django-unfold 0.60.0__py3-none-any.whl → 0.62.0__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 (46) hide show
  1. {django_unfold-0.60.0.dist-info → django_unfold-0.62.0.dist-info}/METADATA +15 -6
  2. {django_unfold-0.60.0.dist-info → django_unfold-0.62.0.dist-info}/RECORD +46 -43
  3. unfold/admin.py +1 -1
  4. unfold/contrib/forms/widgets.py +12 -1
  5. unfold/contrib/import_export/templates/admin/import_export/change_list_import.html +5 -0
  6. unfold/contrib/simple_history/templates/simple_history/submit_line.html +16 -18
  7. unfold/forms.py +2 -2
  8. unfold/mixins/base_model_admin.py +7 -2
  9. unfold/sites.py +15 -2
  10. unfold/static/unfold/css/styles.css +1 -1
  11. unfold/static/unfold/js/app.js +61 -0
  12. unfold/styles.css +5 -8
  13. unfold/templates/admin/auth/user/add_form.html +1 -5
  14. unfold/templates/admin/base.html +1 -1
  15. unfold/templates/admin/change_form.html +8 -6
  16. unfold/templates/admin/change_list.html +4 -2
  17. unfold/templates/admin/change_list_results.html +3 -3
  18. unfold/templates/admin/edit_inline/stacked.html +10 -4
  19. unfold/templates/admin/edit_inline/tabular.html +4 -4
  20. unfold/templates/admin/includes/fieldset.html +9 -3
  21. unfold/templates/admin/search_form.html +14 -5
  22. unfold/templates/admin/submit_line.html +1 -1
  23. unfold/templates/unfold/components/card.html +4 -4
  24. unfold/templates/unfold/helpers/add_link.html +3 -1
  25. unfold/templates/unfold/helpers/fieldsets_tabs.html +3 -3
  26. unfold/templates/unfold/helpers/help_text.html +1 -1
  27. unfold/templates/unfold/helpers/messages.html +4 -4
  28. unfold/templates/unfold/helpers/navigation_header.html +2 -2
  29. unfold/templates/unfold/helpers/pagination.html +1 -1
  30. unfold/templates/unfold/helpers/popup_header.html +27 -0
  31. unfold/templates/unfold/helpers/search.html +16 -12
  32. unfold/templates/unfold/helpers/search_results.html +10 -9
  33. unfold/templates/unfold/helpers/shortcut.html +3 -0
  34. unfold/templates/unfold/helpers/site_branding.html +2 -2
  35. unfold/templates/unfold/helpers/tab_action.html +4 -3
  36. unfold/templates/unfold/helpers/tab_actions.html +1 -1
  37. unfold/templates/unfold/helpers/tab_list.html +1 -1
  38. unfold/templates/unfold/widgets/text.html +1 -1
  39. unfold/templates/unfold_crispy/field.html +12 -10
  40. unfold/templates/unfold_crispy/layout/checkbox.html +20 -4
  41. unfold/templates/unfold_crispy/layout/fieldset.html +3 -3
  42. unfold/templatetags/unfold.py +3 -4
  43. unfold/templatetags/unfold_list.py +4 -1
  44. unfold/widgets.py +2 -1
  45. {django_unfold-0.60.0.dist-info → django_unfold-0.62.0.dist-info}/LICENSE.md +0 -0
  46. {django_unfold-0.60.0.dist-info → django_unfold-0.62.0.dist-info}/WHEEL +0 -0
@@ -25,6 +25,67 @@ const sortRecords = (e) => {
25
25
  });
26
26
  };
27
27
 
28
+ /*************************************************************
29
+ * Search form
30
+ *************************************************************/
31
+ function searchForm() {
32
+ return {
33
+ applyShortcut(event) {
34
+ if (
35
+ event.key === "/" &&
36
+ document.activeElement.tagName.toLowerCase() !== "input" &&
37
+ document.activeElement.tagName.toLowerCase() !== "textarea" &&
38
+ !document.activeElement.isContentEditable
39
+ ) {
40
+ event.preventDefault();
41
+ this.$refs.searchInput.focus();
42
+ }
43
+ },
44
+ };
45
+ }
46
+
47
+ /*************************************************************
48
+ * Search dropdown
49
+ *************************************************************/
50
+ function searchDropdown() {
51
+ return {
52
+ openSearchResults: true,
53
+ currentIndex: 0,
54
+ applyShortcut(event) {
55
+ if (
56
+ event.key === "t" &&
57
+ document.activeElement.tagName.toLowerCase() !== "input" &&
58
+ document.activeElement.tagName.toLowerCase() !== "textarea" &&
59
+ !document.activeElement.isContentEditable
60
+ ) {
61
+ event.preventDefault();
62
+ this.$refs.searchInput.focus();
63
+ }
64
+ },
65
+ nextItem() {
66
+ if (this.currentIndex < this.maxItem()) {
67
+ this.currentIndex++;
68
+ }
69
+ },
70
+ prevItem() {
71
+ if (this.currentIndex > 0) {
72
+ this.currentIndex--;
73
+ }
74
+ },
75
+ maxItem() {
76
+ return document.getElementById("search-results").querySelectorAll("li")
77
+ .length;
78
+ },
79
+ selectItem() {
80
+ const items = document
81
+ .getElementById("search-results")
82
+ .querySelectorAll("li");
83
+
84
+ window.location = items[this.currentIndex - 1].querySelector("a").href;
85
+ },
86
+ };
87
+ }
88
+
28
89
  /*************************************************************
29
90
  * Warn without saving
30
91
  *************************************************************/
unfold/styles.css CHANGED
@@ -35,6 +35,8 @@
35
35
 
36
36
  @theme {
37
37
  --font-sans: 'Inter', sans-serif;
38
+ --shadow-raised: 0 2px 12px rgb(var(--color-base-300));
39
+ --shadow-raised-dark: 0 2px 12px rgb(var(--color-base-700));
38
40
  }
39
41
 
40
42
  @theme inline{
@@ -338,10 +340,6 @@ td .inline-deletelink {
338
340
  @apply block lg:mt-2.5;
339
341
  }
340
342
 
341
- h3 span:nth-child(3) {
342
- @apply ml-auto;
343
- }
344
-
345
343
  /*******************************************************
346
344
  Autocomplete
347
345
  *******************************************************/
@@ -380,7 +378,7 @@ h3 span:nth-child(3) {
380
378
 
381
379
  .select2-container.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__clear:after,
382
380
  .select2-container.select2-container--admin-autocomplete .select2-selection--single .select2-selection__clear:after {
383
- @apply material-symbols-outlined transition-all content-['close'] text-[18px] ;
381
+ @apply material-symbols-outlined transition-all content-['close\_small'] text-[18px] ;
384
382
  }
385
383
 
386
384
  .select2-container.select2-container--admin-autocomplete .select2-selection--single .select2-selection__arrow {
@@ -448,9 +446,8 @@ h3 span:nth-child(3) {
448
446
  }
449
447
 
450
448
  .select2-container--admin-autocomplete .select2-selection--multiple li.select2-selection__choice .select2-selection__choice__remove:after {
451
- @apply h-7 leading-7! material-symbols-outlined;
449
+ @apply content-['close\_small'] h-7 leading-7! material-symbols-outlined;
452
450
 
453
- content: "close";
454
451
  font-size: 14px;
455
452
  }
456
453
 
@@ -483,7 +480,7 @@ fieldset details > summary {
483
480
  }
484
481
 
485
482
  fieldset details > summary:after {
486
- @apply material-symbols-outlined absolute right-3 top-3.5;
483
+ @apply material-symbols-outlined absolute cursor-pointer right-3 top-3.5;
487
484
  content: "expand_more";
488
485
  }
489
486
 
@@ -3,10 +3,6 @@
3
3
 
4
4
  {% block form_top %}
5
5
  <p class="bg-blue-50 border-blue-200 mb-8 p-3 rounded-default text-blue-500 text-sm dark:bg-blue-500/20 dark:border-blue-500/10">
6
- {% if not is_popup %}
7
- {% translate 'First, enter a username and password. Then, you’ll be able to edit more user options.' %}
8
- {% else %}
9
- {% translate "Enter a username and password." %}
10
- {% endif %}
6
+ {% translate "After you've created a user, you’ll be able to edit more user options." %}
11
7
  <p>
12
8
  {% endblock %}
@@ -38,7 +38,7 @@
38
38
  </div>
39
39
  {% endblock messages %}
40
40
 
41
- <div class="px-4 pb-4 grow">
41
+ <div class="@container px-4 pb-4 grow">
42
42
  <div id="content" class="{% if not cl.model_admin.list_fullwidth %}container{% endif %} mx-auto {% block coltype %}colM{% endblock %}">
43
43
  {% if cl %}
44
44
  {% tab_list "changelist" cl.opts %}
@@ -59,13 +59,15 @@
59
59
 
60
60
  {% block content %}
61
61
  <div id="content-main">
62
+ {% include "unfold/helpers/popup_header.html" %}
63
+
62
64
  {% block form_before %}{% endblock %}
63
65
 
64
66
  {% if adminform.model_admin.change_form_outer_before_template %}
65
67
  {% include adminform.model_admin.change_form_outer_before_template %}
66
68
  {% endif %}
67
69
 
68
- <form {% if adminform.model_admin.conditional_fields %}x-data='{{ adminform|changeform_data }}'{% endif %} {% if has_file_field %}enctype="multipart/form-data" {% endif %}{% if form_url %}action="{{ form_url }}" {% endif %}method="post" id="{{ opts.model_name }}_form" {% if adminform.model_admin.warn_unsaved_form %}class="warn-unsaved-form"{% endif %} novalidate>
70
+ <form {% if adminform.model_admin.conditional_fields %}x-data='{{ adminform|changeform_data }}'{% endif %} {% if has_file_field %}enctype="multipart/form-data" {% endif %}{% if form_url %}action="{{ form_url }}"{% else %}x-bind:value="activeTab && activeTab !== 'general' ? '#' + activeTab : ''" {% endif %}method="post" id="{{ opts.model_name }}_form" {% if adminform.model_admin.warn_unsaved_form %}class="warn-unsaved-form"{% endif %} novalidate>
69
71
  {% csrf_token %}
70
72
 
71
73
  {% if adminform.model_admin.change_form_before_template %}
@@ -74,7 +76,7 @@
74
76
 
75
77
  {% block form_top %}{% endblock %}
76
78
 
77
- <div>
79
+ <div class="flex flex-col gap-8">
78
80
  {% if is_popup %}
79
81
  <input type="hidden" name="{{ is_popup_var }}" value="1">
80
82
  {% endif %}
@@ -108,16 +110,16 @@
108
110
 
109
111
  {% block after_related_objects %}{% endblock %}
110
112
 
111
- {% if adminform.model_admin.change_form_after_template %}
112
- {% include adminform.model_admin.change_form_after_template %}
113
- {% endif %}
114
-
115
113
  {% block admin_change_form_document_ready %}
116
114
  <script id="django-admin-form-add-constants" src="{% static 'admin/js/change_form.js' %}"{% if adminform and add %} data-model-name="{{ opts.model_name }}"{% endif %} async></script>
117
115
  {% endblock %}
118
116
 
119
117
  {% prepopulated_fields_js %}
120
118
  </div>
119
+
120
+ {% if adminform.model_admin.change_form_after_template %}
121
+ {% include adminform.model_admin.change_form_after_template %}
122
+ {% endif %}
121
123
  </form>
122
124
 
123
125
  {% if adminform.model_admin.change_form_outer_after_template %}
@@ -55,6 +55,8 @@
55
55
 
56
56
  {% block content %}
57
57
  <div id="content-main" x-data="{ filterOpen: false }">
58
+ {% include "unfold/helpers/popup_header.html" %}
59
+
58
60
  {% if cl.formset and cl.formset.errors %}
59
61
  {% include "unfold/helpers/messages/errornote.html" with errors=cl.formset.errors %}
60
62
 
@@ -70,7 +72,7 @@
70
72
  {% endif %}
71
73
  {% endblock %}
72
74
 
73
- {% if cl.model_admin.list_before_template %}
75
+ {% if cl.model_admin.list_before_template and not is_popup %}
74
76
  {% include cl.model_admin.list_before_template %}
75
77
  {% endif %}
76
78
 
@@ -106,7 +108,7 @@
106
108
  {% endblock %}
107
109
  </form>
108
110
 
109
- {% if cl.model_admin.list_after_template %}
111
+ {% if cl.model_admin.list_after_template and not is_popup %}
110
112
  {% include cl.model_admin.list_after_template %}
111
113
  {% endif %}
112
114
  </div>
@@ -70,7 +70,7 @@
70
70
  </thead>
71
71
 
72
72
  {% for result in results %}
73
- <tbody class="block lg:table-row-group" x-data="{rowOpen: false}">
73
+ <tbody class="block relative lg:table-row-group lg:hover:shadow-raised lg:dark:hover:shadow-raised-dark lg:hover:z-20 {% cycle '' 'bg-base-50 dark:bg-white/[.02]' %}" x-data="{rowOpen: false}">
74
74
  {% if result.form and result.form.non_field_errors %}
75
75
  <tr>
76
76
  <td class="text-left" colspan="{{ result|length }}">
@@ -79,7 +79,7 @@
79
79
  </tr>
80
80
  {% endif %}
81
81
 
82
- <tr class="{% cycle '' 'bg-base-50 dark:bg-white/[.02]' %} block border border-base-200 mb-3 rounded-default shadow-xs lg:table-row lg:border-none lg:mb-0 lg:shadow-none dark:border-base-800">
82
+ <tr class="block border border-base-200 mb-3 relative rounded-default shadow-xs lg:table-row lg:border-none lg:mb-0 lg:rounded-none lg:shadow-none dark:border-base-800">
83
83
  {% if cl.model_admin.list_sections|length > 0 %}
84
84
  <td class="align-middle cursor-pointer flex border-b border-base-200 font-normal px-2.5 py-2 relative text-left before:font-semibold before:text-font-important-light before:block before:capitalize before:content-[attr(data-label)] before:mr-auto lg:before:hidden lg:border-b-0 lg:border-t lg:pl-3 lg:pr-0 lg:py-3 lg:table-cell dark:border-base-800 dark:lg:border-base-800 dark:before:text-font-important-dark lg:w-px"
85
85
  data-label="{% trans "Expand row" %}"
@@ -99,7 +99,7 @@
99
99
  </tr>
100
100
 
101
101
  {% if cl.model_admin.list_sections|length > 0 %}
102
- <tr class="block mb-3 lg:table-row" x-show="rowOpen">
102
+ <tr class="block mb-3 relative z-30 lg:table-row" x-show="rowOpen">
103
103
  <td colspan="{{ result|length|add:2 }}" class="border bg-base-200/10 block border-base-200 relative rounded-default p-3 lg:shadow-inner lg:border-0 lg:border-t lg:rounded-none lg:table-cell dark:border-base-800">
104
104
  <div class="absolute bg-primary-600 h-full hidden left-0 top-0 w-0.5 lg:block"></div>
105
105
 
@@ -4,7 +4,7 @@
4
4
  <fieldset class="module relative {{ inline_admin_formset.classes }}" aria-labelledby="{{ inline_admin_formset.formset.prefix }}-heading">
5
5
  {% if inline_admin_formset.is_collapsible %}<details><summary>{% endif %}
6
6
 
7
- <h2 id="{{ inline_admin_formset.formset.prefix }}-heading" class="inline-heading bg-base-100 font-semibold mb-6 px-4 py-3 rounded-default text-font-important-light 2xl:-mx-4 dark:bg-white/[.02] dark:text-font-important-dark {% if inline_admin_formset.opts.tab %}hidden{% endif %} {% if inline_admin_formset.is_collapsible %} cursor-pointer{% endif %}">
7
+ <h2 id="{{ inline_admin_formset.formset.prefix }}-heading" class="inline-heading bg-base-100 font-semibold mb-6 px-4 py-3 rounded-default text-font-important-light @min-[1570px]:-mx-4 dark:bg-white/[.02] dark:text-font-important-dark {% if inline_admin_formset.opts.tab %}hidden{% endif %} {% if inline_admin_formset.is_collapsible %} cursor-pointer{% endif %}">
8
8
  {% if inline_admin_formset.formset.max_num == 1 %}
9
9
  {{ inline_admin_formset.opts.verbose_name|capfirst }}
10
10
  {% else %}
@@ -17,7 +17,7 @@
17
17
  {{ inline_admin_formset.formset.management_form }}
18
18
  {% include "unfold/helpers/messages/error.html" with errors=inline_admin_formset.formset.non_form_errors %}
19
19
 
20
- <div class="border border-base-200 mb-6 overflow-hidden rounded-default shadow-xs w-full dark:border-base-800"
20
+ <div class="border border-base-200 overflow-hidden rounded-default shadow-xs w-full dark:border-base-800"
21
21
  {% if inline_admin_formset.opts.ordering_field %}
22
22
  data-ordering-field="{{ inline_admin_formset.opts.ordering_field }}" x-on:end="sortRecords" x-sort.ghost
23
23
  {% endif %}>
@@ -26,6 +26,12 @@
26
26
  <div x-sort:item class="inline-related group inline-stacked {% if inline_admin_form.original or inline_admin_form.show_url %} has_original{% endif %}{% if forloop.last and inline_admin_formset.has_add_permission %} empty-form last-related{% endif %}" id="{{ inline_admin_formset.formset.prefix }}-{% if not forloop.last %}{{ forloop.counter0 }}{% else %}empty{% endif %}" {% if inline_admin_formset.opts.collapsible and inline_admin_form.original %}x-data="{ open: {% if inline_admin_form.errors %}true{% else %}false{% endif %} }"{% endif %}>
27
27
  {% if not inline_admin_formset.opts.hide_title or inline_admin_formset.formset.can_delete and inline_admin_formset.has_delete_permission %}
28
28
  <h3 class="border-b border-base-200 flex font-medium items-center gap-2 px-3 py-2 text-sm dark:border-base-800 {% if inline_admin_formset.opts.collapsible and inline_admin_form.original %}cursor-pointer{% endif %}" {% if inline_admin_formset.opts.collapsible and inline_admin_form.original %}x-on:click="open = !open"{% endif %}>
29
+ {% if inline_admin_formset.opts.collapsible and inline_admin_form.original %}
30
+ <span class="material-symbols-outlined select-none block! -rotate-90 transition-all" x-bind:class="open && 'rotate-0'">
31
+ expand_more
32
+ </span>
33
+ {% endif %}
34
+
29
35
  {% if inline_admin_formset.opts.ordering_field %}
30
36
  {% if inline_admin_form.original %}
31
37
  <span class="material-symbols-outlined cursor-pointer" x-sort:handle>drag_indicator</span>
@@ -99,8 +105,8 @@
99
105
  {% endfor %}
100
106
  </div>
101
107
 
108
+ {% include "unfold/helpers/pagination_inline.html" %}
109
+
102
110
  {% if inline_admin_formset.is_collapsible %}</details>{% endif %}
103
111
  </fieldset>
104
-
105
- {% include "unfold/helpers/pagination_inline.html" %}
106
112
  </div>
@@ -7,7 +7,7 @@
7
7
  <fieldset class="module relative {{ inline_admin_formset.classes }} min-w-0" aria-labelledby="{{ inline_admin_formset.formset.prefix }}-heading">
8
8
  {% if inline_admin_formset.is_collapsible %}<details><summary>{% endif %}
9
9
 
10
- <h2 id="{{ inline_admin_formset.formset.prefix }}-heading" class="bg-base-100 border border-transparent font-semibold mb-6 px-4 py-3 rounded-default text-font-important-light text-sm 2xl:-mx-4 dark:bg-white/[.02] dark:text-font-important-dark {% if inline_admin_formset.opts.tab %}hidden{% endif %} {% if inline_admin_formset.is_collapsible %} cursor-pointer{% endif %}">
10
+ <h2 id="{{ inline_admin_formset.formset.prefix }}-heading" class="bg-base-100 border border-transparent font-semibold mb-6 px-4 py-3 rounded-default text-font-important-light text-sm @min-[1570px]:-mx-4 dark:bg-white/[.02] dark:text-font-important-dark {% if inline_admin_formset.opts.tab %}hidden{% endif %} {% if inline_admin_formset.is_collapsible %} cursor-pointer{% endif %}">
11
11
  {% if inline_admin_formset.formset.max_num == 1 %}
12
12
  {{ inline_admin_formset.opts.verbose_name|capfirst }}
13
13
  {% else %}
@@ -18,7 +18,7 @@
18
18
  {% if inline_admin_formset.is_collapsible %}</summary>{% endif %}
19
19
 
20
20
  {{ inline_admin_formset.formset.non_form_errors }}
21
- <div class="border border-base-200 mb-6 overflow-x-auto rounded-default shadow-xs dark:border-base-800" data-simplebar data-simplebar-auto-hide="false">
21
+ <div class="border border-base-200 overflow-x-auto rounded-default shadow-xs dark:border-base-800" data-simplebar data-simplebar-auto-hide="false">
22
22
  <table class="tabular-table w-full [&>tbody:nth-child(odd)]:bg-base-50 dark:[&>tbody:nth-child(odd)]:bg-white/[.02]" {% if inline_admin_formset.opts.ordering_field %}data-ordering-field="{{ inline_admin_formset.opts.ordering_field }}" x-on:end="sortRecords" x-sort.ghost x-sort:config="{preventOnFilter: false}"{% endif %}>
23
23
  {% include "unfold/helpers/edit_inline/tabular_heading.html" %}
24
24
 
@@ -34,9 +34,9 @@
34
34
  </table>
35
35
  </div>
36
36
 
37
+ {% include "unfold/helpers/pagination_inline.html" %}
38
+
37
39
  {% if inline_admin_formset.is_collapsible %}</details>{% endif %}
38
40
  </fieldset>
39
-
40
- {% include "unfold/helpers/pagination_inline.html" %}
41
41
  </div>
42
42
  </div>
@@ -1,18 +1,22 @@
1
1
  {% load unfold %}
2
2
 
3
- <fieldset class="module{% if fieldset.classes %} {{ fieldset.classes }}{% endif %}" {% if stacked != 1 %}x-show="activeTab == 'general'"{% endif %}>
3
+ <fieldset class="module relative {% if fieldset.classes %} {{ fieldset.classes }}{% endif %}" {% if stacked != 1 %}x-show="activeTab == 'general'"{% endif %}>
4
+ {% if fieldset.is_collapsible %}<details><summary>{% endif %}
5
+
4
6
  {% if fieldset.name and "tab" not in fieldset.classes %}
5
7
  {% if stacked == 1 %}
6
- <h2 class="border-b border-base-200 border-t border-dashed font-semibold text-font-important-light px-3 py-4.5 dark:text-font-important-dark dark:border-base-800">
8
+ <h2 class="border-b border-base-200 border-t border-dashed font-semibold text-font-important-light px-3 py-4.5 dark:text-font-important-dark dark:border-base-800 {% if fieldset.is_collapsible %}cursor-pointer{% endif %}">
7
9
  {{ fieldset.name }}
8
10
  </h2>
9
11
  {% else %}
10
- <h2 class="bg-base-100 font-semibold mb-6 px-4 py-3 rounded-default text-font-important-light text-sm 2xl:-mx-4 dark:bg-white/[.02] dark:text-font-important-dark">
12
+ <h2 class="bg-base-100 font-semibold mb-6 px-4 py-3 rounded-default text-font-important-light text-sm 2xl:-mx-4 dark:bg-white/[.02] dark:text-font-important-dark {% if fieldset.is_collapsible %}cursor-pointer{% endif %}">
11
13
  {{ fieldset.name }}
12
14
  </h2>
13
15
  {% endif %}
14
16
  {% endif %}
15
17
 
18
+ {% if fieldset.is_collapsible %}</summary>{% endif %}
19
+
16
20
  {% if fieldset.description %}
17
21
  <div class="leading-relaxed mb-4 max-w-4xl text-sm">
18
22
  {{ fieldset.description|safe }}
@@ -24,4 +28,6 @@
24
28
  {% include "unfold/helpers/fieldset_row.html" %}
25
29
  {% endfor %}
26
30
  </div>
31
+
32
+ {% if fieldset.name and fieldset.is_collapsible %}</details>{% endif %}
27
33
  </fieldset>
@@ -2,13 +2,22 @@
2
2
 
3
3
  {% if cl.search_fields %}
4
4
  <div id="toolbar">
5
- <form id="changelist-search" method="get" role="search">
6
- <div class="bg-white border border-base-200 flex rounded-default overflow-hidden shadow-xs lg:w-96 focus-within:outline-2 focus-within:-outline-offset-2 focus-within:outline-primary-600 dark:bg-base-900 dark:border-base-700">
7
- <input class="font-medium grow min-w-0 h-9 px-3 text-font-default-light text-sm focus:outline-hidden dark:bg-base-900 dark:text-font-default-dark placeholder-shown:truncate placeholder-base-400" type="text" name="{{ search_var }}" value="{{ cl.query }}" id="searchbar" placeholder="{% if cl.search_help_text %}{{ cl.search_help_text }}{% else %}{% trans "Type to search" %}{% endif %}" />
8
-
9
- <button type="submit" class="flex items-center px-2 focus:outline-hidden" id="searchbar-submit">
5
+ <form id="changelist-search" method="get" role="search" x-data="searchForm()">
6
+ <div class="bg-white border border-base-200 flex flex-row items-center px-3 rounded-default relative shadow-xs w-full focus-within:outline-2 focus-within:-outline-offset-2 focus-within:outline-primary-600 lg:w-96 dark:bg-base-900 dark:border-base-700">
7
+ <button type="submit" class="flex items-center focus:outline-hidden" id="searchbar-submit">
10
8
  <span class="material-symbols-outlined md-18 text-base-400 dark:text-base-500">search</span>
11
9
  </button>
10
+
11
+ <input type="text"
12
+ x-ref="searchInput"
13
+ x-on:keydown.window="applyShortcut($event)"
14
+ class="grow font-medium min-w-0 overflow-hidden p-2 placeholder-font-subtle-light truncate focus:outline-hidden dark:bg-base-900 dark:placeholder-font-subtle-dark dark:text-font-default-dark"
15
+ name="{{ search_var }}"
16
+ value="{{ cl.query }}"
17
+ id="searchbar"
18
+ placeholder="{% if cl.search_help_text %}{{ cl.search_help_text }}{% else %}{% trans "Type to search" %}{% endif %}" />
19
+
20
+ {% include "unfold/helpers/shortcut.html" with shortcut="/" %}
12
21
  </div>
13
22
 
14
23
  {% for pair in cl.filter_params.items %}
@@ -1,7 +1,7 @@
1
1
  {% load i18n admin_urls %}
2
2
 
3
3
  <div {% if not is_popup %}id="submit-row"{% endif %} class="relative lg:sticky lg:bottom-0 z-40">
4
- <div class="backdrop-blur-xs bg-white/80 rounded-b-default pb-4 px-4 dark:bg-base-900/80 {% if not is_popup %}lg:border-t lg:border-base-200 relative lg:scrollable-top lg:py-0 dark:border-base-800{% endif %}">
4
+ <div class="backdrop-blur-xs bg-white/80 rounded-b-default pb-4 px-4 dark:bg-base-900/80 lg:border-t lg:border-base-200 relative lg:scrollable-top lg:py-0 dark:border-base-800">
5
5
  <div class="flex flex-col-reverse gap-3 items-center mx-auto lg:flex-row-reverse container lg:h-[64px]">
6
6
  {% block submit-row %}
7
7
  {% if show_save %}
@@ -5,7 +5,7 @@
5
5
  </h2>
6
6
  {% endif %}
7
7
 
8
- <span class="grow relative {% if icon %} pl-6{% endif %}">
8
+ <div class="grow relative {% if icon %} pl-6{% endif %}">
9
9
  {{ children }}
10
10
 
11
11
  {% if label %}
@@ -17,11 +17,11 @@
17
17
  {% if icon %}
18
18
  <span class="material-symbols-outlined absolute -left-6 text-base-300 top-1/2 -translate-x-1/3 -translate-y-1/2 text-6xl! dark:text-base-500">{{ icon }}</span>
19
19
  {% endif %}
20
- </span>
20
+ </div>
21
21
 
22
22
  {% if footer %}
23
- <span class="border-t border-base-200 flex items-center -mb-6 -mx-6 mt-6 pb-2 pt-2 px-6 text-sm dark:border-base-800">
23
+ <div class="border-t border-base-200 flex items-center -mb-6 -mx-6 mt-6 pb-2 pt-2 px-6 text-sm dark:border-base-800">
24
24
  {{ footer }}
25
- </span>
25
+ </div>
26
26
  {% endif %}
27
27
  </{% if href %}a{% else %}div{% endif %}>
@@ -10,7 +10,9 @@
10
10
 
11
11
  {% if add_url %}
12
12
  <div class="flex flex-row items-center">
13
- <span class="block bg-base-200 h-5 mx-4 w-px dark:bg-base-700"></span>
13
+ {% if not hide_separator %}
14
+ <span class="block bg-base-200 h-5 mx-4 w-px dark:bg-base-700"></span>
15
+ {% endif %}
14
16
 
15
17
  <a href="{% add_preserved_filters add_url is_popup to_field %}" class="addlink bg-primary-600 flex items-center h-9 justify-center -my-1 rounded-full w-9" title="{{ title }}">
16
18
  <span class="material-symbols-outlined text-white">add</span>
@@ -3,12 +3,12 @@
3
3
  {% with tabs=adminform|tabs %}
4
4
  {% if tabs %}
5
5
  <div x-data="{openTab: null}" x-show="activeTab == 'general'">
6
- <ul class="bg-base-100 flex gap-10 mb-6 px-4 py-3 rounded-default text-font-default-light 2xl:-mx-4 dark:bg-white/[.02] dark:text-font-default-dark">
6
+ <ul class="bg-base-100 flex gap-1 mb-6 px-1.5 py-1.5 rounded-default text-font-default-light @min-[1570px]:-mx-4 dark:bg-white/[.02] dark:text-font-default-dark">
7
7
  {% for fieldset in tabs %}
8
8
  <li>
9
- <a class="cursor-pointer font-semibold hover:text-base-700 dark:hover:text-white"
9
+ <a class="block cursor-pointer font-semibold px-2.5 py-2 rounded-default hover:text-base-700 dark:hover:text-white"
10
10
  x-on:click="openTab = '{{ forloop.counter0 }}-{{ fieldset.name|slugify }}'"
11
- x-bind:class="openTab == '{{ forloop.counter0 }}-{{ fieldset.name|slugify }}'{% if forloop.first %} || openTab == null{% endif %} ? 'text-font-important-light dark:text-font-important-dark' : ''">
11
+ x-bind:class="openTab == '{{ forloop.counter0 }}-{{ fieldset.name|slugify }}'{% if forloop.first %} || openTab == null{% endif %} ? 'bg-white text-font-important-light shadow-xs dark:bg-base-900 dark:text-font-important-dark' : ''">
12
12
  {{ fieldset.name }}
13
13
  </a>
14
14
  </li>
@@ -1,5 +1,5 @@
1
1
  {% if help_text %}
2
2
  <div class="leading-relaxed mt-2 text-xs">
3
- {{ help_text }}
3
+ {{ help_text|safe }}
4
4
  </div>
5
5
  {% endif %}
@@ -2,13 +2,13 @@
2
2
  <ul class="flex flex-col gap-4 mb-8">
3
3
  {% for message in messages %}
4
4
  <li class="*:mb-0!">
5
- {% if message.tags == 'info' %}
5
+ {% if message.level == DEFAULT_MESSAGE_LEVELS.INFO %}
6
6
  {% include "unfold/helpers/messages/info.html" with message=message %}
7
- {% elif message.tags == 'success' %}
7
+ {% elif message.level == DEFAULT_MESSAGE_LEVELS.SUCCESS %}
8
8
  {% include "unfold/helpers/messages/success.html" with message=message %}
9
- {% elif message.tags == 'warning' %}
9
+ {% elif message.level == DEFAULT_MESSAGE_LEVELS.WARNING %}
10
10
  {% include "unfold/helpers/messages/warning.html" with message=message %}
11
- {% elif message.tags == 'error' %}
11
+ {% elif message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}
12
12
  {% include "unfold/helpers/messages/error.html" with message=message %}
13
13
  {% else %}
14
14
  {% include "unfold/helpers/messages/debug.html" with message=message %}
@@ -1,10 +1,10 @@
1
1
  {% load unfold %}
2
2
 
3
3
  <div class="border-b border-base-200 flex gap-3 items-center h-[65px] mb-5 dark:border-base-800 px-3 {% element_classes 'navigation_header' %}" {% if site_dropdown %}x-data="{ openDropdown: false }"{% endif %}>
4
- <div class="bg-transparent border border-transparent flex font-semibold gap-3 grow min-w-0 -mx-px h-[54px] items-center px-3 {% if site_dropdown %}cursor-pointer rounded-default transition-all hover:bg-white hover:border-base-200 hover:shadow-xs dark:hover:bg-base-800 dark:hover:border-base-700{% endif %}"
4
+ <div class="bg-transparent flex font-semibold gap-3 grow min-w-0 -mx-px h-[54px] items-center px-3 {% if site_dropdown %}cursor-pointer rounded-default transition-all hover:bg-base-100 dark:hover:bg-white/[.06]{% endif %}"
5
5
  {% if site_dropdown %}
6
6
  x-on:click="openDropdown = !openDropdown"
7
- x-bind:class="{'bg-white border-base-200 shadow-xs dark:bg-base-800 dark:border-base-700': openDropdown, 'bg-transparent border-transparent': !openDropdown}"
7
+ x-bind:class="{'bg-base-100 dark:bg-white/[.06]': openDropdown, 'bg-transparent': !openDropdown}"
8
8
  {% endif %}
9
9
  >
10
10
  {% if site_logo %}
@@ -1,7 +1,7 @@
1
1
  {% load admin_list unfold %}
2
2
 
3
3
  {% if cl %}
4
- <div {% if not is_popup %}class="px-4 lg:backdrop-blur-xs lg:bg-white/80 lg:flex lg:items-center lg:dark:bg-base-900/80 lg:left-0 lg:right-0 lg:bottom-0 lg:sticky relative z-40 {% if not is_popup %}lg:border-t lg:border-base-200 lg:relative lg:scrollable-top lg:dark:border-base-800{% endif %} {% element_classes 'pagination' %}"{% endif %}>
4
+ <div class="px-4 lg:backdrop-blur-xs lg:bg-white/80 lg:flex lg:items-center lg:dark:bg-base-900/80 lg:left-0 lg:right-0 lg:bottom-0 lg:sticky relative z-40 lg:border-t lg:border-base-200 lg:relative lg:scrollable-top lg:dark:border-base-800 {% element_classes 'pagination' %}">
5
5
  {% pagination cl %}
6
6
  </div>
7
7
  {% endif %}
@@ -0,0 +1,27 @@
1
+ {% load i18n admin_urls unfold %}
2
+
3
+ {% if is_popup %}
4
+ <div class="flex flex-row items-center">
5
+ <h1 class="font-semibold overflow-hidden my-6 text-ellipsis whitespace-nowrap text-base text-font-important-light dark:text-font-important-dark">
6
+ <span class="tracking-tight">
7
+ {{ pretitle }}
8
+
9
+ {{ content_title }}
10
+ </span>
11
+
12
+ {% if cl and cl.full_result_count != cl.result_count and cl.paginator|class_name != "InfinitePaginator" %}
13
+ <span class="font-medium ml-2 text-font-subtle-light text-sm dark:text-font-subtle-dark">
14
+ {% blocktranslate count counter=cl.result_count %}{{ counter }} result{% plural %}{{ counter }} results{% endblocktranslate %} (<a href="?{% if cl.is_popup %}_popup=1{% endif %}">{% if cl.show_full_result_count %}{% blocktranslate with full_result_count=cl.full_result_count %}{{ full_result_count }} total{% endblocktranslate %}{% else %}{% translate "Show all" %}{% endif %}</a>)
15
+ </span>
16
+ {% endif %}
17
+
18
+ {% if content_subtitle %}
19
+ {{ content_subtitle }}
20
+ {% endif %}
21
+ </h1>
22
+
23
+ <div class="ml-auto">
24
+ {% include "unfold/helpers/add_link.html" with hide_separator=True %}
25
+ </div>
26
+ </div>
27
+ {% endif %}
@@ -1,24 +1,28 @@
1
1
  {% load i18n %}
2
2
 
3
3
  {% if sidebar_show_search %}
4
- <div class="mb-2.5 mx-3 relative" x-data="{openSearchResults: false}">
5
- <div class="bg-white border border-base-200 flex items-center overflow-hidden rounded-default shadow-xs focus-within:outline-2 focus-within:-outline-offset-2 focus-within:outline-primary-600 dark:bg-base-900 dark:border-base-700">
6
- <span class="material-symbols-outlined md-18 pl-3 text-base-400">manage_search</span>
4
+ <div class="mb-2.5 mx-3 relative" x-data="searchDropdown()" x-on:keydown.window="applyShortcut($event)" x-on:click.outside="openSearchResults = false">
5
+ <div class="bg-white border border-base-200 flex flex-row items-center px-3 rounded-default relative shadow-xs w-full focus-within:outline-2 focus-within:-outline-offset-2 focus-within:outline-primary-600 dark:bg-base-900 dark:border-base-700">
6
+ <span class="material-symbols-outlined md-18 text-base-400">manage_search</span>
7
7
 
8
8
  <input type="search"
9
9
  id="nav-filter"
10
10
  name="s"
11
- x-on:blur="setTimeout(function() {openSearchResults = false}, 200)"
12
- x-on:focus="openSearchResults=true"
11
+ x-ref="searchInput"
12
+ x-on:focus="openSearchResults = true; currentIndex = 0"
13
+ x-on:keydown.arrow-down.prevent="nextItem()"
14
+ x-on:keydown.arrow-up.prevent="prevItem()"
15
+ x-on:keydown.escape.prevent="openSearchResults = false; if ($refs.searchInput.value === '') { $refs.searchInput.blur() } else { $refs.searchInput.value = '' }"
16
+ x-on:keydown.enter.prevent="selectItem()"
17
+ x-on:search="currentIndex = 0"
13
18
  hx-get="{% url "admin:search" %}"
14
- hx-trigger="keyup changed delay:500ms, search"
19
+ hx-trigger="keyup changed delay:500ms"
15
20
  hx-target="#search-results"
16
- hx-indicator=".htmx-indicator"
17
- class="grow font-medium overflow-hidden pl-2 pr-3 py-2 text-font-default-light text-sm placeholder-base-400 focus:outline-hidden dark:bg-base-900 dark:text-font-default-dark"
18
- placeholder="{% translate 'Search apps and models...' %}" aria-label="{% translate 'Filter navigation items' %}" />
19
- <div class="absolute opacity-0 htmx-indicator mt-0.5 right-2 top-2">
20
- <span class="animate-spin material-symbols-outlined md-18 text-base-300">sync</span>
21
- </div>
21
+ class="grow font-medium min-w-0 overflow-hidden p-2 placeholder-font-subtle-light truncate focus:outline-hidden dark:bg-base-900 dark:placeholder-font-subtle-dark dark:text-font-default-dark"
22
+ placeholder="{% translate 'Search apps and models...' %}"
23
+ aria-label="{% translate 'Filter navigation items' %}">
24
+
25
+ {% include "unfold/helpers/shortcut.html" with shortcut="t" %}
22
26
  </div>
23
27
 
24
28
  <div id="search-results" x-show="openSearchResults"></div>
@@ -1,13 +1,14 @@
1
1
  {% if results %}
2
- <ul class="absolute bg-white border border-base-200 left-0 mt-12 right-0 rounded-default top-0 shadow-xs text-sm z-10 dark:bg-base-800 dark:border-base-700">
3
- {% for app in results %}
4
- {% for model in app.models %}
5
- <li>
6
- <a href="{{ model.admin_url }}" class="block px-3 py-2 truncate hover:text-base-700 dark:hover:text-base-200">
7
- {{ app.name }} <span class="align-text-top material-symbols-outlined md-18">arrow_right_alt</span> {{ model.name }}
8
- </a>
9
- </li>
10
- {% endfor %}
2
+ <ul class="absolute bg-white border border-base-200 flex flex-col leading-none left-0 mt-12 py-1 right-0 rounded-default top-0 shadow-xs text-sm z-10 dark:bg-base-800 dark:border-base-700">
3
+ {% for item in results %}
4
+ <li class="mx-1">
5
+ <a href="{{ item.model.admin_url }}"
6
+ class="block items-center px-3 py-2 rounded-default truncate"
7
+ x-on:mouseenter="currentIndex = {{ forloop.counter }}"
8
+ x-bind:class="{'bg-base-100 text-base-700 dark:bg-base-700 dark:text-base-200': currentIndex === {{ forloop.counter }}}">
9
+ {{ item.app.name }} <span class="text-font-subtle-light mx-1 dark:text-font-subtle-dark">/</span> {{ item.model.name }}
10
+ </a>
11
+ </li>
11
12
  {% endfor %}
12
13
  </ul>
13
14
  {% endif %}
@@ -0,0 +1,3 @@
1
+ <kbd class="bg-base-50 border border-base-200 font-mono text-xs text-font-subtle-light rounded-xs px-1 dark:bg-white/[.04] dark:border-base-700 dark:text-font-subtle-dark">
2
+ {{ shortcut }}
3
+ </kbd>
@@ -1,4 +1,4 @@
1
- <h1 id="site-name">
1
+ <div id="site-name">
2
2
  {% if site_dropdown %}
3
3
  {{ site_header|default:_('Django administration') }}
4
4
  {% else %}
@@ -6,4 +6,4 @@
6
6
  {{ site_header|default:_('Django administration') }}
7
7
  </a>
8
8
  {% endif %}
9
- </h1>
9
+ </div>