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
<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>
--- /dev/null
+<li class="divider"></li>
--- /dev/null
+<li {% if item.is_active() %}class="active"{% end %}>
+ <a href="{{ item.url }}">
+ {{ item.title }}
+ </a>
+</li>
--- /dev/null
+<li class="dropdown-header">{{ item.title }}</li>
--- /dev/null
+<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>
<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>
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")
import tornado.web
+N_ = lambda x: x
+
_handlers = []
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):
"""
"""
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)
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)