* src/web/ejabberd_web_admin.erl: Improve Web Admin navigation

menu for vhosts and nodes (EJAB-734)

SVN Revision: 1642
This commit is contained in:
Badlop 2008-10-12 13:58:05 +00:00
parent 9a66082998
commit 42115a8cfb
2 changed files with 183 additions and 94 deletions

View File

@ -1,5 +1,8 @@
2008-10-12 Badlop <badlop@process-one.net>
* src/web/ejabberd_web_admin.erl: Improve Web Admin navigation
menu for vhosts and nodes (EJAB-734)
* doc/guide.tex: Explain the new ejabberdctl command 'help'
* doc/guide.html: Likewise

View File

@ -104,60 +104,15 @@ get_auth(Auth) ->
unauthorized
end.
make_xhtml(Els, global, Lang) ->
MenuItems1 = ejabberd_hooks:run_fold(webadmin_menu_main, [], [Lang]),
MenuItems2 = [?LI([?AC("/admin/"++MI_uri++"/", MI_name)]) || {MI_uri, MI_name} <- MenuItems1],
{200, [html],
{xmlelement, "html", [{"xmlns", "http://www.w3.org/1999/xhtml"},
{"xml:lang", Lang},
{"lang", Lang}],
[{xmlelement, "head", [],
[?XCT("title", "ejabberd Web Admin"),
{xmlelement, "meta", [{"http-equiv", "Content-Type"},
{"content", "text/html; charset=utf-8"}], []},
{xmlelement, "link", [{"href", "/admin/favicon.ico"},
{"type", "image/x-icon"},
{"rel", "shortcut icon"}], []},
{xmlelement, "link", [{"href", "/admin/style.css"},
{"type", "text/css"},
{"rel", "stylesheet"}], []}]},
?XE("body",
[?XAE("div",
[{"id", "container"}],
[?XAE("div",
[{"id", "header"}],
[?XE("h1",
[?ACT("/admin/", "Administration")]
)]),
?XAE("div",
[{"id", "navigation"}],
[?XE("ul",
[?LI([?ACT("/admin/acls/", "Access Control Lists")]),
?LI([?ACT("/admin/access/", "Access Rules")]),
?LI([?ACT("/admin/vhosts/", "Virtual Hosts")]),
?LI([?ACT("/admin/nodes/", "Nodes")]),
?LI([?ACT("/admin/stats/", "Statistics")])
] ++ MenuItems2
)]),
?XAE("div",
[{"id", "content"}],
Els),
?XAE("div",
[{"id", "clearcopyright"}],
[{xmlcdata, ""}])]),
?XAE("div",
[{"id", "copyrightouter"}],
[?XAE("div",
[{"id", "copyright"}],
[?XC("p",
"ejabberd (c) 2002-2008 ProcessOne")
])])])
]}};
make_xhtml(Els, Host, Lang) ->
Base = "/admin/server/" ++ Host ++ "/",
MenuItems1 = ejabberd_hooks:run_fold(webadmin_menu_host, Host, [], [Host, Lang]),
MenuItems2 = [?LI([?AC(Base ++ MI_uri ++ "/", MI_name)]) || {MI_uri, MI_name} <- MenuItems1],
make_xhtml(Els, Host, cluster, Lang).
%% @spec (Els, Host, Node, Lang)
%% where Host = global | string()
%% Node = cluster | atom()
make_xhtml(Els, Host, Node, Lang) ->
Base = get_base_path(Host, cluster), %% Enforcing 'cluster' on purpose here
MenuItems = make_navigation(Host, Node, Lang),
{200, [html],
{xmlelement, "html", [{"xmlns", "http://www.w3.org/1999/xhtml"},
{"xml:lang", Lang},
@ -166,7 +121,7 @@ make_xhtml(Els, Host, Lang) ->
[?XCT("title", "ejabberd Web Admin"),
{xmlelement, "meta", [{"http-equiv", "Content-Type"},
{"content", "text/html; charset=utf-8"}], []},
{xmlelement, "link", [{"href", "/admin/favicon.ico"},
{xmlelement, "link", [{"href", Base ++ "favicon.ico"},
{"type", "image/x-icon"},
{"rel", "shortcut icon"}], []},
{xmlelement, "link", [{"href", Base ++ "style.css"},
@ -183,18 +138,7 @@ make_xhtml(Els, Host, Lang) ->
?XAE("div",
[{"id", "navigation"}],
[?XE("ul",
[?LI([?XAE("div",
[{"id", "navheadhost"}],
[?AC(Base, Host)]
)]),
?LI([?ACT(Base ++ "acls/", "Access Control Lists")]),
?LI([?ACT(Base ++ "access/", "Access Rules")]),
?LI([?ACT(Base ++ "users/", "Users")]),
?LI([?ACT(Base ++ "online-users/", "Online Users")]),
?LI([?ACT(Base ++ "last-activity/", "Last Activity")]),
?LI([?ACT(Base ++ "nodes/", "Nodes")]),
?LI([?ACT(Base ++ "stats/", "Statistics")])
] ++ MenuItems2
MenuItems
)]),
?XAE("div",
[{"id", "content"}],
@ -211,13 +155,13 @@ make_xhtml(Els, Host, Lang) ->
])])])
]}}.
get_base_path(global, cluster) -> "/admin/";
get_base_path(Host, cluster) -> "/admin/server/" ++ Host ++ "/";
get_base_path(global, Node) -> "/admin/node/" ++ atom_to_list(Node) ++ "/";
get_base_path(Host, Node) -> "/admin/server/" ++ Host ++ "/node/" ++ atom_to_list(Node) ++ "/".
css(Host) ->
Base = case Host of
global ->
"/admin/";
_ ->
"/admin/server/" ++ Host ++ "/"
end,
Base = get_base_path(Host, cluster),
"
html,body {
background: white;
@ -298,7 +242,7 @@ html>body #container {
#navigation ul {
position: absolute;
top: 54px;
top: 65px;
left: 0;
padding: 0 1px 1px 1px;
margin: 0;
@ -306,7 +250,7 @@ html>body #container {
font-size: 8pt;
font-weight: bold;
background: #d47911;
width: 13em;
width: 17em;
}
#navigation ul li {
@ -340,9 +284,20 @@ html>body #container {
background: #332;
}
#navheadhost {
text-align: left;
border-bottom: 2px solid #d47911;
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;
}
#navheadsub, #navitemsub {
border-left: 7px solid white;
margin-left: 2px solid #d47911;
}
#navheadsubsub, #navitemsubsub {
border-left: 14px solid white;
margin-left: 4px solid #d47911;
}
#lastactivity li {
@ -550,7 +505,7 @@ h3 {
#content {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 10pt;
padding-left: 13em;
padding-left: 17em;
padding-top: 5px;
}
@ -595,11 +550,12 @@ logo_fill() ->
"1c5dvhSU2BpKqBXl6R0ljYGS50R5zVC+tVD+vfE6YyUexE9x7g4AAAAASUVO"
"RK5CYII=").
process_admin(global,
#request{path = [],
lang = Lang}) ->
MenuItems1 = ejabberd_hooks:run_fold(webadmin_menu_main, [], [Lang]),
MenuItems2 = [?LI([?AC("/admin/"++MI_uri++"/", MI_name)]) || {MI_uri, MI_name} <- MenuItems1],
Base = get_base_path(global, cluster),
MenuItems2 = make_menu_items(global, cluster, Base, Lang),
make_xhtml([?XCT("h1", "Administration"),
?XE("ul",
[?LI([?ACT("/admin/acls/", "Access Control Lists"), ?C(" "),
@ -616,9 +572,8 @@ process_admin(global,
process_admin(Host,
#request{path = [],
lang = Lang}) ->
Base = "/admin/server/" ++ Host ++ "/",
MenuItems1 = ejabberd_hooks:run_fold(webadmin_menu_host, Host, [], [Host, Lang]),
MenuItems2 = [?LI([?AC(Base ++ MI_uri ++ "/", MI_name)]) || {MI_uri, MI_name} <- MenuItems1],
Base = get_base_path(Host, cluster),
MenuItems2 = make_menu_items(Host, cluster, Base, Lang),
make_xhtml([?XCT("h1", "Administration"),
?XE("ul",
[?LI([?ACT(Base ++ "acls/", "Access Control Lists"), ?C(" "),
@ -971,7 +926,7 @@ process_admin(Host,
make_xhtml([?XCT("h1", "Node not found")], Host, Lang);
Node ->
Res = get_node(Host, Node, NPath, Query, Lang),
make_xhtml(Res, Host, Lang)
make_xhtml(Res, Host, Node, Lang)
end;
process_admin(Host, #request{lang = Lang} = Request) ->
@ -1661,8 +1616,8 @@ search_running_node(SNode, [Node | Nodes]) ->
get_node(global, Node, [], Query, Lang) ->
Res = node_parse_query(Node, Query),
MenuItems1 = ejabberd_hooks:run_fold(webadmin_menu_node, [], [Node, Lang]),
MenuItems2 = [?LI([?AC(MI_uri++"/", MI_name)]) || {MI_uri, MI_name} <- MenuItems1],
Base = get_base_path(global, Node),
MenuItems2 = make_menu_items(global, Node, Base, Lang),
[?XC("h1", ?T("Node ") ++ atom_to_list(Node))] ++
case Res of
ok -> [?CT("Submitted"), ?P];
@ -1670,11 +1625,11 @@ get_node(global, Node, [], Query, Lang) ->
nothing -> []
end ++
[?XE("ul",
[?LI([?ACT("db/", "Database")]),
?LI([?ACT("backup/", "Backup")]),
?LI([?ACT("ports/", "Listened Ports")]),
?LI([?ACT("stats/", "Statistics")]),
?LI([?ACT("update/", "Update")])
[?LI([?ACT(Base ++ "db/", "Database")]),
?LI([?ACT(Base ++ "backup/", "Backup")]),
?LI([?ACT(Base ++ "ports/", "Listened Ports")]),
?LI([?ACT(Base ++ "stats/", "Statistics")]),
?LI([?ACT(Base ++ "update/", "Update")])
] ++ MenuItems2),
?XAE("form", [{"action", ""}, {"method", "post"}],
[?INPUTT("submit", "restart", "Restart"),
@ -1683,11 +1638,11 @@ get_node(global, Node, [], Query, Lang) ->
];
get_node(Host, Node, [], _Query, Lang) ->
MenuItems1 = ejabberd_hooks:run_fold(webadmin_menu_hostnode, Host, [], [Host, Node, Lang]),
MenuItems2 = [?LI([?AC(MI_uri++"/", MI_name)]) || {MI_uri, MI_name} <- MenuItems1],
Base = get_base_path(Host, Node),
MenuItems2 = make_menu_items(global, Node, Base, Lang),
[?XC("h1", ?T("Node ") ++ atom_to_list(Node)),
?XE("ul",
[?LI([?ACT("modules/", "Modules")])] ++ MenuItems2)
[?LI([?ACT(Base ++ "modules/", "Modules")])] ++ MenuItems2)
];
get_node(global, Node, ["db"], Query, Lang) ->
@ -2276,3 +2231,134 @@ last_modified() ->
{"Last-Modified", "Mon, 25 Feb 2008 13:23:30 GMT"}.
cache_control_public() ->
{"Cache-Control", "public"}.
%%%
%%% Navigation Menu
%%%
%% @spec (Host, Node, Lang) -> [LI]
make_navigation(Host, Node, Lang) ->
HostNodeMenu = make_host_node_menu(Host, Node, Lang),
HostMenu = make_host_menu(Host, HostNodeMenu, Lang),
NodeMenu = make_node_menu(Host, Node, Lang),
Menu = make_server_menu(HostMenu, NodeMenu, Lang),
make_menu_items(Lang, Menu).
%% @spec (Host, Node, Base, Lang) -> [LI]
make_menu_items(global, cluster, Base, Lang) ->
HookItems = get_menu_items_hook(server, Lang),
make_menu_items(Lang, {Base, "", HookItems});
make_menu_items(global, _Node, Base, Lang) ->
HookItems = get_menu_items_hook(node, Lang),
make_menu_items(Lang, {Base, "", HookItems});
make_menu_items(Host, cluster, Base, Lang) ->
HookItems = get_menu_items_hook({host, Host}, Lang),
make_menu_items(Lang, {Base, "", HookItems});
make_menu_items(Host, _Node, Base, Lang) ->
HookItems = get_menu_items_hook({hostnode, Host}, Lang),
make_menu_items(Lang, {Base, "", HookItems}).
make_host_node_menu(global, _, _Lang) ->
{"", "", []};
make_host_node_menu(_, cluster, _Lang) ->
{"", "", []};
make_host_node_menu(Host, Node, Lang) ->
HostNodeBase = get_base_path(Host, Node),
HostNodeFixed = [{"modules/", "Modules"}],
HostNodeHook = get_menu_items_hook({hostnode, Host}, Lang),
{HostNodeBase, atom_to_list(Node), HostNodeFixed ++ HostNodeHook}.
make_host_menu(global, _HostNodeMenu, _Lang) ->
{"", "", []};
make_host_menu(Host, HostNodeMenu, Lang) ->
HostBase = get_base_path(Host, cluster),
HostFixed = [{"acls", "Access Control Lists"},
{"access", "Access Rules"},
{"users", "Users"},
{"online-users", "Online Users"},
{"last-activity", "Last Activity"},
{"nodes", "Nodes", HostNodeMenu},
{"stats", "Statistics"}],
HostHook = get_menu_items_hook({host, Host}, Lang),
{HostBase, Host, HostFixed ++ HostHook}.
make_node_menu(_Host, cluster, _Lang) ->
{"", "", []};
make_node_menu(global, Node, Lang) ->
NodeBase = get_base_path(global, Node),
NodeFixed = [{"db/", "Database"},
{"backup/", "Backup"},
{"ports/", "Listened Ports"},
{"stats/", "Statistics"},
{"update/", "Update"}],
NodeHook = get_menu_items_hook(node, Lang),
{NodeBase, atom_to_list(Node), NodeFixed ++ NodeHook};
make_node_menu(_Host, _Node, _Lang) ->
{"", "", []}.
make_server_menu(HostMenu, NodeMenu, Lang) ->
Base = get_base_path(global, cluster),
Fixed = [{"acls", "Access Control Lists"},
{"access", "Access Rules"},
{"vhosts", "Virtual Hosts", HostMenu},
{"nodes", "Nodes", NodeMenu},
{"stats", "Statistics"}],
Hook = get_menu_items_hook(server, Lang),
{Base, "ejabberd", Fixed ++ Hook}.
get_menu_items_hook({hostnode, Host}, Lang) ->
ejabberd_hooks:run_fold(webadmin_menu_hostnode, Host, [], [Host, Lang]);
get_menu_items_hook({host, Host}, Lang) ->
ejabberd_hooks:run_fold(webadmin_menu_host, Host, [], [Host, Lang]);
get_menu_items_hook(node, Lang) ->
ejabberd_hooks:run_fold(webadmin_menu_node, [], [Lang]);
get_menu_items_hook(server, Lang) ->
ejabberd_hooks:run_fold(webadmin_menu_main, [], [Lang]).
%% @spec (Lang::string(), Menu) -> [LI]
%% where Menu = {MURI::string(), MName::string(), Items::[Item]}
%% Item = {IURI::string(), IName::string()} | {IURI::string(), IName::string(), Menu}
make_menu_items(Lang, Menu) ->
lists:reverse(make_menu_items2(Lang, 1, Menu)).
make_menu_items2(Lang, Deep, {MURI, MName, _} = Menu) ->
Res = case MName of
"" -> [];
_ -> [make_menu_item(header, Deep, MURI, MName, Lang) ]
end,
make_menu_items2(Lang, Deep, Menu, Res).
make_menu_items2(_, _Deep, {_, _, []}, Res) ->
Res;
make_menu_items2(Lang, Deep, {MURI, MName, [Item | Items]}, Res) ->
Res2 = case Item of
{IURI, IName} ->
[make_menu_item(item, Deep, MURI++IURI++"/", IName, Lang) | Res];
{IURI, IName, SubMenu} ->
%%ResTemp = [?LI([?ACT(MURI ++ IURI ++ "/", IName)]) | Res],
ResTemp = [make_menu_item(item, Deep, MURI++IURI++"/", IName, Lang) | Res],
ResSubMenu = make_menu_items2(Lang, Deep+1, SubMenu),
ResSubMenu ++ ResTemp
end,
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++" ~")] )]);
make_menu_item(header, 2, URI, Name, _Lang) ->
?LI([?XAE("div", [{"id", "navheadsub"}], [?AC(URI, "~ "++Name++" ~")] )]);
make_menu_item(header, 3, URI, Name, _Lang) ->
?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) ->
?LI([?XAE("div", [{"id", "navitemsub"}], [?ACT(URI, Name)] )]);
make_menu_item(item, 3, URI, Name, Lang) ->
?LI([?XAE("div", [{"id", "navitemsubsub"}], [?ACT(URI, Name)] )]).