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.
Files changed (74) hide show
  1. {django_unfold-0.29.1.dist-info → django_unfold-0.31.0.dist-info}/METADATA +63 -19
  2. {django_unfold-0.29.1.dist-info → django_unfold-0.31.0.dist-info}/RECORD +74 -73
  3. unfold/admin.py +32 -11
  4. unfold/contrib/filters/templates/unfold/filters/filters_numeric_slider.html +3 -3
  5. unfold/contrib/forms/static/unfold/forms/js/trix.js +2 -2
  6. unfold/contrib/forms/templates/unfold/forms/array.html +3 -1
  7. unfold/contrib/forms/templates/unfold/forms/helpers/toolbar.html +6 -6
  8. unfold/contrib/forms/templates/unfold/forms/wysiwyg.html +1 -1
  9. unfold/contrib/forms/widgets.py +22 -11
  10. unfold/contrib/guardian/templates/unfold/guardian/group_form.html +4 -4
  11. unfold/contrib/guardian/templates/unfold/guardian/user_form.html +4 -4
  12. unfold/contrib/import_export/templates/admin/import_export/change_form.html +1 -1
  13. unfold/contrib/import_export/templates/admin/import_export/import_errors.html +1 -1
  14. unfold/contrib/import_export/templates/admin/import_export/import_preview.html +3 -3
  15. unfold/contrib/import_export/templates/admin/import_export/import_validation.html +4 -4
  16. unfold/contrib/inlines/forms.py +1 -2
  17. unfold/contrib/simple_history/templates/simple_history/object_history_list.html +9 -9
  18. unfold/contrib/simple_history/templates/simple_history/submit_line.html +1 -1
  19. unfold/dataclasses.py +10 -1
  20. unfold/fields.py +2 -2
  21. unfold/forms.py +18 -3
  22. unfold/settings.py +1 -0
  23. unfold/sites.py +39 -15
  24. unfold/static/unfold/css/styles.css +1 -1
  25. unfold/static/unfold/js/alpine.anchor.js +1 -0
  26. unfold/static/unfold/js/alpine.js +2 -2
  27. unfold/static/unfold/js/alpine.persist.js +1 -1
  28. unfold/static/unfold/js/app.js +45 -3
  29. unfold/styles.css +15 -11
  30. unfold/templates/admin/actions.html +1 -1
  31. unfold/templates/admin/app_list.html +1 -1
  32. unfold/templates/admin/base.html +4 -4
  33. unfold/templates/admin/change_list.html +2 -2
  34. unfold/templates/admin/change_list_results.html +3 -3
  35. unfold/templates/admin/delete_confirmation.html +4 -4
  36. unfold/templates/admin/delete_selected_confirmation.html +4 -4
  37. unfold/templates/admin/edit_inline/stacked.html +2 -2
  38. unfold/templates/admin/edit_inline/tabular.html +4 -4
  39. unfold/templates/admin/filter.html +2 -2
  40. unfold/templates/admin/includes/fieldset.html +1 -1
  41. unfold/templates/admin/includes/object_delete_summary.html +1 -1
  42. unfold/templates/admin/login.html +8 -8
  43. unfold/templates/admin/object_history.html +4 -4
  44. unfold/templates/admin/search_form.html +1 -1
  45. unfold/templates/admin/submit_line.html +7 -5
  46. unfold/templates/auth/widgets/read_only_password_hash.html +1 -1
  47. unfold/templates/registration/logged_out.html +1 -1
  48. unfold/templates/unfold/change_list_filter.html +10 -2
  49. unfold/templates/unfold/helpers/account_links.html +2 -2
  50. unfold/templates/unfold/helpers/actions_row.html +4 -4
  51. unfold/templates/unfold/helpers/app_list.html +48 -38
  52. unfold/templates/unfold/helpers/app_list_default.html +4 -4
  53. unfold/templates/unfold/helpers/breadcrumb_item.html +1 -1
  54. unfold/templates/unfold/helpers/field_readonly_value.html +1 -1
  55. unfold/templates/unfold/helpers/fieldset_row.html +7 -7
  56. unfold/templates/unfold/helpers/fieldsets_tabs.html +2 -2
  57. unfold/templates/unfold/helpers/header.html +1 -1
  58. unfold/templates/unfold/helpers/help_text.html +1 -1
  59. unfold/templates/unfold/helpers/history.html +1 -1
  60. unfold/templates/unfold/helpers/label.html +1 -1
  61. unfold/templates/unfold/helpers/search.html +7 -4
  62. unfold/templates/unfold/helpers/search_results.html +2 -2
  63. unfold/templates/unfold/helpers/tab_action.html +1 -1
  64. unfold/templates/unfold/helpers/tab_list.html +27 -5
  65. unfold/templates/unfold/helpers/theme_switch.html +2 -2
  66. unfold/templates/unfold/layouts/skeleton.html +6 -1
  67. unfold/templates/unfold/widgets/clearable_file_input.html +14 -6
  68. unfold/templates/unfold/widgets/clearable_file_input_small.html +4 -4
  69. unfold/templates/unfold/widgets/split_datetime.html +2 -2
  70. unfold/templatetags/unfold.py +33 -12
  71. unfold/templatetags/unfold_list.py +16 -6
  72. unfold/widgets.py +11 -4
  73. {django_unfold-0.29.1.dist-info → django_unfold-0.31.0.dist-info}/LICENSE.md +0 -0
  74. {django_unfold-0.29.1.dist-info → django_unfold-0.31.0.dist-info}/WHEEL +0 -0
unfold/admin.py CHANGED
@@ -1,6 +1,6 @@
1
1
  import copy
2
2
  from functools import update_wrapper
3
- from typing import Any, Callable, Dict, List, Optional, Tuple
3
+ from typing import Any, Callable, Dict, List, Optional, Tuple, Union
4
4
 
5
5
  from django import forms
6
6
  from django.contrib.admin import ModelAdmin as BaseModelAdmin
@@ -148,6 +148,7 @@ class ModelAdminMixin:
148
148
  else:
149
149
  kwargs["widget"] = UnfoldAdminSelectWidget()
150
150
 
151
+ if "choices" not in kwargs:
151
152
  kwargs["choices"] = db_field.get_choices(
152
153
  include_blank=db_field.blank, blank_choice=[("", _("Select value"))]
153
154
  )
@@ -227,7 +228,10 @@ class ModelAdmin(ModelAdminMixin, BaseModelAdmin):
227
228
  actions_submit_line = ()
228
229
  custom_urls = ()
229
230
  add_fieldsets = ()
231
+ list_horizontal_scrollbar_top = False
230
232
  list_filter_submit = False
233
+ list_fullwidth = False
234
+ compressed_fields = False
231
235
  readonly_preprocess_fields = {}
232
236
  checks_class = UnfoldModelAdminChecks
233
237
 
@@ -253,7 +257,10 @@ class ModelAdmin(ModelAdminMixin, BaseModelAdmin):
253
257
  return super().get_fieldsets(request, obj)
254
258
 
255
259
  def _filter_unfold_actions_by_permissions(
256
- self, request: HttpRequest, actions: List[UnfoldAction]
260
+ self,
261
+ request: HttpRequest,
262
+ actions: List[UnfoldAction],
263
+ object_id: Optional[Union[int, str]] = None,
257
264
  ) -> List[UnfoldAction]:
258
265
  """Filter out any Unfold actions that the user doesn't have access to."""
259
266
  filtered_actions = []
@@ -261,12 +268,22 @@ class ModelAdmin(ModelAdminMixin, BaseModelAdmin):
261
268
  if not hasattr(action.method, "allowed_permissions"):
262
269
  filtered_actions.append(action)
263
270
  continue
271
+
264
272
  permission_checks = (
265
273
  getattr(self, f"has_{permission}_permission")
266
274
  for permission in action.method.allowed_permissions
267
275
  )
268
- if any(has_permission(request) for has_permission in permission_checks):
269
- filtered_actions.append(action)
276
+
277
+ if object_id:
278
+ if any(
279
+ has_permission(request, object_id)
280
+ for has_permission in permission_checks
281
+ ):
282
+ filtered_actions.append(action)
283
+ else:
284
+ if any(has_permission(request) for has_permission in permission_checks):
285
+ filtered_actions.append(action)
286
+
270
287
  return filtered_actions
271
288
 
272
289
  def get_actions_list(self, request: HttpRequest) -> List[UnfoldAction]:
@@ -280,9 +297,11 @@ class ModelAdmin(ModelAdminMixin, BaseModelAdmin):
280
297
  """
281
298
  return [self.get_unfold_action(action) for action in self.actions_list or []]
282
299
 
283
- def get_actions_detail(self, request: HttpRequest) -> List[UnfoldAction]:
300
+ def get_actions_detail(
301
+ self, request: HttpRequest, object_id: int
302
+ ) -> List[UnfoldAction]:
284
303
  return self._filter_unfold_actions_by_permissions(
285
- request, self._get_base_actions_detail()
304
+ request, self._get_base_actions_detail(), object_id
286
305
  )
287
306
 
288
307
  def _get_base_actions_detail(self) -> List[UnfoldAction]:
@@ -302,9 +321,11 @@ class ModelAdmin(ModelAdminMixin, BaseModelAdmin):
302
321
  """
303
322
  return [self.get_unfold_action(action) for action in self.actions_row or []]
304
323
 
305
- def get_actions_submit_line(self, request: HttpRequest) -> List[UnfoldAction]:
324
+ def get_actions_submit_line(
325
+ self, request: HttpRequest, object_id: int
326
+ ) -> List[UnfoldAction]:
306
327
  return self._filter_unfold_actions_by_permissions(
307
- request, self._get_base_actions_submit_line()
328
+ request, self._get_base_actions_submit_line(), object_id
308
329
  )
309
330
 
310
331
  def _get_base_actions_submit_line(self) -> List[UnfoldAction]:
@@ -402,7 +423,7 @@ class ModelAdmin(ModelAdminMixin, BaseModelAdmin):
402
423
 
403
424
  actions = []
404
425
  if object_id:
405
- for action in self.get_actions_detail(request):
426
+ for action in self.get_actions_detail(request, object_id):
406
427
  actions.append(
407
428
  {
408
429
  "title": action.description,
@@ -416,7 +437,7 @@ class ModelAdmin(ModelAdminMixin, BaseModelAdmin):
416
437
 
417
438
  extra_context.update(
418
439
  {
419
- "actions_submit_line": self.get_actions_submit_line(request),
440
+ "actions_submit_line": self.get_actions_submit_line(request, object_id),
420
441
  "actions_detail": actions,
421
442
  }
422
443
  )
@@ -483,7 +504,7 @@ class ModelAdmin(ModelAdminMixin, BaseModelAdmin):
483
504
  ) -> None:
484
505
  super().save_model(request, obj, form, change)
485
506
 
486
- for action in self.get_actions_submit_line(request):
507
+ for action in self.get_actions_submit_line(request, obj.pk):
487
508
  if action.action_name not in request.POST:
488
509
  continue
489
510
 
@@ -9,11 +9,11 @@
9
9
 
10
10
  {% if choice.min is not None and choice.max is not None and choice.step %}
11
11
  <div class="admin-numeric-filter-slider-tooltips">
12
- <span class="admin-numeric-filter-slider-tooltip-from border cursor-not-allowed flex flex-grow flex-row items-center mr-auto rounded-md shadow-sm px-3 py-2 w-full dark:bg-gray-900 dark:border-gray-700 dark:text-gray-400">
12
+ <span class="admin-numeric-filter-slider-tooltip-from border cursor-not-allowed flex flex-grow flex-row items-center mr-auto rounded-md shadow-sm px-3 py-2 w-full dark:bg-gray-900 dark:border-gray-700 dark:text-gray-300">
13
13
  {{ choice.value_from }}
14
14
  </span>
15
15
 
16
- <span class="admin-numeric-filter-slider-tooltip-to border cursor-not-allowed flex flex-grow flex-row items-center rounded-md shadow-sm px-3 py-2 w-full dark:bg-gray-900 dark:border-gray-700 dark:text-gray-400">
16
+ <span class="admin-numeric-filter-slider-tooltip-to border cursor-not-allowed flex flex-grow flex-row items-center rounded-md shadow-sm px-3 py-2 w-full dark:bg-gray-900 dark:border-gray-700 dark:text-gray-300">
17
17
  {{ choice.value_to }}
18
18
  </span>
19
19
  </div>
@@ -25,7 +25,7 @@
25
25
  {{ choice.form.as_p }}
26
26
  </div>
27
27
  {% else %}
28
- <div class="admin-numeric-filter-slider-error dark:text-gray-400">
28
+ <div class="admin-numeric-filter-slider-error dark:text-gray-300">
29
29
  <p>
30
30
  {% trans 'Not enough data.' %}
31
31
  </p>