]> git.ipfire.org Git - people/ms/westferry.git/commitdiff
UI: Add tabs
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 4 Dec 2021 16:04:46 +0000 (16:04 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 4 Dec 2021 16:04:46 +0000 (16:04 +0000)
This is a proof-of-concept that it would be nice and easy to add tabs to
handlers.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/templates/default.html [new file with mode: 0644]
src/templates/modules/tabs.html [new file with mode: 0644]
src/westferry/handlers/analytics.py
src/westferry/handlers/base.py
src/westferry/ui/__init__.py
src/westferry/ui/tabs.py [new file with mode: 0644]

index 0ddef809b079ee671d0d6a98672d5f5f1c2c7121..7a819b9c4c26514fe9611bc083a3e18f42fbb3eb 100644 (file)
@@ -132,6 +132,7 @@ westferry_ui_PYTHON = \
        src/westferry/ui/forms.py \
        src/westferry/ui/graphs.py \
        src/westferry/ui/menu.py \
+       src/westferry/ui/tabs.py \
        src/westferry/ui/utils.py
 
 westferry_uidir = $(pythondir)/westferry/ui
@@ -142,6 +143,7 @@ templatesdir = $(datadir)/westferry/templates
 
 dist_templates_DATA = \
        src/templates/base.html \
+       src/templates/default.html \
        src/templates/graphs.html
 
 templates_demodir = $(templatesdir)/demo
@@ -153,7 +155,8 @@ dist_templates_demo_DATA = \
 templates_modulesdir = $(templatesdir)/modules
 
 dist_templates_modules_DATA = \
-       src/templates/modules/box.html
+       src/templates/modules/box.html \
+       src/templates/modules/tabs.html
 
 templates_modules_formsdir = $(templates_modulesdir)/forms
 
diff --git a/src/templates/default.html b/src/templates/default.html
new file mode 100644 (file)
index 0000000..1829b36
--- /dev/null
@@ -0,0 +1,8 @@
+{% extends "base.html" %}
+
+{% block main %}
+       {#
+               Render the default tabbed view
+       #}
+       {% module Tabs(handler.tabs) %}
+{% end block %}
diff --git a/src/templates/modules/tabs.html b/src/templates/modules/tabs.html
new file mode 100644 (file)
index 0000000..4fb6e4e
--- /dev/null
@@ -0,0 +1,39 @@
+{% import westferry.ui.graphs %}
+
+{#
+       Render the tab navigation bar
+#}
+<ul class="tabs" data-tabs id="{{ tabs.id }}">
+       {% for i, tab in enumerate(tabs) %}
+               {#
+                       Select the first tab
+               #}
+               {% set selected = i == 0 %}
+
+               <li class="tabs-title {% if selected %}is-active{% end %}">
+                       <a href="#{{ tab.id }}" {% if selected %}aria-selected="true"{% end %}>
+                               {{ tab.title }}
+                       </a>
+               </li>
+       {% end %}
+</ul>
+
+<div class="tabs-content" data-tabs-content="{{ tabs.id }}">
+       {% for i, tab in enumerate(tabs) %}
+               {#
+                       Select the first tab
+               #}
+               {% set selected = i == 0 %}
+
+               <div class="tabs-panel {% if selected %}is-active{% end %}" id="{{ tab.id }}">
+                       {% for item in tab.items %}
+                               {% if isinstance(item, westferry.ui.graphs.Graph) %}
+                                       {% module GraphBox(item) %}
+                               {% else %}
+                                       {% module WarningBox(_("Unknown UI Element"),
+                                               _("A UI element which was supposed to be at this place could not be rendered: %r") % item) %}
+                               {% end %}
+                       {% end %}
+               </div>
+       {% end %}
+</div>
index 1660cec99ceb4f419b2591c17936df7f36e5a4db..1bb932ecbcf157afe7e81295106fdb63f2bd0f97 100644 (file)
@@ -106,15 +106,13 @@ class AnalyticsNetworkIPFragmentationHandler(AnalyticsNetworkBaseHandler):
        url = r"/analytics/network/fragmentation"
        title = N_("Fragmentation")
 
-       def get(self):
+       def initialize(self):
                _ = self.locale.translate
 
-               graphs = [
-                       ui.graphs.Graph(self, "ipv6-fragmentation"),
-                       ui.graphs.Graph(self, "ipv4-fragmentation"),
-               ]
+               for proto, title in (("ipv6", _("IPv6")), ("ipv4", _("IPv4"))):
+                       tab = self.tabs.add_tab(proto, title=title)
 
-               self.render_graphs(graphs)
+                       tab.add_graph("%s-fragmentation" % proto)
 
 
 class AnalyticsSystemBaseHandler(AnalyticsBaseHandler):
index baa20c6a5390f4ee294f99aa636860216f678116..222767148f86098cf3a0713c8b290a9e077e54d4 100644 (file)
 #                                                                             #
 ###############################################################################
 
+import functools
 import tornado.web
 
+from .. import ui
 from ..i18n import _, N_
 
 _handlers = []
@@ -59,6 +61,10 @@ class BaseHandler(tornado.web.RequestHandler, metaclass=HandlerRegistration):
                """
                return self.application.backend
 
+       @functools.cached_property
+       def tabs(self):
+               return ui.tabs.Tabs(self)
+
        def get_template_namespace(self):
                ns = tornado.web.RequestHandler.get_template_namespace(self)
 
@@ -85,3 +91,7 @@ class BaseHandler(tornado.web.RequestHandler, metaclass=HandlerRegistration):
                except ValueError:
                        raise tornado.web.HTTPError(400,
                                _("Invalid type for '%s', expected integer") % name)
+
+       def get(self):
+               # Render the default view
+               self.render("default.html")
index 025987c3d00410a8f90ccc204c8e2360a0a04804..99c898f7ffd8c62b7441afe58a68a67c1495a51e 100644 (file)
@@ -24,6 +24,7 @@ from . import boxes
 from . import forms
 from . import graphs
 from . import menu
+from . import tabs
 from . import utils
 
 def get_ui_methods():
diff --git a/src/westferry/ui/tabs.py b/src/westferry/ui/tabs.py
new file mode 100644 (file)
index 0000000..82f7e48
--- /dev/null
@@ -0,0 +1,79 @@
+#!/usr/bin/python3
+###############################################################################
+#                                                                             #
+# Westferry - The IPFire web user interface                                   #
+# Copyright (C) 2021 IPFire development team                                  #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+###############################################################################
+
+import uuid
+
+from . import base
+from . import graphs
+
+class TabsModule(base.BaseUIModule):
+       def render(self, tabs):
+               return self.render_string("modules/tabs.html", tabs=tabs)
+
+
+class Tabs(object):
+       def __init__(self, handler, id=None):
+               self.handler = handler
+
+               # Store ID or generate a random one
+               self.id = id or uuid.uuid4()
+
+               self.tabs = {}
+
+       def __getattr__(self, key):
+               try:
+                       return self.tabs[key]
+               except KeyError as e:
+                       raise AttributeError(key) from e
+
+       def __iter__(self):
+               for id in self.tabs:
+                       yield self.tabs[id]
+
+       def add_tab(self, id, *args, **kwargs):
+               # Check if a tab with this ID already exists
+               #if id in self:
+               #       raise ValueError("Tab with ID '%s' already exists" % id)
+
+               # Create a new tab
+               self.tabs[id] = tab = Tab(self.handler, id, *args, **kwargs)
+
+               # Return the new tab
+               return tab
+
+
+class Tab(object):
+       def __init__(self, handler, id, title):
+               self.handler = handler
+
+               # TODO Check format of ID
+               self.id = id
+
+               self.title = title
+
+               # List to store all items that have been added to this tab
+               self.items = []
+
+       def add_graph(self, *args, **kwargs):
+               graph = graphs.Graph(self.handler, *args, **kwargs)
+               self.items.append(graph)
+
+               return graph