wagtail 6.2.2__py3-none-any.whl → 6.3rc1__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 +8 -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.3rc1.dist-info}/METADATA +6 -6
  374. {wagtail-6.2.2.dist-info → wagtail-6.3rc1.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.3rc1.dist-info}/LICENSE +0 -0
  384. {wagtail-6.2.2.dist-info → wagtail-6.3rc1.dist-info}/WHEEL +0 -0
  385. {wagtail-6.2.2.dist-info → wagtail-6.3rc1.dist-info}/entry_points.txt +0 -0
  386. {wagtail-6.2.2.dist-info → wagtail-6.3rc1.dist-info}/top_level.txt +0 -0
@@ -1,104 +1,75 @@
1
- {% extends "wagtailadmin/base.html" %}
1
+ {% extends "wagtailadmin/generic/edit.html" %}
2
2
  {% load wagtailimages_tags wagtailadmin_tags i18n l10n %}
3
- {% block titletag %}{% blocktrans trimmed with title=image.title %}Editing image {{ title }}{% endblocktrans %}{% endblock %}
4
- {% block extra_css %}
5
- {{ block.super }}
6
-
7
- {{ form.media.css }}
8
- {% endblock %}
9
3
 
10
4
  {% block extra_js %}
11
5
  {{ block.super }}
12
6
 
13
- {{ form.media.js }}
14
-
15
7
  <!-- Focal point chooser -->
16
8
  <script src="{% versioned_static 'wagtailadmin/js/vendor/jquery.ba-throttle-debounce.min.js' %}"></script>
17
9
  <script src="{% versioned_static 'wagtailimages/js/vendor/jquery.Jcrop.min.js' %}"></script>
18
10
  <script src="{% versioned_static 'wagtailimages/js/focal-point-chooser.js' %}"></script>
19
11
  {% endblock %}
20
12
 
21
- {% block content %}
22
- {% trans "Editing" as editing_str %}
23
- {% include "wagtailadmin/shared/header.html" with title=editing_str subtitle=image.title icon="image" %}
24
- {% include "wagtailadmin/shared/non_field_errors.html" %}
13
+ {% block form_content %}
14
+ <div class="w-grid w-grid-cols-1 sm:w-grid-cols-2 w-gap-8">
15
+ <div>
16
+ <input type="hidden" value="{{ next }}" name="next">
17
+ {% for field in form %}
18
+ {% if field.name == 'file' %}
19
+ {% include "wagtailimages/images/_file_field.html" %}
20
+ {% elif field.is_hidden %}
21
+ {{ field }}
22
+ {% else %}
23
+ {% formattedfield field %}
24
+ {% endif %}
25
+ {% endfor %}
26
+ </div>
27
+ <div>
28
+ {% image image max-800x600 as rendition %}
25
29
 
26
- <form action="{% url 'wagtailimages:edit' image.id %}" method="POST" enctype="multipart/form-data" novalidate>
27
- {% csrf_token %}
28
- <input type="hidden" value="{{ next }}" name="next">
29
- <div class="row row-flush nice-padding">
30
- <div class="col6">
31
- {% for field in form %}
32
- {% if field.name == 'file' %}
33
- {% include "wagtailimages/images/_file_field.html" %}
34
- {% elif field.is_hidden %}
35
- {{ field }}
36
- {% else %}
37
- {% formattedfield field %}
38
- {% endif %}
39
- {% endfor %}
40
- <div class="w-hidden sm:w-block">
41
- <input type="submit" value="{% trans 'Save' %}" class="button" />
42
- {% if user_can_delete %}
43
- <a href="{% url 'wagtailimages:delete' image.id %}{% if next %}?next={{ next|urlencode }}{% endif %}" class="button no">{% trans "Delete image" %}</a>
44
- {% endif %}
45
- </div>
30
+ <div
31
+ class="focal-point-chooser"
32
+ style="max-width: {{ rendition.width|unlocalize }}px; max-height: {{ rendition.height|unlocalize }}px;"
33
+ data-focal-point-x="{{ image.focal_point_x|default_if_none:''|unlocalize }}"
34
+ data-focal-point-y="{{ image.focal_point_y|default_if_none:''|unlocalize }}"
35
+ data-focal-point-width="{{ image.focal_point_width|default_if_none:''|unlocalize }}"
36
+ data-focal-point-height="{{ image.focal_point_height|default_if_none:''|unlocalize }}"
37
+ data-focal-input-label="{% trans 'Image focal point' %}"
38
+ >
39
+ <img {{ rendition.attrs }} decoding="async" data-original-width="{{ image.width|unlocalize }}" data-original-height="{{ image.height|unlocalize }}" class="show-transparency">
40
+ <div class="current-focal-point-indicator{% if not image.has_focal_point %} hidden{% endif %}"></div>
46
41
  </div>
47
42
 
48
- <div class="col6">
49
- {% image image max-800x600 as rendition %}
50
-
51
- <div
52
- class="focal-point-chooser"
53
- style="max-width: {{ rendition.width|unlocalize }}px; max-height: {{ rendition.height|unlocalize }}px;"
54
- data-focal-point-x="{{ image.focal_point_x|default_if_none:''|unlocalize }}"
55
- data-focal-point-y="{{ image.focal_point_y|default_if_none:''|unlocalize }}"
56
- data-focal-point-width="{{ image.focal_point_width|default_if_none:''|unlocalize }}"
57
- data-focal-point-height="{{ image.focal_point_height|default_if_none:''|unlocalize }}"
58
- data-focal-input-label="{% trans 'Image focal point' %}"
59
- >
60
- <img {{ rendition.attrs }} decoding="async" data-original-width="{{ image.width|unlocalize }}" data-original-height="{{ image.height|unlocalize }}" class="show-transparency">
61
- <div class="current-focal-point-indicator{% if not image.has_focal_point %} hidden{% endif %}"></div>
62
- </div>
63
-
64
- {% if url_generator_enabled %}
65
- <a href="{% url 'wagtailimages:url_generator' image.id %}" class="button bicolor button--icon">{% icon name="link" wrapped=1 %}{% trans "URL Generator" %}</a>
66
- <hr />
67
- {% endif %}
43
+ {% if url_generator_url %}
44
+ <a href="{{ url_generator_url }}" class="button bicolor button--icon">{% icon name="link" wrapped=1 %}{% trans "URL Generator" %}</a>
45
+ <hr />
46
+ {% endif %}
68
47
 
69
- <div class="row">
70
- <div class="col8">
71
- <h2 class="w-label-3">{% trans "Focal point" %} <span class="w-font-normal">{% trans "(optional)" %}</span></h2>
72
- <p>{% trans "To define this image's most important region, drag a box over the image above." %} {% if image.has_focal_point %}({% trans "Current focal point shown" %}){% endif %}</p>
48
+ <div class="w-grid md:w-grid-cols-3 w-gap-2">
49
+ <div class="w-col-span-2">
50
+ <h2 class="w-label-3">{% trans "Focal point" %} <span class="w-font-normal">{% trans "(optional)" %}</span></h2>
51
+ <p>{% trans "To define this image's most important region, drag a box over the image above." %} {% if image.has_focal_point %}({% trans "Current focal point shown" %}){% endif %}</p>
73
52
 
74
- <button class="button button-secondary no remove-focal-point" type="button">{% trans "Remove focal area" %}</button>
75
- </div>
76
- <div class="col4">
77
- {% image image original as original_image %}
53
+ <button class="button button-secondary no remove-focal-point" type="button">{% trans "Remove focal area" %}</button>
54
+ </div>
55
+ <div class="w-col-span-1">
56
+ {% image image original as original_image %}
78
57
 
79
- <dl>
80
- <dt>{% trans "Max dimensions" %}</dt>
81
- <dd>{{ original_image.width }}x{{ original_image.height }}</dd>
82
- <dt>{% trans "Filesize" %}</dt>
83
- <dd>{% if filesize %}{{ filesize|filesizeformat }}{% else %}{% trans "File not found" %}{% endif %}</dd>
58
+ <dl>
59
+ <dt>{% trans "Max dimensions" %}</dt>
60
+ <dd>{{ original_image.width|unlocalize }}x{{ original_image.height|unlocalize }}</dd>
61
+ <dt>{% trans "Filesize" %}</dt>
62
+ <dd>{% if filesize %}{{ filesize|filesizeformat }}{% else %}{% trans "File not found" %}{% endif %}</dd>
84
63
 
85
- <dt>{% trans "Usage" %}</dt>
86
- <dd>
87
- <a href="{{ image.usage_url }}">{% blocktrans trimmed count usage_count=image.get_usage.count %}Used {{ usage_count }} time{% plural %}Used {{ usage_count }} times{% endblocktrans %}</a>
88
- </dd>
89
- </dl>
90
- </div>
64
+ <dt>{% trans "Usage" %}</dt>
65
+ <dd>
66
+ {% with image.get_usage.count as usage_count_val %}
67
+ <a href="{{ image.usage_url }}">{% blocktrans trimmed with usage_count=usage_count_val|intcomma count usage_count_val=usage_count_val %}Used {{ usage_count }} time{% plural %}Used {{ usage_count }} times{% endblocktrans %}</a>
68
+ {% endwith %}
69
+ </dd>
70
+ </dl>
91
71
  </div>
92
72
  </div>
93
73
  </div>
94
-
95
- <div class="row row-flush nice-padding sm:!w-hidden">
96
- <div class="col5">
97
- <input type="submit" value="{% trans 'Save' %}" class="button" />
98
- {% if user_can_delete %}
99
- <a href="{% url 'wagtailimages:delete' image.id %}{% if next %}?next={{ next }}{% endif %}" class="button no">{% trans "Delete image" %}</a>
100
- {% endif %}
101
- </div>
102
- </div>
103
- </form>
74
+ </div>
104
75
  {% endblock %}
@@ -3,9 +3,6 @@
3
3
 
4
4
  {% block extra_js %}
5
5
  {{ block.super }}
6
- <script>
7
- window.wagtailConfig.BULK_ACTION_ITEM_TYPE = 'IMAGE';
8
- </script>
9
6
  <script defer src="{% versioned_static 'wagtailadmin/js/bulk-actions.js' %}"></script>
10
7
  {% endblock %}
11
8
 
@@ -24,5 +21,5 @@
24
21
 
25
22
  {% block bulk_actions %}
26
23
  {% trans "Select all images in listing" as select_all_text %}
27
- {% include 'wagtailadmin/bulk_actions/footer.html' with select_all_obj_text=select_all_text app_label=model_opts.app_label model_name=model_opts.model_name objects=page_obj parent=current_collection.id %}
24
+ {% include 'wagtailadmin/bulk_actions/footer.html' with select_all_obj_text=select_all_text app_label=model_opts.app_label model_name=model_opts.model_name objects=page_obj parent=current_collection.id item_type="IMAGE" %}
28
25
  {% endblock %}
@@ -10,7 +10,7 @@
10
10
  {% endblock %}
11
11
 
12
12
  {% block main_content %}
13
- <div class="w-image-url-generator nice-padding" data-generator-url="{% url 'wagtailimages:generate_url' object.id '__filterspec__' %}">
13
+ <div class="w-image-url-generator w-mt-8" data-generator-url="{% url 'wagtailimages:generate_url' object.id '__filterspec__' %}">
14
14
  <form class="w-image-url-generator__form w-mb-5">
15
15
  {% include "wagtailadmin/shared/field.html" with field=form.filter_method %}
16
16
  {% field_row max_content=True %}
@@ -1,4 +1,4 @@
1
- {% extends "wagtailadmin/base.html" %}
1
+ {% extends "wagtailadmin/generic/base.html" %}
2
2
  {% load i18n %}
3
3
  {% load l10n %}
4
4
  {% load wagtailadmin_tags wagtailimages_tags %}
@@ -9,43 +9,48 @@
9
9
  {{ form_media.css }}
10
10
  {% endblock %}
11
11
 
12
- {% block content %}
13
- {% trans "Add images" as add_str %}
14
- {% include "wagtailadmin/shared/header.html" with title=add_str icon="image" %}
12
+ {% block main_content %}
13
+ <div class="drop-zone w-mt-8">
14
+ <p>{% trans "Drag and drop images into this area to upload immediately." %}</p>
15
+ <p>{{ help_text }}</p>
15
16
 
16
- <div class="nice-padding">
17
- <div class="drop-zone">
18
- <p>{% trans "Drag and drop images into this area to upload immediately." %}</p>
19
- <p>{{ help_text }}</p>
20
-
21
- <form action="{% url 'wagtailimages:add_multiple' %}" method="POST" enctype="multipart/form-data">
22
- <div class="replace-file-input">
23
- <button class="button bicolor button--icon">{% icon name="plus" wrapped=1 %}{% trans "Or choose from your computer" %}</button>
24
- <input id="fileupload" type="file" name="files[]" data-url="{% url 'wagtailimages:add_multiple' %}" multiple>
25
- </div>
26
- {% csrf_token %}
27
- {% if collections %}
28
- {% trans "Add to collection:" as label_text %}
29
- {% rawformattedfield label_text=label_text id_for_label="id_addimage_collection" classname="w-mx-auto w-mt-4 w-grid w-justify-center" %}
30
- <select id="id_addimage_collection" name="collection">
31
- {% for pk, display_name in collections.get_indented_choices %}
32
- <option value="{{ pk|unlocalize }}"{% if pk|unlocalize == selected_collection_id %} selected{% endif %} >
33
- {{ display_name }}
34
- </option>
35
- {% endfor %}
36
- </select>
37
- {% endrawformattedfield %}
38
- {% endif %}
39
- </form>
40
- </div>
41
-
42
- <div id="overall-progress" class="progress progress-secondary">
43
- <div class="bar" style="width: 0%;">0%</div>
44
- </div>
17
+ <form action="{% url 'wagtailimages:add_multiple' %}" method="POST" enctype="multipart/form-data">
18
+ <div class="replace-file-input">
19
+ <button class="button bicolor button--icon">{% icon name="plus" wrapped=1 %}{% trans "Or choose from your computer" %}</button>
20
+ <input
21
+ id="fileupload"
22
+ multiple
23
+ name="files[]"
24
+ type="file"
25
+ data-accept-file-types="/\.({{ allowed_extensions|join:'|' }})$/i"
26
+ data-max-file-size="{{ max_filesize|stringformat:'s'|default:'null' }}"
27
+ data-max-title-length="{{ max_title_length|stringformat:'s'|default:'null' }}"
28
+ data-messages='{"maxFileSize": "{{ error_max_file_size|escapejs }}", "acceptFileTypes": "{{ error_accepted_file_types|escapejs }}"}'
29
+ data-url="{% url 'wagtailimages:add_multiple' %}"
30
+ >
31
+ </div>
32
+ {% csrf_token %}
33
+ {% if collections %}
34
+ {% trans "Add to collection:" as label_text %}
35
+ {% rawformattedfield label_text=label_text id_for_label="id_addimage_collection" classname="w-mx-auto w-mt-4 w-grid w-justify-center" %}
36
+ <select id="id_addimage_collection" name="collection">
37
+ {% for pk, display_name in collections.get_indented_choices %}
38
+ <option value="{{ pk|unlocalize }}"{% if pk|unlocalize == selected_collection_id %} selected{% endif %} >
39
+ {{ display_name }}
40
+ </option>
41
+ {% endfor %}
42
+ </select>
43
+ {% endrawformattedfield %}
44
+ {% endif %}
45
+ </form>
46
+ </div>
45
47
 
46
- <ul id="upload-list" class="upload-list multiple"></ul>
48
+ <div id="overall-progress" class="progress progress-secondary">
49
+ <div class="bar" style="width: 0%;">0%</div>
47
50
  </div>
48
51
 
52
+ <ul id="upload-list" class="upload-list multiple"></ul>
53
+
49
54
  <template id="upload-list-item">
50
55
  <li class="row">
51
56
  <div class="left col3">
@@ -59,6 +64,7 @@
59
64
  </div>
60
65
  </div>
61
66
  <div class="right col9">
67
+ <p class="error-message">{% trans "Please provide an image description to comply with best practices for accessibility." %}</p>
62
68
  <p class="status-msg success">{% trans "Upload successful. Please update this image with a more appropriate title, if necessary. You may also delete the image completely if the upload wasn't required." %}</p>
63
69
  <p class="status-msg warning">
64
70
  {% trans "Upload successful. However, your new image seems to be a duplicate of this existing image. You may delete it if it wasn't required." %}
@@ -93,17 +99,4 @@
93
99
 
94
100
  <!-- Main script -->
95
101
  <script src="{% versioned_static 'wagtailimages/js/add-multiple.js' %}"></script>
96
-
97
- <script>
98
- window.fileupload_opts = {
99
- simple_upload_url: "{% url 'wagtailimages:add' %}",
100
- accepted_file_types: /\.({{ allowed_extensions|join:"|" }})$/i, //must be regex
101
- max_file_size: {{ max_filesize|stringformat:"s"|default:"null" }}, //numeric format
102
- max_title_length: {{ max_title_length|stringformat:"s"|default:"null" }}, //numeric format
103
- errormessages: {
104
- max_file_size: "{{ error_max_file_size|escapejs }}",
105
- accepted_file_types: "{{ error_accepted_file_types|escapejs }}"
106
- }
107
- }
108
- </script>
109
102
  {% endblock %}
@@ -0,0 +1,5 @@
1
+ {% load wagtailimages_tags %}
2
+
3
+ <figure>
4
+ {% image value fill-600x338 loading="lazy" %}
5
+ </figure>
@@ -3,5 +3,5 @@
3
3
 
4
4
  {% block chosen_icon %}
5
5
  {# Empty alt because the chosen item’s title is already displayed next to the image. #}
6
- <img class="chooser__image" data-chooser-image alt="" class="show-transparency" decoding="async" height="{{ preview.height|unlocalize }}" src="{{ preview.url }}" width="{{ preview.width|unlocalize }}">
6
+ <img class="chooser__image show-transparency" data-chooser-image alt="" decoding="async" height="{{ preview.height|unlocalize }}" src="{{ preview.url }}" width="{{ preview.width|unlocalize }}">
7
7
  {% endblock chosen_icon %}
@@ -16,6 +16,7 @@ from django.utils.encoding import force_str
16
16
  from django.utils.html import escape, escapejs
17
17
  from django.utils.http import RFC3986_SUBDELIMS, urlencode
18
18
  from django.utils.safestring import mark_safe
19
+ from django.utils.text import capfirst
19
20
  from willow.optimizers.base import OptimizerBase
20
21
  from willow.registry import registry
21
22
 
@@ -37,6 +38,7 @@ from wagtail.test.testapp.models import (
37
38
  VariousOnDeleteModel,
38
39
  )
39
40
  from wagtail.test.utils import WagtailTestUtils
41
+ from wagtail.test.utils.template_tests import AdminTemplateTestUtils
40
42
  from wagtail.test.utils.timestamps import local_datetime
41
43
 
42
44
  from .utils import Image, get_test_image_file, get_test_image_file_svg
@@ -83,12 +85,10 @@ class TestImageIndexView(WagtailTestUtils, TestCase):
83
85
  self.assertContains(response, "a cute puppy")
84
86
 
85
87
  def test_pagination(self):
86
- # page numbers in range should be accepted
87
- response = self.get({"p": 1})
88
- self.assertEqual(response.status_code, 200)
89
- # page numbers out of range should return 404
90
- response = self.get({"p": 9999})
91
- self.assertEqual(response.status_code, 404)
88
+ pages = ["0", "1", "-1", "9999", "Not a page"]
89
+ for page in pages:
90
+ response = self.get({"p": page})
91
+ self.assertEqual(response.status_code, 200)
92
92
 
93
93
  def test_pagination_preserves_other_params(self):
94
94
  root_collection = Collection.get_first_root_node()
@@ -539,7 +539,7 @@ class TestImageListingResultsView(WagtailTestUtils, TransactionTestCase):
539
539
  )
540
540
 
541
541
 
542
- class TestImageAddView(WagtailTestUtils, TestCase):
542
+ class TestImageAddView(AdminTemplateTestUtils, WagtailTestUtils, TestCase):
543
543
  def setUp(self):
544
544
  self.login()
545
545
 
@@ -567,6 +567,14 @@ class TestImageAddView(WagtailTestUtils, TestCase):
567
567
  # draftail should NOT be a standard JS include on this page
568
568
  self.assertNotContains(response, "wagtailadmin/js/draftail.js")
569
569
 
570
+ self.assertBreadcrumbsItemsRendered(
571
+ [
572
+ {"url": reverse("wagtailimages:index"), "label": "Images"},
573
+ {"url": "", "label": "New: Image"},
574
+ ],
575
+ response.content,
576
+ )
577
+
570
578
  def test_get_with_collections(self):
571
579
  root_collection = Collection.get_first_root_node()
572
580
  root_collection.add_child(name="Evil plans")
@@ -951,7 +959,7 @@ class TestImageAddViewWithLimitedCollectionPermissions(WagtailTestUtils, TestCas
951
959
  )
952
960
 
953
961
 
954
- class TestImageEditView(WagtailTestUtils, TestCase):
962
+ class TestImageEditView(AdminTemplateTestUtils, WagtailTestUtils, TestCase):
955
963
  def setUp(self):
956
964
  self.user = self.login()
957
965
 
@@ -989,6 +997,14 @@ class TestImageEditView(WagtailTestUtils, TestCase):
989
997
  # definitions are being respected)
990
998
  self.assertNotContains(response, "wagtailadmin/js/draftail.js")
991
999
 
1000
+ self.assertBreadcrumbsItemsRendered(
1001
+ [
1002
+ {"url": reverse("wagtailimages:index"), "label": "Images"},
1003
+ {"url": "", "label": "Test image"},
1004
+ ],
1005
+ response.content,
1006
+ )
1007
+
992
1008
  def test_simple_with_collection_nesting(self):
993
1009
  root_collection = Collection.get_first_root_node()
994
1010
  evil_plans = root_collection.add_child(name="Evil plans")
@@ -1605,6 +1621,10 @@ class TestImageChooserView(WagtailTestUtils, TestCase):
1605
1621
  # draftail should NOT be a standard JS include on this page
1606
1622
  self.assertNotIn("wagtailadmin/js/draftail.js", response_json["html"])
1607
1623
 
1624
+ # upload file field should have accept="image/*"
1625
+ soup = self.get_soup(response_json["html"])
1626
+ self.assertEqual(soup.select_one('input[type="file"]').get("accept"), "image/*")
1627
+
1608
1628
  def test_simple_with_collection_nesting(self):
1609
1629
  root_collection = Collection.get_first_root_node()
1610
1630
  evil_plans = root_collection.add_child(name="Evil plans")
@@ -1614,6 +1634,22 @@ class TestImageChooserView(WagtailTestUtils, TestCase):
1614
1634
  # "Eviler Plans" should be prefixed with &#x21b3 (↳) and 4 non-breaking spaces.
1615
1635
  self.assertContains(response, "&nbsp;&nbsp;&nbsp;&nbsp;&#x21b3 Eviler plans")
1616
1636
 
1637
+ @override_settings(
1638
+ WAGTAILIMAGES_EXTENSIONS=["gif", "jpg", "jpeg", "png", "webp", "avif", "heic"]
1639
+ )
1640
+ def test_upload_field_accepts_heic(self):
1641
+ response = self.get()
1642
+ self.assertEqual(response.status_code, 200)
1643
+ response_json = json.loads(response.content.decode())
1644
+ self.assertEqual(response_json["step"], "choose")
1645
+ self.assertTemplateUsed(response, "wagtailimages/chooser/chooser.html")
1646
+
1647
+ # upload file field should have an explicit 'accept' case for image/heic
1648
+ soup = self.get_soup(response_json["html"])
1649
+ self.assertEqual(
1650
+ soup.select_one('input[type="file"]').get("accept"), "image/*, image/heic"
1651
+ )
1652
+
1617
1653
  def test_choose_permissions(self):
1618
1654
  # Create group with access to admin and Chooser permission on one Collection, but not another.
1619
1655
  bakers_group = Group.objects.create(name="Bakers")
@@ -2362,7 +2398,7 @@ class TestImageChooserUploadViewWithLimitedPermissions(WagtailTestUtils, TestCas
2362
2398
  )
2363
2399
 
2364
2400
 
2365
- class TestMultipleImageUploader(WagtailTestUtils, TestCase):
2401
+ class TestMultipleImageUploader(AdminTemplateTestUtils, WagtailTestUtils, TestCase):
2366
2402
  """
2367
2403
  This tests the multiple image upload views located in wagtailimages/views/multiple.py
2368
2404
  """
@@ -2392,6 +2428,17 @@ class TestMultipleImageUploader(WagtailTestUtils, TestCase):
2392
2428
  # definitions are being respected)
2393
2429
  self.assertNotContains(response, "wagtailadmin/js/draftail.js")
2394
2430
 
2431
+ self.assertBreadcrumbsItemsRendered(
2432
+ [
2433
+ {
2434
+ "url": reverse("wagtailimages:index"),
2435
+ "label": capfirst(self.image._meta.verbose_name_plural),
2436
+ },
2437
+ {"url": "", "label": "Add images"},
2438
+ ],
2439
+ response.content,
2440
+ )
2441
+
2395
2442
  @override_settings(WAGTAILIMAGES_MAX_UPLOAD_SIZE=1000)
2396
2443
  def test_add_max_file_size_context_variables(self):
2397
2444
  response = self.client.get(reverse("wagtailimages:add_multiple"))
@@ -3370,7 +3417,7 @@ class TestMultipleImageUploaderWithCustomRequiredFields(WagtailTestUtils, TestCa
3370
3417
  self.assertTrue(response_json["success"])
3371
3418
 
3372
3419
 
3373
- class TestURLGeneratorView(WagtailTestUtils, TestCase):
3420
+ class TestURLGeneratorView(AdminTemplateTestUtils, WagtailTestUtils, TestCase):
3374
3421
  def setUp(self):
3375
3422
  # Create an image for running tests on
3376
3423
  self.image = Image.objects.create(
@@ -3393,6 +3440,19 @@ class TestURLGeneratorView(WagtailTestUtils, TestCase):
3393
3440
  # Check response
3394
3441
  self.assertEqual(response.status_code, 200)
3395
3442
  self.assertTemplateUsed(response, "wagtailimages/images/url_generator.html")
3443
+ self.assertTemplateUsed(response, "wagtailadmin/generic/base.html")
3444
+
3445
+ self.assertBreadcrumbsItemsRendered(
3446
+ [
3447
+ {"url": reverse("wagtailimages:index"), "label": "Images"},
3448
+ {
3449
+ "url": reverse("wagtailimages:edit", args=(self.image.id,)),
3450
+ "label": "Test image",
3451
+ },
3452
+ {"url": "", "label": "Generate URL", "sublabel": "Test image"},
3453
+ ],
3454
+ response.content,
3455
+ )
3396
3456
 
3397
3457
  def test_get_bad_permissions(self):
3398
3458
  """