pageflow 17.1.0 → 17.2.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +319 -345
- data/README.md +3 -4
- data/admins/pageflow/accounts.rb +6 -6
- data/admins/pageflow/entry.rb +10 -8
- data/admins/pageflow/membership.rb +11 -11
- data/admins/pageflow/translations.rb +5 -5
- data/app/assets/images/pageflow/admin/icons/comment.svg +1 -0
- data/app/assets/javascripts/pageflow/dist/ui.js +1350 -630
- data/app/assets/javascripts/pageflow/editor/vendor.js +0 -1
- data/app/assets/javascripts/pageflow/ui.js +0 -1
- data/app/assets/stylesheets/pageflow/admin/entry_comments_indicator.scss +45 -0
- data/app/assets/stylesheets/pageflow/admin/permalink_input.scss +8 -1
- data/app/assets/stylesheets/pageflow/admin.scss +1 -0
- data/app/assets/stylesheets/pageflow/animations/spin.scss +9 -0
- data/app/assets/stylesheets/pageflow/animations.scss +1 -0
- data/app/assets/stylesheets/pageflow/editor/background_positioning.scss +21 -5
- data/app/assets/stylesheets/pageflow/editor/base.scss +9 -1
- data/app/assets/stylesheets/pageflow/editor/drop_down_button.scss +13 -1
- data/app/assets/stylesheets/pageflow/editor/edit_configuration_view.scss +5 -0
- data/app/assets/stylesheets/pageflow/editor/file_folders.scss +127 -0
- data/app/assets/stylesheets/pageflow/editor/file_meta_data.scss +0 -1
- data/app/assets/stylesheets/pageflow/editor/file_meta_data_overlay.scss +45 -0
- data/app/assets/stylesheets/pageflow/editor/file_preview.scss +138 -0
- data/app/assets/stylesheets/pageflow/editor/file_references.scss +68 -0
- data/app/assets/stylesheets/pageflow/editor/file_settings_dialog.scss +1 -1
- data/app/assets/stylesheets/pageflow/editor/file_stage_icons.scss +17 -0
- data/app/assets/stylesheets/pageflow/editor/file_stages.scss +25 -32
- data/app/assets/stylesheets/pageflow/editor/file_thumbnails.scss +31 -48
- data/app/assets/stylesheets/pageflow/editor/file_type_pills.scss +73 -0
- data/app/assets/stylesheets/pageflow/editor/files.scss +230 -50
- data/app/assets/stylesheets/pageflow/editor/filtered_files.scss +142 -14
- data/app/assets/stylesheets/pageflow/editor/folder_breadcrumb.scss +40 -0
- data/app/assets/stylesheets/pageflow/editor/info_box.scss +12 -0
- data/app/assets/stylesheets/pageflow/editor/inputs/edit_defaults_button.scss +15 -0
- data/app/assets/stylesheets/pageflow/editor/inputs.scss +1 -0
- data/app/assets/stylesheets/pageflow/editor/list.scss +88 -38
- data/app/assets/stylesheets/pageflow/editor/manage_files.scss +9 -0
- data/app/assets/stylesheets/pageflow/editor/menu.scss +14 -0
- data/app/assets/stylesheets/pageflow/editor/move_to_folder_dialog.scss +83 -0
- data/app/assets/stylesheets/pageflow/mixins/pageflow.scss +9 -5
- data/app/assets/stylesheets/pageflow/ui/color_picker.scss +230 -0
- data/app/assets/stylesheets/pageflow/ui/forms.scss +34 -4
- data/app/assets/stylesheets/pageflow/ui/functions.scss +12 -2
- data/app/assets/stylesheets/pageflow/ui/input/color_input.scss +9 -16
- data/app/assets/stylesheets/pageflow/ui/input/text_area_input.scss +15 -0
- data/app/assets/stylesheets/pageflow/ui/overrides.scss +8 -0
- data/app/assets/stylesheets/pageflow/ui/properties.scss +29 -0
- data/app/assets/stylesheets/pageflow/ui/tabs_view.scss +8 -3
- data/app/assets/stylesheets/pageflow/ui.scss +4 -2
- data/app/controllers/pageflow/editor/entries_controller.rb +1 -0
- data/app/controllers/pageflow/editor/file_folders_controller.rb +80 -0
- data/app/controllers/pageflow/editor/file_import_controller.rb +1 -0
- data/app/controllers/pageflow/editor/files_controller.rb +15 -6
- data/app/controllers/pageflow/editor/oembeds_controller.rb +21 -0
- data/app/controllers/pageflow/entries_controller.rb +17 -13
- data/app/controllers/pageflow/review/comment_thread_reads_controller.rb +30 -0
- data/app/controllers/pageflow/review/comment_threads_controller.rb +60 -0
- data/app/controllers/pageflow/review/comments_controller.rb +53 -0
- data/app/controllers/pageflow/revisions_controller.rb +4 -1
- data/app/helpers/pageflow/admin/entries_helper.rb +40 -0
- data/app/helpers/pageflow/admin/widgets_helper.rb +2 -2
- data/app/helpers/pageflow/common_entry_seed_helper.rb +5 -3
- data/app/helpers/pageflow/editor/config_helper.rb +3 -1
- data/app/helpers/pageflow/entries_helper.rb +24 -42
- data/app/helpers/pageflow/entry_json_seed_helper.rb +4 -4
- data/app/helpers/pageflow/public_i18n_helper.rb +9 -8
- data/app/helpers/pageflow/structured_data_helper.rb +4 -1
- data/app/helpers/pageflow/themes_helper.rb +1 -3
- data/app/helpers/pageflow/widgets_helper.rb +2 -1
- data/app/inputs/pageflow_permalink_input.rb +6 -2
- data/app/models/concerns/pageflow/auto_generated_perma_id.rb +11 -4
- data/app/models/concerns/pageflow/reusable_file.rb +1 -1
- data/app/models/concerns/pageflow/serialization_blacklist.rb +2 -4
- data/app/models/concerns/pageflow/translated_attributes.rb +101 -0
- data/app/models/concerns/pageflow/uploadable_file.rb +1 -1
- data/app/models/pageflow/comment.rb +30 -0
- data/app/models/pageflow/comment_thread.rb +65 -0
- data/app/models/pageflow/comment_thread_read.rb +22 -0
- data/app/models/pageflow/customized_theme.rb +3 -2
- data/app/models/pageflow/draft_entry.rb +20 -8
- data/app/models/pageflow/entry.rb +2 -0
- data/app/models/pageflow/entry_at_revision.rb +9 -1
- data/app/models/pageflow/entry_comment_summary.rb +114 -0
- data/app/models/pageflow/file_folder.rb +74 -0
- data/app/models/pageflow/file_reuse.rb +3 -2
- data/app/models/pageflow/file_usage.rb +8 -0
- data/app/models/pageflow/image_file.rb +24 -20
- data/app/models/pageflow/image_file_url_templates.rb +3 -3
- data/app/models/pageflow/legal_info.rb +38 -0
- data/app/models/pageflow/nested_revision_component_copy.rb +1 -1
- data/app/models/pageflow/permalink.rb +1 -0
- data/app/models/pageflow/revision.rb +6 -2
- data/app/models/pageflow/site.rb +10 -0
- data/app/models/pageflow/used_file.rb +8 -2
- data/app/models/pageflow/widget.rb +2 -2
- data/app/views/pageflow/audio_files/_audio_file.json.jbuilder +0 -1
- data/app/views/pageflow/editor/config/_seeds.json.jbuilder +4 -2
- data/app/views/pageflow/editor/entries/_entry.json.jbuilder +2 -1
- data/app/views/pageflow/editor/entries/seed.json.erb +1 -0
- data/app/views/pageflow/editor/file_folders/_file_folder.json.jbuilder +5 -0
- data/app/views/pageflow/editor/file_folders/create.json.jbuilder +1 -0
- data/app/views/pageflow/editor/file_folders/index.json.jbuilder +3 -0
- data/app/views/pageflow/editor/files/_file.json.jbuilder +2 -1
- data/app/views/pageflow/editor/image_files/_image_file.json.jbuilder +3 -0
- data/app/views/pageflow/editor/video_files/_video_file.json.jbuilder +3 -0
- data/app/views/pageflow/files/_file.json.jbuilder +2 -0
- data/app/views/pageflow/image_files/_image_file.json.jbuilder +0 -1
- data/app/views/pageflow/review/comment_threads/_comment_thread.json.jbuilder +20 -0
- data/app/views/pageflow/review/comment_threads/create.json.jbuilder +2 -0
- data/app/views/pageflow/review/comment_threads/index.json.jbuilder +13 -0
- data/app/views/pageflow/review/comments/_comment.json.jbuilder +13 -0
- data/app/views/pageflow/review/comments/create.json.jbuilder +1 -0
- data/app/views/pageflow/structured_data/_entry.json.jbuilder +2 -3
- data/app/views/pageflow/video_files/_video_file.json.jbuilder +0 -1
- data/config/locales/de.yml +152 -14
- data/config/locales/en.yml +150 -14
- data/config/routes.rb +14 -0
- data/db/migrate/20140418225525_setup_schema.rb +2 -2
- data/db/migrate/20251015000000_add_structured_data_type_name_to_revisions.rb +5 -0
- data/db/migrate/20251029142849_convert_legacy_social_embeds_to_unified_social_embed.rb +38 -0
- data/db/migrate/20251119083347_fix_main_storyline_positions.rb +16 -0
- data/db/migrate/20251119083348_ensure_scrolled_entries_have_excursion_storyline.rb +15 -0
- data/db/migrate/20260303000000_add_layout_version_to_revisions.rb +6 -0
- data/db/migrate/20260323000000_create_comment_threads_and_comments.rb +30 -0
- data/db/migrate/20260414000000_add_subject_range_to_comment_threads.rb +5 -0
- data/db/migrate/20260415000000_add_section_perma_id_to_comment_threads.rb +5 -0
- data/db/migrate/20260727000000_add_quote_to_comments.rb +5 -0
- data/db/migrate/20260728000000_create_file_folders.rb +17 -0
- data/db/migrate/20260805000000_add_attribute_translations_to_sites.rb +5 -0
- data/db/migrate/20260806000000_add_edited_at_to_comments.rb +5 -0
- data/db/migrate/20260810000000_create_pageflow_scrolled_lottie_files.rb +24 -0
- data/db/migrate/20260817000000_create_comment_thread_reads.rb +16 -0
- data/db/migrate/20260819000000_add_unread_comments_since_at_to_users.rb +18 -0
- data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/editor.js +8665 -3890
- data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/frontend.js +979 -3571
- data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/react-client.js +20199 -28120
- data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/react-server.js +18652 -26584
- data/entry_types/scrolled/app/assets/stylesheets/pageflow_scrolled/ui.scss +2 -0
- data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/content_elements_controller.rb +33 -3
- data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/sections_controller.rb +2 -3
- data/entry_types/scrolled/app/controllers/pageflow_scrolled/entries_controller.rb +21 -1
- data/entry_types/scrolled/app/helpers/pageflow_scrolled/cache_helper.rb +3 -3
- data/entry_types/scrolled/app/helpers/pageflow_scrolled/editor/entry_json_seed_helper.rb +7 -5
- data/entry_types/scrolled/app/helpers/pageflow_scrolled/editor/seed_html_helper.rb +5 -2
- data/entry_types/scrolled/app/helpers/pageflow_scrolled/entry_json_seed_helper.rb +13 -5
- data/entry_types/scrolled/app/helpers/pageflow_scrolled/i18n_helper.rb +28 -13
- data/entry_types/scrolled/app/helpers/pageflow_scrolled/packs_helper.rb +26 -11
- data/entry_types/scrolled/app/helpers/pageflow_scrolled/react_server_side_rendering_helper.rb +2 -2
- data/entry_types/scrolled/app/helpers/pageflow_scrolled/sprockets_helper.rb +16 -0
- data/entry_types/scrolled/app/helpers/pageflow_scrolled/themes_helper.rb +174 -3
- data/entry_types/scrolled/app/models/pageflow_scrolled/content_element.rb +49 -7
- data/entry_types/scrolled/app/models/pageflow_scrolled/lottie_file.rb +6 -0
- data/entry_types/scrolled/app/models/pageflow_scrolled/lottie_file_url_templates.rb +16 -0
- data/entry_types/scrolled/app/models/pageflow_scrolled/storyline.rb +1 -0
- data/entry_types/scrolled/app/views/pageflow_scrolled/entries/show.html.erb +13 -12
- data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_entry.json.jbuilder +30 -10
- data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_theme.json.jbuilder +9 -0
- data/entry_types/scrolled/app/views/pageflow_scrolled/favicons/_entry.html.erb +1 -1
- data/entry_types/scrolled/config/configuration_schemas/pageflow-scrolled.json +414 -0
- data/entry_types/scrolled/config/locales/de.yml +512 -65
- data/entry_types/scrolled/config/locales/en.yml +518 -52
- data/entry_types/scrolled/lib/pageflow_scrolled/additional_seed_data.rb +2 -2
- data/entry_types/scrolled/lib/pageflow_scrolled/configuration.rb +51 -6
- data/entry_types/scrolled/lib/pageflow_scrolled/configuration_schemas.rb +91 -0
- data/entry_types/scrolled/lib/pageflow_scrolled/engine.rb +2 -1
- data/entry_types/scrolled/lib/pageflow_scrolled/entry_file_reference_locations.rb +71 -0
- data/entry_types/scrolled/lib/pageflow_scrolled/entry_structured_data_types/faq_page.rb +58 -0
- data/entry_types/scrolled/lib/pageflow_scrolled/file_reference_locations.rb +69 -0
- data/entry_types/scrolled/lib/pageflow_scrolled/plugin.rb +205 -22
- data/entry_types/scrolled/lib/pageflow_scrolled/react_widget_type.rb +2 -4
- data/entry_types/scrolled/lib/pageflow_scrolled/seeds.rb +56 -36
- data/entry_types/scrolled/lib/pageflow_scrolled/theme_options_default_scale.rb +35 -0
- data/entry_types/scrolled/lib/pageflow_scrolled.rb +13 -0
- data/entry_types/scrolled/lib/tasks/pageflow_scrolled/storybook.rake +19 -1
- data/entry_types/scrolled/package/config/configurationSchemas.js +70 -0
- data/entry_types/scrolled/package/config/rollup/configurationSchemas.js +19 -0
- data/entry_types/scrolled/package/config/webpack.js +72 -0
- data/entry_types/scrolled/package/contentElements/hotspots-frontend.css +1 -1
- data/entry_types/scrolled/package/contentElements/hotspots-frontend.js +1181 -915
- data/entry_types/scrolled/package/contentElements/inlineBeforeAfter-frontend.css +1 -0
- data/entry_types/scrolled/package/contentElements/inlineBeforeAfter-frontend.js +219 -0
- data/entry_types/scrolled/package/contentElements/lottieAnimation-frontend.css +1 -0
- data/entry_types/scrolled/package/contentElements/lottieAnimation-frontend.js +244 -0
- data/entry_types/scrolled/package/contentElements/socialEmbed-frontend.css +1 -0
- data/entry_types/scrolled/package/contentElements/socialEmbed-frontend.js +823 -0
- data/entry_types/scrolled/package/contentElements/tikTokEmbed-frontend.js +71 -21
- data/entry_types/scrolled/package/contentElements/twitterEmbed-frontend.css +1 -0
- data/entry_types/scrolled/package/contentElements/twitterEmbed-frontend.js +277 -0
- data/entry_types/scrolled/package/contentElements/videoEmbed-frontend.css +1 -0
- data/entry_types/scrolled/package/contentElements/videoEmbed-frontend.js +244 -0
- data/entry_types/scrolled/package/contentElements-editor.js +1915 -1097
- data/entry_types/scrolled/package/contentElements-frontend.css +1 -1
- data/entry_types/scrolled/package/contentElements-frontend.js +3093 -1679
- data/entry_types/scrolled/package/editor.css +1 -0
- data/entry_types/scrolled/package/editor.js +8667 -4077
- data/entry_types/scrolled/package/entryState.js +1600 -0
- data/entry_types/scrolled/package/frontend/FloatingPortalRootProvider-20c600de.js +1979 -0
- data/entry_types/scrolled/package/frontend/FloatingPortalRootProvider-58189220.js +2538 -0
- data/entry_types/scrolled/package/frontend/{PhonePlatformContext-9f76033e.js → PhonePlatformContext-035a99fa.js} +7 -12
- data/entry_types/scrolled/package/frontend/PhonePlatformContext-9da43797.js +33 -0
- data/entry_types/scrolled/package/frontend/Placeholder.module-bf0966b4.js +5267 -0
- data/entry_types/scrolled/package/frontend/Placeholder.module-d22a9335.js +4180 -0
- data/entry_types/scrolled/package/frontend/ThemeIcon-ab834849.js +754 -0
- data/entry_types/scrolled/package/frontend/ThemeIcon-f6cb3a8f.js +773 -0
- data/entry_types/scrolled/package/frontend/{ToggleFullscreenCornerButton-788e9cdb.js → ToggleFullscreenCornerButton-30fd1124.js} +6 -6
- data/entry_types/scrolled/package/frontend/ToggleFullscreenCornerButton-61c25224.js +72 -0
- data/entry_types/scrolled/package/frontend/Viewer-1074fd59.js +147 -0
- data/entry_types/scrolled/package/frontend/Viewer-1482ca34.js +480 -0
- data/entry_types/scrolled/package/frontend/Viewer-70504231.js +210 -0
- data/entry_types/scrolled/package/frontend/{Viewer-0345ce57.js → Viewer-cc8d4072.js} +84 -92
- data/entry_types/scrolled/package/frontend/Wavesurfer-656e3c36.js +302 -0
- data/entry_types/scrolled/package/frontend/Wavesurfer-b753b838.js +385 -0
- data/entry_types/scrolled/package/frontend/commenting.css +1 -0
- data/entry_types/scrolled/package/frontend/extensions-167ae143.js +1455 -0
- data/entry_types/scrolled/package/frontend/extensions-2318f92b.js +5918 -0
- data/entry_types/scrolled/package/frontend/extensions-a461fd13.js +4890 -0
- data/entry_types/scrolled/package/frontend/extensions-c98269fd.js +1982 -0
- data/entry_types/scrolled/package/frontend/i18n-493cd2a6.js +93 -0
- data/entry_types/scrolled/package/frontend/i18n-e06cac14.js +100 -0
- data/entry_types/scrolled/package/frontend/{index-eb670c2f.js → index-2e5546f7.js} +36 -44
- data/entry_types/scrolled/package/frontend/index-de2b418d.js +130 -0
- data/entry_types/scrolled/package/frontend/index.css +1 -1
- data/entry_types/scrolled/package/frontend/index.js +1870 -875
- data/entry_types/scrolled/package/frontend/inlineEditing.css +1 -0
- data/entry_types/scrolled/package/frontend/useContentElementEditorState-a084912e.js +25 -0
- data/entry_types/scrolled/package/frontend/useDelayedBoolean-a387d85b.js +24 -0
- data/entry_types/scrolled/package/frontend/{usePhonePlatform-c2ba875d.js → usePhonePlatform-4ecb96d4.js} +1 -1
- data/entry_types/scrolled/package/frontend/usePhonePlatform-ce9ff08d.js +8 -0
- data/entry_types/scrolled/package/frontend-server.js +20 -209
- data/entry_types/scrolled/package/package.json +5 -3
- data/entry_types/scrolled/package/review.css +1 -0
- data/entry_types/scrolled/package/review.js +3306 -0
- data/entry_types/scrolled/package/testHelpers.js +836 -359
- data/entry_types/scrolled/package/widgets/consentBar.css +1 -1
- data/entry_types/scrolled/package/widgets/consentBar.js +269 -290
- data/entry_types/scrolled/package/widgets/defaultNavigation.css +2 -2
- data/entry_types/scrolled/package/widgets/defaultNavigation.js +911 -352
- data/entry_types/scrolled/package/widgets/excursionSheet.css +1 -1
- data/entry_types/scrolled/package/widgets/excursionSheet.js +87 -124
- data/entry_types/scrolled/package/widgets/iconInlineFileRights.css +1 -1
- data/entry_types/scrolled/package/widgets/iconInlineFileRights.js +62 -29
- data/entry_types/scrolled/package/widgets/iconScrollIndicator.js +32 -13
- data/entry_types/scrolled/package/widgets/mainStorylineSheet.css +1 -1
- data/entry_types/scrolled/package/widgets/mainStorylineSheet.js +56 -100
- data/entry_types/scrolled/package/widgets/textInlineFileRights.css +1 -1
- data/entry_types/scrolled/package/widgets/textInlineFileRights.js +33 -28
- data/entry_types/scrolled/package/widgets-server.js +1 -0
- data/entry_types/scrolled/spec/factories/lottie_files.rb +29 -0
- data/entry_types/scrolled/spec/fixtures/animation.lottie +0 -0
- data/entry_types/scrolled/spec/fixtures/font.woff +0 -0
- data/entry_types/scrolled/spec/fixtures/font.woff2 +0 -0
- data/lib/generators/pageflow/resque/resque_generator.rb +0 -2
- data/lib/pageflow/configuration.rb +49 -7
- data/lib/pageflow/deprecation.rb +19 -0
- data/lib/pageflow/engine.rb +1 -1
- data/lib/pageflow/entries_controller_env_helper.rb +32 -2
- data/lib/pageflow/entry_export_import/entry_serialization.rb +4 -4
- data/lib/pageflow/entry_export_import/page_type_versions.rb +2 -2
- data/lib/pageflow/entry_export_import/revision_serialization/import.rb +10 -0
- data/lib/pageflow/entry_export_import/revision_serialization.rb +3 -0
- data/lib/pageflow/entry_structured_data_types.rb +43 -0
- data/lib/pageflow/entry_type_configuration.rb +1 -0
- data/lib/pageflow/file_type.rb +2 -2
- data/lib/pageflow/file_types.rb +1 -1
- data/lib/pageflow/oembed_providers.rb +42 -0
- data/lib/pageflow/primary_domain_entry_redirect.rb +6 -0
- data/lib/pageflow/rails_version.rb +13 -2
- data/lib/pageflow/themes.rb +41 -0
- data/lib/pageflow/user_mixin.rb +12 -0
- data/lib/pageflow/version.rb +1 -1
- data/lib/pageflow.rb +1 -0
- data/package/config/eslint-rules/documented-in-toc.js +125 -0
- data/package/config/jest/index.js +0 -1
- data/package/config/webpack.js +0 -1
- data/package/config/webpack5.js +0 -1
- data/package/editor.js +4378 -1897
- data/package/frontend.js +647 -886
- data/package/package.json +2 -1
- data/package/review.js +384 -0
- data/package/testHelpers.js +248 -188
- data/package/ui.js +1346 -630
- data/package/vendor/stubs/wysihtml5.js +2 -0
- data/spec/factories/comment_thread_reads.rb +10 -0
- data/spec/factories/comment_threads.rb +10 -0
- data/spec/factories/comments.rb +9 -0
- data/spec/factories/file_folders.rb +8 -0
- data/spec/factories/published_entries.rb +2 -0
- metadata +188 -67
- data/app/assets/stylesheets/pageflow/editor/select_button.scss +0 -51
- data/entry_types/scrolled/app/helpers/pageflow_scrolled/generated_media_queries_helper.rb +0 -55
- data/entry_types/scrolled/package/frontend/FloatingPortalRootProvider-51914be7.js +0 -5439
- data/entry_types/scrolled/package/frontend/ThemeIcon-81f2f066.js +0 -1932
- data/entry_types/scrolled/package/frontend/Viewer-cdc549cc.js +0 -147
- data/entry_types/scrolled/package/frontend/Wavesurfer-1cdc3925.js +0 -313
- data/entry_types/scrolled/package/frontend/components-96660ffd.js +0 -3803
- data/entry_types/scrolled/package/frontend/inherits-539844a6.js +0 -99
- data/entry_types/scrolled/package/frontend/useContentElementEditorState-77fe6c79.js +0 -51
- data/entry_types/scrolled/package/widgets/excursionDialog.css +0 -1
- data/entry_types/scrolled/package/widgets/excursionDialog.js +0 -109
- data/lib/generators/pageflow/resque/templates/resque_enqueue_after_commit_patch.rb +0 -25
- data/package/vendor/jquery.minicolors.js +0 -1108
|
@@ -1,59 +1,351 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { ConfigurationEditorTabView } from 'pageflow/ui';
|
|
2
|
+
import { FileInputView } from 'pageflow/editor';
|
|
3
|
+
import { render, act } from '@testing-library/react';
|
|
4
|
+
import { renderBackboneView, ConfigurationEditor } from 'pageflow/testHelpers';
|
|
5
|
+
export { renderBackboneView as renderReactBasedBackboneView } from 'pageflow/testHelpers';
|
|
6
|
+
import { EditContentElementView, editor } from 'pageflow-scrolled/editor';
|
|
7
|
+
import React, { useEffect, useState } from 'react';
|
|
2
8
|
import { DndProvider } from 'react-dnd';
|
|
3
9
|
import { HTML5Backend } from 'react-dnd-html5-backend';
|
|
4
10
|
import BackboneEvents from 'backbone-events-standalone';
|
|
5
|
-
import {
|
|
6
|
-
import { RootProviders, useEntryStateDispatch, ContentElementLifecycleContext, ContentElementEditorStateContext, PhonePlatformContext, ContentElementAttributesProvider, ContentElementEditorCommandEmitterContext } from 'pageflow-scrolled/frontend';
|
|
7
|
-
import { renderHook } from '@testing-library/react-hooks/dom';
|
|
11
|
+
import { PhonePlatformContext, RootProviders, useEntryStateDispatch, ContentElementLifecycleContext, ContentElementEditorCommandEmitterContext, ContentElementEditorStateContext, MainStorylineActivity, ContentElementAttributesProvider, ContentElementViewTimelineContext } from 'pageflow-scrolled/frontend';
|
|
8
12
|
import { Consent } from 'pageflow/frontend';
|
|
13
|
+
import { renderHook } from '@testing-library/react-hooks/dom';
|
|
9
14
|
|
|
10
|
-
function
|
|
11
|
-
if (
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
function styleInject(css, ref) {
|
|
16
|
+
if ( ref === void 0 ) ref = {};
|
|
17
|
+
var insertAt = ref.insertAt;
|
|
18
|
+
|
|
19
|
+
if (!css || typeof document === 'undefined') { return; }
|
|
20
|
+
|
|
21
|
+
var head = document.head || document.getElementsByTagName('head')[0];
|
|
22
|
+
var style = document.createElement('style');
|
|
23
|
+
style.type = 'text/css';
|
|
24
|
+
|
|
25
|
+
if (insertAt === 'top') {
|
|
26
|
+
if (head.firstChild) {
|
|
27
|
+
head.insertBefore(style, head.firstChild);
|
|
28
|
+
} else {
|
|
29
|
+
head.appendChild(style);
|
|
30
|
+
}
|
|
18
31
|
} else {
|
|
19
|
-
|
|
32
|
+
head.appendChild(style);
|
|
20
33
|
}
|
|
21
34
|
|
|
22
|
-
|
|
35
|
+
if (style.styleSheet) {
|
|
36
|
+
style.styleSheet.cssText = css;
|
|
37
|
+
} else {
|
|
38
|
+
style.appendChild(document.createTextNode(css));
|
|
39
|
+
}
|
|
23
40
|
}
|
|
24
41
|
|
|
25
|
-
|
|
26
|
-
|
|
42
|
+
var css = ".ContentElementBox-module_properties__1ljc9 {\n --content-element-box-box-shadow:\n var(--content-element-box-shadow, 0 0 #000),\n 0 0 0 1px var(--content-element-box-outline-color, transparent);\n}\n\n.ContentElementBox-module_wrapper__3wZgP {\n overflow: hidden;\n border-radius: var(--content-element-box-border-radius,\n var(--theme-content-element-box-border-radius));\n box-shadow: var(--content-element-box-box-shadow);\n}\n\n.ContentElementBox-module_full__AfWPr {\n border-radius: var(--content-element-box-border-radius,\n var(--theme-content-element-full-box-border-radius,\n var(--theme-content-element-box-border-radius)));\n}\n\n.ContentElementBox-module_positioned__3R1dq {\n position: relative;\n height: 100%;\n}\n";
|
|
43
|
+
var styles = {"properties":"ContentElementBox-module_properties__1ljc9","wrapper":"ContentElementBox-module_wrapper__3wZgP","full":"ContentElementBox-module_full__AfWPr","positioned":"ContentElementBox-module_positioned__3R1dq"};
|
|
44
|
+
styleInject(css);
|
|
27
45
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
});
|
|
33
|
-
keys.push.apply(keys, symbols);
|
|
34
|
-
}
|
|
46
|
+
function getElement(subject) {
|
|
47
|
+
var _subject$el;
|
|
48
|
+
return (_subject$el = subject === null || subject === void 0 ? void 0 : subject.el) !== null && _subject$el !== void 0 ? _subject$el : subject;
|
|
49
|
+
}
|
|
35
50
|
|
|
36
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Assert that the subject contains a `ContentElementBox` and, optionally,
|
|
53
|
+
* that the box has specific theme styles applied. Registered via
|
|
54
|
+
* {@link useContentElementMatchers}.
|
|
55
|
+
*
|
|
56
|
+
* The subject is a DOM element, e.g. the `container` returned by
|
|
57
|
+
* {@link renderInContentElement}. Negate with `.not` to assert that no
|
|
58
|
+
* box is present.
|
|
59
|
+
*
|
|
60
|
+
* @param {Object} [options]
|
|
61
|
+
* @param {string} [options.boxShadow] - Expected box shadow theme scale, e.g. `'md'`.
|
|
62
|
+
* @param {string} [options.borderRadius] - Expected border radius theme scale, e.g. `'circle'`.
|
|
63
|
+
* @param {string} [options.outlineColor] - Expected outline color.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* expect(container).toContainContentElementBox();
|
|
67
|
+
* expect(container).toContainContentElementBox({borderRadius: 'circle', boxShadow: 'md'});
|
|
68
|
+
* expect(container).not.toContainContentElementBox();
|
|
69
|
+
*/
|
|
70
|
+
function toContainContentElementBox(subject, options = {}) {
|
|
71
|
+
const wrapper = getElement(subject).querySelector(`.${styles.wrapper}`);
|
|
72
|
+
if (!wrapper) {
|
|
73
|
+
return {
|
|
74
|
+
pass: false,
|
|
75
|
+
message: () => 'expected element to contain a content element box, but found none'
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const mismatches = boxPropertyMismatches(wrapper, options);
|
|
79
|
+
return {
|
|
80
|
+
pass: mismatches.length === 0,
|
|
81
|
+
message: () => mismatches.length ? `expected content element box to have ${mismatches.join(', ')}` : `expected element not to contain a content element box${describeOptions(options)}`
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
const boxProperties = {
|
|
85
|
+
boxShadow: {
|
|
86
|
+
customProperty: '--content-element-box-shadow',
|
|
87
|
+
expectedValue: value => `var(--theme-content-element-box-shadow-${value})`
|
|
88
|
+
},
|
|
89
|
+
borderRadius: {
|
|
90
|
+
customProperty: '--content-element-box-border-radius',
|
|
91
|
+
expectedValue: value => `var(--theme-content-element-box-border-radius-${value})`
|
|
92
|
+
},
|
|
93
|
+
outlineColor: {
|
|
94
|
+
customProperty: '--content-element-box-outline-color',
|
|
95
|
+
expectedValue: value => value
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
function boxPropertyMismatches(wrapper, options) {
|
|
99
|
+
return Object.keys(options).reduce((mismatches, name) => {
|
|
100
|
+
const property = boxProperties[name];
|
|
101
|
+
if (property) {
|
|
102
|
+
const expected = property.expectedValue(options[name]);
|
|
103
|
+
const actual = wrapper.style.getPropertyValue(property.customProperty);
|
|
104
|
+
if (actual !== expected) {
|
|
105
|
+
mismatches.push(`${name} ${JSON.stringify(options[name])} (found ${JSON.stringify(actual)})`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return mismatches;
|
|
109
|
+
}, []);
|
|
110
|
+
}
|
|
111
|
+
function describeOptions(options) {
|
|
112
|
+
const names = Object.keys(options).filter(name => boxProperties[name]);
|
|
113
|
+
return names.length ? ` with ${names.join(', ')}` : '';
|
|
37
114
|
}
|
|
38
115
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
116
|
+
var css$1 = ".FitViewport-module_container__-awVj {\n width: 100%;\n margin: 0 auto;\n max-width: var(\n --theme-fit-viewport,\n calc(100 * var(--vh) / var(--fit-viewport-aspect-ratio) * var(--fit-viewport-scale, 1))\n );\n}\n\n.FitViewport-module_content__1_K5a {\n position: relative;\n}\n\n.FitViewport-module_content__1_K5a > div:first-child {\n padding-top: calc(100% * var(--fit-viewport-aspect-ratio));\n}\n\n.FitViewport-module_inner__3psd1 {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n}\n\n@media print {\n .FitViewport-module_container__-awVj {\n page-break-inside: avoid;\n }\n}\n";
|
|
117
|
+
var styles$1 = {"container":"FitViewport-module_container__-awVj","content":"FitViewport-module_content__1_K5a","inner":"FitViewport-module_inner__3psd1"};
|
|
118
|
+
styleInject(css$1);
|
|
42
119
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
120
|
+
/**
|
|
121
|
+
* Assert that the subject contains a `FitViewport` and, optionally, that
|
|
122
|
+
* it has a specific aspect ratio. Registered via
|
|
123
|
+
* {@link useContentElementMatchers}.
|
|
124
|
+
*
|
|
125
|
+
* The subject is a DOM element, e.g. the `container` returned by
|
|
126
|
+
* {@link renderInContentElement}. Negate with `.not` to assert that no
|
|
127
|
+
* `FitViewport` is present.
|
|
128
|
+
*
|
|
129
|
+
* @param {Object} [options]
|
|
130
|
+
* @param {string} [options.aspectRatio] -
|
|
131
|
+
* Expected aspect ratio: a theme scale name (e.g. `'square'`) or a raw
|
|
132
|
+
* ratio value (e.g. `'0.75'`).
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* expect(container).toContainFitViewport();
|
|
136
|
+
* expect(container).toContainFitViewport({aspectRatio: 'square'});
|
|
137
|
+
*/
|
|
138
|
+
function toContainFitViewport(subject, {
|
|
139
|
+
aspectRatio
|
|
140
|
+
} = {}) {
|
|
141
|
+
const container = getElement(subject).querySelector(`.${styles$1.container}`);
|
|
142
|
+
if (!container) {
|
|
143
|
+
return {
|
|
144
|
+
pass: false,
|
|
145
|
+
message: () => 'expected element to contain a FitViewport, but found none'
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
if (aspectRatio !== undefined) {
|
|
149
|
+
const actual = getAspectRatio(container);
|
|
150
|
+
if (actual !== aspectRatio) {
|
|
151
|
+
return {
|
|
152
|
+
pass: false,
|
|
153
|
+
message: () => `expected FitViewport to have aspect ratio ${JSON.stringify(aspectRatio)} ` + `(found ${JSON.stringify(actual)})`
|
|
154
|
+
};
|
|
53
155
|
}
|
|
54
156
|
}
|
|
157
|
+
return {
|
|
158
|
+
pass: true,
|
|
159
|
+
message: () => 'expected element not to contain a FitViewport'
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function getAspectRatio(container) {
|
|
163
|
+
const cssValue = container.style.getPropertyValue('--fit-viewport-aspect-ratio');
|
|
164
|
+
const match = cssValue.match(/var\(--theme-aspect-ratio-(.+)\)/);
|
|
165
|
+
return match ? match[1] : cssValue;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Assert that all inputs rendered by a configuration editor are
|
|
170
|
+
* described by a configuration schema. Registered via
|
|
171
|
+
* {@link useConfigurationEditorMatchers}.
|
|
172
|
+
*
|
|
173
|
+
* The subject is a function that renders the configuration editor. Only
|
|
174
|
+
* inputs of the rendered form are seen. Views on nested routes render a
|
|
175
|
+
* form of their own and are checked against the part of the schema that
|
|
176
|
+
* describes the object they configure.
|
|
177
|
+
*
|
|
178
|
+
* @param {Object} schema - Configuration schema of the subject.
|
|
179
|
+
* @param {Object} [options]
|
|
180
|
+
* @param {Array<string>} [options.path] - Path of the configuration the
|
|
181
|
+
* rendered form writes, if it is not the root. `*` stands for array
|
|
182
|
+
* items and map values.
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* expect(() => renderContentElementConfigurationEditor({entry, contentElement}))
|
|
186
|
+
* .toRenderInputsMatching(require('./schema.json'));
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* expect(() => renderBackboneView(new SidebarEditAreaView(options)))
|
|
190
|
+
* .toRenderInputsMatching(require('../schema.json'), {path: ['areas', '*']});
|
|
191
|
+
*/
|
|
192
|
+
function toRenderInputsMatching(render, schema, {
|
|
193
|
+
path = []
|
|
194
|
+
} = {}) {
|
|
195
|
+
const subschema = subschemaAt(schema, path);
|
|
196
|
+
if (!subschema) {
|
|
197
|
+
return {
|
|
198
|
+
pass: false,
|
|
199
|
+
message: () => `expected schema to describe configuration at ${path.join('/')}`
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
const inputs = recordInputs(render);
|
|
203
|
+
if (!inputs.length) {
|
|
204
|
+
return {
|
|
205
|
+
pass: false,
|
|
206
|
+
message: () => 'expected configuration editor to render inputs, but it rendered none'
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
const mismatches = inputs.flatMap(input => mismatchesOf(input, subschema));
|
|
210
|
+
return {
|
|
211
|
+
pass: mismatches.length === 0,
|
|
212
|
+
message: () => mismatches.length ? `expected rendered inputs to match schema:\n ${mismatches.join('\n ')}` : 'expected rendered inputs not to match schema'
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
function subschemaAt(schema, path) {
|
|
216
|
+
return path.reduce((current, segment) => dereference(child(current, segment), schema), dereference(schema, schema));
|
|
217
|
+
}
|
|
218
|
+
function child(schema, segment) {
|
|
219
|
+
var _schema$properties;
|
|
220
|
+
if (!schema) {
|
|
221
|
+
return undefined;
|
|
222
|
+
}
|
|
223
|
+
return segment === '*' ? schema.items || schema.additionalProperties : (_schema$properties = schema.properties) === null || _schema$properties === void 0 ? void 0 : _schema$properties[segment];
|
|
224
|
+
}
|
|
225
|
+
function dereference(schema, document) {
|
|
226
|
+
var _schema2;
|
|
227
|
+
const seen = [];
|
|
228
|
+
while (((_schema = schema) === null || _schema === void 0 ? void 0 : _schema.$ref) && !seen.includes(schema.$ref)) {
|
|
229
|
+
var _schema;
|
|
230
|
+
seen.push(schema.$ref);
|
|
231
|
+
schema = localTarget(document, schema.$ref);
|
|
232
|
+
}
|
|
233
|
+
return ((_schema2 = schema) === null || _schema2 === void 0 ? void 0 : _schema2.$ref) ? undefined : schema;
|
|
234
|
+
}
|
|
235
|
+
function localTarget(document, ref) {
|
|
236
|
+
const [otherDocumentId, pointer] = ref.split('#');
|
|
237
|
+
if (otherDocumentId) {
|
|
238
|
+
return undefined;
|
|
239
|
+
}
|
|
240
|
+
return pointer.split('/').filter(Boolean).reduce((value, segment) => value === null || value === void 0 ? void 0 : value[segment], document);
|
|
241
|
+
}
|
|
242
|
+
function recordInputs(render) {
|
|
243
|
+
const inputs = [];
|
|
244
|
+
const input = ConfigurationEditorTabView.prototype.input;
|
|
245
|
+
jest.spyOn(ConfigurationEditorTabView.prototype, 'input').mockImplementation(function (propertyName, view, options = {}) {
|
|
246
|
+
inputs.push({
|
|
247
|
+
propertyName,
|
|
248
|
+
view,
|
|
249
|
+
options
|
|
250
|
+
});
|
|
251
|
+
return input.call(this, propertyName, view, options);
|
|
252
|
+
});
|
|
253
|
+
try {
|
|
254
|
+
render();
|
|
255
|
+
} finally {
|
|
256
|
+
ConfigurationEditorTabView.prototype.input.mockRestore();
|
|
257
|
+
}
|
|
258
|
+
return inputs;
|
|
259
|
+
}
|
|
260
|
+
const checks = [fileCollectionMismatch];
|
|
261
|
+
function mismatchesOf({
|
|
262
|
+
propertyName,
|
|
263
|
+
view,
|
|
264
|
+
options
|
|
265
|
+
}, schema) {
|
|
266
|
+
const property = (schema.properties || {})[propertyName];
|
|
267
|
+
return checks.flatMap(check => check({
|
|
268
|
+
propertyName,
|
|
269
|
+
view,
|
|
270
|
+
options,
|
|
271
|
+
property
|
|
272
|
+
}) || []);
|
|
273
|
+
}
|
|
274
|
+
function fileCollectionMismatch({
|
|
275
|
+
propertyName,
|
|
276
|
+
view,
|
|
277
|
+
options,
|
|
278
|
+
property
|
|
279
|
+
}) {
|
|
280
|
+
if (!isFileInput(view) || !options.collection) {
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
const declared = property && property['x-fileCollection'];
|
|
284
|
+
if (declared !== options.collection) {
|
|
285
|
+
return `${propertyName}: expected x-fileCollection ${JSON.stringify(options.collection)}, ` + `found ${JSON.stringify(declared)}`;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
function isFileInput(view) {
|
|
289
|
+
return view === FileInputView || view.prototype instanceof FileInputView;
|
|
290
|
+
}
|
|
55
291
|
|
|
56
|
-
|
|
292
|
+
/**
|
|
293
|
+
* Register the public content element matchers for the surrounding
|
|
294
|
+
* `describe` block: {@link toContainContentElementBox} and
|
|
295
|
+
* {@link toContainFitViewport}.
|
|
296
|
+
*
|
|
297
|
+
* Call inside a `describe` block. Content element plugins can use this to
|
|
298
|
+
* assert that their component opts into the framework chrome correctly.
|
|
299
|
+
*
|
|
300
|
+
* @example
|
|
301
|
+
* import {renderInContentElement, useContentElementMatchers} from 'pageflow-scrolled/testHelpers';
|
|
302
|
+
*
|
|
303
|
+
* describe('MyContentElement', () => {
|
|
304
|
+
* useContentElementMatchers();
|
|
305
|
+
*
|
|
306
|
+
* it('renders inside a box', () => {
|
|
307
|
+
* const {container} = renderInContentElement(<MyContentElement />);
|
|
308
|
+
* expect(container).toContainContentElementBox();
|
|
309
|
+
* });
|
|
310
|
+
* });
|
|
311
|
+
*/
|
|
312
|
+
function useContentElementMatchers() {
|
|
313
|
+
beforeEach(() => {
|
|
314
|
+
expect.extend({
|
|
315
|
+
toContainContentElementBox,
|
|
316
|
+
toContainFitViewport
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Register the configuration editor matchers for the surrounding
|
|
323
|
+
* `describe` block: {@link toRenderInputsMatching}.
|
|
324
|
+
*
|
|
325
|
+
* Call inside a `describe` block. Content element plugins can use this to
|
|
326
|
+
* assert that their configuration schema keeps up with their editor
|
|
327
|
+
* integration.
|
|
328
|
+
*
|
|
329
|
+
* @example
|
|
330
|
+
* import {
|
|
331
|
+
* renderContentElementConfigurationEditor, useConfigurationEditorMatchers
|
|
332
|
+
* } from 'pageflow-scrolled/testHelpers';
|
|
333
|
+
*
|
|
334
|
+
* describe('myContentElement/editor', () => {
|
|
335
|
+
* useConfigurationEditorMatchers();
|
|
336
|
+
*
|
|
337
|
+
* it('renders inputs described by schema', () => {
|
|
338
|
+
* expect(() => renderContentElementConfigurationEditor({entry, contentElement}))
|
|
339
|
+
* .toRenderInputsMatching(schema);
|
|
340
|
+
* });
|
|
341
|
+
* });
|
|
342
|
+
*/
|
|
343
|
+
function useConfigurationEditorMatchers() {
|
|
344
|
+
beforeEach(() => {
|
|
345
|
+
expect.extend({
|
|
346
|
+
toRenderInputsMatching
|
|
347
|
+
});
|
|
348
|
+
});
|
|
57
349
|
}
|
|
58
350
|
|
|
59
351
|
/**
|
|
@@ -68,10 +360,16 @@ function _objectSpread2(target) {
|
|
|
68
360
|
* @param {Object} [options.legalInfo] - imprint, copyright and privacy information of entry.
|
|
69
361
|
* @param {Object} [options.themeOptions] - Options set via theme registration.
|
|
70
362
|
* @param {Object} [options.themeAssets] - Paths to theme assets.
|
|
363
|
+
* @param {Object} [options.themeTranslations] - Pre-merged theme translations (e.g., scales).
|
|
71
364
|
* @param {Object} [options.additionalSeedData] - Seed data by name.
|
|
72
365
|
* @param {Array} [options.consentVendors] - Server rendered consent vendor data.
|
|
73
366
|
* @param {Object} [options.contentElementConsentVendors] - Consent vendor name by content element id.
|
|
74
367
|
* @param {Object} [options.entry] - attributes of entry.
|
|
368
|
+
* @param {Object} [options.fileModelTypes] - Mapping of file collection names to model types.
|
|
369
|
+
* Only needed to associate nested files with their parent. Collections of file types
|
|
370
|
+
* registered by plugins get a placeholder model type.
|
|
371
|
+
* @param {Object} [options.fileUrlTemplates] - Mapping of file collection names to mappings of
|
|
372
|
+
* url template names to url templates.
|
|
75
373
|
* @param {Array} [options.imageFiles] - Array of objects with image file attributes of entry.
|
|
76
374
|
* @param {Array} [options.videoFiles] - Array of objects with video file attributes of entry.
|
|
77
375
|
* @param {Array} [options.audioFiles] - Array of objects with audio file attributes of entry.
|
|
@@ -83,75 +381,89 @@ function _objectSpread2(target) {
|
|
|
83
381
|
* @param {Array} [options.widgets] - Array of objects with widget attributes of entry.
|
|
84
382
|
* @returns {Object} - Data that resembles seed generated by server side rendering.
|
|
85
383
|
*/
|
|
86
|
-
function normalizeSeed(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
384
|
+
function normalizeSeed({
|
|
385
|
+
imageFileUrlTemplates,
|
|
386
|
+
fileUrlTemplates,
|
|
387
|
+
fileModelTypes,
|
|
388
|
+
prettyUrl,
|
|
389
|
+
shareUrlTemplates,
|
|
390
|
+
defaultFileRights,
|
|
391
|
+
legalInfo,
|
|
392
|
+
themeOptions,
|
|
393
|
+
themeAssets,
|
|
394
|
+
themeTranslations,
|
|
395
|
+
entry,
|
|
396
|
+
imageFiles,
|
|
397
|
+
videoFiles,
|
|
398
|
+
audioFiles,
|
|
399
|
+
textTrackFiles,
|
|
400
|
+
storylines,
|
|
401
|
+
chapters,
|
|
402
|
+
sections,
|
|
403
|
+
contentElements,
|
|
404
|
+
widgets,
|
|
405
|
+
additionalSeedData,
|
|
406
|
+
consentVendors,
|
|
407
|
+
contentElementConsentVendors,
|
|
408
|
+
cutOff,
|
|
409
|
+
embed,
|
|
410
|
+
originUrl,
|
|
411
|
+
fileLicenses,
|
|
412
|
+
entryTranslations,
|
|
413
|
+
fileReferenceLocations,
|
|
414
|
+
...customFiles
|
|
415
|
+
} = {}) {
|
|
416
|
+
const customFileCollectionNames = [...new Set([...Object.keys(customFiles).filter(name => name.endsWith('Files')), ...Object.keys(fileModelTypes || {})])].filter(name => !builtInFileCollectionNames.includes(name));
|
|
417
|
+
const entries = entry ? [entry] : [{}];
|
|
418
|
+
const normalizedEntries = normalizeCollection(entries, {
|
|
115
419
|
locale: 'en',
|
|
116
420
|
configuration: {}
|
|
117
421
|
});
|
|
118
|
-
|
|
422
|
+
const normalizedContentElements = normalizeCollection(contentElements, {
|
|
119
423
|
typeName: 'textBlock',
|
|
120
424
|
configuration: {}
|
|
121
425
|
});
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
426
|
+
const normalizedSections = normalizeSections(sections, normalizedContentElements);
|
|
427
|
+
const normalizedChapters = normalizeChapters(chapters, normalizedSections);
|
|
428
|
+
const normalizedStorylines = normalizeStorylines(storylines, normalizedChapters);
|
|
125
429
|
return {
|
|
126
430
|
config: {
|
|
127
|
-
fileUrlTemplates:
|
|
128
|
-
imageFiles:
|
|
431
|
+
fileUrlTemplates: {
|
|
432
|
+
imageFiles: {
|
|
433
|
+
...imageFileUrlTemplates
|
|
434
|
+
},
|
|
129
435
|
videoFiles: {},
|
|
130
436
|
audioFiles: {},
|
|
131
|
-
textTrackFiles: {}
|
|
132
|
-
|
|
133
|
-
|
|
437
|
+
textTrackFiles: {},
|
|
438
|
+
...emptyUrlTemplates(customFileCollectionNames),
|
|
439
|
+
...fileUrlTemplates
|
|
440
|
+
},
|
|
441
|
+
fileModelTypes: {
|
|
134
442
|
audioFiles: 'Pageflow::AudioFile',
|
|
135
443
|
imageFiles: 'Pageflow::ImageFile',
|
|
136
444
|
textTrackFiles: 'Pageflow::TextTrackFile',
|
|
137
|
-
videoFiles: 'Pageflow::VideoFile'
|
|
138
|
-
|
|
445
|
+
videoFiles: 'Pageflow::VideoFile',
|
|
446
|
+
...placeholderModelTypes(customFileCollectionNames),
|
|
447
|
+
...fileModelTypes
|
|
448
|
+
},
|
|
139
449
|
prettyUrl: prettyUrl,
|
|
140
450
|
shareUrlTemplates: normalizeShareUrlTemplates(shareUrlTemplates),
|
|
141
451
|
defaultFileRights: defaultFileRights,
|
|
142
452
|
legalInfo: normalizeLegalInfo(legalInfo),
|
|
143
453
|
theme: normalizeTheme({
|
|
144
|
-
themeOptions
|
|
145
|
-
themeAssets
|
|
454
|
+
themeOptions,
|
|
455
|
+
themeAssets,
|
|
456
|
+
themeTranslations
|
|
146
457
|
}),
|
|
147
|
-
additionalSeedData: additionalSeedData || {
|
|
148
|
-
frontendVersion: 1
|
|
149
|
-
},
|
|
458
|
+
additionalSeedData: additionalSeedData || {},
|
|
150
459
|
consentVendors: consentVendors || [],
|
|
151
460
|
contentElementConsentVendors: contentElementConsentVendors || {},
|
|
152
|
-
cutOff
|
|
461
|
+
cutOff,
|
|
462
|
+
embed,
|
|
463
|
+
originUrl,
|
|
153
464
|
fileLicenses: fileLicenses || {},
|
|
154
|
-
entryTranslations: entryTranslations || []
|
|
465
|
+
entryTranslations: entryTranslations || [],
|
|
466
|
+
fileReferenceLocations: normalizeFileReferenceLocations(fileReferenceLocations)
|
|
155
467
|
},
|
|
156
468
|
collections: {
|
|
157
469
|
entries: normalizedEntries,
|
|
@@ -178,6 +490,7 @@ function normalizeSeed() {
|
|
|
178
490
|
parentFileType: null,
|
|
179
491
|
configuration: {}
|
|
180
492
|
}),
|
|
493
|
+
...customFileCollections(customFileCollectionNames, customFiles),
|
|
181
494
|
storylines: normalizedStorylines,
|
|
182
495
|
chapters: normalizedChapters,
|
|
183
496
|
sections: normalizedSections,
|
|
@@ -186,10 +499,25 @@ function normalizeSeed() {
|
|
|
186
499
|
}
|
|
187
500
|
};
|
|
188
501
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
502
|
+
const builtInFileCollectionNames = ['imageFiles', 'videoFiles', 'audioFiles', 'textTrackFiles'];
|
|
503
|
+
|
|
504
|
+
// Model types are only compared to associate nested files with their
|
|
505
|
+
// parent. Specs that seed nested files need to pass the real model type
|
|
506
|
+
// via the fileModelTypes option.
|
|
507
|
+
function placeholderModelTypes(collectionNames) {
|
|
508
|
+
return Object.fromEntries(collectionNames.map(name => [name, name.replace(/Files$/, 'File').replace(/^./, letter => letter.toUpperCase())]));
|
|
509
|
+
}
|
|
510
|
+
function emptyUrlTemplates(collectionNames) {
|
|
511
|
+
return Object.fromEntries(collectionNames.map(name => [name, {}]));
|
|
512
|
+
}
|
|
513
|
+
function customFileCollections(collectionNames, customFiles) {
|
|
514
|
+
return Object.fromEntries(collectionNames.map(name => [name, normalizeCollection(customFiles[name], {
|
|
515
|
+
isReady: true,
|
|
516
|
+
configuration: {}
|
|
517
|
+
})]));
|
|
518
|
+
}
|
|
519
|
+
function normalizeSections(sections = [], contentElements) {
|
|
520
|
+
const sectionDefaults = {
|
|
193
521
|
configuration: {
|
|
194
522
|
transition: 'scroll',
|
|
195
523
|
backdrop: {
|
|
@@ -198,46 +526,38 @@ function normalizeSections() {
|
|
|
198
526
|
}
|
|
199
527
|
};
|
|
200
528
|
if (contentElements.length && !sections.length) {
|
|
201
|
-
contentElements.forEach(
|
|
202
|
-
|
|
203
|
-
});
|
|
204
|
-
return [_objectSpread2({
|
|
529
|
+
contentElements.forEach(contentElement => contentElement.sectionId = 10);
|
|
530
|
+
return [{
|
|
205
531
|
id: 10,
|
|
206
|
-
permaId: 1
|
|
207
|
-
|
|
532
|
+
permaId: 1,
|
|
533
|
+
...sectionDefaults
|
|
534
|
+
}];
|
|
208
535
|
}
|
|
209
|
-
return normalizeCollection(sections, sectionDefaults).map(
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
}
|
|
215
|
-
});
|
|
536
|
+
return normalizeCollection(sections, sectionDefaults).map(section => ({
|
|
537
|
+
...section,
|
|
538
|
+
configuration: {
|
|
539
|
+
transition: sectionDefaults.configuration.transition,
|
|
540
|
+
...section.configuration
|
|
541
|
+
}
|
|
542
|
+
}));
|
|
216
543
|
}
|
|
217
|
-
function normalizeChapters() {
|
|
218
|
-
|
|
219
|
-
var sections = arguments.length > 1 ? arguments[1] : undefined;
|
|
220
|
-
var chapterDefaults = {
|
|
544
|
+
function normalizeChapters(chapters = [], sections) {
|
|
545
|
+
const chapterDefaults = {
|
|
221
546
|
configuration: {}
|
|
222
547
|
};
|
|
223
548
|
if (sections.length && !chapters.length) {
|
|
224
|
-
sections.forEach(
|
|
225
|
-
|
|
226
|
-
});
|
|
227
|
-
return [_objectSpread2({
|
|
549
|
+
sections.forEach(section => section.chapterId = 100);
|
|
550
|
+
return [{
|
|
228
551
|
id: 100,
|
|
229
|
-
permaId: 10
|
|
230
|
-
|
|
552
|
+
permaId: 10,
|
|
553
|
+
...chapterDefaults
|
|
554
|
+
}];
|
|
231
555
|
}
|
|
232
556
|
return normalizeCollection(chapters, chapterDefaults);
|
|
233
557
|
}
|
|
234
|
-
function normalizeStorylines() {
|
|
235
|
-
var storylines = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
236
|
-
var chapters = arguments.length > 1 ? arguments[1] : undefined;
|
|
558
|
+
function normalizeStorylines(storylines = [], chapters) {
|
|
237
559
|
if (!storylines.length) {
|
|
238
|
-
chapters.forEach(
|
|
239
|
-
return chapter.storylineId = 1000;
|
|
240
|
-
});
|
|
560
|
+
chapters.forEach(chapter => chapter.storylineId = 1000);
|
|
241
561
|
return [{
|
|
242
562
|
id: 1000,
|
|
243
563
|
permaId: 100,
|
|
@@ -285,132 +605,75 @@ function normalizeLegalInfo(legalInfo) {
|
|
|
285
605
|
};
|
|
286
606
|
}
|
|
287
607
|
}
|
|
288
|
-
function normalizeTheme(
|
|
289
|
-
|
|
290
|
-
|
|
608
|
+
function normalizeTheme({
|
|
609
|
+
themeAssets,
|
|
610
|
+
themeOptions,
|
|
611
|
+
themeTranslations
|
|
612
|
+
}) {
|
|
291
613
|
return {
|
|
292
|
-
assets:
|
|
293
|
-
icons: {}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
614
|
+
assets: {
|
|
615
|
+
icons: {},
|
|
616
|
+
...themeAssets
|
|
617
|
+
},
|
|
618
|
+
options: {
|
|
619
|
+
colors: {},
|
|
620
|
+
...themeOptions
|
|
621
|
+
},
|
|
622
|
+
translations: themeTranslations
|
|
298
623
|
};
|
|
299
624
|
}
|
|
300
|
-
function normalizeWidgets() {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
}, widget);
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
function normalizeCollection() {
|
|
310
|
-
var collection = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
311
|
-
var defaults = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
312
|
-
return collection.map(function (item, index) {
|
|
313
|
-
return _objectSpread2(_objectSpread2({
|
|
314
|
-
id: index + 1,
|
|
315
|
-
permaId: index + 1
|
|
316
|
-
}, defaults), item);
|
|
317
|
-
});
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
function _objectWithoutPropertiesLoose(source, excluded) {
|
|
321
|
-
if (source == null) return {};
|
|
322
|
-
var target = {};
|
|
323
|
-
var sourceKeys = Object.keys(source);
|
|
324
|
-
var key, i;
|
|
325
|
-
|
|
326
|
-
for (i = 0; i < sourceKeys.length; i++) {
|
|
327
|
-
key = sourceKeys[i];
|
|
328
|
-
if (excluded.indexOf(key) >= 0) continue;
|
|
329
|
-
target[key] = source[key];
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
return target;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
function _objectWithoutProperties(source, excluded) {
|
|
336
|
-
if (source == null) return {};
|
|
337
|
-
var target = _objectWithoutPropertiesLoose(source, excluded);
|
|
338
|
-
var key, i;
|
|
339
|
-
|
|
340
|
-
if (Object.getOwnPropertySymbols) {
|
|
341
|
-
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
|
|
342
|
-
|
|
343
|
-
for (i = 0; i < sourceSymbolKeys.length; i++) {
|
|
344
|
-
key = sourceSymbolKeys[i];
|
|
345
|
-
if (excluded.indexOf(key) >= 0) continue;
|
|
346
|
-
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
|
347
|
-
target[key] = source[key];
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
return target;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
function _arrayWithHoles(arr) {
|
|
355
|
-
if (Array.isArray(arr)) return arr;
|
|
625
|
+
function normalizeWidgets(widgets = []) {
|
|
626
|
+
return widgets.map(widget => ({
|
|
627
|
+
permaId: widget.role,
|
|
628
|
+
configuration: {},
|
|
629
|
+
...widget
|
|
630
|
+
}));
|
|
356
631
|
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
try {
|
|
366
|
-
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
|
|
367
|
-
_arr.push(_s.value);
|
|
368
|
-
|
|
369
|
-
if (i && _arr.length === i) break;
|
|
370
|
-
}
|
|
371
|
-
} catch (err) {
|
|
372
|
-
_d = true;
|
|
373
|
-
_e = err;
|
|
374
|
-
} finally {
|
|
375
|
-
try {
|
|
376
|
-
if (!_n && _i["return"] != null) _i["return"]();
|
|
377
|
-
} finally {
|
|
378
|
-
if (_d) throw _e;
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
return _arr;
|
|
632
|
+
function normalizeCollection(collection = [], defaults = {}) {
|
|
633
|
+
return collection.map((item, index) => ({
|
|
634
|
+
id: index + 1,
|
|
635
|
+
permaId: index + 1,
|
|
636
|
+
...defaults,
|
|
637
|
+
...item
|
|
638
|
+
}));
|
|
383
639
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
return arr2;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
function _unsupportedIterableToArray(o, minLen) {
|
|
396
|
-
if (!o) return;
|
|
397
|
-
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
|
|
398
|
-
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
399
|
-
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
400
|
-
if (n === "Map" || n === "Set") return Array.from(n);
|
|
401
|
-
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
function _nonIterableRest() {
|
|
405
|
-
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
640
|
+
function normalizeFileReferenceLocations(fileReferenceLocations) {
|
|
641
|
+
return {
|
|
642
|
+
contentElements: {},
|
|
643
|
+
sections: [],
|
|
644
|
+
entry: [],
|
|
645
|
+
...fileReferenceLocations
|
|
646
|
+
};
|
|
406
647
|
}
|
|
407
648
|
|
|
408
|
-
|
|
409
|
-
|
|
649
|
+
/**
|
|
650
|
+
* Render the configuration editor of a content element. Content element
|
|
651
|
+
* packs can use this to assert how their editor integration behaves.
|
|
652
|
+
*
|
|
653
|
+
* @param {Object} options
|
|
654
|
+
* @param {Object} options.entry - Entry the content element belongs to.
|
|
655
|
+
* @param {Object} options.contentElement - Content element to configure.
|
|
656
|
+
*
|
|
657
|
+
* @example
|
|
658
|
+
* import {renderContentElementConfigurationEditor} from 'pageflow-scrolled/testHelpers';
|
|
659
|
+
*/
|
|
660
|
+
function renderContentElementConfigurationEditor({
|
|
661
|
+
entry,
|
|
662
|
+
contentElement
|
|
663
|
+
}) {
|
|
664
|
+
// Normally contributed by the text inline file rights widget type
|
|
665
|
+
// once the widgets of the entry have been set up.
|
|
666
|
+
ConfigurationEditorTabView.groups.define('ContentElementInlineFileRightsSettings', () => {});
|
|
667
|
+
const view = new EditContentElementView({
|
|
668
|
+
model: contentElement,
|
|
669
|
+
editor,
|
|
670
|
+
entry
|
|
671
|
+
});
|
|
672
|
+
renderBackboneView(view);
|
|
673
|
+
return ConfigurationEditor.find(view);
|
|
410
674
|
}
|
|
411
675
|
|
|
412
|
-
var
|
|
413
|
-
_excluded2 = ["seed", "setup", "wrapper"];
|
|
676
|
+
var _jsxFileName = "/home/tfischbach/code/pageflow/entry_types/scrolled/package/src/testHelpers/rendering.js";
|
|
414
677
|
|
|
415
678
|
/**
|
|
416
679
|
* Render a component that depends on entry state. Accepts all options
|
|
@@ -448,17 +711,18 @@ var _excluded = ["seed", "setup", "wrapper", "consent"],
|
|
|
448
711
|
* function. The normalized seed constructed from the `seed` option
|
|
449
712
|
* is passed as a second parameter.
|
|
450
713
|
*/
|
|
451
|
-
function renderInEntry(ui
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
options =
|
|
460
|
-
wrapper: createWrapper(seed, setup, wrapper, consent)
|
|
461
|
-
|
|
714
|
+
function renderInEntry(ui, {
|
|
715
|
+
seed,
|
|
716
|
+
setup,
|
|
717
|
+
wrapper,
|
|
718
|
+
consent = Consent.create(),
|
|
719
|
+
phonePlatform,
|
|
720
|
+
...options
|
|
721
|
+
} = {}) {
|
|
722
|
+
options = {
|
|
723
|
+
wrapper: createWrapper(seed, setup, wrapper, consent, phonePlatform),
|
|
724
|
+
...options
|
|
725
|
+
};
|
|
462
726
|
if (typeof ui === 'function') {
|
|
463
727
|
// Evaluate `ui` inside a React component to allow using hooks in
|
|
464
728
|
// the test. We also could have used `ui` as a React component
|
|
@@ -473,20 +737,34 @@ function renderInEntry(ui) {
|
|
|
473
737
|
// render call and mount a new one. We therefore define a single
|
|
474
738
|
// component that is reused across rerenders to ensure
|
|
475
739
|
// `MyComponent` stays mounted and just receives new props.
|
|
476
|
-
|
|
477
|
-
|
|
740
|
+
function HooksWrapper({
|
|
741
|
+
ui
|
|
742
|
+
}) {
|
|
478
743
|
return ui();
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
ui: ui
|
|
744
|
+
}
|
|
745
|
+
const result = render( /*#__PURE__*/React.createElement(HooksWrapper, {
|
|
746
|
+
ui: ui,
|
|
747
|
+
__self: this,
|
|
748
|
+
__source: {
|
|
749
|
+
fileName: _jsxFileName,
|
|
750
|
+
lineNumber: 71,
|
|
751
|
+
columnNumber: 27
|
|
752
|
+
}
|
|
482
753
|
}), options);
|
|
483
|
-
return
|
|
484
|
-
|
|
754
|
+
return {
|
|
755
|
+
...result,
|
|
756
|
+
rerender(ui) {
|
|
485
757
|
result.rerender( /*#__PURE__*/React.createElement(HooksWrapper, {
|
|
486
|
-
ui: ui
|
|
758
|
+
ui: ui,
|
|
759
|
+
__self: this,
|
|
760
|
+
__source: {
|
|
761
|
+
fileName: _jsxFileName,
|
|
762
|
+
lineNumber: 76,
|
|
763
|
+
columnNumber: 25
|
|
764
|
+
}
|
|
487
765
|
}));
|
|
488
766
|
}
|
|
489
|
-
}
|
|
767
|
+
};
|
|
490
768
|
} else {
|
|
491
769
|
return render(ui, options);
|
|
492
770
|
}
|
|
@@ -505,39 +783,75 @@ function renderInEntry(ui) {
|
|
|
505
783
|
* @param {Object} [options.seed] - Seed data for entry state. Passed through {@link normalizeSeed}.
|
|
506
784
|
* @param {Function} [options.setup] - See {@link renderInEntry}.
|
|
507
785
|
*/
|
|
508
|
-
function renderHookInEntry(callback
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
786
|
+
function renderHookInEntry(callback, {
|
|
787
|
+
seed,
|
|
788
|
+
setup,
|
|
789
|
+
wrapper,
|
|
790
|
+
phonePlatform,
|
|
791
|
+
...options
|
|
792
|
+
} = {}) {
|
|
793
|
+
return renderHook(callback, {
|
|
794
|
+
wrapper: createWrapper(seed, setup, wrapper, undefined, phonePlatform),
|
|
795
|
+
...options
|
|
796
|
+
});
|
|
797
|
+
}
|
|
798
|
+
function createWrapper(seed, setup, originalWrapper, consent, phonePlatform) {
|
|
799
|
+
const normalizedSeed = normalizeSeed(seed);
|
|
800
|
+
const OriginalWrapper = originalWrapper || function Noop({
|
|
801
|
+
children
|
|
802
|
+
}) {
|
|
522
803
|
return children;
|
|
523
804
|
};
|
|
524
|
-
return function Wrapper(
|
|
525
|
-
|
|
805
|
+
return function Wrapper({
|
|
806
|
+
children
|
|
807
|
+
}) {
|
|
808
|
+
let content = /*#__PURE__*/React.createElement(Dispatcher, {
|
|
809
|
+
callback: setup,
|
|
810
|
+
seed: normalizedSeed,
|
|
811
|
+
__self: this,
|
|
812
|
+
__source: {
|
|
813
|
+
fileName: _jsxFileName,
|
|
814
|
+
lineNumber: 112,
|
|
815
|
+
columnNumber: 7
|
|
816
|
+
}
|
|
817
|
+
}, /*#__PURE__*/React.createElement(OriginalWrapper, {
|
|
818
|
+
__self: this,
|
|
819
|
+
__source: {
|
|
820
|
+
fileName: _jsxFileName,
|
|
821
|
+
lineNumber: 113,
|
|
822
|
+
columnNumber: 9
|
|
823
|
+
}
|
|
824
|
+
}, children));
|
|
825
|
+
if (phonePlatform !== undefined) {
|
|
826
|
+
content = /*#__PURE__*/React.createElement(PhonePlatformContext.Provider, {
|
|
827
|
+
value: phonePlatform,
|
|
828
|
+
__self: this,
|
|
829
|
+
__source: {
|
|
830
|
+
fileName: _jsxFileName,
|
|
831
|
+
lineNumber: 121,
|
|
832
|
+
columnNumber: 9
|
|
833
|
+
}
|
|
834
|
+
}, content);
|
|
835
|
+
}
|
|
526
836
|
return /*#__PURE__*/React.createElement(RootProviders, {
|
|
527
837
|
seed: normalizedSeed,
|
|
528
|
-
consent: consent
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
838
|
+
consent: consent,
|
|
839
|
+
__self: this,
|
|
840
|
+
__source: {
|
|
841
|
+
fileName: _jsxFileName,
|
|
842
|
+
lineNumber: 128,
|
|
843
|
+
columnNumber: 7
|
|
844
|
+
}
|
|
845
|
+
}, content);
|
|
533
846
|
};
|
|
534
847
|
}
|
|
535
|
-
function Dispatcher(
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
848
|
+
function Dispatcher({
|
|
849
|
+
children,
|
|
850
|
+
seed,
|
|
851
|
+
callback
|
|
852
|
+
}) {
|
|
853
|
+
const dispatch = useEntryStateDispatch();
|
|
854
|
+
useEffect(() => {
|
|
541
855
|
if (callback) {
|
|
542
856
|
callback(dispatch, seed);
|
|
543
857
|
}
|
|
@@ -545,7 +859,7 @@ function Dispatcher(_ref6) {
|
|
|
545
859
|
return children;
|
|
546
860
|
}
|
|
547
861
|
|
|
548
|
-
var
|
|
862
|
+
var _jsxFileName$1 = "/home/tfischbach/code/pageflow/entry_types/scrolled/package/src/testHelpers/scrollPositionLifecycle.js";
|
|
549
863
|
|
|
550
864
|
/**
|
|
551
865
|
* Takes the same options as {@link renderInEntry} but returns
|
|
@@ -557,37 +871,38 @@ var _excluded$1 = ["lifecycleContext", "wrapper"];
|
|
|
557
871
|
* // => Turns `shouldLoad` and `shouldPrepare` to true
|
|
558
872
|
*/
|
|
559
873
|
function renderInEntryWithContentElementLifecycle(ui, options) {
|
|
560
|
-
return renderInEntryWithScrollPositionLifecycle(ui,
|
|
561
|
-
lifecycleContext: ContentElementLifecycleContext
|
|
562
|
-
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
874
|
+
return renderInEntryWithScrollPositionLifecycle(ui, {
|
|
875
|
+
lifecycleContext: ContentElementLifecycleContext,
|
|
876
|
+
...options
|
|
877
|
+
});
|
|
878
|
+
}
|
|
879
|
+
function renderInEntryWithScrollPositionLifecycle(ui, {
|
|
880
|
+
lifecycleContext,
|
|
881
|
+
wrapper,
|
|
882
|
+
...options
|
|
883
|
+
} = {}) {
|
|
884
|
+
const emitter = createEmitter();
|
|
885
|
+
return withSimulateScrollPositionHelper(emitter, renderInEntry(ui, {
|
|
886
|
+
wrapper: createScrollPositionProvider(lifecycleContext, emitter, wrapper),
|
|
887
|
+
...options
|
|
888
|
+
}));
|
|
573
889
|
}
|
|
574
890
|
function createScrollPositionProvider(Context, emitter, originalWrapper) {
|
|
575
|
-
|
|
576
|
-
|
|
891
|
+
const OriginalWrapper = originalWrapper || function Noop({
|
|
892
|
+
children
|
|
893
|
+
}) {
|
|
577
894
|
return children;
|
|
578
895
|
};
|
|
579
|
-
return function ScrollPositionProvider(
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
setValue = _useState2[1];
|
|
590
|
-
useEffect(function () {
|
|
896
|
+
return function ScrollPositionProvider({
|
|
897
|
+
children
|
|
898
|
+
}) {
|
|
899
|
+
const [value, setValue] = useState({
|
|
900
|
+
shouldLoad: false,
|
|
901
|
+
shouldPrepare: false,
|
|
902
|
+
isVisible: false,
|
|
903
|
+
isActive: false
|
|
904
|
+
});
|
|
905
|
+
useEffect(() => {
|
|
591
906
|
function handle(scrollPosition) {
|
|
592
907
|
switch (scrollPosition) {
|
|
593
908
|
case 'near viewport':
|
|
@@ -623,89 +938,251 @@ function createScrollPositionProvider(Context, emitter, originalWrapper) {
|
|
|
623
938
|
}
|
|
624
939
|
}
|
|
625
940
|
emitter.on('scroll', handle);
|
|
626
|
-
return
|
|
627
|
-
return emitter.off('scroll', handle);
|
|
628
|
-
};
|
|
941
|
+
return () => emitter.off('scroll', handle);
|
|
629
942
|
});
|
|
630
|
-
return /*#__PURE__*/React.createElement(OriginalWrapper,
|
|
631
|
-
|
|
943
|
+
return /*#__PURE__*/React.createElement(OriginalWrapper, {
|
|
944
|
+
__self: this,
|
|
945
|
+
__source: {
|
|
946
|
+
fileName: _jsxFileName$1,
|
|
947
|
+
lineNumber: 69,
|
|
948
|
+
columnNumber: 7
|
|
949
|
+
}
|
|
950
|
+
}, /*#__PURE__*/React.createElement(Context.Provider, {
|
|
951
|
+
value: value,
|
|
952
|
+
__self: this,
|
|
953
|
+
__source: {
|
|
954
|
+
fileName: _jsxFileName$1,
|
|
955
|
+
lineNumber: 70,
|
|
956
|
+
columnNumber: 9
|
|
957
|
+
}
|
|
632
958
|
}, children));
|
|
633
959
|
};
|
|
634
960
|
}
|
|
635
|
-
|
|
961
|
+
const allowedScrollPositions = ['outside viewport', 'near viewport', 'in viewport', 'center of viewport'];
|
|
636
962
|
function withSimulateScrollPositionHelper(emitter, result) {
|
|
637
|
-
return
|
|
638
|
-
|
|
963
|
+
return {
|
|
964
|
+
...result,
|
|
965
|
+
simulateScrollPosition(scrollPosition) {
|
|
639
966
|
if (!allowedScrollPositions.includes(scrollPosition)) {
|
|
640
|
-
throw new Error(
|
|
967
|
+
throw new Error(`Invalid scrollPosition '${scrollPosition}'. ` + `Allowed values: ${allowedScrollPositions.join(', ')}`);
|
|
641
968
|
}
|
|
642
|
-
act(
|
|
969
|
+
act(() => {
|
|
643
970
|
emitter.trigger('scroll', scrollPosition);
|
|
644
971
|
});
|
|
645
972
|
}
|
|
646
|
-
}
|
|
973
|
+
};
|
|
647
974
|
}
|
|
648
975
|
function createEmitter() {
|
|
649
|
-
return
|
|
976
|
+
return {
|
|
977
|
+
...BackboneEvents
|
|
978
|
+
};
|
|
650
979
|
}
|
|
651
980
|
|
|
652
|
-
var
|
|
981
|
+
var _jsxFileName$2 = "/home/tfischbach/code/pageflow/entry_types/scrolled/package/src/testHelpers/renderInContentElement.js";
|
|
653
982
|
|
|
654
983
|
/**
|
|
655
984
|
* Provide context as if component was rendered inside of a content element.
|
|
656
985
|
*
|
|
657
|
-
* Returns
|
|
658
|
-
* lifecycle
|
|
986
|
+
* Returns additional functions to control content element scroll
|
|
987
|
+
* lifecycle, view timeline progress, editor commands, and storyline
|
|
988
|
+
* mode: `simulateScrollPosition`, `simulateScrollProgress`,
|
|
989
|
+
* `triggerEditorCommand`, and `simulateStorylineMode`.
|
|
990
|
+
*
|
|
991
|
+
* `simulateScrollProgress` passes the given progress to all
|
|
992
|
+
* `useContentElementViewTimelineProgress` callbacks, no matter which
|
|
993
|
+
* range they observe. Pass a `range` option to only invoke callbacks
|
|
994
|
+
* observing that range.
|
|
659
995
|
*
|
|
660
996
|
* @param {Function} callback - React component or function returning a React component.
|
|
661
997
|
* @param {Object} [options] - Supports all options supported by {@link `renderInEntry`}.
|
|
662
|
-
* @param {Object} [options.
|
|
998
|
+
* @param {boolean|Object} [options.inlineEditing] -
|
|
999
|
+
* Opt the content element into an inline-editing context (matching
|
|
1000
|
+
* what's available when inline editing is loaded in production).
|
|
1001
|
+
* Pass `true` for editable defaults, or an object to override:
|
|
1002
|
+
* `{isEditable, isSelected, transientState}`. `transientState` is
|
|
1003
|
+
* installed as the `setTransientState` function on the editor state
|
|
1004
|
+
* context — pass a jest spy to assert on it. Omitting the option
|
|
1005
|
+
* gives the frontend-mode defaults (`isEditable: false, isSelected:
|
|
1006
|
+
* false, setTransientState: noop`) without wrapping any
|
|
1007
|
+
* inline-editing-only providers (DndProvider, editor command
|
|
1008
|
+
* emitter).
|
|
663
1009
|
* @param {Object} [options.phonePlatform] - Fake result of `usePhonePlatform`.
|
|
1010
|
+
* @param {Object} [options.consentState] - Pass 'undecided' to render third party consent opt in.
|
|
664
1011
|
*
|
|
665
1012
|
* @example
|
|
666
1013
|
*
|
|
667
|
-
* const {getByRole, simulateScrollPosition, triggerEditorCommand} =
|
|
1014
|
+
* const {getByRole, simulateScrollPosition, triggerEditorCommand, simulateStorylineMode} =
|
|
668
1015
|
* renderInContentElement(<MyContentElement />, {
|
|
669
|
-
* seed: {...}
|
|
1016
|
+
* seed: {...},
|
|
1017
|
+
* inlineEditing: {isSelected: true}
|
|
670
1018
|
* });
|
|
671
1019
|
* simulateScrollPosition('near viewport');
|
|
1020
|
+
* simulateScrollProgress(0.5);
|
|
1021
|
+
* simulateScrollProgress(0.5, {range: 'pinned'});
|
|
672
1022
|
* triggerEditorCommand({type: 'HIGHLIGHT'});
|
|
1023
|
+
* simulateStorylineMode('background');
|
|
673
1024
|
*/
|
|
674
|
-
function renderInContentElement(ui
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
1025
|
+
function renderInContentElement(ui, {
|
|
1026
|
+
inlineEditing,
|
|
1027
|
+
phonePlatform = false,
|
|
1028
|
+
wrapper: OriginalWrapper,
|
|
1029
|
+
consentState = 'accepted',
|
|
1030
|
+
seed,
|
|
1031
|
+
...options
|
|
1032
|
+
} = {}) {
|
|
1033
|
+
const emitter = Object.assign({}, BackboneEvents);
|
|
1034
|
+
const storylineEmitter = Object.assign({}, BackboneEvents);
|
|
1035
|
+
const viewTimelineEmitter = Object.assign({}, BackboneEvents);
|
|
1036
|
+
const viewTimeline = {
|
|
1037
|
+
subscribe(range, callback) {
|
|
1038
|
+
function handleProgress(progress, options) {
|
|
1039
|
+
if (!options.range || options.range === range) {
|
|
1040
|
+
callback(progress);
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
viewTimelineEmitter.on('progress', handleProgress);
|
|
1044
|
+
return () => viewTimelineEmitter.off('progress', handleProgress);
|
|
1045
|
+
}
|
|
1046
|
+
};
|
|
1047
|
+
const inlineEditingConfig = resolveInlineEditing(inlineEditing);
|
|
1048
|
+
function Wrapper({
|
|
1049
|
+
children
|
|
1050
|
+
}) {
|
|
1051
|
+
const [storylineMode, setStorylineMode] = useState('active');
|
|
1052
|
+
useEffect(() => {
|
|
1053
|
+
storylineEmitter.on('storylineMode', setStorylineMode);
|
|
1054
|
+
return () => storylineEmitter.off('storylineMode', setStorylineMode);
|
|
1055
|
+
}, []);
|
|
1056
|
+
let tree = OriginalWrapper ? /*#__PURE__*/React.createElement(OriginalWrapper, {
|
|
1057
|
+
children: children,
|
|
1058
|
+
__self: this,
|
|
1059
|
+
__source: {
|
|
1060
|
+
fileName: _jsxFileName$2,
|
|
1061
|
+
lineNumber: 95,
|
|
1062
|
+
columnNumber: 34
|
|
1063
|
+
}
|
|
1064
|
+
}) : children;
|
|
1065
|
+
if (inlineEditingConfig) {
|
|
1066
|
+
tree = /*#__PURE__*/React.createElement(DndProvider, {
|
|
1067
|
+
backend: HTML5Backend,
|
|
1068
|
+
__self: this,
|
|
1069
|
+
__source: {
|
|
1070
|
+
fileName: _jsxFileName$2,
|
|
1071
|
+
lineNumber: 99,
|
|
1072
|
+
columnNumber: 9
|
|
1073
|
+
}
|
|
1074
|
+
}, /*#__PURE__*/React.createElement(ContentElementEditorCommandEmitterContext.Provider, {
|
|
1075
|
+
value: emitter,
|
|
1076
|
+
__self: this,
|
|
1077
|
+
__source: {
|
|
1078
|
+
fileName: _jsxFileName$2,
|
|
1079
|
+
lineNumber: 100,
|
|
1080
|
+
columnNumber: 11
|
|
1081
|
+
}
|
|
1082
|
+
}, /*#__PURE__*/React.createElement(ContentElementEditorStateContext.Provider, {
|
|
1083
|
+
value: inlineEditingConfig,
|
|
1084
|
+
__self: this,
|
|
1085
|
+
__source: {
|
|
1086
|
+
fileName: _jsxFileName$2,
|
|
1087
|
+
lineNumber: 101,
|
|
1088
|
+
columnNumber: 13
|
|
1089
|
+
}
|
|
1090
|
+
}, tree)));
|
|
1091
|
+
}
|
|
1092
|
+
return /*#__PURE__*/React.createElement(MainStorylineActivity, {
|
|
1093
|
+
activeExcursion: storylineMode !== 'active' ? {
|
|
1094
|
+
id: 1
|
|
1095
|
+
} : null,
|
|
1096
|
+
__self: this,
|
|
1097
|
+
__source: {
|
|
1098
|
+
fileName: _jsxFileName$2,
|
|
1099
|
+
lineNumber: 110,
|
|
1100
|
+
columnNumber: 7
|
|
1101
|
+
}
|
|
689
1102
|
}, /*#__PURE__*/React.createElement(ContentElementAttributesProvider, {
|
|
690
|
-
id: 42
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
}
|
|
1103
|
+
id: 42,
|
|
1104
|
+
__self: this,
|
|
1105
|
+
__source: {
|
|
1106
|
+
fileName: _jsxFileName$2,
|
|
1107
|
+
lineNumber: 111,
|
|
1108
|
+
columnNumber: 9
|
|
1109
|
+
}
|
|
1110
|
+
}, /*#__PURE__*/React.createElement(ContentElementViewTimelineContext.Provider, {
|
|
1111
|
+
value: viewTimeline,
|
|
1112
|
+
__self: this,
|
|
1113
|
+
__source: {
|
|
1114
|
+
fileName: _jsxFileName$2,
|
|
1115
|
+
lineNumber: 112,
|
|
1116
|
+
columnNumber: 11
|
|
1117
|
+
}
|
|
1118
|
+
}, tree)));
|
|
698
1119
|
}
|
|
699
|
-
return
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
1120
|
+
return {
|
|
1121
|
+
...renderInEntryWithScrollPositionLifecycle(ui, {
|
|
1122
|
+
lifecycleContext: ContentElementLifecycleContext,
|
|
1123
|
+
wrapper: Wrapper,
|
|
1124
|
+
consent: createConsent(consentState),
|
|
1125
|
+
phonePlatform,
|
|
1126
|
+
seed: {
|
|
1127
|
+
...consentSeed,
|
|
1128
|
+
...seed
|
|
1129
|
+
},
|
|
1130
|
+
...options
|
|
1131
|
+
}),
|
|
1132
|
+
triggerEditorCommand(command) {
|
|
1133
|
+
act(() => {
|
|
1134
|
+
emitter.trigger(`command:42`, command);
|
|
1135
|
+
});
|
|
1136
|
+
},
|
|
1137
|
+
simulateStorylineMode(mode) {
|
|
1138
|
+
act(() => {
|
|
1139
|
+
storylineEmitter.trigger('storylineMode', mode);
|
|
1140
|
+
});
|
|
1141
|
+
},
|
|
1142
|
+
simulateScrollProgress(progress, {
|
|
1143
|
+
range
|
|
1144
|
+
} = {}) {
|
|
1145
|
+
act(() => {
|
|
1146
|
+
viewTimelineEmitter.trigger('progress', progress, {
|
|
1147
|
+
range
|
|
1148
|
+
});
|
|
706
1149
|
});
|
|
707
1150
|
}
|
|
1151
|
+
};
|
|
1152
|
+
}
|
|
1153
|
+
function resolveInlineEditing(option) {
|
|
1154
|
+
var _overrides$isEditable, _overrides$isSelected, _overrides$transientS;
|
|
1155
|
+
if (!option) return null;
|
|
1156
|
+
const overrides = option === true ? {} : option;
|
|
1157
|
+
return {
|
|
1158
|
+
isEditable: (_overrides$isEditable = overrides.isEditable) !== null && _overrides$isEditable !== void 0 ? _overrides$isEditable : true,
|
|
1159
|
+
isSelected: (_overrides$isSelected = overrides.isSelected) !== null && _overrides$isSelected !== void 0 ? _overrides$isSelected : false,
|
|
1160
|
+
setTransientState: (_overrides$transientS = overrides.transientState) !== null && _overrides$transientS !== void 0 ? _overrides$transientS : () => {},
|
|
1161
|
+
select: () => {},
|
|
1162
|
+
selectNewThread: () => {}
|
|
1163
|
+
};
|
|
1164
|
+
}
|
|
1165
|
+
function createConsent(consentState) {
|
|
1166
|
+
const consent = Consent.create();
|
|
1167
|
+
consent.registerVendor('testVendor', {
|
|
1168
|
+
displayName: 'Test Vendor',
|
|
1169
|
+
description: 'Test embeds',
|
|
1170
|
+
paradigm: 'lazy opt-in'
|
|
708
1171
|
});
|
|
1172
|
+
consent.closeVendorRegistration();
|
|
1173
|
+
if (consentState === 'accepted') {
|
|
1174
|
+
consent.accept('testVendor');
|
|
1175
|
+
}
|
|
1176
|
+
return consent;
|
|
709
1177
|
}
|
|
1178
|
+
const consentSeed = {
|
|
1179
|
+
consentVendors: [{
|
|
1180
|
+
name: 'testVendor',
|
|
1181
|
+
paradigm: 'lazy opt-in'
|
|
1182
|
+
}],
|
|
1183
|
+
contentElementConsentVendors: {
|
|
1184
|
+
42: 'testVendor'
|
|
1185
|
+
}
|
|
1186
|
+
};
|
|
710
1187
|
|
|
711
|
-
export { normalizeSeed, renderHookInEntry, renderInContentElement, renderInEntry, renderInEntryWithContentElementLifecycle, renderInEntryWithScrollPositionLifecycle };
|
|
1188
|
+
export { normalizeSeed, renderContentElementConfigurationEditor, renderHookInEntry, renderInContentElement, renderInEntry, renderInEntryWithContentElementLifecycle, renderInEntryWithScrollPositionLifecycle, useConfigurationEditorMatchers, useContentElementMatchers };
|