Files
django-maraudes/website/decorators.py
artus40 0be59a61a7 Navbar (#31)
* 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
2017-02-11 18:20:13 +01:00

94 lines
3.4 KiB
Python

from .mixins import (WebsiteTemplateMixin, WebsiteAjaxTemplateMixin,
SpecialUserRequiredMixin)
from .navbar import ApplicationMenu
def _insert_bases(cls, bases):
""" Insert new bases in given view class """
old_bases = cls.__bases__
new_bases = tuple(bases) + old_bases
cls.__bases__ = new_bases
class Webpage:
""" Webpage configurator. It is used as a decorator.
The constructor takes one positionnal argument:
- app_name : name of the application where this view shall be categorized.
and keyword arguments:
- defaults : mapping of default options.
- menu : does it register a menu ? default is True
- icon : bootstrap name of menu header icon, ignored if 'menu' is False.
Options are :
- title: tuple of (header, header_small), header_small is optionnal.
- restricted: set of group to which access is restricted.
- ajax: can this view be called as ajax ?
"""
options = [
('title', ('Unset', 'small header')),
('restricted', []),
('ajax', False)
]
def __init__(self, app_name, icon=None, defaults={}, menu=True):
self.app_name = app_name
if menu: # Build ApplicationMenu subclass
app_menu = type(
app_name.title() + "Menu",
(ApplicationMenu,),
{'name': app_name,
'header': (app_name.title(), '%s:index' % app_name, icon),
'_links': [],
'_dropdowns': [],
}
)
self.app_menu = app_menu
else:
self.app_menu = None
self._defaults = {}
self._updated = {} # Store updated options
# Set all default options
for opt_name, opt_default in self.options:
self._set_option(opt_name, defaults.get(opt_name, opt_default))
def __getattr__(self, attr):
""" Return the overriden value if any, default overwise """
return self._updated.get(attr, self._defaults[attr])
def _set_option(self, attr, value):
""" Set the default value if there is none already, updated overwise """
if not attr in self._defaults:
self._defaults[attr] = value
else:
if attr in self._updated:
raise RuntimeError(attr, 'has already been updated !')
self._updated[attr] = value
def __call__(self, view_cls):
""" Setup the view and return it """
bases_to_add = []
if self.ajax: bases_to_add.append(WebsiteAjaxTemplateMixin)
else: bases_to_add.append(WebsiteTemplateMixin)
if self.restricted: bases_to_add.append(SpecialUserRequiredMixin)
_insert_bases(view_cls, bases_to_add)
# Setup configuration. ISSUE: defaults values will be overriden !
view_cls.app_name = self.app_name
view_cls.header = self.title
view_cls.app_users = self.restricted
self._updated = {} # Reset updated attributes to avoid misbehavior
return view_cls
def using(self, **kwargs):
""" Overrides defaults options with the values given """
for opt_name, _ in self.options:
if opt_name in kwargs:
self._set_option(opt_name, kwargs[opt_name])
return self