diff libervia/server/pages.py @ 1417:314bba1ae433

pages: breadcrumbs handling: a new `breadcrumbs` list of dict is created in `template_data`. By default it is automatically filled by pages run to reach the requested URI, but a page can customize it. A breadcrumb data dict must have a `label`, should have an `url` and may have an `icon` (which is the name of a SàT Media well-known icon). Pages may now have a `label` attribute, which is used to automatically fill the crumb (otherwise page name then URI is used). A new `add_breadcrumb` method can be used to manually breadcrumb data, in which case auto-filling is disabled.
author Goffi <goffi@goffi.org>
date Thu, 29 Apr 2021 20:48:35 +0200
parents 2c3bdba880bb
children 870b198e98ea
line wrap: on
line diff
--- a/libervia/server/pages.py	Thu Apr 29 16:55:07 2021 +0200
+++ b/libervia/server/pages.py	Thu Apr 29 20:48:35 2021 +0200
@@ -119,10 +119,10 @@
     cache_pubsub_sub = set()
 
     def __init__(
-        self, host, vhost_root, root_dir, url, name=None, redirect=None, access=None,
-        dynamic=False, parse_url=None, prepare_render=None, render=None, template=None,
-        on_data_post=None, on_data=None, on_signal=None, url_cache=False,
-        replace_on_conflict=False
+        self, host, vhost_root, root_dir, url, name=None, label=None, redirect=None,
+        access=None, dynamic=False, parse_url=None, add_breadcrumb=None,
+        prepare_render=None, render=None, template=None, on_data_post=None, on_data=None,
+        on_signal=None, url_cache=False, replace_on_conflict=False
         ):
         """Initiate LiberviaPage instance
 
@@ -152,6 +152,8 @@
         @param parse_url(callable, None): if set it will be called to handle the URL path
             after this method, the page will be rendered if noting is left in path
             (request.postpath) else a the request will be transmitted to a subpage
+        @param add_breadcrumb(callable, None): if set, manage the breadcrumb data for this
+            page, otherwise it will be set automatically from page name or label.
         @param prepare_render(callable, None): if set, will be used to prepare the
             rendering. That often means gathering data using the bridge
         @param render(callable, None): if template is not set, this method will be
@@ -185,6 +187,7 @@
         self.root_dir = root_dir
         self.url = url
         self.name = name
+        self.label = label
         self.dyn_data = {}
         if name is not None:
             if (name in self.named_pages
@@ -222,6 +225,7 @@
         else:
             self.redirect = None
         self.parse_url = parse_url
+        self.add_breadcrumb = add_breadcrumb
         self.prepare_render = prepare_render
         self.template = template
         self.render_method = render
@@ -298,10 +302,12 @@
             root_dir=dir_path,
             url="/" + "/".join(url_elts),
             name=page_data.get("name"),
+            label=page_data.get("label"),
             redirect=page_data.get("redirect"),
             access=page_data.get("access"),
             dynamic=page_data.get("dynamic", False),
             parse_url=page_data.get("parse_url"),
+            add_breadcrumb=page_data.get("add_breadcrumb"),
             prepare_render=page_data.get("prepare_render"),
             render=page_data.get("render"),
             template=page_data.get("template"),
@@ -1455,6 +1461,14 @@
             templates_root_url=str(self.vhost_root.getFrontURL(theme)),
             profile=session_data.profile)
 
+        uri = request.uri.decode()
+        try:
+            template_data["current_page"] = next(
+                m[0] for m in self.main_menu if uri.startswith(m[1])
+            )
+        except StopIteration:
+            pass
+
         return self.host.renderer.render(
             self.template,
             theme=theme,
@@ -1768,6 +1782,7 @@
                 "profile": session_data.profile,
                 "csrf_token": session_data.csrf_token,
                 "session_uuid": session_data.uuid,
+                "breadcrumbs": []
             }
 
             # XXX: here is the code which need to be executed once
@@ -1831,6 +1846,25 @@
                     else:
                         await asDeferred(self.parse_url, self, request)
 
+                if self.add_breadcrumb is None:
+                    label = (
+                        self.label
+                        or self.name
+                        or self.url[self.url.rfind('/')+1:]
+                    )
+                    breadcrumb = {
+                        "url": self.url,
+                        "label": label.title(),
+                    }
+                    request.template_data["breadcrumbs"].append(breadcrumb)
+                else:
+                    await asDeferred(
+                        self.add_breadcrumb,
+                        self,
+                        request,
+                        request.template_data["breadcrumbs"]
+                    )
+
                 self._subpagesHandler(request)
 
                 if request.method not in (C.HTTP_METHOD_GET, C.HTTP_METHOD_POST):