django-smartbase-admin 1.0.13__py3-none-any.whl → 1.0.15__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 (53) hide show
  1. django_smartbase_admin/admin/admin_base.py +21 -2
  2. django_smartbase_admin/admin/site.py +7 -1
  3. django_smartbase_admin/admin/widgets.py +19 -7
  4. django_smartbase_admin/engine/admin_base_view.py +14 -0
  5. django_smartbase_admin/engine/configuration.py +25 -25
  6. django_smartbase_admin/engine/menu_item.py +8 -5
  7. django_smartbase_admin/locale/sk/LC_MESSAGES/django.mo +0 -0
  8. django_smartbase_admin/locale/sk/LC_MESSAGES/django.po +22 -13
  9. django_smartbase_admin/migrations/0005_sbadminuserconfiguration.py +26 -0
  10. django_smartbase_admin/models.py +33 -0
  11. django_smartbase_admin/services/configuration.py +13 -0
  12. django_smartbase_admin/static/sb_admin/build/tailwind_config_partials/colors.js +4 -0
  13. django_smartbase_admin/static/sb_admin/css/ckeditor/ckeditor_content_dark.css +208 -0
  14. django_smartbase_admin/static/sb_admin/dist/calendar.js +1 -1
  15. django_smartbase_admin/static/sb_admin/dist/calendar_style.css +1 -1
  16. django_smartbase_admin/static/sb_admin/dist/chart.js +1 -1
  17. django_smartbase_admin/static/sb_admin/dist/main.js +1 -1
  18. django_smartbase_admin/static/sb_admin/dist/main_style.css +1 -1
  19. django_smartbase_admin/static/sb_admin/dist/table.js +1 -1
  20. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Moon.svg +3 -0
  21. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Sun-one.svg +3 -0
  22. django_smartbase_admin/static/sb_admin/src/css/_base.css +1 -1
  23. django_smartbase_admin/static/sb_admin/src/css/_colors.css +257 -82
  24. django_smartbase_admin/static/sb_admin/src/css/_components.css +1 -1
  25. django_smartbase_admin/static/sb_admin/src/css/_tabulator.css +2 -2
  26. django_smartbase_admin/static/sb_admin/src/css/calendar.css +3 -3
  27. django_smartbase_admin/static/sb_admin/src/css/components/_button.css +1 -1
  28. django_smartbase_admin/static/sb_admin/src/css/components/_dropdown.css +25 -7
  29. django_smartbase_admin/static/sb_admin/src/css/components/_input.css +33 -2
  30. django_smartbase_admin/static/sb_admin/src/css/components/_modal.css +1 -1
  31. django_smartbase_admin/static/sb_admin/src/css/components/_query-builder.css +1 -7
  32. django_smartbase_admin/static/sb_admin/src/css/style.css +1 -1
  33. django_smartbase_admin/static/sb_admin/src/js/main.js +58 -15
  34. django_smartbase_admin/static/sb_admin/src/js/multiselect.js +14 -21
  35. django_smartbase_admin/static/sb_admin/src/js/utils.js +47 -23
  36. django_smartbase_admin/templates/sb_admin/actions/change_form.html +25 -23
  37. django_smartbase_admin/templates/sb_admin/filter_widgets/advanced_filters/multiple_choice_field.html +1 -1
  38. django_smartbase_admin/templates/sb_admin/filter_widgets/radio_choice_field.html +1 -1
  39. django_smartbase_admin/templates/sb_admin/includes/inline_fieldset.html +11 -11
  40. django_smartbase_admin/templates/sb_admin/navigation.html +9 -7
  41. django_smartbase_admin/templates/sb_admin/sb_admin_base_no_sidebar.html +1 -1
  42. django_smartbase_admin/templates/sb_admin/sprites/sb_admin.svg +1 -1
  43. django_smartbase_admin/templates/sb_admin/tailwind_whitelist.html +2 -1
  44. django_smartbase_admin/templates/sb_admin/widgets/{checkbox_select.html → checkbox_dropdown.html} +2 -2
  45. django_smartbase_admin/templates/sb_admin/widgets/radio.html +3 -2
  46. django_smartbase_admin/templates/sb_admin/widgets/radio_dropdown.html +30 -0
  47. django_smartbase_admin/utils.py +4 -1
  48. django_smartbase_admin/views/translations_view.py +9 -3
  49. django_smartbase_admin/views/user_config_view.py +35 -0
  50. {django_smartbase_admin-1.0.13.dist-info → django_smartbase_admin-1.0.15.dist-info}/METADATA +1 -1
  51. {django_smartbase_admin-1.0.13.dist-info → django_smartbase_admin-1.0.15.dist-info}/RECORD +53 -47
  52. {django_smartbase_admin-1.0.13.dist-info → django_smartbase_admin-1.0.15.dist-info}/LICENSE.md +0 -0
  53. {django_smartbase_admin-1.0.13.dist-info → django_smartbase_admin-1.0.15.dist-info}/WHEEL +0 -0
@@ -36,7 +36,6 @@ from django.utils.text import capfirst
36
36
  from django.utils.translation import gettext_lazy as _
37
37
  from django_admin_inline_paginator.admin import TabularInlinePaginated
38
38
  from django_htmx.http import trigger_client_event
39
- from django_smartbase_admin.engine.field import SBAdminField
40
39
  from filer.fields.file import FilerFileField
41
40
  from filer.fields.image import AdminImageFormField, FilerImageField
42
41
  from nested_admin.formsets import NestedInlineFormSet
@@ -54,6 +53,8 @@ from django_smartbase_admin.utils import FormFieldsetMixin, is_modal
54
53
 
55
54
  parler_enabled = None
56
55
  try:
56
+ from parler.admin import TranslatableAdmin
57
+
57
58
  from parler.forms import (
58
59
  TranslatableModelForm,
59
60
  TranslatableModelFormMetaclass,
@@ -130,7 +131,6 @@ from django_smartbase_admin.engine.const import (
130
131
  OBJECT_ID_PLACEHOLDER,
131
132
  TRANSLATIONS_SELECTED_LANGUAGES,
132
133
  ROW_CLASS_FIELD,
133
- Action,
134
134
  )
135
135
  from django_smartbase_admin.services.translations import SBAdminTranslationsService
136
136
  from django_smartbase_admin.services.views import SBAdminViewService
@@ -821,6 +821,9 @@ class SBAdmin(
821
821
  def get_additional_filter_for_previous_next_context(self, request, object_id) -> Q:
822
822
  return Q()
823
823
 
824
+ def get_change_view_context(self, request, object_id) -> dict | dict[str, Any]:
825
+ return {"show_back_button": True}
826
+
824
827
  def get_previous_next_context(self, request, object_id) -> dict | dict[str, Any]:
825
828
  if not self.sbadmin_previous_next_buttons_enabled or not object_id:
826
829
  return {}
@@ -871,6 +874,7 @@ class SBAdmin(
871
874
 
872
875
  def change_view(self, request, object_id, form_url="", extra_context=None):
873
876
  extra_context = extra_context or {}
877
+ extra_context.update(self.get_change_view_context(request, object_id))
874
878
  extra_context.update(self.get_global_context(request, object_id))
875
879
  extra_context.update(self.get_fieldsets_context(request, object_id))
876
880
  extra_context.update(self.get_tabs_context(request, object_id))
@@ -1151,3 +1155,18 @@ class SBAdminStackedInline(SBAdminInline, NestedStackedInline):
1151
1155
  class SBAdminGenericStackedInline(SBAdminInline, NestedGenericStackedInline):
1152
1156
  template = "sb_admin/inlines/stacked_inline.html"
1153
1157
  fieldset_template = "sb_admin/includes/inline_fieldset.html"
1158
+
1159
+
1160
+ if parler_enabled:
1161
+
1162
+ class SBTranslatableAdmin(SBAdmin, TranslatableAdmin):
1163
+ def get_readonly_fields(self, request, obj=...):
1164
+ readonly_fields = super().get_readonly_fields(request, obj)
1165
+ if "sbadmin_translation_status" not in readonly_fields:
1166
+ readonly_fields += ("sbadmin_translation_status",)
1167
+ return readonly_fields
1168
+
1169
+ def get_fieldsets(self, request, obj=...):
1170
+ fieldsets = super().get_fieldsets(request, obj)
1171
+ fieldsets.append(SBAdminTranslationsService.get_translation_fieldset())
1172
+ return fieldsets
@@ -33,8 +33,8 @@ class SBAdminSite(admin.AdminSite):
33
33
  pass
34
34
  request.sbadmin_selected_view = selected_view
35
35
  kwargs["view"] = selected_view.get_id() if selected_view else None
36
- request_data = SBAdminViewRequestData.from_request_and_kwargs(request, **kwargs)
37
36
  SBAdminThreadLocalService.set_request(request)
37
+ request_data = SBAdminViewRequestData.from_request_and_kwargs(request, **kwargs)
38
38
  if selected_view:
39
39
  # Initialize SBAdmin, ModelAdmin instances, class-based SBAdminEntrypointView are initialized with request_data
40
40
  selected_view.init_view_dynamic(
@@ -77,6 +77,7 @@ class SBAdminSite(admin.AdminSite):
77
77
  PasswordChangeView,
78
78
  PasswordChangeDoneView,
79
79
  )
80
+ from django_smartbase_admin.views.user_config_view import ColorSchemeView
80
81
 
81
82
  urls = [
82
83
  path(
@@ -152,6 +153,11 @@ class SBAdminSite(admin.AdminSite):
152
153
  self.admin_view(GlobalFilterView.as_view()),
153
154
  name="global_filter",
154
155
  ),
156
+ path(
157
+ "color-scheme",
158
+ self.admin_view(ColorSchemeView.as_view()),
159
+ name="color_scheme",
160
+ ),
155
161
  path(
156
162
  "<str:view>/<str:action>/<str:modifier>",
157
163
  self.admin_view(SBAdminEntrypointView.as_view()),
@@ -190,8 +190,20 @@ class SBAdminRadioWidget(SBAdminBaseWidget, forms.RadioSelect):
190
190
  )
191
191
 
192
192
 
193
+ class SBAdminRadioDropdownWidget(SBAdminBaseWidget, forms.RadioSelect):
194
+ template_name = "sb_admin/widgets/radio_dropdown.html"
195
+ option_template_name = "sb_admin/widgets/radio_option.html"
196
+
197
+ def __init__(self, form_field=None, attrs=None, choices=()):
198
+ super().__init__(
199
+ form_field,
200
+ attrs={"class": "radio radio-list", **(attrs or {})},
201
+ choices=choices,
202
+ )
203
+
204
+
193
205
  class SBAdminMultipleChoiceWidget(SBAdminBaseWidget, forms.CheckboxSelectMultiple):
194
- template_name = "sb_admin/widgets/checkbox_select.html"
206
+ template_name = "sb_admin/widgets/checkbox_dropdown.html"
195
207
  option_template_name = "sb_admin/widgets/checkbox_option.html"
196
208
 
197
209
  def __init__(self, form_field=None, attrs=None, choices=()):
@@ -421,25 +433,25 @@ class SBAdminAutocompleteWidget(
421
433
  )
422
434
  and not self.is_multiselect()
423
435
  ):
424
- self.add_related_buttons_urls(parsed_value, context)
436
+ self.add_related_buttons_urls(parsed_value, threadsafe_request, context)
425
437
 
426
438
  return context
427
439
 
428
- def add_related_buttons_urls(self, parsed_value, context):
440
+ def add_related_buttons_urls(self, parsed_value, request, context):
429
441
  related_model = self.model
430
442
  app_label = related_model._meta.app_label
431
443
  model_name = related_model._meta.model_name
432
444
 
433
445
  try:
434
- if parsed_value:
446
+ if parsed_value and self.has_view_or_change_permission(request, self.model):
435
447
  change_url = reverse(
436
448
  "sb_admin:{}_{}_change".format(app_label, model_name),
437
449
  args=(parsed_value,),
438
450
  )
439
451
  context["widget"]["attrs"]["related_edit_url"] = change_url
440
-
441
- add_url = reverse("sb_admin:{}_{}_add".format(app_label, model_name))
442
- context["widget"]["attrs"]["related_add_url"] = add_url
452
+ if self.has_add_permission(request, self.model):
453
+ add_url = reverse("sb_admin:{}_{}_add".format(app_label, model_name))
454
+ context["widget"]["attrs"]["related_add_url"] = add_url
443
455
  except NoReverseMatch:
444
456
  pass
445
457
 
@@ -38,6 +38,9 @@ from django_smartbase_admin.engine.const import (
38
38
  IGNORE_LIST_SELECTION,
39
39
  SUPPORTED_FILE_TYPE_ICONS,
40
40
  )
41
+ from django_smartbase_admin.services.configuration import (
42
+ SBAdminUserConfigurationService,
43
+ )
41
44
  from django_smartbase_admin.services.views import SBAdminViewService
42
45
  from django_smartbase_admin.services.xlsx_export import (
43
46
  SBAdminXLSXExportService,
@@ -208,6 +211,16 @@ class SBAdminBaseView(object):
208
211
  ) -> Iterable[SBAdminCustomAction] | None:
209
212
  return self.sbadmin_detail_actions
210
213
 
214
+ def get_color_scheme_context(self, request):
215
+ from django_smartbase_admin.views.user_config_view import ColorSchemeForm
216
+
217
+ user_config = SBAdminUserConfigurationService.get_user_config(request)
218
+ color_scheme_form = ColorSchemeForm(instance=user_config)
219
+ return {
220
+ "user_config": user_config,
221
+ "color_scheme_form": color_scheme_form,
222
+ }
223
+
211
224
  def get_global_context(
212
225
  self, request, object_id: int | str | None = None
213
226
  ) -> dict[str, Any]:
@@ -234,6 +247,7 @@ class SBAdminBaseView(object):
234
247
  "STATIC_BASE_PATH": static("sb_admin"),
235
248
  }
236
249
  ),
250
+ **self.get_color_scheme_context(request),
237
251
  }
238
252
 
239
253
  def get_model_path(self) -> str:
@@ -41,12 +41,12 @@ class SBAdminRoleConfiguration(metaclass=Singleton):
41
41
  filters_version = FilterVersions.FILTERS_VERSION_1
42
42
 
43
43
  def __init__(
44
- self,
45
- default_view=None,
46
- registered_views=None,
47
- menu_items=None,
48
- global_filter_form=None,
49
- filters_version=None,
44
+ self,
45
+ default_view=None,
46
+ registered_views=None,
47
+ menu_items=None,
48
+ global_filter_form=None,
49
+ filters_version=None,
50
50
  ) -> None:
51
51
  super().__init__()
52
52
  self.default_view = default_view or self.default_view or []
@@ -134,13 +134,13 @@ class SBAdminRoleConfiguration(metaclass=Singleton):
134
134
  self.autocomplete_map[view.get_id()] = view
135
135
 
136
136
  def restrict_queryset(
137
- self,
138
- qs,
139
- model,
140
- request,
141
- request_data,
142
- global_filter=True,
143
- global_filter_data_map=None,
137
+ self,
138
+ qs,
139
+ model,
140
+ request,
141
+ request_data,
142
+ global_filter=True,
143
+ global_filter_data_map=None,
144
144
  ):
145
145
  return qs
146
146
 
@@ -154,7 +154,7 @@ class SBAdminRoleConfiguration(metaclass=Singleton):
154
154
  return request.user.is_staff
155
155
 
156
156
  def has_permission(
157
- self, request, request_data, view, model=None, obj=None, permission=None
157
+ self, request, request_data, view, model=None, obj=None, permission=None
158
158
  ):
159
159
  if isinstance(permission, SBAdminCustomAction):
160
160
  return self.has_action_permission(
@@ -174,7 +174,7 @@ class SBAdminRoleConfiguration(metaclass=Singleton):
174
174
  return request.user.is_staff
175
175
 
176
176
  def get_autocomplete_widget(
177
- self, view, request, form_field, db_field, model, multiselect=False
177
+ self, view, request, form_field, db_field, model, multiselect=False
178
178
  ):
179
179
  from django_smartbase_admin.admin.widgets import SBAdminAutocompleteWidget
180
180
 
@@ -186,12 +186,12 @@ class SBAdminRoleConfiguration(metaclass=Singleton):
186
186
  return default_widget
187
187
 
188
188
  def get_form_field_widget_class(
189
- self, view, request, form_field, db_field, default_widget_class
189
+ self, view, request, form_field, db_field, default_widget_class
190
190
  ):
191
191
  return default_widget_class
192
192
 
193
193
  def apply_global_filter_to_queryset(
194
- self, qs, request, request_data, global_filter_data_map
194
+ self, qs, request, request_data, global_filter_data_map
195
195
  ):
196
196
  global_filter_data_map = global_filter_data_map or {}
197
197
  global_filter_data_map = {
@@ -211,9 +211,9 @@ class SBAdminRoleConfiguration(metaclass=Singleton):
211
211
  except:
212
212
  pass
213
213
  if (
214
- include_all_values_for_empty_fields
215
- and field.name in include_all_values_for_empty_fields
216
- and not field_value
214
+ include_all_values_for_empty_fields
215
+ and field.name in include_all_values_for_empty_fields
216
+ and not field_value
217
217
  ):
218
218
  continue
219
219
  field_value = to_list(field_value)
@@ -228,10 +228,10 @@ class SBAdminRoleConfiguration(metaclass=Singleton):
228
228
  return response
229
229
 
230
230
  def autocomplete_show_related_buttons(
231
- self,
232
- related_model,
233
- field_name,
234
- current_view,
235
- request,
231
+ self,
232
+ related_model,
233
+ field_name,
234
+ current_view,
235
+ request,
236
236
  ) -> bool:
237
237
  return not is_modal(request)
@@ -56,11 +56,14 @@ class SBAdminMenuItem(object):
56
56
  return self.label or self.view.get_menu_label()
57
57
 
58
58
  def get_url(self, request):
59
- return (
60
- self.url
61
- or (self.view.get_menu_view_url(request) if self.view else None)
62
- or ""
63
- )
59
+ if callable(self.url):
60
+ return self.url(request)
61
+ elif self.url:
62
+ return self.url
63
+ elif self.view:
64
+ return self.view.get_menu_view_url(request)
65
+ else:
66
+ return ""
64
67
 
65
68
  def get_icon(self):
66
69
  return self.icon or getattr(self.view, "icon", None)
@@ -7,7 +7,7 @@ msgid ""
7
7
  msgstr ""
8
8
  "Project-Id-Version: \n"
9
9
  "Report-Msgid-Bugs-To: \n"
10
- "POT-Creation-Date: 2025-02-11 13:28+0100\n"
10
+ "POT-Creation-Date: 2025-07-29 12:46+0200\n"
11
11
  "PO-Revision-Date: 2023-11-15 15:21+0100\n"
12
12
  "Last-Translator: \n"
13
13
  "Language-Team: \n"
@@ -206,6 +206,18 @@ msgctxt "Tree widget"
206
206
  msgid "No data."
207
207
  msgstr "Žiadne dáta."
208
208
 
209
+ msgid "System"
210
+ msgstr "Systém"
211
+
212
+ msgid "Dark"
213
+ msgstr "Tmavá"
214
+
215
+ msgid "Light"
216
+ msgstr "Svetlá"
217
+
218
+ msgid "Theme"
219
+ msgstr "Téma"
220
+
209
221
  msgid "Translations"
210
222
  msgstr "Preklady"
211
223
 
@@ -221,15 +233,21 @@ msgstr[0] "Opravte chybu nižšie."
221
233
  msgstr[1] "Opravte chyby nižšie."
222
234
  msgstr[2] "Opravte chyby nižšie."
223
235
 
236
+ msgid "Save"
237
+ msgstr "Uložiť"
238
+
239
+ msgid "Close"
240
+ msgstr "Zatvoriť"
241
+
224
242
  msgid "Prev"
225
- msgstr ""
243
+ msgstr "Pred."
226
244
 
227
245
  #, python-format
228
246
  msgid "<strong>%(current_index)s</strong> / %(all_objects_count)s"
229
247
  msgstr ""
230
248
 
231
249
  msgid "Next"
232
- msgstr ""
250
+ msgstr "Ďal."
233
251
 
234
252
  msgid "Back"
235
253
  msgstr "Naspäť"
@@ -326,9 +344,6 @@ msgstr "Vyhľadať"
326
344
  msgid "Copy"
327
345
  msgstr "Kopírovať"
328
346
 
329
- msgid "Save"
330
- msgstr "Uložiť"
331
-
332
347
  msgid "Show translations"
333
348
  msgstr "Zobraziť preklady"
334
349
 
@@ -337,7 +352,7 @@ msgstr "Uložiť zoradenie"
337
352
 
338
353
  #, python-format
339
354
  msgid "You are authenticated as %(username)s, but are not authorized to access this page. Would you like to login to a different account?"
340
- msgstr ""
355
+ msgstr "Ste prihlásený ako %(username)s, ale k tejto stránke nemáte prístup. Chcete sa prihlásiť pod iným účtom?"
341
356
 
342
357
  msgid "Welcome back"
343
358
  msgstr "Vitajte späť"
@@ -650,9 +665,6 @@ msgstr "Zobraziť menu"
650
665
  msgid "Change current folder details"
651
666
  msgstr "Zmeniť detaily priečinka"
652
667
 
653
- msgid "Close"
654
- msgstr "Zatvoriť"
655
-
656
668
  msgid "Limit"
657
669
  msgstr "Limit"
658
670
 
@@ -704,9 +716,6 @@ msgstr "Poradie sa upravuje, prosím čakajte"
704
716
  msgid "Logout"
705
717
  msgstr "Odhlásiť sa"
706
718
 
707
- msgid "Choose domain"
708
- msgstr "Zvoľte si doménu"
709
-
710
719
  msgid "Continue"
711
720
  msgstr "Pokračovať"
712
721
 
@@ -0,0 +1,26 @@
1
+ # Generated by Django 5.0.3 on 2025-07-29 08:28
2
+
3
+ import django.db.models.deletion
4
+ from django.conf import settings
5
+ from django.db import migrations, models
6
+
7
+
8
+ class Migration(migrations.Migration):
9
+
10
+ dependencies = [
11
+ ('django_smartbase_admin', '0004_alter_sbadminlistviewconfiguration_action_and_more'),
12
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
13
+ ]
14
+
15
+ operations = [
16
+ migrations.CreateModel(
17
+ name='SBAdminUserConfiguration',
18
+ fields=[
19
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20
+ ('created_at', models.DateTimeField(auto_now_add=True)),
21
+ ('updated_at', models.DateTimeField(auto_now=True)),
22
+ ('color_scheme', models.CharField(choices=[('auto', '<span class="flex gap-8"><svg class="w-20 h-20"><use href="#Translation"></use></svg><span>System</span></span>'), ('dark', '<span class="flex gap-8"><svg class="w-20 h-20"><use href="#Moon"></use></svg><span>Dark</span></span>'), ('light', '<span class="flex gap-8"><svg class="w-20 h-20"><use href="#Sun-one"></use></svg><span>Light</span></span>')], default='auto', max_length=255, verbose_name='Theme')),
23
+ ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
24
+ ],
25
+ ),
26
+ ]
@@ -1,8 +1,26 @@
1
1
  from django.conf import settings
2
2
  from django.db import models
3
+ from django.utils.html import format_html
4
+ from django.utils.translation import gettext_lazy as _
3
5
 
4
6
  from django_smartbase_admin.querysets import SBAdminListViewConfigurationQueryset
5
7
 
8
+ AUTO_LABEL = _("System")
9
+ DARK_LABEL = _("Dark")
10
+ LIGHT_LABEL = _("Light")
11
+
12
+
13
+ class ColorScheme(models.TextChoices):
14
+ AUTO = "auto", format_html(
15
+ f'<span class="flex gap-8"><svg class="w-20 h-20"><use href="#Translation"></use></svg><span>{AUTO_LABEL}</span></span>'
16
+ )
17
+ DARK = "dark", format_html(
18
+ f'<span class="flex gap-8"><svg class="w-20 h-20"><use href="#Moon"></use></svg><span>{DARK_LABEL}</span></span>'
19
+ )
20
+ LIGHT = "light", format_html(
21
+ f'<span class="flex gap-8"><svg class="w-20 h-20"><use href="#Sun-one"></use></svg><span>{LIGHT_LABEL}</span></span>'
22
+ )
23
+
6
24
 
7
25
  class SBAdminListViewConfiguration(models.Model):
8
26
  created_at = models.DateTimeField(auto_now_add=True)
@@ -18,3 +36,18 @@ class SBAdminListViewConfiguration(models.Model):
18
36
  url_params = models.TextField()
19
37
 
20
38
  objects = SBAdminListViewConfigurationQueryset.as_manager()
39
+
40
+
41
+ class SBAdminUserConfiguration(models.Model):
42
+ created_at = models.DateTimeField(auto_now_add=True)
43
+ updated_at = models.DateTimeField(auto_now=True)
44
+ user = models.ForeignKey(
45
+ to=settings.AUTH_USER_MODEL,
46
+ on_delete=models.CASCADE,
47
+ )
48
+ color_scheme = models.CharField(
49
+ max_length=255,
50
+ choices=ColorScheme.choices,
51
+ default=ColorScheme.AUTO,
52
+ verbose_name=_("Theme"),
53
+ )
@@ -20,3 +20,16 @@ class SBAdminConfigurationService(object):
20
20
  return slugify(view_id)
21
21
  else:
22
22
  return view_id
23
+
24
+
25
+ class SBAdminUserConfigurationService(object):
26
+ @classmethod
27
+ def get_user_config(cls, request):
28
+ if not request.user:
29
+ return None
30
+ from django_smartbase_admin.models import SBAdminUserConfiguration
31
+
32
+ user_config, created = SBAdminUserConfiguration.objects.get_or_create(
33
+ user_id=request.user.id
34
+ )
35
+ return user_config
@@ -25,7 +25,11 @@ module.exports = {
25
25
  colors: {
26
26
  current: 'currentColor',
27
27
  light: 'var(--color-light)',
28
+ 'light-a': 'rgb(var(--color-light-a) / <alpha-value>)',
28
29
  'transparent': 'var(--color-transparent)',
29
30
  ...createColorConfig(),
31
+ 'bg': 'var(--color-bg)',
32
+ 'bg-elevated': 'var(--color-bg-elevated)',
33
+ 'bg-input': 'var(--color-bg-input)',
30
34
  }
31
35
  }