django-unfold 0.57.0__tar.gz → 0.59.0__tar.gz

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 (296) hide show
  1. {django_unfold-0.57.0 → django_unfold-0.59.0}/PKG-INFO +1 -1
  2. {django_unfold-0.57.0 → django_unfold-0.59.0}/pyproject.toml +5 -6
  3. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/checks.py +24 -2
  4. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/templates/unfold/filters/filters_numeric_slider.html +2 -2
  5. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/import_export/templates/admin/import_export/base.html +1 -5
  6. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/import_export/templates/admin/import_export/import_form.html +1 -1
  7. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/simple_history/templates/simple_history/object_history_form.html +1 -1
  8. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/decorators.py +28 -15
  9. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/fields.py +1 -1
  10. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/forms.py +4 -2
  11. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/layout.py +16 -0
  12. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/mixins/action_model_admin.py +22 -14
  13. django_unfold-0.59.0/src/unfold/paginator.py +21 -0
  14. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/settings.py +8 -1
  15. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/sites.py +87 -40
  16. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/admin/js/admin/RelatedObjectLookups.js +9 -3
  17. django_unfold-0.59.0/src/unfold/static/unfold/css/styles.css +2 -0
  18. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/styles.css +59 -104
  19. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/auth/user/change_password.html +1 -1
  20. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/base.html +1 -1
  21. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/change_form.html +2 -1
  22. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/edit_inline/stacked.html +1 -1
  23. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/includes/fieldset.html +9 -3
  24. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/login.html +1 -1
  25. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/pagination.html +1 -1
  26. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/submit_line.html +7 -7
  27. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/registration/password_change_done.html +1 -1
  28. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/registration/password_change_form.html +1 -1
  29. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/components/button.html +1 -1
  30. django_unfold-0.59.0/src/unfold/templates/unfold/components/card.html +27 -0
  31. django_unfold-0.59.0/src/unfold/templates/unfold/components/progress.html +23 -0
  32. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/components/table.html +5 -5
  33. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/account_links.html +14 -6
  34. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/change_list_actions.html +2 -2
  35. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/change_list_filter_actions.html +2 -2
  36. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/edit_inline/tabular_heading.html +1 -1
  37. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/empty_results.html +2 -2
  38. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/field.html +2 -2
  39. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/header.html +1 -1
  40. django_unfold-0.59.0/src/unfold/templates/unfold/helpers/language_form.html +10 -0
  41. django_unfold-0.59.0/src/unfold/templates/unfold/helpers/language_switch.html +25 -0
  42. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/navigation.html +1 -1
  43. django_unfold-0.59.0/src/unfold/templates/unfold/helpers/pagination_infinite.html +11 -0
  44. django_unfold-0.59.0/src/unfold/templates/unfold/helpers/theme_switch.html +34 -0
  45. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/userlinks.html +2 -6
  46. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/welcomemsg.html +9 -7
  47. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/widgets/select.html +1 -1
  48. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold_crispy/field.html +1 -1
  49. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold_crispy/layout/checkbox.html +2 -2
  50. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold_crispy/layout/fieldset.html +4 -2
  51. django_unfold-0.59.0/src/unfold/templates/unfold_crispy/layout/fieldset_subheader.html +3 -0
  52. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold_crispy/layout/table_inline_formset.html +18 -16
  53. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templatetags/unfold.py +20 -1
  54. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/utils.py +2 -2
  55. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/widgets.py +10 -4
  56. django_unfold-0.57.0/src/unfold/paginator.py +0 -10
  57. django_unfold-0.57.0/src/unfold/static/unfold/css/styles.css +0 -2
  58. django_unfold-0.57.0/src/unfold/templates/unfold/components/card.html +0 -27
  59. django_unfold-0.57.0/src/unfold/templates/unfold/components/progress.html +0 -21
  60. django_unfold-0.57.0/src/unfold/templates/unfold/helpers/language_switch.html +0 -27
  61. django_unfold-0.57.0/src/unfold/templates/unfold/helpers/pagination_infinite.html +0 -11
  62. django_unfold-0.57.0/src/unfold/templates/unfold/helpers/theme_switch.html +0 -32
  63. {django_unfold-0.57.0 → django_unfold-0.59.0}/LICENSE.md +0 -0
  64. {django_unfold-0.57.0 → django_unfold-0.59.0}/README.md +0 -0
  65. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/__init__.py +0 -0
  66. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/admin.py +0 -0
  67. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/apps.py +0 -0
  68. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/components.py +0 -0
  69. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/__init__.py +0 -0
  70. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/__init__.py +0 -0
  71. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/admin/__init__.py +0 -0
  72. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/admin/autocomplete_filters.py +0 -0
  73. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/admin/choice_filters.py +0 -0
  74. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/admin/datetime_filters.py +0 -0
  75. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/admin/dropdown_filters.py +0 -0
  76. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/admin/mixins.py +0 -0
  77. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/admin/numeric_filters.py +0 -0
  78. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/admin/text_filters.py +0 -0
  79. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/apps.py +0 -0
  80. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/forms.py +0 -0
  81. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/static/unfold/filters/css/nouislider/LICENSE +0 -0
  82. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/static/unfold/filters/css/nouislider/nouislider.min.css +0 -0
  83. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/static/unfold/filters/js/DateTimeShortcuts.js +0 -0
  84. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/static/unfold/filters/js/admin-numeric-filter.js +0 -0
  85. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/static/unfold/filters/js/nouislider/LICENSE +0 -0
  86. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/static/unfold/filters/js/nouislider/nouislider.min.js +0 -0
  87. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/static/unfold/filters/js/wnumb/LICENSE +0 -0
  88. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/static/unfold/filters/js/wnumb/wNumb.min.js +0 -0
  89. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/templates/unfold/filters/filters_date_range.html +0 -0
  90. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/templates/unfold/filters/filters_datetime_range.html +0 -0
  91. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/templates/unfold/filters/filters_field.html +0 -0
  92. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/templates/unfold/filters/filters_numeric_range.html +0 -0
  93. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/filters/templates/unfold/filters/filters_numeric_single.html +0 -0
  94. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/forms/__init__.py +0 -0
  95. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/forms/apps.py +0 -0
  96. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/forms/static/unfold/forms/css/trix/LICENSE +0 -0
  97. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/forms/static/unfold/forms/css/trix/trix.css +0 -0
  98. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/forms/static/unfold/forms/js/trix/LICENSE +0 -0
  99. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/forms/static/unfold/forms/js/trix/trix.js +0 -0
  100. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/forms/static/unfold/forms/js/trix.config.js +0 -0
  101. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/forms/templates/unfold/forms/array.html +0 -0
  102. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/forms/templates/unfold/forms/helpers/toolbar.html +0 -0
  103. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/forms/templates/unfold/forms/wysiwyg.html +0 -0
  104. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/forms/widgets.py +0 -0
  105. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/guardian/__init__.py +0 -0
  106. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/guardian/apps.py +0 -0
  107. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/guardian/templates/admin/guardian/model/change_form.html +0 -0
  108. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/guardian/templates/admin/guardian/model/field.html +0 -0
  109. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/guardian/templates/admin/guardian/model/obj_perms_manage.html +0 -0
  110. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/guardian/templates/admin/guardian/model/obj_perms_manage_group.html +0 -0
  111. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/guardian/templates/admin/guardian/model/obj_perms_manage_user.html +0 -0
  112. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/guardian/templates/unfold/guardian/group_form.html +0 -0
  113. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/guardian/templates/unfold/guardian/user_form.html +0 -0
  114. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/import_export/__init__.py +0 -0
  115. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/import_export/apps.py +0 -0
  116. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/import_export/forms.py +0 -0
  117. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/import_export/templates/admin/import_export/change_form.html +0 -0
  118. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/import_export/templates/admin/import_export/change_list_export.html +0 -0
  119. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/import_export/templates/admin/import_export/change_list_export_item.html +0 -0
  120. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/import_export/templates/admin/import_export/change_list_import_export.html +0 -0
  121. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/import_export/templates/admin/import_export/change_list_import_item.html +0 -0
  122. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/import_export/templates/admin/import_export/export.html +0 -0
  123. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/import_export/templates/admin/import_export/import.html +0 -0
  124. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/import_export/templates/admin/import_export/import_confirm.html +0 -0
  125. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/import_export/templates/admin/import_export/import_errors.html +0 -0
  126. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/import_export/templates/admin/import_export/import_preview.html +0 -0
  127. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/import_export/templates/admin/import_export/import_validation.html +0 -0
  128. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/import_export/templates/admin/import_export/resource_fields_list.html +0 -0
  129. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/inlines/__init__.py +0 -0
  130. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/inlines/admin.py +0 -0
  131. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/inlines/apps.py +0 -0
  132. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/inlines/checks.py +0 -0
  133. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/inlines/forms.py +0 -0
  134. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/simple_history/__init__.py +0 -0
  135. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/simple_history/apps.py +0 -0
  136. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/simple_history/templates/simple_history/object_history.html +0 -0
  137. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/simple_history/templates/simple_history/object_history_list.html +0 -0
  138. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/contrib/simple_history/templates/simple_history/submit_line.html +0 -0
  139. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/dataclasses.py +0 -0
  140. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/enums.py +0 -0
  141. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/exceptions.py +0 -0
  142. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/mixins/__init__.py +0 -0
  143. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/mixins/base_model_admin.py +0 -0
  144. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/overrides.py +0 -0
  145. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/sections.py +0 -0
  146. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/admin/js/inlines.js +0 -0
  147. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/css/simplebar/LICENSE +0 -0
  148. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/css/simplebar/simplebar.css +0 -0
  149. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/fonts/inter/Inter-Bold.woff2 +0 -0
  150. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/fonts/inter/Inter-Medium.woff2 +0 -0
  151. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/fonts/inter/Inter-Regular.woff2 +0 -0
  152. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/fonts/inter/Inter-SemiBold.woff2 +0 -0
  153. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/fonts/inter/LICENSE +0 -0
  154. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/fonts/inter/styles.css +0 -0
  155. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/fonts/material-symbols/LICENSE +0 -0
  156. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/fonts/material-symbols/Material-Symbols-Outlined.woff2 +0 -0
  157. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/fonts/material-symbols/styles.css +0 -0
  158. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/js/alpine/LICENSE +0 -0
  159. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/js/alpine/alpine.anchor.js +0 -0
  160. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/js/alpine/alpine.js +0 -0
  161. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/js/alpine/alpine.persist.js +0 -0
  162. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/js/alpine/alpine.resize.js +0 -0
  163. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/js/alpine/alpine.sort.js +0 -0
  164. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/js/app.js +0 -0
  165. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/js/chart/LICENSE +0 -0
  166. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/js/chart/chart.js +0 -0
  167. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/js/htmx/LICENSE +0 -0
  168. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/js/htmx/htmx.js +0 -0
  169. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/js/select2.init.js +0 -0
  170. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/js/simplebar/LICENSE +0 -0
  171. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/static/unfold/js/simplebar/simplebar.js +0 -0
  172. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/actions.html +0 -0
  173. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/app_index.html +0 -0
  174. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/app_list.html +0 -0
  175. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/auth/user/add_form.html +0 -0
  176. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/base_site.html +0 -0
  177. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/change_form_object_tools.html +0 -0
  178. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/change_list.html +0 -0
  179. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/change_list_object_tools.html +0 -0
  180. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/change_list_results.html +0 -0
  181. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/date_hierarchy.html +0 -0
  182. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/delete_confirmation.html +0 -0
  183. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/delete_selected_confirmation.html +0 -0
  184. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/edit_inline/tabular.html +0 -0
  185. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/filter.html +0 -0
  186. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/includes/object_delete_summary.html +0 -0
  187. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/index.html +0 -0
  188. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/nav_sidebar.html +0 -0
  189. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/object_history.html +0 -0
  190. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/admin/search_form.html +0 -0
  191. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/auth/widgets/read_only_password_hash.html +0 -0
  192. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/registration/logged_out.html +0 -0
  193. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/components/chart/bar.html +0 -0
  194. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/components/chart/cohort.html +0 -0
  195. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/components/chart/line.html +0 -0
  196. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/components/container.html +0 -0
  197. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/components/flex.html +0 -0
  198. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/components/icon.html +0 -0
  199. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/components/navigation.html +0 -0
  200. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/components/separator.html +0 -0
  201. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/components/text.html +0 -0
  202. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/components/title.html +0 -0
  203. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/components/tracker.html +0 -0
  204. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/actions_row.html +0 -0
  205. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/add_link.html +0 -0
  206. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/app_list.html +0 -0
  207. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/app_list_default.html +0 -0
  208. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/attrs.html +0 -0
  209. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/boolean.html +0 -0
  210. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/breadcrumb_item.html +0 -0
  211. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/change_list_filter.html +0 -0
  212. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/delete_submit_line.html +0 -0
  213. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/display_dropdown.html +0 -0
  214. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/display_header.html +0 -0
  215. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/display_label.html +0 -0
  216. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/edit_inline/tabular_delete.html +0 -0
  217. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/edit_inline/tabular_error.html +0 -0
  218. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/edit_inline/tabular_field.html +0 -0
  219. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/edit_inline/tabular_row.html +0 -0
  220. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/edit_inline/tabular_title.html +0 -0
  221. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/field_readonly.html +0 -0
  222. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/field_readonly_value.html +0 -0
  223. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/fieldset_row.html +0 -0
  224. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/fieldset_row_checkbox.html +0 -0
  225. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/fieldset_row_field.html +0 -0
  226. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/fieldsets_tabs.html +0 -0
  227. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/form_errors.html +0 -0
  228. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/form_label.html +0 -0
  229. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/header_back_button.html +0 -0
  230. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/help_text.html +0 -0
  231. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/history.html +0 -0
  232. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/label.html +0 -0
  233. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/messages/debug.html +0 -0
  234. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/messages/error.html +0 -0
  235. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/messages/errornote.html +0 -0
  236. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/messages/info.html +0 -0
  237. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/messages/success.html +0 -0
  238. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/messages/warning.html +0 -0
  239. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/messages.html +0 -0
  240. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/navigation_header.html +0 -0
  241. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/pagination.html +0 -0
  242. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/pagination_current_item.html +0 -0
  243. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/pagination_default.html +0 -0
  244. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/pagination_ellipsis.html +0 -0
  245. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/search.html +0 -0
  246. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/search_results.html +0 -0
  247. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/site_branding.html +0 -0
  248. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/site_dropdown.html +0 -0
  249. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/site_icon.html +0 -0
  250. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/site_logo.html +0 -0
  251. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/submit.html +0 -0
  252. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/tab_action.html +0 -0
  253. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/tab_actions.html +0 -0
  254. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/tab_items.html +0 -0
  255. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/helpers/tab_list.html +0 -0
  256. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/layouts/base.html +0 -0
  257. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/layouts/base_simple.html +0 -0
  258. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/layouts/skeleton.html +0 -0
  259. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/templatetags/preserve_changelist_filters.html +0 -0
  260. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/widgets/clearable_file_input.html +0 -0
  261. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/widgets/clearable_file_input_small.html +0 -0
  262. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/widgets/date.html +0 -0
  263. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/widgets/foreign_key_raw_id.html +0 -0
  264. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/widgets/radio.html +0 -0
  265. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/widgets/radio_option.html +0 -0
  266. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/widgets/range.html +0 -0
  267. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/widgets/related_widget_wrapper.html +0 -0
  268. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/widgets/split_datetime.html +0 -0
  269. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/widgets/split_datetime_vertical.html +0 -0
  270. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/widgets/split_money.html +0 -0
  271. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/widgets/textarea.html +0 -0
  272. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/widgets/time.html +0 -0
  273. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold/widgets/url.html +0 -0
  274. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold_crispy/display_form.html +0 -0
  275. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold_crispy/errors.html +0 -0
  276. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold_crispy/errors_formset.html +0 -0
  277. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold_crispy/inputs.html +0 -0
  278. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold_crispy/layout/attrs.html +0 -0
  279. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold_crispy/layout/baseinput.html +0 -0
  280. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold_crispy/layout/button.html +0 -0
  281. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold_crispy/layout/buttonholder.html +0 -0
  282. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold_crispy/layout/column.html +0 -0
  283. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold_crispy/layout/div.html +0 -0
  284. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold_crispy/layout/field_errors.html +0 -0
  285. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold_crispy/layout/help_text.html +0 -0
  286. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold_crispy/layout/help_text_and_errors.html +0 -0
  287. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold_crispy/layout/hr.html +0 -0
  288. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold_crispy/layout/radio_checkbox_select.html +0 -0
  289. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold_crispy/layout/row.html +0 -0
  290. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold_crispy/uni_form.html +0 -0
  291. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold_crispy/whole_uni_form.html +0 -0
  292. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templates/unfold_crispy/whole_uni_formset.html +0 -0
  293. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templatetags/__init__.py +0 -0
  294. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/templatetags/unfold_list.py +0 -0
  295. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/typing.py +0 -0
  296. {django_unfold-0.57.0 → django_unfold-0.59.0}/src/unfold/views.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: django-unfold
3
- Version: 0.57.0
3
+ Version: 0.59.0
4
4
  Summary: Modern Django admin theme for seamless interface development
5
5
  License: MIT
6
6
  Keywords: django,admin,tailwind,theme
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "django-unfold"
3
- version = "0.57.0"
3
+ version = "0.59.0"
4
4
  description = "Modern Django admin theme for seamless interface development"
5
5
  license = "MIT"
6
6
  readme = "README.md"
@@ -28,13 +28,12 @@ django = ">=4.2"
28
28
 
29
29
  [tool.poetry.group.test.dependencies]
30
30
  pytest = "^8.3"
31
- pytest-django = "^4.9"
32
- tox = "^4.21"
33
- django-money = "^3.5.3"
34
-
31
+ pytest-django = "^4.11"
32
+ tox = "^4.26"
33
+ django-money = "^3.5"
35
34
 
36
35
  [tool.poetry.group.dev.dependencies]
37
- python-semantic-release = "^8.7"
36
+ python-semantic-release = "^9.21"
38
37
 
39
38
  [tool.ruff]
40
39
  fix = true
@@ -2,9 +2,10 @@ from typing import Any
2
2
 
3
3
  from django.contrib.admin.checks import ModelAdminChecks
4
4
  from django.contrib.admin.options import BaseModelAdmin
5
+ from django.contrib.auth.models import Permission
5
6
  from django.core import checks
6
7
 
7
- from .dataclasses import UnfoldAction
8
+ from unfold.dataclasses import UnfoldAction
8
9
 
9
10
 
10
11
  class UnfoldModelAdminChecks(ModelAdminChecks):
@@ -29,14 +30,35 @@ class UnfoldModelAdminChecks(ModelAdminChecks):
29
30
  for action in actions:
30
31
  if not hasattr(action.method, "allowed_permissions"):
31
32
  continue
33
+
32
34
  for permission in action.method.allowed_permissions:
35
+ # Check the existence of Django permission
36
+ if "." in permission:
37
+ app_label, codename = permission.split(".")
38
+
39
+ if not Permission.objects.filter(
40
+ content_type__app_label=app_label,
41
+ codename=codename,
42
+ ).exists():
43
+ errors.append(
44
+ checks.Error(
45
+ f"@action decorator on {action.method.original_function_name}() in class {obj.__class__.__name__} specifies permission {permission} which does not exists.",
46
+ obj=obj.__class__,
47
+ id="admin.E129",
48
+ )
49
+ )
50
+
51
+ continue
52
+
53
+ # Check the permission method existence
33
54
  method_name = f"has_{permission}_permission"
34
55
  if not hasattr(obj, method_name):
35
56
  errors.append(
36
57
  checks.Error(
37
- f"{obj.__class__.__name__} must define a {method_name}() method for the {action.method.__name__} action.",
58
+ f"{obj.__class__.__name__} must define a {method_name}() method for the {action.method.original_function_name}() action.",
38
59
  obj=obj.__class__,
39
60
  id="admin.E129",
40
61
  )
41
62
  )
63
+
42
64
  return errors
@@ -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 grow flex-row items-center mr-auto rounded-default shadow-xs px-3 py-2 w-full dark:bg-base-900 dark:border-base-700 dark:text-font-default-dark">
12
+ <span class="admin-numeric-filter-slider-tooltip-from border border-base-200 cursor-not-allowed flex grow flex-row items-center mr-auto rounded-default shadow-xs px-3 py-2 w-full dark:bg-base-900 dark:border-base-700 dark:text-font-default-dark">
13
13
  {{ choice.value_from }}
14
14
  </span>
15
15
 
16
- <span class="admin-numeric-filter-slider-tooltip-to border cursor-not-allowed flex grow flex-row items-center rounded-default shadow-xs px-3 py-2 w-full dark:bg-base-900 dark:border-base-700 dark:text-font-default-dark">
16
+ <span class="admin-numeric-filter-slider-tooltip-to border border-base-200 cursor-not-allowed flex grow flex-row items-center rounded-default shadow-xs px-3 py-2 w-full dark:bg-base-900 dark:border-base-700 dark:text-font-default-dark">
17
17
  {{ choice.value_to }}
18
18
  </span>
19
19
  </div>
@@ -1,11 +1,7 @@
1
1
  {% extends "admin/base_site.html" %}
2
2
  {% load admin_modify admin_urls i18n static %}
3
3
 
4
- {% block extrastyle %}
5
- {{ block.super }}
6
-
7
- <link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}" />
8
- {% endblock %}
4
+ {% block extrastyle %}{{ block.super }}{% endblock %}
9
5
 
10
6
  {% block bodyclass %}
11
7
  {{ block.super }} {{ opts.app_label }}-{{ opts.object_name.lower }} change-form
@@ -6,7 +6,7 @@
6
6
 
7
7
  {% include "admin/import_export/resource_fields_list.html" with import_or_export="import" %}
8
8
 
9
- <fieldset class="border border-base-200 mb-8 rounded-default pt-3 px-3 shadow-xs dark:border-base-800">
9
+ <fieldset class="border border-base-200 mb-8 rounded-default pt-2.5 px-3 shadow-xs dark:border-base-800">
10
10
  {% for field in form %}
11
11
  {% if field.field.widget.attrs.readonly %}
12
12
  {% include "unfold/helpers/field_readonly.html" with title=field.label value=field.field.value %}
@@ -43,7 +43,7 @@
43
43
  {% endblock %}
44
44
 
45
45
  {% block form_top %}
46
- <p class="px-3 py-3 rounded-default text-sm last:mb-8 er-amber-600/10 bg-blue-50 mb-8 text-blue-500 dark:bg-blue-500/20 dark:border-blue-500/10">
46
+ <p class="px-3 py-3 rounded-default text-sm last:mb-8 bg-blue-50 mb-8 text-blue-500 dark:bg-blue-500/20">
47
47
  {% if not revert_disabled %}
48
48
  {% blocktrans %}Press the 'Revert' button below to revert to this version of the object.{% endblocktrans %}
49
49
  {% endif %}
@@ -8,8 +8,7 @@ from django.db.models.expressions import BaseExpression, Combinable
8
8
  from django.http import HttpRequest, HttpResponse
9
9
 
10
10
  from unfold.enums import ActionVariant
11
-
12
- from .typing import ActionFunction
11
+ from unfold.typing import ActionFunction
13
12
 
14
13
 
15
14
  def action(
@@ -30,13 +29,19 @@ def action(
30
29
  **kwargs,
31
30
  ) -> Optional[HttpResponse]:
32
31
  if permissions:
33
- permission_checks = (
34
- getattr(model_admin, f"has_{permission}_permission")
35
- for permission in permissions
36
- )
37
- # Permissions methods have following syntax: has_<some>_permission(self, request, obj=None):
38
- # But obj is not examined by default in django admin and it would also require additional
39
- # fetch from database, therefore it is not supported yet
32
+ permission_rules = []
33
+
34
+ for permission in permissions:
35
+ if "." in permission:
36
+ permission_rules.append(permission)
37
+ else:
38
+ # Permissions methods have following syntax: has_<some>_permission(self, request, obj=None):
39
+ # But obj is not examined by default in django admin and it would also require additional
40
+ # fetch from database, therefore it is not supported yet
41
+ permission_rules.append(
42
+ getattr(model_admin, f"has_{permission}_permission")
43
+ )
44
+
40
45
  has_detail_action = func.__name__ in model_admin._extract_action_names(
41
46
  model_admin.actions_detail
42
47
  )
@@ -47,12 +52,19 @@ def action(
47
52
  )
48
53
  )
49
54
 
50
- if not all(
51
- has_permission(request, kwargs.get("object_id"))
52
- if has_detail_action or has_submit_line_action
53
- else has_permission(request)
54
- for has_permission in permission_checks
55
- ):
55
+ permission_checks = []
56
+
57
+ for permission_rule in permission_rules:
58
+ if isinstance(permission_rule, str) and "." in permission_rule:
59
+ permission_checks.append(request.user.has_perm(permission_rule))
60
+ elif has_detail_action or has_submit_line_action:
61
+ permission_checks.append(
62
+ permission_rule(request, kwargs.get("object_id"))
63
+ )
64
+ else:
65
+ permission_checks.append(permission_rule(request))
66
+
67
+ if not all(permission_checks):
56
68
  raise PermissionDenied
57
69
  return func(model_admin, request, *args, **kwargs)
58
70
 
@@ -74,6 +86,7 @@ def action(
74
86
  inner.variant = ActionVariant.DEFAULT
75
87
 
76
88
  inner.attrs = attrs or {}
89
+ inner.original_function_name = func.__name__
77
90
  return inner
78
91
 
79
92
  if function is None:
@@ -140,7 +140,7 @@ class UnfoldAdminReadonlyField(helpers.AdminReadonlyField):
140
140
  ):
141
141
  result_repr = self.get_admin_url(f.remote_field, value)
142
142
  elif isinstance(f, models.JSONField):
143
- formatted_output = prettify_json(value)
143
+ formatted_output = prettify_json(value, f.encoder)
144
144
 
145
145
  if formatted_output:
146
146
  return formatted_output
@@ -43,15 +43,17 @@ class ActionForm(forms.Form):
43
43
  "class": " ".join(
44
44
  [
45
45
  "appearance-none",
46
- "bg-white/20",
46
+ "!bg-white/20",
47
47
  "font-medium",
48
48
  "grow",
49
49
  "px-3",
50
50
  "py-2",
51
51
  "pr-8",
52
52
  "rounded-default",
53
- "text-white",
53
+ "!text-white",
54
54
  "truncate",
55
+ "!outline-primary-400",
56
+ "dark:!outline-primary-700",
55
57
  "*:text-base-700",
56
58
  "lg:w-72",
57
59
  ]
@@ -25,6 +25,22 @@ class Button(ButtonClassesMixin, BaseInput):
25
25
  input_type = "button"
26
26
 
27
27
 
28
+ class FieldsetSubheader(LayoutObject):
29
+ template = "unfold_crispy/layout/fieldset_subheader.html"
30
+
31
+ def __init__(self, title=None, *args, **kwargs):
32
+ self.title = title
33
+ super().__init__(*args, **kwargs)
34
+
35
+ def render(self, form, context, template_pack=TEMPLATE_PACK, **kwargs):
36
+ return render_to_string(
37
+ self.template,
38
+ {
39
+ "title": self.title,
40
+ },
41
+ )
42
+
43
+
28
44
  class Hr(LayoutObject):
29
45
  template = "unfold_crispy/layout/hr.html"
30
46
 
@@ -316,19 +316,27 @@ class ActionModelAdminMixin:
316
316
  filtered_actions.append(action)
317
317
  continue
318
318
 
319
- permission_checks = (
320
- getattr(self, f"has_{permission}_permission")
321
- for permission in action.method.allowed_permissions
322
- )
323
-
324
- if object_id:
325
- if all(
326
- has_permission(request, object_id)
327
- for has_permission in permission_checks
328
- ):
329
- filtered_actions.append(action)
330
- else:
331
- if all(has_permission(request) for has_permission in permission_checks):
332
- filtered_actions.append(action)
319
+ permission_rules = []
320
+
321
+ for permission in action.method.allowed_permissions:
322
+ if "." in permission:
323
+ permission_rules.append(permission)
324
+ else:
325
+ permission_rules.append(
326
+ getattr(self, f"has_{permission}_permission")
327
+ )
328
+
329
+ permission_checks = []
330
+
331
+ for permission_rule in permission_rules:
332
+ if isinstance(permission_rule, str) and "." in permission_rule:
333
+ permission_checks.append(request.user.has_perm(permission_rule))
334
+ elif object_id:
335
+ permission_checks.append(permission_rule(request, object_id))
336
+ else:
337
+ permission_checks.append(permission_rule(request))
338
+
339
+ if all(permission_checks):
340
+ filtered_actions.append(action)
333
341
 
334
342
  return filtered_actions
@@ -0,0 +1,21 @@
1
+ from django.core.paginator import Page, Paginator
2
+ from django.utils.functional import cached_property
3
+
4
+
5
+ class InfinitePage(Page):
6
+ def has_next(self):
7
+ if len(self.object_list) == 0:
8
+ return False
9
+
10
+ return self.number < self.paginator.num_pages
11
+
12
+
13
+ class InfinitePaginator(Paginator):
14
+ template_name = "unfold/helpers/pagination_infinite.html"
15
+
16
+ @cached_property
17
+ def count(self):
18
+ return 9_999_999_999
19
+
20
+ def _get_page(self, *args, **kwargs):
21
+ return InfinitePage(*args, **kwargs)
@@ -57,10 +57,17 @@ CONFIG_DEFAULTS = {
57
57
  "ENVIRONMENT_TITLE_PREFIX": None,
58
58
  "STYLES": [],
59
59
  "SCRIPTS": [],
60
+ "ACCOUNT": {
61
+ "navigation": [],
62
+ },
63
+ "LANGUAGES": {
64
+ "action": None,
65
+ "navigation": [],
66
+ },
60
67
  "SIDEBAR": {
61
68
  "show_search": False,
62
69
  "show_all_applications": False,
63
- "navigation": {},
70
+ "navigation": [],
64
71
  },
65
72
  "TABS": [],
66
73
  "LOGIN": {
@@ -102,6 +102,13 @@ class UnfoldAdminSite(AdminSite):
102
102
  "environment_title_prefix": self._get_config(
103
103
  "ENVIRONMENT_TITLE_PREFIX", request
104
104
  ),
105
+ "languages_list": self._get_value(
106
+ self._get_config("LANGUAGES", request).get("navigation"), request
107
+ ),
108
+ "languages_action": self._get_value(
109
+ self._get_config("LANGUAGES", request).get("action"), request
110
+ ),
111
+ "account_links": self._get_account_links(request),
105
112
  "tab_list": self.get_tabs_list(request),
106
113
  "styles": self._get_list("STYLES", request),
107
114
  "scripts": self._get_list("SCRIPTS", request),
@@ -243,58 +250,75 @@ class UnfoldAdminSite(AdminSite):
243
250
  results = []
244
251
 
245
252
  for group in copy.deepcopy(navigation):
246
- allowed_items = []
253
+ group["items"] = self._get_navigation_items(request, group["items"], tabs)
254
+ results.append(group)
247
255
 
248
- for item in group["items"]:
249
- if "active" in item:
250
- item["active"] = self._get_value(item["active"], request)
251
- else:
252
- item["active"] = self._get_is_active(
253
- request, item.get("link_callback") or item["link"]
254
- )
256
+ return results
255
257
 
256
- # Checks if any tab item is active and then marks the sidebar link as active
257
- for tab in tabs:
258
- has_primary_link = False
259
- has_tab_link_active = False
258
+ def _get_navigation_items(
259
+ self, request: HttpRequest, items: list[dict], tabs: list[dict] = None
260
+ ) -> list:
261
+ allowed_items = []
260
262
 
261
- for tab_item in tab["items"]:
262
- if item["link"] == tab_item["link"]:
263
- has_primary_link = True
264
- continue
263
+ for item in items:
264
+ link = item.get("link")
265
265
 
266
- if self._get_is_active(
267
- request, tab_item.get("link_callback") or tab_item["link"]
268
- ):
269
- has_tab_link_active = True
270
- break
266
+ if "active" in item:
267
+ item["active"] = self._get_value(item["active"], request)
268
+ else:
269
+ item["active"] = self._get_is_active(
270
+ request, item.get("link_callback") or link
271
+ )
271
272
 
272
- if has_primary_link and has_tab_link_active:
273
- item["active"] = True
273
+ # Checks if any tab item is active and then marks the sidebar link as active
274
+ if (
275
+ tabs
276
+ and (is_active := self._get_is_tab_active(request, tabs, link))
277
+ and is_active
278
+ ):
279
+ item["active"] = True
274
280
 
275
- if isinstance(item["link"], Callable):
276
- item["link_callback"] = lazy(item["link"])(request)
281
+ # Link callback
282
+ if isinstance(link, Callable):
283
+ item["link_callback"] = lazy(link)(request)
277
284
 
278
- # Permission callback
279
- item["has_permission"] = self._call_permission_callback(
280
- item.get("permission"), request
281
- )
285
+ # Permission callback
286
+ item["has_permission"] = self._call_permission_callback(
287
+ item.get("permission"), request
288
+ )
282
289
 
283
- # Badge callbacks
284
- if "badge" in item and isinstance(item["badge"], str):
285
- try:
286
- callback = import_string(item["badge"])
287
- item["badge_callback"] = lazy(callback)(request)
288
- except ImportError:
289
- pass
290
+ # Badge callbacks
291
+ if "badge" in item and isinstance(item["badge"], str):
292
+ try:
293
+ callback = import_string(item["badge"])
294
+ item["badge_callback"] = lazy(callback)(request)
295
+ except ImportError:
296
+ pass
290
297
 
291
- allowed_items.append(item)
298
+ # Process nested items
299
+ if "items" in item:
300
+ item["items"] = self._get_navigation_items(request, item["items"])
292
301
 
293
- group["items"] = allowed_items
302
+ allowed_items.append(item)
294
303
 
295
- results.append(group)
304
+ return allowed_items
296
305
 
297
- return results
306
+ def _get_account_links(self, request: HttpRequest) -> list[dict[str, Any]]:
307
+ links = []
308
+
309
+ navigation = self._get_value(
310
+ get_config(self.settings_name)["ACCOUNT"].get("navigation"), request
311
+ )
312
+
313
+ for item in navigation:
314
+ links.append(
315
+ {
316
+ "title": self._get_value(item["title"], request),
317
+ "link": self._get_value(item["link"], request),
318
+ }
319
+ )
320
+
321
+ return links
298
322
 
299
323
  def get_tabs_list(self, request: HttpRequest) -> list[dict[str, Any]]:
300
324
  tabs = copy.deepcopy(self._get_config("TABS", request))
@@ -381,6 +405,29 @@ class UnfoldAdminSite(AdminSite):
381
405
 
382
406
  return False
383
407
 
408
+ def _get_is_tab_active(
409
+ self, request: HttpRequest, tabs: list[dict], link: str
410
+ ) -> bool:
411
+ for tab in tabs:
412
+ has_primary_link = False
413
+ has_tab_link_active = False
414
+
415
+ for tab_item in tab["items"]:
416
+ if link == tab_item["link"]:
417
+ has_primary_link = True
418
+ continue
419
+
420
+ if self._get_is_active(
421
+ request, tab_item.get("link_callback") or tab_item["link"]
422
+ ):
423
+ has_tab_link_active = True
424
+ break
425
+
426
+ if has_primary_link and has_tab_link_active:
427
+ return True
428
+
429
+ return False
430
+
384
431
  def _get_config(self, key: str, *args) -> Any:
385
432
  config = get_config(self.settings_name)
386
433
 
@@ -74,9 +74,15 @@
74
74
 
75
75
  function updateRelatedObjectLinks(triggeringLink) {
76
76
  const $this = $(triggeringLink);
77
- const siblings = $this.nextAll(
78
- ".view-related, .change-related, .delete-related"
79
- );
77
+ // !CHANGED from original
78
+ // const siblings = $this.nextAll(
79
+ // ".view-related, .change-related, .delete-related"
80
+ // );
81
+
82
+ const siblings = $this
83
+ .parent()
84
+ .nextAll(".view-related, .change-related, .delete-related");
85
+
80
86
  if (!siblings.length) {
81
87
  return;
82
88
  }