wagtail 7.1.1__py3-none-any.whl → 7.2rc1__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/actions/copy_page.py +1 -1
- wagtail/actions/create_alias.py +1 -1
- wagtail/actions/delete_page.py +1 -1
- wagtail/actions/publish_page_revision.py +1 -1
- wagtail/actions/publish_revision.py +1 -1
- wagtail/actions/revert_to_page_revision.py +1 -1
- wagtail/actions/unpublish.py +1 -1
- wagtail/actions/unpublish_page.py +1 -1
- wagtail/admin/auth.py +3 -1
- wagtail/admin/checks.py +2 -2
- wagtail/admin/filters.py +28 -1
- wagtail/admin/forms/collections.py +1 -1
- wagtail/admin/forms/comments.py +1 -1
- wagtail/admin/forms/models.py +1 -1
- wagtail/admin/forms/pages.py +1 -1
- wagtail/admin/forms/tags.py +1 -1
- wagtail/admin/locale/cs/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/cs/LC_MESSAGES/django.po +25 -1
- wagtail/admin/locale/en/LC_MESSAGES/django.po +278 -192
- wagtail/admin/locale/en/LC_MESSAGES/djangojs.po +29 -15
- wagtail/admin/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/it/LC_MESSAGES/django.po +3 -2
- wagtail/admin/locale/nl/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/nl/LC_MESSAGES/django.po +57 -3
- wagtail/admin/locale/nl/LC_MESSAGES/djangojs.mo +0 -0
- wagtail/admin/locale/nl/LC_MESSAGES/djangojs.po +8 -2
- wagtail/admin/locale/ru/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/ru/LC_MESSAGES/django.po +58 -1
- wagtail/admin/locale/tr/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/tr/LC_MESSAGES/django.po +3 -2
- wagtail/admin/static/wagtailadmin/css/core.css +1 -1
- 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 +2 -2
- 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/filtered-select.js +1 -1
- wagtail/admin/static/wagtailadmin/js/icons.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/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/userbar.js.LICENSE.txt +2 -2
- wagtail/admin/static/wagtailadmin/js/vendor/bootstrap-modal.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor/bootstrap-transition.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor/jquery-3.6.0.min.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor/jquery-ui-1.13.2.min.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor/jquery.datetimepicker.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor/jquery.fileupload-process.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor/jquery.fileupload.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor/jquery.iframe-transport.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor/tag-it.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor.js.LICENSE.txt +1 -1
- wagtail/admin/static/wagtailadmin/js/wagtailadmin.js +1 -1
- wagtail/admin/static/wagtailadmin/js/workflow-action.js +1 -1
- wagtail/admin/templates/wagtailadmin/account/account.html +2 -0
- wagtail/admin/templates/wagtailadmin/base.html +14 -0
- wagtail/admin/templates/wagtailadmin/generic/chooser/chooser.html +2 -1
- wagtail/admin/templates/wagtailadmin/generic/chooser/creation_form.html +2 -1
- wagtail/admin/templates/wagtailadmin/generic/form.html +3 -1
- wagtail/admin/templates/wagtailadmin/panels/multi_field_panel_child.html +1 -1
- wagtail/admin/templates/wagtailadmin/panels/object_list.html +1 -1
- wagtail/admin/templates/wagtailadmin/panels/tabbed_interface.html +3 -2
- wagtail/admin/templates/wagtailadmin/shared/formatted_field.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/forms/single_checkbox.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/keyboard_shortcuts_dialog.html +19 -0
- wagtail/admin/templates/wagtailadmin/shared/panel.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/set_privacy.html +15 -0
- wagtail/admin/templates/wagtailadmin/shared/side_panels/checks.html +28 -1
- wagtail/admin/templates/wagtailadmin/shared/workflow_history/detail.html +2 -2
- wagtail/admin/templates/wagtailadmin/{pages/listing/_ordering_header.html → tables/ordering_header.html} +2 -2
- wagtail/admin/templates/wagtailadmin/tables/title_cell.html +1 -1
- wagtail/admin/templates/wagtailadmin/userbar/base.html +6 -3
- wagtail/admin/templates/wagtailadmin/userbar/item_admin.html +2 -2
- wagtail/admin/templates/wagtailadmin/userbar/item_page_add.html +2 -2
- wagtail/admin/templates/wagtailadmin/userbar/item_page_edit.html +2 -2
- wagtail/admin/templates/wagtailadmin/userbar/item_page_explore.html +2 -2
- wagtail/admin/templates/wagtailadmin/widgets/{daterange_input.html → range_input.html} +1 -1
- wagtail/admin/templates/wagtailadmin/workflows/task_chooser/chooser.html +4 -2
- wagtail/admin/templatetags/wagtailadmin_tags.py +56 -22
- wagtail/admin/tests/api/test_pages.py +7 -7
- wagtail/admin/tests/api/test_renderer_classes.py +16 -0
- wagtail/admin/tests/pages/test_create_page.py +34 -2
- wagtail/admin/tests/pages/test_edit_page.py +128 -14
- wagtail/admin/tests/pages/test_explorer_view.py +34 -7
- wagtail/admin/tests/pages/test_reorder_page.py +11 -0
- wagtail/admin/tests/test_collections_views.py +12 -0
- wagtail/admin/tests/test_edit_handlers.py +3 -3
- wagtail/admin/tests/test_filters.py +2 -2
- wagtail/admin/tests/test_keyboard_shortcuts.py +52 -2
- wagtail/admin/tests/test_menu.py +0 -2
- wagtail/admin/tests/test_privacy.py +16 -16
- wagtail/admin/tests/test_templatetags.py +137 -0
- wagtail/admin/tests/test_userbar.py +75 -35
- wagtail/admin/tests/test_views_generic.py +34 -0
- wagtail/admin/tests/test_workflows.py +34 -0
- wagtail/admin/tests/viewsets/test_model_viewset.py +322 -0
- wagtail/admin/ui/tables/orderable.py +73 -0
- wagtail/admin/ui/tables/pages.py +3 -13
- wagtail/admin/userbar.py +6 -1
- wagtail/admin/views/collection_privacy.py +6 -2
- wagtail/admin/views/generic/__init__.py +1 -0
- wagtail/admin/views/generic/mixins.py +20 -2
- wagtail/admin/views/generic/models.py +67 -1
- wagtail/admin/views/generic/ordering.py +79 -0
- wagtail/admin/views/home.py +3 -3
- wagtail/admin/views/page_privacy.py +5 -2
- wagtail/admin/views/pages/create.py +1 -1
- wagtail/admin/views/pages/edit.py +2 -2
- wagtail/admin/views/pages/listing.py +7 -42
- wagtail/admin/views/pages/move.py +1 -1
- wagtail/admin/views/pages/ordering.py +1 -1
- wagtail/admin/viewsets/base.py +1 -1
- wagtail/admin/viewsets/model.py +49 -1
- wagtail/admin/wagtail_hooks.py +2 -1
- wagtail/admin/widgets/slug.py +10 -10
- wagtail/api/v2/serializers.py +1 -1
- wagtail/api/v2/tests/test_renderer_classes.py +32 -0
- wagtail/apps.py +2 -0
- wagtail/bin/wagtail.py +1 -1
- wagtail/blocks/struct_block.py +2 -1
- wagtail/contrib/forms/locale/en/LC_MESSAGES/django.po +14 -14
- wagtail/contrib/forms/locale/nl/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/forms/locale/nl/LC_MESSAGES/django.po +19 -2
- wagtail/contrib/forms/locale/ru/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/forms/locale/ru/LC_MESSAGES/django.po +18 -1
- wagtail/contrib/frontend_cache/tests.py +4 -2
- wagtail/contrib/redirects/locale/en/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/tests/test_tmp_storages.py +20 -0
- wagtail/contrib/redirects/tmp_storages.py +1 -1
- wagtail/contrib/redirects/views.py +3 -3
- wagtail/contrib/search_promotions/locale/en/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/search_promotions/locale/tr/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/search_promotions/locale/tr/LC_MESSAGES/django.po +43 -3
- wagtail/contrib/search_promotions/static/wagtailsearchpromotions/js/query-chooser-modal.js +1 -1
- wagtail/contrib/search_promotions/views/settings.py +2 -2
- wagtail/contrib/settings/locale/cs/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/settings/locale/cs/LC_MESSAGES/django.po +6 -1
- wagtail/contrib/settings/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/settings/locale/nl/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/settings/locale/nl/LC_MESSAGES/django.po +6 -2
- wagtail/contrib/settings/locale/ru/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/settings/locale/ru/LC_MESSAGES/django.po +6 -1
- wagtail/contrib/settings/tests/site_specific/test_admin.py +40 -6
- wagtail/contrib/simple_translation/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/styleguide/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/styleguide/templates/wagtailstyleguide/base.html +5 -5
- wagtail/contrib/table_block/blocks.py +1 -0
- wagtail/contrib/table_block/locale/en/LC_MESSAGES/django.po +5 -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 +5 -5
- wagtail/documents/forms.py +18 -1
- wagtail/documents/locale/en/LC_MESSAGES/django.po +10 -10
- wagtail/documents/locale/nl/LC_MESSAGES/django.mo +0 -0
- wagtail/documents/locale/nl/LC_MESSAGES/django.po +9 -0
- wagtail/documents/locale/ru/LC_MESSAGES/django.mo +0 -0
- wagtail/documents/locale/ru/LC_MESSAGES/django.po +9 -0
- wagtail/documents/models.py +1 -1
- wagtail/documents/static/wagtaildocs/js/add-multiple.js +1 -1
- 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/add.html +0 -34
- wagtail/documents/tests/test_admin_views.py +132 -26
- wagtail/documents/tests/test_collection_privacy.py +18 -4
- wagtail/documents/tests/test_form_overrides.py +1 -1
- wagtail/documents/tests/test_search.py +21 -8
- wagtail/documents/views/documents.py +1 -1
- wagtail/embeds/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/embeds/static/wagtailembeds/js/embed-chooser-modal.js +1 -1
- wagtail/images/forms.py +16 -1
- wagtail/images/locale/cs/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/cs/LC_MESSAGES/django.po +12 -1
- wagtail/images/locale/en/LC_MESSAGES/django.po +57 -46
- wagtail/images/locale/nl/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/nl/LC_MESSAGES/django.po +37 -14
- wagtail/images/locale/ru/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/ru/LC_MESSAGES/django.po +20 -1
- wagtail/images/models.py +1 -1
- wagtail/images/static/wagtailimages/js/add-multiple.js +1 -1
- wagtail/images/static/wagtailimages/js/focal-point-chooser.js +1 -1
- wagtail/images/static/wagtailimages/js/image-block.js +1 -1
- 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/static/wagtailimages/js/image-url-generator.js +1 -1
- wagtail/images/static/wagtailimages/js/vendor/jquery.Jcrop.min.js +1 -1
- wagtail/images/static/wagtailimages/js/vendor/jquery.fileupload-image.js +1 -1
- wagtail/images/static/wagtailimages/js/vendor/jquery.fileupload-validate.js +1 -1
- wagtail/images/static/wagtailimages/js/vendor/load-image.min.js +1 -1
- wagtail/images/templates/wagtailimages/chooser/chooser.html +22 -13
- wagtail/images/templates/wagtailimages/chooser/image_preview_column_cell.html +10 -0
- wagtail/images/templates/wagtailimages/chooser/results.html +24 -20
- wagtail/images/templates/wagtailimages/chooser/title_column_cell.html +15 -0
- wagtail/images/templates/wagtailimages/images/add.html +0 -34
- wagtail/images/templates/wagtailimages/images/index.html +3 -3
- wagtail/images/templates/wagtailimages/images/index_results.html +1 -1
- wagtail/images/templates/wagtailimages/images/layout_toggle_button.html +8 -7
- wagtail/images/templatetags/wagtailimages_tags.py +2 -2
- wagtail/images/tests/test_admin_views.py +87 -0
- wagtail/images/tests/test_form_overrides.py +1 -1
- wagtail/images/tests/test_models.py +48 -9
- wagtail/images/views/chooser.py +66 -2
- wagtail/locale/en/LC_MESSAGES/django.po +55 -55
- wagtail/locale/is_IS/LC_MESSAGES/django.mo +0 -0
- wagtail/locale/is_IS/LC_MESSAGES/django.po +3 -3
- wagtail/locale/nl/LC_MESSAGES/django.mo +0 -0
- wagtail/locale/nl/LC_MESSAGES/django.po +11 -2
- wagtail/locale/ru/LC_MESSAGES/django.mo +0 -0
- wagtail/locale/ru/LC_MESSAGES/django.po +11 -1
- wagtail/locales/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/nl/LC_MESSAGES/django.mo +0 -0
- wagtail/locales/locale/nl/LC_MESSAGES/django.po +12 -1
- wagtail/locales/locale/ru/LC_MESSAGES/django.mo +0 -0
- wagtail/locales/locale/ru/LC_MESSAGES/django.po +10 -1
- wagtail/locales/views.py +2 -2
- wagtail/models/orderable.py +10 -0
- wagtail/models/pages.py +9 -11
- wagtail/models/sites.py +1 -1
- wagtail/models/workflows.py +8 -5
- wagtail/project_template/home/tests.py +6 -7
- wagtail/project_template/project_name/settings/base.py +9 -9
- wagtail/project_template/requirements.txt +1 -1
- wagtail/query.py +7 -2
- wagtail/rich_text/rewriters.py +1 -1
- wagtail/search/apps.py +4 -49
- wagtail/search/backends/__init__.py +1 -113
- wagtail/search/backends/base.py +1 -547
- wagtail/search/backends/database/__init__.py +1 -50
- wagtail/search/backends/database/fallback.py +1 -253
- wagtail/search/backends/database/mysql/mysql.py +1 -700
- wagtail/search/backends/database/mysql/query.py +1 -258
- wagtail/search/backends/database/postgres/postgres.py +1 -749
- wagtail/search/backends/database/postgres/query.py +1 -83
- wagtail/search/backends/database/postgres/weights.py +1 -63
- wagtail/search/backends/database/sqlite/query.py +1 -294
- wagtail/search/backends/database/sqlite/sqlite.py +1 -719
- wagtail/search/backends/database/sqlite/utils.py +1 -35
- wagtail/search/backends/deprecation.py +45 -0
- wagtail/search/backends/elasticsearch7.py +18 -1260
- wagtail/search/backends/elasticsearch8.py +21 -96
- wagtail/search/backends/elasticsearch9.py +35 -0
- wagtail/search/backends/opensearch2.py +35 -0
- wagtail/search/backends/opensearch3.py +35 -0
- wagtail/search/index.py +1 -358
- wagtail/search/locale/en/LC_MESSAGES/django.po +2 -10
- wagtail/search/management/commands/update_index.py +1 -205
- wagtail/search/management/commands/wagtail_update_index.py +1 -4
- wagtail/search/models.py +32 -158
- wagtail/search/query.py +1 -114
- wagtail/search/queryset.py +1 -43
- wagtail/search/signal_handlers.py +1 -24
- wagtail/search/tasks.py +1 -10
- wagtail/search/tests/test_elasticsearch.py +22 -0
- wagtail/search/utils.py +1 -206
- wagtail/sites/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/snippets/locale/en/LC_MESSAGES/django.po +3 -3
- wagtail/snippets/locale/ru/LC_MESSAGES/django.mo +0 -0
- wagtail/snippets/locale/ru/LC_MESSAGES/django.po +8 -1
- wagtail/snippets/locale/tr/LC_MESSAGES/django.mo +0 -0
- wagtail/snippets/locale/tr/LC_MESSAGES/django.po +8 -1
- wagtail/snippets/static/wagtailsnippets/js/snippet-chooser-telepath.js +1 -1
- wagtail/snippets/static/wagtailsnippets/js/snippet-chooser.js +1 -1
- wagtail/snippets/tests/test_preview.py +5 -6
- wagtail/snippets/tests/test_reordering.py +319 -0
- wagtail/snippets/tests/test_snippets.py +65 -12
- wagtail/snippets/views/snippets.py +16 -0
- wagtail/test/numberformat.py +30 -0
- wagtail/test/settings.py +35 -12
- wagtail/test/testapp/fields.py +12 -0
- wagtail/test/testapp/migrations/0056_commentablejsonpage.py +50 -0
- wagtail/test/testapp/migrations/0057_featurecompletetoy_sort_order.py +23 -0
- wagtail/test/testapp/migrations/0058_customlocktask.py +31 -0
- wagtail/test/testapp/models.py +27 -0
- wagtail/test/testapp/urls.py +1 -0
- wagtail/test/testapp/views.py +18 -2
- wagtail/test/utils/page_tests.py +17 -17
- wagtail/test/utils/template_tests.py +4 -6
- wagtail/test/utils/wagtail_tests.py +1 -2
- wagtail/tests/test_blocks.py +15 -0
- wagtail/tests/test_page_model.py +15 -0
- wagtail/{search/tests → tests}/test_page_search.py +29 -2
- wagtail/tests/test_search_fields.py +69 -0
- wagtail/tests/test_tests.py +62 -6
- wagtail/tests/test_workflow.py +25 -1
- wagtail/users/locale/cs/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/cs/LC_MESSAGES/django.po +3 -0
- wagtail/users/locale/en/LC_MESSAGES/django.po +2 -2
- wagtail/users/locale/nl/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/nl/LC_MESSAGES/django.po +6 -3
- wagtail/users/locale/ru/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/ru/LC_MESSAGES/django.po +5 -1
- wagtail/users/locale/tr/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/tr/LC_MESSAGES/django.po +78 -4
- wagtail/users/templates/wagtailusers/users/create.html +2 -0
- wagtail/users/templates/wagtailusers/users/edit.html +2 -0
- wagtail/users/tests/test_admin_views.py +4 -0
- wagtail/users/views/users.py +1 -1
- {wagtail-7.1.1.dist-info → wagtail-7.2rc1.dist-info}/METADATA +7 -6
- {wagtail-7.1.1.dist-info → wagtail-7.2rc1.dist-info}/RECORD +322 -328
- wagtail/admin/templates/wagtailadmin/collection_privacy/set_privacy.html +0 -13
- wagtail/admin/templates/wagtailadmin/page_privacy/set_privacy.html +0 -13
- wagtail/search/tests/__init__.py +0 -0
- wagtail/search/tests/elasticsearch_common_tests.py +0 -251
- wagtail/search/tests/test_backends.py +0 -1215
- wagtail/search/tests/test_db_backend.py +0 -62
- wagtail/search/tests/test_elasticsearch7_backend.py +0 -1452
- wagtail/search/tests/test_elasticsearch8_backend.py +0 -15
- wagtail/search/tests/test_index_functions.py +0 -256
- wagtail/search/tests/test_indexed_class.py +0 -157
- wagtail/search/tests/test_mysql_backend.py +0 -192
- wagtail/search/tests/test_postgres_backend.py +0 -210
- wagtail/search/tests/test_queries.py +0 -332
- wagtail/search/tests/test_related_fields.py +0 -102
- wagtail/search/tests/test_sqlite_backend.py +0 -52
- wagtail/test/search/__init__.py +0 -0
- wagtail/test/search/apps.py +0 -9
- wagtail/test/search/fixtures/search.json +0 -545
- wagtail/test/search/migrations/0001_initial.py +0 -146
- wagtail/test/search/migrations/0002_bookunindexed.py +0 -43
- wagtail/test/search/migrations/0003_book_summary.py +0 -18
- wagtail/test/search/migrations/__init__.py +0 -0
- wagtail/test/search/models.py +0 -137
- /wagtail/admin/templates/wagtailadmin/{pages/listing/_ordering_cell.html → tables/ordering_cell.html} +0 -0
- /wagtail/{search/checks.py → checks.py} +0 -0
- {wagtail-7.1.1.dist-info → wagtail-7.2rc1.dist-info}/WHEEL +0 -0
- {wagtail-7.1.1.dist-info → wagtail-7.2rc1.dist-info}/entry_points.txt +0 -0
- {wagtail-7.1.1.dist-info → wagtail-7.2rc1.dist-info}/licenses/LICENSE +0 -0
- {wagtail-7.1.1.dist-info → wagtail-7.2rc1.dist-info}/top_level.txt +0 -0
|
@@ -206,6 +206,21 @@ def admin_url_name(obj, action):
|
|
|
206
206
|
return obj.snippet_viewset.get_url_name(action)
|
|
207
207
|
|
|
208
208
|
|
|
209
|
+
@register.simple_tag(takes_context=True)
|
|
210
|
+
def build_absolute_url(context, url):
|
|
211
|
+
"""
|
|
212
|
+
Usage: {% build_absolute_url url %}
|
|
213
|
+
Returns the absolute URL of the given URL based on the request's host.
|
|
214
|
+
If the request doesn't exist in the context, falls back to
|
|
215
|
+
WAGTAILADMIN_BASE_URL as the base URL.
|
|
216
|
+
If the given URL is already absolute, returns it unchanged.
|
|
217
|
+
"""
|
|
218
|
+
request = context.get("request")
|
|
219
|
+
if not request:
|
|
220
|
+
return urljoin(get_admin_base_url(), url)
|
|
221
|
+
return request.build_absolute_uri(url)
|
|
222
|
+
|
|
223
|
+
|
|
209
224
|
@register.simple_tag
|
|
210
225
|
def latest_str(obj):
|
|
211
226
|
"""
|
|
@@ -900,9 +915,7 @@ def wagtail_config(context):
|
|
|
900
915
|
request = context["request"]
|
|
901
916
|
config = {
|
|
902
917
|
"CSRF_TOKEN": get_token(request),
|
|
903
|
-
"CSRF_HEADER_NAME": HttpHeaders.parse_header_name(
|
|
904
|
-
getattr(settings, "CSRF_HEADER_NAME")
|
|
905
|
-
),
|
|
918
|
+
"CSRF_HEADER_NAME": HttpHeaders.parse_header_name(settings.CSRF_HEADER_NAME),
|
|
906
919
|
"ADMIN_API": {
|
|
907
920
|
"PAGES": reverse("wagtailadmin_api:pages:listing"),
|
|
908
921
|
"DOCUMENTS": reverse("wagtailadmin_api:documents:listing"),
|
|
@@ -1175,6 +1188,7 @@ def formattedfield(
|
|
|
1175
1188
|
label_text=None,
|
|
1176
1189
|
error_message_id=None,
|
|
1177
1190
|
wrapper_id=None,
|
|
1191
|
+
attrs=None,
|
|
1178
1192
|
):
|
|
1179
1193
|
"""
|
|
1180
1194
|
Renders a form field in standard Wagtail admin layout.
|
|
@@ -1192,12 +1206,15 @@ def formattedfield(
|
|
|
1192
1206
|
- `label_text` - Manually set this if the field’s HTML is hard-coded.
|
|
1193
1207
|
- `error_message_id` - ID of the error message container element.
|
|
1194
1208
|
- `wrapper_id` - ID of the overall wrapper element.
|
|
1209
|
+
- `attrs` - Dict of additional HTML attributes to add to the field wrapper element, `data-field-wrapper` will be included by default.
|
|
1195
1210
|
"""
|
|
1196
1211
|
|
|
1197
1212
|
label_for = id_for_label or (field and field.id_for_label) or ""
|
|
1198
1213
|
|
|
1199
1214
|
context = {
|
|
1200
1215
|
"classname": classname,
|
|
1216
|
+
# Ensure data-field-wrapper is always present
|
|
1217
|
+
"attrs": {**(attrs or {}), "data-field-wrapper": True},
|
|
1201
1218
|
"show_label": show_label,
|
|
1202
1219
|
"sr_only_label": sr_only_label,
|
|
1203
1220
|
"icon": icon,
|
|
@@ -1319,15 +1336,42 @@ def keyboard_shortcuts_dialog(context):
|
|
|
1319
1336
|
appropriate shortcuts for the user's platform.
|
|
1320
1337
|
Note: Shortcut keys are intentionally not translated.
|
|
1321
1338
|
"""
|
|
1339
|
+
request = context.get("request")
|
|
1340
|
+
keyboard_shortcuts_enabled = True
|
|
1341
|
+
|
|
1342
|
+
if request and getattr(request, "user", None):
|
|
1343
|
+
profile = getattr(request.user, "wagtail_userprofile", None)
|
|
1344
|
+
if profile is not None:
|
|
1345
|
+
keyboard_shortcuts_enabled = bool(
|
|
1346
|
+
getattr(profile, "keyboard_shortcuts", True)
|
|
1347
|
+
)
|
|
1322
1348
|
|
|
1323
1349
|
comments_enabled = get_comments_enabled()
|
|
1324
|
-
user_agent =
|
|
1350
|
+
user_agent = request.headers.get("User-Agent", "") if request else ""
|
|
1325
1351
|
is_mac = re.search(r"Mac|iPod|iPhone|iPad", user_agent)
|
|
1326
|
-
KEYS = get_keyboard_key_labels_from_request(
|
|
1352
|
+
KEYS = get_keyboard_key_labels_from_request(request) if request else {}
|
|
1327
1353
|
|
|
1328
1354
|
return {
|
|
1355
|
+
"keyboard_shortcuts_enabled": keyboard_shortcuts_enabled,
|
|
1329
1356
|
"shortcuts": {
|
|
1330
|
-
|
|
1357
|
+
# Translators: Shortcuts for admin common shortcuts that are available across the admin
|
|
1358
|
+
("admin-common", _("Application")): [
|
|
1359
|
+
(_("Show keyboard shortcuts"), "?"),
|
|
1360
|
+
(_("Search"), "/"),
|
|
1361
|
+
(_("Toggle sidebar"), "["),
|
|
1362
|
+
(_("Toggle minimap"), "]"),
|
|
1363
|
+
(_("Close modal dialogs (like this one)"), f"{KEYS.ESC}"),
|
|
1364
|
+
],
|
|
1365
|
+
# Translators: Shortcuts for admin actions that can be taken while working on core models
|
|
1366
|
+
("admin-core-models", _("Actions")): [
|
|
1367
|
+
(_("Save changes"), f"{KEYS.MOD} + s"),
|
|
1368
|
+
(_("Preview"), f"{KEYS.MOD} + p"),
|
|
1369
|
+
(_("Add or show comments"), f"{KEYS.CTRL} + {KEYS.ALT} + m")
|
|
1370
|
+
if comments_enabled
|
|
1371
|
+
else None,
|
|
1372
|
+
],
|
|
1373
|
+
# Translators: Shortcuts for common text editing features available in all fields (even if not a rich text field)
|
|
1374
|
+
("text-editing-basic", _("Text editing")): [
|
|
1331
1375
|
(_("Copy"), f"{KEYS.MOD} + c"),
|
|
1332
1376
|
(_("Cut"), f"{KEYS.MOD} + x"),
|
|
1333
1377
|
(_("Paste"), f"{KEYS.MOD} + v"),
|
|
@@ -1343,27 +1387,17 @@ def keyboard_shortcuts_dialog(context):
|
|
|
1343
1387
|
f"{KEYS.MOD} + {KEYS.SHIFT} + z" if is_mac else f"{KEYS.MOD} + y",
|
|
1344
1388
|
),
|
|
1345
1389
|
],
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
(_("
|
|
1349
|
-
(_("
|
|
1350
|
-
(_("Toggle minimap"), "]"),
|
|
1351
|
-
(_("Add or show comments"), f"{KEYS.CTRL} + {KEYS.ALT} + m")
|
|
1352
|
-
if comments_enabled
|
|
1353
|
-
else None,
|
|
1354
|
-
],
|
|
1355
|
-
("rich-text-content", _("Text content")): [
|
|
1356
|
-
(_("Insert or edit a link"), f"{KEYS.MOD} + k")
|
|
1357
|
-
],
|
|
1358
|
-
("rich-text-formatting", _("Text formatting")): [
|
|
1390
|
+
# Translators: Shortcuts for formatting & editing features available in rich text fields
|
|
1391
|
+
("text-editing-rich-text", _("Text formatting")): [
|
|
1392
|
+
(_("Insert or edit a link"), f"{KEYS.MOD} + k"),
|
|
1393
|
+
(_("Bold"), f"{KEYS.MOD} + b"),
|
|
1359
1394
|
(_("Italic"), f"{KEYS.MOD} + i"),
|
|
1360
|
-
(_("Underline"), f"{KEYS.MOD} + u"),
|
|
1361
1395
|
(_("Monospace (code)"), f"{KEYS.MOD} + j"),
|
|
1362
|
-
(_("Strike-through"), f"{KEYS.MOD} + x"),
|
|
1396
|
+
(_("Strike-through"), f"{KEYS.MOD} + {KEYS.SHIFT} + x"),
|
|
1363
1397
|
(_("Superscript"), f"{KEYS.MOD} + ."),
|
|
1364
1398
|
(_("Subscript"), f"{KEYS.MOD} + ,"),
|
|
1365
1399
|
],
|
|
1366
|
-
}
|
|
1400
|
+
},
|
|
1367
1401
|
}
|
|
1368
1402
|
|
|
1369
1403
|
|
|
@@ -1378,7 +1378,7 @@ class TestCopyPageAction(AdminAPITestCase, TestCase):
|
|
|
1378
1378
|
content,
|
|
1379
1379
|
{
|
|
1380
1380
|
"detail": (
|
|
1381
|
-
"You do not have permission to publish a page at the destination"
|
|
1381
|
+
"You do not have permission to publish a page at the destination."
|
|
1382
1382
|
)
|
|
1383
1383
|
},
|
|
1384
1384
|
)
|
|
@@ -1407,7 +1407,7 @@ class TestCopyPageAction(AdminAPITestCase, TestCase):
|
|
|
1407
1407
|
content,
|
|
1408
1408
|
{
|
|
1409
1409
|
"slug": [
|
|
1410
|
-
"The slug 'events' is already in use within the parent page at '/'"
|
|
1410
|
+
"The slug 'events' is already in use within the parent page at '/'."
|
|
1411
1411
|
]
|
|
1412
1412
|
},
|
|
1413
1413
|
)
|
|
@@ -1517,7 +1517,7 @@ class TestDeletePageAction(AdminAPITestCase, TestCase):
|
|
|
1517
1517
|
self.assertEqual(response.status_code, 403)
|
|
1518
1518
|
content = json.loads(response.content.decode("utf-8"))
|
|
1519
1519
|
self.assertEqual(
|
|
1520
|
-
content, {"detail": "You do not have permission to delete this page"}
|
|
1520
|
+
content, {"detail": "You do not have permission to delete this page."}
|
|
1521
1521
|
)
|
|
1522
1522
|
|
|
1523
1523
|
# Page is still there
|
|
@@ -1565,7 +1565,7 @@ class TestPublishPageAction(AdminAPITestCase, TestCase):
|
|
|
1565
1565
|
self.assertEqual(response.status_code, 403)
|
|
1566
1566
|
content = json.loads(response.content.decode("utf-8"))
|
|
1567
1567
|
self.assertEqual(
|
|
1568
|
-
content, {"detail": "You do not have permission to publish this page"}
|
|
1568
|
+
content, {"detail": "You do not have permission to publish this page."}
|
|
1569
1569
|
)
|
|
1570
1570
|
|
|
1571
1571
|
def test_publish_alias_page(self):
|
|
@@ -1655,7 +1655,7 @@ class TestUnpublishPageAction(AdminAPITestCase, TestCase):
|
|
|
1655
1655
|
self.assertEqual(response.status_code, 403)
|
|
1656
1656
|
content = json.loads(response.content.decode("utf-8"))
|
|
1657
1657
|
self.assertEqual(
|
|
1658
|
-
content, {"detail": "You do not have permission to unpublish this page"}
|
|
1658
|
+
content, {"detail": "You do not have permission to unpublish this page."}
|
|
1659
1659
|
)
|
|
1660
1660
|
|
|
1661
1661
|
|
|
@@ -1969,7 +1969,7 @@ class TestCreatePageAliasAction(AdminAPITestCase, TestCase):
|
|
|
1969
1969
|
content,
|
|
1970
1970
|
{
|
|
1971
1971
|
"detail": (
|
|
1972
|
-
"You do not have permission to publish a page at the destination"
|
|
1972
|
+
"You do not have permission to publish a page at the destination."
|
|
1973
1973
|
),
|
|
1974
1974
|
},
|
|
1975
1975
|
)
|
|
@@ -2028,7 +2028,7 @@ class TestRevertToPageRevisionAction(AdminAPITestCase, TestCase):
|
|
|
2028
2028
|
|
|
2029
2029
|
content = json.loads(response.content.decode("utf-8"))
|
|
2030
2030
|
self.assertEqual(
|
|
2031
|
-
content, {"detail": "You do not have permission to edit this page"}
|
|
2031
|
+
content, {"detail": "You do not have permission to edit this page."}
|
|
2032
2032
|
)
|
|
2033
2033
|
|
|
2034
2034
|
def test_revert_to_page_revision_without_revision_id(self):
|
|
@@ -6,6 +6,7 @@ from django.urls import reverse
|
|
|
6
6
|
from rest_framework.renderers import BrowsableAPIRenderer, JSONRenderer
|
|
7
7
|
|
|
8
8
|
from wagtail.admin.api.views import PagesAdminAPIViewSet
|
|
9
|
+
from wagtail.test.numberformat import ignore_numberformat
|
|
9
10
|
from wagtail.test.utils import WagtailTestUtils
|
|
10
11
|
|
|
11
12
|
|
|
@@ -59,3 +60,18 @@ class TestPagesAdminAPIRendererClasses(WagtailTestUtils, TestCase):
|
|
|
59
60
|
content = json.loads(response.content.decode("UTF-8"))
|
|
60
61
|
self.assertIn("meta", content)
|
|
61
62
|
self.assertIn("items", content)
|
|
63
|
+
|
|
64
|
+
def test_api_response_returns_html_with_html_accept_header(self):
|
|
65
|
+
"""Test that API returns HTML when HTML is explicitly requested via Accept header."""
|
|
66
|
+
with ignore_numberformat(["rest_framework/base.html"]):
|
|
67
|
+
response = self.client.get(
|
|
68
|
+
reverse("wagtailadmin_api:pages:listing"), HTTP_ACCEPT="text/html"
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
self.assertEqual(response.status_code, 200)
|
|
72
|
+
self.assertEqual(response["Content-Type"], "text/html; charset=utf-8")
|
|
73
|
+
|
|
74
|
+
# Should contain HTML content
|
|
75
|
+
content = response.content.decode("UTF-8")
|
|
76
|
+
self.assertIn("<html", content)
|
|
77
|
+
self.assertIn("</html>", content)
|
|
@@ -544,6 +544,22 @@ class TestPageCreation(WagtailTestUtils, TestCase):
|
|
|
544
544
|
post_data,
|
|
545
545
|
)
|
|
546
546
|
|
|
547
|
+
soup = self.get_soup(response.content)
|
|
548
|
+
header_messages = soup.css.select(".messages[role='status'] ul > li")
|
|
549
|
+
|
|
550
|
+
# the top level message should indicate that the page could not be created
|
|
551
|
+
self.assertEqual(len(header_messages), 1)
|
|
552
|
+
message = header_messages[0]
|
|
553
|
+
self.assertIn(
|
|
554
|
+
"The page could not be created due to validation errors", message.get_text()
|
|
555
|
+
)
|
|
556
|
+
|
|
557
|
+
# the top level message should provide a go to error button
|
|
558
|
+
buttons = message.find_all("button")
|
|
559
|
+
self.assertEqual(len(buttons), 1)
|
|
560
|
+
self.assertEqual(buttons[0].attrs["data-controller"], "w-count w-focus")
|
|
561
|
+
self.assertIn("Go to the first error", buttons[0].get_text())
|
|
562
|
+
|
|
547
563
|
# Check that a form error was raised
|
|
548
564
|
self.assertFormError(
|
|
549
565
|
response.context["form"], "title", "This field is required."
|
|
@@ -760,6 +776,22 @@ class TestPageCreation(WagtailTestUtils, TestCase):
|
|
|
760
776
|
)
|
|
761
777
|
self.assertEqual(response.status_code, 200)
|
|
762
778
|
|
|
779
|
+
soup = self.get_soup(response.content)
|
|
780
|
+
header_messages = soup.css.select(".messages[role='status'] ul > li")
|
|
781
|
+
|
|
782
|
+
# the top level message should indicate that the page could not be created
|
|
783
|
+
self.assertEqual(len(header_messages), 1)
|
|
784
|
+
message = header_messages[0]
|
|
785
|
+
self.assertIn(
|
|
786
|
+
"The page could not be created due to validation errors", message.get_text()
|
|
787
|
+
)
|
|
788
|
+
|
|
789
|
+
# the top level message should provide a go to error button
|
|
790
|
+
buttons = message.find_all("button")
|
|
791
|
+
self.assertEqual(len(buttons), 1)
|
|
792
|
+
self.assertEqual(buttons[0].attrs["data-controller"], "w-count w-focus")
|
|
793
|
+
self.assertIn("Go to the first error", buttons[0].get_text())
|
|
794
|
+
|
|
763
795
|
# Check that a form error was raised
|
|
764
796
|
self.assertFormError(
|
|
765
797
|
response.context["form"], "date_from", "This field is required."
|
|
@@ -1144,7 +1176,7 @@ class TestPageCreation(WagtailTestUtils, TestCase):
|
|
|
1144
1176
|
self.assertFormError(
|
|
1145
1177
|
response.context["form"],
|
|
1146
1178
|
"expire_at",
|
|
1147
|
-
"Expiry date/time must be in the future",
|
|
1179
|
+
"Expiry date/time must be in the future.",
|
|
1148
1180
|
)
|
|
1149
1181
|
|
|
1150
1182
|
self.assertContains(
|
|
@@ -1328,7 +1360,7 @@ class TestPageCreation(WagtailTestUtils, TestCase):
|
|
|
1328
1360
|
self.assertFormError(
|
|
1329
1361
|
response.context["form"],
|
|
1330
1362
|
"slug",
|
|
1331
|
-
"The slug 'hello-world' is already in use within the parent page",
|
|
1363
|
+
"The slug 'hello-world' is already in use within the parent page.",
|
|
1332
1364
|
)
|
|
1333
1365
|
|
|
1334
1366
|
# form should be marked as having unsaved changes for the purposes of the dirty-forms warning
|
|
@@ -32,6 +32,7 @@ from wagtail.test.testapp.models import (
|
|
|
32
32
|
EVENT_AUDIENCE_CHOICES,
|
|
33
33
|
Advert,
|
|
34
34
|
AdvertPlacement,
|
|
35
|
+
CommentableJSONPage,
|
|
35
36
|
CustomPermissionPage,
|
|
36
37
|
EventCategory,
|
|
37
38
|
EventPage,
|
|
@@ -883,7 +884,7 @@ class TestPageEdit(WagtailTestUtils, TestCase):
|
|
|
883
884
|
self.assertFormError(
|
|
884
885
|
response.context["form"],
|
|
885
886
|
"expire_at",
|
|
886
|
-
"Expiry date/time must be in the future",
|
|
887
|
+
"Expiry date/time must be in the future.",
|
|
887
888
|
)
|
|
888
889
|
|
|
889
890
|
self.assertContains(
|
|
@@ -1749,7 +1750,7 @@ class TestPageEdit(WagtailTestUtils, TestCase):
|
|
|
1749
1750
|
self.assertFormError(
|
|
1750
1751
|
response.context["form"],
|
|
1751
1752
|
"slug",
|
|
1752
|
-
"The slug 'hello-world' is already in use within the parent page",
|
|
1753
|
+
"The slug 'hello-world' is already in use within the parent page.",
|
|
1753
1754
|
)
|
|
1754
1755
|
|
|
1755
1756
|
def test_preview_on_edit(self):
|
|
@@ -2986,12 +2987,31 @@ class TestValidationErrorMessages(WagtailTestUtils, TestCase):
|
|
|
2986
2987
|
)
|
|
2987
2988
|
self.assertEqual(response.status_code, 200)
|
|
2988
2989
|
|
|
2989
|
-
self.
|
|
2990
|
-
|
|
2990
|
+
soup = self.get_soup(response.content)
|
|
2991
|
+
|
|
2992
|
+
header_messages = soup.css.select(".messages[role='status'] ul > li")
|
|
2993
|
+
|
|
2994
|
+
# the top level message should indicate that the page could not be saved
|
|
2995
|
+
self.assertEqual(len(header_messages), 1)
|
|
2996
|
+
message = header_messages[0]
|
|
2997
|
+
self.assertIn(
|
|
2998
|
+
"The page could not be saved due to validation errors", message.get_text()
|
|
2991
2999
|
)
|
|
3000
|
+
|
|
3001
|
+
# the top level message should provide a go to error button
|
|
3002
|
+
buttons = message.find_all("button")
|
|
3003
|
+
self.assertEqual(len(buttons), 1)
|
|
3004
|
+
self.assertEqual(buttons[0].attrs["data-controller"], "w-count w-focus")
|
|
3005
|
+
self.assertIn("Go to the first error", buttons[0].get_text())
|
|
3006
|
+
|
|
2992
3007
|
# the error should only appear once: against the field, not in the header message
|
|
2993
|
-
|
|
2994
|
-
self.
|
|
3008
|
+
error_messages = soup.css.select(".error-message")
|
|
3009
|
+
self.assertEqual(len(error_messages), 1)
|
|
3010
|
+
error_message = error_messages[0]
|
|
3011
|
+
self.assertEqual(
|
|
3012
|
+
error_message.parent["id"], "panel-child-content-child-title-errors"
|
|
3013
|
+
)
|
|
3014
|
+
self.assertIn("This field is required", error_message.get_text())
|
|
2995
3015
|
|
|
2996
3016
|
def test_non_field_error(self):
|
|
2997
3017
|
"""Non-field errors should be shown in the header message"""
|
|
@@ -3070,19 +3090,43 @@ class TestValidationErrorMessages(WagtailTestUtils, TestCase):
|
|
|
3070
3090
|
)
|
|
3071
3091
|
self.assertEqual(response.status_code, 200)
|
|
3072
3092
|
|
|
3073
|
-
self.
|
|
3074
|
-
|
|
3093
|
+
soup = self.get_soup(response.content)
|
|
3094
|
+
|
|
3095
|
+
# there should be top level messages should indicate that the page could not be saved alongside other messages
|
|
3096
|
+
header_messages = soup.css.select(".messages[role='status'] ul > li")
|
|
3097
|
+
self.assertEqual(len(header_messages), 3)
|
|
3098
|
+
|
|
3099
|
+
# the first header message should indicate that the page could not be saved & contain a go to error button
|
|
3100
|
+
self.assertIn(
|
|
3101
|
+
"The page could not be saved due to validation errors",
|
|
3102
|
+
header_messages[0].get_text(),
|
|
3075
3103
|
)
|
|
3076
|
-
|
|
3077
|
-
|
|
3104
|
+
buttons = header_messages[0].find_all("button")
|
|
3105
|
+
self.assertEqual(len(buttons), 1)
|
|
3106
|
+
self.assertEqual(buttons[0].attrs["data-controller"], "w-count w-focus")
|
|
3107
|
+
self.assertIn("Go to the first error", buttons[0].get_text())
|
|
3108
|
+
|
|
3109
|
+
# the second should be a general message about the title, no go to error button
|
|
3110
|
+
self.assertIn(
|
|
3111
|
+
"Title: This field is required",
|
|
3112
|
+
header_messages[1].get_text(),
|
|
3113
|
+
)
|
|
3114
|
+
self.assertEqual(len(header_messages[1].find_all("button")), 0)
|
|
3115
|
+
|
|
3116
|
+
# the third header message should be the non-field error
|
|
3117
|
+
self.assertIn(
|
|
3118
|
+
"The end date must be after the start date",
|
|
3119
|
+
header_messages[2].get_text(),
|
|
3078
3120
|
)
|
|
3079
3121
|
|
|
3080
3122
|
# Error on title shown against the title field
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3123
|
+
error_messages = soup.css.select(".error-message")
|
|
3124
|
+
self.assertEqual(len(error_messages), 1)
|
|
3125
|
+
error_message = error_messages[0]
|
|
3126
|
+
self.assertEqual(
|
|
3127
|
+
error_message.parent["id"], "panel-child-content-child-title-errors"
|
|
3085
3128
|
)
|
|
3129
|
+
self.assertIn("This field is required.", error_message.get_text())
|
|
3086
3130
|
|
|
3087
3131
|
|
|
3088
3132
|
class TestNestedInlinePanel(WagtailTestUtils, TestCase):
|
|
@@ -4107,3 +4151,73 @@ class TestCommentOutput(WagtailTestUtils, TestCase):
|
|
|
4107
4151
|
comment_text = [comment["text"] for comment in comments_data["comments"]]
|
|
4108
4152
|
comment_text.sort()
|
|
4109
4153
|
self.assertEqual(comment_text, ["A test comment", "This is quite expensive"])
|
|
4154
|
+
|
|
4155
|
+
def test_comments_with_deep_contentpath_on_custom_fields(self):
|
|
4156
|
+
page = CommentableJSONPage(
|
|
4157
|
+
title="Commentable JSON Page",
|
|
4158
|
+
slug="commentable-json-page",
|
|
4159
|
+
commentable_body={
|
|
4160
|
+
"header": {
|
|
4161
|
+
"title": "Comments are Welcome",
|
|
4162
|
+
},
|
|
4163
|
+
},
|
|
4164
|
+
uncommentable_body={
|
|
4165
|
+
"title": "No feedback here",
|
|
4166
|
+
},
|
|
4167
|
+
stream_body=[
|
|
4168
|
+
{
|
|
4169
|
+
"id": "1",
|
|
4170
|
+
"type": "text",
|
|
4171
|
+
"value": "This allows comments",
|
|
4172
|
+
}
|
|
4173
|
+
],
|
|
4174
|
+
)
|
|
4175
|
+
self.root_page.add_child(instance=page)
|
|
4176
|
+
|
|
4177
|
+
Comment.objects.create(
|
|
4178
|
+
page=page,
|
|
4179
|
+
user=self.user,
|
|
4180
|
+
text="1. Comment on an existing JSON path in commentable JSONField",
|
|
4181
|
+
contentpath="commentable_body.header.title",
|
|
4182
|
+
)
|
|
4183
|
+
Comment.objects.create(
|
|
4184
|
+
page=page,
|
|
4185
|
+
user=self.user,
|
|
4186
|
+
text="2. Comment on a non-existing JSON path in commentable JSONField",
|
|
4187
|
+
contentpath="commentable_body.header.not_valid",
|
|
4188
|
+
)
|
|
4189
|
+
Comment.objects.create(
|
|
4190
|
+
page=page,
|
|
4191
|
+
user=self.user,
|
|
4192
|
+
text="3. Comment on an existing JSON path in base JSONField",
|
|
4193
|
+
contentpath="uncommentable_body.title",
|
|
4194
|
+
)
|
|
4195
|
+
Comment.objects.create(
|
|
4196
|
+
page=page,
|
|
4197
|
+
user=self.user,
|
|
4198
|
+
text="4. Comment on a non-existing JSON path in base JSONField",
|
|
4199
|
+
contentpath="uncommentable_body.not_valid",
|
|
4200
|
+
)
|
|
4201
|
+
Comment.objects.create(
|
|
4202
|
+
page=page,
|
|
4203
|
+
user=self.user,
|
|
4204
|
+
text="5. Comment on the top-level of a base JSONField",
|
|
4205
|
+
contentpath="uncommentable_body",
|
|
4206
|
+
)
|
|
4207
|
+
|
|
4208
|
+
response = self.client.get(reverse("wagtailadmin_pages:edit", args=[page.id]))
|
|
4209
|
+
soup = self.get_soup(response.content)
|
|
4210
|
+
comments_data_json = soup.select_one("#comments-data").string
|
|
4211
|
+
comments_data = json.loads(comments_data_json)
|
|
4212
|
+
comment_text = [comment["text"] for comment in comments_data["comments"]]
|
|
4213
|
+
comment_text.sort()
|
|
4214
|
+
|
|
4215
|
+
self.assertEqual(
|
|
4216
|
+
comment_text,
|
|
4217
|
+
[
|
|
4218
|
+
# Custom fields can define which paths are valid for comments
|
|
4219
|
+
"1. Comment on an existing JSON path in commentable JSONField",
|
|
4220
|
+
# Comments directly on the top-level (the field itself) are always valid
|
|
4221
|
+
"5. Comment on the top-level of a base JSONField",
|
|
4222
|
+
],
|
|
4223
|
+
)
|
|
@@ -180,13 +180,15 @@ class TestPageExplorer(WagtailTestUtils, TestCase):
|
|
|
180
180
|
self.root_page.add_child(instance=event_page)
|
|
181
181
|
|
|
182
182
|
orderings = {
|
|
183
|
-
"
|
|
184
|
-
|
|
185
|
-
|
|
183
|
+
"content_type__model": (
|
|
184
|
+
# SimplePage, SingleEventPage, StandardIndex
|
|
185
|
+
[self.new_page.id, event_page.id, self.old_page.id],
|
|
186
|
+
"-content_type__model",
|
|
186
187
|
),
|
|
187
|
-
"-
|
|
188
|
-
|
|
189
|
-
|
|
188
|
+
"-content_type__model": (
|
|
189
|
+
# StandardIndex, SingleEventPage, SimplePage
|
|
190
|
+
[self.old_page.id, event_page.id, self.new_page.id],
|
|
191
|
+
"content_type__model",
|
|
190
192
|
),
|
|
191
193
|
}
|
|
192
194
|
url = reverse("wagtailadmin_explore", args=(self.root_page.id,))
|
|
@@ -345,7 +347,31 @@ class TestPageExplorer(WagtailTestUtils, TestCase):
|
|
|
345
347
|
)
|
|
346
348
|
|
|
347
349
|
# Pages must not be paginated
|
|
348
|
-
self.assertNotIsInstance(response.context["
|
|
350
|
+
self.assertNotIsInstance(response.context["page_obj"], paginator.Page)
|
|
351
|
+
|
|
352
|
+
def test_reordering_disabled_when_searching_or_filtering(self):
|
|
353
|
+
standard_index_ct = ContentType.objects.get_for_model(StandardIndex).pk
|
|
354
|
+
cases = [
|
|
355
|
+
{"q": "old"},
|
|
356
|
+
{"content_type": standard_index_ct},
|
|
357
|
+
{"content_type": standard_index_ct, "q": "old"},
|
|
358
|
+
]
|
|
359
|
+
for query in cases:
|
|
360
|
+
with self.subTest(query=query):
|
|
361
|
+
response = self.client.get(
|
|
362
|
+
reverse("wagtailadmin_explore", args=(self.root_page.id,)),
|
|
363
|
+
{"ordering": "ord", **query},
|
|
364
|
+
)
|
|
365
|
+
self.assertEqual(response.status_code, 200)
|
|
366
|
+
self.assertTemplateUsed(
|
|
367
|
+
response, "wagtailadmin/pages/explorable_index.html"
|
|
368
|
+
)
|
|
369
|
+
self.assertEqual(
|
|
370
|
+
response.context["ordering"],
|
|
371
|
+
"-latest_revision_created_at",
|
|
372
|
+
)
|
|
373
|
+
# Pages is paginated
|
|
374
|
+
self.assertIsInstance(response.context["page_obj"], paginator.Page)
|
|
349
375
|
|
|
350
376
|
def test_construct_explorer_page_queryset_hook(self):
|
|
351
377
|
# testapp implements a construct_explorer_page_queryset hook
|
|
@@ -421,6 +447,7 @@ class TestPageExplorer(WagtailTestUtils, TestCase):
|
|
|
421
447
|
self.assertTemplateUsed(response, "wagtailadmin/pages/explorable_index.html")
|
|
422
448
|
|
|
423
449
|
# Check that we got the correct page
|
|
450
|
+
self.assertIsInstance(response.context["page_obj"], paginator.Page)
|
|
424
451
|
self.assertEqual(response.context["page_obj"].number, 2)
|
|
425
452
|
self.assertContains(response, "51-100 of 153")
|
|
426
453
|
|
|
@@ -70,6 +70,17 @@ class TestPageReorder(WagtailTestUtils, TestCase):
|
|
|
70
70
|
child_slugs = self.index_page.get_children().values_list("slug", flat=True)
|
|
71
71
|
self.assertListEqual(list(child_slugs), ["child-2", "child-3", "child-1"])
|
|
72
72
|
|
|
73
|
+
def test_page_set_page_position_non_integer_position_moves_it_to_the_end(self):
|
|
74
|
+
response = self.client.post(
|
|
75
|
+
reverse("wagtailadmin_pages:set_page_position", args=(self.child_1.id,))
|
|
76
|
+
+ "?position=good"
|
|
77
|
+
)
|
|
78
|
+
self.assertEqual(response.status_code, 200)
|
|
79
|
+
|
|
80
|
+
# check if child_1 is the last child page:
|
|
81
|
+
child_slugs = self.index_page.get_children().values_list("slug", flat=True)
|
|
82
|
+
self.assertListEqual(list(child_slugs), ["child-2", "child-3", "child-1"])
|
|
83
|
+
|
|
73
84
|
def test_page_move_page_position_up(self):
|
|
74
85
|
"""Moves child 3 to the first position."""
|
|
75
86
|
response = self.client.post(
|
|
@@ -781,6 +781,18 @@ class TestSetCollectionPrivacy(CollectionInstanceTestUtils, WagtailTestUtils, Te
|
|
|
781
781
|
params,
|
|
782
782
|
)
|
|
783
783
|
|
|
784
|
+
def test_privacy_for_collection(self):
|
|
785
|
+
response = self.get(self.finance_collection.id)
|
|
786
|
+
|
|
787
|
+
# Check response
|
|
788
|
+
self.assertEqual(response.status_code, 200)
|
|
789
|
+
self.assertTemplateUsed(response, "wagtailadmin/shared/set_privacy.html")
|
|
790
|
+
self.assertEqual(response.context["object"], self.finance_collection)
|
|
791
|
+
self.assertEqual(
|
|
792
|
+
response.context["action_url"],
|
|
793
|
+
"/admin/collections/{}/privacy/".format(self.finance_collection.id),
|
|
794
|
+
)
|
|
795
|
+
|
|
784
796
|
def test_get_private_child(self):
|
|
785
797
|
CollectionViewRestriction.objects.create(
|
|
786
798
|
collection=self.root_collection,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from collections.abc import Mapping
|
|
2
2
|
from datetime import date, datetime, timezone
|
|
3
3
|
from functools import wraps
|
|
4
|
-
from typing import Any
|
|
4
|
+
from typing import Any
|
|
5
5
|
from unittest import mock
|
|
6
6
|
|
|
7
7
|
from django import VERSION as DJANGO_VERSION
|
|
@@ -871,8 +871,8 @@ class TestFieldPanel(TestCase):
|
|
|
871
871
|
|
|
872
872
|
def _get_form(
|
|
873
873
|
self,
|
|
874
|
-
data:
|
|
875
|
-
fields:
|
|
874
|
+
data: Mapping[str, Any] | None = None,
|
|
875
|
+
fields: list[str] | None = None,
|
|
876
876
|
) -> WagtailAdminPageForm:
|
|
877
877
|
cls = get_form_for_model(
|
|
878
878
|
EventPage,
|
|
@@ -75,7 +75,7 @@ class TestFilteredModelChoiceField(WagtailTestUtils, TestCase):
|
|
|
75
75
|
users = FilteredModelChoiceField(
|
|
76
76
|
queryset=User.objects.order_by(User.USERNAME_FIELD),
|
|
77
77
|
filter_field="id_group",
|
|
78
|
-
filter_accessor=lambda user: user.groups.all(),
|
|
78
|
+
filter_accessor=lambda user: user.groups.all().order_by("name"),
|
|
79
79
|
)
|
|
80
80
|
|
|
81
81
|
form = UserForm()
|
|
@@ -83,7 +83,7 @@ class TestFilteredModelChoiceField(WagtailTestUtils, TestCase):
|
|
|
83
83
|
expected_html = """
|
|
84
84
|
<select name="users" data-widget="filtered-select" data-filter-field="id_group" required id="id_users">
|
|
85
85
|
<option value="" selected>---------</option>
|
|
86
|
-
<option value="{david}" data-filter-value="{
|
|
86
|
+
<option value="{david}" data-filter-value="{actors},{musicians}">{david_username}</option>
|
|
87
87
|
<option value="{kevin}" data-filter-value="{actors}">{kevin_username}</option>
|
|
88
88
|
<option value="{morten}" data-filter-value="{musicians}">{morten_username}</option>
|
|
89
89
|
</select>
|