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
@@ -0,0 +1,16 @@
1
+ {% load sb_admin_tags %}
2
+
3
+ <div class="dropdown-menu max-h-none w-248">
4
+ <div class="px-12 pt-8 border-b border-dark-200">
5
+ {% with tree_widget_id=filter_widget.view_id|add:"-"|add:filter_widget.input_id|add:"_tree" %}
6
+ <div class="relative -mx-12">
7
+ <input form="{{ filter_widget.view_id }}-filter-form" type="hidden"
8
+ id="{{ filter_widget.input_id }}" name="{{ filter_widget.input_name }}"
9
+ {% if not all_filters_visible %}disabled{% endif %}{% if filter_widget.get_default_value %} value="{{ filter_widget.get_default_value|get_json }}"{% endif %}>
10
+ {% include "sb_admin/widgets/tree_base.html" with tree_additional_columns=filter_widget.additional_columns tree_strings=filter_widget.tree_strings tree_filter=True tree_value=filter_widget.get_default_value tree_multiselect=filter_widget.multiselect tree_component_id=filter_widget.input_id tree_data_url=filter_widget.to_json.autocomplete_url tree_show_checkbox=True search_wrapper_classes="pb-8 px-12" table_wrapper_classes="max-h-432 overflow-auto custom-scrollbar" %}
11
+ </div>
12
+ {% endwith %}
13
+ </div>
14
+ {% include "sb_admin/filter_widgets/partials/clear.html" %}
15
+ </div>
16
+
@@ -1,7 +1,9 @@
1
1
  {% load i18n %}
2
2
 
3
3
  {% if add %}
4
- {% blocktrans with name=opts.verbose_name %}Add {{ name }}{% endblocktrans %}
4
+ {% trans 'Add' %}{% if add_label %} {{ add_label }}{% endif %}
5
+ {% elif change_label %}
6
+ {{ change_label }}
5
7
  {% else %}
6
8
  {{ original|truncatewords:"18" }}
7
9
  {% endif %}
@@ -1,3 +1,6 @@
1
+ {% extends 'sb_admin/sb_admin_base_no_sidebar.html' %}
2
+ {% load i18n %}
3
+ {% block main_wrapper %}
1
4
  <div class="alert bg-notice-50 border border-notice-100 text-notice-900">
2
5
  <div class="flex">
3
6
  <svg class="w-20 h-20 mr-12 text-notice">
@@ -439,4 +442,5 @@
439
442
  <div>
440
443
  <input type="text" id="date-picker" class="js-datepicker-range">
441
444
  </div>
442
- </div>
445
+ </div>
446
+ {% endblock %}
@@ -1,49 +1,58 @@
1
- {% if fieldset.name %}
2
- <header class="mb-24">
3
- <span class="text-dark-900">{{ fieldset.name }}</span>
4
- <div class="ml-auto flex items-center">
5
- {% for action in fieldset_context.actions %}
6
- <a href="{{ action.url }}" class="btn btn-small">{{ action.title }}</a>
7
- {% endfor %}
8
- {% if fieldset.description %}
9
- <div class="js-tooltip ml-8" data-bs-toggle="tooltip" data-bs-placement="bottom" title="{{ fieldset.description|safe }}">
10
- <svg class="w-20 h-20">
11
- <use xlink:href="#Help"></use>
12
- </svg>
1
+ {% load sb_admin_tags %}
2
+
3
+ {% block content %}
4
+ {% block header %}
5
+ {% if fieldset.name %}
6
+ <header class="mb-24 flex items-center">
7
+ <span class="text-dark-900">{{ fieldset.name }}</span>
8
+ {% block description %}
9
+ {% if fieldset.description %}
10
+ <div class="js-tooltip ml-8" data-bs-toggle="tooltip" data-bs-placement="bottom" title="{{ fieldset.description|safe }}">
11
+ <svg class="w-20 h-20">
12
+ <use xlink:href="#Help"></use>
13
+ </svg>
14
+ </div>
15
+ {% endif %}
16
+ {% endblock %}
17
+ <div class="ml-auto flex items-center gap-4">
18
+ {% block actions %}
19
+ {% for action in fieldset_context.actions %}
20
+ <a href="{{ action.url }}" class="btn btn-small">{{ action.title }}</a>
21
+ {% endfor %}
22
+ {% endblock %}
13
23
  </div>
14
- {% endif %}
15
- </div>
16
- </header>
17
- {% endif %}
18
- {% for line in fieldset %}
19
- <div class="field{% if forloop.last %} -mb-24{% endif %}{% if line.fields|length == 1 and line.errors %} errors{% endif %}{% if not line.has_visible_field %} hidden{% endif %}{% for field in line %}{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% endfor %}">
20
- {% if line.fields|length > 1 %}
21
- <div class="flex max-xs:flex-wrap gap-x-16">{% endif %}
24
+ </header>
25
+ {% endif %}
26
+ {% endblock %}
22
27
 
23
- {% for field in line %}
24
- <div class="mb-16 sm:mb-24 max-xs:w-full sm:flex-1{% if field.field.is_hidden %} hidden{% endif %}">
25
- {% if field.is_readonly %}
26
- <div class="flex flex-wrap w-full">
27
- {% if field.field.label %}
28
- <label class="inline-flex text-dark-900 text-14 leading-18 font-medium mr-8">{{ field.field.label }}:</label>
28
+ {% block lines %}
29
+ {% for line in fieldset %}
30
+ <div class="field{% if forloop.last %} -mb-24{% endif %}{% if line.fields|length == 1 and line.errors %} errors{% endif %}{% if not line.has_visible_field %} hidden{% endif %}{% for field in line %}{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% endfor %}">
31
+ {% if line.fields|length > 1 %}
32
+ <div class="flex max-xs:flex-wrap gap-x-16">{% endif %}
33
+
34
+ {% for field in line %}
35
+ <div class="mb-16 sm:mb-24 max-xs:w-full sm:flex-1{% if field.field.is_hidden or field.field|is_row_class_field %} hidden{% endif %}">
36
+ {% if field.is_readonly %}
37
+ {% call_method field "contents" request %}
38
+ {% else %}
39
+ {{ field.field }}
40
+ {% if not line.fields|length == 1 %}{{ field.errors }}{% endif %}
29
41
  {% endif %}
30
- <div class="text-14 w-full break-all">{{ field.contents }}</div>
31
42
  </div>
32
- {% else %}
33
- {{ field.field }}
34
- {% if not line.fields|length == 1 %}{{ field.errors }}{% endif %}
43
+ {% endfor %}
44
+
45
+ {% if line.fields|length == 1 and line.errors %}
46
+ <div class="-mt-16 mb-24">
47
+ {{ line.errors }}
48
+ </div>
35
49
  {% endif %}
50
+ {% if line.fields|length > 1 %}</div>{% endif %}
36
51
  </div>
37
52
  {% endfor %}
38
53
 
39
- {% if line.fields|length == 1 and line.errors %}
40
- <div class="-mt-16 mb-24">
41
- {{ line.errors }}
42
- </div>
43
- {% endif %}
44
- {% if line.fields|length > 1 %}</div>{% endif %}
45
- </div>
46
- {% endfor %}
47
- {% block additional_fields %}
54
+ {% endblock %}
55
+ {% block additional_fields %}
48
56
 
57
+ {% endblock %}
49
58
  {% endblock %}
@@ -1,4 +1,5 @@
1
- <div id="notification-messages" hx-swap-oob="beforeend" class="z-1000 fixed right-0 left-0 xl:left-260 mx-24">
1
+ <div id="notification-messages" hx-swap-oob="beforeend"
2
+ class="messagelist z-1000 fixed right-0 left-0 xl:left-260 mx-24{% if classes %} {{ classes }}{% endif %}">
2
3
  {% for message in messages %}
3
4
  {% if message.level == DEFAULT_MESSAGE_LEVELS.SUCCESS %}
4
5
  {% include 'sb_admin/partials/messages/alert_success.html' with text=message %}
@@ -0,0 +1,9 @@
1
+ <div class="w-full">
2
+ <div class="text-14 w-full break-all">
3
+ <div class="relative">
4
+ <input type="checkbox" name="{{ field_name }}" id="id_{{ field_name }}" form="#" class="toggle"{% if value %} checked{% endif %} readonly disabled>
5
+ <label for="id_{{ field_name }}"></label>
6
+ <label for="id_{{ field_name }}">{{ field_label }}</label>
7
+ </div>
8
+ </div>
9
+ </div>
@@ -0,0 +1,12 @@
1
+ {% load sb_admin_tags %}
2
+
3
+ <div class="w-full">
4
+ {% if field_label %}
5
+ <label class="inline-flex text-dark-900 text-14 leading-18 font-medium mb-8">
6
+ {{ field_label }}{{ field_label_suffix }}
7
+ </label>
8
+ {% endif %}
9
+ <div class="text-14 w-full break-all">
10
+ {{ readonly_content }}
11
+ </div>
12
+ </div>
@@ -1,7 +1,7 @@
1
1
  {% load widget_tweaks %}
2
2
  {% if inline_admin_formset.formset.can_delete %}
3
3
  {% if inline_admin_form.original %}
4
- <td class="w-40">
4
+ <td class="w-40{% if sticky %} sticky-table-col{% endif %}">
5
5
  <div class="relative min-h-40 flex items-center delete djn-delete-handler {{ inline_admin_formset.handler_classes|join:" " }}">
6
6
  {% render_field inline_admin_form.deletion_field.field class="checkbox checkbox-delete" %}
7
7
  <label for="{{ inline_admin_form.deletion_field.field.auto_id }}">
@@ -12,10 +12,9 @@
12
12
  </div>
13
13
  </td>
14
14
  {% else %}
15
- <td class="delete w-40">
16
- <a
17
- class="flex-center h-40 inline-deletelink djn-remove-handler {{ inline_admin_formset.handler_classes|join:" " }}"
18
- href="javascript:void(0)">
15
+ <td class="delete w-40{% if sticky %} sticky-table-col{% endif %}">
16
+ <a class="flex-center h-40 inline-deletelink djn-remove-handler {{ inline_admin_formset.handler_classes|join:" " }}"
17
+ href="javascript:void(0)">
19
18
  <svg class="w-20 h-20 text-dark-300 hover:text-dark-400">
20
19
  <use xlink:href="#Delete"></use>
21
20
  </svg>
@@ -1,6 +1,7 @@
1
- {% load i18n nested_admin admin_urls widget_tweaks %}
1
+ {% load i18n nested_admin admin_urls widget_tweaks sb_admin_tags %}
2
2
  {% block extra_style %}{% endblock %}
3
3
 
4
+ {% call_method inline_admin_formset.opts "get_context_data" request as context_data %}
4
5
  {% with inline_admin_formset.formset.is_nested as is_nested %}
5
6
 
6
7
  {% with inline_admin_formset.opts as inline_opts %}
@@ -11,9 +12,28 @@
11
12
  data-inline-model="{{ inline_admin_formset.inline_model_id }}">
12
13
 
13
14
  {% ifinlineclasses %}<fieldset class="djn-fieldset module {{ inline_admin_formset.classes }}">{% endifinlineclasses %}
14
- <h2 class="stacked-inline-heading">
15
- {% if inline_admin_formset.opts.title %}{{ inline_admin_formset.opts.title }}{% else %}{{ inline_admin_formset.opts.verbose_name_plural|capfirst }}{% endif %}
16
- </h2>
15
+
16
+ <header class="flex items-center mb-24">
17
+ <h2 class="stacked-inline-heading">
18
+ {% if inline_admin_formset.opts.title %}{{ inline_admin_formset.opts.title }}{% else %}{{ inline_admin_formset.opts.verbose_name_plural|capfirst }}{% endif %}
19
+ </h2>
20
+
21
+ <div class="djn-module djn-add-item add-item add-row max-sm:px-24 ml-auto flex items-center gap-8">
22
+ {% for list_action in context_data.inline_list_actions %}
23
+ <a {% if list_action.open_in_modal %}{% include 'sb_admin/actions/partials/open_modal_attrs.html' with action=list_action %}{% endif %} href="{{ list_action.url }}"
24
+ class="btn {{ list_action.css_class|default_if_none:'' }}">{{ list_action.title }}</a>
25
+ {% endfor %}
26
+ <a href="javascript://" class="add-handler djn-add-handler btn btn-icon ml-auto {{ inline_admin_formset.handler_classes|join:" " }}">
27
+ <svg class="w-20 h-20 md:mr-8">
28
+ <use xlink:href="#Plus"></use>
29
+ </svg>
30
+ <span>
31
+ {% blocktrans with inline_admin_formset.opts.verbose_name|strip_parent_name:inline_opts.verbose_name|title as verbose_name %}Add another {{ verbose_name }}{% endblocktrans %}
32
+ </span>
33
+ </a>
34
+ </div>
35
+ </header>
36
+
17
37
 
18
38
  {{ inline_admin_formset.formset.management_form }}
19
39
  {{ inline_admin_formset.formset.non_form_errors }}
@@ -31,12 +51,23 @@
31
51
  data-is-initial="{% if inline_admin_form.pk_field.field.value %}true{% else %}false{% endif %}"
32
52
  {% endif %}
33
53
  id="{{ inline_admin_formset.formset.prefix }}-{% if forloop.last and inline_admin_formset.has_add_permission %}empty{% else %}{{ inline_admin_form.form|form_index }}{% endif %}">
34
- <div class="card p-0 sm:mb-24 {% if inline_admin_form.formset.nesting_depth > 1 %}border-0{% endif %}">
35
- {% if not inline_opts.sortable_options or not inline_opts.sortable_options.disabled %}<div class="djn-drag-handler"></div>{% endif %}
36
- <div class="p-24 pb-0">
54
+ <div class="djn-tools card level-{{ inline_admin_form.formset.nesting_depth }} p-0 sm:mb-24 {% if inline_admin_form.formset.nesting_depth > 1 %}border-0{% endif %}">
55
+ <div class="p-24">
37
56
  {# <b>{{ inline_admin_formset.opts.verbose_name|capfirst }}:</b>&nbsp;#}
38
57
  <div class="flex items-center">
39
- <span class="text-dark-900 font-semibold">{% if inline_admin_form.original %}{{ inline_admin_form.original }}{% else %}#{{ forloop.counter }}{% endif %}</span>
58
+ {% if not inline_opts.sortable_options or not inline_opts.sortable_options.disabled %}
59
+ <div class="drag-handler btn btn-empty cursor-move static transform-none mr-8">
60
+ <svg class="w-20 h-20 text-dark-400"><use xlink:href="#Drag"></use></svg>
61
+ </div>
62
+ {% endif %}
63
+ <span class="text-dark-900 font-semibold">
64
+ {% call_method inline_opts "get_instance_label" request inline_admin_form.original as instance_label %}
65
+ {% if instance_label %}
66
+ {{ instance_label }}
67
+ {% else %}
68
+ #{{ forloop.counter }}
69
+ {% endif %}
70
+ </span>
40
71
  <div class="ml-auto">
41
72
  {% if inline_admin_form.original and inline_admin_form.model_admin.show_change_link and inline_admin_form.model_admin.has_registered_model %}
42
73
  <a href="{% url inline_admin_form.model_admin.opts|admin_urlname:'change' inline_admin_form.original.pk|admin_urlquote %}" class="{% if inline_admin_formset.has_change_permission %}inlinechangelink{% else %}inlineviewlink{% endif %}">
@@ -44,8 +75,8 @@
44
75
  </a>
45
76
  {% endif %}
46
77
  {% if inline_admin_form.show_url %}<a href="{{ inline_admin_form.absolute_url }}" class="ml-8">{% trans "View on site" %}</a>{% endif %}
47
- {% if inline_admin_formset.formset.can_delete %}
48
- <div class="ml-8">
78
+ <div class="ml-8 flex items-center gap-8">
79
+ {% if inline_admin_formset.formset.can_delete %}
49
80
  {% if inline_admin_form.original %}
50
81
  <div class="delete djn-delete-handler {{ inline_admin_formset.handler_classes|join:" " }}">
51
82
  <div class="relative flex items-center h-40">
@@ -58,8 +89,14 @@
58
89
  {% else %}
59
90
  <span><a class="inline-deletelink djn-remove-handler {{ inline_admin_formset.handler_classes|join:" " }}" href="javascript:void(0)">{% trans 'Delete' %}</a></span>
60
91
  {% endif %}
61
- </div>
62
- {% endif %}
92
+ {% endif %}
93
+ <div class="w-2 bg-dark-200 self-stretch"></div>
94
+ <button type="button" class="btn btn-empty js-collapse-stacked-inline" aria-expanded="{{ context_data.default_collapsed|yesno:"false,true" }}">
95
+ <svg class="w-20 h-20 text-dark-400">
96
+ <use xlink:href="#Down"></use>
97
+ </svg>
98
+ </button>
99
+ </div>
63
100
  </div>
64
101
  </div>
65
102
 
@@ -70,39 +107,30 @@
70
107
  {% endif %}
71
108
  </div>
72
109
 
73
-
74
- {% for fieldset in inline_admin_form %}
75
- <div class="p-24 stacked-row{% if not forloop.first %} border-t border-dark-200{% endif %}">
76
- {% include inline_admin_formset.opts.fieldset_template %}
77
- </div>
78
- {% endfor %}
79
- {% if inline_admin_form.has_auto_field or inline_admin_form.needs_explicit_pk_field %}
80
- {{ inline_admin_form.pk_field.field }}
81
- {% endif %}
82
- {% if inline_admin_form.fk_field %}{{ inline_admin_form.fk_field.field }}{% endif %}
110
+ <div class="collapse flex flex-col {% if not context_data.default_collapsed %}show{% endif %}">
111
+ {% for fieldset in inline_admin_form %}
112
+ <div class="pt-0 pb-24 px-24 stacked-row{% if not forloop.first %} border-t border-dark-200{% endif %}">
113
+ {% include inline_admin_formset.opts.fieldset_template %}
114
+ </div>
115
+ {% endfor %}
116
+ {% if inline_admin_form.has_auto_field or inline_admin_form.needs_explicit_pk_field %}
117
+ {{ inline_admin_form.pk_field.field }}
118
+ {% endif %}
119
+ {% if inline_admin_form.fk_field %}{{ inline_admin_form.fk_field.field }}{% endif %}
120
+ {% if inline_admin_form.form.inlines %}
121
+ {% for nested in inline_admin_form.form.inlines %}
122
+ <div class="card level-{{ nested.formset.nesting_depth }} p-0 mx-24 sm:my-24">
123
+ {% include nested.opts.template with inline_admin_formset=nested %}
124
+ </div>
125
+ {% endfor %}
126
+ {% endif %}
127
+ </div>
83
128
  </div>
84
- {% if inline_admin_form.form.inlines %}
85
- {% for nested in inline_admin_form.form.inlines %}
86
- <div class="card p-0 sm:mb-24 {% if nested.formset.nesting_depth > 2 %}border-x-0 rounded-none{% endif %}">
87
- {% include nested.opts.template with inline_admin_formset=nested %}
88
- </div>
89
- {% endfor %}
90
- {% endif %}
91
-
92
129
  </div>
93
130
  {% endfor %}
94
131
  {% endwith %}
95
132
  </div>
96
- <div class="djn-module djn-add-item add-item add-row max-sm:px-24 max-sm:mt-8">
97
- <a href="javascript://" class="add-handler djn-add-handler btn btn-icon ml-auto {{ inline_admin_formset.handler_classes|join:" " }}">
98
- <svg class="w-20 h-20 md:mr-8">
99
- <use xlink:href="#Plus"></use>
100
- </svg>
101
- <span>
102
- {% blocktrans with inline_admin_formset.opts.verbose_name|strip_parent_name:inline_opts.verbose_name|title as verbose_name %}Add another {{ verbose_name }}{% endblocktrans %}
103
- </span>
104
- </a>
105
- </div>
133
+
106
134
  {% ifinlineclasses %}</fieldset>{% endifinlineclasses %}
107
135
  </div>
108
136
  {% endwith %}{# ends with inline_admin_formset.opts as inline_opts #}
@@ -1,15 +1,16 @@
1
1
  {% load admin_urlname admin_urlquote from admin_urls %}
2
- {% load i18n nested_admin static widget_tweaks %}
2
+ {% load i18n nested_admin static widget_tweaks sb_admin_tags %}
3
3
 
4
+ {% call_method inline_admin_formset.opts "get_context_data" request as context_data %}
4
5
  {% with inline_admin_formset.formset.is_nested as is_nested %}
5
6
 
6
7
  {% with inline_admin_formset.opts as inline_opts %}
7
8
  <div
8
- class="card p-0 sm:mb-24 inline-group group djn-group djn-tabular{% if is_nested %} djn-group-nested{% else %} djn-group-root{% endif %}"
9
+ class="{% if inline_admin_formset.opts.class_name %}{{ inline_admin_formset.opts.class_name }}{% else %}{{ inline_admin_formset.opts|to_class_name|slugify }}{% endif %}{% if inline_admin_formset.formset.can_delete %} can-delete{% endif %} card p-0 sm:mb-24 inline-group group djn-group djn-tabular{% if is_nested %} djn-group-nested{% else %} djn-group-root{% endif %}"
9
10
  id="{{ inline_admin_formset.formset.prefix }}-group"
10
11
  data-inline-type="stacked"
11
12
  data-inline-formset="{{ inline_admin_formset.inline_formset_data }}"
12
- data-inline-model="{{ inline_admin_formset.inline_model_id }}">
13
+ data-inline-model="{{ inline_admin_formset.inline_model_id }}"{% block additional_wrapper_attributes %}{% endblock %}>
13
14
 
14
15
  {% block card_content %}
15
16
  <header class="mb-24 px-20 md:px-24 pt-20 md:pt-24 table-header">
@@ -18,17 +19,36 @@
18
19
  {{ inline_admin_formset.opts.verbose_name_plural|capfirst }}{% endif %}
19
20
  </span>
20
21
  <div class="ml-auto flex gap-8">
21
- {% for list_action in inline_admin_formset.opts.get_context_data.inline_list_actions %}
22
+ {% for list_action in context_data.inline_list_actions %}
22
23
  <a {% if list_action.open_in_modal %}{% include 'sb_admin/actions/partials/open_modal_attrs.html' with action=list_action %}{% endif %} href="{{ list_action.url }}"
23
24
  class="btn {{ list_action.css_class|default_if_none:'' }}">{{ list_action.title }}</a>
24
25
  {% endfor %}
25
26
  {% if inline_admin_formset.has_add_permission %}
26
- <a href="javascript://" class="add-handler djn-add-handler btn btn-icon ml-auto {{ inline_admin_formset.handler_classes|join:" " }}">
27
- <svg class="w-20 h-20 md:mr-8">
28
- <use xlink:href="#Plus"></use>
29
- </svg>
30
- <span>{% trans 'Add' %}</span>
31
- </a>
27
+ {% if context_data.add_url and not sbadmin_is_modal %}
28
+ <a
29
+ class="btn btn-icon ml-auto {{ inline_admin_formset.handler_classes|join:" " }}"
30
+ data-bs-toggle="modal"
31
+ data-bs-target="#sb-admin-modal"
32
+ hx-get="{{ context_data.add_url }}?_popup=1&sbadmin_is_modal=1&sbadmin_reload_on_save=1&sbadmin_parent_instance_field=modal_{{ context_data.parent_data.sbadmin_parent_instance_field }}&sbadmin_parent_instance_pk={{ context_data.parent_data.sbadmin_parent_instance_pk }}&sbadmin_parent_instance_label={{ context_data.parent_data.sbadmin_parent_instance_label }}"
33
+ hx-target="#sb-admin-modal"
34
+ hx-select="#modal-content"
35
+ hx-swap="innerHTML"
36
+ >
37
+ <svg class="w-20 h-20 md:mr-8">
38
+ <use xlink:href="#Plus"></use>
39
+ </svg>
40
+ <span>{% trans 'Add' %}</span>
41
+ </a>
42
+ {% else %}
43
+ <div class="djn-add-item ml-auto">
44
+ <a href="javascript://" class="add-handler djn-add-handler btn btn-icon {{ inline_admin_formset.handler_classes|join:" " }}">
45
+ <svg class="w-20 h-20 md:mr-8">
46
+ <use xlink:href="#Plus"></use>
47
+ </svg>
48
+ <span>{% trans 'Add' %}</span>
49
+ </a>
50
+ </div>
51
+ {% endif %}
32
52
  {% endif %}
33
53
  </div>
34
54
  </header>
@@ -46,30 +66,35 @@
46
66
  <table class="djn-items inline-related djn-table">
47
67
  {% with inline_admin_formset.opts.sortable_field_name|default:"" as sortable_field_name %}
48
68
  <thead class="djn-module djn-thead">
49
- <tr>
69
+ <tr>
70
+ {% if context_data.is_sortable_active %}
50
71
  <th class="original{% if sortable_field_name %} is-sortable{% endif %}"></th>
51
- {% for field in inline_admin_formset.fields %}
52
- {% if not field.widget.is_hidden %}
53
- <th class="djn-th
72
+ {% endif %}
73
+ {% for field in inline_admin_formset.fields %}
74
+ {% if not field.widget.is_hidden and not field|is_row_class_field %}
75
+ <th class="djn-th
54
76
  {{ field.label|lower|slugify }}{% if field.required %} required{% endif %}">
55
- <div class="flex items-center">
56
- <span class="mr-auto">{{ field.label|capfirst }}{% if field.required %}<span class="ml-4 text-negative">*</span>{% endif %}</span>
57
- {% if field.help_text %}&nbsp;
58
- <div class="ml-4">
59
- <div class="js-tooltip flex" data-bs-toggle="tooltip" data-bs-placement="bottom" title="{{ field.help_text|striptags }}">
60
- <svg class="w-12 h-12">
61
- <use xlink:href="#Help"></use>
62
- </svg>
63
- </div>
77
+ <div class="flex items-center">
78
+ <span class="mr-auto">{{ field.label|capfirst }}{% if field.required %}<span class="ml-4 text-negative">*</span>{% endif %}</span>
79
+ {% if field.help_text %}&nbsp;
80
+ <div class="ml-4">
81
+ <div class="js-tooltip flex" data-bs-toggle="tooltip" data-bs-placement="bottom" title="{{ field.help_text|striptags }}">
82
+ <svg class="w-12 h-12">
83
+ <use xlink:href="#Help"></use>
84
+ </svg>
64
85
  </div>
65
- {% endif %}
66
- </div>
67
- </th>
68
- {% endif %}
69
- {% endfor %}
86
+ </div>
87
+ {% endif %}
88
+ </div>
89
+ </th>
90
+ {% endif %}
91
+ {% endfor %}
92
+ {% block table_inline_delete_table_head %}
70
93
  {% if inline_admin_formset.formset.can_delete %}
71
- <th class="djn-th" style="min-width: 54px; width: 54px;"></th>{% endif %}
72
- </tr>
94
+ <th class="djn-th sticky-table-head" style="min-width: 54px; width: 54px;"></th>
95
+ {% endif %}
96
+ {% endblock %}
97
+ </tr>
73
98
  </thead>
74
99
 
75
100
 
@@ -97,8 +122,8 @@
97
122
  </td>
98
123
  </tr>
99
124
  {% endif %}
100
- <tr class="djn-tr form-row{% if inline_admin_form.original or inline_admin_form.show_url %} has_original{% endif %}">
101
- <td class="original{% if inline_admin_formset.opts.sortable_field_name %} is-sortable{% endif %}">
125
+ <tr class="djn-tr form-row{% if inline_admin_form.original or inline_admin_form.show_url %} has_original{% endif %} {% get_row_class inline_admin_form %}">
126
+ <td class="original{% if inline_admin_formset.opts.sortable_field_name %} is-sortable{% endif %}" style="{% if not context_data.is_sortable_active %}display: none;{% endif %}">
102
127
  {% if inline_admin_formset.opts.sortable_field_name %}
103
128
  <div class="djn-drag-handler">
104
129
  <svg class="w-20 h-20 text-dark-400">
@@ -142,10 +167,12 @@
142
167
  {% for fieldset in inline_admin_form %}
143
168
  {% for line in fieldset %}
144
169
  {% for field in line %}
145
- {% if not field.field.is_hidden %}
170
+ {% if not field.field.is_hidden and not field.field|is_row_class_field %}
146
171
  <td class="djn-td field-{{ field.field.name }}">
147
172
  {% if field.is_readonly %}
148
- <div class="px-10 py-8">{{ field.contents }}</div>
173
+ <div class="px-10 py-8">
174
+ {% call_method field "contents" request %}
175
+ </div>
149
176
  {% else %}
150
177
  {{ field.field }}
151
178
  {% if field.field.errors %}
@@ -158,10 +185,10 @@
158
185
  {% endfor %}
159
186
  {% endfor %}
160
187
  {% block table_inline_delete_button %}
161
- {% include "sb_admin/includes/table_inline_delete_button.html" %}
188
+ {% include "sb_admin/includes/table_inline_delete_button.html" with sticky=True %}
162
189
  {% endblock %}
163
190
  </tr>
164
-
191
+ {% block table_inline_after_line %}{% endblock %}
165
192
  {% if inline_admin_form.form.inlines %}
166
193
  <tr class="djn-tr">
167
194
  <td class="djn-td" colspan="{{ inline_admin_form|cell_count }}">
@@ -178,6 +205,21 @@
178
205
  {% endblock %}
179
206
  </table>
180
207
 
208
+ {% block table_script %}
209
+ <script>
210
+ {# move all non initial lines to the top of the table to maintain original order #}
211
+ {# this should happen only during validation error #}
212
+ (function(){
213
+ const group = document.getElementById('{{ inline_admin_formset.formset.prefix }}-group');
214
+ const table = group.querySelector('.djn-table');
215
+ const bodies_to_move = Array.from(group.querySelectorAll('.djn-tbody[data-is-initial="false"]'));
216
+ if(bodies_to_move) {
217
+ table.prepend(...bodies_to_move.reverse());
218
+ }
219
+ }());
220
+ </script>
221
+ {% endblock %}
222
+
181
223
  </fieldset>
182
224
  </div>
183
225
 
@@ -59,6 +59,24 @@
59
59
  }
60
60
  </style>
61
61
  {% endif %}
62
+ <style>
63
+ .fa {
64
+ display: inline-flex;
65
+ width: 20px;
66
+ height: 20px;
67
+ background-size: 20px;
68
+ background-repeat: no-repeat;
69
+ }
70
+ .fa.fa-download {
71
+ background-image: url('data:image/svg+xml,<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill="%23249ff8" fill-rule="evenodd" clip-rule="evenodd" d="M12.9961 13.5898L15.793 10.7929L17.2072 12.2071L12.7072 16.7071C12.3167 17.0976 11.6835 17.0976 11.293 16.7071L6.79297 12.2071L8.20718 10.7929L10.9961 13.5818V3H12.9961V13.5898ZM22 12V21C22 21.5523 21.5523 22 21 22H3C2.44772 22 2 21.5523 2 21V12.0042H4V20H20V12H22Z"/></svg>');
72
+ }
73
+ .fa.fa-pencil {
74
+ background-image: url('data:image/svg+xml,<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill="%23249ff8" fill-rule="evenodd" clip-rule="evenodd" d="M16.5548 2.29305C16.3672 2.10537 16.1127 1.99995 15.8474 2C15.582 2.00005 15.3275 2.10557 15.14 2.29332L4.79247 12.6533C4.60519 12.8408 4.5 13.0949 4.5 13.36V17C4.5 17.5523 4.94772 18 5.5 18H9.1586C9.42389 18 9.67831 17.8946 9.86586 17.707L20.2073 7.361C20.5976 6.97051 20.5976 6.33759 20.2073 5.9471L16.5548 2.29305ZM6.5 13.7738L15.8478 4.41479L18.0861 6.65405L8.74426 16H6.5V13.7738ZM3.5 22H21.5V20H3.5V22Z"/></svg>');
75
+ }
76
+ .fa.fa-trash {
77
+ background-image: url('data:image/svg+xml,<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill="%23249ff8" fill-rule="evenodd" clip-rule="evenodd" d="M9.6445 1C9.2793 1 8.94315 1.19908 8.76761 1.51932L7.40778 4H4.5H2V6H3.5V22C3.5 22.5523 3.94772 23 4.5 23H19.5C20.0523 23 20.5 22.5523 20.5 22V6H22V4H19.5H16.598L15.2695 1.5268C15.0952 1.20239 14.7568 1 14.3885 1H9.6445ZM14.3277 4L13.7906 3H10.2367L9.68856 4H14.3277ZM8 6H5.5V21H18.5V6H16H8ZM9 16.5V10H11V16.5H9ZM13 10V16.5H15V10H13Z"/></svg>');
78
+ }
79
+ </style>
62
80
  {% endblock %}
63
81
 
64
82
  {% block content %}