wagtail 6.0.2__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.
- wagtail/__init__.py +1 -1
- wagtail/admin/checks.py +51 -0
- wagtail/admin/compare.py +1 -1
- wagtail/admin/filters.py +70 -1
- wagtail/admin/forms/account.py +1 -1
- wagtail/admin/forms/collections.py +15 -0
- wagtail/admin/forms/pages.py +49 -0
- wagtail/admin/locale/de/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/de/LC_MESSAGES/django.po +5 -5
- wagtail/admin/locale/en/LC_MESSAGES/django.po +474 -385
- wagtail/admin/locale/en/LC_MESSAGES/djangojs.po +3 -3
- wagtail/admin/locale/pt_PT/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/pt_PT/LC_MESSAGES/django.po +73 -2
- wagtail/admin/locale/ro/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/ro/LC_MESSAGES/django.po +3 -3
- wagtail/admin/panels/comment_panel.py +1 -1
- wagtail/admin/panels/field_panel.py +1 -1
- wagtail/admin/rich_text/converters/editor_html.py +3 -1
- wagtail/admin/rich_text/editors/draftail/__init__.py +28 -2
- wagtail/admin/static/wagtailadmin/css/core.css +1 -1
- wagtail/admin/static/wagtailadmin/css/panels/draftail.css +1 -1
- wagtail/admin/static/wagtailadmin/images/favicon.ico +0 -0
- wagtail/admin/static/wagtailadmin/js/bulk-actions.js +1 -1
- wagtail/admin/static/wagtailadmin/js/chooser-modal.js +1 -1
- wagtail/admin/static/wagtailadmin/js/chooser-widget-telepath.js +1 -1
- wagtail/admin/static/wagtailadmin/js/chooser-widget.js +1 -1
- wagtail/admin/static/wagtailadmin/js/comments.js +1 -1
- wagtail/admin/static/wagtailadmin/js/core.js +1 -1
- wagtail/admin/static/wagtailadmin/js/core.js.LICENSE.txt +1 -1
- wagtail/admin/static/wagtailadmin/js/date-time-chooser.js +1 -1
- wagtail/admin/static/wagtailadmin/js/draftail.js +1 -1
- wagtail/admin/static/wagtailadmin/js/expanding-formset.js +1 -1
- wagtail/admin/static/wagtailadmin/js/filtered-select.js +1 -1
- wagtail/admin/static/wagtailadmin/js/modal-workflow.js +1 -1
- wagtail/admin/static/wagtailadmin/js/page-chooser-modal.js +1 -1
- wagtail/admin/static/wagtailadmin/js/page-chooser-telepath.js +1 -1
- wagtail/admin/static/wagtailadmin/js/page-chooser.js +1 -1
- wagtail/admin/static/wagtailadmin/js/preview-panel.js +1 -1
- wagtail/admin/static/wagtailadmin/js/privacy-switch.js +1 -1
- wagtail/admin/static/wagtailadmin/js/sidebar.js +1 -1
- wagtail/admin/static/wagtailadmin/js/task-chooser-modal.js +1 -1
- wagtail/admin/static/wagtailadmin/js/task-chooser.js +1 -1
- wagtail/admin/static/wagtailadmin/js/telepath/blocks.js +1 -1
- wagtail/admin/static/wagtailadmin/js/telepath/telepath.js +1 -1
- wagtail/admin/static/wagtailadmin/js/telepath/widgets.js +1 -1
- wagtail/admin/static/wagtailadmin/js/userbar.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor.js.LICENSE.txt +4 -4
- wagtail/admin/static/wagtailadmin/js/wagtailadmin.js +1 -1
- wagtail/admin/static/wagtailadmin/js/workflow-action.js +1 -1
- wagtail/admin/staticfiles.py +1 -0
- wagtail/admin/templates/wagtailadmin/base.html +1 -0
- wagtail/admin/templates/wagtailadmin/collection_privacy/set_privacy.html +3 -1
- wagtail/admin/templates/wagtailadmin/collections/index_results.html +10 -0
- wagtail/admin/templates/wagtailadmin/generic/base.html +1 -9
- wagtail/admin/templates/wagtailadmin/generic/form.html +3 -2
- wagtail/admin/templates/wagtailadmin/generic/history/action_cell.html +27 -0
- wagtail/admin/templates/wagtailadmin/home/workflow_objects_to_moderate.html +3 -3
- wagtail/admin/templates/wagtailadmin/icons/keyboard.svg +1 -0
- wagtail/admin/templates/wagtailadmin/page_privacy/set_privacy.html +3 -1
- wagtail/admin/templates/wagtailadmin/pages/_editor_js.html +0 -14
- wagtail/admin/templates/wagtailadmin/pages/action_menu/save_draft.html +3 -1
- wagtail/admin/templates/wagtailadmin/pages/choose_parent.html +17 -0
- wagtail/admin/templates/wagtailadmin/pages/explorable_index.html +8 -0
- wagtail/admin/templates/wagtailadmin/pages/history.html +1 -61
- wagtail/admin/templates/wagtailadmin/pages/index.html +1 -3
- wagtail/admin/templates/wagtailadmin/pages/listing/_locked_indicator.html +2 -2
- wagtail/admin/templates/wagtailadmin/pages/listing/_page_title_column_header.html +25 -27
- wagtail/admin/templates/wagtailadmin/pages/page_listing_header.html +2 -1
- wagtail/admin/templates/wagtailadmin/panels/multi_field_panel_child.html +1 -1
- wagtail/admin/templates/wagtailadmin/panels/publishing/schedule_publishing_panel.html +3 -1
- wagtail/admin/templates/wagtailadmin/panels/tabbed_interface.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/active_filters.html +2 -1
- wagtail/admin/templates/wagtailadmin/shared/breadcrumbs.html +8 -0
- wagtail/admin/templates/wagtailadmin/shared/forms/single_checkbox.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/headers/page_edit_header.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/headers/slim_header.html +21 -9
- wagtail/admin/templates/wagtailadmin/shared/human_readable_date.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/keyboard_shortcuts_dialog.html +29 -0
- wagtail/admin/templates/wagtailadmin/shared/side_panel_toggle.html +2 -1
- wagtail/admin/templates/wagtailadmin/skeleton.html +2 -1
- wagtail/admin/templates/wagtailadmin/tables/related_objects_cell.html +9 -0
- wagtail/admin/templates/wagtailadmin/tables/title_cell.html +9 -7
- wagtail/admin/templates/wagtailadmin/widgets/draftail_rich_text_area.html +1 -1
- wagtail/admin/templates/wagtailadmin/workflows/create.html +6 -23
- wagtail/admin/templates/wagtailadmin/workflows/create_task.html +6 -15
- wagtail/admin/templates/wagtailadmin/workflows/edit.html +6 -23
- wagtail/admin/templates/wagtailadmin/workflows/edit_task.html +6 -13
- wagtail/admin/templates/wagtailadmin/workflows/includes/task_usage_cell.html +4 -4
- wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_tasks_cell.html +18 -0
- wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_title_cell.html +7 -0
- wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_used_by_cell.html +25 -0
- wagtail/admin/templates/wagtailadmin/workflows/index.html +0 -99
- wagtail/admin/templates/wagtailadmin/workflows/index_results.html +10 -0
- wagtail/admin/templates/wagtailadmin/workflows/task_index.html +0 -30
- wagtail/admin/templates/wagtailadmin/workflows/task_index_results.html +10 -0
- wagtail/admin/templates/wagtailadmin/workflows/usage.html +1 -1
- wagtail/admin/templatetags/wagtailadmin_tags.py +116 -39
- wagtail/admin/tests/pages/test_create_page.py +10 -4
- wagtail/admin/tests/pages/test_custom_listing.py +37 -0
- wagtail/admin/tests/pages/test_edit_page.py +6 -6
- wagtail/admin/tests/pages/test_explorer_view.py +19 -18
- wagtail/admin/tests/pages/test_move_page.py +1 -1
- wagtail/admin/tests/pages/test_page_usage.py +50 -2
- wagtail/admin/tests/pages/test_parent_page_chooser_view.py +119 -0
- wagtail/admin/tests/pages/test_preview.py +18 -4
- wagtail/admin/tests/test_account_management.py +20 -1
- wagtail/admin/tests/test_audit_log.py +172 -5
- wagtail/admin/tests/test_checks.py +92 -0
- wagtail/admin/tests/test_collections_views.py +19 -5
- wagtail/admin/tests/test_compare.py +6 -6
- wagtail/admin/tests/test_dashboard.py +404 -0
- wagtail/admin/tests/test_dbwhitelister.py +4 -5
- wagtail/admin/tests/test_edit_handlers.py +2 -2
- wagtail/admin/tests/test_keyboard_shortcuts.py +84 -0
- wagtail/admin/tests/test_page_chooser.py +31 -18
- wagtail/admin/tests/test_privacy.py +36 -2
- wagtail/admin/tests/test_rich_text.py +168 -23
- wagtail/admin/tests/test_templatetags.py +411 -43
- wagtail/admin/tests/test_views.py +4 -2
- wagtail/admin/tests/test_workflows.py +531 -9
- wagtail/admin/tests/tests.py +3 -1
- wagtail/admin/tests/ui/test_tables.py +48 -1
- wagtail/admin/tests/viewsets/test_model_viewset.py +126 -29
- wagtail/admin/ui/side_panels.py +3 -1
- wagtail/admin/ui/tables/__init__.py +13 -1
- wagtail/admin/ui/tables/pages.py +17 -6
- wagtail/admin/urls/__init__.py +8 -3
- wagtail/admin/urls/pages.py +5 -0
- wagtail/admin/urls/workflows.py +10 -0
- wagtail/admin/views/chooser.py +20 -24
- wagtail/admin/views/collections.py +17 -1
- wagtail/admin/views/generic/base.py +31 -4
- wagtail/admin/views/generic/history.py +220 -51
- wagtail/admin/views/generic/mixins.py +7 -4
- wagtail/admin/views/generic/models.py +54 -38
- wagtail/admin/views/generic/multiple_upload.py +17 -8
- wagtail/admin/views/generic/usage.py +17 -11
- wagtail/admin/views/home.py +15 -12
- wagtail/admin/views/mixins.py +30 -0
- wagtail/admin/views/pages/choose_parent.py +73 -0
- wagtail/admin/views/pages/history.py +54 -66
- wagtail/admin/views/pages/listing.py +187 -106
- wagtail/admin/views/pages/usage.py +6 -1
- wagtail/admin/views/pages/utils.py +70 -1
- wagtail/admin/views/workflows.py +150 -21
- wagtail/admin/viewsets/model.py +2 -2
- wagtail/admin/viewsets/pages.py +77 -0
- wagtail/admin/wagtail_hooks.py +40 -2
- wagtail/admin/widgets/button.py +10 -9
- wagtail/api/v2/filters.py +1 -1
- wagtail/api/v2/tests/test_pages.py +1 -1
- wagtail/blocks/base.py +18 -9
- wagtail/blocks/field_block.py +9 -7
- wagtail/blocks/list_block.py +16 -6
- wagtail/blocks/static_block.py +3 -0
- wagtail/blocks/stream_block.py +58 -23
- wagtail/blocks/struct_block.py +15 -9
- wagtail/contrib/forms/locale/en/LC_MESSAGES/django.po +39 -47
- wagtail/contrib/forms/models.py +5 -5
- wagtail/contrib/forms/templates/wagtailforms/list_submissions.html +44 -33
- wagtail/contrib/forms/templates/wagtailforms/submissions_index.html +2 -63
- wagtail/contrib/forms/tests/test_models.py +26 -0
- wagtail/contrib/forms/urls.py +6 -0
- wagtail/contrib/forms/views.py +52 -49
- wagtail/contrib/redirects/locale/ca/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/redirects/locale/ca/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/redirects/locale/en/LC_MESSAGES/django.po +34 -42
- wagtail/contrib/redirects/signal_handlers.py +1 -1
- wagtail/contrib/redirects/templates/wagtailredirects/index.html +1 -36
- wagtail/contrib/redirects/templates/wagtailredirects/index_results.html +18 -0
- wagtail/contrib/redirects/templates/wagtailredirects/redirect_target_cell.html +8 -0
- wagtail/contrib/redirects/tests/test_import_command.py +1 -1
- wagtail/contrib/redirects/tests/test_redirects.py +79 -8
- wagtail/contrib/redirects/urls.py +2 -1
- wagtail/contrib/redirects/views.py +85 -55
- wagtail/contrib/search_promotions/admin_urls.py +2 -1
- wagtail/contrib/search_promotions/locale/en/LC_MESSAGES/django.po +41 -64
- wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/index.html +1 -16
- wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/index_results.html +11 -0
- wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/list.html +0 -51
- wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/results.html +3 -16
- wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/search_promotion_column.html +15 -0
- wagtail/contrib/search_promotions/tests.py +122 -9
- wagtail/contrib/search_promotions/views.py +66 -65
- wagtail/contrib/settings/locale/en/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/settings/registry.py +10 -5
- wagtail/contrib/settings/tests/generic/test_admin.py +9 -0
- wagtail/contrib/settings/tests/site_specific/test_admin.py +10 -1
- wagtail/contrib/settings/tests/site_specific/test_model.py +3 -3
- wagtail/contrib/settings/tests/site_specific/test_templates.py +1 -1
- wagtail/contrib/settings/views.py +3 -1
- wagtail/contrib/simple_translation/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/simple_translation/tests/test_wagtail_hooks.py +2 -2
- wagtail/contrib/styleguide/locale/en/LC_MESSAGES/django.po +7 -7
- wagtail/contrib/table_block/blocks.py +1 -1
- wagtail/contrib/table_block/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/table_block/static/table_block/js/table.js +1 -1
- wagtail/contrib/typed_table_block/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/typed_table_block/static/typed_table_block/js/typed_table_block.js +1 -1
- wagtail/coreutils.py +3 -2
- wagtail/documents/admin_urls.py +2 -2
- wagtail/documents/locale/en/LC_MESSAGES/django.po +22 -22
- wagtail/documents/migrations/0013_delete_uploadeddocument.py +16 -0
- wagtail/documents/models.py +1 -20
- wagtail/documents/rich_text/__init__.py +11 -7
- wagtail/documents/static/wagtaildocs/js/document-chooser-modal.js +1 -1
- wagtail/documents/static/wagtaildocs/js/document-chooser-telepath.js +1 -1
- wagtail/documents/static/wagtaildocs/js/document-chooser.js +1 -1
- wagtail/documents/templates/wagtaildocs/documents/index.html +0 -16
- wagtail/documents/tests/test_admin_views.py +155 -23
- wagtail/documents/tests/test_collection_privacy.py +55 -1
- wagtail/documents/tests/test_rich_text.py +14 -0
- wagtail/documents/views/documents.py +25 -22
- wagtail/documents/views/multiple.py +6 -7
- wagtail/documents/views/serve.py +16 -1
- wagtail/documents/wagtail_hooks.py +20 -15
- wagtail/embeds/blocks.py +5 -0
- wagtail/embeds/locale/en/LC_MESSAGES/django.po +2 -2
- wagtail/embeds/rich_text/__init__.py +1 -1
- wagtail/embeds/tests/test_rich_text.py +14 -0
- wagtail/embeds/wagtail_hooks.py +4 -14
- wagtail/fields.py +3 -48
- wagtail/images/admin_urls.py +2 -2
- wagtail/images/check_files/wagtail.jpg +0 -0
- wagtail/images/check_files/wagtail.png +0 -0
- wagtail/images/fields.py +2 -0
- wagtail/images/image_operations.py +1 -1
- wagtail/images/locale/en/LC_MESSAGES/django.po +33 -45
- wagtail/images/locale/pt_PT/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/pt_PT/LC_MESSAGES/django.po +4 -0
- wagtail/images/migrations/0026_delete_uploadedimage.py +16 -0
- wagtail/images/models.py +49 -43
- wagtail/images/rich_text/__init__.py +18 -8
- wagtail/images/static/wagtailimages/js/image-chooser-modal.js +1 -1
- wagtail/images/static/wagtailimages/js/image-chooser-telepath.js +1 -1
- wagtail/images/static/wagtailimages/js/image-chooser.js +1 -1
- wagtail/images/templates/wagtailimages/images/image_listing_header.html +6 -0
- wagtail/images/templates/wagtailimages/images/index.html +11 -51
- wagtail/images/tests/test_admin_views.py +119 -62
- wagtail/images/tests/test_image_operations.py +10 -0
- wagtail/images/tests/test_models.py +35 -33
- wagtail/images/tests/test_rich_text.py +14 -0
- wagtail/images/tests/utils.py +1 -1
- wagtail/images/views/images.py +35 -64
- wagtail/images/views/multiple.py +6 -7
- wagtail/images/wagtail_hooks.py +4 -14
- wagtail/locale/en/LC_MESSAGES/django.po +150 -136
- wagtail/locales/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/locales/tests.py +18 -3
- wagtail/locales/views.py +0 -1
- wagtail/management/commands/rebuild_references_index.py +3 -1
- wagtail/migrations/0092_alter_collectionviewrestriction_password_and_more.py +33 -0
- wagtail/migrations/0093_uploadedfile.py +53 -0
- wagtail/models/__init__.py +147 -32
- wagtail/models/i18n.py +1 -1
- wagtail/models/{collections.py → media.py} +33 -2
- wagtail/models/reference_index.py +1 -1
- wagtail/models/view_restrictions.py +10 -3
- wagtail/project_template/project_name/settings/base.py +6 -0
- wagtail/project_template/requirements.txt +1 -1
- wagtail/rich_text/__init__.py +25 -8
- wagtail/rich_text/pages.py +19 -8
- wagtail/rich_text/rewriters.py +140 -68
- wagtail/search/backends/database/mysql/mysql.py +3 -3
- wagtail/search/backends/database/postgres/postgres.py +3 -3
- wagtail/search/backends/database/sqlite/sqlite.py +2 -2
- wagtail/search/backends/elasticsearch7.py +4 -0
- wagtail/search/locale/en/LC_MESSAGES/django.po +3 -3
- wagtail/search/tests/test_postgres_backend.py +50 -0
- wagtail/sites/locale/en/LC_MESSAGES/django.po +8 -8
- wagtail/sites/tests.py +35 -9
- wagtail/sites/views.py +3 -1
- wagtail/snippets/locale/de/LC_MESSAGES/django.mo +0 -0
- wagtail/snippets/locale/de/LC_MESSAGES/django.po +5 -6
- wagtail/snippets/locale/en/LC_MESSAGES/django.po +16 -56
- wagtail/snippets/static/wagtailsnippets/js/snippet-chooser-telepath.js +1 -1
- wagtail/snippets/static/wagtailsnippets/js/snippet-chooser.js +1 -1
- wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/publish.html +3 -1
- wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/save.html +3 -1
- wagtail/snippets/templates/wagtailsnippets/snippets/create.html +1 -1
- wagtail/snippets/templates/wagtailsnippets/snippets/edit.html +1 -1
- wagtail/snippets/tests/test_preview.py +13 -2
- wagtail/snippets/tests/test_snippets.py +41 -16
- wagtail/snippets/tests/test_viewset.py +63 -18
- wagtail/snippets/tests/test_workflows.py +12 -0
- wagtail/snippets/views/snippets.py +1 -40
- wagtail/templatetags/wagtailcore_tags.py +1 -1
- wagtail/test/demosite/models.py +1 -1
- wagtail/test/middleware.py +14 -1
- wagtail/test/testapp/fixtures/test.json +20 -0
- wagtail/test/testapp/migrations/0001_squashed_0073_revisablechildmodel_secret_text.py +8 -8
- wagtail/test/testapp/migrations/0023_snippetchoosermodel_full_featured.py +1 -0
- wagtail/test/testapp/migrations/0034_custompermissionmodel.py +44 -0
- wagtail/test/testapp/migrations/0035_modelwithcustommanager.py +30 -0
- wagtail/test/testapp/migrations/0036_complexdefaultstreampage.py +28 -0
- wagtail/test/testapp/models.py +79 -2
- wagtail/test/testapp/templates/tests/custom_docs_password_required.html +10 -0
- wagtail/test/testapp/templates/tests/custom_page_password_required.html +10 -0
- wagtail/test/testapp/views.py +24 -2
- wagtail/test/testapp/wagtail_hooks.py +19 -0
- wagtail/test/utils/wagtail_tests.py +2 -2
- wagtail/tests/test_blocks.py +262 -1
- wagtail/tests/test_migrations.py +1 -1
- wagtail/tests/test_page_model.py +77 -0
- wagtail/tests/test_page_privacy.py +18 -1
- wagtail/tests/test_rich_text.py +95 -5
- wagtail/tests/test_streamfield.py +43 -0
- wagtail/tests/test_utils.py +8 -2
- wagtail/tests/test_views.py +52 -1
- wagtail/tests/test_whitelist.py +7 -7
- wagtail/users/forms.py +3 -1
- wagtail/users/locale/en/LC_MESSAGES/django.po +124 -96
- wagtail/users/migrations/0013_userprofile_density.py +23 -0
- wagtail/users/models.py +14 -3
- wagtail/users/templates/wagtailusers/groups/create.html +1 -7
- wagtail/users/templates/wagtailusers/groups/edit.html +1 -13
- wagtail/users/templates/wagtailusers/groups/includes/formatted_permissions.html +46 -2
- wagtail/users/templates/wagtailusers/groups/includes/group_form_js.html +0 -2
- wagtail/users/templates/wagtailusers/users/create.html +1 -9
- wagtail/users/templates/wagtailusers/users/edit.html +1 -9
- wagtail/users/templates/wagtailusers/users/index.html +2 -5
- wagtail/users/templates/wagtailusers/users/index_results.html +3 -13
- wagtail/users/templates/wagtailusers/users/user_cell.html +9 -0
- wagtail/users/templatetags/wagtailusers_tags.py +107 -20
- wagtail/users/tests/test_admin_views.py +669 -90
- wagtail/users/views/groups.py +58 -61
- wagtail/users/views/users.py +211 -92
- wagtail/users/wagtail_hooks.py +6 -38
- wagtail/users/widgets.py +3 -5
- wagtail/utils/text.py +1 -1
- wagtail/views.py +5 -9
- wagtail/whitelist.py +1 -1
- {wagtail-6.0.2.dist-info → wagtail-6.1rc1.dist-info}/METADATA +4 -5
- {wagtail-6.0.2.dist-info → wagtail-6.1rc1.dist-info}/RECORD +339 -320
- wagtail/admin/static/wagtailadmin/js/page-editor.js +0 -1
- wagtail/admin/static/wagtailadmin/js/vendor/mousetrap.min.js +0 -1
- wagtail/admin/static/wagtailadmin/js/vendor/urlify.js +0 -1
- wagtail/admin/static/wagtailadmin/js/vendor/xregexp.min.js +0 -1
- wagtail/admin/templates/wagtailadmin/collections/index.html +0 -34
- wagtail/admin/templates/wagtailadmin/pages/revisions/_actions.html +0 -22
- wagtail/admin/templates/wagtailadmin/shared/page_breadcrumbs.html +0 -55
- wagtail/admin/tests/pages/test_dashboard.py +0 -172
- wagtail/contrib/redirects/templates/wagtailredirects/results.html +0 -23
- wagtail/documents/templates/wagtaildocs/documents/list.html +0 -2
- wagtail/search/tests/test_postgres_stemming.py +0 -40
- wagtail/sites/templates/wagtailsites/create.html +0 -6
- wagtail/sites/templates/wagtailsites/edit.html +0 -6
- wagtail/snippets/templates/wagtailsnippets/snippets/revisions/_actions.html +0 -36
- wagtail/users/templates/wagtailusers/users/list.html +0 -62
- wagtail/users/urls/users.py +0 -12
- {wagtail-6.0.2.dist-info → wagtail-6.1rc1.dist-info}/LICENSE +0 -0
- {wagtail-6.0.2.dist-info → wagtail-6.1rc1.dist-info}/WHEEL +0 -0
- {wagtail-6.0.2.dist-info → wagtail-6.1rc1.dist-info}/entry_points.txt +0 -0
- {wagtail-6.0.2.dist-info → wagtail-6.1rc1.dist-info}/top_level.txt +0 -0
|
@@ -2,7 +2,13 @@ from django.template import Context, Template
|
|
|
2
2
|
from django.test import RequestFactory, TestCase
|
|
3
3
|
from django.utils.html import format_html
|
|
4
4
|
|
|
5
|
-
from wagtail.admin.ui.tables import
|
|
5
|
+
from wagtail.admin.ui.tables import (
|
|
6
|
+
BaseColumn,
|
|
7
|
+
Column,
|
|
8
|
+
RelatedObjectsColumn,
|
|
9
|
+
Table,
|
|
10
|
+
TitleColumn,
|
|
11
|
+
)
|
|
6
12
|
from wagtail.models import Page, Site
|
|
7
13
|
|
|
8
14
|
|
|
@@ -322,3 +328,44 @@ class TestTable(TestCase):
|
|
|
322
328
|
</table>
|
|
323
329
|
""",
|
|
324
330
|
)
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
class TestRelatedObjectsColumn(TestCase):
|
|
334
|
+
def setUp(self):
|
|
335
|
+
self.rf = RequestFactory()
|
|
336
|
+
|
|
337
|
+
def render_component(self, obj):
|
|
338
|
+
request = self.rf.get("/")
|
|
339
|
+
template = Template("{% load wagtailadmin_tags %}{% component obj %}")
|
|
340
|
+
return template.render(Context({"request": request, "obj": obj}))
|
|
341
|
+
|
|
342
|
+
def test_table_render(self):
|
|
343
|
+
table = Table(
|
|
344
|
+
[
|
|
345
|
+
Column("title"),
|
|
346
|
+
RelatedObjectsColumn("sites_rooted_here"),
|
|
347
|
+
],
|
|
348
|
+
Page.objects.all(),
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
html = self.render_component(table)
|
|
352
|
+
self.assertHTMLEqual(
|
|
353
|
+
html,
|
|
354
|
+
"""
|
|
355
|
+
<table class="listing">
|
|
356
|
+
<thead>
|
|
357
|
+
<tr><th>Title</th><th>Sites rooted here</th></tr>
|
|
358
|
+
</thead>
|
|
359
|
+
<tbody>
|
|
360
|
+
<tr>
|
|
361
|
+
<td>Root</td>
|
|
362
|
+
<td></td>
|
|
363
|
+
</tr>
|
|
364
|
+
<tr>
|
|
365
|
+
<td>Welcome to your new Wagtail site!</td>
|
|
366
|
+
<td><ul><li>localhost [default]</li></ul></td>
|
|
367
|
+
</tr>
|
|
368
|
+
</tbody>
|
|
369
|
+
</table>
|
|
370
|
+
""",
|
|
371
|
+
)
|
|
@@ -6,7 +6,7 @@ from django.contrib.admin.utils import quote
|
|
|
6
6
|
from django.contrib.auth import get_permission_codename
|
|
7
7
|
from django.contrib.auth.models import Permission
|
|
8
8
|
from django.contrib.contenttypes.models import ContentType
|
|
9
|
-
from django.test import
|
|
9
|
+
from django.test import TestCase
|
|
10
10
|
from django.urls import NoReverseMatch, reverse
|
|
11
11
|
from django.utils.formats import date_format, localize
|
|
12
12
|
from django.utils.html import escape
|
|
@@ -14,7 +14,6 @@ from django.utils.timezone import make_aware
|
|
|
14
14
|
from openpyxl import load_workbook
|
|
15
15
|
|
|
16
16
|
from wagtail.admin.admin_url_finder import AdminURLFinder
|
|
17
|
-
from wagtail.admin.staticfiles import versioned_static
|
|
18
17
|
from wagtail.log_actions import log
|
|
19
18
|
from wagtail.models import ModelLogEntry
|
|
20
19
|
from wagtail.test.testapp.models import (
|
|
@@ -23,7 +22,6 @@ from wagtail.test.testapp.models import (
|
|
|
23
22
|
SearchTestModel,
|
|
24
23
|
VariousOnDeleteModel,
|
|
25
24
|
)
|
|
26
|
-
from wagtail.test.testapp.views import FCToyAlt1ViewSet
|
|
27
25
|
from wagtail.test.utils.template_tests import AdminTemplateTestUtils
|
|
28
26
|
from wagtail.test.utils.wagtail_tests import WagtailTestUtils
|
|
29
27
|
from wagtail.utils.deprecation import RemovedInWagtail70Warning
|
|
@@ -995,7 +993,7 @@ class TestHistoryView(WagtailTestUtils, TestCase):
|
|
|
995
993
|
)
|
|
996
994
|
response = self.client.get(self.url)
|
|
997
995
|
soup = self.get_soup(response.content)
|
|
998
|
-
rows = soup.select("tbody tr")
|
|
996
|
+
rows = soup.select("#listing-results tbody tr")
|
|
999
997
|
self.assertEqual(response.status_code, 200)
|
|
1000
998
|
self.assertEqual(len(rows), 2)
|
|
1001
999
|
|
|
@@ -1012,28 +1010,109 @@ class TestHistoryView(WagtailTestUtils, TestCase):
|
|
|
1012
1010
|
for rendered_row, expected_row in zip(rendered_rows, expected):
|
|
1013
1011
|
self.assertSequenceEqual(rendered_row, expected_row)
|
|
1014
1012
|
|
|
1015
|
-
def
|
|
1016
|
-
response = self.client.get(self.url
|
|
1013
|
+
def test_action_filter(self):
|
|
1014
|
+
response = self.client.get(self.url)
|
|
1015
|
+
self.assertEqual(response.status_code, 200)
|
|
1016
|
+
|
|
1017
|
+
# Should only show the created and edited options for the filter
|
|
1017
1018
|
soup = self.get_soup(response.content)
|
|
1018
|
-
|
|
1019
|
+
options = soup.select('input[name="action"][type="checkbox"]')
|
|
1020
|
+
self.assertEqual(len(options), 2)
|
|
1021
|
+
self.assertEqual(
|
|
1022
|
+
{option.attrs.get("value") for option in options},
|
|
1023
|
+
{"wagtail.create", "wagtail.edit"},
|
|
1024
|
+
)
|
|
1025
|
+
# Should not show the heading when not searching
|
|
1026
|
+
heading = soup.select_one('h2[role="alert"]')
|
|
1027
|
+
self.assertIsNone(heading)
|
|
1028
|
+
|
|
1029
|
+
# Should only show the edited log
|
|
1030
|
+
response = self.client.get(self.url, {"action": "wagtail.edit"})
|
|
1019
1031
|
self.assertEqual(response.status_code, 200)
|
|
1032
|
+
soup = self.get_soup(response.content)
|
|
1033
|
+
rows = soup.select("#listing-results tbody tr")
|
|
1020
1034
|
self.assertEqual(len(rows), 1)
|
|
1021
1035
|
self.assertEqual(rows[0].select_one("td").text.strip(), "Edited")
|
|
1022
1036
|
|
|
1037
|
+
# Should only show the created log
|
|
1023
1038
|
response = self.client.get(self.url, {"action": "wagtail.create"})
|
|
1039
|
+
self.assertEqual(response.status_code, 200)
|
|
1024
1040
|
soup = self.get_soup(response.content)
|
|
1025
|
-
rows = soup.select("tbody tr")
|
|
1041
|
+
rows = soup.select("#listing-results tbody tr")
|
|
1026
1042
|
heading = soup.select_one('h2[role="alert"]')
|
|
1027
|
-
self.assertEqual(response.status_code, 200)
|
|
1028
1043
|
self.assertEqual(heading.string.strip(), "There is 1 match")
|
|
1029
1044
|
self.assertEqual(len(rows), 1)
|
|
1030
1045
|
self.assertEqual(rows[0].select_one("td").text.strip(), "Created")
|
|
1031
1046
|
|
|
1047
|
+
# Should display the heading when there are results
|
|
1048
|
+
heading = soup.select_one('h2[role="alert"]')
|
|
1049
|
+
self.assertEqual(heading.string.strip(), "There is 1 match")
|
|
1050
|
+
|
|
1051
|
+
response = self.client.get(
|
|
1052
|
+
self.url,
|
|
1053
|
+
{"action": ["wagtail.create", "wagtail.edit"]},
|
|
1054
|
+
)
|
|
1055
|
+
self.assertEqual(response.status_code, 200)
|
|
1056
|
+
self.assertEqual(len(response.context["object_list"]), 2)
|
|
1057
|
+
|
|
1058
|
+
def test_user_filter(self):
|
|
1059
|
+
# A user who absolutely has no permissions to the model
|
|
1060
|
+
self.create_user("no_power")
|
|
1061
|
+
|
|
1062
|
+
# A user who has permissions to the model,
|
|
1063
|
+
# but only has logs for a different object
|
|
1064
|
+
has_power = self.create_superuser("has_power")
|
|
1065
|
+
other_obj = FeatureCompleteToy.objects.create(name="Woody")
|
|
1066
|
+
log(
|
|
1067
|
+
instance=other_obj,
|
|
1068
|
+
action="wagtail.create",
|
|
1069
|
+
content_changed=True,
|
|
1070
|
+
user=has_power,
|
|
1071
|
+
)
|
|
1072
|
+
|
|
1073
|
+
# A user who does not have permissions to the model,
|
|
1074
|
+
# but has logs for the object (e.g. maybe they used to have permissions)
|
|
1075
|
+
previously_has_power = self.create_user("previously_has_power")
|
|
1076
|
+
log(
|
|
1077
|
+
instance=self.object,
|
|
1078
|
+
action="wagtail.edit",
|
|
1079
|
+
content_changed=True,
|
|
1080
|
+
user=previously_has_power,
|
|
1081
|
+
)
|
|
1082
|
+
|
|
1083
|
+
response = self.client.get(self.url)
|
|
1084
|
+
self.assertEqual(response.status_code, 200)
|
|
1085
|
+
soup = self.get_soup(response.content)
|
|
1086
|
+
|
|
1087
|
+
# Should only show the current user and the previously_has_power user
|
|
1088
|
+
options = soup.select('input[name="user"][type="checkbox"]')
|
|
1089
|
+
self.assertEqual(len(options), 2)
|
|
1090
|
+
self.assertEqual(
|
|
1091
|
+
{option.attrs.get("value") for option in options},
|
|
1092
|
+
{str(self.user.pk), str(previously_has_power.pk)},
|
|
1093
|
+
)
|
|
1094
|
+
|
|
1095
|
+
response = self.client.get(self.url, {"user": str(self.user.pk)})
|
|
1096
|
+
self.assertEqual(response.status_code, 200)
|
|
1097
|
+
self.assertEqual(len(response.context["object_list"]), 2)
|
|
1098
|
+
|
|
1099
|
+
response = self.client.get(self.url, {"user": str(previously_has_power.pk)})
|
|
1100
|
+
self.assertEqual(response.status_code, 200)
|
|
1101
|
+
self.assertEqual(len(response.context["object_list"]), 1)
|
|
1102
|
+
|
|
1103
|
+
# Should allow filtering by multiple users
|
|
1104
|
+
response = self.client.get(
|
|
1105
|
+
self.url,
|
|
1106
|
+
{"user": [str(self.user.pk), str(previously_has_power.pk)]},
|
|
1107
|
+
)
|
|
1108
|
+
self.assertEqual(response.status_code, 200)
|
|
1109
|
+
self.assertEqual(len(response.context["object_list"]), 3)
|
|
1110
|
+
|
|
1032
1111
|
def test_filtered_no_results(self):
|
|
1033
|
-
response = self.client.get(self.url, {"
|
|
1112
|
+
response = self.client.get(self.url, {"timestamp_to": "2020-01-01"})
|
|
1034
1113
|
soup = self.get_soup(response.content)
|
|
1035
1114
|
results = soup.select_one("#listing-results")
|
|
1036
|
-
table = soup.select_one("table")
|
|
1115
|
+
table = soup.select_one("#listing-results table")
|
|
1037
1116
|
p = results.select_one("p")
|
|
1038
1117
|
self.assertEqual(response.status_code, 200)
|
|
1039
1118
|
self.assertIsNotNone(results)
|
|
@@ -1046,12 +1125,25 @@ class TestHistoryView(WagtailTestUtils, TestCase):
|
|
|
1046
1125
|
response = self.client.get(self.url)
|
|
1047
1126
|
soup = self.get_soup(response.content)
|
|
1048
1127
|
results = soup.select_one("#listing-results")
|
|
1049
|
-
table = soup.select_one("table")
|
|
1128
|
+
table = soup.select_one("#listing-results table")
|
|
1050
1129
|
self.assertEqual(response.status_code, 200)
|
|
1051
1130
|
self.assertIsNotNone(results)
|
|
1052
1131
|
self.assertEqual(results.text.strip(), "There are no log entries to display.")
|
|
1053
1132
|
self.assertIsNone(table)
|
|
1054
1133
|
|
|
1134
|
+
# Should hide the action and user filters as there are no choices for
|
|
1135
|
+
# these filters (since the choices are based on the current queryset)
|
|
1136
|
+
action_inputs = soup.select('input[name="action"]')
|
|
1137
|
+
self.assertEqual(len(action_inputs), 0)
|
|
1138
|
+
user_inputs = soup.select('input[name="user"]')
|
|
1139
|
+
self.assertEqual(len(user_inputs), 0)
|
|
1140
|
+
|
|
1141
|
+
# Should still render the timestamp filter as it is always available
|
|
1142
|
+
timestamp_before_input = soup.select_one('input[name="timestamp_to"]')
|
|
1143
|
+
self.assertIsNotNone(timestamp_before_input)
|
|
1144
|
+
timestamp_after_input = soup.select_one('input[name="timestamp_from"]')
|
|
1145
|
+
self.assertIsNotNone(timestamp_after_input)
|
|
1146
|
+
|
|
1055
1147
|
def test_edit_view_links_to_history_view(self):
|
|
1056
1148
|
edit_url = reverse("feature_complete_toy:edit", args=(quote(self.object.pk),))
|
|
1057
1149
|
response = self.client.get(edit_url)
|
|
@@ -1060,6 +1152,19 @@ class TestHistoryView(WagtailTestUtils, TestCase):
|
|
|
1060
1152
|
history_link = header.find("a", attrs={"href": self.url})
|
|
1061
1153
|
self.assertIsNotNone(history_link)
|
|
1062
1154
|
|
|
1155
|
+
def test_deleted_user(self):
|
|
1156
|
+
to_be_deleted = self.create_user("to_be_deleted")
|
|
1157
|
+
user_id = to_be_deleted.pk
|
|
1158
|
+
log(
|
|
1159
|
+
instance=self.object,
|
|
1160
|
+
action="wagtail.edit",
|
|
1161
|
+
content_changed=True,
|
|
1162
|
+
user=to_be_deleted,
|
|
1163
|
+
)
|
|
1164
|
+
to_be_deleted.delete()
|
|
1165
|
+
response = self.client.get(self.url)
|
|
1166
|
+
self.assertContains(response, f"user {user_id} (deleted)")
|
|
1167
|
+
|
|
1063
1168
|
|
|
1064
1169
|
class TestUsageView(WagtailTestUtils, TestCase):
|
|
1065
1170
|
@classmethod
|
|
@@ -1085,7 +1190,7 @@ class TestUsageView(WagtailTestUtils, TestCase):
|
|
|
1085
1190
|
h1 = soup.select_one("h1")
|
|
1086
1191
|
self.assertEqual(h1.text.strip(), f"Usage: {self.object}")
|
|
1087
1192
|
|
|
1088
|
-
tds = soup.select("tbody tr td")
|
|
1193
|
+
tds = soup.select("#listing-results tbody tr td")
|
|
1089
1194
|
self.assertEqual(len(tds), 3)
|
|
1090
1195
|
self.assertEqual(tds[0].text.strip(), str(self.tbx))
|
|
1091
1196
|
self.assertEqual(tds[1].text.strip(), "Various on delete model")
|
|
@@ -1133,7 +1238,7 @@ class TestUsageView(WagtailTestUtils, TestCase):
|
|
|
1133
1238
|
h1 = soup.select_one("h1")
|
|
1134
1239
|
self.assertEqual(h1.text.strip(), f"Usage: {self.object}")
|
|
1135
1240
|
|
|
1136
|
-
tds = soup.select("tbody tr td")
|
|
1241
|
+
tds = soup.select("#listing-results tbody tr td")
|
|
1137
1242
|
self.assertEqual(len(tds), 3)
|
|
1138
1243
|
self.assertEqual(tds[0].text.strip(), "(Private various on delete model)")
|
|
1139
1244
|
self.assertEqual(tds[1].text.strip(), "Various on delete model")
|
|
@@ -1155,7 +1260,7 @@ class TestUsageView(WagtailTestUtils, TestCase):
|
|
|
1155
1260
|
h1 = soup.select_one("h1")
|
|
1156
1261
|
self.assertEqual(h1.text.strip(), f"Usage: {self.object}")
|
|
1157
1262
|
|
|
1158
|
-
tds = soup.select("tbody tr td")
|
|
1263
|
+
tds = soup.select("#listing-results tbody tr td")
|
|
1159
1264
|
self.assertEqual(len(tds), 3)
|
|
1160
1265
|
self.assertEqual(tds[0].text.strip(), str(self.tbx))
|
|
1161
1266
|
self.assertEqual(tds[1].text.strip(), "Various on delete model")
|
|
@@ -1181,7 +1286,7 @@ class TestUsageView(WagtailTestUtils, TestCase):
|
|
|
1181
1286
|
response = self.client.get(self.url)
|
|
1182
1287
|
soup = self.get_soup(response.content)
|
|
1183
1288
|
results = soup.select_one("#listing-results")
|
|
1184
|
-
table = soup.select_one("table")
|
|
1289
|
+
table = soup.select_one("#listing-results table")
|
|
1185
1290
|
self.assertEqual(response.status_code, 200)
|
|
1186
1291
|
self.assertIsNotNone(results)
|
|
1187
1292
|
self.assertEqual(results.text.strip(), "There are no results.")
|
|
@@ -1426,14 +1531,11 @@ class TestCopyView(WagtailTestUtils, TestCase):
|
|
|
1426
1531
|
self.assertRedirects(response, reverse("wagtailadmin_home"))
|
|
1427
1532
|
|
|
1428
1533
|
def test_form_is_prefilled(self):
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
view.kwargs = {"pk": self.object.pk}
|
|
1435
|
-
|
|
1436
|
-
self.assertEqual(view.get_form_kwargs()["instance"], self.object)
|
|
1534
|
+
response = self.client.get(self.url)
|
|
1535
|
+
self.assertEqual(response.status_code, 200)
|
|
1536
|
+
soup = self.get_soup(response.content)
|
|
1537
|
+
name_input = soup.select_one('input[name="name"]')
|
|
1538
|
+
self.assertEqual(name_input.attrs.get("value"), "Test Toy")
|
|
1437
1539
|
|
|
1438
1540
|
|
|
1439
1541
|
class TestEditHandler(WagtailTestUtils, TestCase):
|
|
@@ -1469,11 +1571,6 @@ class TestEditHandler(WagtailTestUtils, TestCase):
|
|
|
1469
1571
|
self.assertIsNotNone(rendered_heading)
|
|
1470
1572
|
self.assertEqual(rendered_heading.text.strip(), expected_heading)
|
|
1471
1573
|
|
|
1472
|
-
# Ensure modal-workflow.js is included, as it's needed by choosers
|
|
1473
|
-
modal_workflow_js = versioned_static("wagtailadmin/js/modal-workflow.js")
|
|
1474
|
-
modal_workflow_script = soup.select_one(f'script[src="{modal_workflow_js}"]')
|
|
1475
|
-
self.assertIsNotNone(modal_workflow_script)
|
|
1476
|
-
|
|
1477
1574
|
|
|
1478
1575
|
class TestDefaultMessages(WagtailTestUtils, TestCase):
|
|
1479
1576
|
def setUp(self):
|
wagtail/admin/ui/side_panels.py
CHANGED
|
@@ -15,6 +15,7 @@ class BaseSidePanel(Component):
|
|
|
15
15
|
icon_name = ""
|
|
16
16
|
has_counter = True
|
|
17
17
|
counter_classname = ""
|
|
18
|
+
keyboard_shortcut = None
|
|
18
19
|
|
|
19
20
|
def __init__(self, panel):
|
|
20
21
|
self.panel = panel
|
|
@@ -229,7 +230,7 @@ class StatusSidePanel(BaseSidePanel):
|
|
|
229
230
|
context["last_updated_info"] = self.last_updated_info
|
|
230
231
|
context.update(self.get_scheduled_publishing_context(parent_context))
|
|
231
232
|
context.update(self.get_lock_context(parent_context))
|
|
232
|
-
if self.object.pk:
|
|
233
|
+
if self.object.pk and self.usage_url:
|
|
233
234
|
context.update(self.get_usage_context())
|
|
234
235
|
return context
|
|
235
236
|
|
|
@@ -338,6 +339,7 @@ class PreviewSidePanel(BaseSidePanel):
|
|
|
338
339
|
aria_label = gettext_lazy("Toggle preview")
|
|
339
340
|
icon_name = "mobile-alt"
|
|
340
341
|
has_counter = False
|
|
342
|
+
keyboard_shortcut = "mod+p"
|
|
341
343
|
|
|
342
344
|
name = "preview"
|
|
343
345
|
title = gettext_lazy("Preview")
|
|
@@ -149,7 +149,10 @@ class Column(BaseColumn):
|
|
|
149
149
|
if callable(self.accessor):
|
|
150
150
|
return self.accessor(instance)
|
|
151
151
|
else:
|
|
152
|
-
|
|
152
|
+
try:
|
|
153
|
+
return multigetattr(instance, self.accessor)
|
|
154
|
+
except AttributeError:
|
|
155
|
+
return None
|
|
153
156
|
|
|
154
157
|
def get_cell_context_data(self, instance, parent_context):
|
|
155
158
|
context = super().get_cell_context_data(instance, parent_context)
|
|
@@ -393,6 +396,15 @@ class DownloadColumn(Column):
|
|
|
393
396
|
return context
|
|
394
397
|
|
|
395
398
|
|
|
399
|
+
class RelatedObjectsColumn(Column):
|
|
400
|
+
"""Outputs a list of objects related to the object through a one-to-many relationship"""
|
|
401
|
+
|
|
402
|
+
cell_template_name = "wagtailadmin/tables/related_objects_cell.html"
|
|
403
|
+
|
|
404
|
+
def get_value(self, instance):
|
|
405
|
+
return getattr(instance, self.accessor).all()
|
|
406
|
+
|
|
407
|
+
|
|
396
408
|
class Table(Component):
|
|
397
409
|
template_name = "wagtailadmin/tables/table.html"
|
|
398
410
|
classname = "listing"
|
wagtail/admin/ui/tables/pages.py
CHANGED
|
@@ -11,14 +11,24 @@ class PageTitleColumn(BaseColumn):
|
|
|
11
11
|
|
|
12
12
|
def get_header_context_data(self, parent_context):
|
|
13
13
|
context = super().get_header_context_data(parent_context)
|
|
14
|
+
parent_page = parent_context.get("parent_page")
|
|
15
|
+
|
|
14
16
|
context["items_count"] = parent_context.get("items_count")
|
|
15
17
|
context["page_obj"] = parent_context.get("page_obj")
|
|
16
|
-
context["parent_page"] =
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
context["parent_page"] = parent_page
|
|
19
|
+
|
|
20
|
+
if parent_page and (
|
|
21
|
+
parent_context.get("is_searching") or parent_context.get("is_filtering")
|
|
22
|
+
):
|
|
23
|
+
# Results are switchable between searching the whole tree and searching just this parent.
|
|
24
|
+
# Add extra signposting to show which scope we're in, and provide a link to switch scope.
|
|
25
|
+
if parent_context.get("is_searching_whole_tree"):
|
|
26
|
+
context["result_scope"] = "whole_tree"
|
|
27
|
+
else:
|
|
28
|
+
context["result_scope"] = "parent"
|
|
29
|
+
else:
|
|
30
|
+
# No signposting needed
|
|
31
|
+
context["result_scope"] = None
|
|
22
32
|
|
|
23
33
|
# If results are not paginated e.g. when using the OrderingColumn,
|
|
24
34
|
# all items are displayed on the page
|
|
@@ -27,6 +37,7 @@ class PageTitleColumn(BaseColumn):
|
|
|
27
37
|
if context["page_obj"]:
|
|
28
38
|
context["start_index"] = context["page_obj"].start_index()
|
|
29
39
|
context["end_index"] = context["page_obj"].end_index()
|
|
40
|
+
|
|
30
41
|
return context
|
|
31
42
|
|
|
32
43
|
def get_cell_context_data(self, instance, parent_context):
|
wagtail/admin/urls/__init__.py
CHANGED
|
@@ -28,15 +28,19 @@ urlpatterns = [
|
|
|
28
28
|
path("api/", include(api_urls)),
|
|
29
29
|
path("failwhale/", home.error_test, name="wagtailadmin_error_test"),
|
|
30
30
|
# TODO: Move into wagtailadmin_pages namespace
|
|
31
|
-
path(
|
|
31
|
+
path(
|
|
32
|
+
"pages/",
|
|
33
|
+
listing.ExplorableIndexView.as_view(),
|
|
34
|
+
name="wagtailadmin_explore_root",
|
|
35
|
+
),
|
|
32
36
|
path(
|
|
33
37
|
"pages/<int:parent_page_id>/",
|
|
34
|
-
listing.
|
|
38
|
+
listing.ExplorableIndexView.as_view(),
|
|
35
39
|
name="wagtailadmin_explore",
|
|
36
40
|
),
|
|
37
41
|
path(
|
|
38
42
|
"pages/<int:parent_page_id>/results/",
|
|
39
|
-
listing.
|
|
43
|
+
listing.ExplorableIndexView.as_view(results_only=True),
|
|
40
44
|
name="wagtailadmin_explore_results",
|
|
41
45
|
),
|
|
42
46
|
# bulk actions
|
|
@@ -127,6 +131,7 @@ def get_sprite_hash():
|
|
|
127
131
|
global sprite_hash
|
|
128
132
|
if not sprite_hash:
|
|
129
133
|
content = str(home.sprite(None).content, "utf-8")
|
|
134
|
+
# SECRET_KEY is used to prevent exposing the Wagtail version
|
|
130
135
|
sprite_hash = hashlib.sha1(
|
|
131
136
|
(content + settings.SECRET_KEY).encode("utf-8")
|
|
132
137
|
).hexdigest()[:8]
|
wagtail/admin/urls/pages.py
CHANGED
|
@@ -121,4 +121,9 @@ urlpatterns = [
|
|
|
121
121
|
name="workflow_history_detail",
|
|
122
122
|
),
|
|
123
123
|
path("<int:page_id>/history/", history.PageHistoryView.as_view(), name="history"),
|
|
124
|
+
path(
|
|
125
|
+
"<int:page_id>/history/results/",
|
|
126
|
+
history.PageHistoryView.as_view(results_only=True),
|
|
127
|
+
name="history_results",
|
|
128
|
+
),
|
|
124
129
|
]
|
wagtail/admin/urls/workflows.py
CHANGED
|
@@ -5,6 +5,11 @@ from wagtail.admin.views import workflows
|
|
|
5
5
|
app_name = "wagtailadmin_workflows"
|
|
6
6
|
urlpatterns = [
|
|
7
7
|
path("list/", workflows.Index.as_view(), name="index"),
|
|
8
|
+
path(
|
|
9
|
+
"list/results/",
|
|
10
|
+
workflows.Index.as_view(results_only=True),
|
|
11
|
+
name="index_results",
|
|
12
|
+
),
|
|
8
13
|
path("add/", workflows.Create.as_view(), name="add"),
|
|
9
14
|
path("enable/<int:pk>/", workflows.enable_workflow, name="enable"),
|
|
10
15
|
path("disable/<int:pk>/", workflows.Disable.as_view(), name="disable"),
|
|
@@ -23,6 +28,11 @@ urlpatterns = [
|
|
|
23
28
|
),
|
|
24
29
|
path("tasks/select_type/", workflows.select_task_type, name="select_task_type"),
|
|
25
30
|
path("tasks/index/", workflows.TaskIndex.as_view(), name="task_index"),
|
|
31
|
+
path(
|
|
32
|
+
"tasks/index/results/",
|
|
33
|
+
workflows.TaskIndex.as_view(results_only=True),
|
|
34
|
+
name="task_index_results",
|
|
35
|
+
),
|
|
26
36
|
path("tasks/edit/<int:pk>/", workflows.EditTask.as_view(), name="edit_task"),
|
|
27
37
|
path(
|
|
28
38
|
"tasks/disable/<int:pk>/", workflows.DisableTask.as_view(), name="disable_task"
|
wagtail/admin/views/chooser.py
CHANGED
|
@@ -7,7 +7,6 @@ from django.http import Http404
|
|
|
7
7
|
from django.shortcuts import get_object_or_404
|
|
8
8
|
from django.template.response import TemplateResponse
|
|
9
9
|
from django.urls.base import reverse
|
|
10
|
-
from django.utils.http import urlencode
|
|
11
10
|
from django.utils.translation import gettext_lazy as _
|
|
12
11
|
from django.views.generic.base import View
|
|
13
12
|
|
|
@@ -93,7 +92,7 @@ def can_choose_page(
|
|
|
93
92
|
|
|
94
93
|
if user_perm == "move_to":
|
|
95
94
|
return page_to_move.permissions_for_user(user).can_move_to(page)
|
|
96
|
-
if user_perm
|
|
95
|
+
if user_perm in {"add_subpage", "copy_to"}:
|
|
97
96
|
return page.permissions_for_user(user).can_add_subpage()
|
|
98
97
|
|
|
99
98
|
return True
|
|
@@ -286,6 +285,11 @@ class BrowseView(View):
|
|
|
286
285
|
selected_locale = None
|
|
287
286
|
locale_options = []
|
|
288
287
|
if self.i18n_enabled:
|
|
288
|
+
# Ensure query parameters (e.g. `page_type`, `user_perms`, etc.) are
|
|
289
|
+
# preserved when switching locales, but reset the pagination as the
|
|
290
|
+
# number of pages might be different.
|
|
291
|
+
new_params = request.GET.copy()
|
|
292
|
+
new_params.pop("p", None)
|
|
289
293
|
if self.parent_page.is_root():
|
|
290
294
|
# 'locale' is the current value of the "Locale" selector in the UI
|
|
291
295
|
if request.GET.get("locale"):
|
|
@@ -298,25 +302,20 @@ class BrowseView(View):
|
|
|
298
302
|
|
|
299
303
|
# we are at the Root level, so get the locales from the current pages
|
|
300
304
|
choose_url = reverse("wagtailadmin_choose_page")
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
),
|
|
312
|
-
}
|
|
313
|
-
for locale in Locale.objects.filter(
|
|
314
|
-
pk__in=pages.values_list("locale_id")
|
|
315
|
-
).exclude(pk=active_locale_id)
|
|
316
|
-
]
|
|
305
|
+
for locale in Locale.objects.filter(
|
|
306
|
+
pk__in=pages.values_list("locale_id")
|
|
307
|
+
).exclude(pk=active_locale_id):
|
|
308
|
+
new_params["locale"] = locale.language_code
|
|
309
|
+
locale_options.append(
|
|
310
|
+
{
|
|
311
|
+
"locale": locale,
|
|
312
|
+
"url": choose_url + "?" + new_params.urlencode(),
|
|
313
|
+
}
|
|
314
|
+
)
|
|
317
315
|
else:
|
|
318
316
|
# We have a parent page (that is not the root page). Use its locale as the selected localer
|
|
319
317
|
selected_locale = self.parent_page.locale
|
|
318
|
+
new_params.pop("locale", None)
|
|
320
319
|
# and get the locales based on its available translations
|
|
321
320
|
locales_and_parent_pages = {
|
|
322
321
|
item["locale"]: item["pk"]
|
|
@@ -332,17 +331,14 @@ class BrowseView(View):
|
|
|
332
331
|
"wagtailadmin_choose_page_child",
|
|
333
332
|
args=[locales_and_parent_pages[locale.pk]],
|
|
334
333
|
)
|
|
335
|
-
|
|
336
334
|
locale_options.append(
|
|
337
335
|
{
|
|
338
336
|
"locale": locale,
|
|
339
|
-
"url": choose_child_url
|
|
340
|
-
+ "?"
|
|
341
|
-
+ urlencode({"page_type": page_type_string}),
|
|
337
|
+
"url": choose_child_url + "?" + new_params.urlencode(),
|
|
342
338
|
}
|
|
343
339
|
)
|
|
344
340
|
|
|
345
|
-
# finally, filter the
|
|
341
|
+
# finally, filter the browsable pages on the selected locale
|
|
346
342
|
if selected_locale:
|
|
347
343
|
pages = pages.filter(locale=selected_locale)
|
|
348
344
|
|
|
@@ -355,7 +351,7 @@ class BrowseView(View):
|
|
|
355
351
|
except InvalidPage:
|
|
356
352
|
raise Http404
|
|
357
353
|
|
|
358
|
-
# Annotate each page with can_choose/
|
|
354
|
+
# Annotate each page with can_choose/can_descend flags
|
|
359
355
|
for page in pages:
|
|
360
356
|
page.can_choose = can_choose_page(
|
|
361
357
|
page,
|
|
@@ -5,6 +5,7 @@ from django.utils.translation import gettext_lazy
|
|
|
5
5
|
from wagtail import hooks
|
|
6
6
|
from wagtail.admin import messages
|
|
7
7
|
from wagtail.admin.forms.collections import CollectionForm
|
|
8
|
+
from wagtail.admin.ui.tables import TitleColumn
|
|
8
9
|
from wagtail.admin.views.generic import CreateView, DeleteView, EditView, IndexView
|
|
9
10
|
from wagtail.models import Collection
|
|
10
11
|
from wagtail.permissions import collection_permission_policy
|
|
@@ -14,18 +15,31 @@ class Index(IndexView):
|
|
|
14
15
|
permission_policy = collection_permission_policy
|
|
15
16
|
model = Collection
|
|
16
17
|
context_object_name = "collections"
|
|
17
|
-
|
|
18
|
+
results_template_name = "wagtailadmin/collections/index_results.html"
|
|
18
19
|
add_url_name = "wagtailadmin_collections:add"
|
|
19
20
|
index_url_name = "wagtailadmin_collections:index"
|
|
20
21
|
page_title = gettext_lazy("Collections")
|
|
21
22
|
add_item_label = gettext_lazy("Add a collection")
|
|
22
23
|
header_icon = "folder-open-1"
|
|
24
|
+
columns = [
|
|
25
|
+
TitleColumn(
|
|
26
|
+
"name",
|
|
27
|
+
label=gettext_lazy("Name"),
|
|
28
|
+
url_name="wagtailadmin_collections:edit",
|
|
29
|
+
id_accessor="0",
|
|
30
|
+
accessor="1",
|
|
31
|
+
)
|
|
32
|
+
]
|
|
33
|
+
_show_breadcrumbs = True
|
|
23
34
|
|
|
24
35
|
def get_queryset(self):
|
|
25
36
|
return self.permission_policy.instances_user_has_any_permission_for(
|
|
26
37
|
self.request.user, ["add", "change", "delete"]
|
|
27
38
|
).exclude(depth=1)
|
|
28
39
|
|
|
40
|
+
def get_table(self, object_list):
|
|
41
|
+
return super().get_table(object_list.get_indented_choices())
|
|
42
|
+
|
|
29
43
|
|
|
30
44
|
class Create(CreateView):
|
|
31
45
|
permission_policy = collection_permission_policy
|
|
@@ -37,6 +51,7 @@ class Create(CreateView):
|
|
|
37
51
|
edit_url_name = "wagtailadmin_collections:edit"
|
|
38
52
|
index_url_name = "wagtailadmin_collections:index"
|
|
39
53
|
header_icon = "folder-open-1"
|
|
54
|
+
_show_breadcrumbs = True
|
|
40
55
|
|
|
41
56
|
def get_form(self, form_class=None):
|
|
42
57
|
form = super().get_form(form_class)
|
|
@@ -67,6 +82,7 @@ class Edit(EditView):
|
|
|
67
82
|
delete_url_name = "wagtailadmin_collections:delete"
|
|
68
83
|
context_object_name = "collection"
|
|
69
84
|
header_icon = "folder-open-1"
|
|
85
|
+
_show_breadcrumbs = True
|
|
70
86
|
|
|
71
87
|
def _user_may_move_collection(self, user, instance):
|
|
72
88
|
"""
|