wagtail 6.0.1__py3-none-any.whl → 6.1rc1__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 (512) hide show
  1. wagtail/__init__.py +1 -1
  2. wagtail/admin/checks.py +51 -0
  3. wagtail/admin/compare.py +1 -1
  4. wagtail/admin/filters.py +70 -1
  5. wagtail/admin/forms/account.py +1 -1
  6. wagtail/admin/forms/collections.py +15 -0
  7. wagtail/admin/forms/pages.py +49 -0
  8. wagtail/admin/locale/ca/LC_MESSAGES/django.mo +0 -0
  9. wagtail/admin/locale/ca/LC_MESSAGES/django.po +122 -0
  10. wagtail/admin/locale/de/LC_MESSAGES/django.mo +0 -0
  11. wagtail/admin/locale/de/LC_MESSAGES/django.po +5 -5
  12. wagtail/admin/locale/en/LC_MESSAGES/django.po +474 -385
  13. wagtail/admin/locale/en/LC_MESSAGES/djangojs.po +3 -3
  14. wagtail/admin/locale/es/LC_MESSAGES/django.mo +0 -0
  15. wagtail/admin/locale/es/LC_MESSAGES/django.po +6 -6
  16. wagtail/admin/locale/fr/LC_MESSAGES/django.mo +0 -0
  17. wagtail/admin/locale/fr/LC_MESSAGES/django.po +70 -3
  18. wagtail/admin/locale/he_IL/LC_MESSAGES/django.mo +0 -0
  19. wagtail/admin/locale/he_IL/LC_MESSAGES/django.po +2 -6
  20. wagtail/admin/locale/he_IL/LC_MESSAGES/djangojs.mo +0 -0
  21. wagtail/admin/locale/he_IL/LC_MESSAGES/djangojs.po +2 -2
  22. wagtail/admin/locale/hr_HR/LC_MESSAGES/django.mo +0 -0
  23. wagtail/admin/locale/hr_HR/LC_MESSAGES/django.po +4 -0
  24. wagtail/admin/locale/hu/LC_MESSAGES/django.mo +0 -0
  25. wagtail/admin/locale/hu/LC_MESSAGES/django.po +142 -2
  26. wagtail/admin/locale/it/LC_MESSAGES/django.mo +0 -0
  27. wagtail/admin/locale/it/LC_MESSAGES/django.po +80 -8
  28. wagtail/admin/locale/it/LC_MESSAGES/djangojs.mo +0 -0
  29. wagtail/admin/locale/it/LC_MESSAGES/djangojs.po +14 -2
  30. wagtail/admin/locale/lv/LC_MESSAGES/django.mo +0 -0
  31. wagtail/admin/locale/lv/LC_MESSAGES/django.po +154 -1
  32. wagtail/admin/locale/pt_PT/LC_MESSAGES/django.mo +0 -0
  33. wagtail/admin/locale/pt_PT/LC_MESSAGES/django.po +73 -2
  34. wagtail/admin/locale/ro/LC_MESSAGES/django.mo +0 -0
  35. wagtail/admin/locale/ro/LC_MESSAGES/django.po +3 -3
  36. wagtail/admin/locale/sl/LC_MESSAGES/django.mo +0 -0
  37. wagtail/admin/locale/sl/LC_MESSAGES/django.po +145 -2
  38. wagtail/admin/locale/sv/LC_MESSAGES/django.mo +0 -0
  39. wagtail/admin/locale/sv/LC_MESSAGES/django.po +77 -3
  40. wagtail/admin/locale/zh_Hant/LC_MESSAGES/django.mo +0 -0
  41. wagtail/admin/locale/zh_Hant/LC_MESSAGES/django.po +17 -1
  42. wagtail/admin/panels/comment_panel.py +1 -1
  43. wagtail/admin/panels/field_panel.py +1 -1
  44. wagtail/admin/rich_text/converters/editor_html.py +3 -1
  45. wagtail/admin/rich_text/editors/draftail/__init__.py +28 -2
  46. wagtail/admin/static/wagtailadmin/css/core.css +1 -1
  47. wagtail/admin/static/wagtailadmin/css/panels/draftail.css +1 -1
  48. wagtail/admin/static/wagtailadmin/images/favicon.ico +0 -0
  49. wagtail/admin/static/wagtailadmin/js/bulk-actions.js +1 -1
  50. wagtail/admin/static/wagtailadmin/js/chooser-modal.js +1 -1
  51. wagtail/admin/static/wagtailadmin/js/chooser-widget-telepath.js +1 -1
  52. wagtail/admin/static/wagtailadmin/js/chooser-widget.js +1 -1
  53. wagtail/admin/static/wagtailadmin/js/comments.js +1 -1
  54. wagtail/admin/static/wagtailadmin/js/core.js +1 -1
  55. wagtail/admin/static/wagtailadmin/js/core.js.LICENSE.txt +1 -1
  56. wagtail/admin/static/wagtailadmin/js/date-time-chooser.js +1 -1
  57. wagtail/admin/static/wagtailadmin/js/draftail.js +1 -1
  58. wagtail/admin/static/wagtailadmin/js/expanding-formset.js +1 -1
  59. wagtail/admin/static/wagtailadmin/js/filtered-select.js +1 -1
  60. wagtail/admin/static/wagtailadmin/js/modal-workflow.js +1 -1
  61. wagtail/admin/static/wagtailadmin/js/page-chooser-modal.js +1 -1
  62. wagtail/admin/static/wagtailadmin/js/page-chooser-telepath.js +1 -1
  63. wagtail/admin/static/wagtailadmin/js/page-chooser.js +1 -1
  64. wagtail/admin/static/wagtailadmin/js/preview-panel.js +1 -1
  65. wagtail/admin/static/wagtailadmin/js/privacy-switch.js +1 -1
  66. wagtail/admin/static/wagtailadmin/js/sidebar.js +1 -1
  67. wagtail/admin/static/wagtailadmin/js/task-chooser-modal.js +1 -1
  68. wagtail/admin/static/wagtailadmin/js/task-chooser.js +1 -1
  69. wagtail/admin/static/wagtailadmin/js/telepath/blocks.js +1 -1
  70. wagtail/admin/static/wagtailadmin/js/telepath/telepath.js +1 -1
  71. wagtail/admin/static/wagtailadmin/js/telepath/widgets.js +1 -1
  72. wagtail/admin/static/wagtailadmin/js/userbar.js +1 -1
  73. wagtail/admin/static/wagtailadmin/js/vendor.js +1 -1
  74. wagtail/admin/static/wagtailadmin/js/vendor.js.LICENSE.txt +4 -4
  75. wagtail/admin/static/wagtailadmin/js/wagtailadmin.js +1 -1
  76. wagtail/admin/static/wagtailadmin/js/workflow-action.js +1 -1
  77. wagtail/admin/staticfiles.py +1 -0
  78. wagtail/admin/templates/wagtailadmin/admin_base.html +1 -0
  79. wagtail/admin/templates/wagtailadmin/base.html +1 -0
  80. wagtail/admin/templates/wagtailadmin/collection_privacy/set_privacy.html +3 -1
  81. wagtail/admin/templates/wagtailadmin/collections/edit.html +0 -1
  82. wagtail/admin/templates/wagtailadmin/collections/index_results.html +10 -0
  83. wagtail/admin/templates/wagtailadmin/generic/base.html +1 -9
  84. wagtail/admin/templates/wagtailadmin/generic/form.html +4 -2
  85. wagtail/admin/templates/wagtailadmin/generic/history/action_cell.html +27 -0
  86. wagtail/admin/templates/wagtailadmin/generic/index_results.html +8 -0
  87. wagtail/admin/templates/wagtailadmin/home/workflow_objects_to_moderate.html +3 -4
  88. wagtail/admin/templates/wagtailadmin/icons/keyboard.svg +1 -0
  89. wagtail/admin/templates/wagtailadmin/page_privacy/set_privacy.html +3 -1
  90. wagtail/admin/templates/wagtailadmin/pages/_editor_js.html +0 -15
  91. wagtail/admin/templates/wagtailadmin/pages/action_menu/save_draft.html +3 -1
  92. wagtail/admin/templates/wagtailadmin/pages/choose_parent.html +17 -0
  93. wagtail/admin/templates/wagtailadmin/pages/explorable_index.html +8 -0
  94. wagtail/admin/templates/wagtailadmin/pages/history.html +1 -61
  95. wagtail/admin/templates/wagtailadmin/pages/index.html +1 -5
  96. wagtail/admin/templates/wagtailadmin/pages/listing/_locked_indicator.html +2 -2
  97. wagtail/admin/templates/wagtailadmin/pages/listing/_page_title_column_header.html +25 -27
  98. wagtail/admin/templates/wagtailadmin/pages/page_listing_header.html +2 -1
  99. wagtail/admin/templates/wagtailadmin/panels/multi_field_panel_child.html +1 -1
  100. wagtail/admin/templates/wagtailadmin/panels/publishing/schedule_publishing_panel.html +3 -1
  101. wagtail/admin/templates/wagtailadmin/panels/tabbed_interface.html +1 -1
  102. wagtail/admin/templates/wagtailadmin/shared/active_filters.html +2 -1
  103. wagtail/admin/templates/wagtailadmin/shared/breadcrumbs.html +8 -0
  104. wagtail/admin/templates/wagtailadmin/shared/forms/single_checkbox.html +1 -1
  105. wagtail/admin/templates/wagtailadmin/shared/headers/page_edit_header.html +1 -1
  106. wagtail/admin/templates/wagtailadmin/shared/headers/slim_header.html +21 -9
  107. wagtail/admin/templates/wagtailadmin/shared/human_readable_date.html +1 -1
  108. wagtail/admin/templates/wagtailadmin/shared/keyboard_shortcuts_dialog.html +29 -0
  109. wagtail/admin/templates/wagtailadmin/shared/side_panel_toggle.html +2 -1
  110. wagtail/admin/templates/wagtailadmin/skeleton.html +2 -1
  111. wagtail/admin/templates/wagtailadmin/tables/related_objects_cell.html +9 -0
  112. wagtail/admin/templates/wagtailadmin/tables/title_cell.html +9 -7
  113. wagtail/admin/templates/wagtailadmin/widgets/draftail_rich_text_area.html +1 -1
  114. wagtail/admin/templates/wagtailadmin/workflows/create.html +6 -23
  115. wagtail/admin/templates/wagtailadmin/workflows/create_task.html +6 -15
  116. wagtail/admin/templates/wagtailadmin/workflows/edit.html +6 -23
  117. wagtail/admin/templates/wagtailadmin/workflows/edit_task.html +6 -13
  118. wagtail/admin/templates/wagtailadmin/workflows/includes/task_usage_cell.html +4 -4
  119. wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_tasks_cell.html +18 -0
  120. wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_title_cell.html +7 -0
  121. wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_used_by_cell.html +25 -0
  122. wagtail/admin/templates/wagtailadmin/workflows/index.html +0 -99
  123. wagtail/admin/templates/wagtailadmin/workflows/index_results.html +10 -0
  124. wagtail/admin/templates/wagtailadmin/workflows/task_index.html +0 -30
  125. wagtail/admin/templates/wagtailadmin/workflows/task_index_results.html +10 -0
  126. wagtail/admin/templates/wagtailadmin/workflows/usage.html +1 -1
  127. wagtail/admin/templatetags/wagtailadmin_tags.py +116 -39
  128. wagtail/admin/tests/api/test_pages.py +26 -10
  129. wagtail/admin/tests/pages/test_create_page.py +10 -4
  130. wagtail/admin/tests/pages/test_custom_listing.py +37 -0
  131. wagtail/admin/tests/pages/test_edit_page.py +6 -6
  132. wagtail/admin/tests/pages/test_explorer_view.py +19 -18
  133. wagtail/admin/tests/pages/test_move_page.py +1 -1
  134. wagtail/admin/tests/pages/test_page_usage.py +50 -2
  135. wagtail/admin/tests/pages/test_parent_page_chooser_view.py +119 -0
  136. wagtail/admin/tests/pages/test_preview.py +18 -4
  137. wagtail/admin/tests/test_account_management.py +20 -1
  138. wagtail/admin/tests/test_audit_log.py +172 -5
  139. wagtail/admin/tests/test_checks.py +92 -0
  140. wagtail/admin/tests/test_collections_views.py +19 -5
  141. wagtail/admin/tests/test_compare.py +6 -6
  142. wagtail/admin/tests/test_dashboard.py +404 -0
  143. wagtail/admin/tests/test_dbwhitelister.py +4 -5
  144. wagtail/admin/tests/test_edit_handlers.py +2 -2
  145. wagtail/admin/tests/test_keyboard_shortcuts.py +84 -0
  146. wagtail/admin/tests/test_page_chooser.py +31 -18
  147. wagtail/admin/tests/test_privacy.py +36 -2
  148. wagtail/admin/tests/test_rich_text.py +168 -23
  149. wagtail/admin/tests/test_templatetags.py +411 -43
  150. wagtail/admin/tests/test_views.py +4 -2
  151. wagtail/admin/tests/test_workflows.py +531 -9
  152. wagtail/admin/tests/tests.py +3 -1
  153. wagtail/admin/tests/ui/test_tables.py +48 -1
  154. wagtail/admin/tests/viewsets/test_model_viewset.py +130 -23
  155. wagtail/admin/ui/side_panels.py +3 -1
  156. wagtail/admin/ui/tables/__init__.py +13 -1
  157. wagtail/admin/ui/tables/pages.py +17 -6
  158. wagtail/admin/urls/__init__.py +8 -3
  159. wagtail/admin/urls/pages.py +5 -0
  160. wagtail/admin/urls/workflows.py +10 -0
  161. wagtail/admin/views/chooser.py +20 -24
  162. wagtail/admin/views/collections.py +17 -1
  163. wagtail/admin/views/generic/base.py +34 -4
  164. wagtail/admin/views/generic/history.py +220 -51
  165. wagtail/admin/views/generic/mixins.py +7 -4
  166. wagtail/admin/views/generic/models.py +54 -47
  167. wagtail/admin/views/generic/multiple_upload.py +17 -8
  168. wagtail/admin/views/generic/usage.py +17 -11
  169. wagtail/admin/views/home.py +15 -12
  170. wagtail/admin/views/mixins.py +30 -0
  171. wagtail/admin/views/pages/choose_parent.py +73 -0
  172. wagtail/admin/views/pages/history.py +54 -66
  173. wagtail/admin/views/pages/listing.py +187 -106
  174. wagtail/admin/views/pages/usage.py +6 -1
  175. wagtail/admin/views/pages/utils.py +70 -1
  176. wagtail/admin/views/workflows.py +150 -21
  177. wagtail/admin/viewsets/model.py +2 -2
  178. wagtail/admin/viewsets/pages.py +77 -0
  179. wagtail/admin/wagtail_hooks.py +40 -2
  180. wagtail/admin/widgets/button.py +10 -10
  181. wagtail/api/v2/filters.py +1 -1
  182. wagtail/api/v2/tests/test_pages.py +1 -1
  183. wagtail/blocks/base.py +18 -9
  184. wagtail/blocks/field_block.py +9 -7
  185. wagtail/blocks/list_block.py +16 -6
  186. wagtail/blocks/static_block.py +3 -0
  187. wagtail/blocks/stream_block.py +58 -23
  188. wagtail/blocks/struct_block.py +15 -9
  189. wagtail/contrib/forms/locale/en/LC_MESSAGES/django.po +39 -47
  190. wagtail/contrib/forms/locale/he_IL/LC_MESSAGES/django.mo +0 -0
  191. wagtail/contrib/forms/locale/he_IL/LC_MESSAGES/django.po +2 -2
  192. wagtail/contrib/forms/models.py +5 -5
  193. wagtail/contrib/forms/templates/wagtailforms/list_submissions.html +44 -33
  194. wagtail/contrib/forms/templates/wagtailforms/submissions_index.html +2 -63
  195. wagtail/contrib/forms/tests/test_models.py +26 -0
  196. wagtail/contrib/forms/urls.py +6 -0
  197. wagtail/contrib/forms/views.py +52 -49
  198. wagtail/contrib/redirects/locale/ca/LC_MESSAGES/django.mo +0 -0
  199. wagtail/contrib/redirects/locale/ca/LC_MESSAGES/django.po +3 -3
  200. wagtail/contrib/redirects/locale/en/LC_MESSAGES/django.po +34 -42
  201. wagtail/contrib/redirects/locale/fr/LC_MESSAGES/django.po +2 -2
  202. wagtail/contrib/redirects/locale/he_IL/LC_MESSAGES/django.mo +0 -0
  203. wagtail/contrib/redirects/locale/he_IL/LC_MESSAGES/django.po +2 -2
  204. wagtail/contrib/redirects/signal_handlers.py +1 -1
  205. wagtail/contrib/redirects/templates/wagtailredirects/index.html +1 -36
  206. wagtail/contrib/redirects/templates/wagtailredirects/index_results.html +18 -0
  207. wagtail/contrib/redirects/templates/wagtailredirects/redirect_target_cell.html +8 -0
  208. wagtail/contrib/redirects/tests/test_import_command.py +1 -1
  209. wagtail/contrib/redirects/tests/test_redirects.py +79 -8
  210. wagtail/contrib/redirects/urls.py +2 -1
  211. wagtail/contrib/redirects/views.py +85 -55
  212. wagtail/contrib/search_promotions/admin_urls.py +2 -1
  213. wagtail/contrib/search_promotions/locale/en/LC_MESSAGES/django.po +41 -64
  214. wagtail/contrib/search_promotions/locale/fr/LC_MESSAGES/django.po +2 -2
  215. wagtail/contrib/search_promotions/locale/he_IL/LC_MESSAGES/django.mo +0 -0
  216. wagtail/contrib/search_promotions/locale/he_IL/LC_MESSAGES/django.po +2 -2
  217. wagtail/contrib/search_promotions/locale/hr_HR/LC_MESSAGES/django.mo +0 -0
  218. wagtail/contrib/search_promotions/locale/hr_HR/LC_MESSAGES/django.po +41 -2
  219. wagtail/contrib/search_promotions/locale/it/LC_MESSAGES/django.mo +0 -0
  220. wagtail/contrib/search_promotions/locale/it/LC_MESSAGES/django.po +9 -3
  221. wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/index.html +1 -16
  222. wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/index_results.html +11 -0
  223. wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/list.html +0 -51
  224. wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/results.html +3 -16
  225. wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/search_promotion_column.html +15 -0
  226. wagtail/contrib/search_promotions/tests.py +122 -9
  227. wagtail/contrib/search_promotions/views.py +66 -65
  228. wagtail/contrib/settings/locale/en/LC_MESSAGES/django.po +3 -3
  229. wagtail/contrib/settings/locale/he_IL/LC_MESSAGES/django.mo +0 -0
  230. wagtail/contrib/settings/locale/he_IL/LC_MESSAGES/django.po +2 -2
  231. wagtail/contrib/settings/locale/tr/LC_MESSAGES/django.mo +0 -0
  232. wagtail/contrib/settings/locale/tr/LC_MESSAGES/django.po +6 -2
  233. wagtail/contrib/settings/registry.py +10 -5
  234. wagtail/contrib/settings/tests/generic/test_admin.py +9 -0
  235. wagtail/contrib/settings/tests/site_specific/test_admin.py +10 -1
  236. wagtail/contrib/settings/tests/site_specific/test_model.py +3 -3
  237. wagtail/contrib/settings/tests/site_specific/test_templates.py +1 -1
  238. wagtail/contrib/settings/views.py +3 -1
  239. wagtail/contrib/simple_translation/locale/en/LC_MESSAGES/django.po +1 -1
  240. wagtail/contrib/simple_translation/tests/test_wagtail_hooks.py +2 -2
  241. wagtail/contrib/styleguide/locale/en/LC_MESSAGES/django.po +7 -7
  242. wagtail/contrib/styleguide/locale/he_IL/LC_MESSAGES/django.mo +0 -0
  243. wagtail/contrib/styleguide/locale/he_IL/LC_MESSAGES/django.po +2 -2
  244. wagtail/contrib/table_block/blocks.py +2 -2
  245. wagtail/contrib/table_block/locale/ca/LC_MESSAGES/django.mo +0 -0
  246. wagtail/contrib/table_block/locale/ca/LC_MESSAGES/django.po +27 -2
  247. wagtail/contrib/table_block/locale/en/LC_MESSAGES/django.po +1 -1
  248. wagtail/contrib/table_block/locale/hu/LC_MESSAGES/django.mo +0 -0
  249. wagtail/contrib/table_block/locale/hu/LC_MESSAGES/django.po +27 -2
  250. wagtail/contrib/table_block/locale/it/LC_MESSAGES/django.mo +0 -0
  251. wagtail/contrib/table_block/locale/it/LC_MESSAGES/django.po +27 -2
  252. wagtail/contrib/table_block/static/table_block/js/table.js +1 -1
  253. wagtail/contrib/table_block/tests.py +6 -0
  254. wagtail/contrib/typed_table_block/locale/ca/LC_MESSAGES/django.mo +0 -0
  255. wagtail/contrib/typed_table_block/locale/ca/LC_MESSAGES/django.po +12 -2
  256. wagtail/contrib/typed_table_block/locale/en/LC_MESSAGES/django.po +1 -1
  257. wagtail/contrib/typed_table_block/locale/hu/LC_MESSAGES/django.mo +0 -0
  258. wagtail/contrib/typed_table_block/locale/hu/LC_MESSAGES/django.po +12 -2
  259. wagtail/contrib/typed_table_block/locale/it/LC_MESSAGES/django.mo +0 -0
  260. wagtail/contrib/typed_table_block/locale/it/LC_MESSAGES/django.po +12 -2
  261. wagtail/contrib/typed_table_block/static/typed_table_block/js/typed_table_block.js +1 -1
  262. wagtail/coreutils.py +3 -2
  263. wagtail/documents/admin_urls.py +2 -2
  264. wagtail/documents/locale/en/LC_MESSAGES/django.po +22 -22
  265. wagtail/documents/locale/fr/LC_MESSAGES/django.po +2 -2
  266. wagtail/documents/locale/he_IL/LC_MESSAGES/django.mo +0 -0
  267. wagtail/documents/locale/he_IL/LC_MESSAGES/django.po +2 -2
  268. wagtail/documents/locale/hr_HR/LC_MESSAGES/django.mo +0 -0
  269. wagtail/documents/locale/hr_HR/LC_MESSAGES/django.po +19 -2
  270. wagtail/documents/locale/hu/LC_MESSAGES/django.mo +0 -0
  271. wagtail/documents/locale/hu/LC_MESSAGES/django.po +16 -2
  272. wagtail/documents/locale/it/LC_MESSAGES/django.mo +0 -0
  273. wagtail/documents/locale/it/LC_MESSAGES/django.po +19 -2
  274. wagtail/documents/migrations/0013_delete_uploadeddocument.py +16 -0
  275. wagtail/documents/models.py +1 -20
  276. wagtail/documents/rich_text/__init__.py +11 -7
  277. wagtail/documents/static/wagtaildocs/js/document-chooser-modal.js +1 -1
  278. wagtail/documents/static/wagtaildocs/js/document-chooser-telepath.js +1 -1
  279. wagtail/documents/static/wagtaildocs/js/document-chooser.js +1 -1
  280. wagtail/documents/templates/wagtaildocs/documents/index.html +0 -16
  281. wagtail/documents/tests/test_admin_views.py +155 -23
  282. wagtail/documents/tests/test_collection_privacy.py +55 -1
  283. wagtail/documents/tests/test_rich_text.py +14 -0
  284. wagtail/documents/views/documents.py +25 -22
  285. wagtail/documents/views/multiple.py +6 -7
  286. wagtail/documents/views/serve.py +16 -1
  287. wagtail/documents/wagtail_hooks.py +20 -15
  288. wagtail/embeds/blocks.py +5 -0
  289. wagtail/embeds/locale/en/LC_MESSAGES/django.po +2 -2
  290. wagtail/embeds/locale/fr/LC_MESSAGES/django.po +2 -2
  291. wagtail/embeds/locale/he_IL/LC_MESSAGES/django.mo +0 -0
  292. wagtail/embeds/locale/he_IL/LC_MESSAGES/django.po +2 -2
  293. wagtail/embeds/rich_text/__init__.py +1 -1
  294. wagtail/embeds/tests/test_rich_text.py +14 -0
  295. wagtail/embeds/wagtail_hooks.py +4 -14
  296. wagtail/fields.py +3 -48
  297. wagtail/images/admin_urls.py +2 -2
  298. wagtail/images/check_files/wagtail.jpg +0 -0
  299. wagtail/images/check_files/wagtail.png +0 -0
  300. wagtail/images/fields.py +2 -0
  301. wagtail/images/image_operations.py +1 -1
  302. wagtail/images/locale/ca/LC_MESSAGES/django.mo +0 -0
  303. wagtail/images/locale/ca/LC_MESSAGES/django.po +12 -0
  304. wagtail/images/locale/en/LC_MESSAGES/django.po +33 -45
  305. wagtail/images/locale/fr/LC_MESSAGES/django.po +2 -2
  306. wagtail/images/locale/he_IL/LC_MESSAGES/django.mo +0 -0
  307. wagtail/images/locale/he_IL/LC_MESSAGES/django.po +2 -2
  308. wagtail/images/locale/hu/LC_MESSAGES/django.mo +0 -0
  309. wagtail/images/locale/hu/LC_MESSAGES/django.po +28 -2
  310. wagtail/images/locale/it/LC_MESSAGES/django.mo +0 -0
  311. wagtail/images/locale/it/LC_MESSAGES/django.po +14 -2
  312. wagtail/images/locale/pt_PT/LC_MESSAGES/django.mo +0 -0
  313. wagtail/images/locale/pt_PT/LC_MESSAGES/django.po +4 -0
  314. wagtail/images/migrations/0026_delete_uploadedimage.py +16 -0
  315. wagtail/images/models.py +49 -43
  316. wagtail/images/rich_text/__init__.py +18 -8
  317. wagtail/images/static/wagtailimages/js/image-chooser-modal.js +1 -1
  318. wagtail/images/static/wagtailimages/js/image-chooser-telepath.js +1 -1
  319. wagtail/images/static/wagtailimages/js/image-chooser.js +1 -1
  320. wagtail/images/templates/wagtailimages/images/image_listing_header.html +6 -0
  321. wagtail/images/templates/wagtailimages/images/index.html +11 -51
  322. wagtail/images/tests/test_admin_views.py +119 -62
  323. wagtail/images/tests/test_image_operations.py +10 -0
  324. wagtail/images/tests/test_models.py +35 -33
  325. wagtail/images/tests/test_rich_text.py +14 -0
  326. wagtail/images/tests/utils.py +1 -1
  327. wagtail/images/views/images.py +35 -64
  328. wagtail/images/views/multiple.py +6 -7
  329. wagtail/images/wagtail_hooks.py +4 -14
  330. wagtail/locale/en/LC_MESSAGES/django.po +150 -136
  331. wagtail/locale/es/LC_MESSAGES/django.mo +0 -0
  332. wagtail/locale/es/LC_MESSAGES/django.po +3 -2
  333. wagtail/locale/fr/LC_MESSAGES/django.po +2 -2
  334. wagtail/locale/he_IL/LC_MESSAGES/django.mo +0 -0
  335. wagtail/locale/he_IL/LC_MESSAGES/django.po +2 -2
  336. wagtail/locale/it/LC_MESSAGES/django.mo +0 -0
  337. wagtail/locale/it/LC_MESSAGES/django.po +5 -5
  338. wagtail/locale/sl/LC_MESSAGES/django.mo +0 -0
  339. wagtail/locale/sl/LC_MESSAGES/django.po +27 -2
  340. wagtail/locales/locale/ar/LC_MESSAGES/django.po +1 -1
  341. wagtail/locales/locale/be/LC_MESSAGES/django.po +1 -1
  342. wagtail/locales/locale/bg/LC_MESSAGES/django.po +1 -1
  343. wagtail/locales/locale/ca/LC_MESSAGES/django.po +1 -1
  344. wagtail/locales/locale/cs/LC_MESSAGES/django.po +1 -1
  345. wagtail/locales/locale/cy/LC_MESSAGES/django.po +1 -1
  346. wagtail/locales/locale/da/LC_MESSAGES/django.po +1 -1
  347. wagtail/locales/locale/de/LC_MESSAGES/django.po +1 -1
  348. wagtail/locales/locale/el/LC_MESSAGES/django.po +1 -1
  349. wagtail/locales/locale/en/LC_MESSAGES/django.po +1 -1
  350. wagtail/locales/locale/es/LC_MESSAGES/django.po +1 -1
  351. wagtail/locales/locale/et/LC_MESSAGES/django.po +2 -2
  352. wagtail/locales/locale/fa/LC_MESSAGES/django.po +1 -1
  353. wagtail/locales/locale/fi/LC_MESSAGES/django.po +1 -1
  354. wagtail/locales/locale/fr/LC_MESSAGES/django.po +1 -1
  355. wagtail/locales/locale/gl/LC_MESSAGES/django.po +1 -1
  356. wagtail/locales/locale/he_IL/LC_MESSAGES/django.mo +0 -0
  357. wagtail/locales/locale/he_IL/LC_MESSAGES/django.po +3 -3
  358. wagtail/locales/locale/hr_HR/LC_MESSAGES/django.po +1 -1
  359. wagtail/locales/locale/hu/LC_MESSAGES/django.po +1 -1
  360. wagtail/locales/locale/id_ID/LC_MESSAGES/django.po +1 -1
  361. wagtail/locales/locale/is_IS/LC_MESSAGES/django.po +1 -1
  362. wagtail/locales/locale/it/LC_MESSAGES/django.po +1 -1
  363. wagtail/locales/locale/ja/LC_MESSAGES/django.po +1 -1
  364. wagtail/locales/locale/ko/LC_MESSAGES/django.po +1 -1
  365. wagtail/locales/locale/lt/LC_MESSAGES/django.po +1 -1
  366. wagtail/locales/locale/lv/LC_MESSAGES/django.po +1 -1
  367. wagtail/locales/locale/mi/LC_MESSAGES/django.po +1 -1
  368. wagtail/locales/locale/mn/LC_MESSAGES/django.po +1 -1
  369. wagtail/locales/locale/my/LC_MESSAGES/django.po +1 -1
  370. wagtail/locales/locale/nb/LC_MESSAGES/django.po +1 -1
  371. wagtail/locales/locale/nl/LC_MESSAGES/django.po +1 -1
  372. wagtail/locales/locale/pl/LC_MESSAGES/django.po +1 -1
  373. wagtail/locales/locale/pt_BR/LC_MESSAGES/django.po +1 -1
  374. wagtail/locales/locale/pt_PT/LC_MESSAGES/django.po +1 -1
  375. wagtail/locales/locale/ro/LC_MESSAGES/django.po +1 -1
  376. wagtail/locales/locale/ru/LC_MESSAGES/django.po +1 -1
  377. wagtail/locales/locale/sk_SK/LC_MESSAGES/django.po +1 -1
  378. wagtail/locales/locale/sl/LC_MESSAGES/django.po +1 -1
  379. wagtail/locales/locale/sv/LC_MESSAGES/django.po +1 -1
  380. wagtail/locales/locale/tet/LC_MESSAGES/django.po +1 -1
  381. wagtail/locales/locale/th/LC_MESSAGES/django.po +1 -1
  382. wagtail/locales/locale/tr/LC_MESSAGES/django.po +1 -1
  383. wagtail/locales/locale/tr_TR/LC_MESSAGES/django.po +1 -1
  384. wagtail/locales/locale/uk/LC_MESSAGES/django.po +1 -1
  385. wagtail/locales/locale/vi/LC_MESSAGES/django.po +1 -1
  386. wagtail/locales/locale/zh/LC_MESSAGES/django.po +1 -1
  387. wagtail/locales/locale/zh_Hans/LC_MESSAGES/django.po +1 -1
  388. wagtail/locales/locale/zh_Hant/LC_MESSAGES/django.po +1 -1
  389. wagtail/locales/tests.py +18 -3
  390. wagtail/locales/views.py +0 -1
  391. wagtail/management/commands/rebuild_references_index.py +3 -1
  392. wagtail/migrations/0092_alter_collectionviewrestriction_password_and_more.py +33 -0
  393. wagtail/migrations/0093_uploadedfile.py +53 -0
  394. wagtail/models/__init__.py +147 -32
  395. wagtail/models/i18n.py +1 -1
  396. wagtail/models/{collections.py → media.py} +33 -2
  397. wagtail/models/reference_index.py +1 -1
  398. wagtail/models/view_restrictions.py +10 -3
  399. wagtail/project_template/project_name/settings/base.py +6 -0
  400. wagtail/project_template/requirements.txt +1 -1
  401. wagtail/rich_text/__init__.py +25 -8
  402. wagtail/rich_text/pages.py +19 -8
  403. wagtail/rich_text/rewriters.py +140 -68
  404. wagtail/search/backends/database/mysql/mysql.py +3 -3
  405. wagtail/search/backends/database/postgres/postgres.py +3 -3
  406. wagtail/search/backends/database/sqlite/sqlite.py +2 -2
  407. wagtail/search/backends/elasticsearch7.py +4 -0
  408. wagtail/search/locale/en/LC_MESSAGES/django.po +3 -3
  409. wagtail/search/tests/test_postgres_backend.py +50 -0
  410. wagtail/sites/locale/en/LC_MESSAGES/django.po +8 -8
  411. wagtail/sites/locale/he_IL/LC_MESSAGES/django.mo +0 -0
  412. wagtail/sites/locale/he_IL/LC_MESSAGES/django.po +2 -2
  413. wagtail/sites/locale/ro/LC_MESSAGES/django.mo +0 -0
  414. wagtail/sites/locale/ro/LC_MESSAGES/django.po +3 -2
  415. wagtail/sites/tests.py +35 -9
  416. wagtail/sites/views.py +3 -1
  417. wagtail/snippets/locale/de/LC_MESSAGES/django.mo +0 -0
  418. wagtail/snippets/locale/de/LC_MESSAGES/django.po +7 -8
  419. wagtail/snippets/locale/en/LC_MESSAGES/django.po +16 -56
  420. wagtail/snippets/locale/fr/LC_MESSAGES/django.po +2 -2
  421. wagtail/snippets/locale/he_IL/LC_MESSAGES/django.mo +0 -0
  422. wagtail/snippets/locale/he_IL/LC_MESSAGES/django.po +2 -2
  423. wagtail/snippets/locale/hr_HR/LC_MESSAGES/django.mo +0 -0
  424. wagtail/snippets/locale/hr_HR/LC_MESSAGES/django.po +6 -2
  425. wagtail/snippets/locale/lv/LC_MESSAGES/django.mo +0 -0
  426. wagtail/snippets/locale/lv/LC_MESSAGES/django.po +12 -0
  427. wagtail/snippets/locale/zh_Hant/LC_MESSAGES/django.mo +0 -0
  428. wagtail/snippets/locale/zh_Hant/LC_MESSAGES/django.po +4 -0
  429. wagtail/snippets/static/wagtailsnippets/js/snippet-chooser-telepath.js +1 -1
  430. wagtail/snippets/static/wagtailsnippets/js/snippet-chooser.js +1 -1
  431. wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/publish.html +3 -1
  432. wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/save.html +3 -1
  433. wagtail/snippets/templates/wagtailsnippets/snippets/create.html +2 -3
  434. wagtail/snippets/templates/wagtailsnippets/snippets/edit.html +2 -3
  435. wagtail/snippets/tests/test_preview.py +13 -2
  436. wagtail/snippets/tests/test_snippets.py +41 -16
  437. wagtail/snippets/tests/test_viewset.py +95 -18
  438. wagtail/snippets/tests/test_workflows.py +12 -0
  439. wagtail/snippets/views/snippets.py +1 -40
  440. wagtail/templatetags/wagtailcore_tags.py +1 -1
  441. wagtail/test/demosite/models.py +1 -1
  442. wagtail/test/middleware.py +14 -1
  443. wagtail/test/testapp/fixtures/test.json +20 -0
  444. wagtail/test/testapp/migrations/0001_squashed_0073_revisablechildmodel_secret_text.py +8 -8
  445. wagtail/test/testapp/migrations/0023_snippetchoosermodel_full_featured.py +1 -0
  446. wagtail/test/testapp/migrations/0034_custompermissionmodel.py +44 -0
  447. wagtail/test/testapp/migrations/0035_modelwithcustommanager.py +30 -0
  448. wagtail/test/testapp/migrations/0036_complexdefaultstreampage.py +28 -0
  449. wagtail/test/testapp/models.py +79 -2
  450. wagtail/test/testapp/templates/tests/custom_docs_password_required.html +10 -0
  451. wagtail/test/testapp/templates/tests/custom_page_password_required.html +10 -0
  452. wagtail/test/testapp/views.py +24 -2
  453. wagtail/test/testapp/wagtail_hooks.py +19 -0
  454. wagtail/test/utils/wagtail_tests.py +2 -2
  455. wagtail/tests/test_blocks.py +262 -1
  456. wagtail/tests/test_migrations.py +1 -1
  457. wagtail/tests/test_page_model.py +77 -0
  458. wagtail/tests/test_page_privacy.py +18 -1
  459. wagtail/tests/test_rich_text.py +95 -5
  460. wagtail/tests/test_streamfield.py +43 -0
  461. wagtail/tests/test_utils.py +8 -2
  462. wagtail/tests/test_views.py +52 -1
  463. wagtail/tests/test_whitelist.py +7 -7
  464. wagtail/users/forms.py +3 -1
  465. wagtail/users/locale/en/LC_MESSAGES/django.po +124 -96
  466. wagtail/users/locale/fr/LC_MESSAGES/django.po +2 -2
  467. wagtail/users/locale/he_IL/LC_MESSAGES/django.mo +0 -0
  468. wagtail/users/locale/he_IL/LC_MESSAGES/django.po +2 -2
  469. wagtail/users/locale/hr_HR/LC_MESSAGES/django.mo +0 -0
  470. wagtail/users/locale/hr_HR/LC_MESSAGES/django.po +13 -2
  471. wagtail/users/migrations/0013_userprofile_density.py +23 -0
  472. wagtail/users/models.py +14 -3
  473. wagtail/users/templates/wagtailusers/groups/create.html +1 -7
  474. wagtail/users/templates/wagtailusers/groups/edit.html +1 -13
  475. wagtail/users/templates/wagtailusers/groups/includes/formatted_permissions.html +46 -2
  476. wagtail/users/templates/wagtailusers/groups/includes/group_form_js.html +0 -3
  477. wagtail/users/templates/wagtailusers/users/create.html +1 -14
  478. wagtail/users/templates/wagtailusers/users/edit.html +1 -14
  479. wagtail/users/templates/wagtailusers/users/index.html +2 -5
  480. wagtail/users/templates/wagtailusers/users/index_results.html +3 -13
  481. wagtail/users/templates/wagtailusers/users/user_cell.html +9 -0
  482. wagtail/users/templatetags/wagtailusers_tags.py +107 -20
  483. wagtail/users/tests/test_admin_views.py +669 -90
  484. wagtail/users/views/groups.py +58 -61
  485. wagtail/users/views/users.py +211 -92
  486. wagtail/users/wagtail_hooks.py +6 -38
  487. wagtail/users/widgets.py +3 -5
  488. wagtail/utils/text.py +1 -1
  489. wagtail/views.py +5 -9
  490. wagtail/whitelist.py +1 -1
  491. {wagtail-6.0.1.dist-info → wagtail-6.1rc1.dist-info}/METADATA +5 -6
  492. {wagtail-6.0.1.dist-info → wagtail-6.1rc1.dist-info}/RECORD +496 -477
  493. wagtail/admin/static/wagtailadmin/js/page-editor.js +0 -1
  494. wagtail/admin/static/wagtailadmin/js/vendor/mousetrap.min.js +0 -1
  495. wagtail/admin/static/wagtailadmin/js/vendor/urlify.js +0 -1
  496. wagtail/admin/static/wagtailadmin/js/vendor/xregexp.min.js +0 -1
  497. wagtail/admin/templates/wagtailadmin/collections/index.html +0 -34
  498. wagtail/admin/templates/wagtailadmin/pages/revisions/_actions.html +0 -22
  499. wagtail/admin/templates/wagtailadmin/shared/page_breadcrumbs.html +0 -55
  500. wagtail/admin/tests/pages/test_dashboard.py +0 -172
  501. wagtail/contrib/redirects/templates/wagtailredirects/results.html +0 -23
  502. wagtail/documents/templates/wagtaildocs/documents/list.html +0 -2
  503. wagtail/search/tests/test_postgres_stemming.py +0 -40
  504. wagtail/sites/templates/wagtailsites/create.html +0 -7
  505. wagtail/sites/templates/wagtailsites/edit.html +0 -7
  506. wagtail/snippets/templates/wagtailsnippets/snippets/revisions/_actions.html +0 -36
  507. wagtail/users/templates/wagtailusers/users/list.html +0 -62
  508. wagtail/users/urls/users.py +0 -12
  509. {wagtail-6.0.1.dist-info → wagtail-6.1rc1.dist-info}/LICENSE +0 -0
  510. {wagtail-6.0.1.dist-info → wagtail-6.1rc1.dist-info}/WHEEL +0 -0
  511. {wagtail-6.0.1.dist-info → wagtail-6.1rc1.dist-info}/entry_points.txt +0 -0
  512. {wagtail-6.0.1.dist-info → wagtail-6.1rc1.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,7 @@
1
1
  import json
2
- from datetime import timedelta
2
+ import unittest
3
+ from datetime import datetime, timedelta
4
+ from datetime import timezone as dt_timezone
3
5
  from unittest import mock
4
6
 
5
7
  from django.conf import settings
@@ -19,9 +21,11 @@ from wagtail.admin.templatetags.wagtailadmin_tags import (
19
21
  timesince_simple,
20
22
  )
21
23
  from wagtail.admin.templatetags.wagtailadmin_tags import locales as locales_tag
24
+ from wagtail.coreutils import get_dummy_request
22
25
  from wagtail.images.tests.utils import get_test_image_file
23
- from wagtail.models import Locale
26
+ from wagtail.models import Locale, Page
24
27
  from wagtail.test.utils import WagtailTestUtils
28
+ from wagtail.test.utils.template_tests import AdminTemplateTestUtils
25
29
  from wagtail.users.models import UserProfile
26
30
 
27
31
 
@@ -115,44 +119,148 @@ class TestVersionedStatic(SimpleTestCase):
115
119
  self.assertEqual(result, "http://example.org/static/wagtailadmin/js/core.js")
116
120
 
117
121
 
118
- @freeze_time("2020-07-01 12:00:00")
119
122
  class TestTimesinceTags(SimpleTestCase):
123
+ # timezone matches TIME_ZONE = "Asia/Tokyo" in tests/settings.py
124
+ @freeze_time("2020-07-01 12:00:00+09:00")
120
125
  def test_timesince_simple(self):
121
- now = timezone.now()
126
+ now = timezone.make_aware(
127
+ datetime(2020, 7, 1, 12, 0, 0)
128
+ ) # aware date in Asia/Tokyo
129
+ ts = timesince_simple(now)
130
+ self.assertEqual(ts, "just now")
131
+
132
+ now = timezone.make_aware(
133
+ datetime(2020, 7, 1, 3, 0, 0), timezone=dt_timezone.utc
134
+ ) # aware date in UTC
122
135
  ts = timesince_simple(now)
123
136
  self.assertEqual(ts, "just now")
124
137
 
125
- ts = timesince_simple(now - timedelta(hours=1, minutes=10))
138
+ seventy_minutes_ago = timezone.make_aware(datetime(2020, 7, 1, 10, 50, 0))
139
+ ts = timesince_simple(seventy_minutes_ago)
126
140
  self.assertEqual(ts, "1\xa0hour ago")
127
141
 
128
- ts = timesince_simple(now - timedelta(weeks=2, hours=1, minutes=10))
142
+ two_weeks_ago = timezone.make_aware(datetime(2020, 6, 17, 10, 50, 0))
143
+ ts = timesince_simple(two_weeks_ago)
129
144
  self.assertEqual(ts, "2\xa0weeks ago")
130
145
 
146
+ @unittest.skipIf(not settings.USE_TZ, "Test assumes timezone support is active")
147
+ @freeze_time("2020-07-01 06:00:00+09:00")
131
148
  def test_timesince_last_update_today_shows_time(self):
132
- dt = timezone.now() - timedelta(hours=1)
133
- formatted_time = dt.astimezone(timezone.get_current_timezone()).strftime(
134
- "%H:%M"
149
+ one_hour_ago = timezone.make_aware(
150
+ datetime(2020, 7, 1, 5, 0, 0)
151
+ ) # aware date in Asia/Tokyo
152
+ timesince = timesince_last_update(one_hour_ago)
153
+ self.assertEqual(timesince, "05:00")
154
+
155
+ # Check prefix output
156
+ timesince = timesince_last_update(one_hour_ago, show_time_prefix=True)
157
+ self.assertEqual(timesince, "at 05:00")
158
+
159
+ # Check user output
160
+ timesince = timesince_last_update(one_hour_ago, user_display_name="Gary")
161
+ self.assertEqual(timesince, "05:00 by Gary")
162
+
163
+ # Check user and prefix output
164
+ timesince = timesince_last_update(
165
+ one_hour_ago, show_time_prefix=True, user_display_name="Gary"
135
166
  )
167
+ self.assertEqual(timesince, "at 05:00 by Gary")
136
168
 
137
- timesince = timesince_last_update(dt)
138
- self.assertEqual(timesince, formatted_time)
169
+ one_hour_ago = timezone.make_aware(
170
+ datetime(2020, 6, 30, 20, 0, 0), timezone=dt_timezone.utc
171
+ ) # aware date in UTC
172
+ timesince = timesince_last_update(one_hour_ago)
173
+ self.assertEqual(timesince, "05:00")
174
+
175
+ @unittest.skipIf(settings.USE_TZ, "Test assumes timezone support is disabled")
176
+ @freeze_time("2020-07-01 06:00:00")
177
+ def test_timesince_last_update_today_shows_time_without_tz(self):
178
+ one_hour_ago = datetime(2020, 7, 1, 5, 0, 0)
179
+ timesince = timesince_last_update(one_hour_ago)
180
+ self.assertEqual(timesince, "05:00")
139
181
 
140
182
  # Check prefix output
141
- timesince = timesince_last_update(dt, show_time_prefix=True)
142
- self.assertEqual(timesince, f"at {formatted_time}")
183
+ timesince = timesince_last_update(one_hour_ago, show_time_prefix=True)
184
+ self.assertEqual(timesince, "at 05:00")
143
185
 
144
186
  # Check user output
145
- timesince = timesince_last_update(dt, user_display_name="Gary")
146
- self.assertEqual(timesince, f"{formatted_time} by Gary")
187
+ timesince = timesince_last_update(one_hour_ago, user_display_name="Gary")
188
+ self.assertEqual(timesince, "05:00 by Gary")
147
189
 
148
190
  # Check user and prefix output
149
191
  timesince = timesince_last_update(
150
- dt, show_time_prefix=True, user_display_name="Gary"
192
+ one_hour_ago, show_time_prefix=True, user_display_name="Gary"
151
193
  )
152
- self.assertEqual(timesince, f"at {formatted_time} by Gary")
194
+ self.assertEqual(timesince, "at 05:00 by Gary")
153
195
 
196
+ @unittest.skipIf(not settings.USE_TZ, "Test assumes timezone support is active")
197
+ @freeze_time("2020-07-01 06:00:00+09:00")
198
+ def test_timesince_last_update_before_midnight_shows_timeago(self):
199
+ """
200
+ If the last update was yesterday in local time, we show "x hours ago" even if it was less
201
+ than 24 hours ago (and even if it matches today's date in UTC)
202
+ """
203
+ eight_hours_ago = timezone.make_aware(
204
+ datetime(2020, 6, 30, 21, 50, 0)
205
+ ) # aware date in Asia/Tokyo
206
+ timesince = timesince_last_update(eight_hours_ago)
207
+ self.assertEqual(timesince, "8\xa0hours ago")
208
+
209
+ @unittest.skipIf(settings.USE_TZ, "Test assumes timezone support is disabled")
210
+ @freeze_time("2020-07-01 06:00:00")
211
+ def test_timesince_last_update_before_midnight_shows_timeago_without_tz(self):
212
+ """
213
+ If the last update was yesterday in local time, we show "x hours ago" even if it was less
214
+ than 24 hours ago
215
+ """
216
+ eight_hours_ago = datetime(2020, 6, 30, 21, 50, 0)
217
+ timesince = timesince_last_update(eight_hours_ago)
218
+ self.assertEqual(timesince, "8\xa0hours ago")
219
+
220
+ @unittest.skipIf(not settings.USE_TZ, "Test assumes timezone support is active")
221
+ @freeze_time("2020-07-01 12:00:00+09:00")
154
222
  def test_timesince_last_update_before_today_shows_timeago(self):
155
- dt = timezone.now() - timedelta(weeks=1, days=2)
223
+ dt = timezone.make_aware(datetime(2020, 6, 22, 12, 0, 0))
224
+
225
+ # 1) use_shorthand=False
226
+
227
+ timesince = timesince_last_update(dt, use_shorthand=False)
228
+ self.assertEqual(timesince, "1\xa0week, 2\xa0days ago")
229
+ # The prefix is not used, if the date is older than the current day.
230
+ self.assertEqual(
231
+ timesince_last_update(dt, use_shorthand=False, show_time_prefix=True),
232
+ timesince,
233
+ )
234
+
235
+ # Check user output
236
+ timesince = timesince_last_update(
237
+ dt, use_shorthand=False, user_display_name="Gary"
238
+ )
239
+ self.assertEqual(timesince, "1\xa0week, 2\xa0days ago by Gary")
240
+ self.assertEqual(
241
+ timesince_last_update(
242
+ dt, use_shorthand=False, user_display_name="Gary", show_time_prefix=True
243
+ ),
244
+ timesince,
245
+ )
246
+
247
+ # 2) use_shorthand=True
248
+
249
+ timesince = timesince_last_update(dt)
250
+ self.assertEqual(timesince, "1\xa0week ago")
251
+ self.assertEqual(timesince_last_update(dt, show_time_prefix=True), timesince)
252
+
253
+ timesince = timesince_last_update(dt, user_display_name="Gary")
254
+ self.assertEqual(timesince, "1\xa0week ago by Gary")
255
+ self.assertEqual(
256
+ timesince_last_update(dt, user_display_name="Gary", show_time_prefix=True),
257
+ timesince,
258
+ )
259
+
260
+ @unittest.skipIf(settings.USE_TZ, "Test assumes timezone support is disabled")
261
+ @freeze_time("2020-07-01 12:00:00")
262
+ def test_timesince_last_update_before_today_shows_timeago_without_tz(self):
263
+ dt = timezone.make_aware(datetime(2020, 6, 22, 12, 0, 0))
156
264
 
157
265
  # 1) use_shorthand=False
158
266
 
@@ -189,6 +297,8 @@ class TestTimesinceTags(SimpleTestCase):
189
297
  timesince,
190
298
  )
191
299
 
300
+ @override_settings(USE_TZ=False)
301
+ @freeze_time("2020-07-01 12:00:00")
192
302
  def test_human_readable_date(self):
193
303
  now = timezone.now()
194
304
  template = """
@@ -204,7 +314,28 @@ class TestTimesinceTags(SimpleTestCase):
204
314
  )
205
315
  self.assertIn("1\xa0hour ago", html)
206
316
  self.assertIn('data-w-tooltip-placement-value="top"', html)
317
+ self.assertIn('data-w-tooltip-content-value="July 1, 2020, 10:50 a.m."', html)
207
318
 
319
+ @override_settings(USE_TZ=False)
320
+ @freeze_time("2020-07-01 12:00:00")
321
+ def test_human_readable_date_with_date_object(self):
322
+ today = timezone.now().date()
323
+ template = """
324
+ {% load wagtailadmin_tags %}
325
+ {% human_readable_date date %}
326
+ """
327
+
328
+ html = Template(template).render(Context({"date": today}))
329
+ self.assertIn("12\xa0hours ago", html)
330
+
331
+ html = Template(template).render(
332
+ Context({"date": today - timedelta(days=1, hours=1)})
333
+ )
334
+ self.assertIn("1\xa0day ago", html)
335
+ self.assertIn('data-w-tooltip-placement-value="top"', html)
336
+ self.assertIn('data-w-tooltip-content-value="June 30, 2020"', html)
337
+
338
+ @freeze_time("2020-07-01 12:00:00")
208
339
  def test_human_readable_date_with_args(self):
209
340
  now = timezone.now()
210
341
  template = """
@@ -459,6 +590,28 @@ class ClassnamesTagTest(SimpleTestCase):
459
590
 
460
591
  self.assertEqual(expected.strip(), actual.strip())
461
592
 
593
+ def test_with_nested_lists(self):
594
+ context = Context(
595
+ {
596
+ "nested": ["button-add", "button-base "],
597
+ "has_falsey": ["", False, [], {}],
598
+ "simple": " wagtail ",
599
+ }
600
+ )
601
+
602
+ template = """
603
+ {% load wagtailadmin_tags %}
604
+ <button class="{% classnames nested "add-second " has_falsey simple %}">Hello!</button>
605
+ """
606
+
607
+ expected = """
608
+ <button class="button-add button-base add-second wagtail">Hello!</button>
609
+ """
610
+
611
+ actual = Template(template).render(context)
612
+
613
+ self.assertEqual(expected.strip(), actual.strip())
614
+
462
615
 
463
616
  class IconTagTest(SimpleTestCase):
464
617
  def test_basic(self):
@@ -572,33 +725,23 @@ class StatusTagTest(SimpleTestCase):
572
725
  self.assertHTMLEqual(expected, Template(template).render(Context()))
573
726
 
574
727
 
575
- class BreadcrumbsTagTest(WagtailTestUtils, SimpleTestCase):
728
+ class BreadcrumbsTagTest(AdminTemplateTestUtils, WagtailTestUtils, SimpleTestCase):
729
+ base_breadcrumb_items = []
576
730
  template = """
577
731
  {% load wagtailadmin_tags %}
578
732
  {% breadcrumbs items %}
579
733
  """
580
734
 
581
- def assertItemsRendered(self, items, soup):
582
- rendered_items = soup.select("ol > li")
583
- arrows = soup.select("ol > li > svg")
584
- self.assertEqual(len(rendered_items), len(items))
585
- self.assertEqual(len(arrows), len(items) - 1)
586
-
587
- for item, rendered_item in zip(items, rendered_items):
588
- if item.get("url"):
589
- element = rendered_item.select_one("a")
590
- self.assertIsNotNone(element)
591
- self.assertEqual(element["href"], item["url"])
592
- else:
593
- element = rendered_item.select_one("div")
594
- self.assertIsNotNone(element)
595
- self.assertEqual(element.text.strip(), item["label"])
596
-
597
735
  def test_single_item(self):
598
736
  items = [{"label": "Something", "url": "/admin/something/"}]
599
737
  rendered = Template(self.template).render(Context({"items": items}))
738
+ self.assertBreadcrumbsItemsRendered(items, rendered)
739
+ # Without specifying is_expanded=False, the breadcrumbs should not be
740
+ # collapsible anyway, so it is not controlled by Stimulus
600
741
  soup = self.get_soup(rendered)
601
- self.assertItemsRendered(items, soup)
742
+ breadcrumbs = soup.select_one(".w-breadcrumbs")
743
+ self.assertIsNotNone(breadcrumbs)
744
+ self.assertIsNone(breadcrumbs.get("data-controller"))
602
745
 
603
746
  def test_trailing_no_url(self):
604
747
  items = [
@@ -607,8 +750,7 @@ class BreadcrumbsTagTest(WagtailTestUtils, SimpleTestCase):
607
750
  {"label": "New: Person"},
608
751
  ]
609
752
  rendered = Template(self.template).render(Context({"items": items}))
610
- soup = self.get_soup(rendered)
611
- self.assertItemsRendered(items, soup)
753
+ self.assertBreadcrumbsItemsRendered(items, rendered)
612
754
 
613
755
  def test_not_is_expanded(self):
614
756
  items = [
@@ -617,13 +759,19 @@ class BreadcrumbsTagTest(WagtailTestUtils, SimpleTestCase):
617
759
  {"label": "Muddy Waters", "url": "/admin/snippets/people/1/edit/"},
618
760
  ]
619
761
  rendered = Template(self.template).render(Context({"items": items}))
620
- soup = self.get_soup(rendered)
621
- self.assertItemsRendered(items, soup)
762
+ self.assertBreadcrumbsItemsRendered(items, rendered)
622
763
 
764
+ soup = self.get_soup(rendered)
623
765
  controller = soup.select_one('[data-controller="w-breadcrumbs"]')
624
766
  toggle_button = soup.select_one('button[data-w-breadcrumbs-target="toggle"]')
625
767
  self.assertIsNotNone(controller)
626
768
  self.assertIsNotNone(toggle_button)
769
+ # If is_expanded=False (the default), the breadcrumbs should be
770
+ # collapsible via Stimulus
771
+ soup = self.get_soup(rendered)
772
+ breadcrumbs = soup.select_one(".w-breadcrumbs")
773
+ self.assertIsNotNone(breadcrumbs)
774
+ self.assertEqual(breadcrumbs.get("data-controller"), "w-breadcrumbs")
627
775
 
628
776
  def test_is_expanded(self):
629
777
  template = """
@@ -636,13 +784,19 @@ class BreadcrumbsTagTest(WagtailTestUtils, SimpleTestCase):
636
784
  {"label": "Muddy Waters", "url": "/admin/snippets/people/1/edit/"},
637
785
  ]
638
786
  rendered = Template(template).render(Context({"items": items}))
639
- soup = self.get_soup(rendered)
640
- self.assertItemsRendered(items, soup)
787
+ self.assertBreadcrumbsItemsRendered(items, rendered)
641
788
 
789
+ soup = self.get_soup(rendered)
642
790
  controller = soup.select_one('[data-controller="w-breadcrumbs"]')
643
791
  toggle_button = soup.select_one('button[data-w-breadcrumbs-target="toggle"]')
644
792
  self.assertIsNone(controller)
645
793
  self.assertIsNone(toggle_button)
794
+ # If is_expanded=True, the breadcrumbs should not be collapsible, so it
795
+ # is not controlled by Stimulus
796
+ soup = self.get_soup(rendered)
797
+ breadcrumbs = soup.select_one(".w-breadcrumbs")
798
+ self.assertIsNotNone(breadcrumbs)
799
+ self.assertIsNone(breadcrumbs.get("data-controller"))
646
800
 
647
801
  def test_classname(self):
648
802
  template = """
@@ -651,9 +805,223 @@ class BreadcrumbsTagTest(WagtailTestUtils, SimpleTestCase):
651
805
  """
652
806
  items = [{"label": "Home", "url": "/admin/"}]
653
807
  rendered = Template(template).render(Context({"items": items}))
808
+ self.assertBreadcrumbsItemsRendered(items, rendered)
809
+
654
810
  soup = self.get_soup(rendered)
655
- self.assertItemsRendered(items, soup)
811
+ div = soup.select_one("div.w-breadcrumbs")
812
+ self.assertIsNotNone(div)
813
+ self.assertIn("my-class", div["class"])
814
+
815
+ def test_icon_name(self):
816
+ template = """
817
+ {% load wagtailadmin_tags %}
818
+ {% breadcrumbs items icon_name="site" %}
819
+ """
820
+ items = [
821
+ {"label": "Home", "url": "/admin/"},
822
+ {"label": "Something", "url": "/admin/something/"},
823
+ ]
824
+ rendered = Template(template).render(Context({"items": items}))
825
+ self.assertBreadcrumbsItemsRendered(items, rendered)
826
+
827
+ soup = self.get_soup(rendered)
828
+ invalid_icons = soup.select("ol li:not(:last-child) svg use[href='#icon-site']")
829
+ self.assertEqual(len(invalid_icons), 0)
830
+ icon = soup.select_one("ol li:last-child svg use[href='#icon-site']")
831
+ self.assertIsNotNone(icon)
656
832
 
833
+
834
+ class PageBreadcrumbsTagTest(AdminTemplateTestUtils, WagtailTestUtils, TestCase):
835
+ fixtures = ["test.json"]
836
+ base_breadcrumb_items = []
837
+
838
+ def setUp(self):
839
+ self.request = get_dummy_request()
840
+ self.user = self.login()
841
+ self.request.user = self.user
842
+
843
+ def test_root_single_item(self):
844
+ template = """
845
+ {% load wagtailadmin_tags %}
846
+ {% page_breadcrumbs page 'wagtailadmin_explore' url_root_name='wagtailadmin_explore_root' %}
847
+ """
848
+ page = Page.objects.get(id=1)
849
+ items = [{"label": "Root", "url": "/admin/pages/"}]
850
+ rendered = Template(template).render(
851
+ Context({"page": page, "request": self.request})
852
+ )
853
+ self.assertBreadcrumbsItemsRendered(items, rendered)
854
+ # Without specifying is_expanded=False, the breadcrumbs should not be
855
+ # collapsible anyway, so it is not controlled by Stimulus
856
+ soup = self.get_soup(rendered)
857
+ breadcrumbs = soup.select_one(".w-breadcrumbs")
858
+ self.assertIsNotNone(breadcrumbs)
859
+ self.assertIsNone(breadcrumbs.get("data-controller"))
860
+
861
+ def test_url_name(self):
862
+ template = """
863
+ {% load wagtailadmin_tags %}
864
+ {% page_breadcrumbs page 'wagtailadmin_choose_page_child' %}
865
+ """
866
+ page = Page.objects.get(id=15)
867
+ items = [
868
+ {
869
+ "label": "Root",
870
+ "url": "/admin/choose-page/1/",
871
+ },
872
+ {
873
+ "label": "Welcome to the Wagtail test site!",
874
+ "url": "/admin/choose-page/2/",
875
+ },
876
+ {
877
+ "label": "Events",
878
+ "url": "/admin/choose-page/3/",
879
+ },
880
+ {
881
+ "label": "Businessy events",
882
+ "url": "/admin/choose-page/15/",
883
+ },
884
+ ]
885
+ rendered = Template(template).render(
886
+ Context({"page": page, "request": self.request})
887
+ )
888
+ self.assertBreadcrumbsItemsRendered(items, rendered)
889
+
890
+ def test_not_include_self(self):
891
+ template = """
892
+ {% load wagtailadmin_tags %}
893
+ {% page_breadcrumbs page 'wagtailadmin_explore' url_root_name='wagtailadmin_explore_root' include_self=False %}
894
+ """
895
+ page = Page.objects.get(id=15)
896
+ items = [
897
+ {"label": "Root", "url": "/admin/pages/"},
898
+ {"label": "Welcome to the Wagtail test site!", "url": "/admin/pages/2/"},
899
+ {"label": "Events", "url": "/admin/pages/3/"},
900
+ ]
901
+ rendered = Template(template).render(
902
+ Context({"page": page, "request": self.request})
903
+ )
904
+ self.assertBreadcrumbsItemsRendered(items, rendered)
905
+
906
+ def test_not_is_expanded(self):
907
+ template = """
908
+ {% load wagtailadmin_tags %}
909
+ {% page_breadcrumbs page 'wagtailadmin_explore' url_root_name='wagtailadmin_explore_root' %}
910
+ """
911
+ page = Page.objects.get(id=15)
912
+ items = [
913
+ {"label": "Root", "url": "/admin/pages/"},
914
+ {"label": "Welcome to the Wagtail test site!", "url": "/admin/pages/2/"},
915
+ {"label": "Events", "url": "/admin/pages/3/"},
916
+ {"label": "Businessy events", "url": "/admin/pages/15/"},
917
+ ]
918
+ rendered = Template(template).render(
919
+ Context({"page": page, "request": self.request})
920
+ )
921
+ self.assertBreadcrumbsItemsRendered(items, rendered)
922
+ # If is_expanded=False, the breadcrumbs should be collapsible via Stimulus
923
+ soup = self.get_soup(rendered)
924
+ breadcrumbs = soup.select_one(".w-breadcrumbs")
925
+ self.assertIsNotNone(breadcrumbs)
926
+ self.assertEqual(breadcrumbs.get("data-controller"), "w-breadcrumbs")
927
+
928
+ def test_is_expanded(self):
929
+ template = """
930
+ {% load wagtailadmin_tags %}
931
+ {% page_breadcrumbs page 'wagtailadmin_explore' url_root_name='wagtailadmin_explore_root' is_expanded=True %}
932
+ """
933
+ page = Page.objects.get(id=15)
934
+ items = [
935
+ {"label": "Root", "url": "/admin/pages/"},
936
+ {"label": "Welcome to the Wagtail test site!", "url": "/admin/pages/2/"},
937
+ {"label": "Events", "url": "/admin/pages/3/"},
938
+ {"label": "Businessy events", "url": "/admin/pages/15/"},
939
+ ]
940
+ rendered = Template(template).render(
941
+ Context({"page": page, "request": self.request})
942
+ )
943
+ self.assertBreadcrumbsItemsRendered(items, rendered)
944
+ # If is_expanded=True, the breadcrumbs should not be collapsible, so it
945
+ # is not controlled by Stimulus
946
+ soup = self.get_soup(rendered)
947
+ breadcrumbs = soup.select_one(".w-breadcrumbs")
948
+ self.assertIsNotNone(breadcrumbs)
949
+ self.assertIsNone(breadcrumbs.get("data-controller"))
950
+
951
+ def test_querystring_value(self):
952
+ template = """
953
+ {% load wagtailadmin_tags %}
954
+ {% page_breadcrumbs page 'wagtailadmin_explore' url_root_name='wagtailadmin_explore_root' querystring_value='?site=2&has_child_pages=true' %}
955
+ """
956
+ page = Page.objects.get(id=15)
957
+ params = "?site=2&has_child_pages=true"
958
+ items = [
959
+ {"label": "Root", "url": f"/admin/pages/{params}"},
960
+ {
961
+ "label": "Welcome to the Wagtail test site!",
962
+ "url": f"/admin/pages/2/{params}",
963
+ },
964
+ {"label": "Events", "url": f"/admin/pages/3/{params}"},
965
+ {"label": "Businessy events", "url": f"/admin/pages/15/{params}"},
966
+ ]
967
+ rendered = Template(template).render(
968
+ Context({"page": page, "request": self.request})
969
+ )
970
+ self.assertBreadcrumbsItemsRendered(items, rendered)
971
+
972
+ def test_trailing_breadcrumb_title(self):
973
+ template = """
974
+ {% load wagtailadmin_tags %}
975
+ {% page_breadcrumbs page 'wagtailadmin_explore' url_root_name='wagtailadmin_explore_root' trailing_breadcrumb_title='New: Simple Page' %}
976
+ """
977
+ page = Page.objects.get(id=15)
978
+ items = [
979
+ {"label": "Root", "url": "/admin/pages/"},
980
+ {"label": "Welcome to the Wagtail test site!", "url": "/admin/pages/2/"},
981
+ {"label": "Events", "url": "/admin/pages/3/"},
982
+ {"label": "Businessy events", "url": "/admin/pages/15/"},
983
+ {"label": "New: Simple Page"},
984
+ ]
985
+ rendered = Template(template).render(
986
+ Context({"page": page, "request": self.request})
987
+ )
988
+ self.assertBreadcrumbsItemsRendered(items, rendered)
989
+
990
+ def test_classname(self):
991
+ template = """
992
+ {% load wagtailadmin_tags %}
993
+ {% page_breadcrumbs page 'wagtailadmin_choose_page_child' classname='my-class' %}
994
+ """
995
+ page = Page.objects.get(id=1)
996
+ items = [{"label": "Root", "url": "/admin/choose-page/1/"}]
997
+ rendered = Template(template).render(
998
+ Context({"page": page, "request": self.request})
999
+ )
1000
+ self.assertBreadcrumbsItemsRendered(items, rendered)
1001
+
1002
+ soup = self.get_soup(rendered)
657
1003
  div = soup.select_one("div.w-breadcrumbs")
658
1004
  self.assertIsNotNone(div)
659
1005
  self.assertIn("my-class", div["class"])
1006
+
1007
+ def test_icon_name(self):
1008
+ template = """
1009
+ {% load wagtailadmin_tags %}
1010
+ {% page_breadcrumbs page 'wagtailadmin_explore' icon_name='site' %}
1011
+ """
1012
+ page = Page.objects.get(id=3)
1013
+ items = [
1014
+ {"label": "Root", "url": "/admin/pages/1/"},
1015
+ {"label": "Welcome to the Wagtail test site!", "url": "/admin/pages/2/"},
1016
+ {"label": "Events", "url": "/admin/pages/3/"},
1017
+ ]
1018
+ rendered = Template(template).render(
1019
+ Context({"page": page, "request": self.request})
1020
+ )
1021
+ self.assertBreadcrumbsItemsRendered(items, rendered)
1022
+
1023
+ soup = self.get_soup(rendered)
1024
+ invalid_icons = soup.select("ol li:not(:last-child) svg use[href='#icon-site']")
1025
+ self.assertEqual(len(invalid_icons), 0)
1026
+ icon = soup.select_one("ol li:last-child svg use[href='#icon-site']")
1027
+ self.assertIsNotNone(icon)
@@ -80,14 +80,16 @@ class TestLoginView(WagtailTestUtils, TestCase):
80
80
  def test_language_code(self):
81
81
  response = self.client.get(reverse("wagtailadmin_login"))
82
82
  self.assertContains(
83
- response, '<html lang="de" dir="ltr" class="w-theme-system">'
83
+ response,
84
+ '<html lang="de" dir="ltr" class="w-theme-system w-density-default">',
84
85
  )
85
86
 
86
87
  @override_settings(LANGUAGE_CODE="he")
87
88
  def test_bidi_language_changes_dir_attribute(self):
88
89
  response = self.client.get(reverse("wagtailadmin_login"))
89
90
  self.assertContains(
90
- response, '<html lang="he" dir="rtl" class="w-theme-system">'
91
+ response,
92
+ '<html lang="he" dir="rtl" class="w-theme-system w-density-default">',
91
93
  )
92
94
 
93
95
  @override_settings(