]> git.ipfire.org Git - people/ms/westferry.git/commitdiff
Add a simple menu implementation
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 22 Oct 2015 00:53:04 +0000 (02:53 +0200)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 22 Oct 2015 00:53:04 +0000 (02:53 +0200)
...and some example code that uses that

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/templates/base.html
src/templates/modules/menu/sidebar-divider.html [new file with mode: 0644]
src/templates/modules/menu/sidebar-link.html [new file with mode: 0644]
src/templates/modules/menu/sidebar-submenu-header.html [new file with mode: 0644]
src/templates/modules/menu/sidebar-submenu.html [new file with mode: 0644]
src/templates/modules/menu/sidebar.html
src/westferry/handlers/analytics.py
src/westferry/handlers/base.py
src/westferry/ui/menu.py

index 6e9087687c4725b5cb92d138c1e6f1c134f136c2..0963f3f74b38490a4af1f5c56625493c0d0b29a7 100644 (file)
@@ -133,7 +133,10 @@ templates_modulesdir = $(templatesdir)/modules
 templates_modules_menudir = $(templates_modulesdir)/menu
 
 dist_templates_modules_menu_DATA = \
-       src/templates/modules/menu/sidebar.html
+       src/templates/modules/menu/sidebar.html \
+       src/templates/modules/menu/sidebar-divider.html \
+       src/templates/modules/menu/sidebar-link.html \
+       src/templates/modules/menu/sidebar-submenu.html
 
 ui_modulesdir = $(datadir)/westferry/templates/modules
 
index 72be9a6fc1f4ae4556c9a100a8894d107d8366f0..449bd7a88505eefb1dab596711b411e281b5f167 100644 (file)
                <meta name="author" content="">
                <link rel="icon" href="/favicon.ico">
 
-               <title>Dashboard Template for Bootstrap</title>
+               <title>
+                       {{ hostname() }}
+                       {% if menu  and menu.title %}
+                               - {{ menu.title }}
+                       {% end %}
+                       - {{ _(handler.title) }}
+               </title>
 
                <link href="{{ static_url("css/bootstrap.min.css") }}" rel="stylesheet">
                <link href="{{ static_url("css/westferry.css") }}" rel="stylesheet">
                </nav>
 
                <div class="container">
-                       <div class="row">
-                               <div class="col-sm-3 col-md-2">
-                                       {% module SidebarMenu() %}
-                               </div>
+                       {% if menu %}
+                               <div class="row">
+                                       <div class="col-sm-3 col-md-2">
+                                               {% module SidebarMenu(menu) %}
+                                       </div>
 
-                               <div class="col-sm-9 col-md-10 main">
-                                       {% block main %}
-                                               <h1 class="page-header">Dashboard</h1>
-                                       {% end %}
+                                       <div class="col-sm-9 col-md-10 main">
+                                               {% block main %}
+                                                       <h1 class="page-header">Dashboard</h1>
+                                               {% end %}
+                                       </div>
                                </div>
-                       </div>
+                       {% else %}
+                               {% block main %}{% end %}
+                       {% end %}
                </div>
 
                <script src="{{ static_url("scripts/jquery.min.js") }}"></script>
diff --git a/src/templates/modules/menu/sidebar-divider.html b/src/templates/modules/menu/sidebar-divider.html
new file mode 100644 (file)
index 0000000..ab404d2
--- /dev/null
@@ -0,0 +1 @@
+<li class="divider"></li>
diff --git a/src/templates/modules/menu/sidebar-link.html b/src/templates/modules/menu/sidebar-link.html
new file mode 100644 (file)
index 0000000..b5ef146
--- /dev/null
@@ -0,0 +1,5 @@
+<li {% if item.is_active() %}class="active"{% end %}>
+       <a href="{{ item.url }}">
+               {{ item.title }}
+       </a>
+</li>
diff --git a/src/templates/modules/menu/sidebar-submenu-header.html b/src/templates/modules/menu/sidebar-submenu-header.html
new file mode 100644 (file)
index 0000000..b3b8eca
--- /dev/null
@@ -0,0 +1 @@
+<li class="dropdown-header">{{ item.title }}</li>
diff --git a/src/templates/modules/menu/sidebar-submenu.html b/src/templates/modules/menu/sidebar-submenu.html
new file mode 100644 (file)
index 0000000..2a70981
--- /dev/null
@@ -0,0 +1,17 @@
+<li class="dropdown">
+       <a href="#" class="dropdown-toggle" data-toggle="dropdown">
+               {{ submenu.title or _("No Title") }} <b class="caret"></b>
+       </a>
+
+       <ul class="dropdown-menu">
+               {% for i in submenu %}
+                       {% if i.type == "header" %}
+                               {% module SidebarMenuSubMenuHeader(submenu, i) %}
+                       {% elif i.type == "link" %}
+                               {% module SidebarMenuLink(submenu, i) %}
+                       {% elif i.type == "divider" %}
+                               {% module SidebarMenuDivider(submenu, i) %}
+                       {% end %}
+               {% end %}
+       </ul>
+</li>
index b4829be0868d97083ec096cec44eb71b588970b4..69d795aa2b846e7bd72eb6e845450aa9f695af00 100644 (file)
 
                <div class="navbar-collapse collapse sidebar-navbar-collapse">
                        <ul class="nav navbar-nav">
-                               <li class="active"><a href="#">Menu Item 1</a></li>
-                               <li><a href="#">Menu Item 2</a></li>
-                               <li class="dropdown">
-                                       <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>
-                                       <ul class="dropdown-menu">
-                                               <li><a href="#">Action</a></li>
-                                               <li><a href="#">Another action</a></li>
-                                               <li><a href="#">Something else here</a></li>
-                                               <li class="divider"></li>
-                                               <li class="dropdown-header">Nav header</li>
-                                               <li><a href="#">Separated link</a></li>
-                                               <li><a href="#">One more separated link</a></li>
-                                       </ul>
-                               </li>
-                               <li><a href="#">Menu Item 4</a></li>
-                               <li><a href="#">Reviews <span class="badge">1,118</span></a></li>
+                               {% for i in menu %}
+                                       {% if i.type == "link" %}
+                                               {% module SidebarMenuLink(menu, i) %}
+                                       {% elif i.type == "menu" %}
+                                               {% module SidebarMenuSubMenu(menu, i) %}
+                                       {% end %}
+                               {% end %}
                        </ul>
                </div>
        </div>
index 488d0ac5ad9f10169e94523a38afe01864076708..59fd86dd16db9e14286976d741f795ac42f7e0b6 100644 (file)
@@ -25,6 +25,71 @@ import mimetypes
 import tornado.web
 
 from . import base
+from .. import ui
+
+N_ = lambda x: x
+
+class AnalyticsBaseHandler(base.BaseHandler):
+       @property
+       def menu(self):
+               _ = self.locale.translate
+
+               m = ui.menu.Menu(self, _("Analytics"))
+
+               # Overview
+               m.add_handler(AnalyticsOverviewHandler)
+               m.add_divider()
+
+               # System
+               m.add_handler(AnalyticsSystemOverviewHandler)
+
+               return m
+
+
+class AnalyticsOverviewHandler(AnalyticsBaseHandler):
+       url = r"/analytics"
+       title = N_("Overview")
+
+       def get(self):
+               self.render("base.html")
+
+
+class AnalyticsSystemBaseHandler(AnalyticsBaseHandler):
+       @property
+       def menu(self):
+               _ = self.locale.translate
+
+               m = ui.menu.Menu(self, _("System"))
+
+               # Back...
+               m.add_handler(AnalyticsOverviewHandler, title=_("Back..."))
+               m.add_divider()
+
+               # Overview
+               m.add_handler(AnalyticsSystemOverviewHandler, title=_("Overview"))
+               m.add_divider()
+
+               # Others
+               m.add_handler(AnalyticsSystemProcessorsHandler)
+               m.add_handler(AnalyticsSystemMemoryHandler)
+
+               return m
+
+
+class AnalyticsSystemOverviewHandler(AnalyticsSystemBaseHandler):
+       url = r"/analytics/system"
+       title = N_("System")
+
+
+class AnalyticsSystemProcessorsHandler(AnalyticsSystemBaseHandler):
+       url = r"/analytics/system/processors"
+       title = N_("Processors")
+
+
+class AnalyticsSystemMemoryHandler(AnalyticsSystemBaseHandler):
+       url = r"/analytics/system/memory"
+       title = N_("Memory")
+
 
 class GraphExportHandler(base.BaseHandler):
        VALID_INTERVALS = ("hour", "day", "month", "week", "year")
index 9027bf4052ba2ee9eb0f94c4279e55a873a4141c..5e2d984434bf39cc6c58cd20cbaa2736abe523a5 100644 (file)
@@ -21,6 +21,8 @@
 
 import tornado.web
 
+N_ = lambda x: x
+
 _handlers = []
 
 class HandlerRegistration(type):
@@ -45,6 +47,11 @@ class HandlerRegistration(type):
 class BaseHandler(tornado.web.RequestHandler, metaclass=HandlerRegistration):
        url = None
 
+       title = N_("No Title")
+
+       # Points to the menu map of the section in which the handler is in
+       menu = None
+
        @property
        def backend(self):
                """
@@ -52,6 +59,21 @@ class BaseHandler(tornado.web.RequestHandler, metaclass=HandlerRegistration):
                """
                return self.application.backend
 
+       def get_template_namespace(self):
+               ns = tornado.web.RequestHandler.get_template_namespace(self)
+
+               # Add some global constants
+               ns.update({
+                       "VERSION" : self.backend.version,
+               })
+
+               # Add some more
+               ns.update({
+                       "menu" : self.menu,
+               })
+
+               return ns
+
        def get_argument_int(self, name, *args, **kwargs):
                val = self.get_argument(name, *args, **kwargs)
 
index dbbdb9986e46bf3ee3de0fe2ebd2c7c193947a37..5afa24b062ba59e01278a8af07fa7b4ab4247d76 100644 (file)
 
 from . import base
 
+class MenuItem(object):
+       type = None
+
+       def __init__(self, menu=None):
+               self.menu = menu
+
+       def is_active(self):
+               return False
+
+
+class MenuDivider(MenuItem):
+       type = "divider"
+
+
+class MenuHeader(MenuItem):
+       type = "header"
+
+       def __init__(self, title, menu=None):
+               MenuItem.__init__(self, menu=menu)
+
+               self.title = title
+
+
+class MenuLink(MenuItem):
+       type = "link"
+
+       def __init__(self, title, handler=None, url=None, menu=None):
+               MenuItem.__init__(self, menu=menu)
+
+               self.title = title
+               self.handler = handler
+
+               self.url = url or handler.url
+
+       def is_active(self):
+               if not self.handler:
+                       return False
+
+               return isinstance(self.menu.handler, self.handler)
+
+
+class MenuMixin(object):
+       type = "menu"
+
+       @property
+       def items(self):
+               if not hasattr(self, "_items"):
+                       self._items = []
+
+               return self._items
+
+       def __iter__(self):
+               """
+                       Iterator over all item in this menu
+               """
+               return iter(self.items)
+
+       def add_divider(self, *args, **kwargs):
+               """
+                       Adds a divider to the menu
+               """
+               divider = MenuDivider(*args, **kwargs)
+               self.items.append(divider)
+
+               return divider
+
+       def add_handler(self, handler, title=None, **kwargs):
+               """
+                       Automatically adds a handler to the menu
+               """
+               title = title or self.locale.translate(handler.title)
+
+               return self.add_link(title=title, handler=handler,
+                       url=handler.url, **kwargs)
+
+       def add_header(self, *args, **kwargs):
+               """
+                       Adds a headline in the menu
+               """
+               header = MenuHeader(*args, **kwargs)
+               self.items.append(header)
+
+               return header
+
+       def add_link(self, *args, **kwargs):
+               """
+                       Adds a link to the menu
+               """
+               link = MenuLink(*args, menu=self, **kwargs)
+               self.items.append(link)
+
+               return link
+
+       def add_submenu(self, *args, **kwargs):
+               """
+                       Adds a submenu to the menu
+               """
+               kwargs.update({
+                       "menu" : self,
+               })
+
+               submenu = SubMenu(*args, **kwargs)
+               self.items.append(submenu)
+
+               return submenu
+
+
+class Menu(MenuMixin):
+       """
+               The main menu object that creates a little menu on the side
+       """
+       def __init__(self, handler, title=None):
+               self.handler = handler
+               self.title = title
+
+       @property
+       def locale(self):
+               """
+                       Shortcut to access the user's locale
+               """
+               return self.handler.locale
+
+
+
+class SubMenu(MenuItem, MenuMixin):
+       """
+               A sub menu in the side menu
+       """
+
+       type = "menu"
+
+       def __init__(self, title, menu=None):
+               self.title = title
+               self.menu = menu
+
+       @property
+       def locale(self):
+               """
+                       Shortcut to access the user's locale
+               """
+               return self.menu.locale
+
+
 class SidebarMenuModule(base.BaseUIModule):
-       def render(self):
-               return self.render_string("modules/menu/sidebar.html")
+       def render(self, menu):
+               return self.render_string("modules/menu/sidebar.html", menu=menu)
+
+
+class SidebarMenuLinkModule(base.BaseUIModule):
+       def render(self, menu, item):
+               return self.render_string("modules/menu/sidebar-link.html", item=item)
+
+
+class SidebarMenuDividerModule(base.BaseUIModule):
+       def render(self, menu, item):
+               return self.render_string("modules/menu/sidebar-divider.html")
+
+
+class SidebarMenuSubMenuModule(base.BaseUIModule):
+       def render(self, menu, submenu):
+               return self.render_string("modules/menu/sidebar-submenu.html", submenu=submenu)
+
+
+class SidebarMenuSubMenuHeaderModule(base.BaseUIModule):
+       def render(self, menu, item):
+               return self.render_string("modules/menu/sidebar-submenu-header.html", item=item)