wagtail 6.0.1__py3-none-any.whl → 6.1rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wagtail/__init__.py +1 -1
- wagtail/admin/checks.py +51 -0
- wagtail/admin/compare.py +1 -1
- wagtail/admin/filters.py +70 -1
- wagtail/admin/forms/account.py +1 -1
- wagtail/admin/forms/collections.py +15 -0
- wagtail/admin/forms/pages.py +49 -0
- wagtail/admin/locale/ca/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/ca/LC_MESSAGES/django.po +122 -0
- wagtail/admin/locale/de/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/de/LC_MESSAGES/django.po +5 -5
- wagtail/admin/locale/en/LC_MESSAGES/django.po +474 -385
- wagtail/admin/locale/en/LC_MESSAGES/djangojs.po +3 -3
- wagtail/admin/locale/es/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/es/LC_MESSAGES/django.po +6 -6
- wagtail/admin/locale/fr/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/fr/LC_MESSAGES/django.po +70 -3
- wagtail/admin/locale/he_IL/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/he_IL/LC_MESSAGES/django.po +2 -6
- wagtail/admin/locale/he_IL/LC_MESSAGES/djangojs.mo +0 -0
- wagtail/admin/locale/he_IL/LC_MESSAGES/djangojs.po +2 -2
- wagtail/admin/locale/hr_HR/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/hr_HR/LC_MESSAGES/django.po +4 -0
- wagtail/admin/locale/hu/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/hu/LC_MESSAGES/django.po +142 -2
- wagtail/admin/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/it/LC_MESSAGES/django.po +80 -8
- wagtail/admin/locale/it/LC_MESSAGES/djangojs.mo +0 -0
- wagtail/admin/locale/it/LC_MESSAGES/djangojs.po +14 -2
- wagtail/admin/locale/lv/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/lv/LC_MESSAGES/django.po +154 -1
- wagtail/admin/locale/pt_PT/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/pt_PT/LC_MESSAGES/django.po +73 -2
- wagtail/admin/locale/ro/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/ro/LC_MESSAGES/django.po +3 -3
- wagtail/admin/locale/sl/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/sl/LC_MESSAGES/django.po +145 -2
- wagtail/admin/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/sv/LC_MESSAGES/django.po +77 -3
- wagtail/admin/locale/zh_Hant/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/zh_Hant/LC_MESSAGES/django.po +17 -1
- wagtail/admin/panels/comment_panel.py +1 -1
- wagtail/admin/panels/field_panel.py +1 -1
- wagtail/admin/rich_text/converters/editor_html.py +3 -1
- wagtail/admin/rich_text/editors/draftail/__init__.py +28 -2
- wagtail/admin/static/wagtailadmin/css/core.css +1 -1
- wagtail/admin/static/wagtailadmin/css/panels/draftail.css +1 -1
- wagtail/admin/static/wagtailadmin/images/favicon.ico +0 -0
- wagtail/admin/static/wagtailadmin/js/bulk-actions.js +1 -1
- wagtail/admin/static/wagtailadmin/js/chooser-modal.js +1 -1
- wagtail/admin/static/wagtailadmin/js/chooser-widget-telepath.js +1 -1
- wagtail/admin/static/wagtailadmin/js/chooser-widget.js +1 -1
- wagtail/admin/static/wagtailadmin/js/comments.js +1 -1
- wagtail/admin/static/wagtailadmin/js/core.js +1 -1
- wagtail/admin/static/wagtailadmin/js/core.js.LICENSE.txt +1 -1
- wagtail/admin/static/wagtailadmin/js/date-time-chooser.js +1 -1
- wagtail/admin/static/wagtailadmin/js/draftail.js +1 -1
- wagtail/admin/static/wagtailadmin/js/expanding-formset.js +1 -1
- wagtail/admin/static/wagtailadmin/js/filtered-select.js +1 -1
- wagtail/admin/static/wagtailadmin/js/modal-workflow.js +1 -1
- wagtail/admin/static/wagtailadmin/js/page-chooser-modal.js +1 -1
- wagtail/admin/static/wagtailadmin/js/page-chooser-telepath.js +1 -1
- wagtail/admin/static/wagtailadmin/js/page-chooser.js +1 -1
- wagtail/admin/static/wagtailadmin/js/preview-panel.js +1 -1
- wagtail/admin/static/wagtailadmin/js/privacy-switch.js +1 -1
- wagtail/admin/static/wagtailadmin/js/sidebar.js +1 -1
- wagtail/admin/static/wagtailadmin/js/task-chooser-modal.js +1 -1
- wagtail/admin/static/wagtailadmin/js/task-chooser.js +1 -1
- wagtail/admin/static/wagtailadmin/js/telepath/blocks.js +1 -1
- wagtail/admin/static/wagtailadmin/js/telepath/telepath.js +1 -1
- wagtail/admin/static/wagtailadmin/js/telepath/widgets.js +1 -1
- wagtail/admin/static/wagtailadmin/js/userbar.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor.js.LICENSE.txt +4 -4
- wagtail/admin/static/wagtailadmin/js/wagtailadmin.js +1 -1
- wagtail/admin/static/wagtailadmin/js/workflow-action.js +1 -1
- wagtail/admin/staticfiles.py +1 -0
- wagtail/admin/templates/wagtailadmin/admin_base.html +1 -0
- wagtail/admin/templates/wagtailadmin/base.html +1 -0
- wagtail/admin/templates/wagtailadmin/collection_privacy/set_privacy.html +3 -1
- wagtail/admin/templates/wagtailadmin/collections/edit.html +0 -1
- wagtail/admin/templates/wagtailadmin/collections/index_results.html +10 -0
- wagtail/admin/templates/wagtailadmin/generic/base.html +1 -9
- wagtail/admin/templates/wagtailadmin/generic/form.html +4 -2
- wagtail/admin/templates/wagtailadmin/generic/history/action_cell.html +27 -0
- wagtail/admin/templates/wagtailadmin/generic/index_results.html +8 -0
- wagtail/admin/templates/wagtailadmin/home/workflow_objects_to_moderate.html +3 -4
- wagtail/admin/templates/wagtailadmin/icons/keyboard.svg +1 -0
- wagtail/admin/templates/wagtailadmin/page_privacy/set_privacy.html +3 -1
- wagtail/admin/templates/wagtailadmin/pages/_editor_js.html +0 -15
- wagtail/admin/templates/wagtailadmin/pages/action_menu/save_draft.html +3 -1
- wagtail/admin/templates/wagtailadmin/pages/choose_parent.html +17 -0
- wagtail/admin/templates/wagtailadmin/pages/explorable_index.html +8 -0
- wagtail/admin/templates/wagtailadmin/pages/history.html +1 -61
- wagtail/admin/templates/wagtailadmin/pages/index.html +1 -5
- wagtail/admin/templates/wagtailadmin/pages/listing/_locked_indicator.html +2 -2
- wagtail/admin/templates/wagtailadmin/pages/listing/_page_title_column_header.html +25 -27
- wagtail/admin/templates/wagtailadmin/pages/page_listing_header.html +2 -1
- wagtail/admin/templates/wagtailadmin/panels/multi_field_panel_child.html +1 -1
- wagtail/admin/templates/wagtailadmin/panels/publishing/schedule_publishing_panel.html +3 -1
- wagtail/admin/templates/wagtailadmin/panels/tabbed_interface.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/active_filters.html +2 -1
- wagtail/admin/templates/wagtailadmin/shared/breadcrumbs.html +8 -0
- wagtail/admin/templates/wagtailadmin/shared/forms/single_checkbox.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/headers/page_edit_header.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/headers/slim_header.html +21 -9
- wagtail/admin/templates/wagtailadmin/shared/human_readable_date.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/keyboard_shortcuts_dialog.html +29 -0
- wagtail/admin/templates/wagtailadmin/shared/side_panel_toggle.html +2 -1
- wagtail/admin/templates/wagtailadmin/skeleton.html +2 -1
- wagtail/admin/templates/wagtailadmin/tables/related_objects_cell.html +9 -0
- wagtail/admin/templates/wagtailadmin/tables/title_cell.html +9 -7
- wagtail/admin/templates/wagtailadmin/widgets/draftail_rich_text_area.html +1 -1
- wagtail/admin/templates/wagtailadmin/workflows/create.html +6 -23
- wagtail/admin/templates/wagtailadmin/workflows/create_task.html +6 -15
- wagtail/admin/templates/wagtailadmin/workflows/edit.html +6 -23
- wagtail/admin/templates/wagtailadmin/workflows/edit_task.html +6 -13
- wagtail/admin/templates/wagtailadmin/workflows/includes/task_usage_cell.html +4 -4
- wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_tasks_cell.html +18 -0
- wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_title_cell.html +7 -0
- wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_used_by_cell.html +25 -0
- wagtail/admin/templates/wagtailadmin/workflows/index.html +0 -99
- wagtail/admin/templates/wagtailadmin/workflows/index_results.html +10 -0
- wagtail/admin/templates/wagtailadmin/workflows/task_index.html +0 -30
- wagtail/admin/templates/wagtailadmin/workflows/task_index_results.html +10 -0
- wagtail/admin/templates/wagtailadmin/workflows/usage.html +1 -1
- wagtail/admin/templatetags/wagtailadmin_tags.py +116 -39
- wagtail/admin/tests/api/test_pages.py +26 -10
- wagtail/admin/tests/pages/test_create_page.py +10 -4
- wagtail/admin/tests/pages/test_custom_listing.py +37 -0
- wagtail/admin/tests/pages/test_edit_page.py +6 -6
- wagtail/admin/tests/pages/test_explorer_view.py +19 -18
- wagtail/admin/tests/pages/test_move_page.py +1 -1
- wagtail/admin/tests/pages/test_page_usage.py +50 -2
- wagtail/admin/tests/pages/test_parent_page_chooser_view.py +119 -0
- wagtail/admin/tests/pages/test_preview.py +18 -4
- wagtail/admin/tests/test_account_management.py +20 -1
- wagtail/admin/tests/test_audit_log.py +172 -5
- wagtail/admin/tests/test_checks.py +92 -0
- wagtail/admin/tests/test_collections_views.py +19 -5
- wagtail/admin/tests/test_compare.py +6 -6
- wagtail/admin/tests/test_dashboard.py +404 -0
- wagtail/admin/tests/test_dbwhitelister.py +4 -5
- wagtail/admin/tests/test_edit_handlers.py +2 -2
- wagtail/admin/tests/test_keyboard_shortcuts.py +84 -0
- wagtail/admin/tests/test_page_chooser.py +31 -18
- wagtail/admin/tests/test_privacy.py +36 -2
- wagtail/admin/tests/test_rich_text.py +168 -23
- wagtail/admin/tests/test_templatetags.py +411 -43
- wagtail/admin/tests/test_views.py +4 -2
- wagtail/admin/tests/test_workflows.py +531 -9
- wagtail/admin/tests/tests.py +3 -1
- wagtail/admin/tests/ui/test_tables.py +48 -1
- wagtail/admin/tests/viewsets/test_model_viewset.py +130 -23
- wagtail/admin/ui/side_panels.py +3 -1
- wagtail/admin/ui/tables/__init__.py +13 -1
- wagtail/admin/ui/tables/pages.py +17 -6
- wagtail/admin/urls/__init__.py +8 -3
- wagtail/admin/urls/pages.py +5 -0
- wagtail/admin/urls/workflows.py +10 -0
- wagtail/admin/views/chooser.py +20 -24
- wagtail/admin/views/collections.py +17 -1
- wagtail/admin/views/generic/base.py +34 -4
- wagtail/admin/views/generic/history.py +220 -51
- wagtail/admin/views/generic/mixins.py +7 -4
- wagtail/admin/views/generic/models.py +54 -47
- wagtail/admin/views/generic/multiple_upload.py +17 -8
- wagtail/admin/views/generic/usage.py +17 -11
- wagtail/admin/views/home.py +15 -12
- wagtail/admin/views/mixins.py +30 -0
- wagtail/admin/views/pages/choose_parent.py +73 -0
- wagtail/admin/views/pages/history.py +54 -66
- wagtail/admin/views/pages/listing.py +187 -106
- wagtail/admin/views/pages/usage.py +6 -1
- wagtail/admin/views/pages/utils.py +70 -1
- wagtail/admin/views/workflows.py +150 -21
- wagtail/admin/viewsets/model.py +2 -2
- wagtail/admin/viewsets/pages.py +77 -0
- wagtail/admin/wagtail_hooks.py +40 -2
- wagtail/admin/widgets/button.py +10 -10
- wagtail/api/v2/filters.py +1 -1
- wagtail/api/v2/tests/test_pages.py +1 -1
- wagtail/blocks/base.py +18 -9
- wagtail/blocks/field_block.py +9 -7
- wagtail/blocks/list_block.py +16 -6
- wagtail/blocks/static_block.py +3 -0
- wagtail/blocks/stream_block.py +58 -23
- wagtail/blocks/struct_block.py +15 -9
- wagtail/contrib/forms/locale/en/LC_MESSAGES/django.po +39 -47
- wagtail/contrib/forms/locale/he_IL/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/forms/locale/he_IL/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/forms/models.py +5 -5
- wagtail/contrib/forms/templates/wagtailforms/list_submissions.html +44 -33
- wagtail/contrib/forms/templates/wagtailforms/submissions_index.html +2 -63
- wagtail/contrib/forms/tests/test_models.py +26 -0
- wagtail/contrib/forms/urls.py +6 -0
- wagtail/contrib/forms/views.py +52 -49
- wagtail/contrib/redirects/locale/ca/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/redirects/locale/ca/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/redirects/locale/en/LC_MESSAGES/django.po +34 -42
- wagtail/contrib/redirects/locale/fr/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/redirects/locale/he_IL/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/redirects/locale/he_IL/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/redirects/signal_handlers.py +1 -1
- wagtail/contrib/redirects/templates/wagtailredirects/index.html +1 -36
- wagtail/contrib/redirects/templates/wagtailredirects/index_results.html +18 -0
- wagtail/contrib/redirects/templates/wagtailredirects/redirect_target_cell.html +8 -0
- wagtail/contrib/redirects/tests/test_import_command.py +1 -1
- wagtail/contrib/redirects/tests/test_redirects.py +79 -8
- wagtail/contrib/redirects/urls.py +2 -1
- wagtail/contrib/redirects/views.py +85 -55
- wagtail/contrib/search_promotions/admin_urls.py +2 -1
- wagtail/contrib/search_promotions/locale/en/LC_MESSAGES/django.po +41 -64
- wagtail/contrib/search_promotions/locale/fr/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/search_promotions/locale/he_IL/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/search_promotions/locale/he_IL/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/search_promotions/locale/hr_HR/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/search_promotions/locale/hr_HR/LC_MESSAGES/django.po +41 -2
- wagtail/contrib/search_promotions/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/search_promotions/locale/it/LC_MESSAGES/django.po +9 -3
- wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/index.html +1 -16
- wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/index_results.html +11 -0
- wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/list.html +0 -51
- wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/results.html +3 -16
- wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/search_promotion_column.html +15 -0
- wagtail/contrib/search_promotions/tests.py +122 -9
- wagtail/contrib/search_promotions/views.py +66 -65
- wagtail/contrib/settings/locale/en/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/settings/locale/he_IL/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/settings/locale/he_IL/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/settings/locale/tr/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/settings/locale/tr/LC_MESSAGES/django.po +6 -2
- wagtail/contrib/settings/registry.py +10 -5
- wagtail/contrib/settings/tests/generic/test_admin.py +9 -0
- wagtail/contrib/settings/tests/site_specific/test_admin.py +10 -1
- wagtail/contrib/settings/tests/site_specific/test_model.py +3 -3
- wagtail/contrib/settings/tests/site_specific/test_templates.py +1 -1
- wagtail/contrib/settings/views.py +3 -1
- wagtail/contrib/simple_translation/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/simple_translation/tests/test_wagtail_hooks.py +2 -2
- wagtail/contrib/styleguide/locale/en/LC_MESSAGES/django.po +7 -7
- wagtail/contrib/styleguide/locale/he_IL/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/styleguide/locale/he_IL/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/table_block/blocks.py +2 -2
- wagtail/contrib/table_block/locale/ca/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/table_block/locale/ca/LC_MESSAGES/django.po +27 -2
- wagtail/contrib/table_block/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/table_block/locale/hu/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/table_block/locale/hu/LC_MESSAGES/django.po +27 -2
- wagtail/contrib/table_block/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/table_block/locale/it/LC_MESSAGES/django.po +27 -2
- wagtail/contrib/table_block/static/table_block/js/table.js +1 -1
- wagtail/contrib/table_block/tests.py +6 -0
- wagtail/contrib/typed_table_block/locale/ca/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/typed_table_block/locale/ca/LC_MESSAGES/django.po +12 -2
- wagtail/contrib/typed_table_block/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/typed_table_block/locale/hu/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/typed_table_block/locale/hu/LC_MESSAGES/django.po +12 -2
- wagtail/contrib/typed_table_block/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/typed_table_block/locale/it/LC_MESSAGES/django.po +12 -2
- wagtail/contrib/typed_table_block/static/typed_table_block/js/typed_table_block.js +1 -1
- wagtail/coreutils.py +3 -2
- wagtail/documents/admin_urls.py +2 -2
- wagtail/documents/locale/en/LC_MESSAGES/django.po +22 -22
- wagtail/documents/locale/fr/LC_MESSAGES/django.po +2 -2
- wagtail/documents/locale/he_IL/LC_MESSAGES/django.mo +0 -0
- wagtail/documents/locale/he_IL/LC_MESSAGES/django.po +2 -2
- wagtail/documents/locale/hr_HR/LC_MESSAGES/django.mo +0 -0
- wagtail/documents/locale/hr_HR/LC_MESSAGES/django.po +19 -2
- wagtail/documents/locale/hu/LC_MESSAGES/django.mo +0 -0
- wagtail/documents/locale/hu/LC_MESSAGES/django.po +16 -2
- wagtail/documents/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/documents/locale/it/LC_MESSAGES/django.po +19 -2
- wagtail/documents/migrations/0013_delete_uploadeddocument.py +16 -0
- wagtail/documents/models.py +1 -20
- wagtail/documents/rich_text/__init__.py +11 -7
- wagtail/documents/static/wagtaildocs/js/document-chooser-modal.js +1 -1
- wagtail/documents/static/wagtaildocs/js/document-chooser-telepath.js +1 -1
- wagtail/documents/static/wagtaildocs/js/document-chooser.js +1 -1
- wagtail/documents/templates/wagtaildocs/documents/index.html +0 -16
- wagtail/documents/tests/test_admin_views.py +155 -23
- wagtail/documents/tests/test_collection_privacy.py +55 -1
- wagtail/documents/tests/test_rich_text.py +14 -0
- wagtail/documents/views/documents.py +25 -22
- wagtail/documents/views/multiple.py +6 -7
- wagtail/documents/views/serve.py +16 -1
- wagtail/documents/wagtail_hooks.py +20 -15
- wagtail/embeds/blocks.py +5 -0
- wagtail/embeds/locale/en/LC_MESSAGES/django.po +2 -2
- wagtail/embeds/locale/fr/LC_MESSAGES/django.po +2 -2
- wagtail/embeds/locale/he_IL/LC_MESSAGES/django.mo +0 -0
- wagtail/embeds/locale/he_IL/LC_MESSAGES/django.po +2 -2
- wagtail/embeds/rich_text/__init__.py +1 -1
- wagtail/embeds/tests/test_rich_text.py +14 -0
- wagtail/embeds/wagtail_hooks.py +4 -14
- wagtail/fields.py +3 -48
- wagtail/images/admin_urls.py +2 -2
- wagtail/images/check_files/wagtail.jpg +0 -0
- wagtail/images/check_files/wagtail.png +0 -0
- wagtail/images/fields.py +2 -0
- wagtail/images/image_operations.py +1 -1
- wagtail/images/locale/ca/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/ca/LC_MESSAGES/django.po +12 -0
- wagtail/images/locale/en/LC_MESSAGES/django.po +33 -45
- wagtail/images/locale/fr/LC_MESSAGES/django.po +2 -2
- wagtail/images/locale/he_IL/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/he_IL/LC_MESSAGES/django.po +2 -2
- wagtail/images/locale/hu/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/hu/LC_MESSAGES/django.po +28 -2
- wagtail/images/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/it/LC_MESSAGES/django.po +14 -2
- wagtail/images/locale/pt_PT/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/pt_PT/LC_MESSAGES/django.po +4 -0
- wagtail/images/migrations/0026_delete_uploadedimage.py +16 -0
- wagtail/images/models.py +49 -43
- wagtail/images/rich_text/__init__.py +18 -8
- wagtail/images/static/wagtailimages/js/image-chooser-modal.js +1 -1
- wagtail/images/static/wagtailimages/js/image-chooser-telepath.js +1 -1
- wagtail/images/static/wagtailimages/js/image-chooser.js +1 -1
- wagtail/images/templates/wagtailimages/images/image_listing_header.html +6 -0
- wagtail/images/templates/wagtailimages/images/index.html +11 -51
- wagtail/images/tests/test_admin_views.py +119 -62
- wagtail/images/tests/test_image_operations.py +10 -0
- wagtail/images/tests/test_models.py +35 -33
- wagtail/images/tests/test_rich_text.py +14 -0
- wagtail/images/tests/utils.py +1 -1
- wagtail/images/views/images.py +35 -64
- wagtail/images/views/multiple.py +6 -7
- wagtail/images/wagtail_hooks.py +4 -14
- wagtail/locale/en/LC_MESSAGES/django.po +150 -136
- wagtail/locale/es/LC_MESSAGES/django.mo +0 -0
- wagtail/locale/es/LC_MESSAGES/django.po +3 -2
- wagtail/locale/fr/LC_MESSAGES/django.po +2 -2
- wagtail/locale/he_IL/LC_MESSAGES/django.mo +0 -0
- wagtail/locale/he_IL/LC_MESSAGES/django.po +2 -2
- wagtail/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/locale/it/LC_MESSAGES/django.po +5 -5
- wagtail/locale/sl/LC_MESSAGES/django.mo +0 -0
- wagtail/locale/sl/LC_MESSAGES/django.po +27 -2
- wagtail/locales/locale/ar/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/be/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/bg/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/ca/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/cs/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/cy/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/da/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/de/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/el/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/es/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/et/LC_MESSAGES/django.po +2 -2
- wagtail/locales/locale/fa/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/fi/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/fr/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/gl/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/he_IL/LC_MESSAGES/django.mo +0 -0
- wagtail/locales/locale/he_IL/LC_MESSAGES/django.po +3 -3
- wagtail/locales/locale/hr_HR/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/hu/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/id_ID/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/is_IS/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/it/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/ja/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/ko/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/lt/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/lv/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/mi/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/mn/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/my/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/nb/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/nl/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/pl/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/pt_BR/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/pt_PT/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/ro/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/ru/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/sk_SK/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/sl/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/sv/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/tet/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/th/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/tr/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/tr_TR/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/uk/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/vi/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/zh/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/zh_Hans/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/zh_Hant/LC_MESSAGES/django.po +1 -1
- wagtail/locales/tests.py +18 -3
- wagtail/locales/views.py +0 -1
- wagtail/management/commands/rebuild_references_index.py +3 -1
- wagtail/migrations/0092_alter_collectionviewrestriction_password_and_more.py +33 -0
- wagtail/migrations/0093_uploadedfile.py +53 -0
- wagtail/models/__init__.py +147 -32
- wagtail/models/i18n.py +1 -1
- wagtail/models/{collections.py → media.py} +33 -2
- wagtail/models/reference_index.py +1 -1
- wagtail/models/view_restrictions.py +10 -3
- wagtail/project_template/project_name/settings/base.py +6 -0
- wagtail/project_template/requirements.txt +1 -1
- wagtail/rich_text/__init__.py +25 -8
- wagtail/rich_text/pages.py +19 -8
- wagtail/rich_text/rewriters.py +140 -68
- wagtail/search/backends/database/mysql/mysql.py +3 -3
- wagtail/search/backends/database/postgres/postgres.py +3 -3
- wagtail/search/backends/database/sqlite/sqlite.py +2 -2
- wagtail/search/backends/elasticsearch7.py +4 -0
- wagtail/search/locale/en/LC_MESSAGES/django.po +3 -3
- wagtail/search/tests/test_postgres_backend.py +50 -0
- wagtail/sites/locale/en/LC_MESSAGES/django.po +8 -8
- wagtail/sites/locale/he_IL/LC_MESSAGES/django.mo +0 -0
- wagtail/sites/locale/he_IL/LC_MESSAGES/django.po +2 -2
- wagtail/sites/locale/ro/LC_MESSAGES/django.mo +0 -0
- wagtail/sites/locale/ro/LC_MESSAGES/django.po +3 -2
- wagtail/sites/tests.py +35 -9
- wagtail/sites/views.py +3 -1
- wagtail/snippets/locale/de/LC_MESSAGES/django.mo +0 -0
- wagtail/snippets/locale/de/LC_MESSAGES/django.po +7 -8
- wagtail/snippets/locale/en/LC_MESSAGES/django.po +16 -56
- wagtail/snippets/locale/fr/LC_MESSAGES/django.po +2 -2
- wagtail/snippets/locale/he_IL/LC_MESSAGES/django.mo +0 -0
- wagtail/snippets/locale/he_IL/LC_MESSAGES/django.po +2 -2
- wagtail/snippets/locale/hr_HR/LC_MESSAGES/django.mo +0 -0
- wagtail/snippets/locale/hr_HR/LC_MESSAGES/django.po +6 -2
- wagtail/snippets/locale/lv/LC_MESSAGES/django.mo +0 -0
- wagtail/snippets/locale/lv/LC_MESSAGES/django.po +12 -0
- wagtail/snippets/locale/zh_Hant/LC_MESSAGES/django.mo +0 -0
- wagtail/snippets/locale/zh_Hant/LC_MESSAGES/django.po +4 -0
- wagtail/snippets/static/wagtailsnippets/js/snippet-chooser-telepath.js +1 -1
- wagtail/snippets/static/wagtailsnippets/js/snippet-chooser.js +1 -1
- wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/publish.html +3 -1
- wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/save.html +3 -1
- wagtail/snippets/templates/wagtailsnippets/snippets/create.html +2 -3
- wagtail/snippets/templates/wagtailsnippets/snippets/edit.html +2 -3
- wagtail/snippets/tests/test_preview.py +13 -2
- wagtail/snippets/tests/test_snippets.py +41 -16
- wagtail/snippets/tests/test_viewset.py +95 -18
- wagtail/snippets/tests/test_workflows.py +12 -0
- wagtail/snippets/views/snippets.py +1 -40
- wagtail/templatetags/wagtailcore_tags.py +1 -1
- wagtail/test/demosite/models.py +1 -1
- wagtail/test/middleware.py +14 -1
- wagtail/test/testapp/fixtures/test.json +20 -0
- wagtail/test/testapp/migrations/0001_squashed_0073_revisablechildmodel_secret_text.py +8 -8
- wagtail/test/testapp/migrations/0023_snippetchoosermodel_full_featured.py +1 -0
- wagtail/test/testapp/migrations/0034_custompermissionmodel.py +44 -0
- wagtail/test/testapp/migrations/0035_modelwithcustommanager.py +30 -0
- wagtail/test/testapp/migrations/0036_complexdefaultstreampage.py +28 -0
- wagtail/test/testapp/models.py +79 -2
- wagtail/test/testapp/templates/tests/custom_docs_password_required.html +10 -0
- wagtail/test/testapp/templates/tests/custom_page_password_required.html +10 -0
- wagtail/test/testapp/views.py +24 -2
- wagtail/test/testapp/wagtail_hooks.py +19 -0
- wagtail/test/utils/wagtail_tests.py +2 -2
- wagtail/tests/test_blocks.py +262 -1
- wagtail/tests/test_migrations.py +1 -1
- wagtail/tests/test_page_model.py +77 -0
- wagtail/tests/test_page_privacy.py +18 -1
- wagtail/tests/test_rich_text.py +95 -5
- wagtail/tests/test_streamfield.py +43 -0
- wagtail/tests/test_utils.py +8 -2
- wagtail/tests/test_views.py +52 -1
- wagtail/tests/test_whitelist.py +7 -7
- wagtail/users/forms.py +3 -1
- wagtail/users/locale/en/LC_MESSAGES/django.po +124 -96
- wagtail/users/locale/fr/LC_MESSAGES/django.po +2 -2
- wagtail/users/locale/he_IL/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/he_IL/LC_MESSAGES/django.po +2 -2
- wagtail/users/locale/hr_HR/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/hr_HR/LC_MESSAGES/django.po +13 -2
- wagtail/users/migrations/0013_userprofile_density.py +23 -0
- wagtail/users/models.py +14 -3
- wagtail/users/templates/wagtailusers/groups/create.html +1 -7
- wagtail/users/templates/wagtailusers/groups/edit.html +1 -13
- wagtail/users/templates/wagtailusers/groups/includes/formatted_permissions.html +46 -2
- wagtail/users/templates/wagtailusers/groups/includes/group_form_js.html +0 -3
- wagtail/users/templates/wagtailusers/users/create.html +1 -14
- wagtail/users/templates/wagtailusers/users/edit.html +1 -14
- wagtail/users/templates/wagtailusers/users/index.html +2 -5
- wagtail/users/templates/wagtailusers/users/index_results.html +3 -13
- wagtail/users/templates/wagtailusers/users/user_cell.html +9 -0
- wagtail/users/templatetags/wagtailusers_tags.py +107 -20
- wagtail/users/tests/test_admin_views.py +669 -90
- wagtail/users/views/groups.py +58 -61
- wagtail/users/views/users.py +211 -92
- wagtail/users/wagtail_hooks.py +6 -38
- wagtail/users/widgets.py +3 -5
- wagtail/utils/text.py +1 -1
- wagtail/views.py +5 -9
- wagtail/whitelist.py +1 -1
- {wagtail-6.0.1.dist-info → wagtail-6.1rc1.dist-info}/METADATA +5 -6
- {wagtail-6.0.1.dist-info → wagtail-6.1rc1.dist-info}/RECORD +496 -477
- wagtail/admin/static/wagtailadmin/js/page-editor.js +0 -1
- wagtail/admin/static/wagtailadmin/js/vendor/mousetrap.min.js +0 -1
- wagtail/admin/static/wagtailadmin/js/vendor/urlify.js +0 -1
- wagtail/admin/static/wagtailadmin/js/vendor/xregexp.min.js +0 -1
- wagtail/admin/templates/wagtailadmin/collections/index.html +0 -34
- wagtail/admin/templates/wagtailadmin/pages/revisions/_actions.html +0 -22
- wagtail/admin/templates/wagtailadmin/shared/page_breadcrumbs.html +0 -55
- wagtail/admin/tests/pages/test_dashboard.py +0 -172
- wagtail/contrib/redirects/templates/wagtailredirects/results.html +0 -23
- wagtail/documents/templates/wagtaildocs/documents/list.html +0 -2
- wagtail/search/tests/test_postgres_stemming.py +0 -40
- wagtail/sites/templates/wagtailsites/create.html +0 -7
- wagtail/sites/templates/wagtailsites/edit.html +0 -7
- wagtail/snippets/templates/wagtailsnippets/snippets/revisions/_actions.html +0 -36
- wagtail/users/templates/wagtailusers/users/list.html +0 -62
- wagtail/users/urls/users.py +0 -12
- {wagtail-6.0.1.dist-info → wagtail-6.1rc1.dist-info}/LICENSE +0 -0
- {wagtail-6.0.1.dist-info → wagtail-6.1rc1.dist-info}/WHEEL +0 -0
- {wagtail-6.0.1.dist-info → wagtail-6.1rc1.dist-info}/entry_points.txt +0 -0
- {wagtail-6.0.1.dist-info → wagtail-6.1rc1.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from django.contrib.auth.models import Group
|
|
2
2
|
from django.core.files.base import ContentFile
|
|
3
|
-
from django.test import TestCase
|
|
3
|
+
from django.test import TestCase, override_settings
|
|
4
4
|
from django.urls import reverse
|
|
5
5
|
|
|
6
6
|
from wagtail.documents.models import Document
|
|
@@ -19,6 +19,7 @@ class TestCollectionPrivacyDocument(WagtailTestUtils, TestCase):
|
|
|
19
19
|
def setUp(self):
|
|
20
20
|
self.fake_file = ContentFile(b"A boring example document")
|
|
21
21
|
self.fake_file.name = "test.txt"
|
|
22
|
+
self.collection = Collection.objects.get(id=2)
|
|
22
23
|
self.password_collection = Collection.objects.get(name="Password protected")
|
|
23
24
|
self.login_collection = Collection.objects.get(name="Login protected")
|
|
24
25
|
self.group_collection = Collection.objects.get(name="Group protected")
|
|
@@ -106,6 +107,28 @@ class TestCollectionPrivacyDocument(WagtailTestUtils, TestCase):
|
|
|
106
107
|
)
|
|
107
108
|
self.assertRedirects(response, "/")
|
|
108
109
|
|
|
110
|
+
@override_settings(
|
|
111
|
+
WAGTAILDOCS_PASSWORD_REQUIRED_TEMPLATE="tests/custom_docs_password_required.html"
|
|
112
|
+
)
|
|
113
|
+
def test_anonymous_user_must_authenticate_with_custom_password_required_template(
|
|
114
|
+
self
|
|
115
|
+
):
|
|
116
|
+
secret_document = Document.objects.create(
|
|
117
|
+
title="Test document",
|
|
118
|
+
file=self.fake_file,
|
|
119
|
+
collection=self.password_collection,
|
|
120
|
+
)
|
|
121
|
+
doc_url = reverse(
|
|
122
|
+
"wagtaildocs_serve", args=(secret_document.id, secret_document.filename)
|
|
123
|
+
)
|
|
124
|
+
response = self.client.get(doc_url)
|
|
125
|
+
self.assertNotEqual(
|
|
126
|
+
response.templates[0].name, "wagtaildocs/password_required.html"
|
|
127
|
+
)
|
|
128
|
+
self.assertEqual(
|
|
129
|
+
response.templates[0].name, "tests/custom_docs_password_required.html"
|
|
130
|
+
)
|
|
131
|
+
|
|
109
132
|
def test_group_restriction_with_anonymous_user(self):
|
|
110
133
|
response, url = self.get_document(self.group_collection)
|
|
111
134
|
self.assertRedirects(response, f"/_util/login/?next={url}")
|
|
@@ -133,3 +156,34 @@ class TestCollectionPrivacyDocument(WagtailTestUtils, TestCase):
|
|
|
133
156
|
self.login(username="eventmoderator", password="password")
|
|
134
157
|
response, url = self.get_document(self.login_collection)
|
|
135
158
|
self.assertEqual(response.status_code, 200)
|
|
159
|
+
|
|
160
|
+
def test_set_shared_password_with_logged_in_user(self):
|
|
161
|
+
self.login()
|
|
162
|
+
response = self.client.get(
|
|
163
|
+
reverse("wagtailadmin_collections:set_privacy", args=(self.collection.id,)),
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
input_el = self.get_soup(response.content).select_one("[data-field-input]")
|
|
167
|
+
self.assertEqual(response.status_code, 200)
|
|
168
|
+
|
|
169
|
+
# check that input option for password is visible
|
|
170
|
+
self.assertIn("password", response.context["form"].fields)
|
|
171
|
+
|
|
172
|
+
# check that the option for password is visible
|
|
173
|
+
self.assertIsNotNone(input_el)
|
|
174
|
+
|
|
175
|
+
@override_settings(
|
|
176
|
+
WAGTAILDOCS_PRIVATE_COLLECTION_OPTIONS={"SHARED_PASSWORD": False}
|
|
177
|
+
)
|
|
178
|
+
def test_unset_shared_password_with_logged_in_user(self):
|
|
179
|
+
self.login()
|
|
180
|
+
response = self.client.get(
|
|
181
|
+
reverse("wagtailadmin_collections:set_privacy", args=(self.collection.id,)),
|
|
182
|
+
)
|
|
183
|
+
self.assertEqual(response.status_code, 200)
|
|
184
|
+
self.assertNotIn("password", response.context["form"].fields)
|
|
185
|
+
self.assertFalse(
|
|
186
|
+
response.context["form"]
|
|
187
|
+
.fields["restriction_type"]
|
|
188
|
+
.valid_value(CollectionViewRestriction.PASSWORD)
|
|
189
|
+
)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from django.test import TestCase
|
|
2
|
+
from django.urls import reverse_lazy
|
|
2
3
|
|
|
3
4
|
from wagtail.documents import get_document_model
|
|
4
5
|
from wagtail.documents.rich_text import (
|
|
@@ -8,6 +9,7 @@ from wagtail.documents.rich_text.editor_html import (
|
|
|
8
9
|
DocumentLinkHandler as EditorHtmlDocumentLinkHandler,
|
|
9
10
|
)
|
|
10
11
|
from wagtail.fields import RichTextField
|
|
12
|
+
from wagtail.rich_text.feature_registry import FeatureRegistry
|
|
11
13
|
from wagtail.test.utils import WagtailTestUtils
|
|
12
14
|
|
|
13
15
|
|
|
@@ -60,3 +62,15 @@ class TestFrontendDocumentLinkHandler(TestCase):
|
|
|
60
62
|
),
|
|
61
63
|
[(get_document_model(), "1", "", "")],
|
|
62
64
|
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class TestEntityFeatureChooserUrls(TestCase):
|
|
68
|
+
def test_chooser_urls_exist(self):
|
|
69
|
+
features = FeatureRegistry()
|
|
70
|
+
document = features.get_editor_plugin("draftail", "document-link")
|
|
71
|
+
|
|
72
|
+
self.assertIsNotNone(document.data.get("chooserUrls"))
|
|
73
|
+
self.assertEqual(
|
|
74
|
+
document.data["chooserUrls"]["documentChooser"],
|
|
75
|
+
reverse_lazy("wagtaildocs_chooser:choose"),
|
|
76
|
+
)
|
|
@@ -12,6 +12,7 @@ from django.utils.translation import gettext_lazy, ngettext
|
|
|
12
12
|
|
|
13
13
|
from wagtail.admin import messages
|
|
14
14
|
from wagtail.admin.auth import PermissionPolicyChecker
|
|
15
|
+
from wagtail.admin.filters import BaseMediaFilterSet
|
|
15
16
|
from wagtail.admin.ui.tables import (
|
|
16
17
|
BulkActionsCheckboxColumn,
|
|
17
18
|
Column,
|
|
@@ -25,9 +26,9 @@ from wagtail.admin.views import generic
|
|
|
25
26
|
from wagtail.documents import get_document_model
|
|
26
27
|
from wagtail.documents.forms import get_document_form
|
|
27
28
|
from wagtail.documents.permissions import permission_policy
|
|
28
|
-
from wagtail.models import Collection
|
|
29
29
|
|
|
30
30
|
permission_checker = PermissionPolicyChecker(permission_policy)
|
|
31
|
+
Document = get_document_model()
|
|
31
32
|
|
|
32
33
|
|
|
33
34
|
class BulkActionsColumn(BulkActionsCheckboxColumn):
|
|
@@ -49,6 +50,14 @@ class DocumentTable(Table):
|
|
|
49
50
|
return context
|
|
50
51
|
|
|
51
52
|
|
|
53
|
+
class DocumentsFilterSet(BaseMediaFilterSet):
|
|
54
|
+
permission_policy = permission_policy
|
|
55
|
+
|
|
56
|
+
class Meta:
|
|
57
|
+
model = Document
|
|
58
|
+
fields = []
|
|
59
|
+
|
|
60
|
+
|
|
52
61
|
class IndexView(generic.IndexView):
|
|
53
62
|
permission_policy = permission_policy
|
|
54
63
|
any_permission_required = ["add", "change", "delete"]
|
|
@@ -65,9 +74,11 @@ class IndexView(generic.IndexView):
|
|
|
65
74
|
results_template_name = "wagtaildocs/documents/index_results.html"
|
|
66
75
|
default_ordering = "title"
|
|
67
76
|
table_class = DocumentTable
|
|
77
|
+
filterset_class = DocumentsFilterSet
|
|
68
78
|
model = get_document_model()
|
|
69
79
|
add_item_label = gettext_lazy("Add a document")
|
|
70
80
|
show_other_searches = True
|
|
81
|
+
_show_breadcrumbs = True
|
|
71
82
|
|
|
72
83
|
def get_base_queryset(self):
|
|
73
84
|
# Get documents (filtered by user permission)
|
|
@@ -75,17 +86,10 @@ class IndexView(generic.IndexView):
|
|
|
75
86
|
self.request.user, ["change", "delete"]
|
|
76
87
|
).select_related("collection")
|
|
77
88
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
try:
|
|
83
|
-
self.current_collection = Collection.objects.get(id=collection_id)
|
|
84
|
-
queryset = queryset.filter(collection=self.current_collection)
|
|
85
|
-
except (ValueError, Collection.DoesNotExist):
|
|
86
|
-
pass
|
|
87
|
-
|
|
88
|
-
return queryset
|
|
89
|
+
@cached_property
|
|
90
|
+
def current_collection(self):
|
|
91
|
+
# Upon validation, the cleaned data is a Collection instance
|
|
92
|
+
return self.filters and self.filters.form.cleaned_data.get("collection_id")
|
|
89
93
|
|
|
90
94
|
@cached_property
|
|
91
95
|
def columns(self):
|
|
@@ -106,7 +110,7 @@ class IndexView(generic.IndexView):
|
|
|
106
110
|
width="16%",
|
|
107
111
|
),
|
|
108
112
|
]
|
|
109
|
-
if self.
|
|
113
|
+
if self.filters and "collection_id" in self.filters.filters:
|
|
110
114
|
columns.insert(
|
|
111
115
|
3,
|
|
112
116
|
Column("collection", label=_("Collection"), accessor="collection.name"),
|
|
@@ -130,10 +134,10 @@ class IndexView(generic.IndexView):
|
|
|
130
134
|
return next_url
|
|
131
135
|
|
|
132
136
|
def get_add_url(self):
|
|
133
|
-
# Pass the
|
|
137
|
+
# Pass the collection filter to prefill the add form's collection field
|
|
134
138
|
return set_query_params(
|
|
135
139
|
super().get_add_url(),
|
|
136
|
-
self.
|
|
140
|
+
{"collection_id": self.current_collection and self.current_collection.pk},
|
|
137
141
|
)
|
|
138
142
|
|
|
139
143
|
def get_edit_url(self, instance):
|
|
@@ -142,15 +146,14 @@ class IndexView(generic.IndexView):
|
|
|
142
146
|
{"next": self.get_next_url()},
|
|
143
147
|
)
|
|
144
148
|
|
|
149
|
+
def get_filterset_kwargs(self):
|
|
150
|
+
kwargs = super().get_filterset_kwargs()
|
|
151
|
+
kwargs["is_searching"] = self.is_searching
|
|
152
|
+
return kwargs
|
|
153
|
+
|
|
145
154
|
def get_context_data(self, **kwargs):
|
|
146
155
|
context = super().get_context_data(**kwargs)
|
|
147
|
-
|
|
148
|
-
context.update(
|
|
149
|
-
{
|
|
150
|
-
"collections": self.collections,
|
|
151
|
-
"current_collection": self.current_collection,
|
|
152
|
-
}
|
|
153
|
-
)
|
|
156
|
+
context["current_collection"] = self.current_collection
|
|
154
157
|
return context
|
|
155
158
|
|
|
156
159
|
|
|
@@ -12,14 +12,12 @@ from wagtail.admin.views.generic.multiple_upload import EditView as BaseEditView
|
|
|
12
12
|
|
|
13
13
|
from .. import get_document_model
|
|
14
14
|
from ..forms import get_document_form, get_document_multi_form
|
|
15
|
-
from ..models import UploadedDocument
|
|
16
15
|
from ..permissions import permission_policy
|
|
17
16
|
|
|
18
17
|
|
|
19
18
|
class AddView(BaseAddView):
|
|
20
19
|
permission_policy = permission_policy
|
|
21
20
|
template_name = "wagtaildocs/multiple/add.html"
|
|
22
|
-
upload_model = UploadedDocument
|
|
23
21
|
|
|
24
22
|
edit_object_url_name = "wagtaildocs:edit_multiple"
|
|
25
23
|
delete_object_url_name = "wagtaildocs:delete_multiple"
|
|
@@ -31,7 +29,7 @@ class AddView(BaseAddView):
|
|
|
31
29
|
delete_upload_url_name = "wagtaildocs:delete_upload_multiple"
|
|
32
30
|
edit_upload_form_prefix = "uploaded-document"
|
|
33
31
|
context_upload_name = "uploaded_document"
|
|
34
|
-
context_upload_id_name = "
|
|
32
|
+
context_upload_id_name = "uploaded_file_id"
|
|
35
33
|
|
|
36
34
|
def get_model(self):
|
|
37
35
|
return get_document_model()
|
|
@@ -90,8 +88,7 @@ class DeleteView(BaseDeleteView):
|
|
|
90
88
|
class CreateFromUploadedDocumentView(BaseCreateFromUploadView):
|
|
91
89
|
edit_upload_url_name = "wagtaildocs:create_multiple_from_uploaded_document"
|
|
92
90
|
delete_upload_url_name = "wagtaildocs:delete_upload_multiple"
|
|
93
|
-
|
|
94
|
-
upload_pk_url_kwarg = "uploaded_document_id"
|
|
91
|
+
upload_pk_url_kwarg = "uploaded_file_id"
|
|
95
92
|
edit_upload_form_prefix = "uploaded-document"
|
|
96
93
|
context_object_id_name = "doc_id"
|
|
97
94
|
context_upload_name = "uploaded_document"
|
|
@@ -118,5 +115,7 @@ class CreateFromUploadedDocumentView(BaseCreateFromUploadView):
|
|
|
118
115
|
|
|
119
116
|
|
|
120
117
|
class DeleteUploadView(BaseDeleteUploadView):
|
|
121
|
-
|
|
122
|
-
|
|
118
|
+
upload_pk_url_kwarg = "uploaded_file_id"
|
|
119
|
+
|
|
120
|
+
def get_model(self):
|
|
121
|
+
return get_document_model()
|
wagtail/documents/views/serve.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from warnings import warn
|
|
2
|
+
|
|
1
3
|
from django.conf import settings
|
|
2
4
|
from django.http import FileResponse, Http404, HttpResponse
|
|
3
5
|
from django.shortcuts import get_object_or_404, redirect
|
|
@@ -12,6 +14,7 @@ from wagtail.documents.models import document_served
|
|
|
12
14
|
from wagtail.forms import PasswordViewRestrictionForm
|
|
13
15
|
from wagtail.models import CollectionViewRestriction
|
|
14
16
|
from wagtail.utils import sendfile_streaming_backend
|
|
17
|
+
from wagtail.utils.deprecation import RemovedInWagtail70Warning
|
|
15
18
|
from wagtail.utils.sendfile import sendfile
|
|
16
19
|
|
|
17
20
|
|
|
@@ -135,9 +138,21 @@ def authenticate_with_password(request, restriction_id):
|
|
|
135
138
|
|
|
136
139
|
password_required_template = getattr(
|
|
137
140
|
settings,
|
|
138
|
-
"
|
|
141
|
+
"WAGTAILDOCS_PASSWORD_REQUIRED_TEMPLATE",
|
|
139
142
|
"wagtaildocs/password_required.html",
|
|
140
143
|
)
|
|
141
144
|
|
|
145
|
+
if hasattr(settings, "DOCUMENT_PASSWORD_REQUIRED_TEMPLATE"):
|
|
146
|
+
warn(
|
|
147
|
+
"The `DOCUMENT_PASSWORD_REQUIRED_TEMPLATE` setting is deprecated - use `WAGTAILDOCS_PASSWORD_REQUIRED_TEMPLATE` instead.",
|
|
148
|
+
category=RemovedInWagtail70Warning,
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
password_required_template = getattr(
|
|
152
|
+
settings,
|
|
153
|
+
"DOCUMENT_PASSWORD_REQUIRED_TEMPLATE",
|
|
154
|
+
password_required_template,
|
|
155
|
+
)
|
|
156
|
+
|
|
142
157
|
context = {"form": form, "action_url": action_url}
|
|
143
158
|
return TemplateResponse(request, password_required_template, context)
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
from warnings import warn
|
|
2
|
+
|
|
1
3
|
from django.conf import settings
|
|
2
4
|
from django.template.response import TemplateResponse
|
|
3
|
-
from django.urls import include, path, reverse
|
|
4
|
-
from django.utils.html import format_html
|
|
5
|
+
from django.urls import include, path, reverse, reverse_lazy
|
|
5
6
|
from django.utils.translation import gettext, ngettext
|
|
6
7
|
from django.utils.translation import gettext_lazy as _
|
|
7
8
|
|
|
@@ -31,6 +32,7 @@ from wagtail.documents.views.bulk_actions import (
|
|
|
31
32
|
)
|
|
32
33
|
from wagtail.documents.views.chooser import viewset as chooser_viewset
|
|
33
34
|
from wagtail.models import BaseViewRestriction
|
|
35
|
+
from wagtail.utils.deprecation import RemovedInWagtail70Warning
|
|
34
36
|
from wagtail.wagtail_hooks import require_wagtail_login
|
|
35
37
|
|
|
36
38
|
|
|
@@ -64,18 +66,6 @@ def register_documents_menu_item():
|
|
|
64
66
|
)
|
|
65
67
|
|
|
66
68
|
|
|
67
|
-
@hooks.register("insert_editor_js")
|
|
68
|
-
def editor_js():
|
|
69
|
-
return format_html(
|
|
70
|
-
"""
|
|
71
|
-
<script>
|
|
72
|
-
window.chooserUrls.documentChooser = '{0}';
|
|
73
|
-
</script>
|
|
74
|
-
""",
|
|
75
|
-
reverse("wagtaildocs_chooser:choose"),
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
|
|
79
69
|
@hooks.register("register_rich_text_features")
|
|
80
70
|
def register_document_feature(features):
|
|
81
71
|
features.register_link_type(DocumentLinkHandler)
|
|
@@ -88,6 +78,9 @@ def register_document_feature(features):
|
|
|
88
78
|
"type": "DOCUMENT",
|
|
89
79
|
"icon": "doc-full-inverse",
|
|
90
80
|
"description": gettext("Document"),
|
|
81
|
+
"chooserUrls": {
|
|
82
|
+
"documentChooser": reverse_lazy("wagtaildocs_chooser:choose")
|
|
83
|
+
},
|
|
91
84
|
},
|
|
92
85
|
js=["wagtaildocs/js/document-chooser-modal.js"],
|
|
93
86
|
),
|
|
@@ -190,10 +183,22 @@ def check_view_restrictions(document, request):
|
|
|
190
183
|
|
|
191
184
|
password_required_template = getattr(
|
|
192
185
|
settings,
|
|
193
|
-
"
|
|
186
|
+
"WAGTAILDOCS_PASSWORD_REQUIRED_TEMPLATE",
|
|
194
187
|
"wagtaildocs/password_required.html",
|
|
195
188
|
)
|
|
196
189
|
|
|
190
|
+
if hasattr(settings, "DOCUMENT_PASSWORD_REQUIRED_TEMPLATE"):
|
|
191
|
+
warn(
|
|
192
|
+
"The `DOCUMENT_PASSWORD_REQUIRED_TEMPLATE` setting is deprecated - use `WAGTAILDOCS_PASSWORD_REQUIRED_TEMPLATE` instead.",
|
|
193
|
+
category=RemovedInWagtail70Warning,
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
password_required_template = getattr(
|
|
197
|
+
settings,
|
|
198
|
+
"DOCUMENT_PASSWORD_REQUIRED_TEMPLATE",
|
|
199
|
+
password_required_template,
|
|
200
|
+
)
|
|
201
|
+
|
|
197
202
|
context = {"form": form, "action_url": action_url}
|
|
198
203
|
return TemplateResponse(request, password_required_template, context)
|
|
199
204
|
|
wagtail/embeds/blocks.py
CHANGED
|
@@ -85,5 +85,10 @@ class EmbedBlock(blocks.URLBlock):
|
|
|
85
85
|
raise ValidationError(_("Cannot find an embed for this URL."))
|
|
86
86
|
return super().clean(value)
|
|
87
87
|
|
|
88
|
+
def normalize(self, value):
|
|
89
|
+
if isinstance(value, EmbedValue):
|
|
90
|
+
return value
|
|
91
|
+
return EmbedValue(value)
|
|
92
|
+
|
|
88
93
|
class Meta:
|
|
89
94
|
icon = "media"
|
|
@@ -8,7 +8,7 @@ msgid ""
|
|
|
8
8
|
msgstr ""
|
|
9
9
|
"Project-Id-Version: PACKAGE VERSION\n"
|
|
10
10
|
"Report-Msgid-Bugs-To: \n"
|
|
11
|
-
"POT-Creation-Date: 2024-
|
|
11
|
+
"POT-Creation-Date: 2024-04-18 17:28+0100\n"
|
|
12
12
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
|
13
13
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
14
14
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
|
@@ -62,6 +62,6 @@ msgid ""
|
|
|
62
62
|
"Please try again later."
|
|
63
63
|
msgstr ""
|
|
64
64
|
|
|
65
|
-
#: wagtail_hooks.py:
|
|
65
|
+
#: wagtail_hooks.py:38
|
|
66
66
|
msgid "Embed"
|
|
67
67
|
msgstr ""
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
#
|
|
5
5
|
# Translators:
|
|
6
6
|
# Bertrand Bordage <bordage.bertrand@gmail.com>, 2015,2018
|
|
7
|
-
#
|
|
8
|
-
#
|
|
7
|
+
# 69c761fa404d2f74d5a7a2904d9e6f47_dc2dbc9 <f37077798760362881f9d396b6e22ec7_1878>, 2018
|
|
8
|
+
# 69c761fa404d2f74d5a7a2904d9e6f47_dc2dbc9 <f37077798760362881f9d396b6e22ec7_1878>, 2018
|
|
9
9
|
# Léo <leo@naeka.fr>, 2016
|
|
10
10
|
# Loic Teixeira, 2018,2020
|
|
11
11
|
# Loic Teixeira, 2020
|
|
Binary file
|
|
@@ -17,8 +17,8 @@ msgstr ""
|
|
|
17
17
|
"Content-Type: text/plain; charset=UTF-8\n"
|
|
18
18
|
"Content-Transfer-Encoding: 8bit\n"
|
|
19
19
|
"Language: he_IL\n"
|
|
20
|
-
"Plural-Forms: nplurals=
|
|
21
|
-
"1 == 0) ? 1:
|
|
20
|
+
"Plural-Forms: nplurals=3; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % "
|
|
21
|
+
"1 == 0) ? 1: 2;\n"
|
|
22
22
|
|
|
23
23
|
msgid "Cannot find an embed for this URL."
|
|
24
24
|
msgstr "לא ניתן למצוא הטמעה לקישור זה "
|
|
@@ -18,7 +18,7 @@ class MediaEmbedHandler(EmbedHandler):
|
|
|
18
18
|
return get_embed(attrs["url"])
|
|
19
19
|
|
|
20
20
|
@staticmethod
|
|
21
|
-
def expand_db_attributes(attrs):
|
|
21
|
+
def expand_db_attributes(attrs: dict) -> str:
|
|
22
22
|
"""
|
|
23
23
|
Given a dict of attributes from the <embed> tag, return the real HTML
|
|
24
24
|
representation for use on the front-end.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from unittest.mock import patch
|
|
2
2
|
|
|
3
3
|
from django.test import TestCase, override_settings
|
|
4
|
+
from django.urls import reverse_lazy
|
|
4
5
|
|
|
5
6
|
from wagtail.embeds.exceptions import EmbedNotFoundException
|
|
6
7
|
from wagtail.embeds.models import Embed
|
|
@@ -9,6 +10,7 @@ from wagtail.embeds.rich_text.editor_html import (
|
|
|
9
10
|
MediaEmbedHandler as EditorHtmlMediaEmbedHandler,
|
|
10
11
|
)
|
|
11
12
|
from wagtail.rich_text import expand_db_html
|
|
13
|
+
from wagtail.rich_text.feature_registry import FeatureRegistry
|
|
12
14
|
from wagtail.test.utils import WagtailTestUtils
|
|
13
15
|
|
|
14
16
|
|
|
@@ -143,3 +145,15 @@ class TestFrontendMediaEmbedHandler(TestCase):
|
|
|
143
145
|
get_embed.assert_called_with(
|
|
144
146
|
"https://www.youtube.com/watch?v=O7D-1RG-VRk&t=25", None, None
|
|
145
147
|
)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class TestEntityFeatureChooserUrls(TestCase):
|
|
151
|
+
def test_chooser_urls_exist(self):
|
|
152
|
+
features = FeatureRegistry()
|
|
153
|
+
embed = features.get_editor_plugin("draftail", "embed")
|
|
154
|
+
|
|
155
|
+
self.assertIsNotNone(embed.data.get("chooserUrls"))
|
|
156
|
+
self.assertEqual(
|
|
157
|
+
embed.data["chooserUrls"]["embedsChooser"],
|
|
158
|
+
reverse_lazy("wagtailembeds:chooser"),
|
|
159
|
+
)
|
wagtail/embeds/wagtail_hooks.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
from django.urls import include, path,
|
|
2
|
-
from django.utils.html import format_html
|
|
1
|
+
from django.urls import include, path, reverse_lazy
|
|
3
2
|
from django.utils.translation import gettext as _
|
|
4
3
|
|
|
5
4
|
import wagtail.admin.rich_text.editors.draftail.features as draftail_features
|
|
@@ -17,18 +16,6 @@ def register_admin_urls():
|
|
|
17
16
|
]
|
|
18
17
|
|
|
19
18
|
|
|
20
|
-
@hooks.register("insert_editor_js")
|
|
21
|
-
def editor_js():
|
|
22
|
-
return format_html(
|
|
23
|
-
"""
|
|
24
|
-
<script>
|
|
25
|
-
window.chooserUrls.embedsChooser = '{0}';
|
|
26
|
-
</script>
|
|
27
|
-
""",
|
|
28
|
-
reverse("wagtailembeds:chooser"),
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
|
|
32
19
|
@hooks.register("register_rich_text_features")
|
|
33
20
|
def register_embed_feature(features):
|
|
34
21
|
# define a handler for converting <embed embedtype="media"> tags into frontend HTML
|
|
@@ -49,6 +36,9 @@ def register_embed_feature(features):
|
|
|
49
36
|
"type": "EMBED",
|
|
50
37
|
"icon": "media",
|
|
51
38
|
"description": _("Embed"),
|
|
39
|
+
"chooserUrls": {
|
|
40
|
+
"embedsChooser": reverse_lazy("wagtailembeds:chooser"),
|
|
41
|
+
},
|
|
52
42
|
},
|
|
53
43
|
js=["wagtailembeds/js/embed-chooser-modal.js"],
|
|
54
44
|
),
|
wagtail/fields.py
CHANGED
|
@@ -131,59 +131,14 @@ class StreamField(models.Field):
|
|
|
131
131
|
return name, path, args, kwargs
|
|
132
132
|
|
|
133
133
|
def to_python(self, value):
|
|
134
|
-
|
|
134
|
+
result = self.stream_block.to_python(value)
|
|
135
135
|
|
|
136
136
|
# The top-level StreamValue is passed a reference to the StreamField, to support
|
|
137
137
|
# pickling. This is necessary because unpickling needs access to the StreamBlock
|
|
138
138
|
# definition, which cannot itself be pickled; instead we store a pointer to the
|
|
139
139
|
# field within the model, which gives us a path to retrieve the StreamBlock definition.
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
return value
|
|
143
|
-
|
|
144
|
-
def _to_python(self, value):
|
|
145
|
-
if value is None or value == "":
|
|
146
|
-
return StreamValue(self.stream_block, [])
|
|
147
|
-
elif isinstance(value, StreamValue):
|
|
148
|
-
return value
|
|
149
|
-
elif isinstance(value, str):
|
|
150
|
-
try:
|
|
151
|
-
unpacked_value = json.loads(value)
|
|
152
|
-
except ValueError:
|
|
153
|
-
# value is not valid JSON; most likely, this field was previously a
|
|
154
|
-
# rich text field before being migrated to StreamField, and the data
|
|
155
|
-
# was left intact in the migration. Return an empty stream instead
|
|
156
|
-
# (but keep the raw text available as an attribute, so that it can be
|
|
157
|
-
# used to migrate that data to StreamField)
|
|
158
|
-
return StreamValue(self.stream_block, [], raw_text=value)
|
|
159
|
-
|
|
160
|
-
if unpacked_value is None:
|
|
161
|
-
# we get here if value is the literal string 'null'. This should probably
|
|
162
|
-
# never happen if the rest of the (de)serialization code is working properly,
|
|
163
|
-
# but better to handle it just in case...
|
|
164
|
-
return StreamValue(self.stream_block, [])
|
|
165
|
-
|
|
166
|
-
return self.stream_block.to_python(unpacked_value)
|
|
167
|
-
elif value and isinstance(value, list) and isinstance(value[0], dict):
|
|
168
|
-
# The value is already unpacked since JSONField-based StreamField should
|
|
169
|
-
# accept deserialised values (no need to call json.dumps() first).
|
|
170
|
-
# In addition, the value is not a list of (block_name, value) tuples
|
|
171
|
-
# handled in the `else` block.
|
|
172
|
-
return self.stream_block.to_python(value)
|
|
173
|
-
else:
|
|
174
|
-
# See if it looks like the standard non-smart representation of a
|
|
175
|
-
# StreamField value: a list of (block_name, value) tuples
|
|
176
|
-
try:
|
|
177
|
-
[None for (x, y) in value]
|
|
178
|
-
except (TypeError, ValueError):
|
|
179
|
-
# Give up trying to make sense of the value
|
|
180
|
-
raise TypeError(
|
|
181
|
-
"Cannot handle %r (type %r) as a value of StreamField"
|
|
182
|
-
% (value, type(value))
|
|
183
|
-
)
|
|
184
|
-
|
|
185
|
-
# Test succeeded, so return as a StreamValue-ified version of that value
|
|
186
|
-
return StreamValue(self.stream_block, value)
|
|
140
|
+
result._stream_field = self
|
|
141
|
+
return result
|
|
187
142
|
|
|
188
143
|
def get_prep_value(self, value):
|
|
189
144
|
if (
|
wagtail/images/admin_urls.py
CHANGED
|
@@ -24,7 +24,7 @@ urlpatterns = [
|
|
|
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"),
|
|
26
26
|
path(
|
|
27
|
-
"multiple/create_from_uploaded_image/<int:
|
|
27
|
+
"multiple/create_from_uploaded_image/<int:uploaded_file_id>/",
|
|
28
28
|
multiple.CreateFromUploadedImageView.as_view(),
|
|
29
29
|
name="create_multiple_from_uploaded_image",
|
|
30
30
|
),
|
|
@@ -34,7 +34,7 @@ urlpatterns = [
|
|
|
34
34
|
name="delete_multiple",
|
|
35
35
|
),
|
|
36
36
|
path(
|
|
37
|
-
"multiple/delete_upload/<int:
|
|
37
|
+
"multiple/delete_upload/<int:uploaded_file_id>/",
|
|
38
38
|
multiple.DeleteUploadView.as_view(),
|
|
39
39
|
name="delete_upload_multiple",
|
|
40
40
|
),
|
|
Binary file
|
|
Binary file
|
wagtail/images/fields.py
CHANGED
|
@@ -205,5 +205,7 @@ def image_format_name_to_content_type(image_format_name):
|
|
|
205
205
|
return "image/webp"
|
|
206
206
|
elif image_format_name == "avif":
|
|
207
207
|
return "image/avif"
|
|
208
|
+
elif image_format_name == "ico":
|
|
209
|
+
return "image/x-icon"
|
|
208
210
|
else:
|
|
209
211
|
raise ValueError("Unknown image format name")
|
|
@@ -409,7 +409,7 @@ class WebPQualityOperation(FilterOperation):
|
|
|
409
409
|
|
|
410
410
|
|
|
411
411
|
class FormatOperation(FilterOperation):
|
|
412
|
-
supported_formats = ["jpeg", "png", "gif", "webp", "avif"]
|
|
412
|
+
supported_formats = ["jpeg", "png", "gif", "webp", "avif", "ico"]
|
|
413
413
|
|
|
414
414
|
def construct(self, format, *options):
|
|
415
415
|
self.format = format
|
|
Binary file
|
|
@@ -416,6 +416,18 @@ msgstr "Previsualització"
|
|
|
416
416
|
msgid "URL"
|
|
417
417
|
msgstr "URL"
|
|
418
418
|
|
|
419
|
+
msgid "Image URL"
|
|
420
|
+
msgstr "URL d'imatge"
|
|
421
|
+
|
|
422
|
+
msgid "Copy URL"
|
|
423
|
+
msgstr "Copiar URL"
|
|
424
|
+
|
|
425
|
+
msgid "Copied to clipboard"
|
|
426
|
+
msgstr "S'ha copiat al porta-retalls"
|
|
427
|
+
|
|
428
|
+
msgid "Copying to clipboard failed"
|
|
429
|
+
msgstr "Ha fallat la còpia al porta-retalls"
|
|
430
|
+
|
|
419
431
|
msgid "Add multiple images"
|
|
420
432
|
msgstr "Afegir diverses imatges"
|
|
421
433
|
|