irie 0.0.27__py3-none-any.whl → 0.0.29__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.
- irie/apps/admin_dash/__init__.py +1 -0
- irie/apps/admin_dash/admin.py +0 -0
- irie/apps/admin_dash/apps.py +6 -0
- irie/apps/admin_dash/forms.py +67 -0
- irie/apps/admin_dash/models.py +1 -0
- irie/apps/admin_dash/templatetags/__init__.py +0 -0
- irie/apps/admin_dash/templatetags/admin_material.py +86 -0
- irie/apps/admin_dash/templatetags/replace_value.py +8 -0
- irie/apps/admin_dash/urls.py +36 -0
- irie/apps/admin_dash/utils.py +462 -0
- irie/apps/admin_dash/views.py +113 -0
- irie/apps/events/views.py +4 -5
- irie/apps/inventory/filters.py +1 -1
- irie/apps/inventory/migrations/0003_asset_notes.py +18 -0
- irie/apps/inventory/models.py +11 -5
- irie/apps/inventory/urls.py +1 -0
- irie/apps/inventory/views.py +72 -33
- irie/apps/static/assets/css/brace.css +22272 -14509
- irie/apps/static/assets/css/brace.css.map +1 -1
- irie/apps/static/assets/css/brace.min.css +32 -1
- irie/apps/static/assets/img/twin.png +0 -0
- irie/apps/static/assets/js/brace.js +858 -38
- irie/apps/templates/events/event-table.html +1 -2
- irie/apps/templates/includes/asset-event-table.html +1 -1
- irie/apps/templates/includes/navigation.html +1 -1
- irie/apps/templates/includes/sidebar.html +4 -4
- irie/apps/templates/inventory/asset-profile.html +6 -1
- irie/apps/templates/inventory/asset-table.html +12 -2
- irie/apps/templates/inventory/dashboard.html +0 -1
- irie/apps/templates/layouts/base.html +1 -0
- irie/apps/templates/site/index.html +10 -10
- irie/apps/templates/site/robots.txt +42 -1
- irie/core/settings.py +1 -0
- irie/init/calid.py +95 -95
- irie/init/management/commands/init_assets.py +1 -11
- irie/init/management/commands/init_cesmd.py +19 -8
- {irie-0.0.27.dist-info → irie-0.0.29.dist-info}/METADATA +3 -2
- {irie-0.0.27.dist-info → irie-0.0.29.dist-info}/RECORD +41 -28
- {irie-0.0.27.dist-info → irie-0.0.29.dist-info}/WHEEL +1 -1
- {irie-0.0.27.dist-info → irie-0.0.29.dist-info}/entry_points.txt +0 -0
- {irie-0.0.27.dist-info → irie-0.0.29.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
File without changes
|
|
@@ -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,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
|
+
|