wagtail 6.2.2__py3-none-any.whl → 6.3rc2__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 (386) hide show
  1. wagtail/__init__.py +1 -1
  2. wagtail/actions/copy_for_translation.py +6 -0
  3. wagtail/actions/publish_revision.py +3 -3
  4. wagtail/admin/action_menu.py +5 -3
  5. wagtail/admin/forms/account.py +1 -1
  6. wagtail/admin/icons.py +2 -6
  7. wagtail/admin/locale/cy/LC_MESSAGES/django.mo +0 -0
  8. wagtail/admin/locale/cy/LC_MESSAGES/django.po +32 -0
  9. wagtail/admin/locale/dv/LC_MESSAGES/django.mo +0 -0
  10. wagtail/admin/locale/dv/LC_MESSAGES/django.po +28 -0
  11. wagtail/admin/locale/en/LC_MESSAGES/django.po +451 -485
  12. wagtail/admin/locale/en/LC_MESSAGES/djangojs.po +7 -7
  13. wagtail/admin/locale/sl/LC_MESSAGES/django.mo +0 -0
  14. wagtail/admin/locale/sl/LC_MESSAGES/django.po +150 -0
  15. wagtail/admin/locale/sl/LC_MESSAGES/djangojs.mo +0 -0
  16. wagtail/admin/locale/sl/LC_MESSAGES/djangojs.po +9 -2
  17. wagtail/admin/locale/ug/LC_MESSAGES/django.mo +0 -0
  18. wagtail/admin/locale/ug/LC_MESSAGES/django.po +3250 -196
  19. wagtail/admin/localization.py +12 -2
  20. wagtail/admin/panels/model_utils.py +1 -1
  21. wagtail/admin/site_summary.py +0 -2
  22. wagtail/admin/static/wagtailadmin/css/core.css +1 -1
  23. wagtail/admin/static/wagtailadmin/css/panels/draftail.css +1 -1
  24. wagtail/admin/static/wagtailadmin/images/email-header.jpg +0 -0
  25. wagtail/admin/static/wagtailadmin/js/bulk-actions.js +1 -1
  26. wagtail/admin/static/wagtailadmin/js/core.js +1 -1
  27. wagtail/admin/static/wagtailadmin/js/core.js.LICENSE.txt +12 -0
  28. wagtail/admin/static/wagtailadmin/js/draftail.js +1 -1
  29. wagtail/admin/static/wagtailadmin/js/sidebar.js +1 -1
  30. wagtail/admin/static/wagtailadmin/js/telepath/telepath.js +1 -1
  31. wagtail/admin/static/wagtailadmin/js/telepath/widgets.js +1 -1
  32. wagtail/admin/static/wagtailadmin/js/userbar.js +1 -1
  33. wagtail/admin/static/wagtailadmin/js/userbar.js.LICENSE.txt +1 -1
  34. wagtail/admin/static/wagtailadmin/js/vendor.js +1 -1
  35. wagtail/admin/static/wagtailadmin/js/wagtailadmin.js +1 -1
  36. wagtail/admin/static/wagtailadmin/js/workflow-action.js +1 -1
  37. wagtail/admin/staticfiles.py +6 -4
  38. wagtail/admin/templates/wagtailadmin/account/account.html +42 -59
  39. wagtail/admin/templates/wagtailadmin/admin_base.html +0 -28
  40. wagtail/admin/templates/wagtailadmin/bulk_actions/footer.html +1 -1
  41. wagtail/admin/templates/wagtailadmin/chooser/_search_results.html +7 -5
  42. wagtail/admin/templates/wagtailadmin/chooser/tables/page_navigate_to_children_cell.html +1 -1
  43. wagtail/admin/templates/wagtailadmin/generic/chooser/results.html +7 -5
  44. wagtail/admin/templates/wagtailadmin/generic/edit.html +0 -8
  45. wagtail/admin/templates/wagtailadmin/generic/form.html +60 -17
  46. wagtail/admin/templates/wagtailadmin/generic/index.html +17 -0
  47. wagtail/admin/templates/wagtailadmin/generic/index_results.html +9 -35
  48. wagtail/admin/templates/wagtailadmin/generic/inspect.html +2 -21
  49. wagtail/admin/templates/wagtailadmin/generic/listing.html +11 -17
  50. wagtail/admin/templates/wagtailadmin/generic/listing_results.html +19 -1
  51. wagtail/admin/templates/wagtailadmin/home/account_summary.html +26 -0
  52. wagtail/admin/templates/wagtailadmin/home/locked_pages.html +28 -18
  53. wagtail/admin/templates/wagtailadmin/home/recent_edits.html +28 -17
  54. wagtail/admin/templates/wagtailadmin/home/site_summary_pages.html +2 -2
  55. wagtail/admin/templates/wagtailadmin/home/upgrade_notification.html +35 -13
  56. wagtail/admin/templates/wagtailadmin/home/user_objects_in_workflow_moderation.html +28 -18
  57. wagtail/admin/templates/wagtailadmin/home/workflow_objects_to_moderate.html +43 -32
  58. wagtail/admin/templates/wagtailadmin/home.html +22 -5
  59. wagtail/admin/templates/wagtailadmin/pages/_editor_js.html +0 -1
  60. wagtail/admin/templates/wagtailadmin/pages/action_menu/menu.html +1 -11
  61. wagtail/admin/templates/wagtailadmin/pages/action_menu/menu_item.html +1 -6
  62. wagtail/admin/templates/wagtailadmin/pages/action_menu/page_locked.html +1 -1
  63. wagtail/admin/templates/wagtailadmin/pages/action_menu/publish.html +1 -1
  64. wagtail/admin/templates/wagtailadmin/pages/action_menu/save_draft.html +1 -1
  65. wagtail/admin/templates/wagtailadmin/pages/bulk_actions/confirm_bulk_delete.html +12 -6
  66. wagtail/admin/templates/wagtailadmin/pages/bulk_actions/confirm_bulk_move.html +12 -7
  67. wagtail/admin/templates/wagtailadmin/pages/bulk_actions/confirm_bulk_publish.html +17 -11
  68. wagtail/admin/templates/wagtailadmin/pages/bulk_actions/confirm_bulk_unpublish.html +15 -9
  69. wagtail/admin/templates/wagtailadmin/pages/confirm_delete.html +9 -9
  70. wagtail/admin/templates/wagtailadmin/pages/confirm_move.html +2 -2
  71. wagtail/admin/templates/wagtailadmin/pages/confirm_unpublish.html +4 -4
  72. wagtail/admin/templates/wagtailadmin/pages/create.html +15 -34
  73. wagtail/admin/templates/wagtailadmin/pages/edit.html +15 -30
  74. wagtail/admin/templates/wagtailadmin/pages/explorable_index.html +6 -0
  75. wagtail/admin/templates/wagtailadmin/pages/explorable_index_results.html +60 -0
  76. wagtail/admin/templates/wagtailadmin/pages/index.html +1 -36
  77. wagtail/admin/templates/wagtailadmin/pages/index_results.html +2 -50
  78. wagtail/admin/templates/wagtailadmin/pages/listing/_locked_indicator.html +1 -1
  79. wagtail/admin/templates/wagtailadmin/pages/listing/_ordering_cell.html +1 -1
  80. wagtail/admin/templates/wagtailadmin/pages/listing/_page_header_buttons.html +1 -1
  81. wagtail/admin/templates/wagtailadmin/pages/listing/_page_title_column_header.html +3 -3
  82. wagtail/admin/templates/wagtailadmin/pages/listing/_pagination.html +1 -1
  83. wagtail/admin/templates/wagtailadmin/pages/listing.html +24 -0
  84. wagtail/admin/templates/wagtailadmin/pages/search.html +1 -20
  85. wagtail/admin/templates/wagtailadmin/pages/search_results.html +27 -25
  86. wagtail/admin/templates/wagtailadmin/permissions/includes/collection_member_permissions_formset.html +0 -1
  87. wagtail/admin/templates/wagtailadmin/reports/listing/_list_page_report.html +2 -2
  88. wagtail/admin/templates/wagtailadmin/reports/listing/_list_page_types_usage.html +6 -6
  89. wagtail/admin/templates/wagtailadmin/reports/workflow_tasks_results.html +1 -1
  90. wagtail/admin/templates/wagtailadmin/shared/action_menu/menu.html +14 -0
  91. wagtail/admin/templates/wagtailadmin/shared/action_menu/menu_item.html +6 -0
  92. wagtail/admin/templates/wagtailadmin/shared/avatar.html +13 -3
  93. wagtail/admin/templates/wagtailadmin/shared/header.html +0 -5
  94. wagtail/admin/templates/wagtailadmin/shared/headers/slim_header.html +1 -1
  95. wagtail/admin/templates/wagtailadmin/shared/page_status_tag_new.html +4 -1
  96. wagtail/admin/templates/wagtailadmin/shared/pagination_nav.html +1 -1
  97. wagtail/admin/templates/wagtailadmin/shared/side_panel_toggle.html +1 -1
  98. wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/status/locale.html +1 -1
  99. wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/status/usage.html +2 -2
  100. wagtail/admin/templates/wagtailadmin/shared/side_panels/preview.html +94 -52
  101. wagtail/admin/templates/wagtailadmin/{pages/_unsaved_changes_warning.html → shared/unsaved_changes_warning.html} +4 -4
  102. wagtail/admin/templates/wagtailadmin/shared/usage_summary.html +2 -2
  103. wagtail/admin/templates/wagtailadmin/shared/workflow_history/detail.html +1 -7
  104. wagtail/admin/templates/wagtailadmin/shared/workflow_history/listing.html +1 -0
  105. wagtail/admin/templates/wagtailadmin/shared/workflow_history/{list.html → listing_results.html} +33 -35
  106. wagtail/admin/templates/wagtailadmin/tables/references_cell.html +1 -1
  107. wagtail/admin/templates/wagtailadmin/workflows/create.html +11 -36
  108. wagtail/admin/templates/wagtailadmin/workflows/create_task.html +0 -38
  109. wagtail/admin/templates/wagtailadmin/workflows/edit.html +44 -74
  110. wagtail/admin/templates/wagtailadmin/workflows/edit_task.html +27 -66
  111. wagtail/admin/templates/wagtailadmin/workflows/includes/task_usage_cell.html +4 -2
  112. wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_tasks_cell.html +4 -4
  113. wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_used_by_cell.html +15 -11
  114. wagtail/admin/templates/wagtailadmin/workflows/task_chooser/includes/results.html +7 -5
  115. wagtail/admin/templatetags/wagtailadmin_tags.py +51 -22
  116. wagtail/admin/tests/pages/test_content_type_use_view.py +82 -2
  117. wagtail/admin/tests/pages/test_edit_page.py +70 -0
  118. wagtail/admin/tests/pages/test_explorer_view.py +65 -4
  119. wagtail/admin/tests/pages/test_page_search.py +8 -7
  120. wagtail/admin/tests/pages/test_page_usage.py +3 -1
  121. wagtail/admin/tests/pages/test_preview.py +208 -63
  122. wagtail/admin/tests/pages/test_reorder_page.py +91 -1
  123. wagtail/admin/tests/pages/test_view_draft.py +32 -1
  124. wagtail/admin/tests/pages/test_workflow_history.py +288 -7
  125. wagtail/admin/tests/test_account_management.py +23 -3
  126. wagtail/admin/tests/test_audit_log.py +24 -2
  127. wagtail/admin/tests/test_collections_views.py +17 -5
  128. wagtail/admin/tests/test_dashboard.py +1 -1
  129. wagtail/admin/tests/test_edit_handlers.py +3 -2
  130. wagtail/admin/tests/test_icon_sprite.py +4 -0
  131. wagtail/admin/tests/test_privacy.py +5 -19
  132. wagtail/admin/tests/test_reports_views.py +1 -1
  133. wagtail/admin/tests/test_site_summary.py +3 -3
  134. wagtail/admin/tests/test_templatetags.py +27 -3
  135. wagtail/admin/tests/test_upgrade_notification.py +71 -18
  136. wagtail/admin/tests/test_views.py +2 -2
  137. wagtail/admin/tests/test_views_generic.py +13 -0
  138. wagtail/admin/tests/test_widgets.py +3 -3
  139. wagtail/admin/tests/test_workflows.py +172 -27
  140. wagtail/admin/tests/tests.py +1 -1
  141. wagtail/admin/tests/viewsets/test_model_viewset.py +55 -3
  142. wagtail/admin/ui/side_panels.py +19 -0
  143. wagtail/admin/ui/sidebar.py +4 -3
  144. wagtail/admin/ui/tables/__init__.py +14 -1
  145. wagtail/admin/ui/tables/pages.py +6 -1
  146. wagtail/admin/urls/pages.py +10 -1
  147. wagtail/admin/urls/workflows.py +6 -1
  148. wagtail/admin/views/account.py +5 -1
  149. wagtail/admin/views/collections.py +0 -2
  150. wagtail/admin/views/generic/base.py +118 -1
  151. wagtail/admin/views/generic/history.py +158 -26
  152. wagtail/admin/views/generic/models.py +113 -99
  153. wagtail/admin/views/home.py +24 -9
  154. wagtail/admin/views/page_privacy.py +54 -30
  155. wagtail/admin/views/pages/history.py +11 -4
  156. wagtail/admin/views/pages/listing.py +76 -89
  157. wagtail/admin/views/pages/preview.py +1 -1
  158. wagtail/admin/views/pages/search.py +27 -71
  159. wagtail/admin/views/pages/usage.py +63 -24
  160. wagtail/admin/views/pages/utils.py +4 -3
  161. wagtail/admin/views/reports/base.py +0 -6
  162. wagtail/admin/views/workflows.py +67 -25
  163. wagtail/admin/viewsets/model.py +4 -3
  164. wagtail/admin/widgets/chooser.py +2 -1
  165. wagtail/api/v2/tests/test_pages.py +15 -2
  166. wagtail/blocks/field_block.py +15 -3
  167. wagtail/blocks/static_block.py +3 -0
  168. wagtail/contrib/forms/locale/cy/LC_MESSAGES/django.mo +0 -0
  169. wagtail/contrib/forms/locale/cy/LC_MESSAGES/django.po +29 -1
  170. wagtail/contrib/forms/locale/en/LC_MESSAGES/django.po +15 -11
  171. wagtail/contrib/forms/templates/wagtailforms/confirm_delete.html +1 -0
  172. wagtail/contrib/forms/templates/wagtailforms/index.html +1 -1
  173. wagtail/contrib/forms/templates/wagtailforms/index_results.html +1 -1
  174. wagtail/contrib/forms/templates/wagtailforms/list_submissions.html +2 -1
  175. wagtail/contrib/forms/templates/wagtailforms/panels/form_responses_panel.html +2 -2
  176. wagtail/contrib/forms/tests/test_views.py +234 -35
  177. wagtail/contrib/forms/utils.py +8 -14
  178. wagtail/contrib/forms/views.py +72 -27
  179. wagtail/contrib/frontend_cache/backends/azure.py +1 -1
  180. wagtail/contrib/frontend_cache/backends/cloudfront.py +2 -2
  181. wagtail/contrib/frontend_cache/backends/dummy.py +11 -0
  182. wagtail/contrib/frontend_cache/tests.py +31 -37
  183. wagtail/contrib/frontend_cache/utils.py +12 -5
  184. wagtail/contrib/redirects/locale/cy/LC_MESSAGES/django.mo +0 -0
  185. wagtail/contrib/redirects/locale/cy/LC_MESSAGES/django.po +16 -1
  186. wagtail/contrib/redirects/locale/en/LC_MESSAGES/django.po +20 -24
  187. wagtail/contrib/redirects/models.py +16 -1
  188. wagtail/contrib/redirects/signal_handlers.py +18 -3
  189. wagtail/contrib/redirects/templates/wagtailredirects/add.html +5 -16
  190. wagtail/contrib/redirects/templates/wagtailredirects/import_summary.html +1 -1
  191. wagtail/contrib/redirects/tests/test_redirects.py +49 -6
  192. wagtail/contrib/redirects/tests/test_signal_handlers.py +42 -1
  193. wagtail/contrib/redirects/views.py +27 -3
  194. wagtail/contrib/search_promotions/locale/cy/LC_MESSAGES/django.mo +0 -0
  195. wagtail/contrib/search_promotions/locale/cy/LC_MESSAGES/django.po +60 -1
  196. wagtail/contrib/search_promotions/locale/en/LC_MESSAGES/django.po +12 -18
  197. wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/add.html +5 -8
  198. wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/edit.html +15 -10
  199. wagtail/contrib/search_promotions/tests.py +13 -2
  200. wagtail/contrib/search_promotions/views.py +15 -3
  201. wagtail/contrib/settings/locale/cy/LC_MESSAGES/django.mo +0 -0
  202. wagtail/contrib/settings/locale/cy/LC_MESSAGES/django.po +6 -1
  203. wagtail/contrib/settings/locale/en/LC_MESSAGES/django.po +2 -10
  204. wagtail/contrib/settings/templates/wagtailsettings/edit.html +12 -45
  205. wagtail/contrib/simple_translation/locale/cy/LC_MESSAGES/django.mo +0 -0
  206. wagtail/contrib/simple_translation/locale/cy/LC_MESSAGES/django.po +13 -1
  207. wagtail/contrib/simple_translation/locale/dv/LC_MESSAGES/django.mo +0 -0
  208. wagtail/contrib/simple_translation/locale/dv/LC_MESSAGES/django.po +3 -0
  209. wagtail/contrib/simple_translation/locale/en/LC_MESSAGES/django.po +4 -4
  210. wagtail/contrib/simple_translation/locale/sl/LC_MESSAGES/django.mo +0 -0
  211. wagtail/contrib/simple_translation/locale/sl/LC_MESSAGES/django.po +5 -2
  212. wagtail/contrib/simple_translation/tests/test_views.py +51 -0
  213. wagtail/contrib/simple_translation/wagtail_hooks.py +16 -11
  214. wagtail/contrib/styleguide/locale/cy/LC_MESSAGES/django.mo +0 -0
  215. wagtail/contrib/styleguide/locale/cy/LC_MESSAGES/django.po +5 -1
  216. wagtail/contrib/styleguide/locale/en/LC_MESSAGES/django.po +1 -1
  217. wagtail/contrib/table_block/locale/cy/LC_MESSAGES/django.mo +0 -0
  218. wagtail/contrib/table_block/locale/cy/LC_MESSAGES/django.po +27 -1
  219. wagtail/contrib/table_block/locale/en/LC_MESSAGES/django.po +1 -1
  220. wagtail/contrib/typed_table_block/blocks.py +25 -0
  221. wagtail/contrib/typed_table_block/locale/cy/LC_MESSAGES/django.mo +0 -0
  222. wagtail/contrib/typed_table_block/locale/cy/LC_MESSAGES/django.po +12 -1
  223. wagtail/contrib/typed_table_block/locale/en/LC_MESSAGES/django.po +10 -10
  224. wagtail/contrib/typed_table_block/tests.py +24 -1
  225. wagtail/coreutils.py +5 -11
  226. wagtail/documents/admin_urls.py +2 -2
  227. wagtail/documents/locale/cy/LC_MESSAGES/django.mo +0 -0
  228. wagtail/documents/locale/cy/LC_MESSAGES/django.po +10 -0
  229. wagtail/documents/locale/en/LC_MESSAGES/django.po +61 -76
  230. wagtail/documents/migrations/0014_alter_document_file_size.py +18 -0
  231. wagtail/documents/models.py +1 -1
  232. wagtail/documents/rich_text/__init__.py +1 -3
  233. wagtail/documents/static/wagtaildocs/js/add-multiple.js +1 -1
  234. wagtail/documents/templates/wagtaildocs/bulk_actions/confirm_bulk_add_tags.html +5 -1
  235. wagtail/documents/templates/wagtaildocs/bulk_actions/confirm_bulk_add_to_collection.html +5 -1
  236. wagtail/documents/templates/wagtaildocs/bulk_actions/confirm_bulk_delete.html +11 -5
  237. wagtail/documents/templates/wagtaildocs/documents/add.html +13 -41
  238. wagtail/documents/templates/wagtaildocs/documents/edit.html +28 -56
  239. wagtail/documents/templates/wagtaildocs/documents/index.html +1 -4
  240. wagtail/documents/templates/wagtaildocs/homepage/site_summary_documents.html +2 -2
  241. wagtail/documents/templates/wagtaildocs/multiple/add.html +36 -41
  242. wagtail/documents/tests/test_admin_views.py +64 -6
  243. wagtail/documents/tests/test_site_summary.py +3 -3
  244. wagtail/documents/views/documents.py +103 -113
  245. wagtail/documents/views/multiple.py +19 -1
  246. wagtail/embeds/locale/en/LC_MESSAGES/django.po +1 -1
  247. wagtail/embeds/oembed_providers.py +9 -19
  248. wagtail/fields.py +43 -27
  249. wagtail/images/admin_urls.py +2 -2
  250. wagtail/images/blocks.py +230 -2
  251. wagtail/images/fields.py +17 -29
  252. wagtail/images/image_operations.py +1 -1
  253. wagtail/images/locale/cy/LC_MESSAGES/django.mo +0 -0
  254. wagtail/images/locale/cy/LC_MESSAGES/django.po +128 -1
  255. wagtail/images/locale/en/LC_MESSAGES/django.po +119 -129
  256. wagtail/images/migrations/0025_alter_image_file_alter_rendition_file.py +36 -43
  257. wagtail/images/migrations/0027_image_description.py +20 -0
  258. wagtail/images/models.py +120 -45
  259. wagtail/images/rich_text/__init__.py +1 -3
  260. wagtail/images/static/wagtailimages/js/add-multiple.js +1 -1
  261. wagtail/images/static/wagtailimages/js/image-block.js +1 -0
  262. wagtail/images/templates/wagtailimages/bulk_actions/confirm_bulk_add_tags.html +5 -1
  263. wagtail/images/templates/wagtailimages/bulk_actions/confirm_bulk_add_to_collection.html +5 -1
  264. wagtail/images/templates/wagtailimages/bulk_actions/confirm_bulk_delete.html +11 -5
  265. wagtail/images/templates/wagtailimages/chooser/results.html +2 -2
  266. wagtail/images/templates/wagtailimages/homepage/site_summary_images.html +2 -2
  267. wagtail/images/templates/wagtailimages/images/_file_field.html +2 -2
  268. wagtail/images/templates/wagtailimages/images/add.html +13 -31
  269. wagtail/images/templates/wagtailimages/images/edit.html +53 -82
  270. wagtail/images/templates/wagtailimages/images/index.html +1 -4
  271. wagtail/images/templates/wagtailimages/images/url_generator.html +1 -1
  272. wagtail/images/templates/wagtailimages/multiple/add.html +40 -47
  273. wagtail/images/templates/wagtailimages/widgets/image.html +5 -0
  274. wagtail/images/templates/wagtailimages/widgets/image_chooser.html +1 -1
  275. wagtail/images/tests/test_admin_views.py +70 -10
  276. wagtail/images/tests/test_blocks.py +367 -1
  277. wagtail/images/tests/test_image_operations.py +23 -0
  278. wagtail/images/tests/test_models.py +20 -0
  279. wagtail/images/tests/test_signal_handlers.py +99 -95
  280. wagtail/images/tests/test_site_summary.py +3 -3
  281. wagtail/images/tests/test_templatetags.py +11 -7
  282. wagtail/images/tests/tests.py +4 -0
  283. wagtail/images/views/images.py +103 -104
  284. wagtail/images/views/multiple.py +17 -1
  285. wagtail/locale/cy/LC_MESSAGES/django.mo +0 -0
  286. wagtail/locale/cy/LC_MESSAGES/django.po +3 -0
  287. wagtail/locale/en/LC_MESSAGES/django.po +137 -125
  288. wagtail/locale/sl/LC_MESSAGES/django.mo +0 -0
  289. wagtail/locale/sl/LC_MESSAGES/django.po +3 -0
  290. wagtail/locales/locale/en/LC_MESSAGES/django.po +8 -8
  291. wagtail/locales/views.py +4 -1
  292. wagtail/migrations/0089_log_entry_data_json_null_to_object.py +1 -7
  293. wagtail/models/__init__.py +122 -14
  294. wagtail/models/audit_log.py +1 -3
  295. wagtail/models/i18n.py +1 -2
  296. wagtail/project_template/Dockerfile +3 -3
  297. wagtail/project_template/requirements.txt +2 -2
  298. wagtail/query.py +17 -4
  299. wagtail/rich_text/__init__.py +2 -3
  300. wagtail/rich_text/pages.py +2 -4
  301. wagtail/rich_text/rewriters.py +2 -2
  302. wagtail/search/backends/database/mysql/query.py +3 -3
  303. wagtail/search/backends/database/sqlite/query.py +6 -6
  304. wagtail/search/locale/en/LC_MESSAGES/django.po +1 -1
  305. wagtail/sites/locale/en/LC_MESSAGES/django.po +6 -6
  306. wagtail/sites/views.py +0 -1
  307. wagtail/snippets/action_menu.py +14 -4
  308. wagtail/snippets/locale/cy/LC_MESSAGES/django.mo +0 -0
  309. wagtail/snippets/locale/cy/LC_MESSAGES/django.po +73 -1
  310. wagtail/snippets/locale/en/LC_MESSAGES/django.po +27 -33
  311. wagtail/snippets/static/wagtailsnippets/js/snippet-chooser-telepath.js +1 -1
  312. wagtail/snippets/static/wagtailsnippets/js/snippet-chooser.js +1 -1
  313. wagtail/snippets/templates/wagtailsnippets/bulk_actions/confirm_bulk_delete.html +5 -3
  314. wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/locked.html +1 -1
  315. wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/menu.html +1 -11
  316. wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/menu_item.html +1 -6
  317. wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/publish.html +1 -1
  318. wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/save.html +1 -1
  319. wagtail/snippets/templates/wagtailsnippets/snippets/create.html +1 -18
  320. wagtail/snippets/templates/wagtailsnippets/snippets/edit.html +1 -14
  321. wagtail/snippets/templates/wagtailsnippets/snippets/index.html +2 -5
  322. wagtail/snippets/tests/test_preview.py +193 -61
  323. wagtail/snippets/tests/test_snippets.py +247 -38
  324. wagtail/snippets/tests/test_usage.py +5 -0
  325. wagtail/snippets/tests/test_viewset.py +25 -9
  326. wagtail/snippets/tests/test_workflows.py +232 -19
  327. wagtail/snippets/views/snippets.py +1 -10
  328. wagtail/test/numberformat.py +104 -0
  329. wagtail/test/settings.py +10 -0
  330. wagtail/test/settings_ui.py +2 -0
  331. wagtail/test/testapp/migrations/0010_alter_customimage_file_and_more.py +71 -78
  332. wagtail/test/testapp/migrations/0040_nocreatablesubpagetypespage_nosubpagetypespage.py +54 -0
  333. wagtail/test/testapp/migrations/0041_alter_jsonstreammodel_options.py +17 -0
  334. wagtail/test/testapp/migrations/0042_alter_customdocument_file_size_and_more.py +28 -0
  335. wagtail/test/testapp/migrations/0043_customimage_description.py +41 -0
  336. wagtail/test/testapp/migrations/0044_custompreviewsizesmodel_custompreviewsizespage.py +52 -0
  337. wagtail/test/testapp/migrations/0045_alter_streampage_body.py +52 -0
  338. wagtail/test/testapp/models.py +62 -4
  339. wagtail/test/testapp/rich_text.py +2 -2
  340. wagtail/test/testapp/templates/tests/form_page_landing.html +2 -1
  341. wagtail/test/testapp/urls.py +5 -0
  342. wagtail/test/testapp/views.py +5 -0
  343. wagtail/test/utils/page_tests.py +5 -5
  344. wagtail/test/utils/template_tests.py +2 -2
  345. wagtail/tests/test_blocks.py +15 -0
  346. wagtail/tests/test_page_permissions.py +109 -0
  347. wagtail/tests/test_revision_model.py +27 -0
  348. wagtail/tests/test_signals.py +21 -2
  349. wagtail/tests/test_tests.py +30 -0
  350. wagtail/users/locale/cy/LC_MESSAGES/django.mo +0 -0
  351. wagtail/users/locale/cy/LC_MESSAGES/django.po +118 -1
  352. wagtail/users/locale/dv/LC_MESSAGES/django.mo +0 -0
  353. wagtail/users/locale/dv/LC_MESSAGES/django.po +3 -0
  354. wagtail/users/locale/en/LC_MESSAGES/django.po +89 -113
  355. wagtail/users/locale/sl/LC_MESSAGES/django.mo +0 -0
  356. wagtail/users/locale/sl/LC_MESSAGES/django.po +3 -0
  357. wagtail/users/migrations/0014_userprofile_contrast.py +23 -0
  358. wagtail/users/models.py +11 -0
  359. wagtail/users/templates/wagtailusers/bulk_actions/confirm_bulk_assign_role.html +5 -1
  360. wagtail/users/templates/wagtailusers/bulk_actions/confirm_bulk_delete.html +5 -1
  361. wagtail/users/templates/wagtailusers/bulk_actions/confirm_bulk_set_active_state.html +5 -1
  362. wagtail/users/templates/wagtailusers/groups/create.html +19 -17
  363. wagtail/users/templates/wagtailusers/groups/edit.html +2 -40
  364. wagtail/users/templates/wagtailusers/groups/includes/formatted_permissions.html +1 -62
  365. wagtail/users/templates/wagtailusers/groups/includes/page_permissions_formset.html +0 -1
  366. wagtail/users/templates/wagtailusers/users/create.html +46 -50
  367. wagtail/users/templates/wagtailusers/users/edit.html +45 -62
  368. wagtail/users/templates/wagtailusers/users/index.html +1 -4
  369. wagtail/users/templatetags/wagtailusers_tags.py +1 -5
  370. wagtail/users/tests/test_admin_views.py +85 -66
  371. wagtail/users/views/groups.py +4 -1
  372. wagtail/users/views/users.py +2 -0
  373. {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/METADATA +6 -6
  374. {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/RECORD +378 -367
  375. wagtail/admin/static/wagtailadmin/js/preview-panel.js +0 -2
  376. wagtail/admin/static/wagtailadmin/js/preview-panel.js.LICENSE.txt +0 -11
  377. wagtail/admin/templates/wagtailadmin/generic/history_results.html +0 -1
  378. wagtail/admin/templates/wagtailadmin/page_privacy/ancestor_privacy.html +0 -3
  379. wagtail/admin/templates/wagtailadmin/pages/usage_results.html +0 -6
  380. wagtail/admin/templates/wagtailadmin/shared/workflow_history/index.html +0 -17
  381. wagtail/admin/templates/wagtailadmin/shared/workflow_history/results.html +0 -17
  382. wagtail/admin/templates/wagtailadmin/workflows/usage.html +0 -44
  383. {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/LICENSE +0 -0
  384. {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/WHEEL +0 -0
  385. {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/entry_points.txt +0 -0
  386. {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/top_level.txt +0 -0
@@ -8,7 +8,7 @@ msgid ""
8
8
  msgstr ""
9
9
  "Project-Id-Version: PACKAGE VERSION\n"
10
10
  "Report-Msgid-Bugs-To: \n"
11
- "POT-Creation-Date: 2024-08-07 10:06+0100\n"
11
+ "POT-Creation-Date: 2024-10-21 17:53+0100\n"
12
12
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -79,24 +79,24 @@ msgstr ""
79
79
  msgid "The locale could not be saved due to errors."
80
80
  msgstr ""
81
81
 
82
- #: views.py:57 views.py:64
83
- msgid "Delete locale"
82
+ #: views.py:62
83
+ #, python-format
84
+ msgid "Locale '%(object)s' deleted."
84
85
  msgstr ""
85
86
 
86
87
  #: views.py:63
87
- #, python-format
88
- msgid "Locale '%(object)s' deleted."
88
+ msgid "Delete locale"
89
89
  msgstr ""
90
90
 
91
- #: views.py:65
91
+ #: views.py:64
92
92
  msgid "Are you sure you want to delete this locale?"
93
93
  msgstr ""
94
94
 
95
- #: views.py:71
95
+ #: views.py:70
96
96
  msgid "This locale cannot be deleted because there are no other locales."
97
97
  msgstr ""
98
98
 
99
- #: views.py:77
99
+ #: views.py:76
100
100
  msgid ""
101
101
  "This locale cannot be deleted because there are pages and/or other objects "
102
102
  "using it."
wagtail/locales/views.py CHANGED
@@ -54,7 +54,6 @@ class CreateView(generic.CreateView):
54
54
  class EditView(generic.EditView):
55
55
  success_message = gettext_lazy("Locale '%(object)s' updated.")
56
56
  error_message = gettext_lazy("The locale could not be saved due to errors.")
57
- delete_item_label = gettext_lazy("Delete locale")
58
57
  context_object_name = "locale"
59
58
  queryset = Locale.all_objects.all()
60
59
 
@@ -104,6 +103,10 @@ class LocaleViewSet(ModelViewSet):
104
103
  edit_view_class = EditView
105
104
  delete_view_class = DeleteView
106
105
 
106
+ # It does not make sense to copy Locale objects as they only contain the
107
+ # language code and are meant to be unique.
108
+ copy_view_enabled = False
109
+
107
110
  template_prefix = "wagtaillocales/"
108
111
 
109
112
  def get_common_view_kwargs(self, **kwargs):
@@ -1,6 +1,5 @@
1
1
  # Generated by Django 4.2.3 on 2023-07-31 11:00
2
2
 
3
- from django import VERSION as DJANGO_VERSION
4
3
  from django.db import migrations, models
5
4
 
6
5
 
@@ -8,12 +7,7 @@ def replace_json_null_with_empty_object(apps, schema_editor):
8
7
  ModelLogEntry = apps.get_model("wagtailcore.ModelLogEntry")
9
8
  PageLogEntry = apps.get_model("wagtailcore.PageLogEntry")
10
9
 
11
- # https://github.com/django/django/pull/16245
12
- # The way to express a JSON `null` value was changed in Django 4.2.
13
- if DJANGO_VERSION >= (4, 2):
14
- null = models.Value(None, models.JSONField())
15
- else:
16
- null = models.Value("null")
10
+ null = models.Value(None, models.JSONField())
17
11
 
18
12
  ModelLogEntry.objects.filter(data=null).update(data={})
19
13
  PageLogEntry.objects.filter(data=null).update(data={})
@@ -193,7 +193,7 @@ def get_default_page_content_type():
193
193
  return ContentType.objects.get_for_model(Page)
194
194
 
195
195
 
196
- @functools.lru_cache(maxsize=None)
196
+ @functools.cache
197
197
  def get_streamfield_names(model_class):
198
198
  return tuple(
199
199
  field.name
@@ -235,6 +235,36 @@ class BasePageManager(models.Manager):
235
235
 
236
236
  return self.get(path=common_parent_path)
237
237
 
238
+ def annotate_parent_page(self, pages):
239
+ """
240
+ Annotates each page with its parent page. This is implemented as a
241
+ manager-only method instead of a QuerySet method so it can be used with
242
+ search results.
243
+
244
+ If given a QuerySet, this method will evaluate it. Only use this method
245
+ when you are ready to consume the queryset, e.g. after pagination has
246
+ been applied. This is typically done in the view's `get_context_data`
247
+ using `context["object_list"]`.
248
+
249
+ This method does not return a new queryset, but modifies the existing one,
250
+ to ensure any references to the queryset in the view's context are updated
251
+ (e.g. when using `context_object_name`).
252
+ """
253
+ parent_page_paths = {
254
+ Page._get_parent_path_from_path(page.path) for page in pages
255
+ }
256
+ parent_pages_by_path = {
257
+ page.path: page
258
+ for page in Page.objects.filter(path__in=parent_page_paths).specific(
259
+ defer=True
260
+ )
261
+ }
262
+ for page in pages:
263
+ parent_page = parent_pages_by_path.get(
264
+ Page._get_parent_path_from_path(page.path)
265
+ )
266
+ page._parent_page = parent_page
267
+
238
268
 
239
269
  PageManager = BasePageManager.from_queryset(PageQuerySet)
240
270
 
@@ -642,7 +672,7 @@ class DraftStateMixin(models.Model):
642
672
 
643
673
  def get_lock(self):
644
674
  # Scheduled publishing lock should take precedence over other locks
645
- if self.scheduled_revision:
675
+ if self.approved_schedule:
646
676
  return ScheduledForPublishLock(self)
647
677
  return super().get_lock()
648
678
 
@@ -775,6 +805,26 @@ class PreviewableMixin:
775
805
  full_url = property(get_full_url)
776
806
 
777
807
  DEFAULT_PREVIEW_MODES = [("", _("Default"))]
808
+ DEFAULT_PREVIEW_SIZES = [
809
+ {
810
+ "name": "mobile",
811
+ "icon": "mobile-alt",
812
+ "device_width": 375,
813
+ "label": _("Preview in mobile size"),
814
+ },
815
+ {
816
+ "name": "tablet",
817
+ "icon": "tablet-alt",
818
+ "device_width": 768,
819
+ "label": _("Preview in tablet size"),
820
+ },
821
+ {
822
+ "name": "desktop",
823
+ "icon": "desktop",
824
+ "device_width": 1280,
825
+ "label": _("Preview in desktop size"),
826
+ },
827
+ ]
778
828
 
779
829
  @property
780
830
  def preview_modes(self):
@@ -798,6 +848,43 @@ class PreviewableMixin:
798
848
  """
799
849
  return self.preview_modes[0][0]
800
850
 
851
+ @property
852
+ def preview_sizes(self):
853
+ """
854
+ A list of dictionaries, each representing a preview size option for this object.
855
+ Override this property to customize the preview sizes.
856
+ Each dictionary in the list should include the following keys:
857
+
858
+ - ``name``: A string representing the internal name of the preview size.
859
+ - ``icon``: A string specifying the icon's name for the preview size button.
860
+ - ``device_width``: An integer indicating the device's width in pixels.
861
+ - ``label``: A string for the aria label on the preview size button.
862
+
863
+ .. code-block:: python
864
+
865
+ @property
866
+ def preview_sizes(self):
867
+ return [
868
+ {
869
+ "name": "mobile",
870
+ "icon": "mobile-icon",
871
+ "device_width": 320,
872
+ "label": "Preview in mobile size"
873
+ },
874
+ # Add more preview size dictionaries as needed.
875
+ ]
876
+ """
877
+ return PreviewableMixin.DEFAULT_PREVIEW_SIZES
878
+
879
+ @property
880
+ def default_preview_size(self):
881
+ """
882
+ The default preview size name to use in live preview.
883
+ Defaults to ``"mobile"``, which is the first one defined in ``preview_sizes``.
884
+ If ``preview_sizes`` is empty, an ``IndexError`` will be raised.
885
+ """
886
+ return self.preview_sizes[0]["name"]
887
+
801
888
  def is_previewable(self):
802
889
  """Returns ``True`` if at least one preview mode is specified in ``preview_modes``."""
803
890
  return bool(self.preview_modes)
@@ -1295,7 +1382,7 @@ class Page(AbstractPage, index.Indexed, ClusterableModel, metaclass=PageBase):
1295
1382
  private_page_options = ["password", "groups", "login"]
1296
1383
 
1297
1384
  @staticmethod
1298
- def route_for_request(request: "HttpRequest", path: str) -> RouteResult | None:
1385
+ def route_for_request(request: HttpRequest, path: str) -> RouteResult | None:
1299
1386
  """
1300
1387
  Find the page route for the given HTTP request object, and URL path. The route
1301
1388
  result (`page`, `args`, and `kwargs`) will be cached via
@@ -1322,7 +1409,7 @@ class Page(AbstractPage, index.Indexed, ClusterableModel, metaclass=PageBase):
1322
1409
  return request._wagtail_route_for_request
1323
1410
 
1324
1411
  @staticmethod
1325
- def find_for_request(request: "HttpRequest", path: str) -> "Page" | None:
1412
+ def find_for_request(request: HttpRequest, path: str) -> Page | None:
1326
1413
  """
1327
1414
  Find the page for the given HTTP request object, and URL path. The full
1328
1415
  page route will be cached via `request._wagtail_route_for_request`
@@ -2792,12 +2879,20 @@ class RevisionQuerySet(models.QuerySet):
2792
2879
  return self.exclude(self.page_revisions_q())
2793
2880
 
2794
2881
  def for_instance(self, instance):
2795
- return self.filter(
2796
- content_type=ContentType.objects.get_for_model(
2797
- instance, for_concrete_model=False
2798
- ),
2799
- object_id=str(instance.pk),
2800
- )
2882
+ try:
2883
+ # Use RevisionMixin.get_base_content_type() if available
2884
+ return self.filter(
2885
+ base_content_type=instance.get_base_content_type(),
2886
+ object_id=str(instance.pk),
2887
+ )
2888
+ except AttributeError:
2889
+ # Fallback to ContentType for the model
2890
+ return self.filter(
2891
+ content_type=ContentType.objects.get_for_model(
2892
+ instance, for_concrete_model=False
2893
+ ),
2894
+ object_id=str(instance.pk),
2895
+ )
2801
2896
 
2802
2897
 
2803
2898
  class RevisionsManager(models.Manager.from_queryset(RevisionQuerySet)):
@@ -3228,10 +3323,13 @@ class PagePermissionTester:
3228
3323
 
3229
3324
  def can_reorder_children(self):
3230
3325
  """
3231
- Keep reorder permissions the same as publishing, since it immediately affects published pages
3232
- (and the use-cases for a non-admin needing to do it are fairly obscure...)
3326
+ Reorder permission checking is similar to publishing a subpage, since it immediately
3327
+ affects published pages. However, it shouldn't care about the 'creatability' of
3328
+ page types, because the action only ever updates existing pages.
3233
3329
  """
3234
- return self.can_publish_subpage()
3330
+ if not self.user.is_active:
3331
+ return False
3332
+ return self.user.is_superuser or ("publish" in self.permissions)
3235
3333
 
3236
3334
  def can_move(self):
3237
3335
  """
@@ -3251,7 +3349,17 @@ class PagePermissionTester:
3251
3349
 
3252
3350
  # reject moves that are forbidden by subpage_types / parent_page_types rules
3253
3351
  # (these rules apply to superusers too)
3254
- if not self.page.specific.can_move_to(destination):
3352
+ # – but only check this if the page is not already under the target parent.
3353
+ # If it already is, then the user is just reordering the page, and we want
3354
+ # to allow it even if the page currently violates the subpage_type /
3355
+ # parent_page_type rules. This can happen if it was either created before
3356
+ # the rules were specified, or it was done programmatically (e.g. to
3357
+ # predefine a set of pages and disallow the creation of new subpages by
3358
+ # setting subpage_types = []).
3359
+
3360
+ if (not self.page.is_child_of(destination)) and (
3361
+ not self.page.specific.can_move_to(destination)
3362
+ ):
3255
3363
  return False
3256
3364
 
3257
3365
  # shortcut the trivial 'everything' / 'nothing' permissions
@@ -158,9 +158,7 @@ class BaseLogEntryManager(models.Manager):
158
158
  content_type = ContentType.objects.get_for_id(
159
159
  permission.content_type_id
160
160
  )
161
- if user.has_perm(
162
- "%s.%s" % (content_type.app_label, permission.codename)
163
- ):
161
+ if user.has_perm(f"{content_type.app_label}.{permission.codename}"):
164
162
  allowed_content_type_ids.add(permission.content_type_id)
165
163
 
166
164
  user._allowed_content_type_ids = allowed_content_type_ids
wagtail/models/i18n.py CHANGED
@@ -1,5 +1,4 @@
1
1
  import uuid
2
- from typing import Dict
3
2
 
4
3
  from django.apps import apps
5
4
  from django.conf import settings
@@ -98,7 +97,7 @@ class Locale(models.Model):
98
97
  def __str__(self):
99
98
  return force_str(self.get_display_name())
100
99
 
101
- def _get_language_info(self) -> Dict[str, str]:
100
+ def _get_language_info(self) -> dict[str, str]:
102
101
  return translation.get_language_info(self.language_code)
103
102
 
104
103
  @property
@@ -1,5 +1,5 @@
1
- # Use an official Python runtime based on Debian 10 "buster" as a parent image.
2
- FROM python:3.8.1-slim-buster
1
+ # Use an official Python runtime based on Debian 12 "bookworm" as a parent image.
2
+ FROM python:3.12-slim-bookworm
3
3
 
4
4
  # Add user that will be used in the container.
5
5
  RUN useradd wagtail
@@ -18,7 +18,7 @@ ENV PYTHONUNBUFFERED=1 \
18
18
  RUN apt-get update --yes --quiet && apt-get install --yes --quiet --no-install-recommends \
19
19
  build-essential \
20
20
  libpq-dev \
21
- libmariadbclient-dev \
21
+ libmariadb-dev \
22
22
  libjpeg62-turbo-dev \
23
23
  zlib1g-dev \
24
24
  libwebp-dev \
@@ -1,2 +1,2 @@
1
- Django>=4.2,<5.1
2
- wagtail>=6.2,<6.3
1
+ Django>=5.1,<5.2
2
+ wagtail==6.3rc2
wagtail/query.py CHANGED
@@ -1,16 +1,18 @@
1
1
  import posixpath
2
2
  import warnings
3
3
  from collections import defaultdict
4
- from typing import Any, Dict, Iterable, Tuple
4
+ from collections.abc import Iterable
5
+ from typing import Any
5
6
 
6
7
  from django.apps import apps
7
8
  from django.contrib.contenttypes.models import ContentType
8
9
  from django.db.models import CharField, Prefetch, Q
9
10
  from django.db.models.expressions import Exists, OuterRef
10
11
  from django.db.models.functions import Cast, Length, Substr
11
- from django.db.models.query import BaseIterable, ModelIterable
12
+ from django.db.models.query import ModelIterable
12
13
  from treebeard.mp_tree import MP_NodeQuerySet
13
14
 
15
+ from wagtail.models.i18n import Locale
14
16
  from wagtail.models.sites import Site
15
17
  from wagtail.search.queryset import SearchableQuerySetMixin
16
18
 
@@ -507,8 +509,19 @@ class PageQuerySet(SearchableQuerySetMixin, SpecificQuerySetMixin, TreeQuerySet)
507
509
  )
508
510
  )
509
511
 
512
+ def annotate_has_untranslated_locale(self):
513
+ return self.annotate(
514
+ _has_untranslated_locale=Exists(
515
+ Locale.objects.exclude(
516
+ id__in=self.model.objects.filter(
517
+ translation_key=OuterRef(OuterRef("translation_key"))
518
+ ).values("locale_id")
519
+ )
520
+ )
521
+ )
522
+
510
523
 
511
- class SpecificIterable(BaseIterable):
524
+ class SpecificIterable(ModelIterable):
512
525
  def __iter__(self):
513
526
  """
514
527
  Identify and return all specific items in a queryset, and return them
@@ -588,7 +601,7 @@ class SpecificIterable(BaseIterable):
588
601
  setattr(item, annotation, value)
589
602
  yield item
590
603
 
591
- def _get_chunks(self, queryset) -> Iterable[Tuple[Dict[str, Any]]]:
604
+ def _get_chunks(self, queryset) -> Iterable[tuple[dict[str, Any]]]:
592
605
  if not self.chunked_fetch:
593
606
  # The entire result will be stored in memory, so there is no
594
607
  # benefit to splitting the result
@@ -1,7 +1,6 @@
1
1
  import re
2
2
  from functools import lru_cache
3
3
  from html import unescape
4
- from typing import List
5
4
 
6
5
  from django.core.validators import MaxLengthValidator
7
6
  from django.db.models import Model
@@ -132,7 +131,7 @@ class EntityHandler:
132
131
  return model._default_manager.get(id=attrs["id"])
133
132
 
134
133
  @classmethod
135
- def get_many(cls, attrs_list: List[dict]) -> List[Model]:
134
+ def get_many(cls, attrs_list: list[dict]) -> list[Model]:
136
135
  model = cls.get_model()
137
136
  instance_ids = [attrs.get("id") for attrs in attrs_list]
138
137
  instances_by_id = model._default_manager.in_bulk(instance_ids)
@@ -148,7 +147,7 @@ class EntityHandler:
148
147
  raise NotImplementedError
149
148
 
150
149
  @classmethod
151
- def expand_db_attributes_many(cls, attrs_list: List[dict]) -> List[str]:
150
+ def expand_db_attributes_many(cls, attrs_list: list[dict]) -> list[str]:
152
151
  """
153
152
  Given a list of attribute dicts from a list of entity tags stored in
154
153
  the database, return the real HTML representation of each one.
@@ -1,5 +1,3 @@
1
- from typing import List
2
-
3
1
  from django.db.models import Model
4
2
  from django.utils.html import escape
5
3
 
@@ -15,7 +13,7 @@ class PageLinkHandler(LinkHandler):
15
13
  return Page
16
14
 
17
15
  @classmethod
18
- def get_many(cls, attrs_list: List[dict]) -> List[Model]:
16
+ def get_many(cls, attrs_list: list[dict]) -> list[Model]:
19
17
  # Override LinkHandler.get_many to reduce database queries through the
20
18
  # use of PageQuerySet.specific() instead of QuerySet.in_bulk().
21
19
  instance_ids = [attrs.get("id") for attrs in attrs_list]
@@ -28,7 +26,7 @@ class PageLinkHandler(LinkHandler):
28
26
  return cls.expand_db_attributes_many([attrs])[0]
29
27
 
30
28
  @classmethod
31
- def expand_db_attributes_many(cls, attrs_list: List[dict]) -> List[str]:
29
+ def expand_db_attributes_many(cls, attrs_list: list[dict]) -> list[str]:
32
30
  return [
33
31
  '<a href="%s">' % escape(page.localized.url) if page else "<a>"
34
32
  for page in cls.get_many(attrs_list)
@@ -4,7 +4,7 @@ Utility classes for rewriting elements of HTML-like strings
4
4
 
5
5
  import re
6
6
  from collections import defaultdict
7
- from typing import Callable, Dict, List
7
+ from typing import Callable
8
8
 
9
9
  from django.utils.functional import cached_property
10
10
 
@@ -101,7 +101,7 @@ class TagRewriter:
101
101
 
102
102
  return html
103
103
 
104
- def extract_tags(self, html: str) -> Dict[str, List[TagMatch]]:
104
+ def extract_tags(self, html: str) -> dict[str, list[TagMatch]]:
105
105
  """Helper method to extract and group HTML tags and their attributes.
106
106
 
107
107
  Returns a dict of TagMatch objects, mapping tag types to a list of all TagMatch objects of that tag type.
@@ -1,5 +1,5 @@
1
1
  import re
2
- from typing import Any, List, Tuple, Union
2
+ from typing import Any, Union
3
3
 
4
4
  from django.db.backends.base.base import BaseDatabaseWrapper
5
5
  from django.db.models.expressions import CombinedExpression, Expression, Value
@@ -166,7 +166,7 @@ class SearchQuery(SearchQueryCombinable, Expression):
166
166
  compiler: SQLCompiler,
167
167
  connection: BaseDatabaseWrapper,
168
168
  **extra_context: Any,
169
- ) -> Tuple[str, List[Any]]:
169
+ ) -> tuple[str, list[Any]]:
170
170
  sql, params = compiler.compile(self.value)
171
171
  return (sql, params)
172
172
 
@@ -229,7 +229,7 @@ class MatchExpression(Expression):
229
229
  def __init__(
230
230
  self,
231
231
  query: SearchQueryCombinable,
232
- columns: List[str] = None,
232
+ columns: list[str] = None,
233
233
  output_field: Field = BooleanField(),
234
234
  ) -> None:
235
235
  super().__init__(output_field=output_field)
@@ -1,4 +1,4 @@
1
- from typing import Any, List, Tuple
1
+ from typing import Any
2
2
 
3
3
  from django.db.backends.base.base import BaseDatabaseWrapper
4
4
  from django.db.models.expressions import CombinedExpression, Expression, Func, Value
@@ -149,7 +149,7 @@ class SearchQueryExpression(SearchQueryCombinable, Expression):
149
149
  compiler: SQLCompiler,
150
150
  connection: BaseDatabaseWrapper,
151
151
  **extra_context: Any,
152
- ) -> Tuple[str, List[Any]]:
152
+ ) -> tuple[str, list[Any]]:
153
153
  sql, params = compiler.compile(self.value)
154
154
  return (sql, params)
155
155
 
@@ -172,7 +172,7 @@ class MatchExpression(Expression):
172
172
  )
173
173
  output_field = BooleanField()
174
174
 
175
- def __init__(self, columns: List[str], query: SearchQueryCombinable) -> None:
175
+ def __init__(self, columns: list[str], query: SearchQueryCombinable) -> None:
176
176
  super().__init__(output_field=self.output_field)
177
177
  self.columns = columns
178
178
  self.query = query
@@ -211,7 +211,7 @@ class AndNot(SearchQuery):
211
211
  return f"<{repr(self.subquery_a)} AndNot {repr(self.subquery_b)}>"
212
212
 
213
213
 
214
- def normalize(search_query: SearchQuery) -> Tuple[SearchQuery]:
214
+ def normalize(search_query: SearchQuery) -> tuple[SearchQuery]:
215
215
  """
216
216
  Turns this query into a normalized version.
217
217
  For example, And(Not(PlainText("Arepa")), PlainText("Crepe")) would be turned into AndNot(PlainText("Crepe"), PlainText("Arepa")): "Crepe AND NOT Arepa".
@@ -222,7 +222,7 @@ def normalize(search_query: SearchQuery) -> Tuple[SearchQuery]:
222
222
  if isinstance(search_query, PlainText):
223
223
  return search_query # We can't normalize a PlainText.
224
224
  if isinstance(search_query, And):
225
- normalized_subqueries: List[SearchQuery] = [
225
+ normalized_subqueries: list[SearchQuery] = [
226
226
  normalize(subquery) for subquery in search_query.subqueries
227
227
  ] # This builds a list of normalized subqueries.
228
228
 
@@ -255,7 +255,7 @@ def normalize(search_query: SearchQuery) -> Tuple[SearchQuery]:
255
255
 
256
256
  return AndNot(And(not_negated_subqueries), Or(negated_subqueries))
257
257
  if isinstance(search_query, Or):
258
- normalized_subqueries: List[SearchQuery] = [
258
+ normalized_subqueries: list[SearchQuery] = [
259
259
  normalize(subquery) for subquery in search_query.subqueries
260
260
  ] # This builds a list of (subquery, negated) tuples.
261
261
 
@@ -8,7 +8,7 @@ msgid ""
8
8
  msgstr ""
9
9
  "Project-Id-Version: PACKAGE VERSION\n"
10
10
  "Report-Msgid-Bugs-To: \n"
11
- "POT-Creation-Date: 2024-08-07 10:06+0100\n"
11
+ "POT-Creation-Date: 2024-10-21 17:53+0100\n"
12
12
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -8,7 +8,7 @@ msgid ""
8
8
  msgstr ""
9
9
  "Project-Id-Version: PACKAGE VERSION\n"
10
10
  "Report-Msgid-Bugs-To: \n"
11
- "POT-Creation-Date: 2024-08-07 10:06+0100\n"
11
+ "POT-Creation-Date: 2024-10-21 17:53+0100\n"
12
12
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -68,15 +68,15 @@ msgstr ""
68
68
  msgid "Site '%(object)s' updated."
69
69
  msgstr ""
70
70
 
71
- #: views.py:44 views.py:50
72
- msgid "Delete site"
71
+ #: views.py:48
72
+ #, python-format
73
+ msgid "Site '%(object)s' deleted."
73
74
  msgstr ""
74
75
 
75
76
  #: views.py:49
76
- #, python-format
77
- msgid "Site '%(object)s' deleted."
77
+ msgid "Delete site"
78
78
  msgstr ""
79
79
 
80
- #: views.py:51
80
+ #: views.py:50
81
81
  msgid "Are you sure you want to delete this site?"
82
82
  msgstr ""
wagtail/sites/views.py CHANGED
@@ -41,7 +41,6 @@ class CreateView(generic.CreateView):
41
41
  class EditView(generic.EditView):
42
42
  success_message = _("Site '%(object)s' updated.")
43
43
  error_message = _("The site could not be saved due to errors.")
44
- delete_item_label = _("Delete site")
45
44
  context_object_name = "site"
46
45
 
47
46
 
@@ -1,5 +1,6 @@
1
1
  """Handles rendering of the list of actions in the footer of the snippet create/edit views."""
2
2
  from functools import lru_cache
3
+ from warnings import warn
3
4
 
4
5
  from django.conf import settings
5
6
  from django.contrib.admin.utils import quote
@@ -13,6 +14,7 @@ from wagtail import hooks
13
14
  from wagtail.admin.ui.components import Component
14
15
  from wagtail.models import DraftStateMixin, LockableMixin, WorkflowMixin
15
16
  from wagtail.snippets.permissions import get_permission_name
17
+ from wagtail.utils.deprecation import RemovedInWagtail70Warning
16
18
 
17
19
 
18
20
  class ActionMenuItem(Component):
@@ -197,7 +199,6 @@ class UnpublishMenuItem(ActionMenuItem):
197
199
  label = _("Unpublish")
198
200
  name = "action-unpublish"
199
201
  icon_name = "download"
200
- classname = "action-secondary"
201
202
 
202
203
  def is_shown(self, context):
203
204
  if context.get("locked_for_user"):
@@ -217,7 +218,14 @@ class DeleteMenuItem(ActionMenuItem):
217
218
  name = "action-delete"
218
219
  label = _("Delete")
219
220
  icon_name = "bin"
220
- classname = "action-secondary"
221
+
222
+ def __init__(self, order=None):
223
+ super().__init__(order)
224
+ warn(
225
+ "DeleteMenuItem is deprecated. "
226
+ "The delete option is now provided via EditView.get_header_more_buttons().",
227
+ RemovedInWagtail70Warning,
228
+ )
221
229
 
222
230
  def is_shown(self, context):
223
231
  delete_permission = get_permission_name("delete", context["model"])
@@ -258,7 +266,6 @@ def get_base_snippet_action_menu_items(model):
258
266
  """
259
267
  menu_items = [
260
268
  SaveMenuItem(order=0),
261
- DeleteMenuItem(order=10),
262
269
  ]
263
270
  if issubclass(model, DraftStateMixin):
264
271
  menu_items += [
@@ -341,6 +348,9 @@ class SnippetActionMenu:
341
348
  self.default_item = None
342
349
 
343
350
  def render_html(self):
351
+ if not self.default_item:
352
+ return ""
353
+
344
354
  rendered_menu_items = [
345
355
  menu_item.render_html(self.context) for menu_item in self.menu_items
346
356
  ]
@@ -358,7 +368,7 @@ class SnippetActionMenu:
358
368
 
359
369
  @cached_property
360
370
  def media(self):
361
- media = Media()
371
+ media = self.default_item.media if self.default_item else Media()
362
372
  for item in self.menu_items:
363
373
  media += item.media
364
374
  return media