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,6 +2,7 @@ import json
|
|
|
2
2
|
from unittest import mock
|
|
3
3
|
|
|
4
4
|
from django.contrib.auth.models import Group, Permission
|
|
5
|
+
from django.contrib.contenttypes.models import ContentType
|
|
5
6
|
from django.core.files.uploadedfile import SimpleUploadedFile
|
|
6
7
|
from django.test import TestCase, TransactionTestCase
|
|
7
8
|
from django.test.utils import override_settings
|
|
@@ -12,7 +13,13 @@ from django.utils.http import urlencode
|
|
|
12
13
|
from wagtail.admin.admin_url_finder import AdminURLFinder
|
|
13
14
|
from wagtail.documents import get_document_model, models
|
|
14
15
|
from wagtail.documents.tests.utils import get_test_document_file
|
|
15
|
-
from wagtail.models import
|
|
16
|
+
from wagtail.models import (
|
|
17
|
+
Collection,
|
|
18
|
+
GroupCollectionPermission,
|
|
19
|
+
Page,
|
|
20
|
+
ReferenceIndex,
|
|
21
|
+
UploadedFile,
|
|
22
|
+
)
|
|
16
23
|
from wagtail.test.testapp.models import (
|
|
17
24
|
CustomDocument,
|
|
18
25
|
CustomDocumentWithAuthor,
|
|
@@ -86,6 +93,9 @@ class TestDocumentIndexView(WagtailTestUtils, TestCase):
|
|
|
86
93
|
response = self.get()
|
|
87
94
|
self.assertNotContains(response, "<th>Collection</th>", html=True)
|
|
88
95
|
self.assertNotContains(response, "<td>Root</td>", html=True)
|
|
96
|
+
soup = self.get_soup(response.content)
|
|
97
|
+
collection_select = soup.select_one('select[name="collection_id"]')
|
|
98
|
+
self.assertIsNone(collection_select)
|
|
89
99
|
|
|
90
100
|
def test_index_with_collection(self):
|
|
91
101
|
root_collection = Collection.get_first_root_node()
|
|
@@ -97,8 +107,18 @@ class TestDocumentIndexView(WagtailTestUtils, TestCase):
|
|
|
97
107
|
response = self.get()
|
|
98
108
|
self.assertContains(response, "<th>Collection</th>", html=True)
|
|
99
109
|
self.assertContains(response, "<td>Root</td>", html=True)
|
|
110
|
+
|
|
111
|
+
response = self.get()
|
|
112
|
+
soup = self.get_soup(response.content)
|
|
113
|
+
collection_options = soup.select(
|
|
114
|
+
'select[name="collection_id"] option[value]:not(option[value=""])'
|
|
115
|
+
)
|
|
116
|
+
|
|
100
117
|
self.assertEqual(
|
|
101
|
-
[
|
|
118
|
+
[
|
|
119
|
+
collection.get_text(strip=True).lstrip("↳ ")
|
|
120
|
+
for collection in collection_options
|
|
121
|
+
],
|
|
102
122
|
["Root", "Evil plans", "Good plans"],
|
|
103
123
|
)
|
|
104
124
|
|
|
@@ -162,7 +182,7 @@ class TestDocumentIndexView(WagtailTestUtils, TestCase):
|
|
|
162
182
|
def test_search_form_rendered(self):
|
|
163
183
|
response = self.get()
|
|
164
184
|
html = response.content.decode()
|
|
165
|
-
search_url = reverse("wagtaildocs:
|
|
185
|
+
search_url = reverse("wagtaildocs:index_results")
|
|
166
186
|
|
|
167
187
|
# Search form in the header should be rendered.
|
|
168
188
|
self.assertTagInHTML(
|
|
@@ -172,6 +192,101 @@ class TestDocumentIndexView(WagtailTestUtils, TestCase):
|
|
|
172
192
|
allow_extra_attrs=True,
|
|
173
193
|
)
|
|
174
194
|
|
|
195
|
+
def test_tags(self):
|
|
196
|
+
document_two_tags = models.Document.objects.create(
|
|
197
|
+
title="Test document with two tags"
|
|
198
|
+
)
|
|
199
|
+
document_two_tags.tags.add("one", "two")
|
|
200
|
+
|
|
201
|
+
response = self.get()
|
|
202
|
+
self.assertEqual(response.status_code, 200)
|
|
203
|
+
|
|
204
|
+
soup = self.get_soup(response.content)
|
|
205
|
+
current_tags = soup.select("input[name=tag][checked]")
|
|
206
|
+
self.assertFalse(current_tags)
|
|
207
|
+
|
|
208
|
+
tags = soup.select("#id_tag label")
|
|
209
|
+
self.assertCountEqual(
|
|
210
|
+
[tags.get_text(strip=True) for tags in tags],
|
|
211
|
+
["one", "two"],
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
def test_tag_filtering(self):
|
|
215
|
+
models.Document.objects.create(title="Test document with no tags")
|
|
216
|
+
|
|
217
|
+
document_one_tag = models.Document.objects.create(
|
|
218
|
+
title="Test document with one tag"
|
|
219
|
+
)
|
|
220
|
+
document_one_tag.tags.add("one")
|
|
221
|
+
|
|
222
|
+
document_two_tags = models.Document.objects.create(
|
|
223
|
+
title="Test document with two tags"
|
|
224
|
+
)
|
|
225
|
+
document_two_tags.tags.add("one", "two")
|
|
226
|
+
|
|
227
|
+
document_unrelated_tag = models.Document.objects.create(
|
|
228
|
+
title="Test document with a different tag"
|
|
229
|
+
)
|
|
230
|
+
document_unrelated_tag.tags.add("unrelated")
|
|
231
|
+
|
|
232
|
+
# no filtering
|
|
233
|
+
response = self.get()
|
|
234
|
+
# four documents created above
|
|
235
|
+
self.assertEqual(response.context["page_obj"].paginator.count, 4)
|
|
236
|
+
|
|
237
|
+
# filter all documents with tag 'one'
|
|
238
|
+
response = self.get({"tag": "one"})
|
|
239
|
+
self.assertEqual(response.context["page_obj"].paginator.count, 2)
|
|
240
|
+
|
|
241
|
+
# filter all documents with tag 'two'
|
|
242
|
+
response = self.get({"tag": "two"})
|
|
243
|
+
self.assertEqual(response.context["page_obj"].paginator.count, 1)
|
|
244
|
+
|
|
245
|
+
# filter all documents with tag 'one' or 'unrelated'
|
|
246
|
+
response = self.get({"tag": ["one", "unrelated"]})
|
|
247
|
+
self.assertEqual(response.context["page_obj"].paginator.count, 3)
|
|
248
|
+
|
|
249
|
+
soup = self.get_soup(response.content)
|
|
250
|
+
|
|
251
|
+
# Should check the 'one' and 'unrelated' tags checkboxes
|
|
252
|
+
tags = soup.select("#id_tag label")
|
|
253
|
+
self.assertCountEqual(
|
|
254
|
+
[
|
|
255
|
+
tag.get_text(strip=True)
|
|
256
|
+
for tag in tags
|
|
257
|
+
if tag.select_one("input[checked]") is not None
|
|
258
|
+
],
|
|
259
|
+
["one", "unrelated"],
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
# Should render the active filter pills separately for each tag
|
|
263
|
+
active_filters = soup.select('[data-w-active-filter-id="id_tag"]')
|
|
264
|
+
self.assertCountEqual(
|
|
265
|
+
[filter.get_text(separator=" ", strip=True) for filter in active_filters],
|
|
266
|
+
["Tag: one", "Tag: unrelated"],
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
def test_tag_filtering_preserves_other_params(self):
|
|
270
|
+
for i in range(1, 130):
|
|
271
|
+
document = models.Document.objects.create(title="Test document %i" % i)
|
|
272
|
+
if i % 2 != 0:
|
|
273
|
+
document.tags.add("even")
|
|
274
|
+
document.save()
|
|
275
|
+
|
|
276
|
+
response = self.get({"tag": "even", "p": 2})
|
|
277
|
+
self.assertEqual(response.status_code, 200)
|
|
278
|
+
|
|
279
|
+
response_body = response.content.decode("utf8")
|
|
280
|
+
|
|
281
|
+
# prev link should exist and include tag
|
|
282
|
+
self.assertTrue(
|
|
283
|
+
"?p=1&tag=even" in response_body or "?tag=even&p=1" in response_body
|
|
284
|
+
)
|
|
285
|
+
# next link should exist and include tag
|
|
286
|
+
self.assertTrue(
|
|
287
|
+
"?p=3&tag=even" in response_body or "?tag=even&p=3" in response_body
|
|
288
|
+
)
|
|
289
|
+
|
|
175
290
|
|
|
176
291
|
class TestDocumentIndexViewSearch(WagtailTestUtils, TransactionTestCase):
|
|
177
292
|
def setUp(self):
|
|
@@ -225,6 +340,24 @@ class TestDocumentIndexViewSearch(WagtailTestUtils, TransactionTestCase):
|
|
|
225
340
|
self.assertTemplateUsed(response, "wagtaildocs/documents/index.html")
|
|
226
341
|
self.assertContains(response, "There are 50 matches")
|
|
227
342
|
|
|
343
|
+
def test_tag_filtering_with_search_term(self):
|
|
344
|
+
models.Document.objects.create(title="Test document with no tags")
|
|
345
|
+
|
|
346
|
+
document_one_tag = models.Document.objects.create(
|
|
347
|
+
title="Test document with one tag"
|
|
348
|
+
)
|
|
349
|
+
document_one_tag.tags.add("one")
|
|
350
|
+
|
|
351
|
+
document_two_tags = models.Document.objects.create(
|
|
352
|
+
title="Test document with two tags"
|
|
353
|
+
)
|
|
354
|
+
document_two_tags.tags.add("one", "two")
|
|
355
|
+
|
|
356
|
+
# The tag shouldn't be ignored, so the result should be the documents
|
|
357
|
+
# that have the "one" tag and "test" in the title.
|
|
358
|
+
response = self.get({"tag": "one", "q": "test"})
|
|
359
|
+
self.assertEqual(response.context["page_obj"].paginator.count, 2)
|
|
360
|
+
|
|
228
361
|
|
|
229
362
|
class TestDocumentIndexResultsView(WagtailTestUtils, TransactionTestCase):
|
|
230
363
|
def setUp(self):
|
|
@@ -1277,15 +1410,16 @@ class TestMultipleCustomDocumentUploaderWithRequiredField(TestMultipleDocumentUp
|
|
|
1277
1410
|
def setUp(self):
|
|
1278
1411
|
super().setUp()
|
|
1279
1412
|
|
|
1280
|
-
# Create an
|
|
1281
|
-
self.uploaded_document =
|
|
1413
|
+
# Create an UploadedFile for running tests on
|
|
1414
|
+
self.uploaded_document = UploadedFile.objects.create(
|
|
1415
|
+
for_content_type=ContentType.objects.get_for_model(get_document_model()),
|
|
1282
1416
|
file=get_test_document_file(),
|
|
1283
1417
|
uploaded_by_user=self.user,
|
|
1284
1418
|
)
|
|
1285
1419
|
|
|
1286
1420
|
def test_add_post(self):
|
|
1287
1421
|
"""
|
|
1288
|
-
This tests that a POST request to the add view saves the document as an
|
|
1422
|
+
This tests that a POST request to the add view saves the document as an UploadedFile
|
|
1289
1423
|
and returns an edit form
|
|
1290
1424
|
"""
|
|
1291
1425
|
response = self.client.post(
|
|
@@ -1326,11 +1460,11 @@ class TestMultipleCustomDocumentUploaderWithRequiredField(TestMultipleDocumentUp
|
|
|
1326
1460
|
|
|
1327
1461
|
# Check JSON
|
|
1328
1462
|
response_json = json.loads(response.content.decode())
|
|
1329
|
-
self.assertIn("
|
|
1463
|
+
self.assertIn("uploaded_file_id", response_json)
|
|
1330
1464
|
self.assertIn("form", response_json)
|
|
1331
1465
|
self.assertIn("success", response_json)
|
|
1332
1466
|
self.assertEqual(
|
|
1333
|
-
response_json["
|
|
1467
|
+
response_json["uploaded_file_id"],
|
|
1334
1468
|
response.context["uploaded_document"].id,
|
|
1335
1469
|
)
|
|
1336
1470
|
self.assertTrue(response_json["success"])
|
|
@@ -1363,10 +1497,10 @@ class TestMultipleCustomDocumentUploaderWithRequiredField(TestMultipleDocumentUp
|
|
|
1363
1497
|
|
|
1364
1498
|
# Check JSON
|
|
1365
1499
|
response_json = json.loads(response.content.decode())
|
|
1366
|
-
self.assertIn("
|
|
1500
|
+
self.assertIn("uploaded_file_id", response_json)
|
|
1367
1501
|
self.assertIn("form", response_json)
|
|
1368
1502
|
self.assertEqual(
|
|
1369
|
-
response_json["
|
|
1503
|
+
response_json["uploaded_file_id"],
|
|
1370
1504
|
response.context["uploaded_document"].id,
|
|
1371
1505
|
)
|
|
1372
1506
|
self.assertTrue(response_json["success"])
|
|
@@ -1419,11 +1553,11 @@ class TestMultipleCustomDocumentUploaderWithRequiredField(TestMultipleDocumentUp
|
|
|
1419
1553
|
|
|
1420
1554
|
# Check JSON
|
|
1421
1555
|
response_json = json.loads(response.content.decode())
|
|
1422
|
-
self.assertIn("
|
|
1556
|
+
self.assertIn("uploaded_file_id", response_json)
|
|
1423
1557
|
self.assertIn("form", response_json)
|
|
1424
1558
|
self.assertIn("success", response_json)
|
|
1425
1559
|
self.assertEqual(
|
|
1426
|
-
response_json["
|
|
1560
|
+
response_json["uploaded_file_id"],
|
|
1427
1561
|
response.context["uploaded_document"].id,
|
|
1428
1562
|
)
|
|
1429
1563
|
self.assertTrue(response_json["success"])
|
|
@@ -1438,10 +1572,10 @@ class TestMultipleCustomDocumentUploaderWithRequiredField(TestMultipleDocumentUp
|
|
|
1438
1572
|
def test_create_from_upload_invalid_post(self):
|
|
1439
1573
|
"""
|
|
1440
1574
|
Posting an invalid form to the create_from_uploaded_document view throws a validation error
|
|
1441
|
-
and leaves the
|
|
1575
|
+
and leaves the UploadedFile intact
|
|
1442
1576
|
"""
|
|
1443
1577
|
doc_count_before = CustomDocumentWithAuthor.objects.count()
|
|
1444
|
-
uploaded_doc_count_before =
|
|
1578
|
+
uploaded_doc_count_before = UploadedFile.objects.count()
|
|
1445
1579
|
|
|
1446
1580
|
# Send request
|
|
1447
1581
|
response = self.client.post(
|
|
@@ -1459,9 +1593,9 @@ class TestMultipleCustomDocumentUploaderWithRequiredField(TestMultipleDocumentUp
|
|
|
1459
1593
|
)
|
|
1460
1594
|
|
|
1461
1595
|
doc_count_after = CustomDocumentWithAuthor.objects.count()
|
|
1462
|
-
uploaded_doc_count_after =
|
|
1596
|
+
uploaded_doc_count_after = UploadedFile.objects.count()
|
|
1463
1597
|
|
|
1464
|
-
# no changes to document /
|
|
1598
|
+
# no changes to document / UploadedFile count
|
|
1465
1599
|
self.assertEqual(doc_count_after, doc_count_before)
|
|
1466
1600
|
self.assertEqual(uploaded_doc_count_after, uploaded_doc_count_before)
|
|
1467
1601
|
|
|
@@ -1497,7 +1631,7 @@ class TestMultipleCustomDocumentUploaderWithRequiredField(TestMultipleDocumentUp
|
|
|
1497
1631
|
Posting a valid form to the create_from_uploaded_document view will create the document
|
|
1498
1632
|
"""
|
|
1499
1633
|
doc_count_before = CustomDocumentWithAuthor.objects.count()
|
|
1500
|
-
uploaded_doc_count_before =
|
|
1634
|
+
uploaded_doc_count_before = UploadedFile.objects.count()
|
|
1501
1635
|
|
|
1502
1636
|
# Send request
|
|
1503
1637
|
response = self.client.post(
|
|
@@ -1519,7 +1653,7 @@ class TestMultipleCustomDocumentUploaderWithRequiredField(TestMultipleDocumentUp
|
|
|
1519
1653
|
)
|
|
1520
1654
|
|
|
1521
1655
|
doc_count_after = CustomDocumentWithAuthor.objects.count()
|
|
1522
|
-
uploaded_doc_count_after =
|
|
1656
|
+
uploaded_doc_count_after = UploadedFile.objects.count()
|
|
1523
1657
|
|
|
1524
1658
|
# Check response
|
|
1525
1659
|
self.assertEqual(response.status_code, 200)
|
|
@@ -1530,7 +1664,7 @@ class TestMultipleCustomDocumentUploaderWithRequiredField(TestMultipleDocumentUp
|
|
|
1530
1664
|
self.assertIn("doc_id", response_json)
|
|
1531
1665
|
self.assertTrue(response_json["success"])
|
|
1532
1666
|
|
|
1533
|
-
# Document should have been created,
|
|
1667
|
+
# Document should have been created, UploadedFile deleted
|
|
1534
1668
|
self.assertEqual(doc_count_after, doc_count_before + 1)
|
|
1535
1669
|
self.assertEqual(uploaded_doc_count_after, uploaded_doc_count_before - 1)
|
|
1536
1670
|
|
|
@@ -1544,7 +1678,7 @@ class TestMultipleCustomDocumentUploaderWithRequiredField(TestMultipleDocumentUp
|
|
|
1544
1678
|
|
|
1545
1679
|
def test_delete_uploaded_document(self):
|
|
1546
1680
|
"""
|
|
1547
|
-
This tests that a POST request to the delete view deletes the
|
|
1681
|
+
This tests that a POST request to the delete view deletes the UploadedFile
|
|
1548
1682
|
"""
|
|
1549
1683
|
# Send request
|
|
1550
1684
|
response = self.client.post(
|
|
@@ -1559,9 +1693,7 @@ class TestMultipleCustomDocumentUploaderWithRequiredField(TestMultipleDocumentUp
|
|
|
1559
1693
|
|
|
1560
1694
|
# Make sure the document is deleted
|
|
1561
1695
|
self.assertFalse(
|
|
1562
|
-
|
|
1563
|
-
id=self.uploaded_document.id
|
|
1564
|
-
).exists()
|
|
1696
|
+
UploadedFile.objects.filter(id=self.uploaded_document.id).exists()
|
|
1565
1697
|
)
|
|
1566
1698
|
|
|
1567
1699
|
# Check JSON
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from django.contrib.auth.models import Group
|
|
2
2
|
from django.core.files.base import ContentFile
|
|
3
|
-
from django.test import TestCase
|
|
3
|
+
from django.test import TestCase, override_settings
|
|
4
4
|
from django.urls import reverse
|
|
5
5
|
|
|
6
6
|
from wagtail.documents.models import Document
|
|
@@ -19,6 +19,7 @@ class TestCollectionPrivacyDocument(WagtailTestUtils, TestCase):
|
|
|
19
19
|
def setUp(self):
|
|
20
20
|
self.fake_file = ContentFile(b"A boring example document")
|
|
21
21
|
self.fake_file.name = "test.txt"
|
|
22
|
+
self.collection = Collection.objects.get(id=2)
|
|
22
23
|
self.password_collection = Collection.objects.get(name="Password protected")
|
|
23
24
|
self.login_collection = Collection.objects.get(name="Login protected")
|
|
24
25
|
self.group_collection = Collection.objects.get(name="Group protected")
|
|
@@ -106,6 +107,28 @@ class TestCollectionPrivacyDocument(WagtailTestUtils, TestCase):
|
|
|
106
107
|
)
|
|
107
108
|
self.assertRedirects(response, "/")
|
|
108
109
|
|
|
110
|
+
@override_settings(
|
|
111
|
+
WAGTAILDOCS_PASSWORD_REQUIRED_TEMPLATE="tests/custom_docs_password_required.html"
|
|
112
|
+
)
|
|
113
|
+
def test_anonymous_user_must_authenticate_with_custom_password_required_template(
|
|
114
|
+
self
|
|
115
|
+
):
|
|
116
|
+
secret_document = Document.objects.create(
|
|
117
|
+
title="Test document",
|
|
118
|
+
file=self.fake_file,
|
|
119
|
+
collection=self.password_collection,
|
|
120
|
+
)
|
|
121
|
+
doc_url = reverse(
|
|
122
|
+
"wagtaildocs_serve", args=(secret_document.id, secret_document.filename)
|
|
123
|
+
)
|
|
124
|
+
response = self.client.get(doc_url)
|
|
125
|
+
self.assertNotEqual(
|
|
126
|
+
response.templates[0].name, "wagtaildocs/password_required.html"
|
|
127
|
+
)
|
|
128
|
+
self.assertEqual(
|
|
129
|
+
response.templates[0].name, "tests/custom_docs_password_required.html"
|
|
130
|
+
)
|
|
131
|
+
|
|
109
132
|
def test_group_restriction_with_anonymous_user(self):
|
|
110
133
|
response, url = self.get_document(self.group_collection)
|
|
111
134
|
self.assertRedirects(response, f"/_util/login/?next={url}")
|
|
@@ -133,3 +156,34 @@ class TestCollectionPrivacyDocument(WagtailTestUtils, TestCase):
|
|
|
133
156
|
self.login(username="eventmoderator", password="password")
|
|
134
157
|
response, url = self.get_document(self.login_collection)
|
|
135
158
|
self.assertEqual(response.status_code, 200)
|
|
159
|
+
|
|
160
|
+
def test_set_shared_password_with_logged_in_user(self):
|
|
161
|
+
self.login()
|
|
162
|
+
response = self.client.get(
|
|
163
|
+
reverse("wagtailadmin_collections:set_privacy", args=(self.collection.id,)),
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
input_el = self.get_soup(response.content).select_one("[data-field-input]")
|
|
167
|
+
self.assertEqual(response.status_code, 200)
|
|
168
|
+
|
|
169
|
+
# check that input option for password is visible
|
|
170
|
+
self.assertIn("password", response.context["form"].fields)
|
|
171
|
+
|
|
172
|
+
# check that the option for password is visible
|
|
173
|
+
self.assertIsNotNone(input_el)
|
|
174
|
+
|
|
175
|
+
@override_settings(
|
|
176
|
+
WAGTAILDOCS_PRIVATE_COLLECTION_OPTIONS={"SHARED_PASSWORD": False}
|
|
177
|
+
)
|
|
178
|
+
def test_unset_shared_password_with_logged_in_user(self):
|
|
179
|
+
self.login()
|
|
180
|
+
response = self.client.get(
|
|
181
|
+
reverse("wagtailadmin_collections:set_privacy", args=(self.collection.id,)),
|
|
182
|
+
)
|
|
183
|
+
self.assertEqual(response.status_code, 200)
|
|
184
|
+
self.assertNotIn("password", response.context["form"].fields)
|
|
185
|
+
self.assertFalse(
|
|
186
|
+
response.context["form"]
|
|
187
|
+
.fields["restriction_type"]
|
|
188
|
+
.valid_value(CollectionViewRestriction.PASSWORD)
|
|
189
|
+
)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from django.test import TestCase
|
|
2
|
+
from django.urls import reverse_lazy
|
|
2
3
|
|
|
3
4
|
from wagtail.documents import get_document_model
|
|
4
5
|
from wagtail.documents.rich_text import (
|
|
@@ -8,6 +9,7 @@ from wagtail.documents.rich_text.editor_html import (
|
|
|
8
9
|
DocumentLinkHandler as EditorHtmlDocumentLinkHandler,
|
|
9
10
|
)
|
|
10
11
|
from wagtail.fields import RichTextField
|
|
12
|
+
from wagtail.rich_text.feature_registry import FeatureRegistry
|
|
11
13
|
from wagtail.test.utils import WagtailTestUtils
|
|
12
14
|
|
|
13
15
|
|
|
@@ -60,3 +62,15 @@ class TestFrontendDocumentLinkHandler(TestCase):
|
|
|
60
62
|
),
|
|
61
63
|
[(get_document_model(), "1", "", "")],
|
|
62
64
|
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class TestEntityFeatureChooserUrls(TestCase):
|
|
68
|
+
def test_chooser_urls_exist(self):
|
|
69
|
+
features = FeatureRegistry()
|
|
70
|
+
document = features.get_editor_plugin("draftail", "document-link")
|
|
71
|
+
|
|
72
|
+
self.assertIsNotNone(document.data.get("chooserUrls"))
|
|
73
|
+
self.assertEqual(
|
|
74
|
+
document.data["chooserUrls"]["documentChooser"],
|
|
75
|
+
reverse_lazy("wagtaildocs_chooser:choose"),
|
|
76
|
+
)
|
|
@@ -12,6 +12,7 @@ from django.utils.translation import gettext_lazy, ngettext
|
|
|
12
12
|
|
|
13
13
|
from wagtail.admin import messages
|
|
14
14
|
from wagtail.admin.auth import PermissionPolicyChecker
|
|
15
|
+
from wagtail.admin.filters import BaseMediaFilterSet
|
|
15
16
|
from wagtail.admin.ui.tables import (
|
|
16
17
|
BulkActionsCheckboxColumn,
|
|
17
18
|
Column,
|
|
@@ -25,9 +26,9 @@ from wagtail.admin.views import generic
|
|
|
25
26
|
from wagtail.documents import get_document_model
|
|
26
27
|
from wagtail.documents.forms import get_document_form
|
|
27
28
|
from wagtail.documents.permissions import permission_policy
|
|
28
|
-
from wagtail.models import Collection
|
|
29
29
|
|
|
30
30
|
permission_checker = PermissionPolicyChecker(permission_policy)
|
|
31
|
+
Document = get_document_model()
|
|
31
32
|
|
|
32
33
|
|
|
33
34
|
class BulkActionsColumn(BulkActionsCheckboxColumn):
|
|
@@ -49,6 +50,14 @@ class DocumentTable(Table):
|
|
|
49
50
|
return context
|
|
50
51
|
|
|
51
52
|
|
|
53
|
+
class DocumentsFilterSet(BaseMediaFilterSet):
|
|
54
|
+
permission_policy = permission_policy
|
|
55
|
+
|
|
56
|
+
class Meta:
|
|
57
|
+
model = Document
|
|
58
|
+
fields = []
|
|
59
|
+
|
|
60
|
+
|
|
52
61
|
class IndexView(generic.IndexView):
|
|
53
62
|
permission_policy = permission_policy
|
|
54
63
|
any_permission_required = ["add", "change", "delete"]
|
|
@@ -65,9 +74,11 @@ class IndexView(generic.IndexView):
|
|
|
65
74
|
results_template_name = "wagtaildocs/documents/index_results.html"
|
|
66
75
|
default_ordering = "title"
|
|
67
76
|
table_class = DocumentTable
|
|
77
|
+
filterset_class = DocumentsFilterSet
|
|
68
78
|
model = get_document_model()
|
|
69
79
|
add_item_label = gettext_lazy("Add a document")
|
|
70
80
|
show_other_searches = True
|
|
81
|
+
_show_breadcrumbs = True
|
|
71
82
|
|
|
72
83
|
def get_base_queryset(self):
|
|
73
84
|
# Get documents (filtered by user permission)
|
|
@@ -75,17 +86,10 @@ class IndexView(generic.IndexView):
|
|
|
75
86
|
self.request.user, ["change", "delete"]
|
|
76
87
|
).select_related("collection")
|
|
77
88
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
try:
|
|
83
|
-
self.current_collection = Collection.objects.get(id=collection_id)
|
|
84
|
-
queryset = queryset.filter(collection=self.current_collection)
|
|
85
|
-
except (ValueError, Collection.DoesNotExist):
|
|
86
|
-
pass
|
|
87
|
-
|
|
88
|
-
return queryset
|
|
89
|
+
@cached_property
|
|
90
|
+
def current_collection(self):
|
|
91
|
+
# Upon validation, the cleaned data is a Collection instance
|
|
92
|
+
return self.filters and self.filters.form.cleaned_data.get("collection_id")
|
|
89
93
|
|
|
90
94
|
@cached_property
|
|
91
95
|
def columns(self):
|
|
@@ -106,7 +110,7 @@ class IndexView(generic.IndexView):
|
|
|
106
110
|
width="16%",
|
|
107
111
|
),
|
|
108
112
|
]
|
|
109
|
-
if self.
|
|
113
|
+
if self.filters and "collection_id" in self.filters.filters:
|
|
110
114
|
columns.insert(
|
|
111
115
|
3,
|
|
112
116
|
Column("collection", label=_("Collection"), accessor="collection.name"),
|
|
@@ -130,10 +134,10 @@ class IndexView(generic.IndexView):
|
|
|
130
134
|
return next_url
|
|
131
135
|
|
|
132
136
|
def get_add_url(self):
|
|
133
|
-
# Pass the
|
|
137
|
+
# Pass the collection filter to prefill the add form's collection field
|
|
134
138
|
return set_query_params(
|
|
135
139
|
super().get_add_url(),
|
|
136
|
-
self.
|
|
140
|
+
{"collection_id": self.current_collection and self.current_collection.pk},
|
|
137
141
|
)
|
|
138
142
|
|
|
139
143
|
def get_edit_url(self, instance):
|
|
@@ -142,15 +146,14 @@ class IndexView(generic.IndexView):
|
|
|
142
146
|
{"next": self.get_next_url()},
|
|
143
147
|
)
|
|
144
148
|
|
|
149
|
+
def get_filterset_kwargs(self):
|
|
150
|
+
kwargs = super().get_filterset_kwargs()
|
|
151
|
+
kwargs["is_searching"] = self.is_searching
|
|
152
|
+
return kwargs
|
|
153
|
+
|
|
145
154
|
def get_context_data(self, **kwargs):
|
|
146
155
|
context = super().get_context_data(**kwargs)
|
|
147
|
-
|
|
148
|
-
context.update(
|
|
149
|
-
{
|
|
150
|
-
"collections": self.collections,
|
|
151
|
-
"current_collection": self.current_collection,
|
|
152
|
-
}
|
|
153
|
-
)
|
|
156
|
+
context["current_collection"] = self.current_collection
|
|
154
157
|
return context
|
|
155
158
|
|
|
156
159
|
|
|
@@ -12,14 +12,12 @@ from wagtail.admin.views.generic.multiple_upload import EditView as BaseEditView
|
|
|
12
12
|
|
|
13
13
|
from .. import get_document_model
|
|
14
14
|
from ..forms import get_document_form, get_document_multi_form
|
|
15
|
-
from ..models import UploadedDocument
|
|
16
15
|
from ..permissions import permission_policy
|
|
17
16
|
|
|
18
17
|
|
|
19
18
|
class AddView(BaseAddView):
|
|
20
19
|
permission_policy = permission_policy
|
|
21
20
|
template_name = "wagtaildocs/multiple/add.html"
|
|
22
|
-
upload_model = UploadedDocument
|
|
23
21
|
|
|
24
22
|
edit_object_url_name = "wagtaildocs:edit_multiple"
|
|
25
23
|
delete_object_url_name = "wagtaildocs:delete_multiple"
|
|
@@ -31,7 +29,7 @@ class AddView(BaseAddView):
|
|
|
31
29
|
delete_upload_url_name = "wagtaildocs:delete_upload_multiple"
|
|
32
30
|
edit_upload_form_prefix = "uploaded-document"
|
|
33
31
|
context_upload_name = "uploaded_document"
|
|
34
|
-
context_upload_id_name = "
|
|
32
|
+
context_upload_id_name = "uploaded_file_id"
|
|
35
33
|
|
|
36
34
|
def get_model(self):
|
|
37
35
|
return get_document_model()
|
|
@@ -90,8 +88,7 @@ class DeleteView(BaseDeleteView):
|
|
|
90
88
|
class CreateFromUploadedDocumentView(BaseCreateFromUploadView):
|
|
91
89
|
edit_upload_url_name = "wagtaildocs:create_multiple_from_uploaded_document"
|
|
92
90
|
delete_upload_url_name = "wagtaildocs:delete_upload_multiple"
|
|
93
|
-
|
|
94
|
-
upload_pk_url_kwarg = "uploaded_document_id"
|
|
91
|
+
upload_pk_url_kwarg = "uploaded_file_id"
|
|
95
92
|
edit_upload_form_prefix = "uploaded-document"
|
|
96
93
|
context_object_id_name = "doc_id"
|
|
97
94
|
context_upload_name = "uploaded_document"
|
|
@@ -118,5 +115,7 @@ class CreateFromUploadedDocumentView(BaseCreateFromUploadView):
|
|
|
118
115
|
|
|
119
116
|
|
|
120
117
|
class DeleteUploadView(BaseDeleteUploadView):
|
|
121
|
-
|
|
122
|
-
|
|
118
|
+
upload_pk_url_kwarg = "uploaded_file_id"
|
|
119
|
+
|
|
120
|
+
def get_model(self):
|
|
121
|
+
return get_document_model()
|
wagtail/documents/views/serve.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from warnings import warn
|
|
2
|
+
|
|
1
3
|
from django.conf import settings
|
|
2
4
|
from django.http import FileResponse, Http404, HttpResponse
|
|
3
5
|
from django.shortcuts import get_object_or_404, redirect
|
|
@@ -12,6 +14,7 @@ from wagtail.documents.models import document_served
|
|
|
12
14
|
from wagtail.forms import PasswordViewRestrictionForm
|
|
13
15
|
from wagtail.models import CollectionViewRestriction
|
|
14
16
|
from wagtail.utils import sendfile_streaming_backend
|
|
17
|
+
from wagtail.utils.deprecation import RemovedInWagtail70Warning
|
|
15
18
|
from wagtail.utils.sendfile import sendfile
|
|
16
19
|
|
|
17
20
|
|
|
@@ -135,9 +138,21 @@ def authenticate_with_password(request, restriction_id):
|
|
|
135
138
|
|
|
136
139
|
password_required_template = getattr(
|
|
137
140
|
settings,
|
|
138
|
-
"
|
|
141
|
+
"WAGTAILDOCS_PASSWORD_REQUIRED_TEMPLATE",
|
|
139
142
|
"wagtaildocs/password_required.html",
|
|
140
143
|
)
|
|
141
144
|
|
|
145
|
+
if hasattr(settings, "DOCUMENT_PASSWORD_REQUIRED_TEMPLATE"):
|
|
146
|
+
warn(
|
|
147
|
+
"The `DOCUMENT_PASSWORD_REQUIRED_TEMPLATE` setting is deprecated - use `WAGTAILDOCS_PASSWORD_REQUIRED_TEMPLATE` instead.",
|
|
148
|
+
category=RemovedInWagtail70Warning,
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
password_required_template = getattr(
|
|
152
|
+
settings,
|
|
153
|
+
"DOCUMENT_PASSWORD_REQUIRED_TEMPLATE",
|
|
154
|
+
password_required_template,
|
|
155
|
+
)
|
|
156
|
+
|
|
142
157
|
context = {"form": form, "action_url": action_url}
|
|
143
158
|
return TemplateResponse(request, password_required_template, context)
|