django-unfold 0.27.0__py3-none-any.whl → 0.28.1__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- {django_unfold-0.27.0.dist-info → django_unfold-0.28.1.dist-info}/METADATA +64 -9
- {django_unfold-0.27.0.dist-info → django_unfold-0.28.1.dist-info}/RECORD +30 -27
- unfold/admin.py +1 -0
- unfold/contrib/forms/widgets.py +2 -0
- unfold/contrib/import_export/forms.py +21 -7
- unfold/contrib/import_export/templates/admin/import_export/change_list_export.html +5 -0
- unfold/contrib/import_export/templates/admin/import_export/export.html +1 -1
- unfold/contrib/simple_history/templates/simple_history/object_history.html +3 -5
- unfold/contrib/simple_history/templates/simple_history/{_object_history_list.html → object_history_list.html} +49 -11
- unfold/dataclasses.py +2 -0
- unfold/fields.py +9 -1
- unfold/static/unfold/css/styles.css +1 -1
- unfold/styles.css +1 -2
- unfold/templates/admin/login.html +4 -0
- unfold/templates/admin/submit_line.html +1 -1
- unfold/templates/unfold/helpers/attrs.html +1 -0
- unfold/templates/unfold/helpers/boolean.html +1 -1
- unfold/templates/unfold/helpers/field_readonly_value.html +1 -1
- unfold/templates/unfold/helpers/fieldset_row.html +2 -2
- unfold/templates/unfold/helpers/navigation.html +1 -1
- unfold/templates/unfold/helpers/search_results.html +10 -10
- unfold/templates/unfold/layouts/base.html +11 -0
- unfold/templates/unfold/layouts/base_simple.html +7 -1
- unfold/templates/unfold/widgets/clearable_file_input_small.html +1 -1
- unfold/templates/unfold/widgets/split_datetime.html +7 -7
- unfold/utils.py +21 -1
- unfold/views.py +18 -6
- unfold/widgets.py +12 -1
- {django_unfold-0.27.0.dist-info → django_unfold-0.28.1.dist-info}/LICENSE.md +0 -0
- {django_unfold-0.27.0.dist-info → django_unfold-0.28.1.dist-info}/WHEEL +0 -0
@@ -1,23 +1,23 @@
|
|
1
|
-
<div class="datetime flex flex-col max-w-2xl lg:flex-row">
|
2
|
-
<div class="basis-1/2 flex flex-col flex-wrap mb-4 lg:mb-0
|
3
|
-
<div class="font-medium mb-2 text-gray-500 text-sm dark:text-gray-400">
|
1
|
+
<div class="datetime flex flex-col gap-2 max-w-2xl lg:flex-row group-[.field-row]:flex-row group-[.field-row]:items-center">
|
2
|
+
<div class="basis-1/2 flex flex-col flex-wrap mb-4 lg:mb-0 group-[.field-row]:flex-row group-[.field-row]:gap-2">
|
3
|
+
<div class="font-medium mb-2 text-gray-500 text-sm dark:text-gray-400 group-[.field-row]:mb-0 group-[.field-row]:flex group-[.field-row]:items-center">
|
4
4
|
{{ date_label }}
|
5
5
|
</div>
|
6
6
|
|
7
7
|
{% with widget=widget.subwidgets.0 %}
|
8
|
-
<div class="flex flex-col relative">
|
8
|
+
<div class="flex flex-col relative group-[.field-row]:flex-grow">
|
9
9
|
{% include widget.template_name %}
|
10
10
|
</div>
|
11
11
|
{% endwith %}
|
12
12
|
</div>
|
13
13
|
|
14
|
-
<div class="basis-1/2 flex flex-col flex-wrap lg:ml-auto mt-3 md:mt-0">
|
15
|
-
<div class="font-medium mb-2 text-gray-500 text-sm dark:text-gray-400">
|
14
|
+
<div class="basis-1/2 flex flex-col flex-wrap lg:ml-auto mt-3 md:mt-0 group-[.field-row]:flex-row group-[.field-row]:gap-2">
|
15
|
+
<div class="font-medium mb-2 text-gray-500 text-sm dark:text-gray-400 group-[.field-row]:mb-0 group-[.field-row]:flex group-[.field-row]:items-center">
|
16
16
|
{{ time_label }}
|
17
17
|
</div>
|
18
18
|
|
19
19
|
{% with widget=widget.subwidgets.1 %}
|
20
|
-
<div class="flex flex-col relative">
|
20
|
+
<div class="flex flex-col relative group-[.field-row]:flex-grow">
|
21
21
|
{% include widget.template_name %}
|
22
22
|
</div>
|
23
23
|
{% endwith %}
|
unfold/utils.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import datetime
|
2
2
|
import decimal
|
3
3
|
import json
|
4
|
-
from typing import Any, Iterable, List
|
4
|
+
from typing import Any, Iterable, List, Optional
|
5
5
|
|
6
6
|
from django.db import models
|
7
7
|
from django.template.loader import render_to_string
|
@@ -121,3 +121,23 @@ def hex_to_rgb(hex_color: str) -> List[int]:
|
|
121
121
|
b = int(hex_color[4:6], 16)
|
122
122
|
|
123
123
|
return (r, g, b)
|
124
|
+
|
125
|
+
|
126
|
+
def prettify_json(data: Any) -> Optional[str]:
|
127
|
+
try:
|
128
|
+
from pygments import highlight
|
129
|
+
from pygments.formatters import HtmlFormatter
|
130
|
+
from pygments.lexers import JsonLexer
|
131
|
+
except ImportError:
|
132
|
+
return None
|
133
|
+
|
134
|
+
def format_response(response: str, theme: str) -> str:
|
135
|
+
formatter = HtmlFormatter(style=theme, noclasses=True, nobackground=True)
|
136
|
+
return highlight(response, JsonLexer(), formatter)
|
137
|
+
|
138
|
+
response = json.dumps(data, sort_keys=True, indent=4)
|
139
|
+
|
140
|
+
return mark_safe(
|
141
|
+
f'<div class="block dark:hidden">{format_response(response, "colorful")}</div>'
|
142
|
+
f'<div class="hidden dark:block">{format_response(response, "monokai")}</div>'
|
143
|
+
)
|
unfold/views.py
CHANGED
@@ -10,13 +10,25 @@ class UnfoldModelAdminViewMixin(PermissionRequiredMixin):
|
|
10
10
|
Prepares views to be displayed in admin
|
11
11
|
"""
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
model_admin = None
|
14
|
+
|
15
|
+
def __init__(self, model_admin, **kwargs):
|
16
|
+
self.model_admin = model_admin
|
17
|
+
super().__init__(**kwargs)
|
18
|
+
|
19
|
+
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
|
20
|
+
if not hasattr(self, "model_admin"):
|
15
21
|
raise UnfoldException(
|
16
22
|
"UnfoldModelAdminViewMixin was not provided with 'model_admin' argument"
|
17
23
|
)
|
18
|
-
|
19
|
-
|
20
|
-
|
24
|
+
|
25
|
+
if not hasattr(self, "title"):
|
26
|
+
raise UnfoldException(
|
27
|
+
"UnfoldModelAdminViewMixin was not provided with 'title' attribute"
|
28
|
+
)
|
29
|
+
|
30
|
+
return super().get_context_data(
|
31
|
+
**kwargs,
|
32
|
+
**self.model_admin.admin_site.each_context(self.request),
|
33
|
+
**{"title": self.title},
|
21
34
|
)
|
22
|
-
return context_data
|
unfold/widgets.py
CHANGED
@@ -288,7 +288,18 @@ class FileFieldMixin:
|
|
288
288
|
def get_context(self, name, value, attrs):
|
289
289
|
widget = super().get_context(name, value, attrs)
|
290
290
|
widget["widget"].update(
|
291
|
-
{
|
291
|
+
{
|
292
|
+
"class": " ".join([*CHECKBOX_CLASSES, *["form-check-input"]]),
|
293
|
+
"file_input_class": " ".join(
|
294
|
+
[
|
295
|
+
self.attrs.get("class", ""),
|
296
|
+
*[
|
297
|
+
"opacity-0",
|
298
|
+
"pointer-events-none",
|
299
|
+
],
|
300
|
+
]
|
301
|
+
),
|
302
|
+
}
|
292
303
|
)
|
293
304
|
return widget
|
294
305
|
|
File without changes
|
File without changes
|