-
Notifications
You must be signed in to change notification settings - Fork 2.2k
/
nav.py
99 lines (80 loc) · 2.77 KB
/
nav.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
from django.core.urlresolvers import reverse
from django.core.exceptions import ImproperlyConfigured
from django.conf import settings
_nodes = []
class Node(object):
def __init__(self, label, url_name=None, url_args=None, url_kwargs=None,
access_fn=None, icon=None):
self.label = label
self.icon = icon
self.url_name = url_name
self.url_args = url_args
self.url_kwargs = url_kwargs
self.access_fn = access_fn
self.children = []
@property
def is_heading(self):
return self.url_name is None
@property
def url(self):
return reverse(self.url_name, args=self.url_args,
kwargs=self.url_kwargs)
def add_child(self, node):
self.children.append(node)
def is_visible(self, user):
if not self.access_fn:
return True
return self.access_fn(user)
def filter(self, user):
if not self.is_visible(user):
return None
node = Node(self.label, self.url_name, self.access_fn)
for child in self.children:
if child.is_visible(node):
node.add_child(child)
return node
def has_children(self):
return len(self.children) > 0
def register(node, display_order=5):
# We use tuples so we can sort later on. The lower the display order, the
# closer to the left the node appears.
_nodes.append((display_order, node))
def flush():
global _nodes
_nodes = []
def get_nodes(user):
"""
Return the visible navigation nodes for the passed user
"""
if not _nodes:
dashboard_nav = settings.OSCAR_DASHBOARD_NAVIGATION
create_menu(dashboard_nav)
nodes = []
for __, node in sorted(_nodes):
filtered_node = node.filter(user)
if filtered_node:
nodes.append(node)
return nodes
def create_menu(menu_items, parent=None):
"""
Create the navigation nodes based on a passed list of dicts
"""
for menu_dict in menu_items:
try:
label = menu_dict['label']
except KeyError:
raise ImproperlyConfigured(
"No label specified for menu item in dashboard")
children = menu_dict.get('children', [])
if children:
node = Node(label=label, icon=menu_dict.get('icon', None))
create_menu(children, parent=node)
else:
node = Node(label=label, icon=menu_dict.get('icon', None),
url_name=menu_dict.get('url_name', None),
url_kwargs=menu_dict.get('url_kwargs', None),
url_args=menu_dict.get('url_args', None))
if parent is None:
register(node, len(_nodes))
else:
parent.add_child(node)