* started workin on 'navbar' module * changed bootstrap theme to bootswatch/Simplex * big work on navbar logic * starting creating menus using navbar * converted app views to new Wepage decorator, updated navbar * reimplemented DernieresMaraudes as a dropdown instead of ContextMixin * reorganised static files, minor code cleanups * turned Link.href into lazy-evaluated property * collapsed 'navbar' module into 'website', dynamic building of ApplicationMenu subclasses * minor cleanup * blah blah blah * added way to add admin/non-admin links * minor style change : red border for active page instead of all dropdowns * deleted file * prepare adding removing menu templates files, being replaced by code * essayé de généraliser le code pour les modaux bootstrap, non testé git status * more preparation and thinking on navbar app_menus logic... * added LinkManager and DropdownManager, getting closer... * small fix in DropdownManager.__get__ * boosted up work: keep it simple so it can be merged fast, major layout changes * added month filter on maraudes:liste * added 'as_icon' filter to display boolean/null values as bootstrap icons * remove inactive user from planning selection * removed all unused 'menu' templates * set up django_select2 to use static files * small fix after review
103 lines
2.7 KiB
Python
103 lines
2.7 KiB
Python
""" Draft for navbar application menu
|
|
"""
|
|
|
|
from django.urls import reverse
|
|
|
|
registered = []
|
|
|
|
|
|
class Link:
|
|
""" Navbar link
|
|
|
|
Constructor takes one required argument :
|
|
- text : text to display for the link
|
|
|
|
and two optional arguments :
|
|
- target : str or tuple (str, dict)
|
|
- icon : bootstrap icon name, no validation
|
|
|
|
"""
|
|
|
|
def __init__(self, text, target="#", icon=None):
|
|
self.text = text
|
|
self._target = target
|
|
self.icon = icon
|
|
|
|
@property
|
|
def href(self):
|
|
""" Lazy creation of html 'href' value, using 'target' instance attribute """
|
|
if not hasattr(self, '_href'):
|
|
if self._target == "#": #Create void link
|
|
self._href = "#"
|
|
else:
|
|
try:
|
|
target, kwargs = self._target
|
|
except ValueError:
|
|
target = self._target
|
|
kwargs = {}
|
|
assert type(target) == str
|
|
assert type(kwargs) == dict
|
|
self._href = reverse(target, **kwargs)
|
|
return self._href
|
|
|
|
|
|
|
|
class LinkManager:
|
|
""" Per-class manager of links """
|
|
|
|
def __init__(self):
|
|
self.items = []
|
|
|
|
def __get__(self, instance, owner):
|
|
if instance: #Filtering done at each call, not optimized at all !
|
|
if not instance.user.is_superuser:
|
|
return [link for link in self.items if link.admin_link == False]
|
|
else:
|
|
return self.items.copy()
|
|
return self
|
|
|
|
def add(self, link):
|
|
self.items.append(link)
|
|
|
|
def __repr__(self):
|
|
return '<LinkManager: [' + ', '.join((l.text for l in self.items)) + ']>'
|
|
|
|
|
|
|
|
class MenuRegistry(type):
|
|
""" Metaclass that registers subclass into module level variable 'registered' """
|
|
def __new__(metacls, name, bases, attrs):
|
|
cls = type.__new__(metacls, name, bases, attrs)
|
|
if name != "ApplicationMenu":
|
|
print('registering menu', cls)
|
|
registered.append(cls)
|
|
# Create Link instance for header attributes
|
|
try:
|
|
header, target, icon = cls.header
|
|
except ValueError:
|
|
header = cls.header
|
|
target = "#"
|
|
icon = None
|
|
cls.header = Link(header, target, icon)
|
|
cls.links = LinkManager()
|
|
return cls
|
|
|
|
|
|
|
|
class ApplicationMenu(metaclass=MenuRegistry):
|
|
name = None
|
|
header = None
|
|
|
|
def __init__(self, view, user):
|
|
self.view = view
|
|
self.user = user
|
|
self.is_active = self.name == self.view.app_name
|
|
|
|
@classmethod
|
|
def add_link(cls, link, admin=False):
|
|
if not isinstance(link, Link):
|
|
link = Link(*link)
|
|
link.admin_link = admin
|
|
cls.links.add(link)
|
|
|