django-smartbase-admin 0.2.47__py3-none-any.whl → 1.0.38__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.
- django_smartbase_admin/actions/admin_action_list.py +80 -51
- django_smartbase_admin/actions/advanced_filters.py +55 -20
- django_smartbase_admin/admin/admin_base.py +477 -89
- django_smartbase_admin/admin/site.py +104 -34
- django_smartbase_admin/admin/widgets.py +598 -26
- django_smartbase_admin/apps.py +2 -0
- django_smartbase_admin/engine/actions.py +34 -16
- django_smartbase_admin/engine/admin_base_view.py +253 -115
- django_smartbase_admin/engine/configuration.py +186 -4
- django_smartbase_admin/engine/const.py +7 -0
- django_smartbase_admin/engine/dashboard.py +44 -23
- django_smartbase_admin/engine/fake_inline.py +44 -7
- django_smartbase_admin/engine/field.py +54 -10
- django_smartbase_admin/engine/field_formatter.py +32 -9
- django_smartbase_admin/engine/filter_widgets.py +356 -21
- django_smartbase_admin/engine/menu_item.py +8 -5
- django_smartbase_admin/engine/modal_view.py +12 -7
- django_smartbase_admin/engine/request.py +2 -0
- django_smartbase_admin/integration/__init__.py +0 -0
- django_smartbase_admin/integration/django_cms.py +43 -0
- django_smartbase_admin/locale/sk/LC_MESSAGES/django.mo +0 -0
- django_smartbase_admin/locale/sk/LC_MESSAGES/django.po +268 -37
- django_smartbase_admin/migrations/0005_sbadminuserconfiguration.py +26 -0
- django_smartbase_admin/migrations/0006_alter_sbadminuserconfiguration_color_scheme.py +18 -0
- django_smartbase_admin/models.py +22 -0
- django_smartbase_admin/monkeypatch/admin_readonly_field_monkeypatch.py +96 -0
- django_smartbase_admin/monkeypatch/fake_inline_monkeypatch.py +1 -1
- django_smartbase_admin/querysets.py +3 -0
- django_smartbase_admin/services/configuration.py +30 -0
- django_smartbase_admin/services/thread_local.py +6 -19
- django_smartbase_admin/services/views.py +82 -27
- django_smartbase_admin/services/xlsx_export.py +6 -0
- django_smartbase_admin/static/sb_admin/build/tailwind.config.js +1 -0
- django_smartbase_admin/static/sb_admin/build/tailwind_config_partials/colors.js +4 -0
- django_smartbase_admin/static/sb_admin/build/tailwind_config_partials/spacing.js +1 -0
- django_smartbase_admin/static/sb_admin/build/webpack.common.js +11 -8
- django_smartbase_admin/static/sb_admin/css/ckeditor/ckeditor_content_dark.css +208 -0
- django_smartbase_admin/static/sb_admin/css/coloris/coloris.min.css +1 -0
- django_smartbase_admin/static/sb_admin/dist/calendar.js +1 -0
- django_smartbase_admin/static/sb_admin/dist/calendar_style.css +1 -0
- django_smartbase_admin/static/sb_admin/dist/calendar_style.js +0 -0
- django_smartbase_admin/static/sb_admin/dist/chart.js +1 -1
- django_smartbase_admin/static/sb_admin/dist/main.js +1 -1
- django_smartbase_admin/static/sb_admin/dist/main_style.css +1 -1
- django_smartbase_admin/static/sb_admin/dist/table.js +1 -1
- django_smartbase_admin/static/sb_admin/dist/table.js.LICENSE.txt +9 -0
- django_smartbase_admin/static/sb_admin/dist/tree_widget.js +1 -0
- django_smartbase_admin/static/sb_admin/dist/tree_widget_style.css +1 -0
- django_smartbase_admin/static/sb_admin/dist/tree_widget_style.js +0 -0
- django_smartbase_admin/static/sb_admin/fancytree/jquery.fancytree-all-deps.min.js +1 -0
- django_smartbase_admin/static/sb_admin/images/file_types/file-csv.svg +11 -0
- django_smartbase_admin/static/sb_admin/images/file_types/file-doc.svg +11 -0
- django_smartbase_admin/static/sb_admin/images/file_types/file-docx.svg +11 -0
- django_smartbase_admin/static/sb_admin/images/file_types/file-other.svg +13 -0
- django_smartbase_admin/static/sb_admin/images/file_types/file-pdf.svg +11 -0
- django_smartbase_admin/static/sb_admin/images/file_types/file-ppt.svg +11 -0
- django_smartbase_admin/static/sb_admin/images/file_types/file-xls.svg +11 -0
- django_smartbase_admin/static/sb_admin/images/file_types/file-xlsx.svg +11 -0
- django_smartbase_admin/static/sb_admin/images/file_types/file-zip.svg +18 -0
- django_smartbase_admin/static/sb_admin/images/flags/de-at.png +0 -0
- django_smartbase_admin/static/sb_admin/images/flags/de-ch.png +0 -0
- django_smartbase_admin/static/sb_admin/images/logo_light.svg +21 -0
- django_smartbase_admin/static/sb_admin/js/coloris/coloris.min.js +6 -0
- django_smartbase_admin/static/sb_admin/js/fullcalendar.min.js +14804 -0
- django_smartbase_admin/static/sb_admin/sprites/sb_admin/Bolt-one.svg +3 -0
- django_smartbase_admin/static/sb_admin/sprites/sb_admin/Calendar.svg +3 -0
- django_smartbase_admin/static/sb_admin/sprites/sb_admin/Caution.svg +3 -0
- django_smartbase_admin/static/sb_admin/sprites/sb_admin/Electric-drill.svg +3 -0
- django_smartbase_admin/static/sb_admin/sprites/sb_admin/Fire-extinguisher.svg +3 -0
- django_smartbase_admin/static/sb_admin/sprites/sb_admin/Gas.svg +3 -0
- django_smartbase_admin/static/sb_admin/sprites/sb_admin/Lightning-fill.svg +3 -0
- django_smartbase_admin/static/sb_admin/sprites/sb_admin/Moon.svg +3 -0
- django_smartbase_admin/static/sb_admin/sprites/sb_admin/Phone-telephone.svg +3 -0
- django_smartbase_admin/static/sb_admin/sprites/sb_admin/Printer.svg +3 -0
- django_smartbase_admin/static/sb_admin/sprites/sb_admin/Pull.svg +3 -0
- django_smartbase_admin/static/sb_admin/sprites/sb_admin/Sun-one.svg +3 -0
- django_smartbase_admin/static/sb_admin/sprites/sb_admin/Time.svg +3 -0
- django_smartbase_admin/static/sb_admin/src/css/_base.css +5 -1
- django_smartbase_admin/static/sb_admin/src/css/_colors.css +257 -82
- django_smartbase_admin/static/sb_admin/src/css/_components.css +66 -13
- django_smartbase_admin/static/sb_admin/src/css/_datepicker.css +8 -1
- django_smartbase_admin/static/sb_admin/src/css/_filer.css +60 -0
- django_smartbase_admin/static/sb_admin/src/css/_inlines.css +51 -10
- django_smartbase_admin/static/sb_admin/src/css/_tabulator.css +8 -2
- django_smartbase_admin/static/sb_admin/src/css/calendar.css +162 -0
- django_smartbase_admin/static/sb_admin/src/css/components/_button.css +41 -1
- django_smartbase_admin/static/sb_admin/src/css/components/_dropdown.css +26 -8
- django_smartbase_admin/static/sb_admin/src/css/components/_input.css +62 -20
- django_smartbase_admin/static/sb_admin/src/css/components/_modal.css +1 -1
- django_smartbase_admin/static/sb_admin/src/css/components/_query-builder.css +21 -2
- django_smartbase_admin/static/sb_admin/src/css/components/_toggle.css +12 -1
- django_smartbase_admin/static/sb_admin/src/css/components/_tooltip.css +8 -22
- django_smartbase_admin/static/sb_admin/src/css/style.css +17 -0
- django_smartbase_admin/static/sb_admin/src/css/tree_widget.css +411 -0
- django_smartbase_admin/static/sb_admin/src/js/autocomplete.js +63 -5
- django_smartbase_admin/static/sb_admin/src/js/calendar.js +56 -0
- django_smartbase_admin/static/sb_admin/src/js/chart.js +8 -22
- django_smartbase_admin/static/sb_admin/src/js/choices.js +18 -8
- django_smartbase_admin/static/sb_admin/src/js/datepicker.js +97 -336
- django_smartbase_admin/static/sb_admin/src/js/datepicker_plugins.js +357 -0
- django_smartbase_admin/static/sb_admin/src/js/main.js +307 -26
- django_smartbase_admin/static/sb_admin/src/js/multiselect.js +50 -41
- django_smartbase_admin/static/sb_admin/src/js/range.js +3 -2
- django_smartbase_admin/static/sb_admin/src/js/sb_ajax_params_tabulator_modifier.js +21 -0
- django_smartbase_admin/static/sb_admin/src/js/table.js +38 -13
- django_smartbase_admin/static/sb_admin/src/js/table_modules/advanced_filter_module.js +43 -20
- django_smartbase_admin/static/sb_admin/src/js/table_modules/data_edit_module.js +8 -10
- django_smartbase_admin/static/sb_admin/src/js/table_modules/filter_module.js +3 -3
- django_smartbase_admin/static/sb_admin/src/js/table_modules/header_tabs_module.js +11 -11
- django_smartbase_admin/static/sb_admin/src/js/table_modules/selection_module.js +28 -8
- django_smartbase_admin/static/sb_admin/src/js/table_modules/table_params_module.js +6 -0
- django_smartbase_admin/static/sb_admin/src/js/table_modules/views_module.js +19 -3
- django_smartbase_admin/static/sb_admin/src/js/tree_widget.js +406 -0
- django_smartbase_admin/static/sb_admin/src/js/utils.js +56 -21
- django_smartbase_admin/templates/sb_admin/actions/change_form.html +169 -117
- django_smartbase_admin/templates/sb_admin/actions/dashboard.html +2 -2
- django_smartbase_admin/templates/sb_admin/actions/delete_selected_confirmation.html +56 -32
- django_smartbase_admin/templates/sb_admin/actions/list.html +79 -42
- django_smartbase_admin/templates/sb_admin/actions/object_history.html +2 -2
- django_smartbase_admin/templates/sb_admin/actions/partials/action_link.html +14 -0
- django_smartbase_admin/templates/sb_admin/actions/partials/selected_rows_actions.html +2 -2
- django_smartbase_admin/templates/sb_admin/actions/partials/tabulator_header_v2.html +2 -2
- django_smartbase_admin/templates/sb_admin/actions/tree_list.html +63 -0
- django_smartbase_admin/templates/sb_admin/authentification/login_base.html +5 -1
- django_smartbase_admin/templates/sb_admin/components/columns.html +1 -1
- django_smartbase_admin/templates/sb_admin/components/filters_v2.html +99 -85
- django_smartbase_admin/templates/sb_admin/config/view.html +0 -1
- django_smartbase_admin/templates/sb_admin/dashboard/calendar_widget.html +69 -0
- django_smartbase_admin/templates/sb_admin/dashboard/chart_widget.html +21 -2
- django_smartbase_admin/templates/sb_admin/dashboard/list_widget.html +6 -0
- django_smartbase_admin/templates/sb_admin/dashboard/widget_base.html +1 -1
- django_smartbase_admin/templates/sb_admin/filter_widgets/advanced_filters/date_field.html +18 -8
- django_smartbase_admin/templates/sb_admin/filter_widgets/advanced_filters/multiple_choice_field.html +1 -1
- django_smartbase_admin/templates/sb_admin/filter_widgets/advanced_filters/tree_select_filter.html +2 -0
- django_smartbase_admin/templates/sb_admin/filter_widgets/date_field.html +18 -4
- django_smartbase_admin/templates/sb_admin/filter_widgets/multiple_choice_field.html +14 -0
- django_smartbase_admin/templates/sb_admin/filter_widgets/partials/clear.html +10 -5
- django_smartbase_admin/templates/sb_admin/filter_widgets/radio_choice_field.html +2 -2
- django_smartbase_admin/templates/sb_admin/filter_widgets/tree_select_filter.html +16 -0
- django_smartbase_admin/templates/sb_admin/includes/change_form_title.html +3 -1
- django_smartbase_admin/templates/sb_admin/includes/components.html +5 -1
- django_smartbase_admin/templates/sb_admin/includes/inline_fieldset.html +48 -39
- django_smartbase_admin/templates/sb_admin/includes/notifications.html +2 -1
- django_smartbase_admin/templates/sb_admin/includes/readonly_boolean_field.html +9 -0
- django_smartbase_admin/templates/sb_admin/includes/readonly_field.html +12 -0
- django_smartbase_admin/templates/sb_admin/includes/table_inline_delete_button.html +4 -5
- django_smartbase_admin/templates/sb_admin/inlines/stacked_inline.html +68 -40
- django_smartbase_admin/templates/sb_admin/inlines/table_inline.html +78 -36
- django_smartbase_admin/templates/sb_admin/integrations/filer/folder_list.html +18 -0
- django_smartbase_admin/templates/sb_admin/navigation.html +166 -158
- django_smartbase_admin/templates/sb_admin/partials/modal/modal_content.html +2 -6
- django_smartbase_admin/templates/sb_admin/sb_admin_base.html +49 -4
- django_smartbase_admin/templates/sb_admin/sb_admin_base_no_sidebar.html +35 -11
- django_smartbase_admin/templates/sb_admin/sb_admin_js_trans.html +3 -0
- django_smartbase_admin/templates/sb_admin/sprites/sb_admin.svg +1 -1
- django_smartbase_admin/templates/sb_admin/tailwind_whitelist.html +6 -3
- django_smartbase_admin/templates/sb_admin/widgets/array.html +0 -1
- django_smartbase_admin/templates/sb_admin/widgets/attributes.html +68 -0
- django_smartbase_admin/templates/sb_admin/widgets/autocomplete.html +13 -2
- django_smartbase_admin/templates/sb_admin/widgets/{checkbox_select.html → checkbox_dropdown.html} +2 -2
- django_smartbase_admin/templates/sb_admin/widgets/checkbox_group.html +15 -0
- django_smartbase_admin/templates/sb_admin/widgets/clearable_file_input.html +2 -2
- django_smartbase_admin/templates/sb_admin/widgets/color_field.html +30 -0
- django_smartbase_admin/templates/sb_admin/widgets/date.html +8 -1
- django_smartbase_admin/templates/sb_admin/widgets/filer_file.html +84 -0
- django_smartbase_admin/templates/sb_admin/widgets/html_read_only.html +1 -0
- django_smartbase_admin/templates/sb_admin/widgets/includes/related_item_buttons.html +38 -0
- django_smartbase_admin/templates/sb_admin/widgets/multiwidget.html +1 -1
- django_smartbase_admin/templates/sb_admin/widgets/radio.html +3 -2
- django_smartbase_admin/templates/sb_admin/widgets/radio_dropdown.html +30 -0
- django_smartbase_admin/templates/sb_admin/widgets/read_only_password_hash.html +3 -0
- django_smartbase_admin/templates/sb_admin/widgets/time.html +8 -1
- django_smartbase_admin/templates/sb_admin/widgets/toggle.html +1 -1
- django_smartbase_admin/templates/sb_admin/widgets/tree_base.html +59 -0
- django_smartbase_admin/templates/sb_admin/widgets/tree_select.html +24 -0
- django_smartbase_admin/templates/sb_admin/widgets/tree_select_inline.html +12 -0
- django_smartbase_admin/templatetags/sb_admin_tags.py +163 -4
- django_smartbase_admin/utils.py +22 -3
- django_smartbase_admin/views/dashboard_view.py +6 -0
- django_smartbase_admin/views/global_filter_view.py +8 -2
- django_smartbase_admin/views/translations_view.py +12 -5
- django_smartbase_admin/views/user_config_view.py +52 -0
- django_smartbase_admin-1.0.38.dist-info/METADATA +166 -0
- {django_smartbase_admin-0.2.47.dist-info → django_smartbase_admin-1.0.38.dist-info}/RECORD +186 -121
- {django_smartbase_admin-0.2.47.dist-info → django_smartbase_admin-1.0.38.dist-info}/WHEEL +1 -1
- django_smartbase_admin/templates/sb_admin/integrations/sorting/change_list.html +0 -401
- django_smartbase_admin-0.2.47.dist-info/METADATA +0 -25
- {django_smartbase_admin-0.2.47.dist-info → django_smartbase_admin-1.0.38.dist-info}/LICENSE.md +0 -0
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
import json
|
|
2
3
|
import math
|
|
4
|
+
from typing import Any, TYPE_CHECKING
|
|
3
5
|
|
|
4
|
-
from django.core.paginator import Paginator
|
|
5
6
|
from django.db.models import Q
|
|
6
7
|
from django.utils import timezone
|
|
8
|
+
from django.utils.html import escape
|
|
9
|
+
from django.utils.safestring import SafeString
|
|
7
10
|
from django.utils.text import smart_split, unescape_string_literal
|
|
8
11
|
|
|
9
|
-
from django_smartbase_admin.engine.actions import SBAdminAction
|
|
10
12
|
from django_smartbase_admin.engine.const import (
|
|
11
13
|
XLSX_PAGE_CHUNK_SIZE,
|
|
12
14
|
SELECTED_ROWS_KWARG_NAME,
|
|
@@ -32,8 +34,8 @@ from django_smartbase_admin.engine.const import (
|
|
|
32
34
|
CONFIG_NAME,
|
|
33
35
|
TABLE_PARAMS_FULL_TEXT_SEARCH,
|
|
34
36
|
TABLE_PARAMS_SELECTED_FILTER_TYPE,
|
|
35
|
-
FilterVersions,
|
|
36
37
|
ADVANCED_FILTER_DATA_NAME,
|
|
38
|
+
IGNORE_LIST_SELECTION,
|
|
37
39
|
)
|
|
38
40
|
from django_smartbase_admin.services.views import SBAdminViewService
|
|
39
41
|
from django_smartbase_admin.utils import import_with_injection
|
|
@@ -42,6 +44,19 @@ QueryBuilderService = import_with_injection(
|
|
|
42
44
|
"django_smartbase_admin.actions.advanced_filters", "QueryBuilderService"
|
|
43
45
|
)
|
|
44
46
|
|
|
47
|
+
if TYPE_CHECKING:
|
|
48
|
+
from django_smartbase_admin.engine.field import SBAdminField
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class SBAdminAction(object):
|
|
52
|
+
view = None
|
|
53
|
+
threadsafe_request = None
|
|
54
|
+
|
|
55
|
+
def __init__(self, view, request) -> None:
|
|
56
|
+
super().__init__()
|
|
57
|
+
self.view = view
|
|
58
|
+
self.threadsafe_request = request
|
|
59
|
+
|
|
45
60
|
|
|
46
61
|
class SBAdminListAction(SBAdminAction):
|
|
47
62
|
def __init__(
|
|
@@ -58,19 +73,12 @@ class SBAdminListAction(SBAdminAction):
|
|
|
58
73
|
self.all_params = json.loads(
|
|
59
74
|
request.request_data.request_get.get(BASE_PARAMS_NAME, "{}")
|
|
60
75
|
)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
source_data = request.body
|
|
68
|
-
else:
|
|
69
|
-
source_data = request.request_data.request_post.get(
|
|
70
|
-
BASE_PARAMS_NAME, "{}"
|
|
71
|
-
)
|
|
72
|
-
else:
|
|
73
|
-
source_data = "{}"
|
|
76
|
+
source_data = request.request_data.request_get.get(BASE_PARAMS_NAME, "{}")
|
|
77
|
+
if (
|
|
78
|
+
request.request_data.request_method == "POST"
|
|
79
|
+
and request.headers.get("X-TabulatorRequest", None) == "true"
|
|
80
|
+
):
|
|
81
|
+
source_data = request.body
|
|
74
82
|
try:
|
|
75
83
|
self.all_params = json.loads(source_data)
|
|
76
84
|
except json.JSONDecodeError:
|
|
@@ -90,7 +98,7 @@ class SBAdminListAction(SBAdminAction):
|
|
|
90
98
|
)
|
|
91
99
|
self.deselected_rows = self.selection_data.get(DESELECTED_ROWS_KWARG_NAME, [])
|
|
92
100
|
self.page_size = page_size or self.table_params.get(
|
|
93
|
-
TABLE_PARAMS_SIZE_NAME, self.view.get_list_per_page()
|
|
101
|
+
TABLE_PARAMS_SIZE_NAME, self.view.get_list_per_page(request)
|
|
94
102
|
)
|
|
95
103
|
self.init_column_fields()
|
|
96
104
|
self.tabulator_definition = tabulator_definition
|
|
@@ -139,11 +147,6 @@ class SBAdminListAction(SBAdminAction):
|
|
|
139
147
|
if field.field in values
|
|
140
148
|
]
|
|
141
149
|
|
|
142
|
-
def is_jquery_required(self, request):
|
|
143
|
-
return (
|
|
144
|
-
self.view.get_filters_version(request) == FilterVersions.FILTERS_VERSION_2
|
|
145
|
-
)
|
|
146
|
-
|
|
147
150
|
def get_template_data(self):
|
|
148
151
|
context_data = self.view.get_context_data(self.threadsafe_request)
|
|
149
152
|
constants = {
|
|
@@ -182,7 +185,9 @@ class SBAdminListAction(SBAdminAction):
|
|
|
182
185
|
tabulator_definition["tableIdColumnName"] = id_column_name
|
|
183
186
|
tabulator_definition["constants"] = constants
|
|
184
187
|
|
|
185
|
-
list_actions = self.list_actions or self.view._get_sbadmin_list_actions(
|
|
188
|
+
list_actions = self.list_actions or self.view._get_sbadmin_list_actions(
|
|
189
|
+
self.threadsafe_request
|
|
190
|
+
)
|
|
186
191
|
|
|
187
192
|
context_data.update(
|
|
188
193
|
{
|
|
@@ -190,7 +195,6 @@ class SBAdminListAction(SBAdminAction):
|
|
|
190
195
|
"tabulator_definition": tabulator_definition,
|
|
191
196
|
"id_column_name": id_column_name,
|
|
192
197
|
"filters": self.get_filters(),
|
|
193
|
-
"is_jquery_required": self.is_jquery_required(self.threadsafe_request),
|
|
194
198
|
"advanced_filters_data": QueryBuilderService.get_advanced_filters_context_data(
|
|
195
199
|
self
|
|
196
200
|
),
|
|
@@ -201,16 +205,18 @@ class SBAdminListAction(SBAdminAction):
|
|
|
201
205
|
self.threadsafe_request
|
|
202
206
|
),
|
|
203
207
|
"search_fields": self.view.get_search_fields(self.threadsafe_request),
|
|
204
|
-
"search_field_placeholder": self.view.get_search_field_placeholder(
|
|
205
|
-
|
|
208
|
+
"search_field_placeholder": self.view.get_search_field_placeholder(
|
|
209
|
+
self.threadsafe_request
|
|
210
|
+
),
|
|
211
|
+
"list_actions": self.view.process_actions(
|
|
206
212
|
self.threadsafe_request, list_actions
|
|
207
213
|
),
|
|
208
214
|
"list_selection_actions": self.view.get_sbadmin_list_selection_actions_grouped(
|
|
209
215
|
self.threadsafe_request
|
|
210
216
|
),
|
|
211
|
-
"config_url": self.view.get_config_url(),
|
|
217
|
+
"config_url": self.view.get_config_url(self.threadsafe_request),
|
|
212
218
|
"new_url": (
|
|
213
|
-
self.view.get_new_url()
|
|
219
|
+
self.view.get_new_url(self.threadsafe_request)
|
|
214
220
|
if self.view.has_add_permission(self.threadsafe_request)
|
|
215
221
|
else None
|
|
216
222
|
),
|
|
@@ -224,9 +230,23 @@ class SBAdminListAction(SBAdminAction):
|
|
|
224
230
|
for sort in self.table_params.get("sort", []):
|
|
225
231
|
order_by.append(f"{'-' if sort['dir'] == 'desc' else ''}{sort['field']}")
|
|
226
232
|
if len(order_by) == 0:
|
|
227
|
-
order_by = self.view.get_list_ordering() or [
|
|
233
|
+
order_by = self.view.get_list_ordering(self.threadsafe_request) or [
|
|
234
|
+
self.get_pk_field().name
|
|
235
|
+
]
|
|
228
236
|
return order_by
|
|
229
237
|
|
|
238
|
+
def get_order_by_fields_from_request(self):
|
|
239
|
+
order_by = self.get_order_by_from_request()
|
|
240
|
+
order_by_fields = []
|
|
241
|
+
order_by_fields_names = set()
|
|
242
|
+
for field in order_by:
|
|
243
|
+
field_name = field[1:] if field.startswith("-") else field
|
|
244
|
+
order_by_fields_names.add(field_name)
|
|
245
|
+
for field in self.column_fields:
|
|
246
|
+
if field.name in order_by_fields_names:
|
|
247
|
+
order_by_fields.append(field)
|
|
248
|
+
return order_by_fields
|
|
249
|
+
|
|
230
250
|
def get_filter_from_request(self):
|
|
231
251
|
base_filters = SBAdminViewService.get_filter_from_request(
|
|
232
252
|
self.threadsafe_request, self.column_fields, self.filter_data
|
|
@@ -253,6 +273,7 @@ class SBAdminListAction(SBAdminAction):
|
|
|
253
273
|
filter_fields.extend(
|
|
254
274
|
QueryBuilderService.get_filters_fields_for_list_action(self)
|
|
255
275
|
)
|
|
276
|
+
filter_fields.extend(self.get_order_by_fields_from_request())
|
|
256
277
|
if self.is_search_query():
|
|
257
278
|
search_fields = self.get_search_fields(self.threadsafe_request)
|
|
258
279
|
filter_fields.extend(search_fields)
|
|
@@ -271,7 +292,7 @@ class SBAdminListAction(SBAdminAction):
|
|
|
271
292
|
**self.get_annotates(visible_fields)
|
|
272
293
|
)
|
|
273
294
|
|
|
274
|
-
def get_visible_column_fields(self):
|
|
295
|
+
def get_visible_column_fields(self) -> list[SBAdminField]:
|
|
275
296
|
columns_data_dict = self.columns_data.get(COLUMNS_DATA_COLUMNS_NAME, {})
|
|
276
297
|
return [
|
|
277
298
|
field
|
|
@@ -288,8 +309,15 @@ class SBAdminListAction(SBAdminAction):
|
|
|
288
309
|
values = [self.get_pk_field().name]
|
|
289
310
|
visible_column_fields = self.get_visible_column_fields()
|
|
290
311
|
values.extend([field.field for field in visible_column_fields])
|
|
312
|
+
# Include supporting_annotates keys for visible columns
|
|
313
|
+
for field in visible_column_fields:
|
|
314
|
+
if field.supporting_annotates:
|
|
315
|
+
values.extend(field.supporting_annotates.keys())
|
|
291
316
|
if self.view.sbadmin_list_display_data:
|
|
292
317
|
values.extend(self.view.sbadmin_list_display_data)
|
|
318
|
+
values.extend(
|
|
319
|
+
[field.field for field in self.get_order_by_fields_from_request()]
|
|
320
|
+
)
|
|
293
321
|
return values
|
|
294
322
|
|
|
295
323
|
def get_search_results(self, request, queryset, search_term):
|
|
@@ -386,32 +414,28 @@ class SBAdminListAction(SBAdminAction):
|
|
|
386
414
|
"last_row": total_count,
|
|
387
415
|
}
|
|
388
416
|
|
|
389
|
-
def process_final_data(self, final_data):
|
|
417
|
+
def process_final_data(self, final_data: list[dict[str, Any]]) -> None:
|
|
390
418
|
visible_columns = self.get_visible_column_fields()
|
|
391
|
-
|
|
392
|
-
field
|
|
393
|
-
|
|
394
|
-
if field.view_method or field.python_formatter
|
|
395
|
-
]
|
|
419
|
+
field_key_field_map: dict[str, SBAdminField] = {
|
|
420
|
+
field.field: field for field in visible_columns
|
|
421
|
+
}
|
|
396
422
|
for row in final_data:
|
|
423
|
+
obj_id = row.get(self.get_pk_field().name, None)
|
|
397
424
|
additional_data = {}
|
|
398
425
|
if self.view.sbadmin_list_display_data:
|
|
399
426
|
additional_data = {
|
|
400
427
|
data: row.get(data, None)
|
|
401
428
|
for data in self.view.sbadmin_list_display_data
|
|
402
429
|
}
|
|
403
|
-
for
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
processed_value = field.view_method(
|
|
409
|
-
object_id, value, **additional_data
|
|
430
|
+
for field_key, value in row.items():
|
|
431
|
+
if field_key in field_key_field_map:
|
|
432
|
+
field = field_key_field_map[field_key]
|
|
433
|
+
value = self.view.process_field_data(
|
|
434
|
+
self.threadsafe_request, field, obj_id, value, additional_data
|
|
410
435
|
)
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
row[field.field] = formatted_value
|
|
436
|
+
if isinstance(value, str) and not isinstance(value, SafeString):
|
|
437
|
+
value = escape(value)
|
|
438
|
+
row[field_key] = value
|
|
415
439
|
|
|
416
440
|
def get_json_data(self):
|
|
417
441
|
return self.get_data()
|
|
@@ -426,6 +450,9 @@ class SBAdminListAction(SBAdminAction):
|
|
|
426
450
|
return final_data
|
|
427
451
|
|
|
428
452
|
def get_selection_queryset(self):
|
|
453
|
+
if not self.selection_data:
|
|
454
|
+
# don't run with no selection data as it will result in querying all records
|
|
455
|
+
return Q(id__in=[])
|
|
429
456
|
additional_filter = None
|
|
430
457
|
if self.selected_rows and self.selected_rows != SELECT_ALL_KEYWORD:
|
|
431
458
|
additional_filter = Q(id__in=self.selected_rows)
|
|
@@ -434,13 +461,15 @@ class SBAdminListAction(SBAdminAction):
|
|
|
434
461
|
additional_filter = ~Q(id__in=self.deselected_rows)
|
|
435
462
|
return additional_filter
|
|
436
463
|
|
|
437
|
-
def get_xlsx_data(self):
|
|
464
|
+
def get_xlsx_data(self, request):
|
|
438
465
|
page_size = XLSX_PAGE_CHUNK_SIZE
|
|
439
466
|
file_name = (
|
|
440
467
|
f'{self.view.get_menu_label()}__{timezone.now().strftime("%Y-%m-%d")}.xlsx'
|
|
441
468
|
)
|
|
442
469
|
columns = self.get_excel_columns()
|
|
443
|
-
additional_filter =
|
|
470
|
+
additional_filter = Q()
|
|
471
|
+
if request.request_data.modifier != IGNORE_LIST_SELECTION:
|
|
472
|
+
additional_filter = self.get_selection_queryset()
|
|
444
473
|
data_list = []
|
|
445
474
|
report_data = self.get_data(
|
|
446
475
|
page_size=page_size,
|
|
@@ -457,8 +486,8 @@ class SBAdminListAction(SBAdminAction):
|
|
|
457
486
|
)["data"]
|
|
458
487
|
)
|
|
459
488
|
options = (
|
|
460
|
-
self.view.get_sbadmin_xlsx_options().to_json()
|
|
461
|
-
if self.view.get_sbadmin_xlsx_options()
|
|
489
|
+
self.view.get_sbadmin_xlsx_options(request).to_json()
|
|
490
|
+
if self.view.get_sbadmin_xlsx_options(request)
|
|
462
491
|
else {}
|
|
463
492
|
)
|
|
464
493
|
return [file_name, data_list, columns, options]
|
|
@@ -5,7 +5,7 @@ from dataclasses import field as dataclass_field
|
|
|
5
5
|
from typing import List, Optional, TYPE_CHECKING
|
|
6
6
|
|
|
7
7
|
from django.db import models
|
|
8
|
-
from django.db.models import Q
|
|
8
|
+
from django.db.models import Q, Count
|
|
9
9
|
from django.template.loader import render_to_string
|
|
10
10
|
from django.utils.translation import gettext_lazy as _
|
|
11
11
|
|
|
@@ -45,8 +45,15 @@ class AllOperators(models.TextChoices):
|
|
|
45
45
|
IS_NOT_NULL = "is_not_null", _("Is not null")
|
|
46
46
|
BEFORE = "before", _("Before")
|
|
47
47
|
AFTER = "after", _("After")
|
|
48
|
+
IN_THE_LAST = "in_the_last", _("In the last")
|
|
49
|
+
IN_THE_NEXT = "in_the_next", _("In the next")
|
|
48
50
|
|
|
49
51
|
|
|
52
|
+
NULL_ATTRIBUTES = [
|
|
53
|
+
AllOperators.IS_NULL,
|
|
54
|
+
AllOperators.IS_NOT_NULL,
|
|
55
|
+
]
|
|
56
|
+
|
|
50
57
|
DATE_ATTRIBUTES = [
|
|
51
58
|
AllOperators.BETWEEN,
|
|
52
59
|
AllOperators.NOT_BETWEEN,
|
|
@@ -54,6 +61,8 @@ DATE_ATTRIBUTES = [
|
|
|
54
61
|
AllOperators.AFTER,
|
|
55
62
|
AllOperators.IS_NULL,
|
|
56
63
|
AllOperators.IS_NOT_NULL,
|
|
64
|
+
AllOperators.IN_THE_LAST,
|
|
65
|
+
AllOperators.IN_THE_NEXT,
|
|
57
66
|
]
|
|
58
67
|
|
|
59
68
|
NUMBER_ATTRIBUTES = [
|
|
@@ -96,12 +105,16 @@ class QueryBuilderFilter:
|
|
|
96
105
|
filter_widget_for_context.input_id = QB_JS_PREFIX
|
|
97
106
|
filter_widget_for_context.input_name = QB_JS_PREFIX
|
|
98
107
|
operators = filter_widget.get_advanced_filter_operators()
|
|
99
|
-
|
|
108
|
+
operators_values = []
|
|
109
|
+
for operator in operators:
|
|
110
|
+
if filter_widget.exclude_null_operators and operator in NULL_ATTRIBUTES:
|
|
111
|
+
continue
|
|
112
|
+
operators_values.append(operator.value)
|
|
100
113
|
return cls(
|
|
101
114
|
id=filter_widget.input_id,
|
|
102
115
|
field=filter_widget.field.field,
|
|
103
116
|
label=filter_widget.field.title,
|
|
104
|
-
operators=
|
|
117
|
+
operators=operators_values,
|
|
105
118
|
input=render_to_string(
|
|
106
119
|
template_name=filter_widget.template_name.replace(
|
|
107
120
|
"filter_widgets/", "filter_widgets/advanced_filters/"
|
|
@@ -148,6 +161,8 @@ class QueryBuilderService:
|
|
|
148
161
|
AllOperators.IS_NOT_NULL.value: "__isnull",
|
|
149
162
|
AllOperators.BEFORE.value: "__lt",
|
|
150
163
|
AllOperators.AFTER.value: "__gte",
|
|
164
|
+
AllOperators.IN_THE_LAST.value: "__range",
|
|
165
|
+
AllOperators.IN_THE_NEXT.value: "__range",
|
|
151
166
|
}
|
|
152
167
|
|
|
153
168
|
ZERO_INPUTS_OPERATORS = {
|
|
@@ -236,36 +251,56 @@ class QueryBuilderService:
|
|
|
236
251
|
if field is None:
|
|
237
252
|
continue
|
|
238
253
|
|
|
239
|
-
value = field.filter_widget.parse_value_from_input(
|
|
240
|
-
request, rule["value"]
|
|
241
|
-
)
|
|
242
|
-
if operator not in cls.LIST_OPERATORS and isinstance(value, list):
|
|
243
|
-
value = value[0]
|
|
244
|
-
|
|
245
254
|
if operator in cls.ZERO_INPUTS_OPERATORS:
|
|
255
|
+
value = None
|
|
246
256
|
filter_value = (
|
|
247
257
|
True
|
|
248
258
|
if operator in [AllOperators.IS_NULL, AllOperators.IS_NOT_NULL]
|
|
249
259
|
else ""
|
|
250
260
|
)
|
|
261
|
+
if field.annotate and isinstance(field.annotate, Count):
|
|
262
|
+
filter_value = 0
|
|
251
263
|
q = Q(
|
|
252
264
|
**{
|
|
253
265
|
f"{field.filter_field}{cls.OPERATOR_MAP[operator]}": filter_value,
|
|
254
266
|
}
|
|
255
267
|
)
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
268
|
+
from django_smartbase_admin.engine.filter_widgets import (
|
|
269
|
+
StringFilterWidget,
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
if isinstance(
|
|
273
|
+
field.filter_widget, StringFilterWidget
|
|
274
|
+
) and operator in [
|
|
275
|
+
AllOperators.IS_EMPTY,
|
|
276
|
+
AllOperators.IS_NOT_EMPTY,
|
|
277
|
+
]:
|
|
278
|
+
q = q | Q(
|
|
279
|
+
**{
|
|
280
|
+
f"{field.filter_field}{cls.OPERATOR_MAP[AllOperators.IS_NULL]}": True
|
|
281
|
+
}
|
|
282
|
+
)
|
|
265
283
|
else:
|
|
266
|
-
|
|
267
|
-
|
|
284
|
+
value = field.filter_widget.parse_value_from_input(
|
|
285
|
+
request, rule["value"]
|
|
268
286
|
)
|
|
287
|
+
if operator not in cls.LIST_OPERATORS and isinstance(value, list):
|
|
288
|
+
value = value[0]
|
|
289
|
+
if operator in [
|
|
290
|
+
AllOperators.BETWEEN.value,
|
|
291
|
+
AllOperators.NOT_BETWEEN.value,
|
|
292
|
+
]:
|
|
293
|
+
q = Q()
|
|
294
|
+
if value[0] is not None:
|
|
295
|
+
q &= Q(**{f"{field.filter_field}__gte": value[0]})
|
|
296
|
+
if value[1] is not None:
|
|
297
|
+
q &= Q(**{f"{field.filter_field}__lte": value[1]})
|
|
298
|
+
else:
|
|
299
|
+
q = Q(
|
|
300
|
+
**{
|
|
301
|
+
f"{field.filter_field}{cls.OPERATOR_MAP[operator]}": value
|
|
302
|
+
}
|
|
303
|
+
)
|
|
269
304
|
|
|
270
305
|
if operator in cls.NEGATIVE_OPERATORS:
|
|
271
306
|
q = ~q
|