irie 0.0.26__py3-none-any.whl → 0.0.28__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of irie might be problematic. Click here for more details.

Files changed (45) hide show
  1. irie/apps/admin_dash/__init__.py +1 -0
  2. irie/apps/admin_dash/admin.py +0 -0
  3. irie/apps/admin_dash/apps.py +6 -0
  4. irie/apps/admin_dash/forms.py +67 -0
  5. irie/apps/admin_dash/models.py +1 -0
  6. irie/apps/admin_dash/templatetags/__init__.py +0 -0
  7. irie/apps/admin_dash/templatetags/admin_material.py +86 -0
  8. irie/apps/admin_dash/templatetags/replace_value.py +8 -0
  9. irie/apps/admin_dash/urls.py +36 -0
  10. irie/apps/admin_dash/utils.py +462 -0
  11. irie/apps/admin_dash/views.py +113 -0
  12. irie/apps/events/views.py +4 -5
  13. irie/apps/inventory/filters.py +1 -1
  14. irie/apps/inventory/migrations/0003_asset_notes.py +18 -0
  15. irie/apps/inventory/models.py +11 -5
  16. irie/apps/inventory/templatetags/__init__.py +0 -0
  17. irie/apps/inventory/templatetags/get.py +6 -0
  18. irie/apps/inventory/templatetags/nbi.py +6 -0
  19. irie/apps/inventory/urls.py +1 -0
  20. irie/apps/inventory/views.py +72 -33
  21. irie/apps/static/assets/css/brace.css +22272 -14509
  22. irie/apps/static/assets/css/brace.css.map +1 -1
  23. irie/apps/static/assets/css/brace.min.css +32 -1
  24. irie/apps/static/assets/img/twin.png +0 -0
  25. irie/apps/static/assets/js/brace.js +858 -38
  26. irie/apps/templates/events/event-table.html +1 -2
  27. irie/apps/templates/includes/asset-event-table.html +1 -1
  28. irie/apps/templates/includes/navigation.html +1 -1
  29. irie/apps/templates/includes/settings-box.html +1 -1
  30. irie/apps/templates/includes/sidebar.html +4 -4
  31. irie/apps/templates/inventory/asset-profile.html +50 -15
  32. irie/apps/templates/inventory/asset-table.html +12 -2
  33. irie/apps/templates/inventory/dashboard.html +0 -1
  34. irie/apps/templates/layouts/base.html +1 -0
  35. irie/apps/templates/site/index.html +42 -12
  36. irie/apps/templates/site/robots.txt +42 -1
  37. irie/core/settings.py +1 -0
  38. irie/init/calid.py +95 -95
  39. irie/init/management/commands/init_assets.py +1 -11
  40. irie/init/management/commands/init_cesmd.py +19 -8
  41. {irie-0.0.26.dist-info → irie-0.0.28.dist-info}/METADATA +3 -2
  42. {irie-0.0.26.dist-info → irie-0.0.28.dist-info}/RECORD +45 -29
  43. {irie-0.0.26.dist-info → irie-0.0.28.dist-info}/WHEEL +1 -1
  44. {irie-0.0.26.dist-info → irie-0.0.28.dist-info}/entry_points.txt +0 -0
  45. {irie-0.0.26.dist-info → irie-0.0.28.dist-info}/top_level.txt +0 -0
@@ -0,0 +1 @@
1
+
File without changes
@@ -0,0 +1,6 @@
1
+ from django.apps import AppConfig
2
+
3
+ class AdminDashConfig(AppConfig):
4
+ default_auto_field = 'django.db.models.BigAutoField'
5
+ name = 'irie.apps.admin_dash'
6
+ icon = 'fa fa-user'
@@ -0,0 +1,67 @@
1
+ from django import forms
2
+ from django.contrib.auth.forms import UserCreationForm, AuthenticationForm, PasswordChangeForm, SetPasswordForm, PasswordResetForm, UsernameField
3
+ from django.contrib.auth.models import User
4
+ from django.utils.translation import gettext_lazy as _
5
+
6
+ class RegistrationForm(UserCreationForm):
7
+ password1 = forms.CharField(
8
+ label=_("Password"),
9
+ widget=forms.PasswordInput(attrs={'class': 'form-control'}),
10
+ )
11
+ password2 = forms.CharField(
12
+ label=_("Password Confirmation"),
13
+ widget=forms.PasswordInput(attrs={'class': 'form-control'}),
14
+ )
15
+
16
+ class Meta:
17
+ model = User
18
+ fields = ('username', 'email', )
19
+
20
+ widgets = {
21
+ 'username': forms.TextInput(attrs={
22
+ 'class': 'form-control'
23
+ }),
24
+ 'email': forms.EmailInput(attrs={
25
+ 'class': 'form-control'
26
+ })
27
+ }
28
+
29
+ class LoginForm(AuthenticationForm):
30
+ username = UsernameField(widget=forms.TextInput(attrs={
31
+ 'class': 'form-control'
32
+ }))
33
+ password = forms.CharField(max_length=50, widget=forms.PasswordInput(attrs={
34
+ 'class': 'form-control'
35
+ }))
36
+
37
+
38
+ class UserPasswordResetForm(PasswordResetForm):
39
+ email = forms.EmailField(widget=forms.EmailInput(attrs={
40
+ 'class': 'form-control',
41
+ 'placeholder': 'Email'
42
+ }))
43
+
44
+ class UserSetPasswordForm(SetPasswordForm):
45
+ new_password1 = forms.CharField(max_length=50, widget=forms.PasswordInput(attrs={
46
+ 'class': 'form-control',
47
+ 'placeholder': 'New Password'
48
+ }), label="New Password")
49
+ new_password2 = forms.CharField(max_length=50, widget=forms.PasswordInput(attrs={
50
+ 'class': 'form-control',
51
+ 'placeholder': 'Confirm New Password'
52
+ }), label="Confirm New Password")
53
+
54
+
55
+ class UserPasswordChangeForm(PasswordChangeForm):
56
+ old_password = forms.CharField(max_length=50, widget=forms.PasswordInput(attrs={
57
+ 'class': 'form-control',
58
+ 'placeholder': 'Old Password'
59
+ }), label='Old Password')
60
+ new_password1 = forms.CharField(max_length=50, widget=forms.PasswordInput(attrs={
61
+ 'class': 'form-control',
62
+ 'placeholder': 'New Password'
63
+ }), label="New Password")
64
+ new_password2 = forms.CharField(max_length=50, widget=forms.PasswordInput(attrs={
65
+ 'class': 'form-control',
66
+ 'placeholder': 'Confirm New Password'
67
+ }), label="Confirm New Password")
@@ -0,0 +1 @@
1
+
File without changes
@@ -0,0 +1,86 @@
1
+ import re
2
+ from django import template
3
+ from django.utils.html import format_html
4
+ from django.utils.safestring import mark_safe
5
+ from django.contrib.admin.views.main import PAGE_VAR
6
+ from irie.apps.admin_dash.utils import get_menu_items
7
+
8
+ register = template.Library()
9
+ assignment_tag = register.assignment_tag if hasattr(register, 'assignment_tag') else register.simple_tag
10
+
11
+
12
+ @register.filter
13
+ def clean_text(value):
14
+ res = value.replace('\n', ' ')
15
+ return res
16
+
17
+
18
+ @register.filter
19
+ def checkbox(value):
20
+ res = re.sub(r"</?(?i:td)(.|\n)*?>", "", value)
21
+ return res
22
+
23
+
24
+ @assignment_tag(takes_context=True)
25
+ def admin_get_menu(context):
26
+ return get_menu_items(context)
27
+
28
+
29
+ @assignment_tag(takes_context=True)
30
+ def get_direction(context):
31
+ res = {
32
+ 'panel': 'text-left',
33
+ 'notify': 'right',
34
+ 'float': 'float-right',
35
+ 'reverse_panel': 'text-right',
36
+ 'nav': 'ml-auto'
37
+ }
38
+
39
+ if context.get('LANGUAGE_BIDI'):
40
+ res['panel'] = 'text-right'
41
+ res['notify'] = 'left'
42
+ res['float'] = ''
43
+ res['reverse_panel'] = 'text-left'
44
+ res['nav'] = 'mr-auto'
45
+ return res
46
+
47
+
48
+ @assignment_tag(takes_context=True)
49
+ def get_admin_setting(context):
50
+ # user = context.get('request').user
51
+ # admin_black_setting = user.admin_black_setting if hasattr(user, 'admin_black_setting') else None
52
+ res = {
53
+ # 'sidebar_background': admin_black_setting.sidebar_background if admin_black_setting else 'primary',
54
+ # 'dark_mode': admin_black_setting.dark_mode if admin_black_setting else True,
55
+ # 'input_bg_color': '#ffffff' if admin_black_setting and not admin_black_setting.dark_mode else '#27293c'
56
+ }
57
+
58
+ return res
59
+
60
+
61
+ @register.simple_tag
62
+ def paginator_number(cl, i):
63
+ """
64
+ Generate an individual page index link in a paginated list.
65
+ """
66
+ if i == cl.paginator.ELLIPSIS:
67
+ return format_html('{} ', cl.paginator.ELLIPSIS)
68
+ elif i == cl.page_num:
69
+ return format_html('<a href="" class="page-link">{}</a> ', i)
70
+ else:
71
+ return format_html(
72
+ '<a href="{}" class="page-link {}">{}</a> ',
73
+ cl.get_query_string({PAGE_VAR: i}),
74
+ mark_safe('end' if i == cl.paginator.num_pages else ''),
75
+ i,
76
+ )
77
+
78
+
79
+ @register.filter
80
+ def sum_number(value, number):
81
+ return value + number
82
+
83
+
84
+ @register.filter
85
+ def neg_num(value, number):
86
+ return value - number
@@ -0,0 +1,8 @@
1
+ from django import template
2
+
3
+ register = template.Library()
4
+
5
+
6
+ @register.filter(name="replace_value")
7
+ def replace_value(value, arg):
8
+ return value.replace(arg, " ").title()
@@ -0,0 +1,36 @@
1
+ from django.urls import path
2
+ from irie.apps.admin_dash import views
3
+ from django.contrib.auth import views as auth_views
4
+
5
+
6
+ urlpatterns = [
7
+ path('', views.index, name="index"),
8
+ path('tables/', views.tables, name="tables"),
9
+ path('billing/', views.billing, name="billing"),
10
+ path('virtual-reality/', views.virtual_reality, name="virtual_reality"),
11
+ path('rtl/', views.rtl, name="rtl"),
12
+ path('notifications/', views.notifications, name="notifications"),
13
+ path('profile/', views.profile, name="profile"),
14
+ path('map/', views.map, name="map"),
15
+ path('icons/', views.icons, name="icons"),
16
+ path('typography/', views.typography, name="typography"),
17
+ path('template/', views.template, name="template"),
18
+
19
+ # Authentication
20
+ path('accounts/register/', views.register, name='register'),
21
+ path('accounts/login/', views.UserLoginView.as_view(), name='login'),
22
+ path('accounts/logout/', views.user_logout_view, name='logout'),
23
+ path('accounts/password-change/', views.UserPasswordChangeView.as_view(), name='password_change'),
24
+ path('accounts/password-change-done/', auth_views.PasswordChangeDoneView.as_view(
25
+ template_name='pages/password_change_done.html'
26
+ ), name="password_change_done" ),
27
+ path('accounts/password-reset/', views.UserPasswordResetView.as_view(), name='password_reset'),
28
+ path('accounts/password-reset-confirm/<uidb64>/<token>/',
29
+ views.UserPasswordResetConfirmView.as_view(), name='password_reset_confirm'),
30
+ path('accounts/password-reset-done/', auth_views.PasswordResetDoneView.as_view(
31
+ template_name='pages/password_reset_done.html'
32
+ ), name='password_reset_done'),
33
+ path('accounts/password-reset-complete/', auth_views.PasswordResetCompleteView.as_view(
34
+ template_name='pages/password_reset_complete.html'
35
+ ), name='password_reset_complete'),
36
+ ]
@@ -0,0 +1,462 @@
1
+ import json
2
+ import datetime
3
+
4
+ from django.template import Context
5
+ from django.utils import translation
6
+
7
+ try:
8
+ from django.apps.registry import apps
9
+ except ImportError:
10
+ try:
11
+ from django.apps import apps # Fix Django 1.7 import issue
12
+ except ImportError:
13
+ pass
14
+
15
+ from django.core.serializers.json import DjangoJSONEncoder
16
+ from django.urls import reverse, resolve, NoReverseMatch
17
+ from django.http import HttpResponse
18
+ from django.contrib.admin import AdminSite
19
+ from django.utils.text import capfirst
20
+ from django.contrib import messages
21
+ from django.contrib.admin.options import IncorrectLookupParameters
22
+ from django.contrib import admin
23
+ from django.utils.text import slugify
24
+
25
+ try:
26
+ from django.utils.translation import ugettext_lazy as _
27
+ except ImportError:
28
+ from django.utils.translation import gettext_lazy as _ # Django 4.0.0 and more
29
+
30
+ from collections import OrderedDict
31
+
32
+
33
+ default_apps_icon = {
34
+ 'auth': 'fa fa-users'
35
+ }
36
+
37
+
38
+ class JsonResponse(HttpResponse):
39
+ """
40
+ An HTTP response class that consumes data to be serialized to JSON.
41
+ :param data: Data to be dumped into json. By default only ``dict`` objects
42
+ are allowed to be passed due to a security flaw before EcmaScript 5. See
43
+ the ``safe`` parameter for more information.
44
+ :param encoder: Should be an json encoder class. Defaults to
45
+ ``django.core.serializers.json.DjangoJSONEncoder``.
46
+ :param safe: Controls if only ``dict`` objects may be serialized. Defaults
47
+ to ``True``.
48
+ """
49
+
50
+ def __init__(self, data, encoder=DjangoJSONEncoder, safe=True, **kwargs):
51
+ if safe and not isinstance(data, dict):
52
+ raise TypeError('In order to allow non-dict objects to be '
53
+ 'serialized set the safe parameter to False')
54
+ kwargs.setdefault('content_type', 'application/json')
55
+ data = json.dumps(data, cls=encoder)
56
+ super(JsonResponse, self).__init__(content=data, **kwargs)
57
+
58
+
59
+ def get_app_list(context, order=True):
60
+ admin_site = get_admin_site(context)
61
+ request = context['request']
62
+
63
+ app_dict = {}
64
+ for model, model_admin in admin_site._registry.items():
65
+
66
+ app_icon = model._meta.app_config.icon if hasattr(model._meta.app_config, 'icon') else None
67
+ app_label = model._meta.app_label
68
+ try:
69
+ has_module_perms = model_admin.has_module_permission(request)
70
+ except AttributeError:
71
+ has_module_perms = request.user.has_module_perms(app_label) # Fix Django < 1.8 issue
72
+
73
+ if has_module_perms:
74
+ perms = model_admin.get_model_perms(request)
75
+
76
+ # Check whether user has any perm for this module.
77
+ # If so, add the module to the model_list.
78
+ if True in perms.values():
79
+ info = (app_label, model._meta.model_name)
80
+ model_dict = {
81
+ 'name': capfirst(model._meta.verbose_name_plural),
82
+ 'object_name': model._meta.object_name,
83
+ 'perms': perms,
84
+ 'model_name': model._meta.model_name
85
+ }
86
+ if perms.get('change', False) or perms.get("view", False):
87
+ try:
88
+ model_dict['admin_url'] = reverse('admin:%s_%s_changelist' % info, current_app=admin_site.name)
89
+ except NoReverseMatch:
90
+ pass
91
+ if perms.get('add', False):
92
+ try:
93
+ model_dict['add_url'] = reverse('admin:%s_%s_add' % info, current_app=admin_site.name)
94
+ except NoReverseMatch:
95
+ pass
96
+ if app_label in app_dict:
97
+ app_dict[app_label]['models'].append(model_dict)
98
+ else:
99
+ try:
100
+ name = apps.get_app_config(app_label).verbose_name
101
+ except NameError:
102
+ name = app_label.title()
103
+ app_dict[app_label] = {
104
+ 'name': name,
105
+ 'app_label': app_label,
106
+ 'app_url': reverse(
107
+ 'admin:app_list',
108
+ kwargs={'app_label': app_label},
109
+ current_app=admin_site.name,
110
+ ),
111
+ 'has_module_perms': has_module_perms,
112
+ 'models': [model_dict],
113
+ }
114
+
115
+ if not app_icon:
116
+ app_icon = default_apps_icon[app_label] if app_label in default_apps_icon else None
117
+ app_dict[app_label]['icon'] = app_icon
118
+
119
+ # Sort the apps alphabetically.
120
+ app_list = list(app_dict.values())
121
+
122
+ if order:
123
+ app_list.sort(key=lambda x: x['name'].lower())
124
+
125
+ # Sort the models alphabetically within each app.
126
+ for app in app_list:
127
+ app['models'].sort(key=lambda x: x['name'])
128
+
129
+ return app_list
130
+
131
+
132
+ def get_admin_site(context):
133
+ try:
134
+ current_resolver = resolve(context.get('request').path)
135
+ index_resolver = resolve(reverse('%s:index' % current_resolver.namespaces[0]))
136
+
137
+ if hasattr(index_resolver.func, 'admin_site'):
138
+ return index_resolver.func.admin_site
139
+
140
+ for func_closure in index_resolver.func.__closure__:
141
+ if isinstance(func_closure.cell_contents, AdminSite):
142
+ return func_closure.cell_contents
143
+ except:
144
+ pass
145
+
146
+ return admin.site
147
+
148
+
149
+ def get_admin_site_name(context):
150
+ return get_admin_site(context).name
151
+
152
+
153
+ class SuccessMessageMixin(object):
154
+ """
155
+ Adds a success message on successful form submission.
156
+ """
157
+ success_message = ''
158
+
159
+ def form_valid(self, form):
160
+ response = super(SuccessMessageMixin, self).form_valid(form)
161
+ success_message = self.get_success_message(form.cleaned_data)
162
+ if success_message:
163
+ messages.success(self.request, success_message)
164
+ return response
165
+
166
+ def get_success_message(self, cleaned_data):
167
+ return self.success_message % cleaned_data
168
+
169
+
170
+ def get_model_queryset(admin_site, model, request, preserved_filters=None):
171
+ model_admin = admin_site._registry.get(model)
172
+
173
+ if model_admin is None:
174
+ return
175
+
176
+ try:
177
+ changelist_url = reverse('%s:%s_%s_changelist' % (
178
+ admin_site.name,
179
+ model._meta.app_label,
180
+ model._meta.model_name
181
+ ))
182
+ except NoReverseMatch:
183
+ return
184
+
185
+ changelist_filters = None
186
+
187
+ if preserved_filters:
188
+ changelist_filters = preserved_filters.get('_changelist_filters')
189
+
190
+ if changelist_filters:
191
+ changelist_url += '?' + changelist_filters
192
+
193
+ if model_admin:
194
+ queryset = model_admin.get_queryset(request)
195
+ else:
196
+ queryset = model.objects
197
+
198
+ list_display = model_admin.get_list_display(request)
199
+ list_display_links = model_admin.get_list_display_links(request, list_display)
200
+ list_filter = model_admin.get_list_filter(request)
201
+ search_fields = model_admin.get_search_fields(request) \
202
+ if hasattr(model_admin, 'get_search_fields') else model_admin.search_fields
203
+ list_select_related = model_admin.get_list_select_related(request) \
204
+ if hasattr(model_admin, 'get_list_select_related') else model_admin.list_select_related
205
+
206
+ actions = model_admin.get_actions(request)
207
+ if actions:
208
+ list_display = ['action_checkbox'] + list(list_display)
209
+
210
+ ChangeList = model_admin.get_changelist(request)
211
+
212
+ change_list_args = [
213
+ request, model, list_display, list_display_links, list_filter,
214
+ model_admin.date_hierarchy, search_fields, list_select_related,
215
+ model_admin.list_per_page, model_admin.list_max_show_all,
216
+ model_admin.list_editable, model_admin]
217
+
218
+ try:
219
+ sortable_by = model_admin.get_sortable_by(request)
220
+ change_list_args.append(sortable_by)
221
+ except AttributeError:
222
+ # django version < 2.1
223
+ pass
224
+
225
+ try:
226
+ cl = ChangeList(*change_list_args)
227
+ queryset = cl.get_queryset(request)
228
+ except IncorrectLookupParameters:
229
+ pass
230
+
231
+ return queryset
232
+
233
+
234
+ def get_possible_language_codes():
235
+ language_code = translation.get_language()
236
+
237
+ language_code = language_code.replace('_', '-').lower()
238
+ language_codes = []
239
+
240
+ # making dialect part uppercase
241
+ split = language_code.split('-', 2)
242
+ if len(split) == 2:
243
+ language_code = '%s-%s' % (split[0].lower(), split[1].upper()) if split[0] != split[1] else split[0]
244
+
245
+ language_codes.append(language_code)
246
+
247
+ # adding language code without dialect part
248
+ if len(split) == 2:
249
+ language_codes.append(split[0].lower())
250
+
251
+ return language_codes
252
+
253
+
254
+ def get_original_menu_items(context):
255
+ if context.get('user') and user_is_authenticated(context['user']):
256
+ # pinned_apps = PinnedApplication.objects.filter(user=context['user'].pk).values_list('app_label', flat=True)
257
+ pinned_apps = []
258
+ else:
259
+ pinned_apps = []
260
+
261
+ original_app_list = get_app_list(context)
262
+
263
+ return map(lambda app: {
264
+ 'app_label': app['app_label'],
265
+ 'url': app['app_url'],
266
+ 'url_blank': False,
267
+ 'label': app.get('name', capfirst(_(app['app_label']))),
268
+ 'has_perms': app.get('has_module_perms', False),
269
+ 'icon': app.get('icon', None),
270
+ 'models': list(map(lambda model: {
271
+ 'url': model.get('admin_url'),
272
+ 'url_blank': False,
273
+ 'name': model['model_name'],
274
+ 'object_name': model['object_name'],
275
+ 'label': model.get('name', model['object_name']),
276
+ 'has_perms': any(model.get('perms', {}).values()),
277
+ }, app['models'])),
278
+ 'pinned': app['app_label'] in pinned_apps,
279
+ 'custom': False
280
+ }, original_app_list)
281
+
282
+
283
+ def get_menu_item_url(url, original_app_list):
284
+ if isinstance(url, dict):
285
+ url_type = url.get('type')
286
+
287
+ if url_type == 'app':
288
+ return original_app_list[url['app_label']]['url']
289
+ elif url_type == 'model':
290
+ models = dict(map(
291
+ lambda x: (x['name'], x['url']),
292
+ original_app_list[url['app_label']]['models']
293
+ ))
294
+ return models[url['model']]
295
+ elif url_type == 'reverse':
296
+ return reverse(url['name'], args=url.get('args'), kwargs=url.get('kwargs'))
297
+ elif isinstance(url, str):
298
+ return url
299
+
300
+
301
+ def get_menu_items(context):
302
+ # pinned_apps = PinnedApplication.objects.filter(user=context['user'].pk).values_list('app_label', flat=True)
303
+ pinned_apps = []
304
+ original_app_list = OrderedDict(map(lambda app: (app['app_label'], app), get_original_menu_items(context)))
305
+ custom_app_list = None
306
+ custom_app_list_deprecated = None
307
+
308
+ if custom_app_list not in (None, False):
309
+ if isinstance(custom_app_list, dict):
310
+ admin_site = get_admin_site(context)
311
+ custom_app_list = custom_app_list.get(admin_site.name, [])
312
+
313
+ app_list = []
314
+
315
+ def get_menu_item_app_model(app_label, data):
316
+ item = {'has_perms': True}
317
+
318
+ if 'name' in data:
319
+ parts = data['name'].split('.', 2)
320
+
321
+ if len(parts) > 1:
322
+ app_label, name = parts
323
+ else:
324
+ name = data['name']
325
+
326
+ if app_label in original_app_list:
327
+ models = dict(map(
328
+ lambda x: (x['name'], x),
329
+ original_app_list[app_label]['models']
330
+ ))
331
+
332
+ if name in models:
333
+ item = models[name].copy()
334
+
335
+ if 'label' in data:
336
+ item['label'] = data['label']
337
+
338
+ if 'url' in data:
339
+ item['url'] = get_menu_item_url(data['url'], original_app_list)
340
+
341
+ if 'url_blank' in data:
342
+ item['url_blank'] = data['url_blank']
343
+
344
+ if 'permissions' in data:
345
+ item['has_perms'] = item.get('has_perms', True) and context['user'].has_perms(data['permissions'])
346
+
347
+ return item
348
+
349
+ def get_menu_item_app(data):
350
+ app_label = data.get('app_label')
351
+
352
+ if not app_label:
353
+ if 'label' not in data:
354
+ raise Exception('Custom menu items should at least have \'label\' or \'app_label\' key')
355
+ app_label = 'custom_%s' % slugify(data['label'], allow_unicode=True)
356
+
357
+ if app_label in original_app_list:
358
+ item = original_app_list[app_label].copy()
359
+ else:
360
+ item = {'app_label': app_label, 'has_perms': True}
361
+
362
+ if 'label' in data:
363
+ item['label'] = data['label']
364
+
365
+ if 'items' in data:
366
+ item['items'] = list(map(lambda x: get_menu_item_app_model(app_label, x), data['items']))
367
+
368
+ if 'url' in data:
369
+ item['url'] = get_menu_item_url(data['url'], original_app_list)
370
+
371
+ if 'url_blank' in data:
372
+ item['url_blank'] = data['url_blank']
373
+
374
+ if 'permissions' in data:
375
+ item['has_perms'] = item.get('has_perms', True) and context['user'].has_perms(data['permissions'])
376
+
377
+ item['pinned'] = item['app_label'] in pinned_apps
378
+
379
+ return item
380
+
381
+ for data in custom_app_list:
382
+ item = get_menu_item_app(data)
383
+ app_list.append(item)
384
+ elif custom_app_list_deprecated not in (None, False):
385
+ app_dict = {}
386
+ models_dict = {}
387
+
388
+ for app in original_app_list.values():
389
+ app_label = app['app_label']
390
+ app_dict[app_label] = app
391
+
392
+ for model in app['models']:
393
+ if app_label not in models_dict:
394
+ models_dict[app_label] = {}
395
+
396
+ models_dict[app_label][model['object_name']] = model
397
+
398
+ app['items'] = []
399
+
400
+ app_list = []
401
+
402
+ if isinstance(custom_app_list_deprecated, dict):
403
+ admin_site = get_admin_site(context)
404
+ custom_app_list_deprecated = custom_app_list_deprecated.get(admin_site.name, [])
405
+
406
+ for item in custom_app_list_deprecated:
407
+ app_label, models = item
408
+
409
+ if app_label in app_dict:
410
+ app = app_dict[app_label]
411
+
412
+ for model_label in models:
413
+ if model_label == '__all__':
414
+ app['items'] = models_dict[app_label].values()
415
+ break
416
+ elif model_label in models_dict[app_label]:
417
+ model = models_dict[app_label][model_label]
418
+ app['items'].append(model)
419
+
420
+ app_list.append(app)
421
+ else:
422
+ def map_item(item):
423
+ item['items'] = item['models']
424
+ return item
425
+
426
+ app_list = list(map(map_item, original_app_list.values()))
427
+
428
+ current_found = False
429
+
430
+ for app in app_list:
431
+ if not current_found:
432
+ for model in app['items']:
433
+ if not current_found and model.get('url') and context['request'].path.startswith(model['url']):
434
+ model['current'] = True
435
+ current_found = True
436
+ else:
437
+ model['current'] = False
438
+
439
+ if not current_found and app.get('url') and context['request'].path.startswith(app['url']):
440
+ app['current'] = True
441
+ current_found = True
442
+ else:
443
+ app['current'] = False
444
+
445
+ return app_list
446
+
447
+
448
+ def context_to_dict(context):
449
+ if isinstance(context, Context):
450
+ flat = {}
451
+ for d in context.dicts:
452
+ flat.update(d)
453
+ context = flat
454
+
455
+ return context
456
+
457
+ def user_is_authenticated(user):
458
+ if not hasattr(user.is_authenticated, '__call__'):
459
+ return user.is_authenticated
460
+ else:
461
+ return user.is_authenticated()
462
+