django-unfold 0.58.0__py3-none-any.whl → 0.59.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 (43) hide show
  1. {django_unfold-0.58.0.dist-info → django_unfold-0.59.0.dist-info}/METADATA +1 -1
  2. {django_unfold-0.58.0.dist-info → django_unfold-0.59.0.dist-info}/RECORD +43 -41
  3. unfold/checks.py +24 -2
  4. unfold/contrib/filters/templates/unfold/filters/filters_numeric_slider.html +2 -2
  5. unfold/decorators.py +27 -13
  6. unfold/fields.py +1 -1
  7. unfold/forms.py +4 -2
  8. unfold/layout.py +16 -0
  9. unfold/mixins/action_model_admin.py +22 -14
  10. unfold/paginator.py +12 -1
  11. unfold/settings.py +8 -1
  12. unfold/sites.py +24 -0
  13. unfold/static/admin/js/admin/RelatedObjectLookups.js +9 -3
  14. unfold/static/unfold/css/styles.css +1 -1
  15. unfold/styles.css +9 -13
  16. unfold/templates/admin/base.html +1 -1
  17. unfold/templates/admin/change_form.html +2 -1
  18. unfold/templates/admin/edit_inline/stacked.html +1 -1
  19. unfold/templates/admin/includes/fieldset.html +9 -3
  20. unfold/templates/admin/login.html +1 -1
  21. unfold/templates/admin/pagination.html +1 -1
  22. unfold/templates/unfold/components/button.html +1 -1
  23. unfold/templates/unfold/helpers/account_links.html +14 -6
  24. unfold/templates/unfold/helpers/change_list_actions.html +2 -2
  25. unfold/templates/unfold/helpers/change_list_filter_actions.html +1 -1
  26. unfold/templates/unfold/helpers/edit_inline/tabular_heading.html +1 -1
  27. unfold/templates/unfold/helpers/empty_results.html +2 -2
  28. unfold/templates/unfold/helpers/header.html +1 -1
  29. unfold/templates/unfold/helpers/language_form.html +10 -0
  30. unfold/templates/unfold/helpers/language_switch.html +17 -19
  31. unfold/templates/unfold/helpers/navigation.html +1 -1
  32. unfold/templates/unfold/helpers/pagination_infinite.html +3 -3
  33. unfold/templates/unfold/helpers/theme_switch.html +29 -27
  34. unfold/templates/unfold/helpers/userlinks.html +2 -6
  35. unfold/templates/unfold/helpers/welcomemsg.html +9 -7
  36. unfold/templates/unfold/widgets/select.html +1 -1
  37. unfold/templates/unfold_crispy/layout/fieldset.html +3 -1
  38. unfold/templates/unfold_crispy/layout/fieldset_subheader.html +3 -0
  39. unfold/templatetags/unfold.py +6 -1
  40. unfold/utils.py +2 -2
  41. unfold/widgets.py +8 -2
  42. {django_unfold-0.58.0.dist-info → django_unfold-0.59.0.dist-info}/LICENSE.md +0 -0
  43. {django_unfold-0.58.0.dist-info → django_unfold-0.59.0.dist-info}/WHEEL +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: django-unfold
3
- Version: 0.58.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,7 +1,7 @@
1
1
  unfold/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  unfold/admin.py,sha256=2YwKqP5slOtqpEInq_u-0-XlddY7Qnj21VeH-lsLkxg,6552
3
3
  unfold/apps.py,sha256=SlBXPYrUd2uXn67qFbRvbXSUk3XFWrF4-5WELgDCvho,381
4
- unfold/checks.py,sha256=8I3i4xR_KgyJdpQyZUZzKNeyYf-sNzg6PAlsREuMfgI,1664
4
+ unfold/checks.py,sha256=e5HEhbXRcu3FwZDT_d-IbimeVpjJ6jgCUPXWvsUjEw0,2601
5
5
  unfold/components.py,sha256=vqkQzseYUvLXDohmTVAlbKopALjyX4WA9yglvdfhqu4,1283
6
6
  unfold/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  unfold/contrib/filters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -28,7 +28,7 @@ unfold/contrib/filters/templates/unfold/filters/filters_datetime_range.html,sha2
28
28
  unfold/contrib/filters/templates/unfold/filters/filters_field.html,sha256=UTlSZlpg-gAc_a-EJLLF0NI_ofuSHQ2kMMoAs99nL2E,164
29
29
  unfold/contrib/filters/templates/unfold/filters/filters_numeric_range.html,sha256=TnklQxXhe17UaImoiHahhtN6d1xVdXt2dhIMQESJY68,661
30
30
  unfold/contrib/filters/templates/unfold/filters/filters_numeric_single.html,sha256=uELVrDzFgmzGwkm37SpZeXXbfpijDnSBIJVtf6evWjM,598
31
- unfold/contrib/filters/templates/unfold/filters/filters_numeric_slider.html,sha256=Z7QBmfKfpe50taQOyOPvLeOA0Uxf95u64zeA-3MJ3vM,1730
31
+ unfold/contrib/filters/templates/unfold/filters/filters_numeric_slider.html,sha256=_yOzo0T0OcHFKAZFj6L3-4_Y9MlKg53yKMq7LizWFS0,1762
32
32
  unfold/contrib/forms/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
33
  unfold/contrib/forms/apps.py,sha256=Di0TMzVuRpVxLG-8Bjdq5ALCSf5r7u2xVhD0jU6H5Sc,132
34
34
  unfold/contrib/forms/static/unfold/forms/css/trix/LICENSE,sha256=-g0UVDdcvHcBvBPZFsOuceYTuK5xgyFkHmeOCUCTk8Q,1053
@@ -78,25 +78,25 @@ unfold/contrib/simple_history/templates/simple_history/object_history_form.html,
78
78
  unfold/contrib/simple_history/templates/simple_history/object_history_list.html,sha256=PWtjuAcxciAI001qIrXLvbUxzCFl_SDAaHA5FhR16Z8,6858
79
79
  unfold/contrib/simple_history/templates/simple_history/submit_line.html,sha256=tJgOgq7lMetWF4DJoBqUYdRSY6EeRivXhOBYlyPXzTk,1750
80
80
  unfold/dataclasses.py,sha256=a-9INnkCAIcnMgoffTcB1rxWCJH33AjhMCWIGWnjWbI,719
81
- unfold/decorators.py,sha256=FZ0to60sg9fefOCpYiziG9UbV6mgmiEk0lc1wQyisXc,4302
81
+ unfold/decorators.py,sha256=jPiYFy1p0WGFn68VZhAZkYCPDF7argb9SDFaH6aemHk,4922
82
82
  unfold/enums.py,sha256=9sTfyEycMWeoGPBa-ft6ZhQGnW1vkFg108RMBVf9nko,187
83
83
  unfold/exceptions.py,sha256=gcCj1ox61E137bk_0Cqy4YC3SttdPgB-fiJUqpmyHSE,43
84
- unfold/fields.py,sha256=J3goIMlP_XOmQ85Xgh2v5MylXSP1o5I7o9_So2FQn2k,7461
85
- unfold/forms.py,sha256=xAFNBB_UqZFeg5tV2jK-_rGzwEKR9r9oaxxnpAvw3a8,4606
86
- unfold/layout.py,sha256=2fPFXDF6kTC9A2liO4P-aeOC3frlbuH7u7d8HLny6ig,1020
84
+ unfold/fields.py,sha256=g8gWFWsCQAooTBT8ngASaryW3fgaBZx6aPuTdLc1NqY,7472
85
+ unfold/forms.py,sha256=f8OanxLAmV6dftNj-apgjtCrIVj_iEU830AbMeZh71I,4709
86
+ unfold/layout.py,sha256=Q-dFTA6UlvvPCA4PsGyTkHQmBLO7PL56xBfZi-bdt0c,1459
87
87
  unfold/mixins/__init__.py,sha256=YlhoDs9Y_DXQ8Ejr3enxuHMS1-Ij9fwukxNwpeOS4Co,190
88
- unfold/mixins/action_model_admin.py,sha256=BPajuTGf7zAaZOqIq4shX8VQ3NTxWQpedvG58fmCTjk,12036
88
+ unfold/mixins/action_model_admin.py,sha256=9Zt4FLrQWEQSO2vrpwjzpFo_I3_yE000uEwHndsW5kg,12365
89
89
  unfold/mixins/base_model_admin.py,sha256=PR4eqU48yB4CNy9Bjd7fjxbOFiFpZM4etYmBOSaRX_M,4140
90
90
  unfold/overrides.py,sha256=ERVY9boZiXgjDYcTEZcIp7KWoeBZ45VM_zN31yAOjyQ,2922
91
- unfold/paginator.py,sha256=vWCIfpuWbV3nvIkQOPyD7MLTg2hZplHz3rze42d-qiA,268
91
+ unfold/paginator.py,sha256=bZiEY-1kqZy_6CYGs9fHo6WntMgpnFCH-LJPoXkEESk,533
92
92
  unfold/sections.py,sha256=Lcg3xCZ76fqjm4vD4x7YdE5VsbTKluL-sX5QTEBlHxA,2379
93
- unfold/settings.py,sha256=M5LVVwatGKk6AOZBkBY_vXFntn7ENla9rqMQG0gxb0U,2753
94
- unfold/sites.py,sha256=Roo_hXNB-6X7uENluXh3yT_NPA0W3uv8Nish72QJUb8,17318
95
- unfold/static/admin/js/admin/RelatedObjectLookups.js,sha256=alI0-yq7YPDJJJn-yg1ce79-Cv88yQDUrfaGqFZnsaY,9048
93
+ unfold/settings.py,sha256=DE3hComMaWtty8o-LqdgGGcoku3mevRWJah4NH1k5B4,2879
94
+ unfold/sites.py,sha256=Zxz2ey_rfFnCrYwqiPaLAvUDSehftPxFLOm-AX6b50M,18166
95
+ unfold/static/admin/js/admin/RelatedObjectLookups.js,sha256=0bZ2MGuO6F0IF_lQ7-hTP6ofqZtrH44Pt4ElaPqyNz8,9199
96
96
  unfold/static/admin/js/inlines.js,sha256=zcYwLGI_6RHg-gucDbbhp43RRoZd3so8bPk841KFaIE,15573
97
97
  unfold/static/unfold/css/simplebar/LICENSE,sha256=okNJf6UFl2NrEiC4iqORNBa16IKgUgV88acdcl9FbtY,1081
98
98
  unfold/static/unfold/css/simplebar/simplebar.css,sha256=5LLaEM11pKi6JFCOLt4XKuZxTpT9rpdq_tNlaQytFlU,4647
99
- unfold/static/unfold/css/styles.css,sha256=8MvwCnrFLcXnTXgB39xn4xSNV8o6q2GZIClcPEuHrzg,158422
99
+ unfold/static/unfold/css/styles.css,sha256=RYbHZGbPj3wTqi87UahjSTRRTeoC1Jrfpjah-o612jU,159143
100
100
  unfold/static/unfold/fonts/inter/Inter-Bold.woff2,sha256=-oiBJ7baAVtlVp8DUfO1w5GtkokElR8cIOn4RiqNleo,114840
101
101
  unfold/static/unfold/fonts/inter/Inter-Medium.woff2,sha256=D_PpRhThST61VjFP0keubEqFp3g7TMhr5TmUDPg_Kkg,114348
102
102
  unfold/static/unfold/fonts/inter/Inter-Regular.woff2,sha256=4G9rG8VTqupORmgCPtCrChRxKcMQf1Ebx9A9NhsK4IU,111268
@@ -120,15 +120,15 @@ unfold/static/unfold/js/htmx/htmx.js,sha256=acrv0NqSJpBm5yXX_hdeJrnVDJYuMFZFnAxH
120
120
  unfold/static/unfold/js/select2.init.js,sha256=l0O8ggw_CkAw-QtH3qEzC8xWk0mR9QHjy4VzAjMwiQQ,1109
121
121
  unfold/static/unfold/js/simplebar/LICENSE,sha256=okNJf6UFl2NrEiC4iqORNBa16IKgUgV88acdcl9FbtY,1081
122
122
  unfold/static/unfold/js/simplebar/simplebar.js,sha256=t-uG1FAD6ZoiMeN--wac0XRS7SxoDVG6zvRnGuEp7X8,27176
123
- unfold/styles.css,sha256=4jfRd3it5Xllssqjc4xcAItlSAmbsF5tsOBut6cK4m0,21729
123
+ unfold/styles.css,sha256=YSDKjgENtZyAg9ceUztuJj9JXgAlUr3wJpwnSOZ6TMc,21246
124
124
  unfold/templates/admin/actions.html,sha256=iuuubcAILkOoYBgV6cpXqFIyZUh4zMqyFp0JaDFlPKU,3096
125
125
  unfold/templates/admin/app_index.html,sha256=LRR07CLcZVsYpisCOncWdMSACARNstcDt536Oydnt60,1239
126
126
  unfold/templates/admin/app_list.html,sha256=2JbGENeKAVqYGYwm2Yv7I0lzQrLz0xRND18kPiMIi_Q,2861
127
127
  unfold/templates/admin/auth/user/add_form.html,sha256=tZgg6UoKxJ7zL6T99PLHlLBwd4LlDI2mGn6d5hmtsPs,486
128
128
  unfold/templates/admin/auth/user/change_password.html,sha256=028v1dfQTlSmdr-WCuV4lBOmFa7Oo38CsYhsXEe8ANI,2831
129
- unfold/templates/admin/base.html,sha256=lXL_Hdhfflcpd_qxZ6o7GVBdAt3kZAtnnETiYrVHKfc,2460
129
+ unfold/templates/admin/base.html,sha256=z9sU8rezHLqOZk5x13_5nvnqpRYf6XxQaMfa7N_GU68,2460
130
130
  unfold/templates/admin/base_site.html,sha256=UOsecaCycpyn_ygJNIKO7MQtDFJuHv--r83-mzaVY30,300
131
- unfold/templates/admin/change_form.html,sha256=pdH089m7iaEDMUxKCWg5OSQmte0nU2Ir8gxFzrwtwB4,5611
131
+ unfold/templates/admin/change_form.html,sha256=stW5bIL_HuxtD9Bb0RVLHZiP8ln8lGBQ3D3V6MeJbAY,5616
132
132
  unfold/templates/admin/change_form_object_tools.html,sha256=eyeH-i2HgEM0Yi-OJA2D1VnKJyC19A_my1IDGxxoP8Y,593
133
133
  unfold/templates/admin/change_list.html,sha256=49PwsDjJuTDXfoCqpUqAFc84HFNOJk8dIHSdYCQIDuk,5269
134
134
  unfold/templates/admin/change_list_object_tools.html,sha256=cmMiT2nT20Ph5yfpj9aHPr76Z-JP4aSXp0o-Rnad28s,147
@@ -136,23 +136,23 @@ unfold/templates/admin/change_list_results.html,sha256=u9eUoOTWJ9woVeLVYhftAriCX
136
136
  unfold/templates/admin/date_hierarchy.html,sha256=A-sIqBKzZTMqSn3NSHORIL1yTEAqhj4Atff0OvWtqT0,1413
137
137
  unfold/templates/admin/delete_confirmation.html,sha256=IPSGhOpxDl6hJB9LtpSg_XRkVmbDO1BpO9q_dthqkac,4635
138
138
  unfold/templates/admin/delete_selected_confirmation.html,sha256=T3NNe7pP0WM2QM4F39AbkDGsfd_d_tKYRpwxvExahgU,4399
139
- unfold/templates/admin/edit_inline/stacked.html,sha256=ee3SWRJXMTcDMc2SO5tSWXIvecdAPuGTgdcKPsz0lBo,7658
139
+ unfold/templates/admin/edit_inline/stacked.html,sha256=RvdjkyXnTEzpWAI0GidvqxEFFK4x8NCEVHMlE2Y6OLQ,7664
140
140
  unfold/templates/admin/edit_inline/tabular.html,sha256=F8o80H3GVHcGv_OARw0l5XrMPKXcgdNWX4cgorsNvkU,2948
141
141
  unfold/templates/admin/filter.html,sha256=DEyrLgCWuncS1O1WR0vlt1evGQFvKoZV2pABkHzSoGU,2039
142
- unfold/templates/admin/includes/fieldset.html,sha256=7ZIdu6kGit1pL3iFq_SHH7pPJohM6b3Ujmp-slB8dXI,821
142
+ unfold/templates/admin/includes/fieldset.html,sha256=F1XS_7bxeIbIxILjNdclXk_jFTmceUs_fZ4GjVwT1VM,1161
143
143
  unfold/templates/admin/includes/object_delete_summary.html,sha256=FgwfapZCKWtnFtTHqh1MRuxxLot4bAw92WCcR_V8ImI,444
144
144
  unfold/templates/admin/index.html,sha256=9ey6IIXxBVTEkVSDiQw01AwvMbUnG_h0B08N1Zg3wTg,578
145
- unfold/templates/admin/login.html,sha256=cdyH_AGQxANC7D8Bcj-KnCRVQ9tWBT3LFwPBJmhYVaY,4590
145
+ unfold/templates/admin/login.html,sha256=fAY1FF3P0Zc4WYXh3CpZOMuyrr7Bfz29VxwD-MJ_vHg,4605
146
146
  unfold/templates/admin/nav_sidebar.html,sha256=xvCaXOamXawmf80NhE0OwjjjuNwoyoePS--lsdqDeIE,772
147
147
  unfold/templates/admin/object_history.html,sha256=t-iJFQnpstowwsabGGA-FQjmcT1KIKhKLKbQ3iVELkk,4832
148
- unfold/templates/admin/pagination.html,sha256=Jc8kqZp2LMZ1xdJCGg2O5YB1lgcUG9nm-sXTWaW9Ckc,897
148
+ unfold/templates/admin/pagination.html,sha256=-9kjc_lKEeqvDVHMrnTfnlXDxMSkM8GNRGZGuI9D8os,912
149
149
  unfold/templates/admin/search_form.html,sha256=ebd6ccOASaIUQsOZ0mVkcoB-EiKLqkN7y7cEm3fwsL8,1360
150
150
  unfold/templates/admin/submit_line.html,sha256=GvknbdmXXEw93BIQ8azUHhnQ1AcojExgGiSr0XaNg2A,4658
151
151
  unfold/templates/auth/widgets/read_only_password_hash.html,sha256=MlaNXJ2PLEbv8Nd01BBp-AQEfMB13LNxD_DzRemXhCg,775
152
152
  unfold/templates/registration/logged_out.html,sha256=oIdaqGcvIdBih3yNnUkXSEpvofRsBJ77obldnhcnP2U,997
153
153
  unfold/templates/registration/password_change_done.html,sha256=ITV6Fug4S6YG3WG-O1cm-sDAXTHEXPcNZ_w2x1IQFu8,1006
154
154
  unfold/templates/registration/password_change_form.html,sha256=-8AauxUHWHXVaokG269UsETY_FHKqU83Zx38ZzrAA1A,2159
155
- unfold/templates/unfold/components/button.html,sha256=19z4DHnhVmq2wL2WyvoZxtNu8xGCAKXGuDa2snZTF50,630
155
+ unfold/templates/unfold/components/button.html,sha256=PXYHCy5x_REPQSOukXiyT901D5KmoWoSfMWlMrUPSEA,670
156
156
  unfold/templates/unfold/components/card.html,sha256=N9ld_SWpXdmaqAea9bboy0bTg1YqIkAhsJmOj7nd0qs,1353
157
157
  unfold/templates/unfold/components/chart/bar.html,sha256=nDdDCUXvFd793OpNgNPQo0vBmvYngMsQyPHVTf1vfOw,297
158
158
  unfold/templates/unfold/components/chart/cohort.html,sha256=L00WR-igYv0C3t2yT_nZqeI-M5gVHpoaGv5RooRojqU,2402
@@ -167,7 +167,7 @@ unfold/templates/unfold/components/table.html,sha256=VVMTrrDy_Oq09MG9aNAsnMZfXSp
167
167
  unfold/templates/unfold/components/text.html,sha256=-GjxvdiaBQIaNfPSzT6SSIwnc3R27FkSDQMoF3FDPso,102
168
168
  unfold/templates/unfold/components/title.html,sha256=aMYSO30ybFYqPnqwlJVh2uNmcgnVrRycZkHTjJTjpX8,171
169
169
  unfold/templates/unfold/components/tracker.html,sha256=krlvsb06lpfdOIANsyrBOoLq1sgv6rXUGr-7MmP5Le0,292
170
- unfold/templates/unfold/helpers/account_links.html,sha256=bQC-VnzIKpeOCrEL0rlN_ZLiKb7e2LZM7-i4lr7LgBU,1948
170
+ unfold/templates/unfold/helpers/account_links.html,sha256=Tq30bAkOU8QRR6CaB1CvTfTgkoPP5dz2v0OHYq0pRSE,2348
171
171
  unfold/templates/unfold/helpers/actions_row.html,sha256=RqhZsxgIFR-r1casv5CueL81uxNl8rA3XuCMDP--zLA,2586
172
172
  unfold/templates/unfold/helpers/add_link.html,sha256=Z0TzUavXH8AQ7A-I0SQ79t-UI87dyP_PZEpsDrm13Q8,810
173
173
  unfold/templates/unfold/helpers/app_list.html,sha256=AoTyb-0jQTnnAtPmXtiN52oEaeIbdtQZgzqqZZhquOc,5744
@@ -175,9 +175,9 @@ unfold/templates/unfold/helpers/app_list_default.html,sha256=LbyLT9xYgev0xXwprkX
175
175
  unfold/templates/unfold/helpers/attrs.html,sha256=Mwpj72kuwYj8hOT3J2T8qx6f1r_4xwwaS1slHA-82jI,166
176
176
  unfold/templates/unfold/helpers/boolean.html,sha256=kcSZr3siQeBWIy_jsx1tFf4m6IB3ooRnu8UUNQrh6so,569
177
177
  unfold/templates/unfold/helpers/breadcrumb_item.html,sha256=9T6ojN7LOXIlgwSwlIwHgy5U22eQYtarCqcmzsQIoPU,201
178
- unfold/templates/unfold/helpers/change_list_actions.html,sha256=XceGYsclqM5atPtN8NC3dffHh_R78mt-OD9QLONqdr8,651
178
+ unfold/templates/unfold/helpers/change_list_actions.html,sha256=xuFMZel6kH014H9sl0hKvQo7LP0UxwlhFQHIUeyQxVM,643
179
179
  unfold/templates/unfold/helpers/change_list_filter.html,sha256=WwU-AG4U5qZQ_sFs1z_jaaYBWqIv3ASmtKIQIhAp2gs,1908
180
- unfold/templates/unfold/helpers/change_list_filter_actions.html,sha256=K32esRWcttvg8_9YvFMDurvUhL71SHjpqBSJv-ll0Po,2037
180
+ unfold/templates/unfold/helpers/change_list_filter_actions.html,sha256=K99hHgpCLaAHxv-eqIf4nOUfq6CeTQHekEeudKTRYME,2036
181
181
  unfold/templates/unfold/helpers/delete_submit_line.html,sha256=7SNS0axGytvUih9KxtOzy9ZC5rwG9u99iQxlnUZQfdE,700
182
182
  unfold/templates/unfold/helpers/display_dropdown.html,sha256=IpOy8-hww4arAVjPIRsHrip30J3IEd2p-2BzD3BjIaA,2906
183
183
  unfold/templates/unfold/helpers/display_header.html,sha256=2u-5Vc3mA6rS3ZlOWm3WRNLUX1wmZy4OSmGY2mdPZYs,1714
@@ -185,10 +185,10 @@ unfold/templates/unfold/helpers/display_label.html,sha256=LS9DWzYjHkYLV27sZDwyXl
185
185
  unfold/templates/unfold/helpers/edit_inline/tabular_delete.html,sha256=wr8zmSUhKcoxxms6gJsBqBrANFTOXELYUvlr3XjnjnE,931
186
186
  unfold/templates/unfold/helpers/edit_inline/tabular_error.html,sha256=8XGlgUJ47JllmXhwPZDlcl81NzZmvuBIp8FZBWoeu9Q,336
187
187
  unfold/templates/unfold/helpers/edit_inline/tabular_field.html,sha256=QETtgDYirbFBMCRH0sRU8IkODS0fBouA6crZ_K4ufTA,1007
188
- unfold/templates/unfold/helpers/edit_inline/tabular_heading.html,sha256=ER8R64wnKOu26WTwP4_Wxt-LRB_zRkXLhheZ_utVvKY,1523
188
+ unfold/templates/unfold/helpers/edit_inline/tabular_heading.html,sha256=wvnpGFJVHFvamGLpRCpGoP7WALFKqR1KKvVIIRhWFQc,1520
189
189
  unfold/templates/unfold/helpers/edit_inline/tabular_row.html,sha256=eCyWEYvvDDCr9SR4_0ua5-GqCLIlFzgQYIZP0ip8cp8,2145
190
190
  unfold/templates/unfold/helpers/edit_inline/tabular_title.html,sha256=2sk1TRzpmwy8PPPMNdf6CJx0zVSk-I2q3yX8uEPjuxE,2710
191
- unfold/templates/unfold/helpers/empty_results.html,sha256=Sbp1dOgazpbSwyiX1CT-Arbe51V79MhV8w9IAiHRIE0,1963
191
+ unfold/templates/unfold/helpers/empty_results.html,sha256=zN1XM6_9_Oj-inMZlDxEnicYfBRr4HhwS9ODAnMiRYc,1947
192
192
  unfold/templates/unfold/helpers/field.html,sha256=2q2M4dfisKJ9v8jt8gcq-iRf74t6H9W6xg16scZNF70,979
193
193
  unfold/templates/unfold/helpers/field_readonly.html,sha256=4qtXjWE7SA2qZSTYLOv0lT4pQfD0TE34mvWQJY7jhS8,237
194
194
  unfold/templates/unfold/helpers/field_readonly_value.html,sha256=FI_CFEsCN7ELQux9gF-IaZ7nT7jyzidqwR2Med-E52g,504
@@ -198,12 +198,13 @@ unfold/templates/unfold/helpers/fieldset_row_field.html,sha256=cqLT1fHsCCszOHxvY
198
198
  unfold/templates/unfold/helpers/fieldsets_tabs.html,sha256=NRmkr_vWnEyIFZ1xLpJf_VW1H3xcDlIhMFBuElp3dIo,1468
199
199
  unfold/templates/unfold/helpers/form_errors.html,sha256=mrv2_J7RPcLfVtoN1UHh3rfUyOSZpHl67wk1UGqtPcY,266
200
200
  unfold/templates/unfold/helpers/form_label.html,sha256=7FfaXfviQmqKpsA1E7NSwM8rJiMNLl9e73XQram0Pfs,249
201
- unfold/templates/unfold/helpers/header.html,sha256=hTLE7_1VCCp-XqmU4xBrFA4Rtb0-8q-I7goP1sOGKg0,1123
201
+ unfold/templates/unfold/helpers/header.html,sha256=cHAPz7niLLQDQbrZpURZS1hiA8OYLzkGaqnYzjgv8aE,1151
202
202
  unfold/templates/unfold/helpers/header_back_button.html,sha256=lNZcYZzQRZdNSI70UrxJ-pq7xnxifziZXtSK1FoPy_U,416
203
203
  unfold/templates/unfold/helpers/help_text.html,sha256=o-2_hyruIr_Xt0fo38aGgrpptPJFhddnVMPOVQOYhE4,113
204
204
  unfold/templates/unfold/helpers/history.html,sha256=qxfCZxFIyl91qDpxfwozhmyVFZwULysA8Y_2H8XJ7bM,1937
205
205
  unfold/templates/unfold/helpers/label.html,sha256=DRs0B08SmIvNY0QcFy78xDiI0hAKyfjExu-cm33PAaQ,911
206
- unfold/templates/unfold/helpers/language_switch.html,sha256=Y3VxZW0JhqBImLQf2PY11gA_J1CWhbo5LouxoNgzawU,1516
206
+ unfold/templates/unfold/helpers/language_form.html,sha256=Ve1qfIcL4DV6cxYfhqGkC_KghDjNyEB8j3hYts1S34M,708
207
+ unfold/templates/unfold/helpers/language_switch.html,sha256=vZiYutLOWChHUQRw1OaHIYVhfzl84-BfZq14FUCKvuo,1225
207
208
  unfold/templates/unfold/helpers/messages/debug.html,sha256=OIWKZp04zxWPmVaKZaEtzrikZq1kVruncYRKiKrHWds,153
208
209
  unfold/templates/unfold/helpers/messages/error.html,sha256=16-4bslrpgXR1fTk8bmRUItIbnQcU5XjDgI1xesoKcc,600
209
210
  unfold/templates/unfold/helpers/messages/errornote.html,sha256=3RVj4BIdft3yEUOdzmli0QPQ_l9hUAOTpHIfL4ZOpMg,356
@@ -211,13 +212,13 @@ unfold/templates/unfold/helpers/messages/info.html,sha256=4SCFtg3p6F33ZHJhYoIm2V
211
212
  unfold/templates/unfold/helpers/messages/success.html,sha256=UWHpRJTvVhXiYC9-AvJ9HeEZJj-poejFgy7EgLvwpf8,157
212
213
  unfold/templates/unfold/helpers/messages/warning.html,sha256=UldycPr8wdyp5vdjlkfs_yHCEvNg9PgspyzTALAjdDY,161
213
214
  unfold/templates/unfold/helpers/messages.html,sha256=ISkUlIDraDAVBwASkX1tFXHo8TY1vHKmmhh8BAg123E,915
214
- unfold/templates/unfold/helpers/navigation.html,sha256=IPE9Z48XTuI2q72sNJcFTPXDn8_F2FhzgvipTymnFck,526
215
+ unfold/templates/unfold/helpers/navigation.html,sha256=U9cMmw3ETMI88zqHvSf5VQkMehcU6YfLKTcH1CmS4fY,554
215
216
  unfold/templates/unfold/helpers/navigation_header.html,sha256=08_LTuJF6MrG0hK6lUI9daCP5kQr5Q7FwY7Pl4kFxJQ,1474
216
217
  unfold/templates/unfold/helpers/pagination.html,sha256=N5TQDlj5kgJLj02oRiaX8W62jQtZVNoWfI2hXdpuY1g,439
217
218
  unfold/templates/unfold/helpers/pagination_current_item.html,sha256=4cZ2KLVcP0Y7xuGyXgexDQ07r94cgM5Gnmtv11dkRPQ,69
218
219
  unfold/templates/unfold/helpers/pagination_default.html,sha256=pseTrqaG5EOn_IpCy0GXNht3ickSkZYJ4lJaocZeI6A,496
219
220
  unfold/templates/unfold/helpers/pagination_ellipsis.html,sha256=8g0KUUKtqRkXx_EBLGtsJsiYQO4tPS3GazZjxT90e0M,56
220
- unfold/templates/unfold/helpers/pagination_infinite.html,sha256=-U1i-90jxzJVui56NvuJ1OxrywN8QLrs-IRu9KLmN20,422
221
+ unfold/templates/unfold/helpers/pagination_infinite.html,sha256=QyHcYb36CeuiwpukC0Y553UC4LU2tPolGos-0mh7WP0,557
221
222
  unfold/templates/unfold/helpers/search.html,sha256=Pu2hxLGkN_NA-BU8_t4E7Q6uaY6hYTLoD8NZHyrcCaQ,1549
222
223
  unfold/templates/unfold/helpers/search_results.html,sha256=pQx7KoDMapWDusV88qe5hxlxicfP-S9iacji1Hq41Kc,661
223
224
  unfold/templates/unfold/helpers/site_branding.html,sha256=_pUyOvdjlV624eRq0wjpJkgXpn9DCDGc-0U6Mw0FupI,266
@@ -229,9 +230,9 @@ unfold/templates/unfold/helpers/tab_action.html,sha256=cy4JxV-wfXv9tNOTgsWXuj1bc
229
230
  unfold/templates/unfold/helpers/tab_actions.html,sha256=Ir0HFxNAdZWdE6GuxaanSScNYONft0lNB1sZZcKMS5Q,685
230
231
  unfold/templates/unfold/helpers/tab_items.html,sha256=5kZcU7R9tZKKxVLahp2siZpZf7FhrluBH1dIAIaWoAg,3377
231
232
  unfold/templates/unfold/helpers/tab_list.html,sha256=mprad7Fu5ms1qGqjDl9HMmtfUodk43smd3IjagYOyr0,452
232
- unfold/templates/unfold/helpers/theme_switch.html,sha256=0-pi-_gmOIL5DwfWLd0_PNIc0-l28hM8HtAioovtB0k,2269
233
- unfold/templates/unfold/helpers/userlinks.html,sha256=oZqiwCxG_zRecAbzYrr8_hQvkndVB6-liP6LEZM1UZc,863
234
- unfold/templates/unfold/helpers/welcomemsg.html,sha256=Ickay1zuj2A6SE9WmEfFqSKvzmrm_nAH6mJz5_JEQuY,1935
233
+ unfold/templates/unfold/helpers/theme_switch.html,sha256=Y46KKpULH_G-fKQuc5LzfSB7Pubcgj_dBJPRMwZoWxE,2408
234
+ unfold/templates/unfold/helpers/userlinks.html,sha256=bJRDQXQ_0XgxLpfmZoNgU9xpn4X6T6LOAgEmzepFXOI,740
235
+ unfold/templates/unfold/helpers/welcomemsg.html,sha256=Z3dDvozCJ5VhSVA_1go0F4ZD0lQYhCmoWqd_RM00pec,2019
235
236
  unfold/templates/unfold/layouts/base.html,sha256=e9T-vuPvrySHf23LLwRuTQXUg0Q4x-6gmT_yXghqc-I,278
236
237
  unfold/templates/unfold/layouts/base_simple.html,sha256=qUZ9YM24UHgWbmTl61zgN4_ty49P1FZJQ2siNbwnFnQ,1244
237
238
  unfold/templates/unfold/layouts/skeleton.html,sha256=2AWjJx6TxpYbXldwrXRbtyp9XTpAu6O0U_zcJtfYfWs,4684
@@ -244,7 +245,7 @@ unfold/templates/unfold/widgets/radio.html,sha256=7Mgc92mMwJdVLjCxoGj5lo76KNaN5d
244
245
  unfold/templates/unfold/widgets/radio_option.html,sha256=wVg6zIB0O44vwBgQCCphPuCXeh-gaDg6ed-0gcf5kg4,324
245
246
  unfold/templates/unfold/widgets/range.html,sha256=Zhfj2VTusS3nZjOYR7slcjk1JtFK0psZbaSCw6TDY1I,294
246
247
  unfold/templates/unfold/widgets/related_widget_wrapper.html,sha256=8poy8kZRGPqmY4gSXkEZt7vevBomrKoe2Lg5zsjpwiU,3919
247
- unfold/templates/unfold/widgets/select.html,sha256=Qx1YUMj2Yq43DaAbDeRcQv-9M8jlIV00NF6970axb7Y,708
248
+ unfold/templates/unfold/widgets/select.html,sha256=MyhlEO4sf7AUjOgH84rL76rhYM0WEn4qRqzuzPmgu5M,715
248
249
  unfold/templates/unfold/widgets/split_datetime.html,sha256=Hfv2PoHxPmV_21DmBFmMcR4WVP9vTV9SrfjVdliRci8,1074
249
250
  unfold/templates/unfold/widgets/split_datetime_vertical.html,sha256=39lZsRyRcKr8DIcy9oL39zC8nAHZTHwW6gyTYOKePrQ,806
250
251
  unfold/templates/unfold/widgets/split_money.html,sha256=AFLUBmzGbY-RXgsfz7gaDxVRhplaIPhXjg_hWYo9xcY,352
@@ -264,7 +265,8 @@ unfold/templates/unfold_crispy/layout/checkbox.html,sha256=V1YGDcYfn4spUHx6M5ux8
264
265
  unfold/templates/unfold_crispy/layout/column.html,sha256=Bob4xRcbJOHScDjSjLMRIMNf4lonNmm8F_JOm2azTik,172
265
266
  unfold/templates/unfold_crispy/layout/div.html,sha256=RE9qQ2w2I2zpi7Z7xzVmVO03UXq0yZvMw-W7rVJkEdw,174
266
267
  unfold/templates/unfold_crispy/layout/field_errors.html,sha256=N0eNJo4OvYzFHPD6vX2gSZWabm46W1GP011sd_dua1I,291
267
- unfold/templates/unfold_crispy/layout/fieldset.html,sha256=batc1TDIHvtzX9ZchvSyH3r3q9s7bgr7DpxEfnwvvjk,601
268
+ unfold/templates/unfold_crispy/layout/fieldset.html,sha256=hbbJVTNUOwFoBtpFMpqGaf-I4cXnQZEG5s91EUxBUzY,654
269
+ unfold/templates/unfold_crispy/layout/fieldset_subheader.html,sha256=fAD3wa9JiuYJwbo8bsmW-LhMw72V2j27EkRgy0G6Kc8,209
268
270
  unfold/templates/unfold_crispy/layout/help_text.html,sha256=FY0UQv5FsoOFhrqvbILEfZE78Hj30r73YHCtg_MWNeY,207
269
271
  unfold/templates/unfold_crispy/layout/help_text_and_errors.html,sha256=Um14wIg0FHthNM0mKE9VdptTrC-lTTcrDUO-UbbXxhY,108
270
272
  unfold/templates/unfold_crispy/layout/hr.html,sha256=_u0V0lIdK3PLREGspx3zywhUQHcFeY7BuMUbaLyN1WU,321
@@ -275,13 +277,13 @@ unfold/templates/unfold_crispy/uni_form.html,sha256=l9UNCUrIycgJ0p_B6qhtO_YxdARy
275
277
  unfold/templates/unfold_crispy/whole_uni_form.html,sha256=ufXRKCIGqkqKFOsh166rpKUnHpFMyBV4eYUCRhs3iws,475
276
278
  unfold/templates/unfold_crispy/whole_uni_formset.html,sha256=CYksfG2hRUdi5n691KW2ih-FfBxpOU4qVBfbOvcu1zs,873
277
279
  unfold/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
278
- unfold/templatetags/unfold.py,sha256=ht7dnFDANrzly8guUMES-PRR4S5e82I8fuWMD0bDieg,17297
280
+ unfold/templatetags/unfold.py,sha256=wIooF34mIRmyN-9l_hKSMVYWNauH8kwL_q11J7OJ3vQ,17411
279
281
  unfold/templatetags/unfold_list.py,sha256=ayShOYEXcV3o7wKt3t2aFTWvg62Mb-WGlxjYVGgk3a0,14344
280
282
  unfold/typing.py,sha256=i7LM2LiwYTAjT5-OLDUPVn5b9X-DMmHnjlZG2toWwSE,692
281
- unfold/utils.py,sha256=SJikRuAuJN0bE9rfzUujZwycTRrzQm14Hk0zB0EwivU,6164
283
+ unfold/utils.py,sha256=lXKkvhaTxoTtd4p3bB0wHIZD26md6XzBcDkPL5bJGH8,6191
282
284
  unfold/views.py,sha256=FuYnMrlg6SegLUDDN6An__yZj8rchD_iBK8myieYhkA,1492
283
- unfold/widgets.py,sha256=ZpwWbxEwgIqf-rZEaU71UwGwyuGyxE5TofaytXxxFEg,23062
284
- django_unfold-0.58.0.dist-info/LICENSE.md,sha256=Ltk_quRyyvV3J5v3brtOqmibeZSw2Hrb8bY1W3ya0Ik,1077
285
- django_unfold-0.58.0.dist-info/METADATA,sha256=bnstJhcMtmg1VBaWRfJO9Mt12BRJp6F_ikTi513G5nI,7951
286
- django_unfold-0.58.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
287
- django_unfold-0.58.0.dist-info/RECORD,,
285
+ unfold/widgets.py,sha256=z8bWwus1CYn20jp4f7tn_ChGUDCS563RZYp09I2kxIY,23216
286
+ django_unfold-0.59.0.dist-info/LICENSE.md,sha256=Ltk_quRyyvV3J5v3brtOqmibeZSw2Hrb8bY1W3ya0Ik,1077
287
+ django_unfold-0.59.0.dist-info/METADATA,sha256=AhBYGL06Dc5hTu3wW55BLYdrLmQxF_-NvvgX3cIibFY,7951
288
+ django_unfold-0.59.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
289
+ django_unfold-0.59.0.dist-info/RECORD,,
unfold/checks.py CHANGED
@@ -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>
unfold/decorators.py CHANGED
@@ -29,13 +29,19 @@ def action(
29
29
  **kwargs,
30
30
  ) -> Optional[HttpResponse]:
31
31
  if permissions:
32
- permission_checks = (
33
- getattr(model_admin, f"has_{permission}_permission")
34
- for permission in permissions
35
- )
36
- # Permissions methods have following syntax: has_<some>_permission(self, request, obj=None):
37
- # But obj is not examined by default in django admin and it would also require additional
38
- # 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
+
39
45
  has_detail_action = func.__name__ in model_admin._extract_action_names(
40
46
  model_admin.actions_detail
41
47
  )
@@ -46,12 +52,19 @@ def action(
46
52
  )
47
53
  )
48
54
 
49
- if not all(
50
- has_permission(request, kwargs.get("object_id"))
51
- if has_detail_action or has_submit_line_action
52
- else has_permission(request)
53
- for has_permission in permission_checks
54
- ):
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):
55
68
  raise PermissionDenied
56
69
  return func(model_admin, request, *args, **kwargs)
57
70
 
@@ -73,6 +86,7 @@ def action(
73
86
  inner.variant = ActionVariant.DEFAULT
74
87
 
75
88
  inner.attrs = attrs or {}
89
+ inner.original_function_name = func.__name__
76
90
  return inner
77
91
 
78
92
  if function is None:
unfold/fields.py CHANGED
@@ -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
unfold/forms.py CHANGED
@@ -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
  ]
unfold/layout.py CHANGED
@@ -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
unfold/paginator.py CHANGED
@@ -1,10 +1,21 @@
1
- from django.core.paginator import Paginator
1
+ from django.core.paginator import Page, Paginator
2
2
  from django.utils.functional import cached_property
3
3
 
4
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
+
5
13
  class InfinitePaginator(Paginator):
6
14
  template_name = "unfold/helpers/pagination_infinite.html"
7
15
 
8
16
  @cached_property
9
17
  def count(self):
10
18
  return 9_999_999_999
19
+
20
+ def _get_page(self, *args, **kwargs):
21
+ return InfinitePage(*args, **kwargs)
unfold/settings.py CHANGED
@@ -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": {
unfold/sites.py CHANGED
@@ -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),
@@ -296,6 +303,23 @@ class UnfoldAdminSite(AdminSite):
296
303
 
297
304
  return allowed_items
298
305
 
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
322
+
299
323
  def get_tabs_list(self, request: HttpRequest) -> list[dict[str, Any]]:
300
324
  tabs = copy.deepcopy(self._get_config("TABS", request))
301
325
 
@@ -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
  }