wagtail 6.2.2__py3-none-any.whl → 6.3rc2__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_for_translation.py +6 -0
- wagtail/actions/publish_revision.py +3 -3
- wagtail/admin/action_menu.py +5 -3
- wagtail/admin/forms/account.py +1 -1
- wagtail/admin/icons.py +2 -6
- wagtail/admin/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/cy/LC_MESSAGES/django.po +32 -0
- wagtail/admin/locale/dv/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/dv/LC_MESSAGES/django.po +28 -0
- wagtail/admin/locale/en/LC_MESSAGES/django.po +451 -485
- wagtail/admin/locale/en/LC_MESSAGES/djangojs.po +7 -7
- wagtail/admin/locale/sl/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/sl/LC_MESSAGES/django.po +150 -0
- wagtail/admin/locale/sl/LC_MESSAGES/djangojs.mo +0 -0
- wagtail/admin/locale/sl/LC_MESSAGES/djangojs.po +9 -2
- wagtail/admin/locale/ug/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/ug/LC_MESSAGES/django.po +3250 -196
- wagtail/admin/localization.py +12 -2
- wagtail/admin/panels/model_utils.py +1 -1
- wagtail/admin/site_summary.py +0 -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/email-header.jpg +0 -0
- wagtail/admin/static/wagtailadmin/js/bulk-actions.js +1 -1
- wagtail/admin/static/wagtailadmin/js/core.js +1 -1
- wagtail/admin/static/wagtailadmin/js/core.js.LICENSE.txt +12 -0
- wagtail/admin/static/wagtailadmin/js/draftail.js +1 -1
- wagtail/admin/static/wagtailadmin/js/sidebar.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 +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor.js +1 -1
- wagtail/admin/static/wagtailadmin/js/wagtailadmin.js +1 -1
- wagtail/admin/static/wagtailadmin/js/workflow-action.js +1 -1
- wagtail/admin/staticfiles.py +6 -4
- wagtail/admin/templates/wagtailadmin/account/account.html +42 -59
- wagtail/admin/templates/wagtailadmin/admin_base.html +0 -28
- wagtail/admin/templates/wagtailadmin/bulk_actions/footer.html +1 -1
- wagtail/admin/templates/wagtailadmin/chooser/_search_results.html +7 -5
- wagtail/admin/templates/wagtailadmin/chooser/tables/page_navigate_to_children_cell.html +1 -1
- wagtail/admin/templates/wagtailadmin/generic/chooser/results.html +7 -5
- wagtail/admin/templates/wagtailadmin/generic/edit.html +0 -8
- wagtail/admin/templates/wagtailadmin/generic/form.html +60 -17
- wagtail/admin/templates/wagtailadmin/generic/index.html +17 -0
- wagtail/admin/templates/wagtailadmin/generic/index_results.html +9 -35
- wagtail/admin/templates/wagtailadmin/generic/inspect.html +2 -21
- wagtail/admin/templates/wagtailadmin/generic/listing.html +11 -17
- wagtail/admin/templates/wagtailadmin/generic/listing_results.html +19 -1
- wagtail/admin/templates/wagtailadmin/home/account_summary.html +26 -0
- wagtail/admin/templates/wagtailadmin/home/locked_pages.html +28 -18
- wagtail/admin/templates/wagtailadmin/home/recent_edits.html +28 -17
- wagtail/admin/templates/wagtailadmin/home/site_summary_pages.html +2 -2
- wagtail/admin/templates/wagtailadmin/home/upgrade_notification.html +35 -13
- wagtail/admin/templates/wagtailadmin/home/user_objects_in_workflow_moderation.html +28 -18
- wagtail/admin/templates/wagtailadmin/home/workflow_objects_to_moderate.html +43 -32
- wagtail/admin/templates/wagtailadmin/home.html +22 -5
- wagtail/admin/templates/wagtailadmin/pages/_editor_js.html +0 -1
- wagtail/admin/templates/wagtailadmin/pages/action_menu/menu.html +1 -11
- wagtail/admin/templates/wagtailadmin/pages/action_menu/menu_item.html +1 -6
- wagtail/admin/templates/wagtailadmin/pages/action_menu/page_locked.html +1 -1
- wagtail/admin/templates/wagtailadmin/pages/action_menu/publish.html +1 -1
- wagtail/admin/templates/wagtailadmin/pages/action_menu/save_draft.html +1 -1
- wagtail/admin/templates/wagtailadmin/pages/bulk_actions/confirm_bulk_delete.html +12 -6
- wagtail/admin/templates/wagtailadmin/pages/bulk_actions/confirm_bulk_move.html +12 -7
- wagtail/admin/templates/wagtailadmin/pages/bulk_actions/confirm_bulk_publish.html +17 -11
- wagtail/admin/templates/wagtailadmin/pages/bulk_actions/confirm_bulk_unpublish.html +15 -9
- wagtail/admin/templates/wagtailadmin/pages/confirm_delete.html +9 -9
- wagtail/admin/templates/wagtailadmin/pages/confirm_move.html +2 -2
- wagtail/admin/templates/wagtailadmin/pages/confirm_unpublish.html +4 -4
- wagtail/admin/templates/wagtailadmin/pages/create.html +15 -34
- wagtail/admin/templates/wagtailadmin/pages/edit.html +15 -30
- wagtail/admin/templates/wagtailadmin/pages/explorable_index.html +6 -0
- wagtail/admin/templates/wagtailadmin/pages/explorable_index_results.html +60 -0
- wagtail/admin/templates/wagtailadmin/pages/index.html +1 -36
- wagtail/admin/templates/wagtailadmin/pages/index_results.html +2 -50
- wagtail/admin/templates/wagtailadmin/pages/listing/_locked_indicator.html +1 -1
- wagtail/admin/templates/wagtailadmin/pages/listing/_ordering_cell.html +1 -1
- wagtail/admin/templates/wagtailadmin/pages/listing/_page_header_buttons.html +1 -1
- wagtail/admin/templates/wagtailadmin/pages/listing/_page_title_column_header.html +3 -3
- wagtail/admin/templates/wagtailadmin/pages/listing/_pagination.html +1 -1
- wagtail/admin/templates/wagtailadmin/pages/listing.html +24 -0
- wagtail/admin/templates/wagtailadmin/pages/search.html +1 -20
- wagtail/admin/templates/wagtailadmin/pages/search_results.html +27 -25
- wagtail/admin/templates/wagtailadmin/permissions/includes/collection_member_permissions_formset.html +0 -1
- wagtail/admin/templates/wagtailadmin/reports/listing/_list_page_report.html +2 -2
- wagtail/admin/templates/wagtailadmin/reports/listing/_list_page_types_usage.html +6 -6
- wagtail/admin/templates/wagtailadmin/reports/workflow_tasks_results.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/action_menu/menu.html +14 -0
- wagtail/admin/templates/wagtailadmin/shared/action_menu/menu_item.html +6 -0
- wagtail/admin/templates/wagtailadmin/shared/avatar.html +13 -3
- wagtail/admin/templates/wagtailadmin/shared/header.html +0 -5
- wagtail/admin/templates/wagtailadmin/shared/headers/slim_header.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/page_status_tag_new.html +4 -1
- wagtail/admin/templates/wagtailadmin/shared/pagination_nav.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/side_panel_toggle.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/status/locale.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/status/usage.html +2 -2
- wagtail/admin/templates/wagtailadmin/shared/side_panels/preview.html +94 -52
- wagtail/admin/templates/wagtailadmin/{pages/_unsaved_changes_warning.html → shared/unsaved_changes_warning.html} +4 -4
- wagtail/admin/templates/wagtailadmin/shared/usage_summary.html +2 -2
- wagtail/admin/templates/wagtailadmin/shared/workflow_history/detail.html +1 -7
- wagtail/admin/templates/wagtailadmin/shared/workflow_history/listing.html +1 -0
- wagtail/admin/templates/wagtailadmin/shared/workflow_history/{list.html → listing_results.html} +33 -35
- wagtail/admin/templates/wagtailadmin/tables/references_cell.html +1 -1
- wagtail/admin/templates/wagtailadmin/workflows/create.html +11 -36
- wagtail/admin/templates/wagtailadmin/workflows/create_task.html +0 -38
- wagtail/admin/templates/wagtailadmin/workflows/edit.html +44 -74
- wagtail/admin/templates/wagtailadmin/workflows/edit_task.html +27 -66
- wagtail/admin/templates/wagtailadmin/workflows/includes/task_usage_cell.html +4 -2
- wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_tasks_cell.html +4 -4
- wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_used_by_cell.html +15 -11
- wagtail/admin/templates/wagtailadmin/workflows/task_chooser/includes/results.html +7 -5
- wagtail/admin/templatetags/wagtailadmin_tags.py +51 -22
- wagtail/admin/tests/pages/test_content_type_use_view.py +82 -2
- wagtail/admin/tests/pages/test_edit_page.py +70 -0
- wagtail/admin/tests/pages/test_explorer_view.py +65 -4
- wagtail/admin/tests/pages/test_page_search.py +8 -7
- wagtail/admin/tests/pages/test_page_usage.py +3 -1
- wagtail/admin/tests/pages/test_preview.py +208 -63
- wagtail/admin/tests/pages/test_reorder_page.py +91 -1
- wagtail/admin/tests/pages/test_view_draft.py +32 -1
- wagtail/admin/tests/pages/test_workflow_history.py +288 -7
- wagtail/admin/tests/test_account_management.py +23 -3
- wagtail/admin/tests/test_audit_log.py +24 -2
- wagtail/admin/tests/test_collections_views.py +17 -5
- wagtail/admin/tests/test_dashboard.py +1 -1
- wagtail/admin/tests/test_edit_handlers.py +3 -2
- wagtail/admin/tests/test_icon_sprite.py +4 -0
- wagtail/admin/tests/test_privacy.py +5 -19
- wagtail/admin/tests/test_reports_views.py +1 -1
- wagtail/admin/tests/test_site_summary.py +3 -3
- wagtail/admin/tests/test_templatetags.py +27 -3
- wagtail/admin/tests/test_upgrade_notification.py +71 -18
- wagtail/admin/tests/test_views.py +2 -2
- wagtail/admin/tests/test_views_generic.py +13 -0
- wagtail/admin/tests/test_widgets.py +3 -3
- wagtail/admin/tests/test_workflows.py +172 -27
- wagtail/admin/tests/tests.py +1 -1
- wagtail/admin/tests/viewsets/test_model_viewset.py +55 -3
- wagtail/admin/ui/side_panels.py +19 -0
- wagtail/admin/ui/sidebar.py +4 -3
- wagtail/admin/ui/tables/__init__.py +14 -1
- wagtail/admin/ui/tables/pages.py +6 -1
- wagtail/admin/urls/pages.py +10 -1
- wagtail/admin/urls/workflows.py +6 -1
- wagtail/admin/views/account.py +5 -1
- wagtail/admin/views/collections.py +0 -2
- wagtail/admin/views/generic/base.py +118 -1
- wagtail/admin/views/generic/history.py +158 -26
- wagtail/admin/views/generic/models.py +113 -99
- wagtail/admin/views/home.py +24 -9
- wagtail/admin/views/page_privacy.py +54 -30
- wagtail/admin/views/pages/history.py +11 -4
- wagtail/admin/views/pages/listing.py +76 -89
- wagtail/admin/views/pages/preview.py +1 -1
- wagtail/admin/views/pages/search.py +27 -71
- wagtail/admin/views/pages/usage.py +63 -24
- wagtail/admin/views/pages/utils.py +4 -3
- wagtail/admin/views/reports/base.py +0 -6
- wagtail/admin/views/workflows.py +67 -25
- wagtail/admin/viewsets/model.py +4 -3
- wagtail/admin/widgets/chooser.py +2 -1
- wagtail/api/v2/tests/test_pages.py +15 -2
- wagtail/blocks/field_block.py +15 -3
- wagtail/blocks/static_block.py +3 -0
- wagtail/contrib/forms/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/forms/locale/cy/LC_MESSAGES/django.po +29 -1
- wagtail/contrib/forms/locale/en/LC_MESSAGES/django.po +15 -11
- wagtail/contrib/forms/templates/wagtailforms/confirm_delete.html +1 -0
- wagtail/contrib/forms/templates/wagtailforms/index.html +1 -1
- wagtail/contrib/forms/templates/wagtailforms/index_results.html +1 -1
- wagtail/contrib/forms/templates/wagtailforms/list_submissions.html +2 -1
- wagtail/contrib/forms/templates/wagtailforms/panels/form_responses_panel.html +2 -2
- wagtail/contrib/forms/tests/test_views.py +234 -35
- wagtail/contrib/forms/utils.py +8 -14
- wagtail/contrib/forms/views.py +72 -27
- wagtail/contrib/frontend_cache/backends/azure.py +1 -1
- wagtail/contrib/frontend_cache/backends/cloudfront.py +2 -2
- wagtail/contrib/frontend_cache/backends/dummy.py +11 -0
- wagtail/contrib/frontend_cache/tests.py +31 -37
- wagtail/contrib/frontend_cache/utils.py +12 -5
- wagtail/contrib/redirects/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/redirects/locale/cy/LC_MESSAGES/django.po +16 -1
- wagtail/contrib/redirects/locale/en/LC_MESSAGES/django.po +20 -24
- wagtail/contrib/redirects/models.py +16 -1
- wagtail/contrib/redirects/signal_handlers.py +18 -3
- wagtail/contrib/redirects/templates/wagtailredirects/add.html +5 -16
- wagtail/contrib/redirects/templates/wagtailredirects/import_summary.html +1 -1
- wagtail/contrib/redirects/tests/test_redirects.py +49 -6
- wagtail/contrib/redirects/tests/test_signal_handlers.py +42 -1
- wagtail/contrib/redirects/views.py +27 -3
- wagtail/contrib/search_promotions/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/search_promotions/locale/cy/LC_MESSAGES/django.po +60 -1
- wagtail/contrib/search_promotions/locale/en/LC_MESSAGES/django.po +12 -18
- wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/add.html +5 -8
- wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/edit.html +15 -10
- wagtail/contrib/search_promotions/tests.py +13 -2
- wagtail/contrib/search_promotions/views.py +15 -3
- wagtail/contrib/settings/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/settings/locale/cy/LC_MESSAGES/django.po +6 -1
- wagtail/contrib/settings/locale/en/LC_MESSAGES/django.po +2 -10
- wagtail/contrib/settings/templates/wagtailsettings/edit.html +12 -45
- wagtail/contrib/simple_translation/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/simple_translation/locale/cy/LC_MESSAGES/django.po +13 -1
- wagtail/contrib/simple_translation/locale/dv/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/simple_translation/locale/dv/LC_MESSAGES/django.po +3 -0
- wagtail/contrib/simple_translation/locale/en/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/simple_translation/locale/sl/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/simple_translation/locale/sl/LC_MESSAGES/django.po +5 -2
- wagtail/contrib/simple_translation/tests/test_views.py +51 -0
- wagtail/contrib/simple_translation/wagtail_hooks.py +16 -11
- wagtail/contrib/styleguide/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/styleguide/locale/cy/LC_MESSAGES/django.po +5 -1
- wagtail/contrib/styleguide/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/table_block/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/table_block/locale/cy/LC_MESSAGES/django.po +27 -1
- wagtail/contrib/table_block/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/typed_table_block/blocks.py +25 -0
- wagtail/contrib/typed_table_block/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/typed_table_block/locale/cy/LC_MESSAGES/django.po +12 -1
- wagtail/contrib/typed_table_block/locale/en/LC_MESSAGES/django.po +10 -10
- wagtail/contrib/typed_table_block/tests.py +24 -1
- wagtail/coreutils.py +5 -11
- wagtail/documents/admin_urls.py +2 -2
- wagtail/documents/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/documents/locale/cy/LC_MESSAGES/django.po +10 -0
- wagtail/documents/locale/en/LC_MESSAGES/django.po +61 -76
- wagtail/documents/migrations/0014_alter_document_file_size.py +18 -0
- wagtail/documents/models.py +1 -1
- wagtail/documents/rich_text/__init__.py +1 -3
- wagtail/documents/static/wagtaildocs/js/add-multiple.js +1 -1
- wagtail/documents/templates/wagtaildocs/bulk_actions/confirm_bulk_add_tags.html +5 -1
- wagtail/documents/templates/wagtaildocs/bulk_actions/confirm_bulk_add_to_collection.html +5 -1
- wagtail/documents/templates/wagtaildocs/bulk_actions/confirm_bulk_delete.html +11 -5
- wagtail/documents/templates/wagtaildocs/documents/add.html +13 -41
- wagtail/documents/templates/wagtaildocs/documents/edit.html +28 -56
- wagtail/documents/templates/wagtaildocs/documents/index.html +1 -4
- wagtail/documents/templates/wagtaildocs/homepage/site_summary_documents.html +2 -2
- wagtail/documents/templates/wagtaildocs/multiple/add.html +36 -41
- wagtail/documents/tests/test_admin_views.py +64 -6
- wagtail/documents/tests/test_site_summary.py +3 -3
- wagtail/documents/views/documents.py +103 -113
- wagtail/documents/views/multiple.py +19 -1
- wagtail/embeds/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/embeds/oembed_providers.py +9 -19
- wagtail/fields.py +43 -27
- wagtail/images/admin_urls.py +2 -2
- wagtail/images/blocks.py +230 -2
- wagtail/images/fields.py +17 -29
- wagtail/images/image_operations.py +1 -1
- wagtail/images/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/cy/LC_MESSAGES/django.po +128 -1
- wagtail/images/locale/en/LC_MESSAGES/django.po +119 -129
- wagtail/images/migrations/0025_alter_image_file_alter_rendition_file.py +36 -43
- wagtail/images/migrations/0027_image_description.py +20 -0
- wagtail/images/models.py +120 -45
- wagtail/images/rich_text/__init__.py +1 -3
- wagtail/images/static/wagtailimages/js/add-multiple.js +1 -1
- wagtail/images/static/wagtailimages/js/image-block.js +1 -0
- wagtail/images/templates/wagtailimages/bulk_actions/confirm_bulk_add_tags.html +5 -1
- wagtail/images/templates/wagtailimages/bulk_actions/confirm_bulk_add_to_collection.html +5 -1
- wagtail/images/templates/wagtailimages/bulk_actions/confirm_bulk_delete.html +11 -5
- wagtail/images/templates/wagtailimages/chooser/results.html +2 -2
- wagtail/images/templates/wagtailimages/homepage/site_summary_images.html +2 -2
- wagtail/images/templates/wagtailimages/images/_file_field.html +2 -2
- wagtail/images/templates/wagtailimages/images/add.html +13 -31
- wagtail/images/templates/wagtailimages/images/edit.html +53 -82
- wagtail/images/templates/wagtailimages/images/index.html +1 -4
- wagtail/images/templates/wagtailimages/images/url_generator.html +1 -1
- wagtail/images/templates/wagtailimages/multiple/add.html +40 -47
- wagtail/images/templates/wagtailimages/widgets/image.html +5 -0
- wagtail/images/templates/wagtailimages/widgets/image_chooser.html +1 -1
- wagtail/images/tests/test_admin_views.py +70 -10
- wagtail/images/tests/test_blocks.py +367 -1
- wagtail/images/tests/test_image_operations.py +23 -0
- wagtail/images/tests/test_models.py +20 -0
- wagtail/images/tests/test_signal_handlers.py +99 -95
- wagtail/images/tests/test_site_summary.py +3 -3
- wagtail/images/tests/test_templatetags.py +11 -7
- wagtail/images/tests/tests.py +4 -0
- wagtail/images/views/images.py +103 -104
- wagtail/images/views/multiple.py +17 -1
- wagtail/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/locale/cy/LC_MESSAGES/django.po +3 -0
- wagtail/locale/en/LC_MESSAGES/django.po +137 -125
- wagtail/locale/sl/LC_MESSAGES/django.mo +0 -0
- wagtail/locale/sl/LC_MESSAGES/django.po +3 -0
- wagtail/locales/locale/en/LC_MESSAGES/django.po +8 -8
- wagtail/locales/views.py +4 -1
- wagtail/migrations/0089_log_entry_data_json_null_to_object.py +1 -7
- wagtail/models/__init__.py +122 -14
- wagtail/models/audit_log.py +1 -3
- wagtail/models/i18n.py +1 -2
- wagtail/project_template/Dockerfile +3 -3
- wagtail/project_template/requirements.txt +2 -2
- wagtail/query.py +17 -4
- wagtail/rich_text/__init__.py +2 -3
- wagtail/rich_text/pages.py +2 -4
- wagtail/rich_text/rewriters.py +2 -2
- wagtail/search/backends/database/mysql/query.py +3 -3
- wagtail/search/backends/database/sqlite/query.py +6 -6
- wagtail/search/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/sites/locale/en/LC_MESSAGES/django.po +6 -6
- wagtail/sites/views.py +0 -1
- wagtail/snippets/action_menu.py +14 -4
- wagtail/snippets/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/snippets/locale/cy/LC_MESSAGES/django.po +73 -1
- wagtail/snippets/locale/en/LC_MESSAGES/django.po +27 -33
- 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/bulk_actions/confirm_bulk_delete.html +5 -3
- wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/locked.html +1 -1
- wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/menu.html +1 -11
- wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/menu_item.html +1 -6
- wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/publish.html +1 -1
- wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/save.html +1 -1
- wagtail/snippets/templates/wagtailsnippets/snippets/create.html +1 -18
- wagtail/snippets/templates/wagtailsnippets/snippets/edit.html +1 -14
- wagtail/snippets/templates/wagtailsnippets/snippets/index.html +2 -5
- wagtail/snippets/tests/test_preview.py +193 -61
- wagtail/snippets/tests/test_snippets.py +247 -38
- wagtail/snippets/tests/test_usage.py +5 -0
- wagtail/snippets/tests/test_viewset.py +25 -9
- wagtail/snippets/tests/test_workflows.py +232 -19
- wagtail/snippets/views/snippets.py +1 -10
- wagtail/test/numberformat.py +104 -0
- wagtail/test/settings.py +10 -0
- wagtail/test/settings_ui.py +2 -0
- wagtail/test/testapp/migrations/0010_alter_customimage_file_and_more.py +71 -78
- wagtail/test/testapp/migrations/0040_nocreatablesubpagetypespage_nosubpagetypespage.py +54 -0
- wagtail/test/testapp/migrations/0041_alter_jsonstreammodel_options.py +17 -0
- wagtail/test/testapp/migrations/0042_alter_customdocument_file_size_and_more.py +28 -0
- wagtail/test/testapp/migrations/0043_customimage_description.py +41 -0
- wagtail/test/testapp/migrations/0044_custompreviewsizesmodel_custompreviewsizespage.py +52 -0
- wagtail/test/testapp/migrations/0045_alter_streampage_body.py +52 -0
- wagtail/test/testapp/models.py +62 -4
- wagtail/test/testapp/rich_text.py +2 -2
- wagtail/test/testapp/templates/tests/form_page_landing.html +2 -1
- wagtail/test/testapp/urls.py +5 -0
- wagtail/test/testapp/views.py +5 -0
- wagtail/test/utils/page_tests.py +5 -5
- wagtail/test/utils/template_tests.py +2 -2
- wagtail/tests/test_blocks.py +15 -0
- wagtail/tests/test_page_permissions.py +109 -0
- wagtail/tests/test_revision_model.py +27 -0
- wagtail/tests/test_signals.py +21 -2
- wagtail/tests/test_tests.py +30 -0
- wagtail/users/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/cy/LC_MESSAGES/django.po +118 -1
- wagtail/users/locale/dv/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/dv/LC_MESSAGES/django.po +3 -0
- wagtail/users/locale/en/LC_MESSAGES/django.po +89 -113
- wagtail/users/locale/sl/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/sl/LC_MESSAGES/django.po +3 -0
- wagtail/users/migrations/0014_userprofile_contrast.py +23 -0
- wagtail/users/models.py +11 -0
- wagtail/users/templates/wagtailusers/bulk_actions/confirm_bulk_assign_role.html +5 -1
- wagtail/users/templates/wagtailusers/bulk_actions/confirm_bulk_delete.html +5 -1
- wagtail/users/templates/wagtailusers/bulk_actions/confirm_bulk_set_active_state.html +5 -1
- wagtail/users/templates/wagtailusers/groups/create.html +19 -17
- wagtail/users/templates/wagtailusers/groups/edit.html +2 -40
- wagtail/users/templates/wagtailusers/groups/includes/formatted_permissions.html +1 -62
- wagtail/users/templates/wagtailusers/groups/includes/page_permissions_formset.html +0 -1
- wagtail/users/templates/wagtailusers/users/create.html +46 -50
- wagtail/users/templates/wagtailusers/users/edit.html +45 -62
- wagtail/users/templates/wagtailusers/users/index.html +1 -4
- wagtail/users/templatetags/wagtailusers_tags.py +1 -5
- wagtail/users/tests/test_admin_views.py +85 -66
- wagtail/users/views/groups.py +4 -1
- wagtail/users/views/users.py +2 -0
- {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/METADATA +6 -6
- {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/RECORD +378 -367
- wagtail/admin/static/wagtailadmin/js/preview-panel.js +0 -2
- wagtail/admin/static/wagtailadmin/js/preview-panel.js.LICENSE.txt +0 -11
- wagtail/admin/templates/wagtailadmin/generic/history_results.html +0 -1
- wagtail/admin/templates/wagtailadmin/page_privacy/ancestor_privacy.html +0 -3
- wagtail/admin/templates/wagtailadmin/pages/usage_results.html +0 -6
- wagtail/admin/templates/wagtailadmin/shared/workflow_history/index.html +0 -17
- wagtail/admin/templates/wagtailadmin/shared/workflow_history/results.html +0 -17
- wagtail/admin/templates/wagtailadmin/workflows/usage.html +0 -44
- {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/LICENSE +0 -0
- {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/WHEEL +0 -0
- {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/entry_points.txt +0 -0
- {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/top_level.txt +0 -0
wagtail/fields.py
CHANGED
|
@@ -3,7 +3,6 @@ import json
|
|
|
3
3
|
from django.core.serializers.json import DjangoJSONEncoder
|
|
4
4
|
from django.core.validators import MaxLengthValidator
|
|
5
5
|
from django.db import models
|
|
6
|
-
from django.db.models.fields.json import KeyTransform
|
|
7
6
|
from django.utils.encoding import force_str
|
|
8
7
|
from django.utils.functional import cached_property
|
|
9
8
|
|
|
@@ -185,6 +184,7 @@ class StreamField(models.Field):
|
|
|
185
184
|
return result
|
|
186
185
|
|
|
187
186
|
def get_prep_value(self, value):
|
|
187
|
+
value = super().get_prep_value(value)
|
|
188
188
|
if (
|
|
189
189
|
isinstance(value, StreamValue)
|
|
190
190
|
and not (value)
|
|
@@ -197,36 +197,37 @@ class StreamField(models.Field):
|
|
|
197
197
|
return value.raw_text
|
|
198
198
|
elif isinstance(value, StreamValue):
|
|
199
199
|
# StreamValue instances must be prepared first.
|
|
200
|
-
return
|
|
201
|
-
self.stream_block.get_prep_value(value), cls=DjangoJSONEncoder
|
|
202
|
-
)
|
|
200
|
+
return self.stream_block.get_prep_value(value)
|
|
203
201
|
else:
|
|
204
|
-
#
|
|
205
|
-
#
|
|
206
|
-
|
|
207
|
-
return self.json_field.get_prep_value(value)
|
|
202
|
+
# If the value is not a StreamValue, it's likely the field is being
|
|
203
|
+
# used in a non-Wagtail context, e.g. in queries with JSONField features.
|
|
204
|
+
return super().get_prep_value(value)
|
|
208
205
|
|
|
209
206
|
def get_db_prep_value(self, value, connection, prepared=False):
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
207
|
+
# Use JSONField's get_db_prep_value method to handle the serialization,
|
|
208
|
+
# which may differ between database backends. However, use our own
|
|
209
|
+
# get_prep_value method to ensure that StreamValue instances are prepared
|
|
210
|
+
# before being passed to JSONField.
|
|
211
|
+
if not prepared:
|
|
212
|
+
value = self.get_prep_value(value)
|
|
213
|
+
return self.json_field.get_db_prep_value(
|
|
214
|
+
value, connection=connection, prepared=True
|
|
215
|
+
)
|
|
216
216
|
|
|
217
217
|
def from_db_value(self, value, expression, connection):
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
218
|
+
# Historically, StreamField's deserialization used to be handled by
|
|
219
|
+
# to_python, which in turn handled by BaseStreamBlock.to_python. This was
|
|
220
|
+
# always the case even before and after the use of the JSON data type.
|
|
221
|
+
|
|
222
|
+
# However, now that we can be confident all StreamField data has been
|
|
223
|
+
# migrated to use JSON in the database, we can reuse any special handling
|
|
224
|
+
# that JSONField.from_db_value provides, e.g. for handling KeyTransforms
|
|
225
|
+
# on SQLite.
|
|
226
|
+
|
|
227
|
+
# This means we are passing a deserialized value to StreamBlock.to_python,
|
|
228
|
+
# which is a change from the previous behaviour. However, this is fine
|
|
229
|
+
# because to_python can handle both serialized and deserialized values.
|
|
230
|
+
value = self.json_field.from_db_value(value, expression, connection)
|
|
230
231
|
return self.to_python(value)
|
|
231
232
|
|
|
232
233
|
def formfield(self, **kwargs):
|
|
@@ -239,8 +240,23 @@ class StreamField(models.Field):
|
|
|
239
240
|
return super().formfield(**defaults)
|
|
240
241
|
|
|
241
242
|
def value_to_string(self, obj):
|
|
243
|
+
# This method is used for serialization using django.core.serializers,
|
|
244
|
+
# which is used by dumpdata and loaddata for serializing model objects.
|
|
245
|
+
# Unlike other fields, JSONField only uses value_from_object without
|
|
246
|
+
# doing the actual serialization, so that it doesn't end up being
|
|
247
|
+
# double-serialized when the model object is serialized.
|
|
248
|
+
|
|
249
|
+
# Unfortunately, this is also used by django-modelcluster, which is used
|
|
250
|
+
# to serialize model objects to be stored in revisions. When we migrated
|
|
251
|
+
# StreamField to use the JSON data type, we did not change this method's
|
|
252
|
+
# behaviour, i.e. it still returns a JSON-shaped string, to ensure that
|
|
253
|
+
# revisions are still saved in the same format as before – even if it
|
|
254
|
+
# means StreamField inside the revision data becomes double-serialized.
|
|
255
|
+
|
|
256
|
+
# Now that we change get_prep_value to not do the serialization in favor
|
|
257
|
+
# of get_db_prep_value, we need to add the serialization here too.
|
|
242
258
|
value = self.value_from_object(obj)
|
|
243
|
-
return self.get_prep_value(value)
|
|
259
|
+
return json.dumps(self.get_prep_value(value), cls=self.json_field.encoder)
|
|
244
260
|
|
|
245
261
|
def get_searchable_content(self, value):
|
|
246
262
|
return self.stream_block.get_searchable_content(value)
|
wagtail/images/admin_urls.py
CHANGED
|
@@ -6,7 +6,7 @@ app_name = "wagtailimages"
|
|
|
6
6
|
urlpatterns = [
|
|
7
7
|
path("", images.IndexView.as_view(), name="index"),
|
|
8
8
|
path("results/", images.IndexView.as_view(results_only=True), name="index_results"),
|
|
9
|
-
path("<int:image_id>/", images.
|
|
9
|
+
path("<int:image_id>/", images.EditView.as_view(), name="edit"),
|
|
10
10
|
path("<int:image_id>/delete/", images.DeleteView.as_view(), name="delete"),
|
|
11
11
|
path(
|
|
12
12
|
"<int:image_id>/generate_url/",
|
|
@@ -19,7 +19,7 @@ urlpatterns = [
|
|
|
19
19
|
name="generate_url",
|
|
20
20
|
),
|
|
21
21
|
path("<int:image_id>/preview/<str:filter_spec>/", images.preview, name="preview"),
|
|
22
|
-
path("add/", images.
|
|
22
|
+
path("add/", images.CreateView.as_view(), name="add"),
|
|
23
23
|
path("usage/<int:image_id>/", images.UsageView.as_view(), name="image_usage"),
|
|
24
24
|
path("multiple/add/", multiple.AddView.as_view(), name="add_multiple"),
|
|
25
25
|
path("multiple/<int:image_id>/", multiple.EditView.as_view(), name="edit_multiple"),
|
wagtail/images/blocks.py
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
|
+
from django import forms
|
|
2
|
+
from django.core.exceptions import ValidationError
|
|
1
3
|
from django.template.loader import render_to_string
|
|
2
4
|
from django.utils.functional import cached_property
|
|
5
|
+
from django.utils.translation import gettext_lazy as _
|
|
3
6
|
|
|
4
|
-
from wagtail.admin.compare import BlockComparison
|
|
5
|
-
from wagtail.blocks import ChooserBlock
|
|
7
|
+
from wagtail.admin.compare import BlockComparison, StructBlockComparison
|
|
8
|
+
from wagtail.blocks import BooleanBlock, CharBlock, ChooserBlock, StructBlock
|
|
9
|
+
from wagtail.blocks.struct_block import StructBlockAdapter, StructBlockValidationError
|
|
10
|
+
from wagtail.images.models import AbstractImage
|
|
11
|
+
from wagtail.telepath import register
|
|
6
12
|
|
|
7
13
|
from .shortcuts import get_rendition_or_not_found
|
|
8
14
|
|
|
@@ -51,3 +57,225 @@ class ImageChooserBlockComparison(BlockComparison):
|
|
|
51
57
|
"image_b": self.val_b,
|
|
52
58
|
},
|
|
53
59
|
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class ImageBlock(StructBlock):
|
|
63
|
+
"""
|
|
64
|
+
An usage of ImageChooserBlock with support for alt text.
|
|
65
|
+
For backward compatibility, this block overrides necessary methods to change
|
|
66
|
+
the StructValue to be an Image model instance, making it compatible in
|
|
67
|
+
places where ImageChooserBlock was used.
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
image = ImageChooserBlock(required=True)
|
|
71
|
+
decorative = BooleanBlock(
|
|
72
|
+
default=False, required=False, label=_("Image is decorative")
|
|
73
|
+
)
|
|
74
|
+
alt_text = CharBlock(required=False, label=_("Alt text"))
|
|
75
|
+
|
|
76
|
+
def __init__(self, required=True, **kwargs):
|
|
77
|
+
super().__init__(
|
|
78
|
+
[
|
|
79
|
+
("image", ImageChooserBlock(required=required)),
|
|
80
|
+
(
|
|
81
|
+
"decorative",
|
|
82
|
+
BooleanBlock(
|
|
83
|
+
default=False, required=False, label=_("Image is decorative")
|
|
84
|
+
),
|
|
85
|
+
),
|
|
86
|
+
("alt_text", CharBlock(required=False, label=_("Alt text"))),
|
|
87
|
+
],
|
|
88
|
+
**kwargs,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
def deconstruct(self):
|
|
92
|
+
"""
|
|
93
|
+
For typical StructBlock subclasses, it makes sense for the deconstructed block object to be a basic StructBlock
|
|
94
|
+
with the child blocks passed to the constructor (because this is largely functionally identical to the
|
|
95
|
+
subclass, and avoids embedding a reference to a potentially-volatile custom class in migrations).
|
|
96
|
+
|
|
97
|
+
This is not the case for ImageBlock, as it overrides enough of StructBlock's behaviour that a basic StructBlock
|
|
98
|
+
is not a suitable substitute - and also has an incompatible constructor signature (as we don't want to support
|
|
99
|
+
passing child blocks to it).
|
|
100
|
+
|
|
101
|
+
Therefore, we opt out of the standard StructBlock deconstruction behaviour here, and always
|
|
102
|
+
deconstruct an ImageBlock as an ImageBlock.
|
|
103
|
+
"""
|
|
104
|
+
return ("wagtail.images.blocks.ImageBlock", [], self._constructor_kwargs)
|
|
105
|
+
|
|
106
|
+
def deconstruct_with_lookup(self, lookup):
|
|
107
|
+
return self.deconstruct()
|
|
108
|
+
|
|
109
|
+
@classmethod
|
|
110
|
+
def construct_from_lookup(cls, lookup, *args, **kwargs):
|
|
111
|
+
return cls(**kwargs)
|
|
112
|
+
|
|
113
|
+
def get_searchable_content(self, value):
|
|
114
|
+
if not self.search_index or not value:
|
|
115
|
+
return []
|
|
116
|
+
|
|
117
|
+
return self.child_blocks["alt_text"].get_searchable_content(
|
|
118
|
+
value.contextual_alt_text
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
def _struct_value_to_image(self, struct_value):
|
|
122
|
+
image = struct_value.get("image")
|
|
123
|
+
decorative = struct_value.get("decorative")
|
|
124
|
+
if image:
|
|
125
|
+
# If the image is decorative, set alt_text to an empty string
|
|
126
|
+
image.contextual_alt_text = (
|
|
127
|
+
"" if decorative else struct_value.get("alt_text")
|
|
128
|
+
)
|
|
129
|
+
image.decorative = decorative
|
|
130
|
+
return image
|
|
131
|
+
|
|
132
|
+
def _image_to_struct_value(self, image):
|
|
133
|
+
return {
|
|
134
|
+
"image": image,
|
|
135
|
+
"alt_text": image and image.contextual_alt_text,
|
|
136
|
+
"decorative": image and image.decorative,
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
def to_python(self, value):
|
|
140
|
+
# For backward compatibility with ImageChooserBlock
|
|
141
|
+
if isinstance(value, int):
|
|
142
|
+
image = self.child_blocks["image"].to_python(value)
|
|
143
|
+
struct_value = {"image": image, "decorative": False, "alt_text": None}
|
|
144
|
+
else:
|
|
145
|
+
struct_value = super().to_python(value)
|
|
146
|
+
return self._struct_value_to_image(struct_value)
|
|
147
|
+
|
|
148
|
+
def bulk_to_python(self, values):
|
|
149
|
+
values = list(values)
|
|
150
|
+
|
|
151
|
+
if not values:
|
|
152
|
+
return []
|
|
153
|
+
|
|
154
|
+
if isinstance(values[0], int):
|
|
155
|
+
# `values` is a list of image IDs (as we might encounter if an ImageChooserBlock has been
|
|
156
|
+
# changed to an ImageBlock with no data migration)
|
|
157
|
+
image_values = self.child_blocks["image"].bulk_to_python(values)
|
|
158
|
+
|
|
159
|
+
struct_values = [
|
|
160
|
+
{
|
|
161
|
+
"image": image,
|
|
162
|
+
"decorative": False,
|
|
163
|
+
"alt_text": None,
|
|
164
|
+
}
|
|
165
|
+
for image in image_values
|
|
166
|
+
]
|
|
167
|
+
|
|
168
|
+
else:
|
|
169
|
+
# assume `values` is a list of dicts containing `image`, `decorative` and `alt_text` keys
|
|
170
|
+
# to be handled by the StructBlock superclass
|
|
171
|
+
struct_values = super().bulk_to_python(values)
|
|
172
|
+
|
|
173
|
+
return [
|
|
174
|
+
self._struct_value_to_image(struct_value) for struct_value in struct_values
|
|
175
|
+
]
|
|
176
|
+
|
|
177
|
+
def value_from_datadict(self, data, files, prefix):
|
|
178
|
+
struct_value = super().value_from_datadict(data, files, prefix)
|
|
179
|
+
return self._struct_value_to_image(struct_value)
|
|
180
|
+
|
|
181
|
+
def clean(self, value):
|
|
182
|
+
try:
|
|
183
|
+
self.child_blocks["image"].clean(value)
|
|
184
|
+
except ValidationError as e:
|
|
185
|
+
raise StructBlockValidationError(
|
|
186
|
+
block_errors={"image": e},
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
if value and not value.contextual_alt_text and not value.decorative:
|
|
190
|
+
raise StructBlockValidationError(
|
|
191
|
+
block_errors={
|
|
192
|
+
"alt_text": ValidationError(
|
|
193
|
+
_(
|
|
194
|
+
"Please add some alt text for your image or mark it as decorative"
|
|
195
|
+
)
|
|
196
|
+
)
|
|
197
|
+
}
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
return value
|
|
201
|
+
|
|
202
|
+
def normalize(self, value):
|
|
203
|
+
if value is None or isinstance(value, AbstractImage):
|
|
204
|
+
return value
|
|
205
|
+
else:
|
|
206
|
+
struct_value = super().normalize(value)
|
|
207
|
+
return self._struct_value_to_image(struct_value)
|
|
208
|
+
|
|
209
|
+
def get_form_context(self, value, prefix="", errors=None):
|
|
210
|
+
dict_value = {
|
|
211
|
+
"image": value,
|
|
212
|
+
"alt_text": value and value.contextual_alt_text,
|
|
213
|
+
"decorative": value and value.decorative,
|
|
214
|
+
}
|
|
215
|
+
context = super().get_form_context(dict_value, prefix=prefix, errors=errors)
|
|
216
|
+
context["suggested_alt_text"] = value
|
|
217
|
+
return context
|
|
218
|
+
|
|
219
|
+
def get_form_state(self, value):
|
|
220
|
+
return {
|
|
221
|
+
"image": self.child_blocks["image"].get_form_state(value),
|
|
222
|
+
"alt_text": value and value.contextual_alt_text,
|
|
223
|
+
"decorative": value and value.decorative,
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
def get_prep_value(self, value):
|
|
227
|
+
return {
|
|
228
|
+
"image": self.child_blocks["image"].get_prep_value(value),
|
|
229
|
+
"alt_text": value and value.contextual_alt_text,
|
|
230
|
+
"decorative": value and value.decorative,
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
def extract_references(self, value):
|
|
234
|
+
return self.child_blocks["image"].extract_references(value)
|
|
235
|
+
|
|
236
|
+
def get_comparison_class(self):
|
|
237
|
+
return ImageBlockComparison
|
|
238
|
+
|
|
239
|
+
def get_api_representation(self, value, context=None):
|
|
240
|
+
return super().get_api_representation(
|
|
241
|
+
self._image_to_struct_value(value), context=context
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
def render_basic(self, value, context=None):
|
|
245
|
+
return self.child_blocks["image"].render_basic(value, context=context)
|
|
246
|
+
|
|
247
|
+
class Meta:
|
|
248
|
+
icon = "image"
|
|
249
|
+
template = "wagtailimages/widgets/image.html"
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
class ImageBlockAdapter(StructBlockAdapter):
|
|
253
|
+
js_constructor = "wagtail.images.blocks.ImageBlock"
|
|
254
|
+
|
|
255
|
+
@cached_property
|
|
256
|
+
def media(self):
|
|
257
|
+
structblock_media = super().media
|
|
258
|
+
return forms.Media(
|
|
259
|
+
js=structblock_media._js + ["wagtailimages/js/image-block.js"],
|
|
260
|
+
css=structblock_media._css,
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
register(ImageBlockAdapter(), ImageBlock)
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
class ImageBlockComparison(StructBlockComparison):
|
|
268
|
+
def __init__(self, block, exists_a, exists_b, val_a, val_b):
|
|
269
|
+
super().__init__(
|
|
270
|
+
block,
|
|
271
|
+
exists_a,
|
|
272
|
+
exists_b,
|
|
273
|
+
block._image_to_struct_value(val_a),
|
|
274
|
+
block._image_to_struct_value(val_b),
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
def htmlvalue(self, val):
|
|
278
|
+
if isinstance(val, AbstractImage):
|
|
279
|
+
return super().htmlvalue(self.block._image_to_struct_value(val))
|
|
280
|
+
else:
|
|
281
|
+
return super().htmlvalue(val)
|
wagtail/images/fields.py
CHANGED
|
@@ -6,6 +6,7 @@ from django.conf import settings
|
|
|
6
6
|
from django.core.exceptions import ValidationError
|
|
7
7
|
from django.core.validators import FileExtensionValidator
|
|
8
8
|
from django.forms.fields import FileField, ImageField
|
|
9
|
+
from django.forms.widgets import FileInput
|
|
9
10
|
from django.template.defaultfilters import filesizeformat
|
|
10
11
|
from django.utils.translation import gettext_lazy as _
|
|
11
12
|
|
|
@@ -32,6 +33,8 @@ class WagtailImageField(ImageField):
|
|
|
32
33
|
default_validators = [ImageFileExtensionValidator]
|
|
33
34
|
|
|
34
35
|
def __init__(self, *args, **kwargs):
|
|
36
|
+
self.allowed_image_extensions = get_allowed_image_extensions()
|
|
37
|
+
|
|
35
38
|
super().__init__(*args, **kwargs)
|
|
36
39
|
|
|
37
40
|
# Get max upload size from settings
|
|
@@ -43,8 +46,6 @@ class WagtailImageField(ImageField):
|
|
|
43
46
|
)
|
|
44
47
|
self.max_upload_size_text = filesizeformat(self.max_upload_size)
|
|
45
48
|
|
|
46
|
-
self.allowed_image_extensions = get_allowed_image_extensions()
|
|
47
|
-
|
|
48
49
|
self.supported_formats_text = ", ".join(self.allowed_image_extensions).upper()
|
|
49
50
|
|
|
50
51
|
# Help text
|
|
@@ -163,7 +164,7 @@ class WagtailImageField(ImageField):
|
|
|
163
164
|
# Annotate the python representation of the FileField with the image
|
|
164
165
|
# property so subclasses can reuse it for their own validation
|
|
165
166
|
f.image = willow.Image.open(file)
|
|
166
|
-
f.content_type =
|
|
167
|
+
f.content_type = f.image.mime_type
|
|
167
168
|
|
|
168
169
|
except Exception as exc: # noqa: BLE001
|
|
169
170
|
# Willow doesn't recognize it as an image.
|
|
@@ -182,30 +183,17 @@ class WagtailImageField(ImageField):
|
|
|
182
183
|
|
|
183
184
|
return f
|
|
184
185
|
|
|
186
|
+
def widget_attrs(self, widget):
|
|
187
|
+
attrs = super().widget_attrs(widget)
|
|
188
|
+
|
|
189
|
+
if (
|
|
190
|
+
isinstance(widget, FileInput)
|
|
191
|
+
and "accept" not in widget.attrs
|
|
192
|
+
and attrs.get("accept") == "image/*"
|
|
193
|
+
and "heic" in self.allowed_image_extensions
|
|
194
|
+
):
|
|
195
|
+
# File upload dialogs (at least on Chrome / Mac) don't count heic as part of image/*, as it's not a
|
|
196
|
+
# web-safe format, so add it explicitly
|
|
197
|
+
attrs["accept"] = "image/*, image/heic"
|
|
185
198
|
|
|
186
|
-
|
|
187
|
-
"""
|
|
188
|
-
Convert a Willow image format name to a content type.
|
|
189
|
-
TODO: Replace once https://github.com/wagtail/Willow/pull/102 and
|
|
190
|
-
a new Willow release is out
|
|
191
|
-
"""
|
|
192
|
-
if image_format_name == "svg":
|
|
193
|
-
return "image/svg+xml"
|
|
194
|
-
elif image_format_name == "jpeg":
|
|
195
|
-
return "image/jpeg"
|
|
196
|
-
elif image_format_name == "png":
|
|
197
|
-
return "image/png"
|
|
198
|
-
elif image_format_name == "gif":
|
|
199
|
-
return "image/gif"
|
|
200
|
-
elif image_format_name == "bmp":
|
|
201
|
-
return "image/bmp"
|
|
202
|
-
elif image_format_name == "tiff":
|
|
203
|
-
return "image/tiff"
|
|
204
|
-
elif image_format_name == "webp":
|
|
205
|
-
return "image/webp"
|
|
206
|
-
elif image_format_name == "avif":
|
|
207
|
-
return "image/avif"
|
|
208
|
-
elif image_format_name == "ico":
|
|
209
|
-
return "image/x-icon"
|
|
210
|
-
else:
|
|
211
|
-
raise ValueError("Unknown image format name")
|
|
199
|
+
return attrs
|
|
@@ -409,7 +409,7 @@ class WebPQualityOperation(FilterOperation):
|
|
|
409
409
|
|
|
410
410
|
|
|
411
411
|
class FormatOperation(FilterOperation):
|
|
412
|
-
supported_formats = ["jpeg", "png", "gif", "webp", "avif", "ico"]
|
|
412
|
+
supported_formats = ["jpeg", "png", "gif", "webp", "avif", "ico", "heic"]
|
|
413
413
|
|
|
414
414
|
def construct(self, format, *options):
|
|
415
415
|
self.format = format
|
|
Binary file
|
|
@@ -6,13 +6,14 @@
|
|
|
6
6
|
# Adam Hughes <adamhughes31@gmail.com>, 2020
|
|
7
7
|
# Philip Crisp, 2022
|
|
8
8
|
# Philip Crisp, 2022
|
|
9
|
+
# Philip Lindsay-Crisp, 2024
|
|
9
10
|
msgid ""
|
|
10
11
|
msgstr ""
|
|
11
12
|
"Project-Id-Version: Wagtail\n"
|
|
12
13
|
"Report-Msgid-Bugs-To: \n"
|
|
13
14
|
"POT-Creation-Date: 2024-08-07 10:06+0100\n"
|
|
14
15
|
"PO-Revision-Date: 2014-02-20 21:05+0000\n"
|
|
15
|
-
"Last-Translator: Philip Crisp,
|
|
16
|
+
"Last-Translator: Philip Lindsay-Crisp, 2024\n"
|
|
16
17
|
"Language-Team: Welsh (http://app.transifex.com/torchbox/wagtail/language/"
|
|
17
18
|
"cy/)\n"
|
|
18
19
|
"MIME-Version: 1.0\n"
|
|
@@ -162,6 +163,14 @@ msgstr "delwedd"
|
|
|
162
163
|
msgid "images"
|
|
163
164
|
msgstr "delweddau"
|
|
164
165
|
|
|
166
|
+
#, python-format
|
|
167
|
+
msgid "Add tags to 1 image"
|
|
168
|
+
msgid_plural "Add tags to %(counter)s images"
|
|
169
|
+
msgstr[0] "Ychwanegu 1 tag i l;lun"
|
|
170
|
+
msgstr[1] "Ychwanegu tagiau i %(counter)s llun"
|
|
171
|
+
msgstr[2] "Ychwanegu tagiau i %(counter)s llun"
|
|
172
|
+
msgstr[3] "Ychwanegu tagiau i %(counter)s llun"
|
|
173
|
+
|
|
165
174
|
msgid "Add tags to images"
|
|
166
175
|
msgstr "Ychwanegu tagiau i lluniau"
|
|
167
176
|
|
|
@@ -185,6 +194,14 @@ msgstr "Ia, ychwanegu"
|
|
|
185
194
|
msgid "No, don't add"
|
|
186
195
|
msgstr "Na, paid a ychwanegu"
|
|
187
196
|
|
|
197
|
+
#, python-format
|
|
198
|
+
msgid "Add 1 image to new collection"
|
|
199
|
+
msgid_plural "Add %(counter)s images to new collection"
|
|
200
|
+
msgstr[0] "Ychwanegu 1 casgliad newydd"
|
|
201
|
+
msgstr[1] "Ychwanegu %(counter)s defnyddio casgliad newydd"
|
|
202
|
+
msgstr[2] "Ychwanegu %(counter)s defnyddio casgliad newydd"
|
|
203
|
+
msgstr[3] "Ychwanegu %(counter)s defnyddio casgliad newydd"
|
|
204
|
+
|
|
188
205
|
msgid "Add images to collection"
|
|
189
206
|
msgstr "Ychwanegu lluniau i'r casgliad"
|
|
190
207
|
|
|
@@ -254,18 +271,72 @@ msgstr "Na, peidiwch a ddileu"
|
|
|
254
271
|
msgid "Popular tags"
|
|
255
272
|
msgstr "Tagiau poblogaidd"
|
|
256
273
|
|
|
274
|
+
msgid ""
|
|
275
|
+
"Upload successful. However, your new image seems to be a duplicate of an "
|
|
276
|
+
"existing image. You may delete it if it wasn't required."
|
|
277
|
+
msgstr ""
|
|
278
|
+
"Llwytho i fyny yn llwyddiannus. Fodd bynnag, mae'n ymddangos bod eich llun "
|
|
279
|
+
"newydd yn ddyblyg o llun sy'n bodoli eisoes. Gallwch ei ddileu os nad oedd "
|
|
280
|
+
"ei angen."
|
|
281
|
+
|
|
282
|
+
msgid "Existing"
|
|
283
|
+
msgstr "Presennol"
|
|
284
|
+
|
|
257
285
|
msgid "New"
|
|
258
286
|
msgstr "Newydd"
|
|
259
287
|
|
|
288
|
+
msgid "Use new image"
|
|
289
|
+
msgstr "Defyddio llun newydd."
|
|
290
|
+
|
|
291
|
+
msgid "Use existing and delete new"
|
|
292
|
+
msgstr "Defnyddio presennol a dileu'r newydd"
|
|
293
|
+
|
|
260
294
|
msgid "Latest images"
|
|
261
295
|
msgstr "Lluniau diweddaraf"
|
|
262
296
|
|
|
297
|
+
#, python-format
|
|
298
|
+
msgid "Select %(title)s"
|
|
299
|
+
msgstr "Dewis %(title)s"
|
|
300
|
+
|
|
301
|
+
msgid "You haven't uploaded any images in this collection."
|
|
302
|
+
msgstr "Nid ydych wedi uwchlwytho unrhyw ddelweddau yn y casgliad hwn."
|
|
303
|
+
|
|
304
|
+
msgid "You haven't uploaded any images."
|
|
305
|
+
msgstr "Nid ydych wedi uwchlwytho unrhyw ddelweddau."
|
|
306
|
+
|
|
307
|
+
msgid ""
|
|
308
|
+
"Why not <a class=\"upload-one-now\" href=\"#tab-upload\" data-tab-"
|
|
309
|
+
"trigger>upload one now</a>?"
|
|
310
|
+
msgstr ""
|
|
311
|
+
"Beth am <a class=\"upload-one-now\" href=\"#tab-upload\" data-tab-"
|
|
312
|
+
"trigger>uwchlwytho un rwan</a>?"
|
|
313
|
+
|
|
263
314
|
msgid "Choose a format"
|
|
264
315
|
msgstr "Dewisiwch fformat"
|
|
265
316
|
|
|
266
317
|
msgid "Insert image"
|
|
267
318
|
msgstr "Mewnosod llun"
|
|
268
319
|
|
|
320
|
+
#, python-format
|
|
321
|
+
msgid ""
|
|
322
|
+
"<span>%(total)s</span> Image <span class=\"w-sr-only\">created in "
|
|
323
|
+
"%(site_name)s</span>"
|
|
324
|
+
msgid_plural ""
|
|
325
|
+
"<span>%(total)s</span> Images <span class=\"w-sr-only\">created in "
|
|
326
|
+
"%(site_name)s</span>"
|
|
327
|
+
msgstr[0] ""
|
|
328
|
+
"<span>%(total)s</span> llun <span class=\"w-sr-only\">wedi'i greu i "
|
|
329
|
+
"%(site_name)s</span>"
|
|
330
|
+
msgstr[1] ""
|
|
331
|
+
"<span>%(total)s</span> lluniau <span class=\"w-sr-only\">wedi'i greu "
|
|
332
|
+
"%(site_name)s</span>"
|
|
333
|
+
msgstr[2] ""
|
|
334
|
+
"<span>%(total)s</span> lluniau <span class=\"w-sr-only\">wedi'i greu "
|
|
335
|
+
"%(site_name)s</span>"
|
|
336
|
+
msgstr[3] ""
|
|
337
|
+
"<span>%(total)s</span> lluniau <span class=\"w-sr-only\">wedi'i greu i "
|
|
338
|
+
"%(site_name)s</span>"
|
|
339
|
+
|
|
269
340
|
msgid "Change image file:"
|
|
270
341
|
msgstr "Newid ffeil llun:"
|
|
271
342
|
|
|
@@ -278,6 +349,12 @@ msgstr "Ychwanegu llun"
|
|
|
278
349
|
msgid "Save"
|
|
279
350
|
msgstr "Cadw"
|
|
280
351
|
|
|
352
|
+
msgid "Keep new image"
|
|
353
|
+
msgstr "Cadw llun newydd"
|
|
354
|
+
|
|
355
|
+
msgid "Delete new image"
|
|
356
|
+
msgstr "Dileu llun newydd"
|
|
357
|
+
|
|
281
358
|
#, python-format
|
|
282
359
|
msgid "Editing image %(title)s"
|
|
283
360
|
msgstr "Golygu llun %(title)s"
|
|
@@ -288,6 +365,9 @@ msgstr "Golygu"
|
|
|
288
365
|
msgid "Delete image"
|
|
289
366
|
msgstr "Dileu delwedd"
|
|
290
367
|
|
|
368
|
+
msgid "Image focal point"
|
|
369
|
+
msgstr "Ffocws llun"
|
|
370
|
+
|
|
291
371
|
msgid "URL Generator"
|
|
292
372
|
msgstr "Cynhyrchydd URL"
|
|
293
373
|
|
|
@@ -322,6 +402,9 @@ msgstr "Ffeil heb ei chanfod"
|
|
|
322
402
|
msgid "Usage"
|
|
323
403
|
msgstr "Defnydd"
|
|
324
404
|
|
|
405
|
+
msgid "Sort by"
|
|
406
|
+
msgstr "Trefnu un ôl"
|
|
407
|
+
|
|
325
408
|
msgid "Select all images in listing"
|
|
326
409
|
msgstr "Dewiswch yr holl lluniau yn y rhestr"
|
|
327
410
|
|
|
@@ -352,6 +435,18 @@ msgstr "Rhagolwg"
|
|
|
352
435
|
msgid "URL"
|
|
353
436
|
msgstr "URL"
|
|
354
437
|
|
|
438
|
+
msgid "Image URL"
|
|
439
|
+
msgstr "URL Llun"
|
|
440
|
+
|
|
441
|
+
msgid "Copy URL"
|
|
442
|
+
msgstr "URL Copi"
|
|
443
|
+
|
|
444
|
+
msgid "Copied to clipboard"
|
|
445
|
+
msgstr "Wedi'i gopïo i'r clipfwrdd"
|
|
446
|
+
|
|
447
|
+
msgid "Copying to clipboard failed"
|
|
448
|
+
msgstr "Methodd copïo i'r clipfwrdd"
|
|
449
|
+
|
|
355
450
|
msgid "Add multiple images"
|
|
356
451
|
msgstr "Ychwanegu lluniau lluosog"
|
|
357
452
|
|
|
@@ -376,6 +471,14 @@ msgstr ""
|
|
|
376
471
|
"priodol, os oes angen. Gallwch hefyd ddileu'r llun yn gyfan gwbl os nad oedd "
|
|
377
472
|
"angen yr uwchlwythiad."
|
|
378
473
|
|
|
474
|
+
msgid ""
|
|
475
|
+
"Upload successful. However, your new image seems to be a duplicate of this "
|
|
476
|
+
"existing image. You may delete it if it wasn't required."
|
|
477
|
+
msgstr ""
|
|
478
|
+
"Llwytho i fyny yn llwyddiannus. Fodd bynnag, mae'n ymddangos bod eich llun "
|
|
479
|
+
"newydd yn ddyblyg o'r llun bresennol hon. Gallwch ei ddileu os nad oedd ei "
|
|
480
|
+
"angen."
|
|
481
|
+
|
|
379
482
|
msgid "Sorry, upload failed."
|
|
380
483
|
msgstr "Mae'n ddrwg gennym, ni fu modd uwchlwytho."
|
|
381
484
|
|
|
@@ -397,6 +500,9 @@ msgstr "Caniatadau llun"
|
|
|
397
500
|
msgid "Add an image permission"
|
|
398
501
|
msgstr "Ychwanegu caniatad llun"
|
|
399
502
|
|
|
503
|
+
msgid "Tags"
|
|
504
|
+
msgstr "Tagiau"
|
|
505
|
+
|
|
400
506
|
msgid "Tag"
|
|
401
507
|
msgstr "Tag"
|
|
402
508
|
|
|
@@ -452,9 +558,30 @@ msgstr "Wrthi'n uwchlwytho…"
|
|
|
452
558
|
msgid "Choose an image"
|
|
453
559
|
msgstr "Dewis delwedd"
|
|
454
560
|
|
|
561
|
+
msgid "Choose another image"
|
|
562
|
+
msgstr "Dewisiwch llun arall"
|
|
563
|
+
|
|
455
564
|
msgid "Edit this image"
|
|
456
565
|
msgstr "Golygu'r llun hon"
|
|
457
566
|
|
|
567
|
+
msgid "Newest"
|
|
568
|
+
msgstr "Ieuengaf"
|
|
569
|
+
|
|
570
|
+
msgid "Oldest"
|
|
571
|
+
msgstr "Hynaf"
|
|
572
|
+
|
|
573
|
+
msgid "Title: (A -> Z)"
|
|
574
|
+
msgstr "Teitl: (A -> Z)"
|
|
575
|
+
|
|
576
|
+
msgid "Title: (Z -> A)"
|
|
577
|
+
msgstr "Teitl: (Z -> A)"
|
|
578
|
+
|
|
579
|
+
msgid "File size: (low to high)"
|
|
580
|
+
msgstr "Maint ffeil: (isel i uchel)"
|
|
581
|
+
|
|
582
|
+
msgid "File size: (high to low)"
|
|
583
|
+
msgstr "Maint ffeil: (uchel i isel)"
|
|
584
|
+
|
|
458
585
|
msgid "Images"
|
|
459
586
|
msgstr "Delweddau"
|
|
460
587
|
|