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.
Files changed (302) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +319 -345
  3. data/README.md +3 -4
  4. data/admins/pageflow/accounts.rb +6 -6
  5. data/admins/pageflow/entry.rb +10 -8
  6. data/admins/pageflow/membership.rb +11 -11
  7. data/admins/pageflow/translations.rb +5 -5
  8. data/app/assets/images/pageflow/admin/icons/comment.svg +1 -0
  9. data/app/assets/javascripts/pageflow/dist/ui.js +1350 -630
  10. data/app/assets/javascripts/pageflow/editor/vendor.js +0 -1
  11. data/app/assets/javascripts/pageflow/ui.js +0 -1
  12. data/app/assets/stylesheets/pageflow/admin/entry_comments_indicator.scss +45 -0
  13. data/app/assets/stylesheets/pageflow/admin/permalink_input.scss +8 -1
  14. data/app/assets/stylesheets/pageflow/admin.scss +1 -0
  15. data/app/assets/stylesheets/pageflow/animations/spin.scss +9 -0
  16. data/app/assets/stylesheets/pageflow/animations.scss +1 -0
  17. data/app/assets/stylesheets/pageflow/editor/background_positioning.scss +21 -5
  18. data/app/assets/stylesheets/pageflow/editor/base.scss +9 -1
  19. data/app/assets/stylesheets/pageflow/editor/drop_down_button.scss +13 -1
  20. data/app/assets/stylesheets/pageflow/editor/edit_configuration_view.scss +5 -0
  21. data/app/assets/stylesheets/pageflow/editor/file_folders.scss +127 -0
  22. data/app/assets/stylesheets/pageflow/editor/file_meta_data.scss +0 -1
  23. data/app/assets/stylesheets/pageflow/editor/file_meta_data_overlay.scss +45 -0
  24. data/app/assets/stylesheets/pageflow/editor/file_preview.scss +138 -0
  25. data/app/assets/stylesheets/pageflow/editor/file_references.scss +68 -0
  26. data/app/assets/stylesheets/pageflow/editor/file_settings_dialog.scss +1 -1
  27. data/app/assets/stylesheets/pageflow/editor/file_stage_icons.scss +17 -0
  28. data/app/assets/stylesheets/pageflow/editor/file_stages.scss +25 -32
  29. data/app/assets/stylesheets/pageflow/editor/file_thumbnails.scss +31 -48
  30. data/app/assets/stylesheets/pageflow/editor/file_type_pills.scss +73 -0
  31. data/app/assets/stylesheets/pageflow/editor/files.scss +230 -50
  32. data/app/assets/stylesheets/pageflow/editor/filtered_files.scss +142 -14
  33. data/app/assets/stylesheets/pageflow/editor/folder_breadcrumb.scss +40 -0
  34. data/app/assets/stylesheets/pageflow/editor/info_box.scss +12 -0
  35. data/app/assets/stylesheets/pageflow/editor/inputs/edit_defaults_button.scss +15 -0
  36. data/app/assets/stylesheets/pageflow/editor/inputs.scss +1 -0
  37. data/app/assets/stylesheets/pageflow/editor/list.scss +88 -38
  38. data/app/assets/stylesheets/pageflow/editor/manage_files.scss +9 -0
  39. data/app/assets/stylesheets/pageflow/editor/menu.scss +14 -0
  40. data/app/assets/stylesheets/pageflow/editor/move_to_folder_dialog.scss +83 -0
  41. data/app/assets/stylesheets/pageflow/mixins/pageflow.scss +9 -5
  42. data/app/assets/stylesheets/pageflow/ui/color_picker.scss +230 -0
  43. data/app/assets/stylesheets/pageflow/ui/forms.scss +34 -4
  44. data/app/assets/stylesheets/pageflow/ui/functions.scss +12 -2
  45. data/app/assets/stylesheets/pageflow/ui/input/color_input.scss +9 -16
  46. data/app/assets/stylesheets/pageflow/ui/input/text_area_input.scss +15 -0
  47. data/app/assets/stylesheets/pageflow/ui/overrides.scss +8 -0
  48. data/app/assets/stylesheets/pageflow/ui/properties.scss +29 -0
  49. data/app/assets/stylesheets/pageflow/ui/tabs_view.scss +8 -3
  50. data/app/assets/stylesheets/pageflow/ui.scss +4 -2
  51. data/app/controllers/pageflow/editor/entries_controller.rb +1 -0
  52. data/app/controllers/pageflow/editor/file_folders_controller.rb +80 -0
  53. data/app/controllers/pageflow/editor/file_import_controller.rb +1 -0
  54. data/app/controllers/pageflow/editor/files_controller.rb +15 -6
  55. data/app/controllers/pageflow/editor/oembeds_controller.rb +21 -0
  56. data/app/controllers/pageflow/entries_controller.rb +17 -13
  57. data/app/controllers/pageflow/review/comment_thread_reads_controller.rb +30 -0
  58. data/app/controllers/pageflow/review/comment_threads_controller.rb +60 -0
  59. data/app/controllers/pageflow/review/comments_controller.rb +53 -0
  60. data/app/controllers/pageflow/revisions_controller.rb +4 -1
  61. data/app/helpers/pageflow/admin/entries_helper.rb +40 -0
  62. data/app/helpers/pageflow/admin/widgets_helper.rb +2 -2
  63. data/app/helpers/pageflow/common_entry_seed_helper.rb +5 -3
  64. data/app/helpers/pageflow/editor/config_helper.rb +3 -1
  65. data/app/helpers/pageflow/entries_helper.rb +24 -42
  66. data/app/helpers/pageflow/entry_json_seed_helper.rb +4 -4
  67. data/app/helpers/pageflow/public_i18n_helper.rb +9 -8
  68. data/app/helpers/pageflow/structured_data_helper.rb +4 -1
  69. data/app/helpers/pageflow/themes_helper.rb +1 -3
  70. data/app/helpers/pageflow/widgets_helper.rb +2 -1
  71. data/app/inputs/pageflow_permalink_input.rb +6 -2
  72. data/app/models/concerns/pageflow/auto_generated_perma_id.rb +11 -4
  73. data/app/models/concerns/pageflow/reusable_file.rb +1 -1
  74. data/app/models/concerns/pageflow/serialization_blacklist.rb +2 -4
  75. data/app/models/concerns/pageflow/translated_attributes.rb +101 -0
  76. data/app/models/concerns/pageflow/uploadable_file.rb +1 -1
  77. data/app/models/pageflow/comment.rb +30 -0
  78. data/app/models/pageflow/comment_thread.rb +65 -0
  79. data/app/models/pageflow/comment_thread_read.rb +22 -0
  80. data/app/models/pageflow/customized_theme.rb +3 -2
  81. data/app/models/pageflow/draft_entry.rb +20 -8
  82. data/app/models/pageflow/entry.rb +2 -0
  83. data/app/models/pageflow/entry_at_revision.rb +9 -1
  84. data/app/models/pageflow/entry_comment_summary.rb +114 -0
  85. data/app/models/pageflow/file_folder.rb +74 -0
  86. data/app/models/pageflow/file_reuse.rb +3 -2
  87. data/app/models/pageflow/file_usage.rb +8 -0
  88. data/app/models/pageflow/image_file.rb +24 -20
  89. data/app/models/pageflow/image_file_url_templates.rb +3 -3
  90. data/app/models/pageflow/legal_info.rb +38 -0
  91. data/app/models/pageflow/nested_revision_component_copy.rb +1 -1
  92. data/app/models/pageflow/permalink.rb +1 -0
  93. data/app/models/pageflow/revision.rb +6 -2
  94. data/app/models/pageflow/site.rb +10 -0
  95. data/app/models/pageflow/used_file.rb +8 -2
  96. data/app/models/pageflow/widget.rb +2 -2
  97. data/app/views/pageflow/audio_files/_audio_file.json.jbuilder +0 -1
  98. data/app/views/pageflow/editor/config/_seeds.json.jbuilder +4 -2
  99. data/app/views/pageflow/editor/entries/_entry.json.jbuilder +2 -1
  100. data/app/views/pageflow/editor/entries/seed.json.erb +1 -0
  101. data/app/views/pageflow/editor/file_folders/_file_folder.json.jbuilder +5 -0
  102. data/app/views/pageflow/editor/file_folders/create.json.jbuilder +1 -0
  103. data/app/views/pageflow/editor/file_folders/index.json.jbuilder +3 -0
  104. data/app/views/pageflow/editor/files/_file.json.jbuilder +2 -1
  105. data/app/views/pageflow/editor/image_files/_image_file.json.jbuilder +3 -0
  106. data/app/views/pageflow/editor/video_files/_video_file.json.jbuilder +3 -0
  107. data/app/views/pageflow/files/_file.json.jbuilder +2 -0
  108. data/app/views/pageflow/image_files/_image_file.json.jbuilder +0 -1
  109. data/app/views/pageflow/review/comment_threads/_comment_thread.json.jbuilder +20 -0
  110. data/app/views/pageflow/review/comment_threads/create.json.jbuilder +2 -0
  111. data/app/views/pageflow/review/comment_threads/index.json.jbuilder +13 -0
  112. data/app/views/pageflow/review/comments/_comment.json.jbuilder +13 -0
  113. data/app/views/pageflow/review/comments/create.json.jbuilder +1 -0
  114. data/app/views/pageflow/structured_data/_entry.json.jbuilder +2 -3
  115. data/app/views/pageflow/video_files/_video_file.json.jbuilder +0 -1
  116. data/config/locales/de.yml +152 -14
  117. data/config/locales/en.yml +150 -14
  118. data/config/routes.rb +14 -0
  119. data/db/migrate/20140418225525_setup_schema.rb +2 -2
  120. data/db/migrate/20251015000000_add_structured_data_type_name_to_revisions.rb +5 -0
  121. data/db/migrate/20251029142849_convert_legacy_social_embeds_to_unified_social_embed.rb +38 -0
  122. data/db/migrate/20251119083347_fix_main_storyline_positions.rb +16 -0
  123. data/db/migrate/20251119083348_ensure_scrolled_entries_have_excursion_storyline.rb +15 -0
  124. data/db/migrate/20260303000000_add_layout_version_to_revisions.rb +6 -0
  125. data/db/migrate/20260323000000_create_comment_threads_and_comments.rb +30 -0
  126. data/db/migrate/20260414000000_add_subject_range_to_comment_threads.rb +5 -0
  127. data/db/migrate/20260415000000_add_section_perma_id_to_comment_threads.rb +5 -0
  128. data/db/migrate/20260727000000_add_quote_to_comments.rb +5 -0
  129. data/db/migrate/20260728000000_create_file_folders.rb +17 -0
  130. data/db/migrate/20260805000000_add_attribute_translations_to_sites.rb +5 -0
  131. data/db/migrate/20260806000000_add_edited_at_to_comments.rb +5 -0
  132. data/db/migrate/20260810000000_create_pageflow_scrolled_lottie_files.rb +24 -0
  133. data/db/migrate/20260817000000_create_comment_thread_reads.rb +16 -0
  134. data/db/migrate/20260819000000_add_unread_comments_since_at_to_users.rb +18 -0
  135. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/editor.js +8665 -3890
  136. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/frontend.js +979 -3571
  137. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/react-client.js +20199 -28120
  138. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/react-server.js +18652 -26584
  139. data/entry_types/scrolled/app/assets/stylesheets/pageflow_scrolled/ui.scss +2 -0
  140. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/content_elements_controller.rb +33 -3
  141. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/sections_controller.rb +2 -3
  142. data/entry_types/scrolled/app/controllers/pageflow_scrolled/entries_controller.rb +21 -1
  143. data/entry_types/scrolled/app/helpers/pageflow_scrolled/cache_helper.rb +3 -3
  144. data/entry_types/scrolled/app/helpers/pageflow_scrolled/editor/entry_json_seed_helper.rb +7 -5
  145. data/entry_types/scrolled/app/helpers/pageflow_scrolled/editor/seed_html_helper.rb +5 -2
  146. data/entry_types/scrolled/app/helpers/pageflow_scrolled/entry_json_seed_helper.rb +13 -5
  147. data/entry_types/scrolled/app/helpers/pageflow_scrolled/i18n_helper.rb +28 -13
  148. data/entry_types/scrolled/app/helpers/pageflow_scrolled/packs_helper.rb +26 -11
  149. data/entry_types/scrolled/app/helpers/pageflow_scrolled/react_server_side_rendering_helper.rb +2 -2
  150. data/entry_types/scrolled/app/helpers/pageflow_scrolled/sprockets_helper.rb +16 -0
  151. data/entry_types/scrolled/app/helpers/pageflow_scrolled/themes_helper.rb +174 -3
  152. data/entry_types/scrolled/app/models/pageflow_scrolled/content_element.rb +49 -7
  153. data/entry_types/scrolled/app/models/pageflow_scrolled/lottie_file.rb +6 -0
  154. data/entry_types/scrolled/app/models/pageflow_scrolled/lottie_file_url_templates.rb +16 -0
  155. data/entry_types/scrolled/app/models/pageflow_scrolled/storyline.rb +1 -0
  156. data/entry_types/scrolled/app/views/pageflow_scrolled/entries/show.html.erb +13 -12
  157. data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_entry.json.jbuilder +30 -10
  158. data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_theme.json.jbuilder +9 -0
  159. data/entry_types/scrolled/app/views/pageflow_scrolled/favicons/_entry.html.erb +1 -1
  160. data/entry_types/scrolled/config/configuration_schemas/pageflow-scrolled.json +414 -0
  161. data/entry_types/scrolled/config/locales/de.yml +512 -65
  162. data/entry_types/scrolled/config/locales/en.yml +518 -52
  163. data/entry_types/scrolled/lib/pageflow_scrolled/additional_seed_data.rb +2 -2
  164. data/entry_types/scrolled/lib/pageflow_scrolled/configuration.rb +51 -6
  165. data/entry_types/scrolled/lib/pageflow_scrolled/configuration_schemas.rb +91 -0
  166. data/entry_types/scrolled/lib/pageflow_scrolled/engine.rb +2 -1
  167. data/entry_types/scrolled/lib/pageflow_scrolled/entry_file_reference_locations.rb +71 -0
  168. data/entry_types/scrolled/lib/pageflow_scrolled/entry_structured_data_types/faq_page.rb +58 -0
  169. data/entry_types/scrolled/lib/pageflow_scrolled/file_reference_locations.rb +69 -0
  170. data/entry_types/scrolled/lib/pageflow_scrolled/plugin.rb +205 -22
  171. data/entry_types/scrolled/lib/pageflow_scrolled/react_widget_type.rb +2 -4
  172. data/entry_types/scrolled/lib/pageflow_scrolled/seeds.rb +56 -36
  173. data/entry_types/scrolled/lib/pageflow_scrolled/theme_options_default_scale.rb +35 -0
  174. data/entry_types/scrolled/lib/pageflow_scrolled.rb +13 -0
  175. data/entry_types/scrolled/lib/tasks/pageflow_scrolled/storybook.rake +19 -1
  176. data/entry_types/scrolled/package/config/configurationSchemas.js +70 -0
  177. data/entry_types/scrolled/package/config/rollup/configurationSchemas.js +19 -0
  178. data/entry_types/scrolled/package/config/webpack.js +72 -0
  179. data/entry_types/scrolled/package/contentElements/hotspots-frontend.css +1 -1
  180. data/entry_types/scrolled/package/contentElements/hotspots-frontend.js +1181 -915
  181. data/entry_types/scrolled/package/contentElements/inlineBeforeAfter-frontend.css +1 -0
  182. data/entry_types/scrolled/package/contentElements/inlineBeforeAfter-frontend.js +219 -0
  183. data/entry_types/scrolled/package/contentElements/lottieAnimation-frontend.css +1 -0
  184. data/entry_types/scrolled/package/contentElements/lottieAnimation-frontend.js +244 -0
  185. data/entry_types/scrolled/package/contentElements/socialEmbed-frontend.css +1 -0
  186. data/entry_types/scrolled/package/contentElements/socialEmbed-frontend.js +823 -0
  187. data/entry_types/scrolled/package/contentElements/tikTokEmbed-frontend.js +71 -21
  188. data/entry_types/scrolled/package/contentElements/twitterEmbed-frontend.css +1 -0
  189. data/entry_types/scrolled/package/contentElements/twitterEmbed-frontend.js +277 -0
  190. data/entry_types/scrolled/package/contentElements/videoEmbed-frontend.css +1 -0
  191. data/entry_types/scrolled/package/contentElements/videoEmbed-frontend.js +244 -0
  192. data/entry_types/scrolled/package/contentElements-editor.js +1915 -1097
  193. data/entry_types/scrolled/package/contentElements-frontend.css +1 -1
  194. data/entry_types/scrolled/package/contentElements-frontend.js +3093 -1679
  195. data/entry_types/scrolled/package/editor.css +1 -0
  196. data/entry_types/scrolled/package/editor.js +8667 -4077
  197. data/entry_types/scrolled/package/entryState.js +1600 -0
  198. data/entry_types/scrolled/package/frontend/FloatingPortalRootProvider-20c600de.js +1979 -0
  199. data/entry_types/scrolled/package/frontend/FloatingPortalRootProvider-58189220.js +2538 -0
  200. data/entry_types/scrolled/package/frontend/{PhonePlatformContext-9f76033e.js → PhonePlatformContext-035a99fa.js} +7 -12
  201. data/entry_types/scrolled/package/frontend/PhonePlatformContext-9da43797.js +33 -0
  202. data/entry_types/scrolled/package/frontend/Placeholder.module-bf0966b4.js +5267 -0
  203. data/entry_types/scrolled/package/frontend/Placeholder.module-d22a9335.js +4180 -0
  204. data/entry_types/scrolled/package/frontend/ThemeIcon-ab834849.js +754 -0
  205. data/entry_types/scrolled/package/frontend/ThemeIcon-f6cb3a8f.js +773 -0
  206. data/entry_types/scrolled/package/frontend/{ToggleFullscreenCornerButton-788e9cdb.js → ToggleFullscreenCornerButton-30fd1124.js} +6 -6
  207. data/entry_types/scrolled/package/frontend/ToggleFullscreenCornerButton-61c25224.js +72 -0
  208. data/entry_types/scrolled/package/frontend/Viewer-1074fd59.js +147 -0
  209. data/entry_types/scrolled/package/frontend/Viewer-1482ca34.js +480 -0
  210. data/entry_types/scrolled/package/frontend/Viewer-70504231.js +210 -0
  211. data/entry_types/scrolled/package/frontend/{Viewer-0345ce57.js → Viewer-cc8d4072.js} +84 -92
  212. data/entry_types/scrolled/package/frontend/Wavesurfer-656e3c36.js +302 -0
  213. data/entry_types/scrolled/package/frontend/Wavesurfer-b753b838.js +385 -0
  214. data/entry_types/scrolled/package/frontend/commenting.css +1 -0
  215. data/entry_types/scrolled/package/frontend/extensions-167ae143.js +1455 -0
  216. data/entry_types/scrolled/package/frontend/extensions-2318f92b.js +5918 -0
  217. data/entry_types/scrolled/package/frontend/extensions-a461fd13.js +4890 -0
  218. data/entry_types/scrolled/package/frontend/extensions-c98269fd.js +1982 -0
  219. data/entry_types/scrolled/package/frontend/i18n-493cd2a6.js +93 -0
  220. data/entry_types/scrolled/package/frontend/i18n-e06cac14.js +100 -0
  221. data/entry_types/scrolled/package/frontend/{index-eb670c2f.js → index-2e5546f7.js} +36 -44
  222. data/entry_types/scrolled/package/frontend/index-de2b418d.js +130 -0
  223. data/entry_types/scrolled/package/frontend/index.css +1 -1
  224. data/entry_types/scrolled/package/frontend/index.js +1870 -875
  225. data/entry_types/scrolled/package/frontend/inlineEditing.css +1 -0
  226. data/entry_types/scrolled/package/frontend/useContentElementEditorState-a084912e.js +25 -0
  227. data/entry_types/scrolled/package/frontend/useDelayedBoolean-a387d85b.js +24 -0
  228. data/entry_types/scrolled/package/frontend/{usePhonePlatform-c2ba875d.js → usePhonePlatform-4ecb96d4.js} +1 -1
  229. data/entry_types/scrolled/package/frontend/usePhonePlatform-ce9ff08d.js +8 -0
  230. data/entry_types/scrolled/package/frontend-server.js +20 -209
  231. data/entry_types/scrolled/package/package.json +5 -3
  232. data/entry_types/scrolled/package/review.css +1 -0
  233. data/entry_types/scrolled/package/review.js +3306 -0
  234. data/entry_types/scrolled/package/testHelpers.js +836 -359
  235. data/entry_types/scrolled/package/widgets/consentBar.css +1 -1
  236. data/entry_types/scrolled/package/widgets/consentBar.js +269 -290
  237. data/entry_types/scrolled/package/widgets/defaultNavigation.css +2 -2
  238. data/entry_types/scrolled/package/widgets/defaultNavigation.js +911 -352
  239. data/entry_types/scrolled/package/widgets/excursionSheet.css +1 -1
  240. data/entry_types/scrolled/package/widgets/excursionSheet.js +87 -124
  241. data/entry_types/scrolled/package/widgets/iconInlineFileRights.css +1 -1
  242. data/entry_types/scrolled/package/widgets/iconInlineFileRights.js +62 -29
  243. data/entry_types/scrolled/package/widgets/iconScrollIndicator.js +32 -13
  244. data/entry_types/scrolled/package/widgets/mainStorylineSheet.css +1 -1
  245. data/entry_types/scrolled/package/widgets/mainStorylineSheet.js +56 -100
  246. data/entry_types/scrolled/package/widgets/textInlineFileRights.css +1 -1
  247. data/entry_types/scrolled/package/widgets/textInlineFileRights.js +33 -28
  248. data/entry_types/scrolled/package/widgets-server.js +1 -0
  249. data/entry_types/scrolled/spec/factories/lottie_files.rb +29 -0
  250. data/entry_types/scrolled/spec/fixtures/animation.lottie +0 -0
  251. data/entry_types/scrolled/spec/fixtures/font.woff +0 -0
  252. data/entry_types/scrolled/spec/fixtures/font.woff2 +0 -0
  253. data/lib/generators/pageflow/resque/resque_generator.rb +0 -2
  254. data/lib/pageflow/configuration.rb +49 -7
  255. data/lib/pageflow/deprecation.rb +19 -0
  256. data/lib/pageflow/engine.rb +1 -1
  257. data/lib/pageflow/entries_controller_env_helper.rb +32 -2
  258. data/lib/pageflow/entry_export_import/entry_serialization.rb +4 -4
  259. data/lib/pageflow/entry_export_import/page_type_versions.rb +2 -2
  260. data/lib/pageflow/entry_export_import/revision_serialization/import.rb +10 -0
  261. data/lib/pageflow/entry_export_import/revision_serialization.rb +3 -0
  262. data/lib/pageflow/entry_structured_data_types.rb +43 -0
  263. data/lib/pageflow/entry_type_configuration.rb +1 -0
  264. data/lib/pageflow/file_type.rb +2 -2
  265. data/lib/pageflow/file_types.rb +1 -1
  266. data/lib/pageflow/oembed_providers.rb +42 -0
  267. data/lib/pageflow/primary_domain_entry_redirect.rb +6 -0
  268. data/lib/pageflow/rails_version.rb +13 -2
  269. data/lib/pageflow/themes.rb +41 -0
  270. data/lib/pageflow/user_mixin.rb +12 -0
  271. data/lib/pageflow/version.rb +1 -1
  272. data/lib/pageflow.rb +1 -0
  273. data/package/config/eslint-rules/documented-in-toc.js +125 -0
  274. data/package/config/jest/index.js +0 -1
  275. data/package/config/webpack.js +0 -1
  276. data/package/config/webpack5.js +0 -1
  277. data/package/editor.js +4378 -1897
  278. data/package/frontend.js +647 -886
  279. data/package/package.json +2 -1
  280. data/package/review.js +384 -0
  281. data/package/testHelpers.js +248 -188
  282. data/package/ui.js +1346 -630
  283. data/package/vendor/stubs/wysihtml5.js +2 -0
  284. data/spec/factories/comment_thread_reads.rb +10 -0
  285. data/spec/factories/comment_threads.rb +10 -0
  286. data/spec/factories/comments.rb +9 -0
  287. data/spec/factories/file_folders.rb +8 -0
  288. data/spec/factories/published_entries.rb +2 -0
  289. metadata +188 -67
  290. data/app/assets/stylesheets/pageflow/editor/select_button.scss +0 -51
  291. data/entry_types/scrolled/app/helpers/pageflow_scrolled/generated_media_queries_helper.rb +0 -55
  292. data/entry_types/scrolled/package/frontend/FloatingPortalRootProvider-51914be7.js +0 -5439
  293. data/entry_types/scrolled/package/frontend/ThemeIcon-81f2f066.js +0 -1932
  294. data/entry_types/scrolled/package/frontend/Viewer-cdc549cc.js +0 -147
  295. data/entry_types/scrolled/package/frontend/Wavesurfer-1cdc3925.js +0 -313
  296. data/entry_types/scrolled/package/frontend/components-96660ffd.js +0 -3803
  297. data/entry_types/scrolled/package/frontend/inherits-539844a6.js +0 -99
  298. data/entry_types/scrolled/package/frontend/useContentElementEditorState-77fe6c79.js +0 -51
  299. data/entry_types/scrolled/package/widgets/excursionDialog.css +0 -1
  300. data/entry_types/scrolled/package/widgets/excursionDialog.js +0 -109
  301. data/lib/generators/pageflow/resque/templates/resque_enqueue_after_commit_patch.rb +0 -25
  302. data/package/vendor/jquery.minicolors.js +0 -1108
@@ -2,138 +2,94 @@ import { useIsomorphicLayoutEffect, frontend } from 'pageflow-scrolled/frontend'
2
2
  import React, { useState, useRef } from 'react';
3
3
  import classNames from 'classnames';
4
4
 
5
- function _defineProperty(obj, key, value) {
6
- if (key in obj) {
7
- Object.defineProperty(obj, key, {
8
- value: value,
9
- enumerable: true,
10
- configurable: true,
11
- writable: true
12
- });
13
- } else {
14
- obj[key] = value;
15
- }
16
-
17
- return obj;
18
- }
19
-
20
- function _arrayWithHoles(arr) {
21
- if (Array.isArray(arr)) return arr;
22
- }
23
-
24
- function _iterableToArrayLimit(arr, i) {
25
- if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
26
- var _arr = [];
27
- var _n = true;
28
- var _d = false;
29
- var _e = undefined;
30
-
31
- try {
32
- for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
33
- _arr.push(_s.value);
34
-
35
- if (i && _arr.length === i) break;
36
- }
37
- } catch (err) {
38
- _d = true;
39
- _e = err;
40
- } finally {
41
- try {
42
- if (!_n && _i["return"] != null) _i["return"]();
43
- } finally {
44
- if (_d) throw _e;
45
- }
46
- }
47
-
48
- return _arr;
49
- }
50
-
51
- function _arrayLikeToArray(arr, len) {
52
- if (len == null || len > arr.length) len = arr.length;
53
-
54
- for (var i = 0, arr2 = new Array(len); i < len; i++) {
55
- arr2[i] = arr[i];
56
- }
57
-
58
- return arr2;
59
- }
60
-
61
- function _unsupportedIterableToArray(o, minLen) {
62
- if (!o) return;
63
- if (typeof o === "string") return _arrayLikeToArray(o, minLen);
64
- var n = Object.prototype.toString.call(o).slice(8, -1);
65
- if (n === "Object" && o.constructor) n = o.constructor.name;
66
- if (n === "Map" || n === "Set") return Array.from(n);
67
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
68
- }
69
-
70
- function _nonIterableRest() {
71
- throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
72
- }
73
-
74
- function _slicedToArray(arr, i) {
75
- return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
76
- }
77
-
78
- var styles = {"inactive":"MainStorylineSheet-module_inactive__1Ji-y","scaler":"MainStorylineSheet-module_scaler__jscn7"};
5
+ var styles = {"inactive":"MainStorylineSheet-module_inactive__1Ji-y","scaler":"MainStorylineSheet-module_scaler__jscn7","fixedPositioningContainingBlock":"MainStorylineSheet-module_fixedPositioningContainingBlock__3Pz_y"};
79
6
 
80
7
  var _jsxFileName = "/home/tfischbach/code/pageflow/entry_types/scrolled/package/src/widgets/mainStorylineSheet/MainStorylineSheet.js";
81
- function MainStorylineSheet(_ref) {
82
- var activeExcursion = _ref.activeExcursion,
83
- children = _ref.children;
84
- var excursionActive = !!activeExcursion;
85
- var activeExcursionId = activeExcursion === null || activeExcursion === void 0 ? void 0 : activeExcursion.id;
86
- var _useState = useState(0),
87
- _useState2 = _slicedToArray(_useState, 2),
88
- previousScrollY = _useState2[0],
89
- setPreviousScrollY = _useState2[1];
90
- var _useState3 = useState(false),
91
- _useState4 = _slicedToArray(_useState3, 2),
92
- inactive = _useState4[0],
93
- setInactive = _useState4[1];
94
- var previousThemeColorRef = useRef();
95
- useIsomorphicLayoutEffect(function () {
96
- var themeColorMeta = document.querySelector('meta[name="theme-color"]');
8
+ function MainStorylineSheet({
9
+ activeExcursion,
10
+ children
11
+ }) {
12
+ const excursionActive = !!activeExcursion;
13
+ const activeExcursionId = activeExcursion === null || activeExcursion === void 0 ? void 0 : activeExcursion.id;
14
+ const [previousScrollY, setPreviousScrollY] = useState(null);
15
+ const [inactive, setInactive] = useState(false);
16
+ const [fixedPositioningContainingBlock, setFixedPositioningContainingBlock] = useState(false);
17
+ const previousThemeColorRef = useRef();
18
+ const transitionTimeoutRef = useRef();
19
+ useIsomorphicLayoutEffect(() => {
20
+ const themeColorMeta = document.querySelector('meta[name="theme-color"]');
97
21
  if (excursionActive) {
98
22
  setPreviousScrollY(window.scrollY);
99
23
  setInactive(true);
24
+ applyFixedPositioningContainingBlockOffset();
100
25
  previousThemeColorRef.current = themeColorMeta.getAttribute('content');
101
26
  themeColorMeta.setAttribute('content', '#000');
102
27
  } else {
103
28
  setInactive(false);
104
- themeColorMeta.setAttribute('content', previousThemeColorRef.current);
29
+ scheduleFixedPositioningContainingBlockReset();
30
+ if (previousThemeColorRef.current) {
31
+ themeColorMeta.setAttribute('content', previousThemeColorRef.current);
32
+ }
33
+ }
34
+ function applyFixedPositioningContainingBlockOffset() {
35
+ setFixedPositioningContainingBlock(true);
36
+ if (transitionTimeoutRef.current) {
37
+ clearTimeout(transitionTimeoutRef.current);
38
+ }
39
+ }
40
+ function scheduleFixedPositioningContainingBlockReset() {
41
+ const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
42
+ if (prefersReducedMotion) {
43
+ setFixedPositioningContainingBlock(false);
44
+ } else {
45
+ const transitionDuration = 300;
46
+ const buffer = 100;
47
+ transitionTimeoutRef.current = setTimeout(() => {
48
+ setFixedPositioningContainingBlock(false);
49
+ }, transitionDuration + buffer);
50
+ }
105
51
  }
106
52
  }, [excursionActive]);
107
- useIsomorphicLayoutEffect(function () {
53
+ useIsomorphicLayoutEffect(() => {
108
54
  if (activeExcursionId) {
109
55
  window.scrollTo(0, 0);
110
56
  } else {
111
- setPreviousScrollY(function (previousScrollY) {
112
- window.queueMicrotask(function () {
113
- return window.scrollTo(0, previousScrollY);
114
- });
57
+ setPreviousScrollY(previousScrollY => {
58
+ if (previousScrollY !== null) {
59
+ window.queueMicrotask(() => window.scrollTo(0, previousScrollY));
60
+ }
115
61
  return previousScrollY;
116
62
  });
117
63
  }
118
64
  }, [activeExcursionId]);
65
+ function resetFixedPositioningContainingBlock(event) {
66
+ if (event.propertyName === 'filter' && event.target === event.currentTarget && !inactive) {
67
+ clearTimeout(transitionTimeoutRef.current);
68
+ setFixedPositioningContainingBlock(false);
69
+ }
70
+ }
119
71
  return /*#__PURE__*/React.createElement("div", {
120
72
  inert: inactive ? 'true' : undefined,
121
73
  style: {
122
- '--previous-scroll-y': "".concat(previousScrollY, "px")
74
+ '--previous-scroll-y': `${previousScrollY || 0}px`
123
75
  },
124
- className: classNames(styles.wrapper, _defineProperty({}, styles.inactive, inactive)),
76
+ className: classNames({
77
+ [styles.inactive]: inactive,
78
+ [styles.fixedPositioningContainingBlock]: fixedPositioningContainingBlock
79
+ }),
125
80
  __self: this,
126
81
  __source: {
127
82
  fileName: _jsxFileName,
128
- lineNumber: 47,
83
+ lineNumber: 87,
129
84
  columnNumber: 5
130
85
  }
131
86
  }, /*#__PURE__*/React.createElement("div", {
132
87
  className: styles.scaler,
88
+ onTransitionEnd: fixedPositioningContainingBlock ? resetFixedPositioningContainingBlock : undefined,
133
89
  __self: this,
134
90
  __source: {
135
91
  fileName: _jsxFileName,
136
- lineNumber: 50,
92
+ lineNumber: 93,
137
93
  columnNumber: 7
138
94
  }
139
95
  }, children));
@@ -1 +1 @@
1
- .colors-module_contentColorScope__3ypcw{--theme-light-content-surface-color:var(--root-light-content-surface-color);--theme-dark-content-surface-color:var(--root-dark-content-surface-color);--theme-light-content-text-color:var(--root-light-content-text-color);--theme-dark-content-text-color:var(--root-dark-content-text-color)}.TextInlineFileRights-module_text__1tT0W{font-size:14px;position:relative;z-index:1;color:var(--content-text-color)}.TextInlineFileRights-module_text__1tT0W li{text-align:right;padding-top:.2em}.TextInlineFileRights-module_text__1tT0W li:before{content:"\A9 ";opacity:.7}.TextInlineFileRights-module_text__1tT0W:not(:has(li:nth-child(2))) span{display:none}.TextInlineFileRights-module_withBackdrop__2cRu8 li{padding:.1em .3em;border-radius:.25rem;margin:.2em 0 0 auto;background-color:color-mix(in srgb,var(--theme-light-content-surface-color,#fff),transparent);color:var(--theme-dark-content-text-color,#222);width:-moz-fit-content;width:fit-content}.TextInlineFileRights-module_withBackdrop__2cRu8.TextInlineFileRights-module_darkBackground__3oIUp li{background-color:color-mix(in srgb,var(--theme-dark-content-surface-color,#101010),transparent);color:var(--theme-light-content-text-color,#fff)}.TextInlineFileRights-module_forSection__22xHD{position:absolute;bottom:0;right:0}.TextInlineFileRights-module_forSection__22xHD li{margin:0 .2em .1em auto}.TextInlineFileRights-module_text__1tT0W a{color:inherit;-webkit-text-decoration-color:color-mix(in srgb,currentColor,transparent);text-decoration-color:color-mix(in srgb,currentColor,transparent)}.TextInlineFileRights-module_text__1tT0W span{opacity:.7}
1
+ .colors-module_contentColorScope__3ypcw{--theme-light-content-surface-color:var(--root-light-content-surface-color);--theme-dark-content-surface-color:var(--root-dark-content-surface-color);--theme-light-content-text-color:var(--root-light-content-text-color);--theme-dark-content-text-color:var(--root-dark-content-text-color)}.TextInlineFileRights-module_text__1tT0W{font-size:14px;position:relative;z-index:2;color:var(--content-text-color);--ai-indicator-letter-color:var(--theme-light-content-surface-color,#fff)}.TextInlineFileRights-module_text__1tT0W.TextInlineFileRights-module_darkBackground__3oIUp{--ai-indicator-letter-color:var(--theme-dark-content-surface-color,#101010)}.TextInlineFileRights-module_text__1tT0W li{text-align:right;justify-content:flex-end;padding-top:.2em}.TextInlineFileRights-module_text__1tT0W li[data-rights] [data-part=rights]:before{content:"\A9 ";opacity:.7}.TextInlineFileRights-module_text__1tT0W li:only-child [data-label]{display:none}.TextInlineFileRights-module_withBackdrop__2cRu8 li{padding:.1em .3em;border-radius:.25rem;margin:.2em 0 0 auto;background-color:color-mix(in srgb,var(--theme-light-content-surface-color,#fff),transparent);color:var(--theme-dark-content-text-color,#222);width:-moz-fit-content;width:fit-content}.TextInlineFileRights-module_withBackdrop__2cRu8.TextInlineFileRights-module_darkBackground__3oIUp li{background-color:color-mix(in srgb,var(--theme-dark-content-surface-color,#101010),transparent);color:var(--theme-light-content-text-color,#fff)}.TextInlineFileRights-module_forSection__22xHD{position:absolute;bottom:0;right:0}.TextInlineFileRights-module_forSection__22xHD li{margin:0 .2em .1em auto}.TextInlineFileRights-module_text__1tT0W a{color:inherit;-webkit-text-decoration-color:color-mix(in srgb,currentColor,transparent);text-decoration-color:color-mix(in srgb,currentColor,transparent)}.TextInlineFileRights-module_text__1tT0W [data-label]{opacity:.7}
@@ -2,38 +2,26 @@ import { useDarkBackground, useContentElementEditorState, frontend } from 'pagef
2
2
  import React, { useEffect } from 'react';
3
3
  import classNames from 'classnames';
4
4
 
5
- function _defineProperty(obj, key, value) {
6
- if (key in obj) {
7
- Object.defineProperty(obj, key, {
8
- value: value,
9
- enumerable: true,
10
- configurable: true,
11
- writable: true
12
- });
13
- } else {
14
- obj[key] = value;
15
- }
16
-
17
- return obj;
18
- }
5
+ var styles = {"darkContentSurfaceColor":"var(--theme-dark-content-surface-color, #101010)","lightContentSurfaceColor":"var(--theme-light-content-surface-color, #fff)","darkContentTextColor":"var(--theme-dark-content-text-color, #222)","lightContentTextColor":"var(--theme-light-content-text-color, #fff)","text":"TextInlineFileRights-module_text__1tT0W","darkBackground":"TextInlineFileRights-module_darkBackground__3oIUp","withBackdrop":"TextInlineFileRights-module_withBackdrop__2cRu8","forSection":"TextInlineFileRights-module_forSection__22xHD"};
19
6
 
20
- var styles = {"darkContentSurfaceColor":"var(--theme-dark-content-surface-color, #101010)","lightContentSurfaceColor":"var(--theme-light-content-surface-color, #fff)","darkContentTextColor":"var(--theme-dark-content-text-color, #222)","lightContentTextColor":"var(--theme-light-content-text-color, #fff)","contentColorScope":"colors-module_contentColorScope__3ypcw","text":"TextInlineFileRights-module_text__1tT0W","withBackdrop":"TextInlineFileRights-module_withBackdrop__2cRu8","darkBackground":"TextInlineFileRights-module_darkBackground__3oIUp","forSection":"TextInlineFileRights-module_forSection__22xHD"};
21
-
22
- function TextInlineFileRights(_ref) {
23
- var configuration = _ref.configuration,
24
- context = _ref.context,
25
- children = _ref.children;
26
- var darkBackground = useDarkBackground();
27
- var _useContentElementEdi = useContentElementEditorState(),
28
- setTransientState = _useContentElementEdi.setTransientState;
29
- var supported = context !== 'insideElement' && context !== 'playerControls';
30
- useEffect(function () {
7
+ var _jsxFileName = "/home/tfischbach/code/pageflow/entry_types/scrolled/package/src/widgets/textInlineFileRights/TextInlineFileRights.js";
8
+ function TextInlineFileRights({
9
+ configuration,
10
+ context,
11
+ children
12
+ }) {
13
+ const darkBackground = useDarkBackground();
14
+ const {
15
+ setTransientState
16
+ } = useContentElementEditorState();
17
+ const supported = context !== 'insideElement' && context !== 'playerControls';
18
+ useEffect(() => {
31
19
  if (supported) {
32
20
  setTransientState({
33
21
  hasFileRights: true
34
22
  });
35
23
  }
36
- return function () {
24
+ return () => {
37
25
  if (supported) {
38
26
  setTransientState({
39
27
  hasFileRights: false
@@ -45,8 +33,25 @@ function TextInlineFileRights(_ref) {
45
33
  return null;
46
34
  }
47
35
  return /*#__PURE__*/React.createElement("div", {
48
- className: classNames(styles.text, _defineProperty(_defineProperty(_defineProperty({}, styles.forSection, context === 'section'), styles.withBackdrop, context === 'section' || configuration.showTextInlineFileRightsBackdrop), styles.darkBackground, darkBackground))
49
- }, /*#__PURE__*/React.createElement("div", null, children));
36
+ className: classNames(styles.text, {
37
+ [styles.forSection]: context === 'section',
38
+ [styles.withBackdrop]: context === 'section' || configuration.showTextInlineFileRightsBackdrop,
39
+ [styles.darkBackground]: darkBackground
40
+ }),
41
+ __self: this,
42
+ __source: {
43
+ fileName: _jsxFileName,
44
+ lineNumber: 29,
45
+ columnNumber: 5
46
+ }
47
+ }, /*#__PURE__*/React.createElement("div", {
48
+ __self: this,
49
+ __source: {
50
+ fileName: _jsxFileName,
51
+ lineNumber: 34,
52
+ columnNumber: 7
53
+ }
54
+ }, children));
50
55
  }
51
56
 
52
57
  frontend.widgetTypes.register('textInlineFileRights', {
@@ -3,3 +3,4 @@ import 'pageflow-scrolled/widgets/consentBar';
3
3
  import 'pageflow-scrolled/widgets/iconInlineFileRights';
4
4
  import 'pageflow-scrolled/widgets/textInlineFileRights';
5
5
  import 'pageflow-scrolled/widgets/iconScrollIndicator';
6
+ import 'pageflow-scrolled/widgets/mainStorylineSheet';
@@ -0,0 +1,29 @@
1
+ module PageflowScrolled
2
+ FactoryBot.define do
3
+ factory :lottie_file, class: LottieFile do
4
+ entry
5
+ uploader { create(:user) }
6
+
7
+ attachment { File.open(Engine.root.join('spec', 'fixtures', 'animation.lottie')) }
8
+ state { 'uploaded' }
9
+
10
+ transient do
11
+ used_in { nil }
12
+ with_configuration { nil }
13
+ end
14
+
15
+ before(:create) do |file, evaluator|
16
+ file.entry = evaluator.used_in.entry if evaluator.used_in
17
+ end
18
+
19
+ after(:create) do |file, evaluator|
20
+ if evaluator.used_in
21
+ create(:file_usage,
22
+ file:,
23
+ revision: evaluator.used_in,
24
+ configuration: evaluator.with_configuration)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -10,8 +10,6 @@ module Pageflow
10
10
 
11
11
  def create_initializers
12
12
  template 'resque.rb', 'config/initializers/resque.rb'
13
- template 'resque_enqueue_after_commit_patch.rb',
14
- 'config/initializers/resque_enqueue_after_commit_patch.rb'
15
13
  template 'resque.rake', 'lib/tasks/resque.rake'
16
14
 
17
15
  inject_into_file 'config/application.rb', after: /config.load_defaults .*\n/ do
@@ -120,6 +120,20 @@ module Pageflow
120
120
  # @return [fileImporters]
121
121
  attr_reader :file_importers
122
122
 
123
+ # Used to register different structured data types for entries.
124
+ #
125
+ # @example
126
+ #
127
+ # config.entry_structured_data_types.register(:about_page, lambda do |entry|
128
+ # {
129
+ # '@type' => 'AboutPage',
130
+ # breadcrumb: entry.configuration['breadcrumb']
131
+ # }
132
+ # end)
133
+ #
134
+ # @return [EntryStructuredDataTypes]
135
+ attr_reader :entry_structured_data_types
136
+
123
137
  # Used to add new sections to the help dialog displayed in the
124
138
  # editor.
125
139
  #
@@ -473,6 +487,19 @@ module Pageflow
473
487
  # @since 17.1
474
488
  attr_accessor :entry_translator_url
475
489
 
490
+ # Registry for oEmbed providers that can be used to resolve URLs.
491
+ #
492
+ # @example
493
+ #
494
+ # config.oembed_providers.register(
495
+ # :bluesky,
496
+ # endpoint: 'https://bsky.app/oembed.{format}',
497
+ # url_patterns: ['https://bsky.app/profile/*/post/*']
498
+ # )
499
+ # @since 17.2
500
+ # @return [OembedProviders]
501
+ attr_reader :oembed_providers
502
+
476
503
  def initialize(target_type_name = nil)
477
504
  @target_type_name = target_type_name
478
505
 
@@ -510,6 +537,13 @@ module Pageflow
510
537
  @file_types = FileTypes.new
511
538
  @widget_types = WidgetTypes.new
512
539
  @file_importers = FileImporters.new
540
+ @entry_structured_data_types = EntryStructuredDataTypes.new
541
+ @entry_structured_data_types.register(:article, lambda do |_entry|
542
+ {
543
+ '@type' => 'Article',
544
+ articleSection: 'longform'
545
+ }
546
+ end, default: true)
513
547
  @help_entries = HelpEntries.new
514
548
  @revision_components = RevisionComponents.new
515
549
 
@@ -562,6 +596,13 @@ module Pageflow
562
596
  @permissions = Permissions.new
563
597
 
564
598
  @edit_lock_polling_interval = 15.seconds
599
+
600
+ @oembed_providers = OembedProviders.new
601
+ @oembed_providers.register(
602
+ :bluesky,
603
+ endpoint: 'https://embed.bsky.app/oembed',
604
+ url_patterns: ['https://bsky.app/profile/*/post/*']
605
+ )
565
606
  end
566
607
 
567
608
  # Activate a plugin.
@@ -584,10 +625,9 @@ module Pageflow
584
625
 
585
626
  # @deprecated Use `config.page_types.register` instead.
586
627
  def register_page_type(page_type)
587
- ActiveSupport::Deprecation.warn(
628
+ Pageflow::Deprecation.warn(
588
629
  'Pageflow::Configuration#register_page_type is deprecated. ' \
589
- 'Use config.page_types.register instead.',
590
- caller
630
+ 'Use config.page_types.register instead.'
591
631
  )
592
632
  page_types.register(page_type)
593
633
  end
@@ -595,14 +635,14 @@ module Pageflow
595
635
  # @deprecated Pageflow now supports direct uploads to S3 via signed post requests.
596
636
  # Please change your forms accordingly.
597
637
  def paperclip_filesystem_root
598
- ActiveSupport::Deprecation.warn(
599
- 'Pageflow::Configuration#paperclip_filesystem_root is deprecated.', caller
638
+ Pageflow::Deprecation.warn(
639
+ 'Pageflow::Configuration#paperclip_filesystem_root is deprecated.'
600
640
  )
601
641
  end
602
642
 
603
643
  def paperclip_filesystem_root=(_val)
604
- ActiveSupport::Deprecation.warn(
605
- 'Pageflow::Configuration#paperclip_filesystem_root is deprecated.', caller
644
+ Pageflow::Deprecation.warn(
645
+ 'Pageflow::Configuration#paperclip_filesystem_root is deprecated.'
606
646
  )
607
647
  end
608
648
 
@@ -687,10 +727,12 @@ module Pageflow
687
727
  delegate :page_types, to: :config
688
728
  delegate :themes, to: :config
689
729
  delegate :widget_types, to: :config
730
+ delegate :entry_structured_data_types, to: :config
690
731
  delegate :public_entry_cache_control_header=, to: :config
691
732
  delegate :additional_public_entry_headers, to: :config
692
733
  delegate :cutoff_modes, to: :config
693
734
  delegate :entry_translator_url=, to: :config
735
+ delegate :public_entry_redirect=, to: :config
694
736
  delegate :public_entry_url_options=, to: :config
695
737
 
696
738
  delegate :for_entry_type, to: :config
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/deprecation'
4
+ require 'pageflow/version'
5
+
6
+ module Pageflow
7
+ # @api private
8
+ module Deprecation
9
+ module_function
10
+
11
+ def warn(message, callstack = nil)
12
+ deprecator.warn(message, callstack || caller_locations(2))
13
+ end
14
+
15
+ def deprecator
16
+ @deprecator ||= ActiveSupport::Deprecation.new(Pageflow::VERSION, 'Pageflow')
17
+ end
18
+ end
19
+ end
@@ -22,10 +22,10 @@ require 'jquery-layout-rails'
22
22
  require 'backbone-rails'
23
23
  require 'marionette-rails'
24
24
  require 'jquery-fileupload-rails'
25
- require 'jquery-minicolors-rails'
26
25
  require 'i18n-js'
27
26
  require 'http_accept_language'
28
27
  require 'pageflow-public-i18n'
28
+ require 'oembed'
29
29
 
30
30
  require 'pageflow_paged'
31
31
  require 'pageflow_scrolled'
@@ -28,9 +28,39 @@ module Pageflow
28
28
  EntriesControllerEnvHelper.get_pageflow_hash(env)['entry_mode']
29
29
  end
30
30
 
31
+ # Returns `true` if the entry is being rendered as an embed. The
32
+ # information will be placed in the request env by the Pageflow
33
+ # engine before delegating to the entry type's frontend app.
34
+ #
35
+ # Use {EntriesControllerTestHelper} to set up the request
36
+ # environment in controller tests.
37
+ def get_embed_from_env(env = request.env)
38
+ EntriesControllerEnvHelper.get_pageflow_hash(env)['embed']
39
+ end
40
+
41
+ # Returns the locale of the signed in user, i.e. the locale any
42
+ # user interface displayed on top of the entry shall use. Returns
43
+ # `nil` for published entries since those are not rendered for a
44
+ # specific user. Entry types are expected to render the entry
45
+ # itself in the locale of the entry, no matter which locale is
46
+ # returned here.
47
+ #
48
+ # Use {EntriesControllerTestHelper} to set up the request
49
+ # environment in controller tests.
50
+ #
51
+ # @since 17.2
52
+ def get_ui_locale_from_env(env = request.env)
53
+ EntriesControllerEnvHelper.get_pageflow_hash(env)['ui_locale']
54
+ end
55
+
31
56
  # @api private
32
- def self.add_entry_info_to_env(env, entry:, mode: nil)
33
- env['pageflow'] = {'published_entry' => entry, 'entry_mode' => mode}
57
+ def self.add_entry_info_to_env(env, entry:, mode: nil, embed: false, ui_locale: nil)
58
+ env['pageflow'] = {
59
+ 'published_entry' => entry,
60
+ 'entry_mode' => mode,
61
+ 'embed' => embed,
62
+ 'ui_locale' => ui_locale
63
+ }
34
64
  end
35
65
 
36
66
  # @api private
@@ -14,10 +14,10 @@ module Pageflow
14
14
  # to prevent it from showing up in Active Admin JSON exports.
15
15
  # It is included separately as part of the entry export.
16
16
  'entry' => entry
17
- .as_json(except: [:folder_id, :password_digest, :users_count])
18
- .merge('features_configuration' => entry.features_configuration,
19
- 'draft' => RevisionSerialization.dump(entry.draft),
20
- 'last_publication' => dump_publication(publication))
17
+ .as_json(except: [:folder_id, :password_digest, :users_count])
18
+ .merge('features_configuration' => entry.features_configuration,
19
+ 'draft' => RevisionSerialization.dump(entry.draft),
20
+ 'last_publication' => dump_publication(publication))
21
21
  }
22
22
  end
23
23
 
@@ -7,8 +7,8 @@ module Pageflow
7
7
  class IncompatibleVersionsError < StandardError; end
8
8
 
9
9
  def dump
10
- Pageflow.config.page_types.each_with_object({}) do |page_type, version_requirements|
11
- version_requirements[page_type.name] = page_type.export_version
10
+ Pageflow.config.page_types.to_h do |page_type|
11
+ [page_type.name, page_type.export_version]
12
12
  end
13
13
  end
14
14
 
@@ -19,6 +19,7 @@ module Pageflow
19
19
 
20
20
  create_widgets(revision, data['widgets'])
21
21
  create_revision_components(revision, data['components'])
22
+ create_file_folders(revision, data['file_folders'])
22
23
  create_files(revision, data['file_usages'])
23
24
 
24
25
  revision
@@ -31,6 +32,7 @@ module Pageflow
31
32
 
32
33
  def create_revision(data)
33
34
  revision_attributes = data.except('storylines',
35
+ 'file_folders',
34
36
  'file_usages',
35
37
  'widgets',
36
38
  'components',
@@ -51,6 +53,14 @@ module Pageflow
51
53
  end
52
54
  end
53
55
 
56
+ # File usages refer to their folder by perma id, so folders have to
57
+ # exist before the usages which point at them are created.
58
+ def create_file_folders(revision, file_folders_data)
59
+ file_folders_data.each do |file_folder_data|
60
+ revision.file_folders.create!(file_folder_data.except(*DEFAULT_REMOVAL_COLUMNS))
61
+ end
62
+ end
63
+
54
64
  def create_revision_components(revision, revision_components_data)
55
65
  revision_components_data.each do |component_data|
56
66
  nested_compontents_data = component_data.delete('components')
@@ -10,6 +10,9 @@ module Pageflow
10
10
  widgets: {
11
11
  except: [:subject_id, :subject_type]
12
12
  },
13
+ file_folders: {
14
+ except: [:revision_id]
15
+ },
13
16
  file_usages: {
14
17
  except: [:revision_id],
15
18
  include: {
@@ -0,0 +1,43 @@
1
+ module Pageflow
2
+ # Registry for structured data types that can be used in entries.
3
+ class EntryStructuredDataTypes
4
+ def initialize
5
+ @types = {}
6
+ @default_name = nil
7
+ end
8
+
9
+ # Register a structured data type for entries.
10
+ #
11
+ # @param name [Symbol] The name of the structured data type
12
+ # @param callable [Proc] A lambda that receives a {PublishedEntry} and returns
13
+ # a hash of structured data properties including @type
14
+ # @param options [Hash] Optional configuration
15
+ # @option options [Boolean] :default (false) Set this type as the default
16
+ # when no structured_data_type_name is specified on the entry
17
+ #
18
+ # @example
19
+ # config.entry_structured_data_types.register(:video_object, lambda do |entry|
20
+ # {
21
+ # '@type' => 'VideoObject',
22
+ # videoSection: 'documentary'
23
+ # }
24
+ # end, default: true)
25
+ def register(name, callable, options = {})
26
+ @types[name.to_s] = callable
27
+ @default_name = name.to_s if options[:default]
28
+ end
29
+
30
+ # @api private
31
+ def names
32
+ @types.keys
33
+ end
34
+
35
+ # @api private
36
+ def for(entry)
37
+ structured_data_type =
38
+ @types[entry.structured_data_type_name] || @types[@default_name]
39
+
40
+ structured_data_type ? structured_data_type.call(entry) : {}
41
+ end
42
+ end
43
+ end
@@ -20,6 +20,7 @@ module Pageflow
20
20
  delegate :widget_types, to: :@config
21
21
  delegate :transform_theme_customization_overrides=, to: :@config
22
22
  delegate :transform_theme_customization_files=, to: :@config
23
+ delegate :entry_structured_data_types, to: :@config
23
24
 
24
25
  def plugin(plugin)
25
26
  plugin.configure(self)
@@ -153,8 +153,8 @@ module Pageflow
153
153
 
154
154
  def convert_custom_attributes_option(custom_attributes)
155
155
  if custom_attributes.is_a?(Array)
156
- custom_attributes.each_with_object({}) do |attribute_name, result|
157
- result[attribute_name] = {permitted_create_param: true}
156
+ custom_attributes.to_h do |attribute_name|
157
+ [attribute_name, {permitted_create_param: true}]
158
158
  end
159
159
  elsif custom_attributes.is_a?(Hash)
160
160
  custom_attributes