]> granicus.if.org Git - ejabberd/commitdiff
* src/web/ejabberd_web_admin.erl: Improve Web Admin navigation
authorBadlop <badlop@process-one.net>
Sun, 12 Oct 2008 13:58:05 +0000 (13:58 +0000)
committerBadlop <badlop@process-one.net>
Sun, 12 Oct 2008 13:58:05 +0000 (13:58 +0000)
menu for vhosts and nodes (EJAB-734)

SVN Revision: 1642

ChangeLog
src/web/ejabberd_web_admin.erl

index 5cd2ada86a927238af2094004a57fd0eb9bb01f7..ebab255b8f43fb8eae3e187c03af5c5fc346e6a4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
 
index cd97edb65110f246ab01835eb1da14ee99907e5e..3ffab97b0e3d64bdf5dcfce46ee869465989f927 100644 (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)] )]).