[?XAE("div",
[{"id", "header"}],
[?XE("h1",
- [?ACT("/admin/", "Administration")]
+ [?ACT("/admin/", "ejabberd Web Admin")]
)]),
?XAE("div",
[{"id", "navigation"}],
text-align: center;
border-top: 2px solid #d47911;
border-bottom: 1px solid #d47911;
+ background: #FED6A6;
}
#navheadsub, #navitemsub {
border: 1px solid #d6760e;
color: #723202;
background-color: #fff2e8;
- vertical-align: middle;
- margin-top: 7px;
- margin-bottom: 5px;
- padding: 0.1em;
}
select {
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;
}
#request{path = ["acls-raw"],
q = Query,
lang = Lang}) ->
+
Res = case lists:keysearch("acls", 1, Query) of
{value, {_, String}} ->
case erl_scan:string(String) of
_ ->
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")
])
[], [{{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")])] ++
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")
])
[{{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")])] ++
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"}],
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))).
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"},
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"}],
[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"}],
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",
{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) ->
])
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",
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",
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"}],
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"}],
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) ->
{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) ->
end, Tables),
ok.
+node_backup_parse_query(_Node, [{nokey,[]}]) ->
+ nothing;
node_backup_parse_query(Node, Query) ->
lists:foldl(
fun(Action, nothing) ->
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
node_ports_to_xhtml(Ports, Lang) ->
- ?XAE("table", [],
+ ?XAE("table", [{"class", "withtextareas"}],
[?XE("thead",
[?XE("tr",
[?XCT("td", "Port"),
{_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,
[?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")])
]
end.
node_modules_to_xhtml(Modules, Lang) ->
- ?XAE("table", [],
+ ?XAE("table", [{"class", "withtextareas"}],
[?XE("thead",
[?XE("tr",
[?XCT("td", "Module"),
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,
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")])
]
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) ->