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
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
{% load i18n filer_admin_tags static %}
|
|
2
|
+
|
|
3
|
+
{% spaceless %}
|
|
4
|
+
<div class="clearfix"></div>
|
|
5
|
+
|
|
6
|
+
<div class="dz-preview dz-file-preview hidden js-filer-dropzone-template">
|
|
7
|
+
<span class="filerFile">
|
|
8
|
+
<div class="dz-thumbnail"><img class="quiet" data-dz-thumbnail></div>
|
|
9
|
+
<div>
|
|
10
|
+
<span data-dz-name class="dz-name"></span>
|
|
11
|
+
<span class="filerClearer filer-icon filer-icon-remove-selection" title="{% trans 'Clear' %}"
|
|
12
|
+
data-dz-remove data-no-icon-file="{% static 'filer/icons/file-unknown.svg' %}">
|
|
13
|
+
<button type="button" class="btn btn-tiny btn-destructive">{% trans 'Delete' %}</button>
|
|
14
|
+
</span>
|
|
15
|
+
</div>
|
|
16
|
+
<div class="dz-progress js-filer-dropzone-progress"><span class="dz-upload" data-dz-uploadprogress></span></div>
|
|
17
|
+
</span>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<div class="js-filer-dropzone filer-dropzone{% if object %} js-object-attached{% endif %}"
|
|
21
|
+
data-url="{% url 'admin:filer-ajax_upload' %}"
|
|
22
|
+
data-max-files="1"
|
|
23
|
+
{% if max_filesize %}}data-max-filesize="{{ max_filesize|safe }}"{% endif %}>
|
|
24
|
+
<div class="z-index-fix"></div>
|
|
25
|
+
<div class="dz-default dz-message js-filer-dropzone-message{% if object %} hidden{% endif %}">
|
|
26
|
+
<span class="w-64 h-64 flex items-center justify-center rounded-full mr-16 js-input-file-empty input-file-upload-icon">
|
|
27
|
+
<svg class="w-24 h-24">
|
|
28
|
+
<use xlink:href="#Upload"></use>
|
|
29
|
+
</svg>
|
|
30
|
+
</span>
|
|
31
|
+
<span>{% trans "drop your file here or" %}</span>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<span class="filerFile js-file-selector">
|
|
35
|
+
{% if object %}
|
|
36
|
+
{% if object.file.exists %}
|
|
37
|
+
<a href="{{ object.url }}" target="_blank">{% file_icon object size='64x64' %}</a>
|
|
38
|
+
{% else %}
|
|
39
|
+
{% file_icon object %}
|
|
40
|
+
{% endif %}
|
|
41
|
+
{% else %}
|
|
42
|
+
<img class="thumbnail_img hidden quiet" alt="{% trans 'No file selected' %}">
|
|
43
|
+
{% endif %}
|
|
44
|
+
|
|
45
|
+
<div>
|
|
46
|
+
{% if object %}
|
|
47
|
+
{% if object.file.exists %}
|
|
48
|
+
<span class="description_text">{{ object.label }}</span>
|
|
49
|
+
{% else %}
|
|
50
|
+
{% file_icon object %}
|
|
51
|
+
<span class="description_text">{% trans 'File is missing' %}</span>
|
|
52
|
+
{% endif %}
|
|
53
|
+
{% else %}
|
|
54
|
+
<span class="description_text"></span>
|
|
55
|
+
{% endif %}
|
|
56
|
+
|
|
57
|
+
<div class="flex items-center gap-4">
|
|
58
|
+
<a class="filerClearer {% if not object %}hidden{% endif %}" title="{% trans 'Clear' %}"
|
|
59
|
+
data-no-icon-file="{% static 'filer/icons/file-unknown.svg' %}">
|
|
60
|
+
<button type="button" class="btn btn-tiny btn-destructive">{% trans 'Delete' %}</button>
|
|
61
|
+
</a>
|
|
62
|
+
|
|
63
|
+
<a href="{{ lookup_url }}" class="js-related-lookup related-lookup {% if object %}related-lookup-change{% endif %} lookup" id="{{ id }}_lookup"
|
|
64
|
+
title="{% trans 'Lookup' %}">
|
|
65
|
+
<button type="button" class="btn btn-primary-light btn-tiny add-file-button">{% trans 'Choose File' %}</button>
|
|
66
|
+
</a>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
<div class="hidden">{{ hidden_input }}</div>
|
|
72
|
+
<script type="text/javascript" id="{{id}}_javascript">
|
|
73
|
+
django.jQuery(document).ready(function(){
|
|
74
|
+
var plus = django.jQuery('#add_{{ id }}');
|
|
75
|
+
if (plus.length){
|
|
76
|
+
plus.remove();
|
|
77
|
+
}
|
|
78
|
+
// Delete this javascript once loaded to avoid the "add new" link duplicates it
|
|
79
|
+
django.jQuery('#{{id}}_javascript').remove();
|
|
80
|
+
});
|
|
81
|
+
</script>
|
|
82
|
+
</span>
|
|
83
|
+
</div>
|
|
84
|
+
{% endspaceless %}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{{ widget.value }}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{% load i18n %}
|
|
2
|
+
<div class="flex items-center gap-4 flex-shrink-0 related-item-buttons">
|
|
3
|
+
{% if widget.attrs.related_edit_url or widget.attrs.related_add_url %}
|
|
4
|
+
<a
|
|
5
|
+
class="btn btn-icon edit-button {% if not widget.attrs.related_edit_url %}hidden{% endif %}"
|
|
6
|
+
title="{% trans 'Edit' %}"
|
|
7
|
+
{% if widget.attrs.related_edit_url %}
|
|
8
|
+
hx-get="{{ widget.attrs.related_edit_url }}?_popup=1&sbadmin_is_modal=1&sb_admin_source_field={{ widget.attrs.id }}{% if reload_on_save %}&sbadmin_reload_on_save=1{% endif %}"
|
|
9
|
+
{% endif %}
|
|
10
|
+
{% if widget.attrs.related_add_url and not widget.attrs.related_edit_url %}
|
|
11
|
+
data-add-url="{{ widget.attrs.related_add_url }}?_popup=1&sbadmin_is_modal=1&sb_admin_source_field={{ widget.attrs.id }}"
|
|
12
|
+
{% endif %}
|
|
13
|
+
data-bs-toggle="modal"
|
|
14
|
+
data-bs-target="#sb-admin-modal"
|
|
15
|
+
hx-target="#sb-admin-modal"
|
|
16
|
+
hx-select="#modal-content"
|
|
17
|
+
hx-swap="innerHTML">
|
|
18
|
+
<svg class="w-20 h-20">
|
|
19
|
+
<use xlink:href="#Edit"></use>
|
|
20
|
+
</svg>
|
|
21
|
+
</a>
|
|
22
|
+
{% endif %}
|
|
23
|
+
{% if widget.attrs.related_add_url %}
|
|
24
|
+
<a
|
|
25
|
+
class="btn btn-icon"
|
|
26
|
+
title="{% trans 'Add' %}"
|
|
27
|
+
data-bs-toggle="modal"
|
|
28
|
+
data-bs-target="#sb-admin-modal"
|
|
29
|
+
hx-get="{{ widget.attrs.related_add_url }}?_popup=1&sbadmin_is_modal=1&sb_admin_source_field={{ widget.attrs.id }}"
|
|
30
|
+
hx-target="#sb-admin-modal"
|
|
31
|
+
hx-select="#modal-content"
|
|
32
|
+
hx-swap="innerHTML">
|
|
33
|
+
<svg class="w-20 h-20">
|
|
34
|
+
<use xlink:href="#Add-one"></use>
|
|
35
|
+
</svg>
|
|
36
|
+
</a>
|
|
37
|
+
{% endif %}
|
|
38
|
+
</div>
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
{% include 'sb_admin/widgets/includes/field_label.html' %}
|
|
1
2
|
{% with id=widget.attrs.id %}
|
|
2
3
|
<ul{% if id %} id="{{ id }}"{% endif %}>
|
|
3
4
|
{% for group, options, index in widget.optgroups %}
|
|
4
5
|
{% for option in options %}
|
|
5
|
-
<li>
|
|
6
|
+
<li class="relative py-8">
|
|
6
7
|
{% include option.template_name with widget=option %}
|
|
7
8
|
</li>
|
|
8
9
|
{% endfor %}
|
|
9
10
|
{% endfor %}
|
|
10
11
|
</ul>
|
|
11
12
|
{% endwith %}
|
|
12
|
-
|
|
13
|
+
{% include 'sb_admin/widgets/includes/help_text.html' %}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{% load i18n %}
|
|
2
|
+
|
|
3
|
+
<div class="relative">
|
|
4
|
+
{% include 'sb_admin/widgets/includes/simple_field_label.html' with label_classes="radio-dropdown-label inline-flex text-dark-900 mb-8 text-14 leading-18 font-medium" %}
|
|
5
|
+
<div id="{{ widget.attrs.id }}-wrapper" class="js-simple-multiselect-detail js-dropdown-wrapper">
|
|
6
|
+
<button
|
|
7
|
+
data-bs-toggle="dropdown"
|
|
8
|
+
aria-expanded="false"
|
|
9
|
+
data-bs-offset="[0, 8]"
|
|
10
|
+
class="btn px-10 font-normal w-full"
|
|
11
|
+
>
|
|
12
|
+
<span id="{{ widget.attrs.id }}-value" class="js-dropdown-label flex gap-8">{{ widget.form_field.empty_label }}</span>
|
|
13
|
+
<svg class="ml-8 no-rotate text-dark">
|
|
14
|
+
<use xlink:href="#Sort Alt"></use>
|
|
15
|
+
</svg>
|
|
16
|
+
</button>
|
|
17
|
+
<div id="{{ widget.attrs.id }}-dropdown" class="dropdown-menu">
|
|
18
|
+
<ul id="{{ widget.attrs.id }}" class="relative py-8">
|
|
19
|
+
{% for group, options, index in widget.optgroups %}
|
|
20
|
+
{% for option in options %}
|
|
21
|
+
<li>
|
|
22
|
+
{% include option.template_name with widget=option %}
|
|
23
|
+
</li>
|
|
24
|
+
{% endfor %}
|
|
25
|
+
{% endfor %}
|
|
26
|
+
</ul>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
{% include 'sb_admin/widgets/includes/help_text.html' %}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
{% include 'sb_admin/widgets/includes/field_label.html' %}
|
|
2
2
|
<div {% include "sb_admin/widgets/attrs.html" %}>
|
|
3
3
|
<p class="text-14 leading-18 read-only-password-hash">{{ widget.form_field.help_text|safe }}</p>
|
|
4
|
+
{% if button_label %}
|
|
5
|
+
<p class="mt-8"><a class="btn btn-small" href="{{ password_url|default:"../password/" }}">{{ button_label }}</a></p>
|
|
6
|
+
{% endif %}
|
|
4
7
|
</div>
|
|
@@ -1,3 +1,10 @@
|
|
|
1
1
|
{% include 'sb_admin/widgets/includes/field_label.html' %}
|
|
2
|
-
|
|
2
|
+
<div class="relative flex time-wrapper">
|
|
3
|
+
{% include "sb_admin/widgets/input.html" %}
|
|
4
|
+
<label class="absolute right-10 top-0 bottom-0 h-full flex items-center pointer-events-none" for="{{ widget.attrs.id }}">
|
|
5
|
+
<svg class="w-20 h-20">
|
|
6
|
+
<use xlink:href="#Time"></use>
|
|
7
|
+
</svg>
|
|
8
|
+
</label>
|
|
9
|
+
</div>
|
|
3
10
|
{% include 'sb_admin/widgets/includes/help_text.html' %}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{% load static sb_admin_tags i18n %}
|
|
2
|
+
|
|
3
|
+
{% if not hide_tree_search %}
|
|
4
|
+
<div class="border-b border-dark-200 {{ search_wrapper_classes }}">
|
|
5
|
+
<div class="js-tree-widget-search relative">
|
|
6
|
+
{% trans 'Search' as search_string %}
|
|
7
|
+
<input id="{{ tree_component_id }}_search" name="search" placeholder="{{ tree_filter_placeholder|default:search_string }}" autocomplete="off" class="input pl-36" type="search">
|
|
8
|
+
<div class="absolute pl-10 left-0 top-0 bottom-0 flex items-center gap-8 rounded-r">
|
|
9
|
+
<svg class="w-20 h-20">
|
|
10
|
+
<use xlink:href="#Search"></use>
|
|
11
|
+
</svg>
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
{% endif %}
|
|
16
|
+
<div class="{{ table_wrapper_classes }}">
|
|
17
|
+
<table style="width: 100%;" id="{{ tree_component_id }}_tree" class="js-tree-widget fancytree-ext-table" data-tree-data-id="{{ tree_component_id }}_data" data-tree-additional-columns-id="{{ tree_component_id }}_additional_columns" data-tree-strings-id="{{ tree_component_id }}_tree_strings">
|
|
18
|
+
<thead>
|
|
19
|
+
<tr>
|
|
20
|
+
{% if tree_show_checkbox %}
|
|
21
|
+
<th class="select-all-checkbox-wrapper"></th>
|
|
22
|
+
{% endif %}
|
|
23
|
+
<th class="text-left">{{ tree_main_column_name }}<span id="{{ tree_component_id }}_matches" class="ml-4"></span></th>
|
|
24
|
+
{% for column in tree_additional_columns %}
|
|
25
|
+
<th>{{ column.title }}</th>
|
|
26
|
+
{% endfor %}
|
|
27
|
+
</tr>
|
|
28
|
+
</thead>
|
|
29
|
+
<tbody>
|
|
30
|
+
<tr>
|
|
31
|
+
{% if tree_show_checkbox %}
|
|
32
|
+
<td class="alignCenter fancytree-checkbox-column"></td>{% endif %}
|
|
33
|
+
<td></td>
|
|
34
|
+
{% for column in tree_additional_columns %}
|
|
35
|
+
<td></td>
|
|
36
|
+
{% endfor %}
|
|
37
|
+
</tr>
|
|
38
|
+
</tbody>
|
|
39
|
+
</table>
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<script id="{{ tree_component_id }}_data" type="application/json">
|
|
43
|
+
{
|
|
44
|
+
"filter": {% if tree_filter %}true{% else %}false{% endif %},
|
|
45
|
+
"input_id": "{{ tree_component_id }}",
|
|
46
|
+
"data_url": "{{ tree_data_url }}",
|
|
47
|
+
"checkbox": {% if tree_show_checkbox %}true{% else %}false{% endif %},
|
|
48
|
+
"multiselect": {% if tree_multiselect %}2{% else %}1{% endif %},
|
|
49
|
+
"detail_url":"{{ tree_detail_url }}",
|
|
50
|
+
"reorder_url":"{{ tree_reorder_url }}",
|
|
51
|
+
"filter_by_table_data": {% if filter_by_table_data %}true{% else %}false{% endif %},
|
|
52
|
+
"allow_select_all": {% if allow_select_all %}true{% else %}false{% endif %}
|
|
53
|
+
}
|
|
54
|
+
</script>
|
|
55
|
+
{{ fancytree_filter_settings|get_json_script:'fancytree_filter_settings' }}
|
|
56
|
+
<script id="{{ tree_component_id }}_additional_columns" type="application/json">{{ tree_additional_columns|get_json|safe }}</script>
|
|
57
|
+
<script id="{{ tree_component_id }}_tree_strings" type="application/json">
|
|
58
|
+
{{ tree_strings|get_json|safe }}
|
|
59
|
+
</script>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{% load sb_admin_tags %}
|
|
2
|
+
|
|
3
|
+
<div class="relative">
|
|
4
|
+
{% include 'sb_admin/widgets/includes/field_label.html' %}
|
|
5
|
+
<div id="{{ widget.attrs.id }}-wrapper" class="tree-widget-wrapper">
|
|
6
|
+
<input type="hidden" id="{{ widget.attrs.id }}" name="{{ widget.name }}"{% if widget.raw_value %} value="{{ widget.raw_value|get_json }}"{% endif %}>
|
|
7
|
+
<button
|
|
8
|
+
data-bs-toggle="dropdown"
|
|
9
|
+
aria-expanded="false"
|
|
10
|
+
data-bs-offset="[0, 8]"
|
|
11
|
+
class="btn px-10 font-normal w-full"
|
|
12
|
+
>
|
|
13
|
+
<span id="{{ widget.attrs.id }}_label">{% get_item widget.value_dict widget.raw_value widget.form_field.empty_label %}</span>
|
|
14
|
+
<svg class="ml-8">
|
|
15
|
+
<use xlink:href="#Down"></use>
|
|
16
|
+
</svg>
|
|
17
|
+
</button>
|
|
18
|
+
<div class="dropdown-menu max-h-none w-248">
|
|
19
|
+
<div class="py-8">
|
|
20
|
+
{% include "sb_admin/widgets/tree_base.html" with tree_additional_columns=widget.additional_columns tree_strings=widget.tree_strings tree_value=widget.raw_value tree_multiselect=filter_widget.multiselect tree_component_id=widget.attrs.id tree_data_url=filter_widget.to_json.autocomplete_url tree_show_checkbox=True table_wrapper_classes="max-h-432 overflow-auto custom-scrollbar" %}
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{% load sb_admin_tags %}
|
|
2
|
+
|
|
3
|
+
<div class="relative -mb-2">
|
|
4
|
+
<script>
|
|
5
|
+
document.currentScript.closest('.djn-table').querySelector('.djn-thead').classList.add('hidden');
|
|
6
|
+
</script>
|
|
7
|
+
<div id="{{ widget.attrs.id }}-wrapper" class="tree-widget-wrapper">
|
|
8
|
+
<input type="hidden" id="{{ widget.attrs.id }}" name="{{ widget.name }}"{% if widget.raw_value %}
|
|
9
|
+
value="{{ widget.raw_value|get_json }}"{% endif %}>
|
|
10
|
+
{% include "sb_admin/widgets/tree_base.html" with tree_main_column_name=filter_widget.form_field.label tree_strings=widget.tree_strings tree_additional_columns=widget.additional_columns tree_value=widget.raw_value tree_multiselect=filter_widget.multiselect tree_component_id=widget.attrs.id tree_data_url=filter_widget.to_json.autocomplete_url tree_show_checkbox=True table_wrapper_classes="max-h-432 overflow-auto custom-scrollbar" search_wrapper_classes="pb-16 px-16" allow_select_all=True %}
|
|
11
|
+
</div>
|
|
12
|
+
</div>
|
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import os
|
|
2
3
|
|
|
3
4
|
from django import template
|
|
4
5
|
from django.contrib.admin.templatetags.admin_modify import submit_row
|
|
6
|
+
from django.contrib.admin.utils import lookup_field
|
|
7
|
+
from django.core.exceptions import ObjectDoesNotExist
|
|
5
8
|
from django.core.serializers.json import DjangoJSONEncoder
|
|
6
9
|
from django.template.defaultfilters import json_script
|
|
10
|
+
from django.templatetags.static import static
|
|
11
|
+
from django.utils.safestring import mark_safe
|
|
12
|
+
from django.utils.text import get_text_list
|
|
13
|
+
from django.utils.translation import gettext
|
|
14
|
+
from easy_thumbnails.exceptions import InvalidImageFormatError
|
|
7
15
|
|
|
16
|
+
from django_smartbase_admin.engine.const import (
|
|
17
|
+
ROW_CLASS_FIELD,
|
|
18
|
+
SUPPORTED_FILE_TYPE_ICONS,
|
|
19
|
+
)
|
|
8
20
|
from django_smartbase_admin.templatetags.base import InclusionSBAdminNode
|
|
9
21
|
|
|
10
22
|
register = template.Library()
|
|
@@ -75,7 +87,7 @@ def sb_admin_render_form_field(context, form_field, label_as_placeholder=False):
|
|
|
75
87
|
@register.simple_tag
|
|
76
88
|
def get_tabular_context(fieldsets, inlines, tabs):
|
|
77
89
|
default_tabs = False
|
|
78
|
-
|
|
90
|
+
any_error = False
|
|
79
91
|
first_error_tab = True
|
|
80
92
|
tabular_context = {}
|
|
81
93
|
inlines_map = {inline.opts.__class__: inline for inline in inlines}
|
|
@@ -87,6 +99,7 @@ def get_tabular_context(fieldsets, inlines, tabs):
|
|
|
87
99
|
default_tabs = True
|
|
88
100
|
for key, values in tabs.items():
|
|
89
101
|
for value in values:
|
|
102
|
+
has_error = False
|
|
90
103
|
fieldset_value = fieldsets_map.get(value)
|
|
91
104
|
inline_value = inlines_map.get(value)
|
|
92
105
|
tabular_context[key] = tabular_context.get(
|
|
@@ -96,7 +109,15 @@ def get_tabular_context(fieldsets, inlines, tabs):
|
|
|
96
109
|
tabular_context[key]["content"].append(
|
|
97
110
|
{"type": "fieldset", "value": fieldset_value}
|
|
98
111
|
)
|
|
99
|
-
|
|
112
|
+
fieldset_fields = set()
|
|
113
|
+
for field in fieldset_value.fields:
|
|
114
|
+
if isinstance(field, (list, tuple)):
|
|
115
|
+
fieldset_fields.update(set(field))
|
|
116
|
+
else:
|
|
117
|
+
fieldset_fields.add(field)
|
|
118
|
+
error_present = bool(
|
|
119
|
+
set(fieldset_value.form.errors.keys()).intersection(fieldset_fields)
|
|
120
|
+
)
|
|
100
121
|
has_error = has_error or error_present
|
|
101
122
|
tabular_context[key]["error"] = (
|
|
102
123
|
tabular_context[key]["error"] or error_present
|
|
@@ -111,16 +132,154 @@ def get_tabular_context(fieldsets, inlines, tabs):
|
|
|
111
132
|
tabular_context[key]["error"] or error_present
|
|
112
133
|
)
|
|
113
134
|
if has_error:
|
|
135
|
+
any_error = True
|
|
114
136
|
tabular_context[key]["classes"].add("error")
|
|
115
137
|
if first_error_tab:
|
|
116
138
|
tabular_context[key]["classes"].update(["active", "show"])
|
|
117
139
|
first_error_tab = False
|
|
118
|
-
if not
|
|
140
|
+
if not any_error:
|
|
119
141
|
tabular_context[list(tabular_context.keys())[0]]["classes"].update(
|
|
120
142
|
["active", "show"]
|
|
121
143
|
)
|
|
122
144
|
return {
|
|
123
145
|
"context": tabular_context,
|
|
124
146
|
"default_tabs": default_tabs,
|
|
125
|
-
"has_error":
|
|
147
|
+
"has_error": any_error,
|
|
126
148
|
}
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
@register.filter
|
|
152
|
+
def to_class_name(value):
|
|
153
|
+
return value.__class__.__name__
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def get_change_message_legacy(log_entry):
|
|
157
|
+
change_message = log_entry.change_message
|
|
158
|
+
if change_message and change_message[0] == "[":
|
|
159
|
+
try:
|
|
160
|
+
change_message = json.loads(change_message)
|
|
161
|
+
except json.JSONDecodeError:
|
|
162
|
+
return change_message
|
|
163
|
+
messages = []
|
|
164
|
+
for sub_message in change_message:
|
|
165
|
+
if "added" in sub_message:
|
|
166
|
+
if sub_message["added"]:
|
|
167
|
+
sub_message["added"]["name"] = gettext(sub_message["added"]["name"])
|
|
168
|
+
messages.append(
|
|
169
|
+
gettext("Added {name} “{object}”.").format(
|
|
170
|
+
**sub_message["added"]
|
|
171
|
+
)
|
|
172
|
+
)
|
|
173
|
+
else:
|
|
174
|
+
messages.append(gettext("Added."))
|
|
175
|
+
|
|
176
|
+
elif "changed" in sub_message:
|
|
177
|
+
sub_message["changed"]["fields"] = get_text_list(
|
|
178
|
+
[
|
|
179
|
+
gettext(field_name)
|
|
180
|
+
for field_name in sub_message["changed"]["fields"]
|
|
181
|
+
],
|
|
182
|
+
gettext("and"),
|
|
183
|
+
)
|
|
184
|
+
if "name" in sub_message["changed"]:
|
|
185
|
+
sub_message["changed"]["name"] = gettext(
|
|
186
|
+
sub_message["changed"]["name"]
|
|
187
|
+
)
|
|
188
|
+
messages.append(
|
|
189
|
+
gettext("Changed {fields} for {name} “{object}”.").format(
|
|
190
|
+
**sub_message["changed"]
|
|
191
|
+
)
|
|
192
|
+
)
|
|
193
|
+
else:
|
|
194
|
+
messages.append(
|
|
195
|
+
gettext("Changed {fields}.").format(**sub_message["changed"])
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
elif "deleted" in sub_message:
|
|
199
|
+
sub_message["deleted"]["name"] = gettext(sub_message["deleted"]["name"])
|
|
200
|
+
messages.append(
|
|
201
|
+
gettext("Deleted {name} “{object}”.").format(
|
|
202
|
+
**sub_message["deleted"]
|
|
203
|
+
)
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
change_message = mark_safe(
|
|
207
|
+
"<br/>".join(msg[0].upper() + msg[1:] for msg in messages)
|
|
208
|
+
)
|
|
209
|
+
return change_message or gettext("No fields changed.")
|
|
210
|
+
else:
|
|
211
|
+
return change_message
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
@register.simple_tag
|
|
215
|
+
def get_log_entry_message(log_entry):
|
|
216
|
+
"""
|
|
217
|
+
If change_message is a JSON structure, interpret it as a change
|
|
218
|
+
string, properly translated.
|
|
219
|
+
"""
|
|
220
|
+
try:
|
|
221
|
+
return get_change_message_legacy(log_entry)
|
|
222
|
+
except Exception as e:
|
|
223
|
+
return ""
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
@register.simple_tag
|
|
227
|
+
def call_method(obj, method_name, *args):
|
|
228
|
+
method = getattr(obj, method_name, None)
|
|
229
|
+
if method:
|
|
230
|
+
return method(*args)
|
|
231
|
+
return False
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
@register.simple_tag
|
|
235
|
+
def get_row_class(inline_admin_form):
|
|
236
|
+
try:
|
|
237
|
+
f, attr, value = lookup_field(
|
|
238
|
+
ROW_CLASS_FIELD, inline_admin_form.original, inline_admin_form.model_admin
|
|
239
|
+
)
|
|
240
|
+
except (AttributeError, ValueError, ObjectDoesNotExist):
|
|
241
|
+
return ""
|
|
242
|
+
return value
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
@register.filter
|
|
246
|
+
def is_row_class_field(field):
|
|
247
|
+
return isinstance(field, dict) and field["name"] == ROW_CLASS_FIELD
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
@register.simple_tag
|
|
251
|
+
def get_file_extension(file):
|
|
252
|
+
if not file:
|
|
253
|
+
return ""
|
|
254
|
+
name, extension = os.path.splitext(file.name)
|
|
255
|
+
return extension.lower().replace(".", "")
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
@register.simple_tag
|
|
259
|
+
def get_file_preview_image(
|
|
260
|
+
file, file_extension=None, thumbnail_width=64, thumbnail_height=64
|
|
261
|
+
):
|
|
262
|
+
file_extension = file_extension or get_file_extension(file)
|
|
263
|
+
if file_extension in ["jpg", "jpeg", "png"]:
|
|
264
|
+
from easy_thumbnails.files import get_thumbnailer
|
|
265
|
+
|
|
266
|
+
thumbnailer = get_thumbnailer(file)
|
|
267
|
+
try:
|
|
268
|
+
thumb = thumbnailer.get_thumbnail(
|
|
269
|
+
{
|
|
270
|
+
"size": (thumbnail_width, thumbnail_height),
|
|
271
|
+
"crop": True,
|
|
272
|
+
"replace_alpha": "#fff",
|
|
273
|
+
}
|
|
274
|
+
)
|
|
275
|
+
return thumb.url
|
|
276
|
+
except ValueError:
|
|
277
|
+
return file.url
|
|
278
|
+
except InvalidImageFormatError:
|
|
279
|
+
return static("sb_admin/images/file_types/file-other.svg")
|
|
280
|
+
if file_extension == "svg" or file_extension == "webp":
|
|
281
|
+
return file.url
|
|
282
|
+
for extension in SUPPORTED_FILE_TYPE_ICONS:
|
|
283
|
+
if file_extension == extension:
|
|
284
|
+
return static(f"sb_admin/images/file_types/file-{extension}.svg")
|
|
285
|
+
return static("sb_admin/images/file_types/file-other.svg")
|
django_smartbase_admin/utils.py
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from collections.abc import Iterable
|
|
3
|
+
|
|
1
4
|
from django import forms
|
|
2
5
|
from django.conf import settings
|
|
3
6
|
from django.contrib.admin.helpers import Fieldset
|
|
4
7
|
from django.template.loader import render_to_string
|
|
5
8
|
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
6
11
|
|
|
7
12
|
class JSONSerializableMixin(object):
|
|
8
13
|
def to_json(self):
|
|
@@ -35,15 +40,29 @@ def render_notifications(request):
|
|
|
35
40
|
return render_to_string("sb_admin/includes/notifications.html", request=request)
|
|
36
41
|
|
|
37
42
|
|
|
43
|
+
def is_modal(request):
|
|
44
|
+
from django_smartbase_admin.engine.admin_base_view import SBADMIN_IS_MODAL_VAR
|
|
45
|
+
|
|
46
|
+
return request and (
|
|
47
|
+
SBADMIN_IS_MODAL_VAR in request.GET or SBADMIN_IS_MODAL_VAR in request.POST
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
38
51
|
class FormFieldsetMixin(forms.Form):
|
|
39
|
-
def
|
|
52
|
+
def get_fieldsets(self) -> Iterable[tuple[str | None, dict]]:
|
|
40
53
|
meta = getattr(self, "Meta", None)
|
|
54
|
+
return getattr(meta, "fieldsets", tuple())
|
|
41
55
|
|
|
42
|
-
|
|
56
|
+
def fieldsets(self) -> Iterable[Fieldset]:
|
|
57
|
+
if not (fieldsets := self.get_fieldsets()):
|
|
58
|
+
logger.warning(
|
|
59
|
+
"No fieldsets defined for form %s. Using form fields as fallback.",
|
|
60
|
+
self.__class__.__name__,
|
|
61
|
+
)
|
|
43
62
|
yield Fieldset(form=self, fields=self.fields)
|
|
44
63
|
return
|
|
45
64
|
|
|
46
|
-
for name, data in
|
|
65
|
+
for name, data in fieldsets:
|
|
47
66
|
yield Fieldset(
|
|
48
67
|
form=self,
|
|
49
68
|
name=name,
|
|
@@ -11,6 +11,7 @@ class SBAdminDashboardView(SBAdminView):
|
|
|
11
11
|
menu_action = Action.DASHBOARD.value
|
|
12
12
|
widgets = None
|
|
13
13
|
title = None
|
|
14
|
+
direct_sub_views = None
|
|
14
15
|
|
|
15
16
|
def __init__(self, title=None, widgets=None) -> None:
|
|
16
17
|
super().__init__()
|
|
@@ -27,16 +28,21 @@ class SBAdminDashboardView(SBAdminView):
|
|
|
27
28
|
view.init_view_dynamic(request, request_data, **kwargs)
|
|
28
29
|
|
|
29
30
|
def get_sub_views(self, configuration):
|
|
31
|
+
self.direct_sub_views = []
|
|
30
32
|
self.sub_views = []
|
|
31
33
|
for idx, widget_view in enumerate(self.widgets):
|
|
32
34
|
widget_view.widget_id = f"{self.get_id()}_{idx}"
|
|
33
35
|
widget_view.init_widget_static(configuration)
|
|
36
|
+
widget_view_sub_views = widget_view.get_sub_views(configuration) or []
|
|
34
37
|
self.sub_views.append(widget_view)
|
|
38
|
+
self.direct_sub_views.append(widget_view)
|
|
39
|
+
self.sub_views.extend(widget_view_sub_views)
|
|
35
40
|
return self.sub_views
|
|
36
41
|
|
|
37
42
|
def dashboard(self, request, modifier):
|
|
38
43
|
context = self.get_global_context(request)
|
|
39
44
|
context["sub_views"] = self.sub_views
|
|
45
|
+
context["direct_sub_views"] = self.direct_sub_views
|
|
40
46
|
context["title"] = self.get_title()
|
|
41
47
|
return TemplateResponse(
|
|
42
48
|
request,
|
|
@@ -4,7 +4,10 @@ from django.http import HttpResponse
|
|
|
4
4
|
from django.shortcuts import redirect
|
|
5
5
|
from django.views import View
|
|
6
6
|
|
|
7
|
-
from django_smartbase_admin.engine.const import
|
|
7
|
+
from django_smartbase_admin.engine.const import (
|
|
8
|
+
GLOBAL_FILTER_DATA_KEY,
|
|
9
|
+
TABLE_RELOAD_DATA_EVENT_NAME,
|
|
10
|
+
)
|
|
8
11
|
from django_smartbase_admin.utils import is_htmx_request, querydict_to_dict
|
|
9
12
|
|
|
10
13
|
|
|
@@ -13,10 +16,13 @@ class GlobalFilterView(View):
|
|
|
13
16
|
response = redirect(request.headers.get("referer", ""))
|
|
14
17
|
if is_htmx_request(request.META):
|
|
15
18
|
response = HttpResponse()
|
|
16
|
-
response["HX-Trigger"] = json.dumps({
|
|
19
|
+
response["HX-Trigger"] = json.dumps({TABLE_RELOAD_DATA_EVENT_NAME: ""})
|
|
17
20
|
new_global_filter_data = querydict_to_dict(request.POST)
|
|
18
21
|
request.request_data.global_filter = new_global_filter_data
|
|
19
22
|
request.request_data.configuration.init_global_filter_form_instance(request)
|
|
20
23
|
if request.request_data.global_filter_instance.is_valid():
|
|
21
24
|
request.session[GLOBAL_FILTER_DATA_KEY] = new_global_filter_data
|
|
25
|
+
response = request.request_data.configuration.process_global_filter_response(
|
|
26
|
+
response, request
|
|
27
|
+
)
|
|
22
28
|
return response
|