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.
Files changed (188) hide show
  1. django_smartbase_admin/actions/admin_action_list.py +80 -51
  2. django_smartbase_admin/actions/advanced_filters.py +55 -20
  3. django_smartbase_admin/admin/admin_base.py +477 -89
  4. django_smartbase_admin/admin/site.py +104 -34
  5. django_smartbase_admin/admin/widgets.py +598 -26
  6. django_smartbase_admin/apps.py +2 -0
  7. django_smartbase_admin/engine/actions.py +34 -16
  8. django_smartbase_admin/engine/admin_base_view.py +253 -115
  9. django_smartbase_admin/engine/configuration.py +186 -4
  10. django_smartbase_admin/engine/const.py +7 -0
  11. django_smartbase_admin/engine/dashboard.py +44 -23
  12. django_smartbase_admin/engine/fake_inline.py +44 -7
  13. django_smartbase_admin/engine/field.py +54 -10
  14. django_smartbase_admin/engine/field_formatter.py +32 -9
  15. django_smartbase_admin/engine/filter_widgets.py +356 -21
  16. django_smartbase_admin/engine/menu_item.py +8 -5
  17. django_smartbase_admin/engine/modal_view.py +12 -7
  18. django_smartbase_admin/engine/request.py +2 -0
  19. django_smartbase_admin/integration/__init__.py +0 -0
  20. django_smartbase_admin/integration/django_cms.py +43 -0
  21. django_smartbase_admin/locale/sk/LC_MESSAGES/django.mo +0 -0
  22. django_smartbase_admin/locale/sk/LC_MESSAGES/django.po +268 -37
  23. django_smartbase_admin/migrations/0005_sbadminuserconfiguration.py +26 -0
  24. django_smartbase_admin/migrations/0006_alter_sbadminuserconfiguration_color_scheme.py +18 -0
  25. django_smartbase_admin/models.py +22 -0
  26. django_smartbase_admin/monkeypatch/admin_readonly_field_monkeypatch.py +96 -0
  27. django_smartbase_admin/monkeypatch/fake_inline_monkeypatch.py +1 -1
  28. django_smartbase_admin/querysets.py +3 -0
  29. django_smartbase_admin/services/configuration.py +30 -0
  30. django_smartbase_admin/services/thread_local.py +6 -19
  31. django_smartbase_admin/services/views.py +82 -27
  32. django_smartbase_admin/services/xlsx_export.py +6 -0
  33. django_smartbase_admin/static/sb_admin/build/tailwind.config.js +1 -0
  34. django_smartbase_admin/static/sb_admin/build/tailwind_config_partials/colors.js +4 -0
  35. django_smartbase_admin/static/sb_admin/build/tailwind_config_partials/spacing.js +1 -0
  36. django_smartbase_admin/static/sb_admin/build/webpack.common.js +11 -8
  37. django_smartbase_admin/static/sb_admin/css/ckeditor/ckeditor_content_dark.css +208 -0
  38. django_smartbase_admin/static/sb_admin/css/coloris/coloris.min.css +1 -0
  39. django_smartbase_admin/static/sb_admin/dist/calendar.js +1 -0
  40. django_smartbase_admin/static/sb_admin/dist/calendar_style.css +1 -0
  41. django_smartbase_admin/static/sb_admin/dist/calendar_style.js +0 -0
  42. django_smartbase_admin/static/sb_admin/dist/chart.js +1 -1
  43. django_smartbase_admin/static/sb_admin/dist/main.js +1 -1
  44. django_smartbase_admin/static/sb_admin/dist/main_style.css +1 -1
  45. django_smartbase_admin/static/sb_admin/dist/table.js +1 -1
  46. django_smartbase_admin/static/sb_admin/dist/table.js.LICENSE.txt +9 -0
  47. django_smartbase_admin/static/sb_admin/dist/tree_widget.js +1 -0
  48. django_smartbase_admin/static/sb_admin/dist/tree_widget_style.css +1 -0
  49. django_smartbase_admin/static/sb_admin/dist/tree_widget_style.js +0 -0
  50. django_smartbase_admin/static/sb_admin/fancytree/jquery.fancytree-all-deps.min.js +1 -0
  51. django_smartbase_admin/static/sb_admin/images/file_types/file-csv.svg +11 -0
  52. django_smartbase_admin/static/sb_admin/images/file_types/file-doc.svg +11 -0
  53. django_smartbase_admin/static/sb_admin/images/file_types/file-docx.svg +11 -0
  54. django_smartbase_admin/static/sb_admin/images/file_types/file-other.svg +13 -0
  55. django_smartbase_admin/static/sb_admin/images/file_types/file-pdf.svg +11 -0
  56. django_smartbase_admin/static/sb_admin/images/file_types/file-ppt.svg +11 -0
  57. django_smartbase_admin/static/sb_admin/images/file_types/file-xls.svg +11 -0
  58. django_smartbase_admin/static/sb_admin/images/file_types/file-xlsx.svg +11 -0
  59. django_smartbase_admin/static/sb_admin/images/file_types/file-zip.svg +18 -0
  60. django_smartbase_admin/static/sb_admin/images/flags/de-at.png +0 -0
  61. django_smartbase_admin/static/sb_admin/images/flags/de-ch.png +0 -0
  62. django_smartbase_admin/static/sb_admin/images/logo_light.svg +21 -0
  63. django_smartbase_admin/static/sb_admin/js/coloris/coloris.min.js +6 -0
  64. django_smartbase_admin/static/sb_admin/js/fullcalendar.min.js +14804 -0
  65. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Bolt-one.svg +3 -0
  66. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Calendar.svg +3 -0
  67. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Caution.svg +3 -0
  68. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Electric-drill.svg +3 -0
  69. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Fire-extinguisher.svg +3 -0
  70. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Gas.svg +3 -0
  71. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Lightning-fill.svg +3 -0
  72. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Moon.svg +3 -0
  73. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Phone-telephone.svg +3 -0
  74. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Printer.svg +3 -0
  75. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Pull.svg +3 -0
  76. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Sun-one.svg +3 -0
  77. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Time.svg +3 -0
  78. django_smartbase_admin/static/sb_admin/src/css/_base.css +5 -1
  79. django_smartbase_admin/static/sb_admin/src/css/_colors.css +257 -82
  80. django_smartbase_admin/static/sb_admin/src/css/_components.css +66 -13
  81. django_smartbase_admin/static/sb_admin/src/css/_datepicker.css +8 -1
  82. django_smartbase_admin/static/sb_admin/src/css/_filer.css +60 -0
  83. django_smartbase_admin/static/sb_admin/src/css/_inlines.css +51 -10
  84. django_smartbase_admin/static/sb_admin/src/css/_tabulator.css +8 -2
  85. django_smartbase_admin/static/sb_admin/src/css/calendar.css +162 -0
  86. django_smartbase_admin/static/sb_admin/src/css/components/_button.css +41 -1
  87. django_smartbase_admin/static/sb_admin/src/css/components/_dropdown.css +26 -8
  88. django_smartbase_admin/static/sb_admin/src/css/components/_input.css +62 -20
  89. django_smartbase_admin/static/sb_admin/src/css/components/_modal.css +1 -1
  90. django_smartbase_admin/static/sb_admin/src/css/components/_query-builder.css +21 -2
  91. django_smartbase_admin/static/sb_admin/src/css/components/_toggle.css +12 -1
  92. django_smartbase_admin/static/sb_admin/src/css/components/_tooltip.css +8 -22
  93. django_smartbase_admin/static/sb_admin/src/css/style.css +17 -0
  94. django_smartbase_admin/static/sb_admin/src/css/tree_widget.css +411 -0
  95. django_smartbase_admin/static/sb_admin/src/js/autocomplete.js +63 -5
  96. django_smartbase_admin/static/sb_admin/src/js/calendar.js +56 -0
  97. django_smartbase_admin/static/sb_admin/src/js/chart.js +8 -22
  98. django_smartbase_admin/static/sb_admin/src/js/choices.js +18 -8
  99. django_smartbase_admin/static/sb_admin/src/js/datepicker.js +97 -336
  100. django_smartbase_admin/static/sb_admin/src/js/datepicker_plugins.js +357 -0
  101. django_smartbase_admin/static/sb_admin/src/js/main.js +307 -26
  102. django_smartbase_admin/static/sb_admin/src/js/multiselect.js +50 -41
  103. django_smartbase_admin/static/sb_admin/src/js/range.js +3 -2
  104. django_smartbase_admin/static/sb_admin/src/js/sb_ajax_params_tabulator_modifier.js +21 -0
  105. django_smartbase_admin/static/sb_admin/src/js/table.js +38 -13
  106. django_smartbase_admin/static/sb_admin/src/js/table_modules/advanced_filter_module.js +43 -20
  107. django_smartbase_admin/static/sb_admin/src/js/table_modules/data_edit_module.js +8 -10
  108. django_smartbase_admin/static/sb_admin/src/js/table_modules/filter_module.js +3 -3
  109. django_smartbase_admin/static/sb_admin/src/js/table_modules/header_tabs_module.js +11 -11
  110. django_smartbase_admin/static/sb_admin/src/js/table_modules/selection_module.js +28 -8
  111. django_smartbase_admin/static/sb_admin/src/js/table_modules/table_params_module.js +6 -0
  112. django_smartbase_admin/static/sb_admin/src/js/table_modules/views_module.js +19 -3
  113. django_smartbase_admin/static/sb_admin/src/js/tree_widget.js +406 -0
  114. django_smartbase_admin/static/sb_admin/src/js/utils.js +56 -21
  115. django_smartbase_admin/templates/sb_admin/actions/change_form.html +169 -117
  116. django_smartbase_admin/templates/sb_admin/actions/dashboard.html +2 -2
  117. django_smartbase_admin/templates/sb_admin/actions/delete_selected_confirmation.html +56 -32
  118. django_smartbase_admin/templates/sb_admin/actions/list.html +79 -42
  119. django_smartbase_admin/templates/sb_admin/actions/object_history.html +2 -2
  120. django_smartbase_admin/templates/sb_admin/actions/partials/action_link.html +14 -0
  121. django_smartbase_admin/templates/sb_admin/actions/partials/selected_rows_actions.html +2 -2
  122. django_smartbase_admin/templates/sb_admin/actions/partials/tabulator_header_v2.html +2 -2
  123. django_smartbase_admin/templates/sb_admin/actions/tree_list.html +63 -0
  124. django_smartbase_admin/templates/sb_admin/authentification/login_base.html +5 -1
  125. django_smartbase_admin/templates/sb_admin/components/columns.html +1 -1
  126. django_smartbase_admin/templates/sb_admin/components/filters_v2.html +99 -85
  127. django_smartbase_admin/templates/sb_admin/config/view.html +0 -1
  128. django_smartbase_admin/templates/sb_admin/dashboard/calendar_widget.html +69 -0
  129. django_smartbase_admin/templates/sb_admin/dashboard/chart_widget.html +21 -2
  130. django_smartbase_admin/templates/sb_admin/dashboard/list_widget.html +6 -0
  131. django_smartbase_admin/templates/sb_admin/dashboard/widget_base.html +1 -1
  132. django_smartbase_admin/templates/sb_admin/filter_widgets/advanced_filters/date_field.html +18 -8
  133. django_smartbase_admin/templates/sb_admin/filter_widgets/advanced_filters/multiple_choice_field.html +1 -1
  134. django_smartbase_admin/templates/sb_admin/filter_widgets/advanced_filters/tree_select_filter.html +2 -0
  135. django_smartbase_admin/templates/sb_admin/filter_widgets/date_field.html +18 -4
  136. django_smartbase_admin/templates/sb_admin/filter_widgets/multiple_choice_field.html +14 -0
  137. django_smartbase_admin/templates/sb_admin/filter_widgets/partials/clear.html +10 -5
  138. django_smartbase_admin/templates/sb_admin/filter_widgets/radio_choice_field.html +2 -2
  139. django_smartbase_admin/templates/sb_admin/filter_widgets/tree_select_filter.html +16 -0
  140. django_smartbase_admin/templates/sb_admin/includes/change_form_title.html +3 -1
  141. django_smartbase_admin/templates/sb_admin/includes/components.html +5 -1
  142. django_smartbase_admin/templates/sb_admin/includes/inline_fieldset.html +48 -39
  143. django_smartbase_admin/templates/sb_admin/includes/notifications.html +2 -1
  144. django_smartbase_admin/templates/sb_admin/includes/readonly_boolean_field.html +9 -0
  145. django_smartbase_admin/templates/sb_admin/includes/readonly_field.html +12 -0
  146. django_smartbase_admin/templates/sb_admin/includes/table_inline_delete_button.html +4 -5
  147. django_smartbase_admin/templates/sb_admin/inlines/stacked_inline.html +68 -40
  148. django_smartbase_admin/templates/sb_admin/inlines/table_inline.html +78 -36
  149. django_smartbase_admin/templates/sb_admin/integrations/filer/folder_list.html +18 -0
  150. django_smartbase_admin/templates/sb_admin/navigation.html +166 -158
  151. django_smartbase_admin/templates/sb_admin/partials/modal/modal_content.html +2 -6
  152. django_smartbase_admin/templates/sb_admin/sb_admin_base.html +49 -4
  153. django_smartbase_admin/templates/sb_admin/sb_admin_base_no_sidebar.html +35 -11
  154. django_smartbase_admin/templates/sb_admin/sb_admin_js_trans.html +3 -0
  155. django_smartbase_admin/templates/sb_admin/sprites/sb_admin.svg +1 -1
  156. django_smartbase_admin/templates/sb_admin/tailwind_whitelist.html +6 -3
  157. django_smartbase_admin/templates/sb_admin/widgets/array.html +0 -1
  158. django_smartbase_admin/templates/sb_admin/widgets/attributes.html +68 -0
  159. django_smartbase_admin/templates/sb_admin/widgets/autocomplete.html +13 -2
  160. django_smartbase_admin/templates/sb_admin/widgets/{checkbox_select.html → checkbox_dropdown.html} +2 -2
  161. django_smartbase_admin/templates/sb_admin/widgets/checkbox_group.html +15 -0
  162. django_smartbase_admin/templates/sb_admin/widgets/clearable_file_input.html +2 -2
  163. django_smartbase_admin/templates/sb_admin/widgets/color_field.html +30 -0
  164. django_smartbase_admin/templates/sb_admin/widgets/date.html +8 -1
  165. django_smartbase_admin/templates/sb_admin/widgets/filer_file.html +84 -0
  166. django_smartbase_admin/templates/sb_admin/widgets/html_read_only.html +1 -0
  167. django_smartbase_admin/templates/sb_admin/widgets/includes/related_item_buttons.html +38 -0
  168. django_smartbase_admin/templates/sb_admin/widgets/multiwidget.html +1 -1
  169. django_smartbase_admin/templates/sb_admin/widgets/radio.html +3 -2
  170. django_smartbase_admin/templates/sb_admin/widgets/radio_dropdown.html +30 -0
  171. django_smartbase_admin/templates/sb_admin/widgets/read_only_password_hash.html +3 -0
  172. django_smartbase_admin/templates/sb_admin/widgets/time.html +8 -1
  173. django_smartbase_admin/templates/sb_admin/widgets/toggle.html +1 -1
  174. django_smartbase_admin/templates/sb_admin/widgets/tree_base.html +59 -0
  175. django_smartbase_admin/templates/sb_admin/widgets/tree_select.html +24 -0
  176. django_smartbase_admin/templates/sb_admin/widgets/tree_select_inline.html +12 -0
  177. django_smartbase_admin/templatetags/sb_admin_tags.py +163 -4
  178. django_smartbase_admin/utils.py +22 -3
  179. django_smartbase_admin/views/dashboard_view.py +6 -0
  180. django_smartbase_admin/views/global_filter_view.py +8 -2
  181. django_smartbase_admin/views/translations_view.py +12 -5
  182. django_smartbase_admin/views/user_config_view.py +52 -0
  183. django_smartbase_admin-1.0.38.dist-info/METADATA +166 -0
  184. {django_smartbase_admin-0.2.47.dist-info → django_smartbase_admin-1.0.38.dist-info}/RECORD +186 -121
  185. {django_smartbase_admin-0.2.47.dist-info → django_smartbase_admin-1.0.38.dist-info}/WHEEL +1 -1
  186. django_smartbase_admin/templates/sb_admin/integrations/sorting/change_list.html +0 -401
  187. django_smartbase_admin-0.2.47.dist-info/METADATA +0 -25
  188. {django_smartbase_admin-0.2.47.dist-info → django_smartbase_admin-1.0.38.dist-info}/LICENSE.md +0 -0
@@ -1,18 +1,25 @@
1
1
  import json
2
2
  import urllib.parse
3
3
  from collections import defaultdict
4
+ from collections.abc import Iterable
5
+ from typing import Any, TYPE_CHECKING
4
6
 
7
+ from django.conf import settings
8
+ from django.contrib import messages
5
9
  from django.contrib.admin.actions import delete_selected
6
10
  from django.core.exceptions import PermissionDenied
7
11
  from django.db.models import F
8
- from django.http import HttpResponse, Http404, JsonResponse
12
+ from django.http import HttpResponse, Http404, JsonResponse, HttpRequest
9
13
  from django.shortcuts import redirect
10
14
  from django.template.response import TemplateResponse
11
15
  from django.urls import reverse
12
16
  from django.utils.translation import gettext_lazy as _
13
17
 
14
18
  from django_smartbase_admin.actions.admin_action_list import SBAdminListAction
15
- from django_smartbase_admin.engine.actions import SBAdminCustomAction
19
+ from django_smartbase_admin.engine.actions import (
20
+ SBAdminCustomAction,
21
+ SBAdminFormViewAction,
22
+ )
16
23
  from django_smartbase_admin.engine.const import (
17
24
  Action,
18
25
  OBJECT_ID_PLACEHOLDER,
@@ -24,6 +31,15 @@ from django_smartbase_admin.engine.const import (
24
31
  GLOBAL_FILTER_ALIAS_WIDGET_ID,
25
32
  OVERRIDE_CONTENT_OF_NOTIFICATION,
26
33
  FilterVersions,
34
+ BASE_PARAMS_NAME,
35
+ TABLE_RELOAD_DATA_EVENT_NAME,
36
+ TABLE_UPDATE_ROW_DATA_EVENT_NAME,
37
+ SELECT_ALL_KEYWORD,
38
+ IGNORE_LIST_SELECTION,
39
+ SUPPORTED_FILE_TYPE_ICONS,
40
+ )
41
+ from django_smartbase_admin.services.configuration import (
42
+ SBAdminUserConfigurationService,
27
43
  )
28
44
  from django_smartbase_admin.services.views import SBAdminViewService
29
45
  from django_smartbase_admin.services.xlsx_export import (
@@ -31,14 +47,26 @@ from django_smartbase_admin.services.xlsx_export import (
31
47
  SBAdminXLSXOptions,
32
48
  SBAdminXLSXFormat,
33
49
  )
34
- from django_smartbase_admin.utils import is_htmx_request
50
+ from django_smartbase_admin.utils import is_htmx_request, render_notifications, is_modal
51
+
52
+ if TYPE_CHECKING:
53
+ from django_smartbase_admin.engine.field import SBAdminField
54
+
55
+ SBADMIN_IS_MODAL_VAR = "sbadmin_is_modal"
56
+ SBADMIN_PARENT_INSTANCE_FIELD_NAME_VAR = "sbadmin_parent_instance_field"
57
+ SBADMIN_PARENT_INSTANCE_PK_VAR = "sbadmin_parent_instance_pk"
58
+ SBADMIN_PARENT_INSTANCE_LABEL_VAR = "sbadmin_parent_instance_label"
59
+ SBADMIN_RELOAD_ON_SAVE_VAR = "sbadmin_reload_on_save"
35
60
 
36
61
 
37
62
  class SBAdminBaseView(object):
38
- menu_label = None
39
63
  global_filter_data_map = None
40
64
  field_cache = None
41
65
  sbadmin_detail_actions = None
66
+ menu_label: str | None = None
67
+ add_label: str | None = None
68
+ change_label: str | None = None
69
+ delete_confirmation_template = "sb_admin/actions/delete_confirmation.html"
42
70
 
43
71
  def init_view_static(self, configuration, model, admin_site):
44
72
  pass
@@ -46,39 +74,64 @@ class SBAdminBaseView(object):
46
74
  def get_id(self):
47
75
  raise NotImplementedError
48
76
 
49
- def get_menu_label(self):
77
+ def get_menu_label(self) -> str:
50
78
  return self.menu_label or self.model._meta.verbose_name_plural
51
79
 
52
- def has_permission(self, request, obj=None, permission=None):
80
+ def has_permission(self, request, obj=None, permission=None) -> bool:
53
81
  return SBAdminViewService.has_permission(
54
82
  request=request, view=self, model=self.model, obj=obj, permission=permission
55
83
  )
56
84
 
57
- def has_add_permission(self, request, obj=None):
85
+ def has_add_permission(self, request, obj=None) -> bool:
58
86
  return self.has_permission(request, obj, "add")
59
87
 
60
- def has_view_permission(self, request, obj=None):
88
+ def has_view_permission(self, request, obj=None) -> bool:
61
89
  return self.has_permission(request, obj, "view")
62
90
 
63
- def has_change_permission(self, request, obj=None):
91
+ def has_change_permission(self, request, obj=None) -> bool:
64
92
  return self.has_permission(request, obj, "change")
65
93
 
66
- def has_delete_permission(self, request, obj=None):
94
+ def has_delete_permission(self, request, obj=None) -> bool:
67
95
  return self.has_permission(request, obj, "delete")
68
96
 
69
- def has_permission_for_action(self, request, action):
97
+ def has_permission_for_action(self, request, action: SBAdminCustomAction) -> bool:
70
98
  return self.has_permission(
71
99
  request=request,
72
100
  obj=None,
73
101
  permission=action,
74
102
  )
75
103
 
76
- def has_view_or_change_permission(self, request, obj=None):
104
+ def has_view_or_change_permission(self, request, obj=None) -> bool:
77
105
  return self.has_view_permission(request, obj) or self.has_change_permission(
78
106
  request, obj
79
107
  )
80
108
 
81
- def process_actions_permissions(self, request, actions):
109
+ def delegate_to_action_view(self, processed_action):
110
+ def inner_view(request, modifier):
111
+ return processed_action.target_view.as_view(view=self)(request)
112
+
113
+ return inner_view
114
+
115
+ def process_actions(
116
+ self, request, actions: list[SBAdminCustomAction]
117
+ ) -> list[SBAdminCustomAction]:
118
+ processed_actions = self.process_actions_permissions(request, actions)
119
+ for processed_action in processed_actions:
120
+ if isinstance(processed_action, SBAdminFormViewAction):
121
+ action_id = processed_action.target_view.__name__
122
+ setattr(
123
+ self,
124
+ action_id,
125
+ self.delegate_to_action_view(processed_action),
126
+ )
127
+ processed_action.url = self.get_action_url(action_id)
128
+ processed_action.action_id = action_id
129
+
130
+ return processed_actions
131
+
132
+ def process_actions_permissions(
133
+ self, request, actions: list[SBAdminCustomAction]
134
+ ) -> list[SBAdminCustomAction]:
82
135
  result = []
83
136
  for action in actions:
84
137
  if self.has_permission_for_action(request, action):
@@ -92,8 +145,8 @@ class SBAdminBaseView(object):
92
145
  def get_field_map(self, request):
93
146
  return self.field_cache
94
147
 
95
- def init_fields_cache(self, fields_source, configuration):
96
- if self.field_cache:
148
+ def init_fields_cache(self, fields_source, configuration, force=False):
149
+ if not force and self.field_cache:
97
150
  return self.field_cache.values()
98
151
  from django_smartbase_admin.engine.field import SBAdminField
99
152
 
@@ -144,7 +197,7 @@ class SBAdminBaseView(object):
144
197
  field.model_field = model_field
145
198
  return field
146
199
 
147
- def get_username_data(self, request):
200
+ def get_username_data(self, request) -> dict[str, Any]:
148
201
  if request.request_data.user.first_name and request.request_data.user.last_name:
149
202
  return {
150
203
  "full_name": f"{request.request_data.user.first_name} {request.request_data.user.last_name}",
@@ -155,30 +208,82 @@ class SBAdminBaseView(object):
155
208
  "initials": request.request_data.user.username[0],
156
209
  }
157
210
 
158
- def get_sbadmin_detail_actions(self, object_id):
211
+ def get_sbadmin_detail_actions(
212
+ self, request, object_id: int | str | None = None
213
+ ) -> Iterable[SBAdminCustomAction] | None:
159
214
  return self.sbadmin_detail_actions
160
215
 
161
- def get_global_context(self, request, object_id=None):
216
+ def get_color_scheme_context(self, request):
217
+ from django_smartbase_admin.views.user_config_view import ColorSchemeForm
218
+
219
+ user_config = SBAdminUserConfigurationService.get_user_config(request)
220
+ color_scheme_form = ColorSchemeForm(instance=user_config)
221
+ return {
222
+ "user_config": user_config,
223
+ "color_scheme_form": color_scheme_form,
224
+ }
225
+
226
+ def get_add_label(
227
+ self, request: HttpRequest, object_id: str | None = None
228
+ ) -> str | None:
229
+ return self.add_label
230
+
231
+ def get_change_label(
232
+ self, request: HttpRequest, object_id: str | None = None
233
+ ) -> str | None:
234
+ return self.change_label
235
+
236
+ def get_global_context(
237
+ self, request, object_id: int | str | None = None
238
+ ) -> dict[str, Any]:
162
239
  return {
163
240
  "view_id": self.get_id(),
164
241
  "configuration": request.request_data.configuration,
165
242
  "request_data": request.request_data,
243
+ "add_label": self.get_add_label(request, object_id),
244
+ "change_label": self.get_change_label(request, object_id),
166
245
  "DETAIL_STRUCTURE_RIGHT_CLASS": DETAIL_STRUCTURE_RIGHT_CLASS,
167
246
  "OVERRIDE_CONTENT_OF_NOTIFICATION": OVERRIDE_CONTENT_OF_NOTIFICATION,
168
247
  "username_data": self.get_username_data(request),
169
- "detail_actions": self.get_sbadmin_detail_actions(object_id),
248
+ "detail_actions": self.get_sbadmin_detail_actions(request, object_id),
249
+ SBADMIN_IS_MODAL_VAR: is_modal(request),
250
+ SBADMIN_RELOAD_ON_SAVE_VAR: SBADMIN_RELOAD_ON_SAVE_VAR in request.GET
251
+ or SBADMIN_RELOAD_ON_SAVE_VAR in request.POST,
170
252
  "const": json.dumps(
171
253
  {
172
254
  "MULTISELECT_FILTER_MAX_CHOICES_SHOWN": MULTISELECT_FILTER_MAX_CHOICES_SHOWN,
173
255
  "AUTOCOMPLETE_PAGE_SIZE": AUTOCOMPLETE_PAGE_SIZE,
174
256
  "GLOBAL_FILTER_ALIAS_WIDGET_ID": GLOBAL_FILTER_ALIAS_WIDGET_ID,
257
+ "TABLE_RELOAD_DATA_EVENT_NAME": TABLE_RELOAD_DATA_EVENT_NAME,
258
+ "TABLE_UPDATE_ROW_DATA_EVENT_NAME": TABLE_UPDATE_ROW_DATA_EVENT_NAME,
259
+ "SELECT_ALL_KEYWORD": SELECT_ALL_KEYWORD,
260
+ "SUPPORTED_FILE_TYPE_ICONS": SUPPORTED_FILE_TYPE_ICONS,
261
+ "STATIC_BASE_PATH": f"{settings.STATIC_URL}sb_admin",
175
262
  }
176
263
  ),
264
+ **self.get_color_scheme_context(request),
177
265
  }
178
266
 
179
- def get_model_path(self):
267
+ def get_model_path(self) -> str:
180
268
  return SBAdminViewService.get_model_path(self.model)
181
269
 
270
+ def process_field_data(
271
+ self,
272
+ request,
273
+ field: "SBAdminField",
274
+ obj_id: Any,
275
+ value: Any,
276
+ additional_data: dict[str, Any],
277
+ ) -> Any:
278
+ is_xlsx_export = request.request_data.action == Action.XLSX_EXPORT.value
279
+ if field.view_method:
280
+ value = field.view_method(obj_id, value, **additional_data)
281
+ if is_xlsx_export and getattr(field.xlsx_options, "python_formatter", None):
282
+ value = field.xlsx_options.python_formatter(obj_id, value)
283
+ elif field.python_formatter:
284
+ value = field.python_formatter(obj_id, value)
285
+ return value
286
+
182
287
 
183
288
  class SBAdminBaseQuerysetMixin(object):
184
289
  def get_queryset(self, request=None):
@@ -205,11 +310,13 @@ class SBAdminBaseListView(SBAdminBaseView):
205
310
  sbadmin_list_reorder_field = None
206
311
  search_field_placeholder = _("Search...")
207
312
  filters_version = None
313
+ sbadmin_actions_initialized = False
314
+ sbadmin_list_action_class = SBAdminListAction
208
315
 
209
- def activate_reorder(self, request):
316
+ def activate_reorder(self, request) -> None:
210
317
  request.reorder_active = True
211
318
 
212
- def action_list_json_reorder(self, request, modifier):
319
+ def action_list_json_reorder(self, request, modifier) -> JsonResponse:
213
320
  self.activate_reorder(request)
214
321
  return self.action_list_json(request, modifier, page_size=100)
215
322
 
@@ -238,24 +345,25 @@ class SBAdminBaseListView(SBAdminBaseView):
238
345
  url=self.get_menu_view_url(request),
239
346
  ),
240
347
  ],
348
+ template=self.reorder_list_template,
241
349
  )
242
350
 
243
- def is_reorder_active(self, request):
351
+ def is_reorder_active(self, request) -> bool:
244
352
  return (
245
- self.is_reorder_available()
353
+ self.is_reorder_available(request)
246
354
  and getattr(request, "reorder_active", False) == True
247
355
  )
248
356
 
249
- def is_reorder_available(self):
357
+ def is_reorder_available(self, request) -> str | None:
250
358
  return self.sbadmin_list_reorder_field
251
359
 
252
- def action_table_reorder(self, request, modifier):
360
+ def action_table_reorder(self, request, modifier) -> JsonResponse:
253
361
  self.activate_reorder(request)
254
362
  qs = self.get_queryset(request)
255
363
  pk_field = SBAdminViewService.get_pk_field_for_model(self.model).name
256
364
  old_order = dict(
257
365
  qs.values_list(pk_field, self.sbadmin_list_reorder_field).order_by(
258
- *self.get_list_ordering()
366
+ *self.get_list_ordering(request)
259
367
  )
260
368
  )
261
369
  current_row_id = json.loads(request.POST.get("currentRowId", ""))
@@ -283,31 +391,50 @@ class SBAdminBaseListView(SBAdminBaseView):
283
391
  )
284
392
  return JsonResponse({"message": request.POST})
285
393
 
286
- def action_table_data_edit(self, request, modifier):
394
+ def action_table_data_edit(self, request, modifier) -> HttpResponse:
287
395
  current_row_id = json.loads(request.POST.get("currentRowId", ""))
288
396
  column_field_name = request.POST.get("columnFieldName", "")
289
397
  cell_value = request.POST.get("cellValue", "")
290
- return JsonResponse({"message": "Not Implemented"})
398
+ messages.add_message(request, messages.ERROR, "Not Implemented")
399
+ return HttpResponse(status=200, content=render_notifications(request))
291
400
 
292
- def init_view_dynamic(self, request, request_data=None, **kwargs):
401
+ def init_actions(self, request) -> None:
402
+ if self.sbadmin_actions_initialized:
403
+ return
404
+ self.process_actions(request, self.get_sbadmin_list_selection_actions(request))
405
+ self.process_actions(request, self.get_sbadmin_list_actions(request))
406
+ self.sbadmin_actions_initialized = True
407
+
408
+ def init_view_dynamic(self, request, request_data=None, **kwargs) -> None:
293
409
  super().init_view_dynamic(request, request_data, **kwargs)
294
410
  self.init_fields_cache(
295
- self.get_sbamin_list_display(request), request.request_data.configuration
411
+ self.get_sbadmin_list_display(request), request.request_data.configuration
296
412
  )
413
+ self.init_actions(request)
297
414
 
298
- def get_sbamin_list_display(self, request):
299
- return self.sbadmin_list_display or self.list_display
415
+ def get_sbadmin_list_display(self, request) -> list[str] | list:
416
+ return self.sbadmin_list_display or self.list_display or []
300
417
 
301
- def register_autocomplete_views(self, request):
418
+ def register_autocomplete_views(self, request) -> None:
302
419
  super().register_autocomplete_views(request)
303
420
  self.init_fields_cache(
304
- self.get_sbamin_list_display(request), request.request_data.configuration
421
+ self.get_sbadmin_list_display(request),
422
+ request.request_data.configuration,
423
+ force=True,
305
424
  )
306
-
307
- def get_list_display(self, request):
425
+ all_list_actions = self.get_sbadmin_list_selection_actions(
426
+ request
427
+ ) + self.get_sbadmin_list_actions(request)
428
+ for list_action in all_list_actions:
429
+ if isinstance(list_action, SBAdminFormViewAction):
430
+ form = list_action.target_view.form_class
431
+ form.view = self
432
+ form()
433
+
434
+ def get_list_display(self, request) -> list[str] | list:
308
435
  return [
309
436
  getattr(field, "name", field)
310
- for field in self.get_sbamin_list_display(request)
437
+ for field in self.get_sbadmin_list_display(request)
311
438
  ]
312
439
 
313
440
  def get_search_fields(self, request):
@@ -316,12 +443,12 @@ class SBAdminBaseListView(SBAdminBaseView):
316
443
  else:
317
444
  return []
318
445
 
319
- def get_list_ordering(self):
446
+ def get_list_ordering(self, request) -> Iterable[str] | list:
320
447
  return self.ordering or []
321
448
 
322
- def get_list_initial_order(self):
449
+ def get_list_initial_order(self, request) -> list[dict[str, Any]]:
323
450
  order = []
324
- for order_field in self.get_list_ordering():
451
+ for order_field in self.get_list_ordering(request):
325
452
  direction = "desc" if order_field.startswith("-") else "asc"
326
453
  order.append(
327
454
  {
@@ -331,15 +458,15 @@ class SBAdminBaseListView(SBAdminBaseView):
331
458
  )
332
459
  return order
333
460
 
334
- def get_list_per_page(self):
461
+ def get_list_per_page(self, request) -> int | None:
335
462
  return self.list_per_page
336
463
 
337
- def has_add_permission(self, request):
464
+ def has_add_permission(self, request, obj=None) -> bool:
338
465
  if self.is_reorder_active(request):
339
466
  return False
340
467
  return super().has_add_permission(request)
341
468
 
342
- def get_tabulator_definition(self, request):
469
+ def get_tabulator_definition(self, request) -> dict[str, Any]:
343
470
  view_id = self.get_id()
344
471
  tabulator_definition = {
345
472
  "viewId": view_id,
@@ -356,8 +483,8 @@ class SBAdminBaseListView(SBAdminBaseView):
356
483
  Action.TABLE_REORDER_ACTION.value
357
484
  ),
358
485
  "tableDetailUrl": self.get_detail_url(),
359
- "tableInitialSort": self.get_list_initial_order(),
360
- "tableInitialPageSize": self.get_list_per_page(),
486
+ "tableInitialSort": self.get_list_initial_order(request),
487
+ "tableInitialPageSize": self.get_list_per_page(request),
361
488
  "tableHistoryEnabled": self.sbadmin_table_history_enabled,
362
489
  # used to initialize all columns with these values
363
490
  "defaultColumnData": {},
@@ -373,6 +500,7 @@ class SBAdminBaseListView(SBAdminBaseView):
373
500
  "tabulatorOptions": {
374
501
  "renderVertical": "basic",
375
502
  "persistence": False,
503
+ "layoutColumnsOnNewData": True,
376
504
  "height": "100%",
377
505
  "ajaxContentType": "json",
378
506
  "ajaxConfig": {
@@ -398,9 +526,9 @@ class SBAdminBaseListView(SBAdminBaseView):
398
526
  )
399
527
  return tabulator_definition
400
528
 
401
- def _get_sbadmin_list_actions(self):
402
- list_actions = [*(self.get_sbadmin_list_actions() or [])]
403
- if self.is_reorder_available():
529
+ def _get_sbadmin_list_actions(self, request) -> list[SBAdminCustomAction] | list:
530
+ list_actions = [*(self.get_sbadmin_list_actions(request) or [])]
531
+ if self.is_reorder_available(request):
404
532
  list_actions = [
405
533
  *list_actions,
406
534
  SBAdminCustomAction(
@@ -412,18 +540,19 @@ class SBAdminBaseListView(SBAdminBaseView):
412
540
  ]
413
541
  return list_actions
414
542
 
415
- def get_sbadmin_list_actions(self):
543
+ def get_sbadmin_list_actions(self, request) -> list[SBAdminCustomAction]:
416
544
  if not self.sbadmin_list_actions:
417
545
  self.sbadmin_list_actions = [
418
546
  SBAdminCustomAction(
419
547
  title=_("Download XLSX"),
420
548
  view=self,
421
549
  action_id=Action.XLSX_EXPORT.value,
550
+ action_modifier=IGNORE_LIST_SELECTION,
422
551
  )
423
552
  ]
424
553
  return self.sbadmin_list_actions
425
554
 
426
- def get_sbadmin_list_selection_actions(self):
555
+ def get_sbadmin_list_selection_actions(self, request) -> list[SBAdminCustomAction]:
427
556
  if not self.sbadmin_list_selection_actions:
428
557
  self.sbadmin_list_selection_actions = [
429
558
  SBAdminCustomAction(
@@ -440,10 +569,12 @@ class SBAdminBaseListView(SBAdminBaseView):
440
569
  ]
441
570
  return self.sbadmin_list_selection_actions
442
571
 
443
- def get_sbadmin_list_selection_actions_grouped(self, request):
572
+ def get_sbadmin_list_selection_actions_grouped(
573
+ self, request
574
+ ) -> dict[str, list[SBAdminCustomAction]]:
444
575
  result = {}
445
- list_selection_actions = self.process_actions_permissions(
446
- request, self.get_sbadmin_list_selection_actions()
576
+ list_selection_actions = self.process_actions(
577
+ request, self.get_sbadmin_list_selection_actions(request)
447
578
  )
448
579
  for action in list_selection_actions:
449
580
  if not result.get(action.group):
@@ -451,7 +582,7 @@ class SBAdminBaseListView(SBAdminBaseView):
451
582
  result[action.group].append(action)
452
583
  return result
453
584
 
454
- def get_sbadmin_xlsx_options(self):
585
+ def get_sbadmin_xlsx_options(self, request) -> SBAdminXLSXOptions:
455
586
  self.sbadmin_xlsx_options = self.sbadmin_xlsx_options or SBAdminXLSXOptions(
456
587
  header_cell_format=SBAdminXLSXFormat(
457
588
  bg_color="#00aaa7", font_color="#ffffff", bold=True
@@ -463,13 +594,28 @@ class SBAdminBaseListView(SBAdminBaseView):
463
594
  )
464
595
  return self.sbadmin_xlsx_options
465
596
 
466
- def action_xlsx_export(self, request, modifier):
467
- action = SBAdminListAction(self, request)
468
- data = action.get_xlsx_data()
597
+ def action_xlsx_export(self, request, modifier) -> HttpResponse:
598
+ action = self.sbadmin_list_action_class(self, request)
599
+ data = action.get_xlsx_data(request)
469
600
  return SBAdminXLSXExportService.create_workbook_http_respone(*data)
470
601
 
471
602
  def action_bulk_delete(self, request, modifier):
472
- action = SBAdminListAction(self, request)
603
+ action = self.sbadmin_list_action_class(self, request)
604
+ if (
605
+ request.request_data.request_method == "POST"
606
+ and request.headers.get("X-TabulatorRequest", None) == "true"
607
+ ):
608
+ return redirect(
609
+ self.get_action_url("action_bulk_delete")
610
+ + "?"
611
+ + urllib.parse.urlencode(
612
+ {BASE_PARAMS_NAME: json.dumps(action.all_params)}
613
+ )
614
+ )
615
+ if not action.selection_data:
616
+ # don't run with no selection data as it will result in delete of all records
617
+ messages.error(request, _("No selection made."))
618
+ return redirect(self.get_menu_view_url(request))
473
619
  additional_filter = action.get_selection_queryset()
474
620
  response = delete_selected(
475
621
  self, request, self.get_queryset(request).filter(additional_filter)
@@ -478,36 +624,29 @@ class SBAdminBaseListView(SBAdminBaseView):
478
624
  return redirect(self.get_menu_view_url(request))
479
625
  return response
480
626
 
481
- def action_config(self, request, config_name=None):
482
- from django_smartbase_admin.models import SBAdminListViewConfiguration
483
-
484
- config_name = config_name if config_name != "None" else None
627
+ def action_config(self, request, config_id=None):
628
+ config_id = config_id if config_id != "None" else None
485
629
 
486
- name = config_name or request.POST.get(CONFIG_NAME, None)
487
- if name:
488
- name = urllib.parse.unquote(name)
630
+ config_name = request.POST.get(CONFIG_NAME, None)
631
+ if config_name:
632
+ config_name = urllib.parse.unquote(config_name)
489
633
  updated_configuration = None
490
634
  if request.request_data.request_method == "POST":
491
- if name:
492
- updated_configuration, created = (
493
- SBAdminListViewConfiguration.objects.update_or_create(
494
- name=name,
495
- user_id=request.request_data.user.id,
496
- defaults={
497
- "url_params": request.request_data.request_post.get(
498
- URL_PARAMS_NAME
499
- ),
500
- "view": self.get_id(),
501
- "action": None,
502
- "modifier": None,
503
- },
504
- )
635
+ updated_configuration = (
636
+ SBAdminUserConfigurationService.create_or_update_saved_view(
637
+ request,
638
+ view_id=self.get_id(),
639
+ config_id=config_id,
640
+ config_name=config_name,
641
+ url_params=request.request_data.request_post.get(URL_PARAMS_NAME),
505
642
  )
643
+ )
506
644
  if request.request_data.request_method == "DELETE":
507
- if name:
508
- SBAdminListViewConfiguration.objects.by_user_id(
509
- request.request_data.user.id
510
- ).by_name(name).by_view_action_modifier(view=self.get_id()).delete()
645
+ SBAdminUserConfigurationService.delete_saved_view(
646
+ request,
647
+ view_id=self.get_id(),
648
+ config_id=config_id,
649
+ )
511
650
 
512
651
  redirect_to = self.get_redirect_url_from_request(request, updated_configuration)
513
652
 
@@ -535,8 +674,9 @@ class SBAdminBaseListView(SBAdminBaseView):
535
674
  tabulator_definition=None,
536
675
  extra_context=None,
537
676
  list_actions=None,
677
+ template=None,
538
678
  ):
539
- action = SBAdminListAction(
679
+ action = self.sbadmin_list_action_class(
540
680
  self,
541
681
  request,
542
682
  page_size=page_size,
@@ -557,7 +697,8 @@ class SBAdminBaseListView(SBAdminBaseView):
557
697
 
558
698
  return TemplateResponse(
559
699
  request,
560
- self.change_list_template
700
+ template
701
+ or self.change_list_template
561
702
  or [
562
703
  "admin/%s/%s/change_list.html"
563
704
  % (self.model._meta.app_label, self.model._meta.model_name),
@@ -567,20 +708,20 @@ class SBAdminBaseListView(SBAdminBaseView):
567
708
  extra_context,
568
709
  )
569
710
 
570
- def action_list_json(self, request, modifier, page_size=None):
571
- action = SBAdminListAction(self, request, page_size=page_size)
711
+ def action_list_json(self, request, modifier, page_size=None) -> JsonResponse:
712
+ action = self.sbadmin_list_action_class(self, request, page_size=page_size)
572
713
  data = action.get_json_data()
573
714
  return JsonResponse(data=data, safe=False)
574
715
 
575
- def get_sbadmin_list_filter(self, request):
716
+ def get_sbadmin_list_filter(self, request) -> Iterable | None:
576
717
  return self.sbadmin_list_filter
577
718
 
578
- def get_all_config(self, request):
719
+ def get_all_config(self, request) -> dict[str, Any]:
579
720
  all_config = {"name": _("All"), "url_params": {}, "default": True}
580
721
  list_filter = self.get_sbadmin_list_filter(request) or []
581
722
  if not list_filter:
582
723
  return all_config
583
- list_fields = self.get_sbamin_list_display(request) or []
724
+ list_fields = self.get_sbadmin_list_display(request) or []
584
725
  self.init_fields_cache(list_fields, request.request_data.configuration)
585
726
  base_filter = {
586
727
  getattr(field, "filter_field", field): ""
@@ -599,45 +740,42 @@ class SBAdminBaseListView(SBAdminBaseView):
599
740
  }
600
741
  return all_config
601
742
 
602
- def get_sbadmin_list_view_config(self, request):
743
+ def get_sbadmin_list_view_config(self, request) -> list:
603
744
  return self.sbadmin_list_view_config or []
604
745
 
605
- def get_base_config(self, request):
746
+ def get_base_config(self, request) -> list[dict[str, Any]]:
606
747
  sbadmin_list_config = self.get_sbadmin_list_view_config(request)
607
748
  list_view_config = [self.get_all_config(request), *sbadmin_list_config]
608
749
  views = []
609
750
  for defined_view in list_view_config:
751
+ url_params = SBAdminViewService.process_url_params(
752
+ view_id=self.get_id(),
753
+ url_params=defined_view["url_params"],
754
+ filter_version=self.get_filters_version(request),
755
+ )
610
756
  views.append(
611
757
  {
612
758
  "name": defined_view["name"],
613
- "url_params": SBAdminViewService.json_dumps_for_url(
614
- defined_view["url_params"]
615
- ),
759
+ "url_params": SBAdminViewService.json_dumps_for_url(url_params),
616
760
  "default": True,
617
761
  }
618
762
  )
619
763
  return views
620
764
 
621
- def get_config_data(self, request):
622
- from django_smartbase_admin.models import SBAdminListViewConfiguration
623
-
624
- current_views = list(
625
- SBAdminListViewConfiguration.objects.by_user_id(
626
- request.request_data.user.id
627
- )
628
- .by_view_action_modifier(view=self.get_id())
629
- .values()
765
+ def get_config_data(self, request) -> dict[str, list[dict[str, Any]]]:
766
+ current_views = SBAdminUserConfigurationService.get_saved_views(
767
+ request, view_id=self.get_id()
630
768
  )
631
769
  for view in current_views:
632
- view["detail_url"] = self.get_config_url(view["name"])
770
+ view["detail_url"] = self.get_config_url(request, view["id"])
633
771
  config_views = self.get_base_config(request)
634
772
  config_views.extend(current_views)
635
773
  return {"current_views": config_views}
636
774
 
637
- def get_ajax_url(self):
775
+ def get_ajax_url(self) -> str:
638
776
  return self.get_action_url(Action.LIST_JSON.value)
639
777
 
640
- def get_detail_url(self):
778
+ def get_detail_url(self) -> str:
641
779
  url = reverse(
642
780
  "sb_admin:sb_admin_base",
643
781
  kwargs={
@@ -648,21 +786,21 @@ class SBAdminBaseListView(SBAdminBaseView):
648
786
  )
649
787
  return f"{url}/{OBJECT_ID_PLACEHOLDER}"
650
788
 
651
- def get_config_url(self, config_name=None):
789
+ def get_config_url(self, request, config_name=None) -> str:
652
790
  return self.get_action_url(Action.CONFIG.value, config_name)
653
791
 
654
- def get_new_url(self):
792
+ def get_new_url(self, request) -> None:
655
793
  return None
656
794
 
657
- def get_context_data(self, request):
795
+ def get_context_data(self, request) -> dict:
658
796
  return {}
659
797
 
660
- def get_filters_version(self, request):
798
+ def get_filters_version(self, request) -> FilterVersions:
661
799
  return (
662
800
  self.filters_version or request.request_data.configuration.filters_version
663
801
  )
664
802
 
665
- def get_filters_template_name(self, request):
803
+ def get_filters_template_name(self, request) -> str:
666
804
  filters_version = self.get_filters_version(request)
667
805
  if filters_version is FilterVersions.FILTERS_VERSION_2:
668
806
  return "sb_admin/components/filters_v2.html"
@@ -670,7 +808,7 @@ class SBAdminBaseListView(SBAdminBaseView):
670
808
  # default
671
809
  return "sb_admin/components/filters.html"
672
810
 
673
- def get_tabulator_header_template_name(self, request):
811
+ def get_tabulator_header_template_name(self, request) -> str:
674
812
  filters_version = self.get_filters_version(request)
675
813
  if filters_version is FilterVersions.FILTERS_VERSION_2:
676
814
  return "sb_admin/actions/partials/tabulator_header_v2.html"
@@ -678,5 +816,5 @@ class SBAdminBaseListView(SBAdminBaseView):
678
816
  # default
679
817
  return "sb_admin/actions/partials/tabulator_header_v1.html"
680
818
 
681
- def get_search_field_placeholder(self):
819
+ def get_search_field_placeholder(self, request) -> str:
682
820
  return self.search_field_placeholder