Mercurial > libervia-web
comparison 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 |
comparison
equal
deleted
inserted
replaced
1416:0554103ec700 | 1417:314bba1ae433 |
---|---|
117 # Set of tuples (service/node/sub_id) of nodes subscribed for caching | 117 # Set of tuples (service/node/sub_id) of nodes subscribed for caching |
118 # sub_id can be empty string if not handled by service | 118 # sub_id can be empty string if not handled by service |
119 cache_pubsub_sub = set() | 119 cache_pubsub_sub = set() |
120 | 120 |
121 def __init__( | 121 def __init__( |
122 self, host, vhost_root, root_dir, url, name=None, redirect=None, access=None, | 122 self, host, vhost_root, root_dir, url, name=None, label=None, redirect=None, |
123 dynamic=False, parse_url=None, prepare_render=None, render=None, template=None, | 123 access=None, dynamic=False, parse_url=None, add_breadcrumb=None, |
124 on_data_post=None, on_data=None, on_signal=None, url_cache=False, | 124 prepare_render=None, render=None, template=None, on_data_post=None, on_data=None, |
125 replace_on_conflict=False | 125 on_signal=None, url_cache=False, replace_on_conflict=False |
126 ): | 126 ): |
127 """Initiate LiberviaPage instance | 127 """Initiate LiberviaPage instance |
128 | 128 |
129 LiberviaPages are the main resources of Libervia, using easy to set python files | 129 LiberviaPages are the main resources of Libervia, using easy to set python files |
130 The non mandatory arguments are the variables found in page_meta.py | 130 The non mandatory arguments are the variables found in page_meta.py |
150 admins. See C.PAGES_ACCESS_* for details | 150 admins. See C.PAGES_ACCESS_* for details |
151 @param dynamic(bool): if True, activate websocket for bidirectional communication | 151 @param dynamic(bool): if True, activate websocket for bidirectional communication |
152 @param parse_url(callable, None): if set it will be called to handle the URL path | 152 @param parse_url(callable, None): if set it will be called to handle the URL path |
153 after this method, the page will be rendered if noting is left in path | 153 after this method, the page will be rendered if noting is left in path |
154 (request.postpath) else a the request will be transmitted to a subpage | 154 (request.postpath) else a the request will be transmitted to a subpage |
155 @param add_breadcrumb(callable, None): if set, manage the breadcrumb data for this | |
156 page, otherwise it will be set automatically from page name or label. | |
155 @param prepare_render(callable, None): if set, will be used to prepare the | 157 @param prepare_render(callable, None): if set, will be used to prepare the |
156 rendering. That often means gathering data using the bridge | 158 rendering. That often means gathering data using the bridge |
157 @param render(callable, None): if template is not set, this method will be | 159 @param render(callable, None): if template is not set, this method will be |
158 called and what it returns will be rendered. | 160 called and what it returns will be rendered. |
159 This method is mutually exclusive with template and must return a unicode | 161 This method is mutually exclusive with template and must return a unicode |
183 self.host = host | 185 self.host = host |
184 self.vhost_root = vhost_root | 186 self.vhost_root = vhost_root |
185 self.root_dir = root_dir | 187 self.root_dir = root_dir |
186 self.url = url | 188 self.url = url |
187 self.name = name | 189 self.name = name |
190 self.label = label | |
188 self.dyn_data = {} | 191 self.dyn_data = {} |
189 if name is not None: | 192 if name is not None: |
190 if (name in self.named_pages | 193 if (name in self.named_pages |
191 and not (replace_on_conflict and self.named_pages[name].url == url)): | 194 and not (replace_on_conflict and self.named_pages[name].url == url)): |
192 raise exceptions.ConflictError( | 195 raise exceptions.ConflictError( |
220 "method, check self.pageRedirect if you need to use them")) | 223 "method, check self.pageRedirect if you need to use them")) |
221 self.redirect = redirect | 224 self.redirect = redirect |
222 else: | 225 else: |
223 self.redirect = None | 226 self.redirect = None |
224 self.parse_url = parse_url | 227 self.parse_url = parse_url |
228 self.add_breadcrumb = add_breadcrumb | |
225 self.prepare_render = prepare_render | 229 self.prepare_render = prepare_render |
226 self.template = template | 230 self.template = template |
227 self.render_method = render | 231 self.render_method = render |
228 self.on_data_post = on_data_post | 232 self.on_data_post = on_data_post |
229 self.on_data = on_data | 233 self.on_data = on_data |
296 host=host, | 300 host=host, |
297 vhost_root=vhost_root, | 301 vhost_root=vhost_root, |
298 root_dir=dir_path, | 302 root_dir=dir_path, |
299 url="/" + "/".join(url_elts), | 303 url="/" + "/".join(url_elts), |
300 name=page_data.get("name"), | 304 name=page_data.get("name"), |
305 label=page_data.get("label"), | |
301 redirect=page_data.get("redirect"), | 306 redirect=page_data.get("redirect"), |
302 access=page_data.get("access"), | 307 access=page_data.get("access"), |
303 dynamic=page_data.get("dynamic", False), | 308 dynamic=page_data.get("dynamic", False), |
304 parse_url=page_data.get("parse_url"), | 309 parse_url=page_data.get("parse_url"), |
310 add_breadcrumb=page_data.get("add_breadcrumb"), | |
305 prepare_render=page_data.get("prepare_render"), | 311 prepare_render=page_data.get("prepare_render"), |
306 render=page_data.get("render"), | 312 render=page_data.get("render"), |
307 template=page_data.get("template"), | 313 template=page_data.get("template"), |
308 on_data_post=page_data.get("on_data_post"), | 314 on_data_post=page_data.get("on_data_post"), |
309 on_data=page_data.get("on_data"), | 315 on_data=page_data.get("on_data"), |
1453 request, | 1459 request, |
1454 cache_path=session_data.cache_dir, | 1460 cache_path=session_data.cache_dir, |
1455 templates_root_url=str(self.vhost_root.getFrontURL(theme)), | 1461 templates_root_url=str(self.vhost_root.getFrontURL(theme)), |
1456 profile=session_data.profile) | 1462 profile=session_data.profile) |
1457 | 1463 |
1464 uri = request.uri.decode() | |
1465 try: | |
1466 template_data["current_page"] = next( | |
1467 m[0] for m in self.main_menu if uri.startswith(m[1]) | |
1468 ) | |
1469 except StopIteration: | |
1470 pass | |
1471 | |
1458 return self.host.renderer.render( | 1472 return self.host.renderer.render( |
1459 self.template, | 1473 self.template, |
1460 theme=theme, | 1474 theme=theme, |
1461 site_themes=self.site_themes, | 1475 site_themes=self.site_themes, |
1462 page_url=self.getURL(), | 1476 page_url=self.getURL(), |
1766 session_data = self.host.getSessionData(request, session_iface.ISATSession) | 1780 session_data = self.host.getSessionData(request, session_iface.ISATSession) |
1767 request.template_data = { | 1781 request.template_data = { |
1768 "profile": session_data.profile, | 1782 "profile": session_data.profile, |
1769 "csrf_token": session_data.csrf_token, | 1783 "csrf_token": session_data.csrf_token, |
1770 "session_uuid": session_data.uuid, | 1784 "session_uuid": session_data.uuid, |
1785 "breadcrumbs": [] | |
1771 } | 1786 } |
1772 | 1787 |
1773 # XXX: here is the code which need to be executed once | 1788 # XXX: here is the code which need to be executed once |
1774 # at the beginning of the request hanling | 1789 # at the beginning of the request hanling |
1775 if request.postpath and not request.postpath[-1]: | 1790 if request.postpath and not request.postpath[-1]: |
1828 else: | 1843 else: |
1829 log.debug(f"using URI cache for {self}") | 1844 log.debug(f"using URI cache for {self}") |
1830 cache_url.use(request) | 1845 cache_url.use(request) |
1831 else: | 1846 else: |
1832 await asDeferred(self.parse_url, self, request) | 1847 await asDeferred(self.parse_url, self, request) |
1848 | |
1849 if self.add_breadcrumb is None: | |
1850 label = ( | |
1851 self.label | |
1852 or self.name | |
1853 or self.url[self.url.rfind('/')+1:] | |
1854 ) | |
1855 breadcrumb = { | |
1856 "url": self.url, | |
1857 "label": label.title(), | |
1858 } | |
1859 request.template_data["breadcrumbs"].append(breadcrumb) | |
1860 else: | |
1861 await asDeferred( | |
1862 self.add_breadcrumb, | |
1863 self, | |
1864 request, | |
1865 request.template_data["breadcrumbs"] | |
1866 ) | |
1833 | 1867 |
1834 self._subpagesHandler(request) | 1868 self._subpagesHandler(request) |
1835 | 1869 |
1836 if request.method not in (C.HTTP_METHOD_GET, C.HTTP_METHOD_POST): | 1870 if request.method not in (C.HTTP_METHOD_GET, C.HTTP_METHOD_POST): |
1837 # only HTTP GET and POST are handled so far | 1871 # only HTTP GET and POST are handled so far |