django-unfold 0.46.0__py3-none-any.whl → 0.47.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.46.0.dist-info → django_unfold-0.47.0.dist-info}/METADATA +5 -6
- {django_unfold-0.46.0.dist-info → django_unfold-0.47.0.dist-info}/RECORD +38 -31
- {django_unfold-0.46.0.dist-info → django_unfold-0.47.0.dist-info}/WHEEL +1 -1
- unfold/admin.py +15 -16
- unfold/checks.py +4 -4
- unfold/components.py +5 -5
- unfold/contrib/filters/admin/__init__.py +43 -0
- unfold/contrib/filters/admin/autocomplete_filters.py +16 -0
- unfold/contrib/filters/admin/datetime_filters.py +212 -0
- unfold/contrib/filters/admin/dropdown_filters.py +100 -0
- unfold/contrib/filters/admin/mixins.py +146 -0
- unfold/contrib/filters/admin/numeric_filters.py +196 -0
- unfold/contrib/filters/admin/text_filters.py +65 -0
- unfold/contrib/filters/admin.py +32 -32
- unfold/contrib/filters/forms.py +68 -17
- unfold/contrib/forms/widgets.py +9 -9
- unfold/contrib/inlines/checks.py +2 -4
- unfold/contrib/simple_history/templates/simple_history/object_history.html +17 -1
- unfold/contrib/simple_history/templates/simple_history/object_history_list.html +1 -1
- unfold/dataclasses.py +2 -2
- unfold/decorators.py +4 -3
- unfold/settings.py +2 -2
- unfold/sites.py +156 -140
- unfold/static/unfold/css/styles.css +1 -1
- unfold/static/unfold/js/app.js +2 -2
- unfold/templates/admin/filter.html +1 -1
- unfold/templates/unfold/helpers/change_list_filter.html +2 -2
- unfold/templates/unfold/helpers/change_list_filter_actions.html +1 -1
- unfold/templates/unfold/helpers/header_back_button.html +2 -2
- unfold/templates/unfold/helpers/tab_list.html +7 -1
- unfold/templates/unfold/layouts/skeleton.html +1 -1
- unfold/templatetags/unfold.py +55 -22
- unfold/templatetags/unfold_list.py +2 -2
- unfold/typing.py +5 -4
- unfold/utils.py +3 -2
- unfold/views.py +2 -2
- unfold/widgets.py +27 -27
- {django_unfold-0.46.0.dist-info → django_unfold-0.47.0.dist-info}/LICENSE.md +0 -0
unfold/static/unfold/js/app.js
CHANGED
@@ -78,9 +78,9 @@ const filterForm = () => {
|
|
78
78
|
}
|
79
79
|
|
80
80
|
filterForm.addEventListener("formdata", (event) => {
|
81
|
-
|
81
|
+
Array.from(event.formData.entries()).forEach(([key, value]) => {
|
82
82
|
if (value === "") event.formData.delete(key);
|
83
|
-
}
|
83
|
+
});
|
84
84
|
});
|
85
85
|
};
|
86
86
|
|
@@ -12,7 +12,7 @@
|
|
12
12
|
{% endfor %}
|
13
13
|
|
14
14
|
{% if spec|class_name == "BooleanFieldListFilter" %}
|
15
|
-
<ul class="
|
15
|
+
<ul class="dark:bg-base-900 border border-base-200 flex min-w-20 rounded shadow-sm text-font-default-light dark:border-base-700 dark:text-font-default-dark w-full">
|
16
16
|
{% for choice in choices %}
|
17
17
|
<li class="basis-1/3 border-r border-base-200 flex-grow truncate last:border-r-0 dark:border-base-700 {% if choice.selected %}font-semibold text-primary-600 dark:text-primary-500 {% else %}hover:text-base-700 dark:hover:text-base-200{% endif %}">
|
18
18
|
<a href="{{ choice.query_string|iriencode }}" title="{{ choice.display }}" class="block px-3 py-2 text-center hover:text-primary-600 dark:hover:text-primary-500">
|
@@ -10,8 +10,8 @@
|
|
10
10
|
{% preserve_filters %}
|
11
11
|
{% endif %}
|
12
12
|
|
13
|
-
<div class="flex flex-col grow gap-4 overflow-auto *:mb-0"
|
14
|
-
<div class="flex flex-col gap-4 {% if cl.model_admin.list_filter_sheet %}px-
|
13
|
+
<div class="flex flex-col grow gap-4 overflow-auto *:mb-0" data-simplebar data-simplebar-direction="rtl">
|
14
|
+
<div class="flex flex-col gap-4 mx-1 px-2 py-2.5 {% if not cl.model_admin.list_filter_sheet %} 2xl:px-0 2xl:py-0{% endif %} *:mb-0">
|
15
15
|
{% for spec in cl.filter_specs %}
|
16
16
|
{% admin_list_filter cl spec %}
|
17
17
|
{% endfor %}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
{% load i18n %}
|
2
2
|
|
3
|
-
<div class="
|
3
|
+
<div class="bg-white border-t border-base-200 p-3 py-2.5 dark:bg-base-800 dark:border-base-700{% if not cl.model_admin.list_filter_sheet %} 2xl:!border-t-0 2xl:!bg-transparent 2xl:px-0{% endif %}">
|
4
4
|
{% if cl.model_admin.list_filter_submit %}
|
5
5
|
<button type="submit" class="bg-primary-600 block border border-transparent font-medium px-3 py-2 rounded text-white w-full">
|
6
6
|
{% trans "Apply Filters" %}
|
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
{% if show_back_button %}
|
4
4
|
{% if opts and adminform %}
|
5
|
-
{% url opts|admin_urlname:'changelist' as
|
5
|
+
{% url opts|admin_urlname:'changelist' as changelist_url %}
|
6
6
|
|
7
|
-
<a href="{
|
7
|
+
<a href="{% add_preserved_filters changelist_url %}" class="block h-4.5 mr-3" title="{% trans "Go back" %}">
|
8
8
|
<span class="material-symbols-outlined">
|
9
9
|
arrow_back
|
10
10
|
</span>
|
@@ -8,7 +8,13 @@
|
|
8
8
|
{% for item in tabs_list %}
|
9
9
|
{% if item.has_permission %}
|
10
10
|
<li class="border-b last:border-b-0 md:border-b-0 md:mr-8 dark:border-base-800">
|
11
|
-
<a href="{% if item.link_callback %}{{ item.link_callback }}{% else %}{{ item.link }}{% endif %}"
|
11
|
+
<a href="{% if item.link_callback %}{{ item.link_callback }}{% else %}{{ item.link }}{% endif %}"
|
12
|
+
class="block px-3 py-2 md:py-4 md:px-0 dark:border-base-800 {% if item.active and not item.inline %} border-b font-semibold -mb-px text-primary-600 hover:text-primary-600 dark:text-primary-500 dark:hover:text-primary-500 md:border-primary-500 dark:md:!border-primary-600{% else %}font-medium hover:text-primary-600 dark:hover:text-primary-500{% endif %}"
|
13
|
+
{% if item.inline %}
|
14
|
+
x-on:click="activeTab = '{{ item.inline }}'"
|
15
|
+
x-bind:class="{'border-b border-base-200 dark:border-base-800 md:border-primary-500 dark:md:!border-primary-600 font-semibold -mb-px text-primary-600 dark:text-primary-500': activeTab == '{{ item.inline }}'}"
|
16
|
+
{% endif %}
|
17
|
+
>
|
12
18
|
{{ item.title }}
|
13
19
|
</a>
|
14
20
|
</li>
|
@@ -59,7 +59,7 @@
|
|
59
59
|
{% endblock %}
|
60
60
|
</head>
|
61
61
|
|
62
|
-
<body class="antialiased bg-white font-sans text-font-default-light text-sm dark:bg-base-900 dark:text-font-default-dark {% if is_popup %}popup {% endif %}{% block bodyclass %}{% endblock %}" data-admin-utc-offset="{% now "Z" %}" x-data="{ mainWidth: 0, activeTab: 'general', sidebarMobileOpen: false, sidebarDesktopOpen: {% if request.session.toggle_sidebar == False %}false{% else %}true{% endif %} }" x-init="activeTab = window.location.hash?.replace('#', '') || 'general'">
|
62
|
+
<body class="antialiased bg-white font-sans text-font-default-light text-sm dark:bg-base-900 dark:text-font-default-dark {% if is_popup %}popup {% endif %}{% block bodyclass %}{% endblock %}" data-admin-utc-offset="{% now "Z" %}" x-data="{ mainWidth: 0, {% if opts %}activeTab: 'general',{% endif %} sidebarMobileOpen: false, sidebarDesktopOpen: {% if request.session.toggle_sidebar == False %}false{% else %}true{% endif %} }" x-init="activeTab = {% if opts %}window.location.hash?.replace('#', '') || 'general'{% else %}''{% endif %}">
|
63
63
|
{% if colors %}
|
64
64
|
<style id="unfold-theme-colors">
|
65
65
|
:root {
|
unfold/templatetags/unfold.py
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
-
from
|
1
|
+
from collections.abc import Mapping
|
2
|
+
from typing import Any, Optional, Union
|
2
3
|
|
3
4
|
from django import template
|
4
5
|
from django.contrib.admin.helpers import AdminForm, Fieldset
|
5
6
|
from django.contrib.admin.views.main import ChangeList
|
7
|
+
from django.db.models.options import Options
|
6
8
|
from django.forms import Field
|
7
9
|
from django.http import HttpRequest
|
8
10
|
from django.template import Context, Library, Node, RequestContext, TemplateSyntaxError
|
@@ -15,9 +17,44 @@ from unfold.components import ComponentRegistry
|
|
15
17
|
register = Library()
|
16
18
|
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
+
def _get_tabs_list(
|
21
|
+
context: RequestContext, page: str, opts: Optional[Options] = None
|
22
|
+
) -> list:
|
20
23
|
tabs_list = []
|
24
|
+
page_id = None
|
25
|
+
|
26
|
+
if page not in ["changeform", "changelist"]:
|
27
|
+
page_id = page
|
28
|
+
|
29
|
+
for tab in context.get("tab_list", []):
|
30
|
+
if page_id:
|
31
|
+
if tab.get("page") == page_id:
|
32
|
+
tabs_list = tab["items"]
|
33
|
+
break
|
34
|
+
|
35
|
+
continue
|
36
|
+
|
37
|
+
if "models" not in tab:
|
38
|
+
continue
|
39
|
+
|
40
|
+
for tab_model in tab["models"]:
|
41
|
+
if isinstance(tab_model, str):
|
42
|
+
if str(opts) == tab_model and page == "changelist":
|
43
|
+
tabs_list = tab["items"]
|
44
|
+
break
|
45
|
+
elif isinstance(tab_model, dict) and str(opts) == tab_model["name"]:
|
46
|
+
is_detail = tab_model.get("detail", False)
|
47
|
+
|
48
|
+
if (page == "changeform" and is_detail) or (
|
49
|
+
page == "changelist" and not is_detail
|
50
|
+
):
|
51
|
+
tabs_list = tab["items"]
|
52
|
+
break
|
53
|
+
return tabs_list
|
54
|
+
|
55
|
+
|
56
|
+
@register.simple_tag(name="tab_list", takes_context=True)
|
57
|
+
def tab_list(context: RequestContext, page: str, opts: Optional[Options] = None) -> str:
|
21
58
|
inlines_list = []
|
22
59
|
|
23
60
|
data = {
|
@@ -26,22 +63,18 @@ def tab_list(context, page, opts) -> str:
|
|
26
63
|
"actions_list": context.get("actions_list"),
|
27
64
|
"actions_items": context.get("actions_items"),
|
28
65
|
"is_popup": context.get("is_popup"),
|
66
|
+
"tabs_list": _get_tabs_list(context, page, opts),
|
29
67
|
}
|
30
68
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
data["tabs_list"] = tabs_list
|
38
|
-
|
39
|
-
for inline in context.get("inline_admin_formsets", []):
|
40
|
-
if hasattr(inline.opts, "tab"):
|
41
|
-
inlines_list.append(inline)
|
69
|
+
# If the changeform is rendered and there are no custom tab navigation
|
70
|
+
# specified, check for inlines to put into tabs
|
71
|
+
if page == "changeform" and len(data["tabs_list"]) == 0:
|
72
|
+
for inline in context.get("inline_admin_formsets", []):
|
73
|
+
if opts and hasattr(inline.opts, "tab"):
|
74
|
+
inlines_list.append(inline)
|
42
75
|
|
43
|
-
|
44
|
-
|
76
|
+
if len(inlines_list) > 0:
|
77
|
+
data["inlines_list"] = inlines_list
|
45
78
|
|
46
79
|
return render_to_string(
|
47
80
|
"unfold/helpers/tab_list.html",
|
@@ -70,7 +103,7 @@ def index(indexable: Mapping[int, Any], i: int) -> Any:
|
|
70
103
|
|
71
104
|
|
72
105
|
@register.filter
|
73
|
-
def tabs(adminform: AdminForm) ->
|
106
|
+
def tabs(adminform: AdminForm) -> list[Fieldset]:
|
74
107
|
result = []
|
75
108
|
|
76
109
|
for fieldset in adminform:
|
@@ -86,7 +119,7 @@ class CaptureNode(Node):
|
|
86
119
|
self.varname = varname
|
87
120
|
self.silent = silent
|
88
121
|
|
89
|
-
def render(self, context:
|
122
|
+
def render(self, context: dict[str, Any]) -> Union[str, SafeText]:
|
90
123
|
output = self.nodelist.render(context)
|
91
124
|
context[self.varname] = output
|
92
125
|
if self.silent:
|
@@ -155,7 +188,7 @@ class RenderComponentNode(template.Node):
|
|
155
188
|
self,
|
156
189
|
template_name: str,
|
157
190
|
nodelist: NodeList,
|
158
|
-
extra_context: Optional[
|
191
|
+
extra_context: Optional[dict] = None,
|
159
192
|
include_context: bool = False,
|
160
193
|
*args,
|
161
194
|
**kwargs,
|
@@ -252,7 +285,7 @@ def add_css_class(field: Field, classes: Union[list, tuple]) -> Field:
|
|
252
285
|
takes_context=True,
|
253
286
|
name="preserve_filters",
|
254
287
|
)
|
255
|
-
def preserve_changelist_filters(context: Context) ->
|
288
|
+
def preserve_changelist_filters(context: Context) -> dict[str, dict[str, str]]:
|
256
289
|
"""
|
257
290
|
Generate hidden input fields to preserve filters for POST forms.
|
258
291
|
"""
|
@@ -262,10 +295,10 @@ def preserve_changelist_filters(context: Context) -> Dict[str, Dict[str, str]]:
|
|
262
295
|
if not request or not changelist:
|
263
296
|
return {"params": {}}
|
264
297
|
|
265
|
-
used_params:
|
298
|
+
used_params: set[str] = {
|
266
299
|
param for spec in changelist.filter_specs for param in spec.used_parameters
|
267
300
|
}
|
268
|
-
preserved_params:
|
301
|
+
preserved_params: dict[str, str] = {
|
269
302
|
param: value for param, value in request.GET.items() if param not in used_params
|
270
303
|
}
|
271
304
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import datetime
|
2
|
-
from typing import Any,
|
2
|
+
from typing import Any, Optional, Union
|
3
3
|
|
4
4
|
from django.contrib.admin.templatetags.admin_list import (
|
5
5
|
ResultList,
|
@@ -355,7 +355,7 @@ def results(cl: ChangeList):
|
|
355
355
|
yield UnfoldResultList(pk_value, None, items_for_result(cl, res, None))
|
356
356
|
|
357
357
|
|
358
|
-
def result_list(context:
|
358
|
+
def result_list(context: dict[str, Any], cl: ChangeList) -> dict[str, Any]:
|
359
359
|
"""
|
360
360
|
Display the headers and data list together.
|
361
361
|
"""
|
unfold/typing.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
from
|
1
|
+
from collections.abc import Iterable
|
2
|
+
from typing import Any, Protocol, Union
|
2
3
|
|
3
4
|
|
4
5
|
class ActionFunction(Protocol):
|
@@ -11,13 +12,13 @@ class ActionFunction(Protocol):
|
|
11
12
|
allowed_permissions: Iterable[str]
|
12
13
|
short_description: str
|
13
14
|
url_path: str
|
14
|
-
attrs:
|
15
|
+
attrs: dict[str, Any]
|
15
16
|
|
16
17
|
def __call__(self, *args, **kwargs):
|
17
18
|
pass
|
18
19
|
|
19
20
|
|
20
21
|
FieldsetsType = Union[
|
21
|
-
|
22
|
-
|
22
|
+
list[tuple[Union[str, None], dict[str, Any]]],
|
23
|
+
tuple[tuple[Union[str, None], dict[str, Any]]],
|
23
24
|
]
|
unfold/utils.py
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
import datetime
|
2
2
|
import decimal
|
3
3
|
import json
|
4
|
-
from
|
4
|
+
from collections.abc import Iterable
|
5
|
+
from typing import Any, Optional
|
5
6
|
|
6
7
|
from django.conf import settings
|
7
8
|
from django.db import models
|
@@ -114,7 +115,7 @@ def display_for_field(value: Any, field: Any, empty_value_display: str) -> str:
|
|
114
115
|
return display_for_value(value, empty_value_display)
|
115
116
|
|
116
117
|
|
117
|
-
def hex_to_rgb(hex_color: str) ->
|
118
|
+
def hex_to_rgb(hex_color: str) -> list[int]:
|
118
119
|
hex_color = hex_color.lstrip("#")
|
119
120
|
|
120
121
|
r = int(hex_color[0:2], 16)
|
unfold/views.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import Any
|
1
|
+
from typing import Any
|
2
2
|
|
3
3
|
from django.contrib.auth.mixins import PermissionRequiredMixin
|
4
4
|
|
@@ -16,7 +16,7 @@ class UnfoldModelAdminViewMixin(PermissionRequiredMixin):
|
|
16
16
|
self.model_admin = model_admin
|
17
17
|
super().__init__(**kwargs)
|
18
18
|
|
19
|
-
def get_context_data(self, **kwargs: Any) ->
|
19
|
+
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
|
20
20
|
if not hasattr(self, "model_admin"):
|
21
21
|
raise UnfoldException(
|
22
22
|
"UnfoldModelAdminViewMixin was not provided with 'model_admin' argument"
|
unfold/widgets.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import Any, Callable,
|
1
|
+
from typing import Any, Callable, Optional, Union
|
2
2
|
|
3
3
|
from django.contrib.admin.options import VERTICAL
|
4
4
|
from django.contrib.admin.sites import AdminSite
|
@@ -255,7 +255,7 @@ SWITCH_CLASSES = [
|
|
255
255
|
|
256
256
|
|
257
257
|
class UnfoldAdminTextInputWidget(AdminTextInputWidget):
|
258
|
-
def __init__(self, attrs: Optional[
|
258
|
+
def __init__(self, attrs: Optional[dict[str, Any]] = None) -> None:
|
259
259
|
super().__init__(
|
260
260
|
attrs={
|
261
261
|
**(attrs or {}),
|
@@ -269,7 +269,7 @@ class UnfoldAdminTextInputWidget(AdminTextInputWidget):
|
|
269
269
|
class UnfoldAdminURLInputWidget(AdminURLFieldWidget):
|
270
270
|
template_name = "unfold/widgets/url.html"
|
271
271
|
|
272
|
-
def __init__(self, attrs: Optional[
|
272
|
+
def __init__(self, attrs: Optional[dict[str, Any]] = None) -> None:
|
273
273
|
super().__init__(
|
274
274
|
attrs={
|
275
275
|
**(attrs or {}),
|
@@ -281,7 +281,7 @@ class UnfoldAdminURLInputWidget(AdminURLFieldWidget):
|
|
281
281
|
|
282
282
|
|
283
283
|
class UnfoldAdminColorInputWidget(AdminTextInputWidget):
|
284
|
-
def __init__(self, attrs: Optional[
|
284
|
+
def __init__(self, attrs: Optional[dict[str, Any]] = None) -> None:
|
285
285
|
super().__init__(
|
286
286
|
attrs={
|
287
287
|
**(attrs or {}),
|
@@ -294,7 +294,7 @@ class UnfoldAdminColorInputWidget(AdminTextInputWidget):
|
|
294
294
|
|
295
295
|
|
296
296
|
class UnfoldAdminUUIDInputWidget(AdminUUIDInputWidget):
|
297
|
-
def __init__(self, attrs: Optional[
|
297
|
+
def __init__(self, attrs: Optional[dict[str, Any]] = None) -> None:
|
298
298
|
super().__init__(
|
299
299
|
attrs={
|
300
300
|
**(attrs or {}),
|
@@ -308,7 +308,7 @@ class UnfoldAdminUUIDInputWidget(AdminUUIDInputWidget):
|
|
308
308
|
class UnfoldAdminIntegerRangeWidget(MultiWidget):
|
309
309
|
template_name = "unfold/widgets/range.html"
|
310
310
|
|
311
|
-
def __init__(self, attrs: Optional[
|
311
|
+
def __init__(self, attrs: Optional[dict[str, Any]] = None) -> None:
|
312
312
|
if attrs is None:
|
313
313
|
attrs = {}
|
314
314
|
|
@@ -320,14 +320,14 @@ class UnfoldAdminIntegerRangeWidget(MultiWidget):
|
|
320
320
|
|
321
321
|
super().__init__(_widgets, attrs)
|
322
322
|
|
323
|
-
def decompress(self, value: Union[str, None]) ->
|
323
|
+
def decompress(self, value: Union[str, None]) -> tuple[Optional[Callable], ...]:
|
324
324
|
if value:
|
325
325
|
return value.lower, value.upper
|
326
326
|
return None, None
|
327
327
|
|
328
328
|
|
329
329
|
class UnfoldAdminEmailInputWidget(AdminEmailInputWidget):
|
330
|
-
def __init__(self, attrs: Optional[
|
330
|
+
def __init__(self, attrs: Optional[dict[str, Any]] = None) -> None:
|
331
331
|
super().__init__(
|
332
332
|
attrs={
|
333
333
|
**(attrs or {}),
|
@@ -374,7 +374,7 @@ class UnfoldAdminDateWidget(AdminDateWidget):
|
|
374
374
|
template_name = "unfold/widgets/date.html"
|
375
375
|
|
376
376
|
def __init__(
|
377
|
-
self, attrs: Optional[
|
377
|
+
self, attrs: Optional[dict[str, Any]] = None, format: Optional[str] = None
|
378
378
|
) -> None:
|
379
379
|
attrs = {
|
380
380
|
**(attrs or {}),
|
@@ -394,7 +394,7 @@ class UnfoldAdminSingleDateWidget(AdminDateWidget):
|
|
394
394
|
template_name = "unfold/widgets/date.html"
|
395
395
|
|
396
396
|
def __init__(
|
397
|
-
self, attrs: Optional[
|
397
|
+
self, attrs: Optional[dict[str, Any]] = None, format: Optional[str] = None
|
398
398
|
) -> None:
|
399
399
|
attrs = {
|
400
400
|
**(attrs or {}),
|
@@ -414,7 +414,7 @@ class UnfoldAdminTimeWidget(AdminTimeWidget):
|
|
414
414
|
template_name = "unfold/widgets/time.html"
|
415
415
|
|
416
416
|
def __init__(
|
417
|
-
self, attrs: Optional[
|
417
|
+
self, attrs: Optional[dict[str, Any]] = None, format: Optional[str] = None
|
418
418
|
) -> None:
|
419
419
|
attrs = {
|
420
420
|
**(attrs or {}),
|
@@ -434,7 +434,7 @@ class UnfoldAdminSingleTimeWidget(AdminTimeWidget):
|
|
434
434
|
template_name = "unfold/widgets/time.html"
|
435
435
|
|
436
436
|
def __init__(
|
437
|
-
self, attrs: Optional[
|
437
|
+
self, attrs: Optional[dict[str, Any]] = None, format: Optional[str] = None
|
438
438
|
) -> None:
|
439
439
|
attrs = {
|
440
440
|
**(attrs or {}),
|
@@ -453,7 +453,7 @@ class UnfoldAdminSingleTimeWidget(AdminTimeWidget):
|
|
453
453
|
class UnfoldAdminTextareaWidget(AdminTextareaWidget):
|
454
454
|
template_name = "unfold/widgets/textarea.html"
|
455
455
|
|
456
|
-
def __init__(self, attrs: Optional[
|
456
|
+
def __init__(self, attrs: Optional[dict[str, Any]] = None) -> None:
|
457
457
|
attrs = attrs or {}
|
458
458
|
|
459
459
|
super().__init__(
|
@@ -473,7 +473,7 @@ class UnfoldAdminTextareaWidget(AdminTextareaWidget):
|
|
473
473
|
class UnfoldAdminExpandableTextareaWidget(AdminTextareaWidget):
|
474
474
|
template_name = "unfold/widgets/textarea_expandable.html"
|
475
475
|
|
476
|
-
def __init__(self, attrs: Optional[
|
476
|
+
def __init__(self, attrs: Optional[dict[str, Any]] = None) -> None:
|
477
477
|
attrs = attrs or {}
|
478
478
|
|
479
479
|
attrs.update({"rows": 2})
|
@@ -496,7 +496,7 @@ class UnfoldAdminExpandableTextareaWidget(AdminTextareaWidget):
|
|
496
496
|
class UnfoldAdminSplitDateTimeWidget(AdminSplitDateTime):
|
497
497
|
template_name = "unfold/widgets/split_datetime.html"
|
498
498
|
|
499
|
-
def __init__(self, attrs: Optional[
|
499
|
+
def __init__(self, attrs: Optional[dict[str, Any]] = None) -> None:
|
500
500
|
widgets = [UnfoldAdminDateWidget, UnfoldAdminTimeWidget]
|
501
501
|
MultiWidget.__init__(self, widgets, attrs)
|
502
502
|
|
@@ -506,9 +506,9 @@ class UnfoldAdminSplitDateTimeVerticalWidget(AdminSplitDateTime):
|
|
506
506
|
|
507
507
|
def __init__(
|
508
508
|
self,
|
509
|
-
attrs: Optional[
|
510
|
-
date_attrs: Optional[
|
511
|
-
time_attrs: Optional[
|
509
|
+
attrs: Optional[dict[str, Any]] = None,
|
510
|
+
date_attrs: Optional[dict[str, Any]] = None,
|
511
|
+
time_attrs: Optional[dict[str, Any]] = None,
|
512
512
|
date_label: Optional[str] = None,
|
513
513
|
time_label: Optional[str] = None,
|
514
514
|
) -> None:
|
@@ -522,8 +522,8 @@ class UnfoldAdminSplitDateTimeVerticalWidget(AdminSplitDateTime):
|
|
522
522
|
MultiWidget.__init__(self, widgets, attrs)
|
523
523
|
|
524
524
|
def get_context(
|
525
|
-
self, name: str, value: Any, attrs: Optional[
|
526
|
-
) ->
|
525
|
+
self, name: str, value: Any, attrs: Optional[dict[str, Any]]
|
526
|
+
) -> dict[str, Any]:
|
527
527
|
context = super().get_context(name, value, attrs)
|
528
528
|
|
529
529
|
if self.date_label is not None:
|
@@ -540,7 +540,7 @@ class UnfoldAdminSplitDateTimeVerticalWidget(AdminSplitDateTime):
|
|
540
540
|
|
541
541
|
|
542
542
|
class UnfoldAdminIntegerFieldWidget(AdminIntegerFieldWidget):
|
543
|
-
def __init__(self, attrs: Optional[
|
543
|
+
def __init__(self, attrs: Optional[dict[str, Any]] = None) -> None:
|
544
544
|
super().__init__(
|
545
545
|
attrs={
|
546
546
|
**(attrs or {}),
|
@@ -552,7 +552,7 @@ class UnfoldAdminIntegerFieldWidget(AdminIntegerFieldWidget):
|
|
552
552
|
|
553
553
|
|
554
554
|
class UnfoldAdminDecimalFieldWidget(AdminIntegerFieldWidget):
|
555
|
-
def __init__(self, attrs: Optional[
|
555
|
+
def __init__(self, attrs: Optional[dict[str, Any]] = None) -> None:
|
556
556
|
super().__init__(
|
557
557
|
attrs={
|
558
558
|
**(attrs or {}),
|
@@ -564,7 +564,7 @@ class UnfoldAdminDecimalFieldWidget(AdminIntegerFieldWidget):
|
|
564
564
|
|
565
565
|
|
566
566
|
class UnfoldAdminBigIntegerFieldWidget(AdminBigIntegerFieldWidget):
|
567
|
-
def __init__(self, attrs: Optional[
|
567
|
+
def __init__(self, attrs: Optional[dict[str, Any]] = None) -> None:
|
568
568
|
super().__init__(
|
569
569
|
attrs={
|
570
570
|
**(attrs or {}),
|
@@ -621,7 +621,7 @@ class UnfoldAdminRadioSelectWidget(AdminRadioSelect):
|
|
621
621
|
self.radio_style = radio_style
|
622
622
|
self.attrs["class"] = " ".join([*RADIO_CLASSES, self.attrs.get("class", "")])
|
623
623
|
|
624
|
-
def get_context(self, *args, **kwargs) ->
|
624
|
+
def get_context(self, *args, **kwargs) -> dict[str, Any]:
|
625
625
|
context = super().get_context(*args, **kwargs)
|
626
626
|
context.update({"radio_style": self.radio_style})
|
627
627
|
return context
|
@@ -666,7 +666,7 @@ except ImportError:
|
|
666
666
|
|
667
667
|
class UnfoldBooleanWidget(CheckboxInput):
|
668
668
|
def __init__(
|
669
|
-
self, attrs: Optional[
|
669
|
+
self, attrs: Optional[dict[str, Any]] = None, check_test: Callable = None
|
670
670
|
) -> None:
|
671
671
|
if attrs is None:
|
672
672
|
attrs = {}
|
@@ -684,7 +684,7 @@ class UnfoldBooleanWidget(CheckboxInput):
|
|
684
684
|
|
685
685
|
class UnfoldBooleanSwitchWidget(CheckboxInput):
|
686
686
|
def __init__(
|
687
|
-
self, attrs: Optional[
|
687
|
+
self, attrs: Optional[dict[str, Any]] = None, check_test: Callable = None
|
688
688
|
) -> None:
|
689
689
|
super().__init__(
|
690
690
|
attrs={
|
@@ -708,7 +708,7 @@ class UnfoldForeignKeyRawIdWidget(ForeignKeyRawIdWidget):
|
|
708
708
|
self,
|
709
709
|
rel: ForeignObjectRel,
|
710
710
|
admin_site: AdminSite,
|
711
|
-
attrs: Optional[
|
711
|
+
attrs: Optional[dict] = None,
|
712
712
|
using: Optional[Any] = None,
|
713
713
|
) -> None:
|
714
714
|
attrs = {
|
File without changes
|