django-unfold 0.29.1__py3-none-any.whl → 0.31.0__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- {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
|