django-unfold 0.25.0__py3-none-any.whl → 0.26.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 (37) hide show
  1. {django_unfold-0.25.0.dist-info → django_unfold-0.26.0.dist-info}/METADATA +51 -6
  2. {django_unfold-0.25.0.dist-info → django_unfold-0.26.0.dist-info}/RECORD +36 -27
  3. unfold/admin.py +11 -3
  4. unfold/contrib/import_export/forms.py +17 -0
  5. unfold/contrib/import_export/templates/admin/import_export/change_form.html +10 -0
  6. unfold/contrib/import_export/templates/admin/import_export/export.html +38 -3
  7. unfold/contrib/import_export/templates/admin/import_export/import_form.html +8 -12
  8. unfold/contrib/import_export/templates/admin/import_export/resource_fields_list.html +1 -1
  9. unfold/contrib/inlines/__init__.py +0 -0
  10. unfold/contrib/inlines/admin.py +141 -0
  11. unfold/contrib/inlines/apps.py +6 -0
  12. unfold/contrib/inlines/checks.py +18 -0
  13. unfold/contrib/inlines/forms.py +43 -0
  14. unfold/forms.py +6 -0
  15. unfold/static/unfold/css/simplebar.css +230 -0
  16. unfold/static/unfold/css/styles.css +1 -1
  17. unfold/static/unfold/js/simplebar.js +10 -0
  18. unfold/styles.css +9 -1
  19. unfold/templates/admin/app_list.html +1 -1
  20. unfold/templates/admin/change_form.html +11 -9
  21. unfold/templates/admin/change_list_results.html +2 -2
  22. unfold/templates/admin/edit_inline/stacked.html +6 -6
  23. unfold/templates/admin/edit_inline/tabular.html +3 -3
  24. unfold/templates/admin/includes/fieldset.html +1 -1
  25. unfold/templates/unfold/helpers/app_list.html +1 -1
  26. unfold/templates/unfold/helpers/display_header.html +11 -8
  27. unfold/templates/unfold/helpers/field.html +20 -6
  28. unfold/templates/unfold/helpers/fieldsets_tabs.html +4 -4
  29. unfold/templates/unfold/helpers/form_label.html +1 -1
  30. unfold/templates/unfold/layouts/skeleton.html +2 -0
  31. unfold/templates/unfold/widgets/foreign_key_raw_id.html +21 -0
  32. unfold/templates/unfold/widgets/textarea.html +1 -7
  33. unfold/templates/unfold/widgets/textarea_expandable.html +7 -0
  34. unfold/widgets.py +36 -3
  35. unfold/contrib/import_export/admin.py +0 -37
  36. {django_unfold-0.25.0.dist-info → django_unfold-0.26.0.dist-info}/LICENSE.md +0 -0
  37. {django_unfold-0.25.0.dist-info → django_unfold-0.26.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,43 @@
1
+ from typing import Any, Callable, Optional
2
+
3
+ from django.db.models import Model, QuerySet
4
+ from django.forms import BaseModelFormSet, ModelForm, modelformset_factory
5
+
6
+
7
+ class NonrelatedInlineModelFormSet(BaseModelFormSet):
8
+ def __init__(
9
+ self,
10
+ instance: Optional[Model] = None,
11
+ save_as_new: bool = False,
12
+ **kwargs: Any,
13
+ ) -> None:
14
+ self.instance = instance
15
+ self.queryset = self.provided_queryset
16
+
17
+ super().__init__(**kwargs)
18
+
19
+ @classmethod
20
+ def get_default_prefix(cls: BaseModelFormSet) -> str:
21
+ return f"{cls.model._meta.app_label}-{cls.model._meta.model_name}"
22
+
23
+ def save_new(self, form: ModelForm, commit: bool = True):
24
+ obj = super().save_new(form, commit=False)
25
+ self.save_new_instance(self.instance, obj)
26
+
27
+ if commit:
28
+ obj.save()
29
+
30
+ return obj
31
+
32
+
33
+ def nonrelated_inline_formset_factory(
34
+ model: Model,
35
+ queryset: Optional[QuerySet] = None,
36
+ formset: BaseModelFormSet = NonrelatedInlineModelFormSet,
37
+ save_new_instance: Optional[Callable] = None,
38
+ **kwargs: Any,
39
+ ) -> BaseModelFormSet:
40
+ inline_formset = modelformset_factory(model, formset=formset, **kwargs)
41
+ inline_formset.provided_queryset = queryset
42
+ inline_formset.save_new_instance = save_new_instance
43
+ return inline_formset
unfold/forms.py CHANGED
@@ -10,6 +10,7 @@ from django.contrib.admin.forms import (
10
10
  from django.contrib.auth.forms import (
11
11
  AdminPasswordChangeForm as BaseAdminPasswordChangeForm,
12
12
  )
13
+ from django.contrib.auth.forms import ReadOnlyPasswordHashWidget
13
14
  from django.contrib.auth.forms import UserChangeForm as BaseUserChangeForm
14
15
  from django.contrib.auth.forms import UserCreationForm as BaseUserCreationForm
15
16
  from django.http import HttpRequest
@@ -19,6 +20,10 @@ from django.utils.translation import gettext_lazy as _
19
20
  from .widgets import BASE_INPUT_CLASSES, INPUT_CLASSES, SELECT_CLASSES
20
21
 
21
22
 
23
+ class UnfoldReadOnlyPasswordHashWidget(ReadOnlyPasswordHashWidget):
24
+ pass
25
+
26
+
22
27
  class ActionForm(forms.Form):
23
28
  action = forms.ChoiceField(
24
29
  label="",
@@ -72,6 +77,7 @@ class UserChangeForm(BaseUserChangeForm):
72
77
  **kwargs,
73
78
  ) -> None:
74
79
  super().__init__(request, *args, **kwargs)
80
+ self.fields["password"].widget = UnfoldReadOnlyPasswordHashWidget()
75
81
 
76
82
  self.fields["password"].help_text = _(
77
83
  "Raw passwords are not stored, so there is no way to see this "
@@ -0,0 +1,230 @@
1
+ [data-simplebar] {
2
+ position: relative;
3
+ flex-direction: column;
4
+ flex-wrap: wrap;
5
+ justify-content: flex-start;
6
+ align-content: flex-start;
7
+ align-items: flex-start;
8
+ }
9
+
10
+ .simplebar-wrapper {
11
+ overflow: hidden;
12
+ width: inherit;
13
+ height: inherit;
14
+ max-width: inherit;
15
+ max-height: inherit;
16
+ }
17
+
18
+ .simplebar-mask {
19
+ direction: inherit;
20
+ position: absolute;
21
+ overflow: hidden;
22
+ padding: 0;
23
+ margin: 0;
24
+ left: 0;
25
+ top: 0;
26
+ bottom: 0;
27
+ right: 0;
28
+ width: auto !important;
29
+ height: auto !important;
30
+ z-index: 0;
31
+ }
32
+
33
+ .simplebar-offset {
34
+ direction: inherit !important;
35
+ box-sizing: inherit !important;
36
+ resize: none !important;
37
+ position: absolute;
38
+ top: 0;
39
+ left: 0;
40
+ bottom: 0;
41
+ right: 0;
42
+ padding: 0;
43
+ margin: 0;
44
+ -webkit-overflow-scrolling: touch;
45
+ }
46
+
47
+ .simplebar-content-wrapper {
48
+ direction: inherit;
49
+ box-sizing: border-box !important;
50
+ position: relative;
51
+ display: block;
52
+ height: 100%; /* Required for horizontal native scrollbar to not appear if parent is taller than natural height */
53
+ width: auto;
54
+ max-width: 100%; /* Not required for horizontal scroll to trigger */
55
+ max-height: 100%; /* Needed for vertical scroll to trigger */
56
+ overflow: auto;
57
+ scrollbar-width: none;
58
+ -ms-overflow-style: none;
59
+ }
60
+
61
+ .simplebar-content-wrapper::-webkit-scrollbar,
62
+ .simplebar-hide-scrollbar::-webkit-scrollbar {
63
+ display: none;
64
+ width: 0;
65
+ height: 0;
66
+ }
67
+
68
+ .simplebar-content:before,
69
+ .simplebar-content:after {
70
+ content: ' ';
71
+ display: table;
72
+ }
73
+
74
+ .simplebar-placeholder {
75
+ max-height: 100%;
76
+ max-width: 100%;
77
+ width: 100%;
78
+ pointer-events: none;
79
+ }
80
+
81
+ .simplebar-height-auto-observer-wrapper {
82
+ box-sizing: inherit !important;
83
+ height: 100%;
84
+ width: 100%;
85
+ max-width: 1px;
86
+ position: relative;
87
+ float: left;
88
+ max-height: 1px;
89
+ overflow: hidden;
90
+ z-index: -1;
91
+ padding: 0;
92
+ margin: 0;
93
+ pointer-events: none;
94
+ flex-grow: inherit;
95
+ flex-shrink: 0;
96
+ flex-basis: 0;
97
+ }
98
+
99
+ .simplebar-height-auto-observer {
100
+ box-sizing: inherit;
101
+ display: block;
102
+ opacity: 0;
103
+ position: absolute;
104
+ top: 0;
105
+ left: 0;
106
+ height: 1000%;
107
+ width: 1000%;
108
+ min-height: 1px;
109
+ min-width: 1px;
110
+ overflow: hidden;
111
+ pointer-events: none;
112
+ z-index: -1;
113
+ }
114
+
115
+ .simplebar-track {
116
+ z-index: 1;
117
+ position: absolute;
118
+ right: 0;
119
+ bottom: 0;
120
+ pointer-events: none;
121
+ overflow: hidden;
122
+ }
123
+
124
+ [data-simplebar].simplebar-dragging {
125
+ pointer-events: none;
126
+ -webkit-touch-callout: none;
127
+ -webkit-user-select: none;
128
+ -khtml-user-select: none;
129
+ -moz-user-select: none;
130
+ -ms-user-select: none;
131
+ user-select: none;
132
+ }
133
+
134
+ [data-simplebar].simplebar-dragging .simplebar-content {
135
+ pointer-events: none;
136
+ -webkit-touch-callout: none;
137
+ -webkit-user-select: none;
138
+ -khtml-user-select: none;
139
+ -moz-user-select: none;
140
+ -ms-user-select: none;
141
+ user-select: none;
142
+ }
143
+
144
+ [data-simplebar].simplebar-dragging .simplebar-track {
145
+ pointer-events: all;
146
+ }
147
+
148
+ .simplebar-scrollbar {
149
+ position: absolute;
150
+ left: 0;
151
+ right: 0;
152
+ min-height: 10px;
153
+ }
154
+
155
+ .simplebar-scrollbar:before {
156
+ position: absolute;
157
+ content: '';
158
+ background: black;
159
+ border-radius: 7px;
160
+ left: 2px;
161
+ right: 2px;
162
+ opacity: 0;
163
+ transition: opacity 0.2s 0.5s linear;
164
+ }
165
+
166
+ .simplebar-scrollbar.simplebar-visible:before {
167
+ opacity: 0.5;
168
+ transition-delay: 0s;
169
+ transition-duration: 0s;
170
+ }
171
+
172
+ .simplebar-track.simplebar-vertical {
173
+ top: 0;
174
+ width: 11px;
175
+ }
176
+
177
+ .simplebar-scrollbar:before {
178
+ top: 2px;
179
+ bottom: 2px;
180
+ left: 2px;
181
+ right: 2px;
182
+ }
183
+
184
+ .simplebar-track.simplebar-horizontal {
185
+ left: 0;
186
+ height: 11px;
187
+ }
188
+
189
+ .simplebar-track.simplebar-horizontal .simplebar-scrollbar {
190
+ right: auto;
191
+ left: 0;
192
+ top: 0;
193
+ bottom: 0;
194
+ min-height: 0;
195
+ min-width: 10px;
196
+ width: auto;
197
+ }
198
+
199
+ /* Rtl support */
200
+ [data-simplebar-direction='rtl'] .simplebar-track.simplebar-vertical {
201
+ right: auto;
202
+ left: 0;
203
+ }
204
+
205
+ .simplebar-dummy-scrollbar-size {
206
+ direction: rtl;
207
+ position: fixed;
208
+ opacity: 0;
209
+ visibility: hidden;
210
+ height: 500px;
211
+ width: 500px;
212
+ overflow-y: hidden;
213
+ overflow-x: scroll;
214
+ -ms-overflow-style: scrollbar !important;
215
+ }
216
+
217
+ .simplebar-dummy-scrollbar-size > div {
218
+ width: 200%;
219
+ height: 200%;
220
+ margin: 10px 0;
221
+ }
222
+
223
+ .simplebar-hide-scrollbar {
224
+ position: fixed;
225
+ left: 0;
226
+ visibility: hidden;
227
+ overflow-y: scroll;
228
+ scrollbar-width: none;
229
+ -ms-overflow-style: none;
230
+ }