summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBadlop <badlop@process-one.net>2009-01-12 21:48:34 +0000
committerBadlop <badlop@process-one.net>2009-01-12 21:48:34 +0000
commit43a98ab69ba4807aa1b702ccf0ec04020529b8e4 (patch)
tree2464fd78bac57ef2d2d647db9b6a2a46319aa0d1 /src
parent* src/ejabberd_listener.erl: New way to configure IP address and (diff)
* src/web/ejabberd_web_admin.erl: Use textareas for large input
like ejabberd module options and listening port options. Show result of POST more clearly. Ensure access rules are shown with some minimum separation. Improve menu headers. (EJAB-562) * src/web/ejabberd_web_admin.hrl: Likewise * src/mod_offline.erl: Likewise * src/mod_offline_odbc.erl: Likewise * src/mod_roster.erl: Likewise * src/mod_roster_odbc.erl: Likewise * src/mod_shared_roster.erl: Likewise SVN Revision: 1813
Diffstat (limited to 'src')
-rw-r--r--src/mod_offline.erl2
-rw-r--r--src/mod_offline_odbc.erl2
-rw-r--r--src/mod_roster.erl4
-rw-r--r--src/mod_roster_odbc.erl4
-rw-r--r--src/mod_shared_roster.erl35
-rw-r--r--src/web/ejabberd_web_admin.erl168
-rw-r--r--src/web/ejabberd_web_admin.hrl10
7 files changed, 130 insertions, 95 deletions
diff --git a/src/mod_offline.erl b/src/mod_offline.erl
index b2e2b5db..0607ddb8 100644
--- a/src/mod_offline.erl
+++ b/src/mod_offline.erl
@@ -500,7 +500,7 @@ user_queue(User, Server, Query, Lang) ->
[?XC("h1", io_lib:format(?T("~s's Offline Messages Queue"),
[us_to_list(US)]))] ++
case Res of
- ok -> [?CT("Submitted"), ?P];
+ ok -> [?XREST("Submitted")];
nothing -> []
end ++
[?XAE("form", [{"action", ""}, {"method", "post"}],
diff --git a/src/mod_offline_odbc.erl b/src/mod_offline_odbc.erl
index b3f1ec10..e70cfbe6 100644
--- a/src/mod_offline_odbc.erl
+++ b/src/mod_offline_odbc.erl
@@ -358,7 +358,7 @@ user_queue(User, Server, Query, Lang) ->
[?XC("h1", io_lib:format(?T("~s's Offline Messages Queue"),
[us_to_list(US)]))] ++
case Res of
- ok -> [?CT("Submitted"), ?P];
+ ok -> [?XREST("Submitted")];
nothing -> []
end ++
[?XAE("form", [{"action", ""}, {"method", "post"}],
diff --git a/src/mod_roster.erl b/src/mod_roster.erl
index c52ff57f..a1639c55 100644
--- a/src/mod_roster.erl
+++ b/src/mod_roster.erl
@@ -844,8 +844,8 @@ user_roster(User, Server, Query, Lang) ->
end,
[?XC("h1", ?T("Roster of ") ++ us_to_list(US))] ++
case Res of
- ok -> [?CT("Submitted"), ?P];
- error -> [?CT("Bad format"), ?P];
+ ok -> [?XREST("Submitted")];
+ error -> [?XREST("Bad format")];
nothing -> []
end ++
[?XAE("form", [{"action", ""}, {"method", "post"}],
diff --git a/src/mod_roster_odbc.erl b/src/mod_roster_odbc.erl
index 1678e525..ee4e326a 100644
--- a/src/mod_roster_odbc.erl
+++ b/src/mod_roster_odbc.erl
@@ -944,8 +944,8 @@ user_roster(User, Server, Query, Lang) ->
end,
[?XC("h1", ?T("Roster of ") ++ us_to_list(US))] ++
case Res of
- ok -> [?CT("Submitted"), ?P];
- error -> [?CT("Bad format"), ?P];
+ ok -> [?XREST("Submitted")];
+ error -> [?XREST("Bad format")];
nothing -> []
end ++
[?XAE("form", [{"action", ""}, {"method", "post"}],
diff --git a/src/mod_shared_roster.erl b/src/mod_shared_roster.erl
index 01bd1662..1a15119b 100644
--- a/src/mod_shared_roster.erl
+++ b/src/mod_shared_roster.erl
@@ -725,8 +725,8 @@ list_shared_roster_groups(Host, Query, Lang) ->
)]),
?H1GL(?T("Shared Roster Groups"), "modsharedroster", "mod_shared_roster") ++
case Res of
- ok -> [?CT("Submitted"), ?P];
- error -> [?CT("Bad format"), ?P];
+ ok -> [?XREST("Submitted")];
+ error -> [?XREST("Bad format")];
nothing -> []
end ++
[?XAE("form", [{"action", ""}, {"method", "post"}],
@@ -789,8 +789,9 @@ shared_roster_group(Host, Group, Query, Lang) ->
[]
end ++ [[us_to_list(Member), $\n] || Member <- Members],
FDisplayedGroups = [[DG, $\n] || DG <- DisplayedGroups],
+ DescNL = length(element(2, regexp:split(Description, "\n"))),
FGroup =
- ?XAE("table", [],
+ ?XAE("table", [{"class", "withtextareas"}],
[?XE("tbody",
[?XE("tr",
[?XCT("td", "Name:"),
@@ -799,34 +800,34 @@ shared_roster_group(Host, Group, Query, Lang) ->
),
?XE("tr",
[?XCT("td", "Description:"),
- ?XE("td", [?XAC("textarea", [{"name", "description"},
- {"rows", "3"},
- {"cols", "20"}],
- Description)])
+ ?XE("td", [
+ ?TEXTAREA("description", integer_to_list(lists:max([3, DescNL])), "20", Description)
+ ]
+ )
]
),
?XE("tr",
[?XCT("td", "Members:"),
- ?XE("td", [?XAC("textarea", [{"name", "members"},
- {"rows", "3"},
- {"cols", "20"}],
- FMembers)])
+ ?XE("td", [
+ ?TEXTAREA("members", integer_to_list(lists:max([3, length(FMembers)])), "20", FMembers)
+ ]
+ )
]
),
?XE("tr",
[?XCT("td", "Displayed Groups:"),
- ?XE("td", [?XAC("textarea", [{"name", "dispgroups"},
- {"rows", "3"},
- {"cols", "20"}],
- FDisplayedGroups)])
+ ?XE("td", [
+ ?TEXTAREA("dispgroups", integer_to_list(lists:max([3, length(FDisplayedGroups)])), "20", FDisplayedGroups)
+ ]
+ )
]
)]
)]),
?H1GL(?T("Shared Roster Groups"), "modsharedroster", "mod_shared_roster") ++
[?XC("h2", ?T("Group ") ++ Group)] ++
case Res of
- ok -> [?CT("Submitted"), ?P];
- error -> [?CT("Bad format"), ?P];
+ ok -> [?XREST("Submitted")];
+ error -> [?XREST("Bad format")];
nothing -> []
end ++
[?XAE("form", [{"action", ""}, {"method", "post"}],
diff --git a/src/web/ejabberd_web_admin.erl b/src/web/ejabberd_web_admin.erl
index cf3150b9..ea1a936e 100644
--- a/src/web/ejabberd_web_admin.erl
+++ b/src/web/ejabberd_web_admin.erl
@@ -157,7 +157,7 @@ make_xhtml(Els, Host, Node, Lang) ->
[?XAE("div",
[{"id", "header"}],
[?XE("h1",
- [?ACT("/admin/", "Administration")]
+ [?ACT("/admin/", "ejabberd Web Admin")]
)]),
?XAE("div",
[{"id", "navigation"}],
@@ -312,6 +312,7 @@ ul li #navhead a, ul li #navheadsub a, ul li #navheadsubsub a {
text-align: center;
border-top: 2px solid #d47911;
border-bottom: 1px solid #d47911;
+ background: #FED6A6;
}
#navheadsub, #navitemsub {
@@ -367,10 +368,6 @@ textarea {
border: 1px solid #d6760e;
color: #723202;
background-color: #fff2e8;
- vertical-align: middle;
- margin-top: 7px;
- margin-bottom: 5px;
- padding: 0.1em;
}
select {
@@ -538,6 +535,19 @@ div.guidelink {
padding-right: 1em;
}
+table.withtextareas>tbody>tr>td {
+ vertical-align: top;
+}
+
+p.result {
+ border: 1px;
+ border-style: dashed;
+ border-color: #FE8A02;
+ padding: 1em;
+ margin-right: 1em;
+ background: #FFE3C9;
+}
+
*.alignright {
font-size: 10pt;
}
@@ -633,6 +643,7 @@ process_admin(Host,
#request{path = ["acls-raw"],
q = Query,
lang = Lang}) ->
+
Res = case lists:keysearch("acls", 1, Query) of
{value, {_, String}} ->
case erl_scan:string(String) of
@@ -654,22 +665,17 @@ process_admin(Host,
_ ->
nothing
end,
- ACLs = lists:flatten(
- io_lib:format(
- "~p.", [lists:keysort(
- 2, ets:select(acl, [{{acl, {'$1', Host}, '$2'},
- [], [{{acl, '$1', '$2'}}]}]))])),
+ ACLs = lists:keysort(2, ets:select(acl, [{{acl, {'$1', Host}, '$2'},
+ [], [{{acl, '$1', '$2'}}]}])),
+ {NumLines, ACLsP} = term_to_paragraph(ACLs, 80),
make_xhtml(?H1GL(?T("Access Control Lists"), "ACLDefinition", "ACL Definition") ++
case Res of
- ok -> [?CT("Submitted"), ?P];
- error -> [?CT("Bad format"), ?P];
+ ok -> [?XREST("Submitted")];
+ error -> [?XREST("Bad format")];
nothing -> []
end ++
[?XAE("form", [{"action", ""}, {"method", "post"}],
- [?XAC("textarea", [{"name", "acls"},
- {"rows", "16"},
- {"cols", "80"}],
- ACLs),
+ [?TEXTAREA("acls", integer_to_list(lists:max([16, NumLines])), "80", ACLsP++"."),
?BR,
?INPUTT("submit", "submit", "Submit")
])
@@ -704,8 +710,8 @@ process_admin(Host,
[], [{{acl, '$1', '$2'}}]}])),
make_xhtml(?H1GL(?T("Access Control Lists"), "ACLDefinition", "ACL Definition") ++
case Res of
- ok -> [?CT("Submitted"), ?P];
- error -> [?CT("Bad format"), ?P];
+ ok -> [?XREST("Submitted")];
+ error -> [?XREST("Bad format")];
nothing -> []
end ++
[?XE("p", [?ACT("../acls-raw/", "Raw")])] ++
@@ -764,23 +770,19 @@ process_admin(Host,
nothing
end,
Access =
- lists:flatten(
- io_lib:format(
- "~p.", [ets:select(config,
+ ets:select(config,
[{{config, {access, '$1', Host}, '$2'},
[],
- [{{access, '$1', '$2'}}]}])])),
+ [{{access, '$1', '$2'}}]}]),
+ {NumLines, AccessP} = term_to_paragraph(Access, 80),
make_xhtml(?H1GL(?T("Access Rules"), "AccessRights", "Access Rights") ++
case Res of
- ok -> [?CT("Submitted"), ?P];
- error -> [?CT("Bad format"), ?P];
+ ok -> [?XREST("Submitted")];
+ error -> [?XREST("Bad format")];
nothing -> []
end ++
[?XAE("form", [{"action", ""}, {"method", "post"}],
- [?XAC("textarea", [{"name", "access"},
- {"rows", "16"},
- {"cols", "80"}],
- Access),
+ [?TEXTAREA("access", integer_to_list(lists:max([16, NumLines])), "80", AccessP++"."),
?BR,
?INPUTT("submit", "submit", "Submit")
])
@@ -810,8 +812,8 @@ process_admin(Host,
[{{access, '$1', '$2'}}]}]),
make_xhtml(?H1GL(?T("Access Rules"), "AccessRights", "Access Rights") ++
case Res of
- ok -> [?CT("Submitted"), ?P];
- error -> [?CT("Bad format"), ?P];
+ ok -> [?XREST("Submitted")];
+ error -> [?XREST("Bad format")];
nothing -> []
end ++
[?XE("p", [?ACT("../access-raw/", "Raw")])] ++
@@ -850,8 +852,8 @@ process_admin(Host,
make_xhtml([?XC("h1",
io_lib:format(?T("~s access rule configuration"), [SName]))] ++
case Res of
- ok -> [?CT("Submitted"), ?P];
- error -> [?CT("Bad format"), ?P];
+ ok -> [?XREST("Submitted")];
+ error -> [?XREST("Bad format")];
nothing -> []
end ++
[?XAE("form", [{"action", ""}, {"method", "post"}],
@@ -1054,12 +1056,20 @@ acl_spec_select(ID, Opt) ->
node_regexp, user_glob, server_glob, node_glob, all, raw]))]).
+%% @spec (T::any()) -> StringLine::string()
term_to_string(T) ->
StringParagraph = lists:flatten(io_lib:format("~1000000p", [T])),
%% Remove from the string all the carriage returns characters
{ok, StringLine, _} = regexp:gsub(StringParagraph, "\\n ", ""),
StringLine.
+%% @spec (T::any()) -> {NumLines::integer(), Paragraph::string()}
+term_to_paragraph(T, Cols) ->
+ Paragraph = erl_prettypr:format(erl_syntax:abstract(T), [{paper, Cols}]),
+ {ok, FieldList} = regexp:split(Paragraph, "\n"),
+ NumLines = length(FieldList),
+ {NumLines, Paragraph}.
+
term_to_id(T) ->
jlib:encode_base64(binary_to_list(term_to_binary(T))).
@@ -1227,7 +1237,7 @@ access_rule_to_xhtml(Rules) ->
fun({Access, ACL} = _Rule) ->
SAccess = element_to_list(Access),
SACL = atom_to_list(ACL),
- SAccess ++ "\t" ++ SACL ++ "\n"
+ SAccess ++ "\s\t" ++ SACL ++ "\n"
end, Rules),
?XAC("textarea", [{"name", "rules"},
{"rows", "16"},
@@ -1304,8 +1314,8 @@ list_users(Host, Query, Lang, URLFunc) ->
end, lists:seq(1, N, M))
end,
case Res of
- ok -> [?CT("Submitted"), ?P];
- error -> [?CT("Bad format"), ?P];
+ ok -> [?XREST("Submitted")];
+ error -> [?XREST("Bad format")];
nothing -> []
end ++
[?XAE("form", [{"action", ""}, {"method", "post"}],
@@ -1500,8 +1510,8 @@ user_info(User, Server, Query, Lang) ->
[User, Server, Lang]),
[?XC("h1", ?T("User ") ++ us_to_list(US))] ++
case Res of
- ok -> [?CT("Submitted"), ?P];
- error -> [?CT("Bad format"), ?P];
+ ok -> [?XREST("Submitted")];
+ error -> [?XREST("Bad format")];
nothing -> []
end ++
[?XAE("form", [{"action", ""}, {"method", "post"}],
@@ -1668,8 +1678,8 @@ get_node(global, Node, [], Query, Lang) ->
MenuItems2 = make_menu_items(global, Node, Base, Lang),
[?XC("h1", ?T("Node ") ++ atom_to_list(Node))] ++
case Res of
- ok -> [?CT("Submitted"), ?P];
- error -> [?CT("Bad format"), ?P];
+ ok -> [?XREST("Submitted")];
+ error -> [?XREST("Bad format")];
nothing -> []
end ++
[?XE("ul",
@@ -1698,7 +1708,10 @@ get_node(global, Node, ["db"], Query, Lang) ->
{badrpc, _Reason} ->
[?XCT("h1", "RPC Call Error")];
Tables ->
- node_db_parse_query(Node, Tables, Query),
+ ResS = case node_db_parse_query(Node, Tables, Query) of
+ nothing -> [];
+ ok -> [?XREST("Submitted")]
+ end,
STables = lists:sort(Tables),
Rows = lists:map(
fun(Table) ->
@@ -1735,7 +1748,7 @@ get_node(global, Node, ["db"], Query, Lang) ->
])
end, STables),
[?XC("h1", ?T("Database Tables at ") ++ atom_to_list(Node))] ++
- [?CT("Submitted"), ?P] ++
+ ResS ++
[?XAE("form", [{"action", ""}, {"method", "post"}],
[?XAE("table", [],
[?XE("thead",
@@ -1757,9 +1770,14 @@ get_node(global, Node, ["db"], Query, Lang) ->
end;
get_node(global, Node, ["backup"], Query, Lang) ->
- _Res = node_backup_parse_query(Node, Query),
- [?XC("h1", ?T("Backup of ") ++ atom_to_list(Node)),
- ?XCT("p", "Remark that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately."),
+ ResS = case node_backup_parse_query(Node, Query) of
+ nothing -> [];
+ ok -> [?XREST("Submitted")];
+ {error, Error} -> [?XRES(?T("Error") ++": " ++ io_lib:format("~p", [Error]))]
+ end,
+ [?XC("h1", ?T("Backup of ") ++ atom_to_list(Node))] ++
+ ResS ++
+ [?XCT("p", "Remark that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately."),
?XAE("form", [{"action", ""}, {"method", "post"}],
[?XAE("table", [],
[?XE("tbody",
@@ -1822,9 +1840,9 @@ get_node(global, Node, ["ports"], Query, Lang) ->
H1String = ?T("Listened Ports at ") ++ atom_to_list(Node),
?H1GL(H1String, "listened", "Listening Ports") ++
case Res of
- ok -> [?CT("Submitted"), ?P];
- error -> [?CT("Bad format"), ?P];
- {error, ReasonT} -> [?CT("Problem: "), ?C(ReasonT), ?P];
+ ok -> [?XREST("Submitted")];
+ error -> [?XREST("Bad format")];
+ {error, ReasonT} -> [?XRES(?T("Error") ++ ": " ++ ReasonT)];
nothing -> []
end ++
[?XAE("form", [{"action", ""}, {"method", "post"}],
@@ -1847,8 +1865,8 @@ get_node(Host, Node, ["modules"], Query, Lang) when is_list(Host) ->
H1String = ?T("Modules at ") ++ atom_to_list(Node),
?H1GL(H1String, "modoverview", "Modules Overview") ++
case Res of
- ok -> [?CT("Submitted"), ?P];
- error -> [?CT("Bad format"), ?P];
+ ok -> [?XREST("Submitted")];
+ error -> [?XREST("Bad format")];
nothing -> []
end ++
[?XAE("form", [{"action", ""}, {"method", "post"}],
@@ -1916,17 +1934,19 @@ get_node(global, Node, ["update"], Query, Lang) ->
FmtLowLevelScript = ?XC("pre", io_lib:format("~p", [LowLevelScript])),
[?XC("h1", ?T("Update ") ++ atom_to_list(Node))] ++
case Res of
- ok -> [?CT("Submitted"), ?P];
- error -> [?CT("Bad format"), ?P];
+ ok -> [?XREST("Submitted")];
+ error -> [?XREST("Bad format")];
nothing -> []
end ++
[?XAE("form", [{"action", ""}, {"method", "post"}],
- [?INPUTT("submit", "update", "Update"),
+ [
?XCT("h2", "Update plan"),
- ?XCT("h3", "Updated modules"), Mods,
+ ?XCT("h3", "Modified modules"), Mods,
?XCT("h3", "Update script"), FmtScript,
?XCT("h3", "Low level update script"), FmtLowLevelScript,
- ?XCT("h3", "Script check"), ?C(atom_to_list(Check))])
+ ?XCT("h3", "Script check"), ?XC("pre", atom_to_list(Check)),
+ ?INPUTT("submit", "update", "Update")
+ ])
];
get_node(Host, Node, NPath, Query, Lang) ->
@@ -1981,6 +2001,8 @@ db_storage_select(ID, Opt, Lang) ->
{disc_only_copies, "Disc only copy"},
{unknown, "Remote copy"}])).
+node_db_parse_query(_Node, _Tables, [{nokey,[]}]) ->
+ nothing;
node_db_parse_query(Node, Tables, Query) ->
lists:foreach(
fun(Table) ->
@@ -2014,6 +2036,8 @@ node_db_parse_query(Node, Tables, Query) ->
end, Tables),
ok.
+node_backup_parse_query(_Node, [{nokey,[]}]) ->
+ nothing;
node_backup_parse_query(Node, Query) ->
lists:foldl(
fun(Action, nothing) ->
@@ -2040,15 +2064,15 @@ node_backup_parse_query(Node, Query) ->
load_textfile, [Path])
end,
case Res of
- {error, _Reason} ->
- error;
- {badrpc, _Reason} ->
- error;
+ {error, Reason} ->
+ {error, Reason};
+ {badrpc, Reason} ->
+ {badrpc, Reason};
_ ->
ok
end;
- _ ->
- error
+ OtherError ->
+ {error, OtherError}
end;
_ ->
nothing
@@ -2059,7 +2083,7 @@ node_backup_parse_query(Node, Query) ->
node_ports_to_xhtml(Ports, Lang) ->
- ?XAE("table", [],
+ ?XAE("table", [{"class", "withtextareas"}],
[?XE("thead",
[?XE("tr",
[?XCT("td", "Port"),
@@ -2073,14 +2097,14 @@ node_ports_to_xhtml(Ports, Lang) ->
{_Port, SPort, _TIP, SIP, SSPort, OptsClean} =
get_port_data(PortIP, Opts),
SModule = atom_to_list(Module),
+ {NumLines, SOptsClean} = term_to_paragraph(OptsClean, 40),
%%ID = term_to_id(E),
?XE("tr",
[?XAE("td", [{"size", "6"}], [?C(SPort)]),
?XAE("td", [{"size", "15"}], [?C(SIP)]),
?XE("td", [?INPUTS("text", "module" ++ SSPort,
SModule, "15")]),
- ?XE("td", [?INPUTS("text", "opts" ++ SSPort,
- term_to_string(OptsClean), "40")]),
+ ?XE("td", [?TEXTAREA("opts" ++ SSPort, integer_to_list(NumLines), "35", SOptsClean)]),
?XE("td", [?INPUTT("submit", "add" ++ SSPort,
"Update")]),
?XE("td", [?INPUTT("submit", "delete" ++ SSPort,
@@ -2091,8 +2115,8 @@ node_ports_to_xhtml(Ports, Lang) ->
[?XE("tr",
[?XE("td", [?INPUTS("text", "portnew", "", "6")]),
?XE("td", [?INPUTS("text", "ipnew", "0.0.0.0", "15")]),
- ?XE("td", [?INPUTS("text", "modulenew", "", "17")]),
- ?XE("td", [?INPUTS("text", "optsnew", "[]", "40")]),
+ ?XE("td", [?INPUTS("text", "modulenew", "", "15")]),
+ ?XE("td", [?TEXTAREA("optsnew", "2", "35", "[]")]),
?XAE("td", [{"colspan", "2"}],
[?INPUTT("submit", "addnew", "Add New")])
]
@@ -2170,7 +2194,7 @@ node_ports_parse_query(Node, Ports, Query) ->
end.
node_modules_to_xhtml(Modules, Lang) ->
- ?XAE("table", [],
+ ?XAE("table", [{"class", "withtextareas"}],
[?XE("thead",
[?XE("tr",
[?XCT("td", "Module"),
@@ -2180,11 +2204,11 @@ node_modules_to_xhtml(Modules, Lang) ->
lists:map(
fun({Module, Opts} = _E) ->
SModule = atom_to_list(Module),
+ {NumLines, SOpts} = term_to_paragraph(Opts, 40),
%%ID = term_to_id(E),
?XE("tr",
[?XC("td", SModule),
- ?XE("td", [?INPUTS("text", "opts" ++ SModule,
- term_to_string(Opts), "40")]),
+ ?XE("td", [?TEXTAREA("opts" ++ SModule, integer_to_list(NumLines), "40", SOpts)]),
?XE("td", [?INPUTT("submit", "restart" ++ SModule,
"Restart")]),
?XE("td", [?INPUTT("submit", "stop" ++ SModule,
@@ -2194,7 +2218,7 @@ node_modules_to_xhtml(Modules, Lang) ->
end, Modules) ++
[?XE("tr",
[?XE("td", [?INPUT("text", "modulenew", "")]),
- ?XE("td", [?INPUTS("text", "optsnew", "", "40")]),
+ ?XE("td", [?TEXTAREA("optsnew", "2", "40", "[]")]),
?XAE("td", [{"colspan", "2"}],
[?INPUTT("submit", "start", "Start")])
]
@@ -2437,11 +2461,11 @@ make_menu_items2(Lang, Deep, {MURI, MName, [Item | Items]}, Res) ->
make_menu_items2(Lang, Deep, {MURI, MName, Items}, Res2).
make_menu_item(header, 1, URI, Name, _Lang) ->
- ?LI([?XAE("div", [{"id", "navhead"}], [?AC(URI, "~ "++Name++" ~")] )]);
+ ?LI([?XAE("div", [{"id", "navhead"}], [?AC(URI, Name)] )]);
make_menu_item(header, 2, URI, Name, _Lang) ->
- ?LI([?XAE("div", [{"id", "navheadsub"}], [?AC(URI, "~ "++Name++" ~")] )]);
+ ?LI([?XAE("div", [{"id", "navheadsub"}], [?AC(URI, Name)] )]);
make_menu_item(header, 3, URI, Name, _Lang) ->
- ?LI([?XAE("div", [{"id", "navheadsubsub"}], [?AC(URI, "~ "++Name++" ~")] )]);
+ ?LI([?XAE("div", [{"id", "navheadsubsub"}], [?AC(URI, Name)] )]);
make_menu_item(item, 1, URI, Name, Lang) ->
?LI([?XAE("div", [{"id", "navitem"}], [?ACT(URI, Name)] )]);
make_menu_item(item, 2, URI, Name, Lang) ->
diff --git a/src/web/ejabberd_web_admin.hrl b/src/web/ejabberd_web_admin.hrl
index d197e3ab..2bf164e0 100644
--- a/src/web/ejabberd_web_admin.hrl
+++ b/src/web/ejabberd_web_admin.hrl
@@ -51,6 +51,16 @@
-define(INPUTST(Type, Name, Value, Size), ?INPUT(Type, Name, ?T(Value), Size)).
-define(ACLINPUT(Text), ?XE("td", [?INPUT("text", "value" ++ ID, Text)])).
+-define(TEXTAREA(Name, Rows, Cols, Value),
+ ?XAC("textarea", [{"name", Name},
+ {"rows", Rows},
+ {"cols", Cols}],
+ Value)).
+
+%% Build an xmlelement for result
+-define(XRES(Text), ?XAC("p", [{"class", "result"}], Text)).
+-define(XREST(Text), ?XRES(?T(Text))).
+
%% Guide Link
-define(GL(Ref, Title),
?XAE("div",