django-unfold 0.29.1__py3-none-any.whl → 0.31.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.
- {django_unfold-0.29.1.dist-info → django_unfold-0.31.0.dist-info}/METADATA +63 -19
- {django_unfold-0.29.1.dist-info → django_unfold-0.31.0.dist-info}/RECORD +74 -73
- unfold/admin.py +32 -11
- unfold/contrib/filters/templates/unfold/filters/filters_numeric_slider.html +3 -3
- unfold/contrib/forms/static/unfold/forms/js/trix.js +2 -2
- unfold/contrib/forms/templates/unfold/forms/array.html +3 -1
- unfold/contrib/forms/templates/unfold/forms/helpers/toolbar.html +6 -6
- unfold/contrib/forms/templates/unfold/forms/wysiwyg.html +1 -1
- unfold/contrib/forms/widgets.py +22 -11
- unfold/contrib/guardian/templates/unfold/guardian/group_form.html +4 -4
- unfold/contrib/guardian/templates/unfold/guardian/user_form.html +4 -4
- unfold/contrib/import_export/templates/admin/import_export/change_form.html +1 -1
- unfold/contrib/import_export/templates/admin/import_export/import_errors.html +1 -1
- unfold/contrib/import_export/templates/admin/import_export/import_preview.html +3 -3
- unfold/contrib/import_export/templates/admin/import_export/import_validation.html +4 -4
- unfold/contrib/inlines/forms.py +1 -2
- unfold/contrib/simple_history/templates/simple_history/object_history_list.html +9 -9
- unfold/contrib/simple_history/templates/simple_history/submit_line.html +1 -1
- unfold/dataclasses.py +10 -1
- unfold/fields.py +2 -2
- unfold/forms.py +18 -3
- unfold/settings.py +1 -0
- unfold/sites.py +39 -15
- unfold/static/unfold/css/styles.css +1 -1
- unfold/static/unfold/js/alpine.anchor.js +1 -0
- unfold/static/unfold/js/alpine.js +2 -2
- unfold/static/unfold/js/alpine.persist.js +1 -1
- unfold/static/unfold/js/app.js +45 -3
- unfold/styles.css +15 -11
- unfold/templates/admin/actions.html +1 -1
- unfold/templates/admin/app_list.html +1 -1
- unfold/templates/admin/base.html +4 -4
- unfold/templates/admin/change_list.html +2 -2
- unfold/templates/admin/change_list_results.html +3 -3
- unfold/templates/admin/delete_confirmation.html +4 -4
- unfold/templates/admin/delete_selected_confirmation.html +4 -4
- unfold/templates/admin/edit_inline/stacked.html +2 -2
- unfold/templates/admin/edit_inline/tabular.html +4 -4
- unfold/templates/admin/filter.html +2 -2
- unfold/templates/admin/includes/fieldset.html +1 -1
- unfold/templates/admin/includes/object_delete_summary.html +1 -1
- unfold/templates/admin/login.html +8 -8
- unfold/templates/admin/object_history.html +4 -4
- unfold/templates/admin/search_form.html +1 -1
- unfold/templates/admin/submit_line.html +7 -5
- unfold/templates/auth/widgets/read_only_password_hash.html +1 -1
- unfold/templates/registration/logged_out.html +1 -1
- unfold/templates/unfold/change_list_filter.html +10 -2
- unfold/templates/unfold/helpers/account_links.html +2 -2
- unfold/templates/unfold/helpers/actions_row.html +4 -4
- unfold/templates/unfold/helpers/app_list.html +48 -38
- unfold/templates/unfold/helpers/app_list_default.html +4 -4
- unfold/templates/unfold/helpers/breadcrumb_item.html +1 -1
- unfold/templates/unfold/helpers/field_readonly_value.html +1 -1
- unfold/templates/unfold/helpers/fieldset_row.html +7 -7
- unfold/templates/unfold/helpers/fieldsets_tabs.html +2 -2
- unfold/templates/unfold/helpers/header.html +1 -1
- unfold/templates/unfold/helpers/help_text.html +1 -1
- unfold/templates/unfold/helpers/history.html +1 -1
- unfold/templates/unfold/helpers/label.html +1 -1
- unfold/templates/unfold/helpers/search.html +7 -4
- unfold/templates/unfold/helpers/search_results.html +2 -2
- unfold/templates/unfold/helpers/tab_action.html +1 -1
- unfold/templates/unfold/helpers/tab_list.html +27 -5
- unfold/templates/unfold/helpers/theme_switch.html +2 -2
- unfold/templates/unfold/layouts/skeleton.html +6 -1
- unfold/templates/unfold/widgets/clearable_file_input.html +14 -6
- unfold/templates/unfold/widgets/clearable_file_input_small.html +4 -4
- unfold/templates/unfold/widgets/split_datetime.html +2 -2
- unfold/templatetags/unfold.py +33 -12
- unfold/templatetags/unfold_list.py +16 -6
- unfold/widgets.py +11 -4
- {django_unfold-0.29.1.dist-info → django_unfold-0.31.0.dist-info}/LICENSE.md +0 -0
- {django_unfold-0.29.1.dist-info → django_unfold-0.31.0.dist-info}/WHEEL +0 -0
@@ -1,17 +1,39 @@
|
|
1
|
+
{% load i18n %}
|
2
|
+
|
1
3
|
{% if not is_popup %}
|
2
|
-
{% if
|
3
|
-
<div class="flex items-start flex-col mb-4 text-gray-500 text-sm w-full md:border-b dark:md:border-gray-800 md:border-l-0 md:flex-row md:items-center md:justify-end dark:text-gray-
|
4
|
-
{% if
|
4
|
+
{% if tabs_list or inlines_list or actions_list or actions_detail or actions_items or nav_global %}
|
5
|
+
<div class="flex items-start flex-col mb-4 text-gray-500 text-sm w-full md:border-b dark:md:border-gray-800 md:border-l-0 md:flex-row md:items-center md:justify-end dark:text-gray-300">
|
6
|
+
{% if inlines_list or tabs_list %}
|
5
7
|
<ul class="border rounded-md flex flex-col w-full md:flex-row md:border-b-0 md:border-t-0 md:border-l-0 md:border-r-0 dark:border-gray-800">
|
6
|
-
{% for item in
|
8
|
+
{% for item in tabs_list %}
|
7
9
|
{% if item.has_permission %}
|
8
10
|
<li class="border-b last:border-b-0 md:border-b-0 md:mr-8 dark:border-gray-800">
|
9
|
-
<a href="{{ item.link }}" class="block px-3 py-2 {% if item.
|
11
|
+
<a href="{% if item.link_callback %}{{ item.link_callback }}{% else %}{{ item.link }}{% endif %}" class="block px-3 py-2 {% if item.active %} border-b md:border-primary-500 dark:md:border-primary-600 font-medium -mb-px text-primary-600 hover:text-primary-600 dark:text-primary-500{% else %} hover:text-gray-700 dark:hover:text-gray-200{% endif %} md:py-4 md:px-0 dark:border-gray-800">
|
10
12
|
{{ item.title }}
|
11
13
|
</a>
|
12
14
|
</li>
|
13
15
|
{% endif %}
|
14
16
|
{% endfor %}
|
17
|
+
|
18
|
+
{% if inlines_list %}
|
19
|
+
<li class="border-b last:border-b-0 md:border-b-0 md:mr-8 dark:border-gray-800">
|
20
|
+
<a class="block cursor-pointer px-3 py-2 hover:text-gray-700 dark:hover:text-gray-200 md:py-4 md:px-0 dark:border-gray-800" x-on:click="activeTab = 'general'" x-bind:class="{'border-b md:border-primary-500 dark:md:border-primary-600 font-medium -mb-px text-primary-600 hover:text-primary-600 dark:text-primary-500': activeTab == 'general'}">
|
21
|
+
{% trans "General" %}
|
22
|
+
</a>
|
23
|
+
</li>
|
24
|
+
|
25
|
+
{% for inline in inlines_list %}
|
26
|
+
<li class="border-b last:border-b-0 md:border-b-0 md:mr-8 dark:border-gray-800">
|
27
|
+
<a class="block cursor-pointer px-3 py-2 hover:text-gray-700 dark:hover:text-gray-200 md:py-4 md:px-0 dark:border-gray-800" x-on:click="activeTab = '{{ inline.opts.verbose_name|slugify }}'" x-bind:class="{'border-b md:border-primary-500 dark:md:border-primary-600 font-medium -mb-px text-primary-600 hover:text-primary-600 dark:text-primary-500': activeTab == '{{ inline.opts.verbose_name|slugify }}'}">
|
28
|
+
{% if inline.formset.max_num == 1 %}
|
29
|
+
{{ inline.opts.verbose_name|capfirst }}
|
30
|
+
{% else %}
|
31
|
+
{{ inline.opts.verbose_name_plural|capfirst }}
|
32
|
+
{% endif %}
|
33
|
+
</a>
|
34
|
+
</li>
|
35
|
+
{% endfor %}
|
36
|
+
{% endif %}
|
15
37
|
</ul>
|
16
38
|
{% endif %}
|
17
39
|
|
@@ -1,13 +1,13 @@
|
|
1
1
|
{% load i18n %}
|
2
2
|
|
3
3
|
<div class="relative" x-data="{ openTheme: false }">
|
4
|
-
<a class="block cursor-pointer leading-none hover:text-gray-700 dark:text-gray-
|
4
|
+
<a class="block cursor-pointer leading-none hover:text-gray-700 dark:text-gray-300 dark:hover:text-gray-200" x-on:click="openTheme = !openTheme">
|
5
5
|
<span class="material-symbols-outlined">
|
6
6
|
<span x-text="adminTheme == 'dark' && 'dark_mode' || adminTheme == 'light' && 'light_mode' || 'computer'"></span>
|
7
7
|
</span>
|
8
8
|
</a>
|
9
9
|
|
10
|
-
<nav class="absolute bg-white border flex flex-col leading-none overflow-hidden py-1 -right-2 rounded shadow-lg text-sm text-gray-500 top-7 w-40 z-50 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-
|
10
|
+
<nav class="absolute bg-white border flex flex-col leading-none overflow-hidden py-1 -right-2 rounded shadow-lg text-sm text-gray-500 top-7 w-40 z-50 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-300" x-cloak x-show="openTheme" @click.outside="openTheme = false">
|
11
11
|
<a class="cursor-pointer flex flex-row leading-none mx-1 px-3 py-1.5 rounded hover:bg-gray-100 hover:text-gray-700 dark:hover:bg-gray-700 dark:hover:text-gray-200"
|
12
12
|
x-on:click="adminTheme = 'dark'"
|
13
13
|
x-bind:class="adminTheme == 'dark' && 'text-primary-600 dark:text-primary-500 dark:hover:!text-primary-500 hover:!text-primary-600'">
|
@@ -24,9 +24,14 @@
|
|
24
24
|
<link href="{{ style }}" rel="stylesheet">
|
25
25
|
{% endfor %}
|
26
26
|
|
27
|
+
{% for favicon in site_favicons %}
|
28
|
+
<link {% if favicon.rel %}rel="{{ favicon.rel }}"{% endif %} {% if favicon.href %}href="{{ favicon.href }}"{% endif %} {% if favicon.type %}type="{{ favicon.type }}"{% endif %} {% if favicon.sizes %}sizes="{{ favicon.sizes }}"{% endif %}>
|
29
|
+
{% endfor %}
|
30
|
+
|
27
31
|
<link href="{% static 'unfold/css/styles.css' %}" rel="stylesheet">
|
28
32
|
<link href="{% static 'unfold/css/simplebar.css' %}" rel="stylesheet">
|
29
33
|
|
34
|
+
<script src="{% static 'unfold/js/alpine.anchor.js' %}" defer></script>
|
30
35
|
<script src="{% static 'unfold/js/alpine.persist.js' %}" defer></script>
|
31
36
|
<script src="{% static 'unfold/js/alpine.js' %}" defer></script>
|
32
37
|
<script src="{% static 'unfold/js/htmx.js' %}"></script>
|
@@ -63,7 +68,7 @@
|
|
63
68
|
{% endif %}
|
64
69
|
</head>
|
65
70
|
|
66
|
-
<body class="antialiased bg-white font-sans text-gray-500 dark:bg-gray-900 dark:text-gray-
|
71
|
+
<body class="antialiased bg-white font-sans text-gray-500 dark:bg-gray-900 dark:text-gray-300 {% if is_popup %}popup {% endif %}{% block bodyclass %}{% endblock %}" data-admin-utc-offset="{% now "Z" %}" x-data="{ activeTab: 'general', sidebarMobileOpen: false, sidebarDesktopOpen: {% if request.session.toggle_sidebar == False %}false{% else %}true{% endif %} }">
|
67
72
|
{% block base %}{% endblock %}
|
68
73
|
|
69
74
|
<div id="modal-overlay" class="backdrop-blur-sm bg-opacity-80 bg-gray-900 bottom-0 fixed hidden left-0 mr-1 right-0 top-0 z-50"></div>
|
@@ -10,24 +10,32 @@
|
|
10
10
|
|
11
11
|
<div class="border flex items-center overflow-hidden rounded-md shadow-sm text-sm max-w-2xl dark:border-gray-700">
|
12
12
|
{% if widget.is_initial and not widget.required %}
|
13
|
-
<div class="bg-gray-50 border-r flex flex-none items-center self-stretch px-3 dark:bg-white/[.02] dark:border-gray-700 dark:text-gray-
|
13
|
+
<div class="bg-gray-50 border-r flex flex-none items-center self-stretch px-3 dark:bg-white/[.02] dark:border-gray-700 dark:text-gray-300">
|
14
14
|
<label for="{{ widget.checkbox_id }}" class="flex items-center">
|
15
15
|
<input type="checkbox"{% if widget.class %} class="{{ widget.class }}"{% endif %} name="{{ widget.checkbox_name }}" id="{{ widget.checkbox_id }}" />
|
16
16
|
|
17
|
-
<span class="ml-2 text-gray-500 dark:text-gray-
|
17
|
+
<span class="ml-2 text-gray-500 dark:text-gray-300">
|
18
18
|
{{ widget.clear_checkbox_label }}
|
19
19
|
</span>
|
20
20
|
</label>
|
21
21
|
</div>
|
22
22
|
{% endif %}
|
23
23
|
|
24
|
-
<input type="text" value="{% if widget.value %}{{ widget.value.url }}{% else %}{% trans 'Choose file to upload' %}{% endif %}" disabled class="bg-white flex-grow font-medium px-3 py-2 text-ellipsis dark:bg-gray-900 {% if widget.value %}text-gray-500 dark:text-gray-
|
24
|
+
<input type="text" value="{% if widget.value %}{{ widget.value.url }}{% else %}{% trans 'Choose file to upload' %}{% endif %}" disabled class="bg-white flex-grow font-medium px-3 py-2 text-ellipsis dark:bg-gray-900 {% if widget.value %}text-gray-500 dark:text-gray-300{% else %}text-gray-300 dark:text-gray-300{% endif %}">
|
25
25
|
|
26
26
|
<div class="flex flex-none items-center leading-none self-stretch">
|
27
|
-
<
|
27
|
+
<div class="hidden">
|
28
|
+
<input type="{{ widget.type }}" name="{{ widget.name }}" {% include "django/forms/widgets/attrs.html" %} />
|
29
|
+
</div>
|
30
|
+
|
31
|
+
{% if widget.is_initial %}
|
32
|
+
<a href="{{ widget.value.url }}" class="border-r cursor-pointer text-gray-400 px-3 hover:text-gray-700 dark:border-gray-700 dark:text-gray-500 dark:hover:text-gray-200" target="_blank">
|
33
|
+
<span class="material-symbols-outlined">download</span>
|
34
|
+
</a>
|
35
|
+
{% endif %}
|
28
36
|
|
29
|
-
<label for="{{ widget.
|
30
|
-
<span class="material-symbols-outlined">
|
37
|
+
<label for="{{ widget.attrs.id }}" class="cursor-pointer text-gray-400 px-3 hover:text-gray-700 dark:text-gray-500 dark:hover:text-gray-200">
|
38
|
+
<span class="material-symbols-outlined">upload</span>
|
31
39
|
</label>
|
32
40
|
</div>
|
33
41
|
</div>
|
@@ -7,19 +7,19 @@
|
|
7
7
|
<label for="{{ widget.checkbox_id }}" class="flex items-center">
|
8
8
|
<input type="checkbox"{% if widget.class %} class="{{ widget.class }}"{% endif %} name="{{ widget.checkbox_name }}" id="{{ widget.checkbox_id }}" />
|
9
9
|
|
10
|
-
<span class="ml-2 text-gray-500 dark:text-gray-
|
10
|
+
<span class="ml-2 text-gray-500 dark:text-gray-300">
|
11
11
|
{{ widget.clear_checkbox_label }}
|
12
12
|
</span>
|
13
13
|
</label>
|
14
14
|
</div>
|
15
15
|
{% endif %}
|
16
16
|
|
17
|
-
<input type="text" value="{% if widget.value %}{{ widget.value.url }}{% else %}{% trans 'Choose file to upload' %}{% endif %}" disabled class="bg-white flex-grow font-medium px-3 py-2 text-ellipsis dark:bg-gray-900 {% if widget.value %}text-gray-500 dark:text-gray-
|
17
|
+
<input type="text" value="{% if widget.value %}{{ widget.value.url }}{% else %}{% trans 'Choose file to upload' %}{% endif %}" disabled class="bg-white flex-grow font-medium px-3 py-2 text-ellipsis dark:bg-gray-900 {% if widget.value %}text-gray-500 dark:text-gray-300{% else %}text-gray-300 dark:text-gray-300{% endif %}">
|
18
18
|
|
19
19
|
<div class="flex flex-none items-center leading-none self-stretch">
|
20
|
-
<input
|
20
|
+
<input type="{{ widget.type }}" name="{{ widget.name }}" class="{{ widget.file_input_class }}" {% include "django/forms/widgets/attrs.html" %} />
|
21
21
|
|
22
|
-
<label for="{{ widget.
|
22
|
+
<label for="{{ widget.attrs.id }}" class="cursor-pointer text-gray-400 px-3 hover:text-gray-700 dark:text-gray-500 dark:hover:text-gray-200">
|
23
23
|
<span class="material-symbols-outlined">file_upload</span>
|
24
24
|
</label>
|
25
25
|
</div>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<div class="datetime flex flex-col gap-2 max-w-2xl lg:flex-row lg:group-[.field-row]:flex-row lg:group-[.field-row]:items-center lg:group-[.field-tabular]:flex-row lg:group-[.field-tabular]:items-center">
|
2
2
|
<div class="basis-1/2 flex flex-col lg:group-[.field-row]:flex-row group-[.field-row]:gap-2 lg:group-[.field-tabular]:flex-row group-[.field-tabular]:gap-2">
|
3
|
-
<div class="font-medium mb-2 text-gray-500 text-sm dark:text-gray-
|
3
|
+
<div class="font-medium mb-2 text-gray-500 text-sm dark:text-gray-300 group-[.field-row]:mb-0 group-[.field-row]:flex group-[.field-row]:items-center group-[.field-tabular]:mb-0 group-[.field-tabular]:flex group-[.field-tabular]:items-center">
|
4
4
|
{{ date_label }}
|
5
5
|
</div>
|
6
6
|
|
@@ -12,7 +12,7 @@
|
|
12
12
|
</div>
|
13
13
|
|
14
14
|
<div class="basis-1/2 flex flex-col lg:ml-auto md:mt-0 lg:group-[.field-row]:flex-row group-[.field-row]:gap-2 lg:group-[.field-tabular]:flex-row group-[.field-tabular]:gap-2">
|
15
|
-
<div class="font-medium mb-2 text-gray-500 text-sm dark:text-gray-
|
15
|
+
<div class="font-medium mb-2 text-gray-500 text-sm dark:text-gray-300 group-[.field-row]:mb-0 group-[.field-row]:flex group-[.field-row]:items-center group-[.field-tabular]:mb-0 group-[.field-tabular]:flex group-[.field-tabular]:items-center">
|
16
16
|
{{ time_label }}
|
17
17
|
</div>
|
18
18
|
|
unfold/templatetags/unfold.py
CHANGED
@@ -12,28 +12,49 @@ register = Library()
|
|
12
12
|
|
13
13
|
|
14
14
|
@register.simple_tag(name="tab_list", takes_context=True)
|
15
|
-
def tab_list(context, opts) -> str:
|
16
|
-
|
15
|
+
def tab_list(context, page, opts) -> str:
|
16
|
+
tabs_list = []
|
17
|
+
inlines_list = []
|
18
|
+
|
19
|
+
data = {
|
20
|
+
"nav_global": context.get("nav_global"),
|
21
|
+
"actions_detail": context.get("actions_detail"),
|
22
|
+
"actions_list": context.get("actions_list"),
|
23
|
+
"actions_items": context.get("actions_items"),
|
24
|
+
"is_popup": context.get("is_popup"),
|
25
|
+
}
|
17
26
|
|
18
27
|
for tab in context.get("tab_list", []):
|
19
28
|
if str(opts) in tab["models"]:
|
20
|
-
|
29
|
+
tabs_list = tab["items"]
|
21
30
|
break
|
22
31
|
|
32
|
+
if page == "changelist":
|
33
|
+
data["tabs_list"] = tabs_list
|
34
|
+
|
35
|
+
for inline in context.get("inline_admin_formsets", []):
|
36
|
+
if hasattr(inline.opts, "tab"):
|
37
|
+
inlines_list.append(inline)
|
38
|
+
|
39
|
+
if page == "changeform" and len(inlines_list) > 0:
|
40
|
+
data["inlines_list"] = inlines_list
|
41
|
+
|
23
42
|
return render_to_string(
|
24
43
|
"unfold/helpers/tab_list.html",
|
25
|
-
request=context
|
26
|
-
context=
|
27
|
-
"tab_list": tabs,
|
28
|
-
"nav_global": context.get("nav_global"),
|
29
|
-
"actions_detail": context.get("actions_detail"),
|
30
|
-
"actions_list": context.get("actions_list"),
|
31
|
-
"actions_items": context.get("actions_items"),
|
32
|
-
"is_popup": context.get("is_popup"),
|
33
|
-
},
|
44
|
+
request=context["request"],
|
45
|
+
context=data,
|
34
46
|
)
|
35
47
|
|
36
48
|
|
49
|
+
@register.simple_tag(name="has_nav_item_active")
|
50
|
+
def has_nav_item_active(items: list) -> bool:
|
51
|
+
for item in items:
|
52
|
+
if "active" in item and item["active"]:
|
53
|
+
return True
|
54
|
+
|
55
|
+
return False
|
56
|
+
|
57
|
+
|
37
58
|
@register.filter
|
38
59
|
def class_name(value: Any) -> str:
|
39
60
|
return value.__class__.__name__
|
@@ -63,8 +63,8 @@ ROW_CLASSES = [
|
|
63
63
|
"before:mr-auto",
|
64
64
|
"before:text-gray-500",
|
65
65
|
"first:border-t-0",
|
66
|
-
"dark:before:text-gray-
|
67
|
-
"dark:text-gray-
|
66
|
+
"dark:before:text-gray-300",
|
67
|
+
"dark:text-gray-300",
|
68
68
|
"lg:before:hidden",
|
69
69
|
"lg:first:border-t",
|
70
70
|
"lg:py-3",
|
@@ -90,7 +90,7 @@ CHECKBOX_CLASSES = [
|
|
90
90
|
"lg:border-t",
|
91
91
|
"lg:border-gray-200",
|
92
92
|
"lg:table-cell",
|
93
|
-
"dark:before:text-gray-
|
93
|
+
"dark:before:text-gray-300",
|
94
94
|
"dark:lg:border-gray-800",
|
95
95
|
]
|
96
96
|
|
@@ -254,7 +254,7 @@ def items_for_result(cl: ChangeList, result: HttpRequest, form) -> SafeText:
|
|
254
254
|
f, (models.DateField, models.TimeField, models.ForeignKey)
|
255
255
|
):
|
256
256
|
row_classes.append("nowrap")
|
257
|
-
|
257
|
+
|
258
258
|
# If list_display_links not defined, add the link tag to the first field
|
259
259
|
|
260
260
|
if link_in_col(first, field_name, cl):
|
@@ -287,7 +287,7 @@ def items_for_result(cl: ChangeList, result: HttpRequest, form) -> SafeText:
|
|
287
287
|
else "",
|
288
288
|
result_repr,
|
289
289
|
)
|
290
|
-
|
290
|
+
row_class = mark_safe(f' class="{" ".join(row_classes)}"')
|
291
291
|
yield format_html(
|
292
292
|
'<{}{} data-label="{}">{}</{}>',
|
293
293
|
table_tag,
|
@@ -309,7 +309,17 @@ def items_for_result(cl: ChangeList, result: HttpRequest, form) -> SafeText:
|
|
309
309
|
)
|
310
310
|
):
|
311
311
|
bf = form[field_name]
|
312
|
-
result_repr = mark_safe(
|
312
|
+
result_repr = mark_safe(
|
313
|
+
str(bf)
|
314
|
+
+ render_to_string(
|
315
|
+
"unfold/helpers/form_errors.html", {"errors": bf.errors}
|
316
|
+
)
|
317
|
+
)
|
318
|
+
|
319
|
+
if bf.errors:
|
320
|
+
row_classes += ["group", "errors"]
|
321
|
+
|
322
|
+
row_class = mark_safe(f' class="{" ".join(row_classes)}"')
|
313
323
|
|
314
324
|
if field_index != 0:
|
315
325
|
yield format_html(
|
unfold/widgets.py
CHANGED
@@ -23,6 +23,7 @@ from django.forms import (
|
|
23
23
|
MultiWidget,
|
24
24
|
NullBooleanSelect,
|
25
25
|
NumberInput,
|
26
|
+
PasswordInput,
|
26
27
|
Select,
|
27
28
|
)
|
28
29
|
from django.utils.translation import gettext_lazy as _
|
@@ -62,7 +63,7 @@ BASE_CLASSES = [
|
|
62
63
|
"group-[.errors]:focus:ring-red-200",
|
63
64
|
"dark:bg-gray-900",
|
64
65
|
"dark:border-gray-700",
|
65
|
-
"dark:text-gray-
|
66
|
+
"dark:text-gray-300",
|
66
67
|
"dark:focus:border-primary-600",
|
67
68
|
"dark:focus:ring-primary-700",
|
68
69
|
"dark:focus:ring-opacity-50",
|
@@ -90,12 +91,10 @@ TEXTAREA_CLASSES = [
|
|
90
91
|
"max-w-4xl",
|
91
92
|
"appearance-none",
|
92
93
|
"expandable",
|
93
|
-
"overflow-hidden",
|
94
94
|
"transition",
|
95
95
|
"transition-height",
|
96
96
|
"duration-75",
|
97
97
|
"ease-in-out",
|
98
|
-
"resize-none",
|
99
98
|
]
|
100
99
|
|
101
100
|
TEXTAREA_EXPANDABLE_CLASSES = [
|
@@ -116,6 +115,7 @@ SELECT_CLASSES = [
|
|
116
115
|
|
117
116
|
PROSE_CLASSES = [
|
118
117
|
"font-normal",
|
118
|
+
"whitespace-normal",
|
119
119
|
"prose-sm",
|
120
120
|
"prose-blockquote:border-l-4",
|
121
121
|
"prose-blockquote:not-italic",
|
@@ -131,7 +131,7 @@ PROSE_CLASSES = [
|
|
131
131
|
"prose-strong:text-gray-700",
|
132
132
|
"dark:prose-pre:bg-gray-800",
|
133
133
|
"dark:prose-blockquote:border-gray-700",
|
134
|
-
"dark:prose-blockquote:text-gray-
|
134
|
+
"dark:prose-blockquote:text-gray-300",
|
135
135
|
"dark:prose-headings:text-gray-200",
|
136
136
|
"dark:prose-strong:text-gray-200",
|
137
137
|
]
|
@@ -567,3 +567,10 @@ class UnfoldForeignKeyRawIdWidget(ForeignKeyRawIdWidget):
|
|
567
567
|
**(attrs or {}),
|
568
568
|
}
|
569
569
|
super().__init__(rel, admin_site, attrs, using)
|
570
|
+
|
571
|
+
|
572
|
+
class UnfoldAdminPasswordInput(PasswordInput):
|
573
|
+
def __init__(self, attrs=None, render_value=False):
|
574
|
+
super().__init__(
|
575
|
+
{"class": " ".join(INPUT_CLASSES), **(attrs or {})}, render_value
|
576
|
+
)
|
File without changes
|
File without changes
|