pageflow 17.0.5 → 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 (636) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +342 -41
  3. data/README.md +3 -5
  4. data/admins/pageflow/accounts.rb +22 -20
  5. data/admins/pageflow/entry.rb +76 -26
  6. data/admins/pageflow/entry_templates.rb +10 -9
  7. data/admins/pageflow/folder.rb +1 -1
  8. data/admins/pageflow/membership.rb +15 -15
  9. data/admins/pageflow/revisions.rb +5 -5
  10. data/admins/pageflow/site_root_entry.rb +64 -0
  11. data/admins/pageflow/sites.rb +12 -3
  12. data/admins/pageflow/translations.rb +75 -0
  13. data/admins/pageflow/user.rb +21 -35
  14. data/app/assets/images/pageflow/admin/icons/comment.svg +1 -0
  15. data/app/assets/javascripts/pageflow/admin/entries.js +30 -5
  16. data/app/assets/javascripts/pageflow/dist/ui.js +4228 -900
  17. data/app/assets/javascripts/pageflow/editor/vendor.js +0 -1
  18. data/app/assets/javascripts/pageflow/ui.js +0 -1
  19. data/app/assets/stylesheets/pageflow/admin/entries/index_table.scss +2 -1
  20. data/app/assets/stylesheets/pageflow/admin/entry_comments_indicator.scss +45 -0
  21. data/app/assets/stylesheets/pageflow/admin/permalink_input.scss +8 -0
  22. data/app/assets/stylesheets/pageflow/admin.scss +1 -0
  23. data/app/assets/stylesheets/pageflow/animations/spin.scss +9 -0
  24. data/app/assets/stylesheets/pageflow/animations.scss +1 -0
  25. data/app/assets/stylesheets/pageflow/editor/background_positioning.scss +27 -5
  26. data/app/assets/stylesheets/pageflow/editor/base.scss +11 -1
  27. data/app/assets/stylesheets/pageflow/editor/drop_down_button.scss +20 -2
  28. data/app/assets/stylesheets/pageflow/editor/edit_configuration_view.scss +5 -0
  29. data/app/assets/stylesheets/pageflow/editor/file_folders.scss +127 -0
  30. data/app/assets/stylesheets/pageflow/editor/file_meta_data.scss +5 -2
  31. data/app/assets/stylesheets/pageflow/editor/file_meta_data_overlay.scss +45 -0
  32. data/app/assets/stylesheets/pageflow/editor/file_preview.scss +138 -0
  33. data/app/assets/stylesheets/pageflow/editor/file_references.scss +68 -0
  34. data/app/assets/stylesheets/pageflow/editor/file_settings_dialog.scss +1 -1
  35. data/app/assets/stylesheets/pageflow/editor/file_stage_icons.scss +17 -0
  36. data/app/assets/stylesheets/pageflow/editor/file_stages.scss +25 -32
  37. data/app/assets/stylesheets/pageflow/editor/file_thumbnails.scss +31 -48
  38. data/app/assets/stylesheets/pageflow/editor/file_type_pills.scss +73 -0
  39. data/app/assets/stylesheets/pageflow/editor/files.scss +242 -50
  40. data/app/assets/stylesheets/pageflow/editor/filtered_files.scss +161 -9
  41. data/app/assets/stylesheets/pageflow/editor/folder_breadcrumb.scss +40 -0
  42. data/app/assets/stylesheets/pageflow/editor/info_box.scss +23 -3
  43. data/app/assets/stylesheets/pageflow/editor/inputs/edit_defaults_button.scss +15 -0
  44. data/app/assets/stylesheets/pageflow/editor/inputs.scss +1 -0
  45. data/app/assets/stylesheets/pageflow/editor/list.scss +89 -37
  46. data/app/assets/stylesheets/pageflow/editor/list_search_field.scss +52 -0
  47. data/app/assets/stylesheets/pageflow/editor/manage_files.scss +9 -0
  48. data/app/assets/stylesheets/pageflow/editor/menu.scss +14 -0
  49. data/app/assets/stylesheets/pageflow/editor/move_to_folder_dialog.scss +83 -0
  50. data/app/assets/stylesheets/pageflow/editor/outline.scss +0 -13
  51. data/app/assets/stylesheets/pageflow/editor/sortable.scss +12 -0
  52. data/app/assets/stylesheets/pageflow/mixins/buttons.scss +4 -4
  53. data/app/assets/stylesheets/pageflow/mixins/pageflow.scss +9 -5
  54. data/app/assets/stylesheets/pageflow/ui/color_picker.scss +230 -0
  55. data/app/assets/stylesheets/pageflow/ui/forms.scss +38 -4
  56. data/app/assets/stylesheets/pageflow/ui/functions.scss +12 -2
  57. data/app/assets/stylesheets/pageflow/ui/input/color_input.scss +9 -8
  58. data/app/assets/stylesheets/pageflow/ui/input/file_name_input.scss +37 -0
  59. data/app/assets/stylesheets/pageflow/ui/input/text_area_input.scss +15 -0
  60. data/app/assets/stylesheets/pageflow/ui/overrides.scss +8 -0
  61. data/app/assets/stylesheets/pageflow/ui/properties.scss +34 -0
  62. data/app/assets/stylesheets/pageflow/ui/tabs_view.scss +8 -3
  63. data/app/assets/stylesheets/pageflow/ui.scss +4 -1
  64. data/app/controllers/concerns/pageflow/controller_delegation.rb +1 -1
  65. data/app/controllers/concerns/pageflow/edit_locking.rb +17 -10
  66. data/app/controllers/concerns/pageflow/entry_password_protection.rb +1 -0
  67. data/app/controllers/concerns/pageflow/public_https_mode.rb +2 -1
  68. data/app/controllers/concerns/pageflow/quota_verification.rb +5 -4
  69. data/app/controllers/pageflow/admin/initial_passwords_controller.rb +1 -0
  70. data/app/controllers/pageflow/application_controller.rb +19 -19
  71. data/app/controllers/pageflow/chapters_controller.rb +3 -2
  72. data/app/controllers/pageflow/edit_locks_controller.rb +3 -2
  73. data/app/controllers/pageflow/editor/encoding_confirmations_controller.rb +1 -0
  74. data/app/controllers/pageflow/editor/entries_controller.rb +3 -1
  75. data/app/controllers/pageflow/editor/entry_publications_controller.rb +1 -0
  76. data/app/controllers/pageflow/editor/file_folders_controller.rb +80 -0
  77. data/app/controllers/pageflow/editor/file_import_controller.rb +4 -3
  78. data/app/controllers/pageflow/editor/files_controller.rb +20 -10
  79. data/app/controllers/pageflow/editor/oembeds_controller.rb +21 -0
  80. data/app/controllers/pageflow/editor/widgets_controller.rb +1 -0
  81. data/app/controllers/pageflow/entries_controller.rb +85 -21
  82. data/app/controllers/pageflow/feeds_controller.rb +1 -1
  83. data/app/controllers/pageflow/files_controller.rb +1 -0
  84. data/app/controllers/pageflow/pages_controller.rb +4 -2
  85. data/app/controllers/pageflow/review/comment_thread_reads_controller.rb +30 -0
  86. data/app/controllers/pageflow/review/comment_threads_controller.rb +60 -0
  87. data/app/controllers/pageflow/review/comments_controller.rb +53 -0
  88. data/app/controllers/pageflow/revisions_controller.rb +5 -1
  89. data/app/controllers/pageflow/sitemaps_controller.rb +1 -1
  90. data/app/controllers/pageflow/storylines_controller.rb +1 -0
  91. data/app/helpers/pageflow/admin/cutoff_modes_helper.rb +12 -0
  92. data/app/helpers/pageflow/admin/entries_helper.rb +41 -1
  93. data/app/helpers/pageflow/admin/entry_translations_helper.rb +18 -0
  94. data/app/helpers/pageflow/admin/features_helper.rb +1 -1
  95. data/app/helpers/pageflow/admin/form_helper.rb +3 -3
  96. data/app/helpers/pageflow/admin/locales_helper.rb +10 -2
  97. data/app/helpers/pageflow/admin/memberships_helper.rb +32 -32
  98. data/app/helpers/pageflow/admin/revisions_helper.rb +1 -1
  99. data/app/helpers/pageflow/admin/sites_helper.rb +22 -0
  100. data/app/helpers/pageflow/admin/users_helper.rb +7 -5
  101. data/app/helpers/pageflow/admin/widgets_helper.rb +5 -5
  102. data/app/helpers/pageflow/asset_urls_helper.rb +1 -1
  103. data/app/helpers/pageflow/audio_files_helper.rb +5 -2
  104. data/app/helpers/pageflow/background_image_helper.rb +7 -6
  105. data/app/helpers/pageflow/common_entry_seed_helper.rb +7 -7
  106. data/app/helpers/pageflow/editor/config_helper.rb +3 -1
  107. data/app/helpers/pageflow/editor/files_helper.rb +1 -1
  108. data/app/helpers/pageflow/embed_code_helper.rb +3 -3
  109. data/app/helpers/pageflow/entries_helper.rb +52 -46
  110. data/app/helpers/pageflow/entry_json_seed_helper.rb +7 -6
  111. data/app/helpers/pageflow/feeds_helper.rb +2 -2
  112. data/app/helpers/pageflow/file_background_images_helper.rb +2 -2
  113. data/app/helpers/pageflow/file_thumbnails_helper.rb +4 -3
  114. data/app/helpers/pageflow/files_helper.rb +5 -4
  115. data/app/helpers/pageflow/folders_helper.rb +8 -5
  116. data/app/helpers/pageflow/help_entries_helper.rb +2 -2
  117. data/app/helpers/pageflow/hreflang_links_helper.rb +37 -0
  118. data/app/helpers/pageflow/info_box_helper.rb +7 -11
  119. data/app/helpers/pageflow/media_query_helper.rb +3 -3
  120. data/app/helpers/pageflow/navigation_bar_helper.rb +1 -1
  121. data/app/helpers/pageflow/overview_helper.rb +1 -1
  122. data/app/helpers/pageflow/page_types_helper.rb +5 -5
  123. data/app/helpers/pageflow/pages_helper.rb +29 -15
  124. data/app/helpers/pageflow/public_i18n_helper.rb +10 -9
  125. data/app/helpers/pageflow/quota_helper.rb +4 -4
  126. data/app/helpers/pageflow/render_json_helper.rb +6 -3
  127. data/app/helpers/pageflow/revision_file_helper.rb +2 -1
  128. data/app/helpers/pageflow/sites_helper.rb +3 -3
  129. data/app/helpers/pageflow/social_share_helper.rb +24 -10
  130. data/app/helpers/pageflow/social_share_links_helper.rb +12 -9
  131. data/app/helpers/pageflow/structured_data_helper.rb +5 -2
  132. data/app/helpers/pageflow/stub_page_configuration.rb +7 -3
  133. data/app/helpers/pageflow/text_direction_helper.rb +1 -1
  134. data/app/helpers/pageflow/themes_helper.rb +2 -4
  135. data/app/helpers/pageflow/video_files_helper.rb +29 -13
  136. data/app/helpers/pageflow/widgets_helper.rb +8 -6
  137. data/app/inputs/pageflow_permalink_input.rb +8 -3
  138. data/app/jobs/pageflow/application_job.rb +1 -0
  139. data/app/jobs/pageflow/entry_export_import/upload_and_publish_file_job.rb +1 -1
  140. data/app/jobs/pageflow/poll_meta_data_from_zencoder_job.rb +1 -0
  141. data/app/jobs/pageflow/poll_zencoder_job.rb +3 -2
  142. data/app/jobs/pageflow/process_image_or_text_track_job.rb +1 -0
  143. data/app/jobs/pageflow/prune_auto_snapshots_job.rb +1 -0
  144. data/app/jobs/pageflow/request_meta_data_from_zencoder_job.rb +1 -0
  145. data/app/jobs/pageflow/submit_file_to_zencoder_job.rb +1 -0
  146. data/app/mailers/pageflow/user_mailer.rb +1 -0
  147. data/app/models/concerns/pageflow/auto_generated_perma_id.rb +20 -1
  148. data/app/models/concerns/pageflow/entry_publication_states.rb +7 -3
  149. data/app/models/concerns/pageflow/feature_target.rb +8 -4
  150. data/app/models/concerns/pageflow/output_source.rb +3 -3
  151. data/app/models/concerns/pageflow/permalinkable.rb +2 -1
  152. data/app/models/concerns/pageflow/reusable_file.rb +24 -24
  153. data/app/models/concerns/pageflow/serialization_blacklist.rb +3 -5
  154. data/app/models/concerns/pageflow/suspendable.rb +5 -3
  155. data/app/models/concerns/pageflow/theme_referencer.rb +1 -1
  156. data/app/models/concerns/pageflow/translatable.rb +62 -0
  157. data/app/models/concerns/pageflow/translated_attributes.rb +101 -0
  158. data/app/models/concerns/pageflow/uploadable_file.rb +6 -6
  159. data/app/models/pageflow/account.rb +6 -5
  160. data/app/models/pageflow/account_member_query.rb +1 -1
  161. data/app/models/pageflow/account_role_query.rb +1 -1
  162. data/app/models/pageflow/application_query.rb +1 -1
  163. data/app/models/pageflow/application_record.rb +1 -1
  164. data/app/models/pageflow/audio_file.rb +4 -4
  165. data/app/models/pageflow/audio_file_url_templates.rb +1 -1
  166. data/app/models/pageflow/authentication_token.rb +2 -2
  167. data/app/models/pageflow/chapter.rb +6 -1
  168. data/app/models/pageflow/chapter_scaffold.rb +2 -4
  169. data/app/models/pageflow/cname_site_request_scope.rb +1 -1
  170. data/app/models/pageflow/comment.rb +30 -0
  171. data/app/models/pageflow/comment_thread.rb +65 -0
  172. data/app/models/pageflow/comment_thread_read.rb +22 -0
  173. data/app/models/pageflow/customized_theme.rb +9 -8
  174. data/app/models/pageflow/draft_entry.rb +49 -9
  175. data/app/models/pageflow/edit_lock.rb +19 -21
  176. data/app/models/pageflow/encoding_confirmation.rb +2 -2
  177. data/app/models/pageflow/entries_feed.rb +2 -2
  178. data/app/models/pageflow/entry.rb +46 -30
  179. data/app/models/pageflow/entry_at_revision.rb +14 -2
  180. data/app/models/pageflow/entry_comment_summary.rb +114 -0
  181. data/app/models/pageflow/entry_duplicate.rb +8 -5
  182. data/app/models/pageflow/entry_publication.rb +2 -2
  183. data/app/models/pageflow/entry_role_query.rb +4 -4
  184. data/app/models/pageflow/entry_template.rb +4 -4
  185. data/app/models/pageflow/entry_title_or_account_name_query.rb +2 -2
  186. data/app/models/pageflow/entry_translation_group.rb +42 -0
  187. data/app/models/pageflow/file_folder.rb +74 -0
  188. data/app/models/pageflow/file_reuse.rb +5 -4
  189. data/app/models/pageflow/file_usage.rb +18 -3
  190. data/app/models/pageflow/folder.rb +2 -2
  191. data/app/models/pageflow/home_button.rb +7 -7
  192. data/app/models/pageflow/image_file.rb +44 -25
  193. data/app/models/pageflow/image_file_url_templates.rb +4 -4
  194. data/app/models/pageflow/invitation_form.rb +2 -1
  195. data/app/models/pageflow/legal_info.rb +38 -0
  196. data/app/models/pageflow/managed_user_query.rb +1 -1
  197. data/app/models/pageflow/membership.rb +5 -5
  198. data/app/models/pageflow/nested_revision_component_copy.rb +263 -0
  199. data/app/models/pageflow/null_user.rb +1 -1
  200. data/app/models/pageflow/overview_button.rb +1 -1
  201. data/app/models/pageflow/page.rb +7 -3
  202. data/app/models/pageflow/permalink.rb +24 -2
  203. data/app/models/pageflow/permalink_directory.rb +7 -0
  204. data/app/models/pageflow/permalink_redirect.rb +7 -0
  205. data/app/models/pageflow/positioned_file.rb +5 -5
  206. data/app/models/pageflow/potential_entry_translations.rb +55 -0
  207. data/app/models/pageflow/potential_memberships.rb +5 -4
  208. data/app/models/pageflow/published_entry.rb +62 -11
  209. data/app/models/pageflow/revision.rb +29 -16
  210. data/app/models/pageflow/roles.rb +14 -18
  211. data/app/models/pageflow/site.rb +46 -3
  212. data/app/models/pageflow/site_root_entry_form.rb +27 -0
  213. data/app/models/pageflow/sitemaps.rb +10 -1
  214. data/app/models/pageflow/storyline.rb +5 -2
  215. data/app/models/pageflow/storyline_scaffold.rb +1 -1
  216. data/app/models/pageflow/text_track_file.rb +1 -1
  217. data/app/models/pageflow/text_track_file_url_templates.rb +1 -1
  218. data/app/models/pageflow/theme_customization_file.rb +3 -2
  219. data/app/models/pageflow/thumbnail_file_resolver.rb +1 -1
  220. data/app/models/pageflow/url_template.rb +1 -1
  221. data/app/models/pageflow/used_file.rb +13 -3
  222. data/app/models/pageflow/user_name_query.rb +2 -2
  223. data/app/models/pageflow/video_file.rb +22 -15
  224. data/app/models/pageflow/video_file_url_templates.rb +6 -4
  225. data/app/models/pageflow/widget.rb +5 -4
  226. data/app/models/pageflow/with_file_usage_extension.rb +1 -1
  227. data/app/models/pageflow/zencoder_attachment.rb +8 -8
  228. data/app/policies/pageflow/account_policy.rb +3 -1
  229. data/app/policies/pageflow/admin/admin_only_tab_policy.rb +1 -0
  230. data/app/policies/pageflow/admin/entry_tab_policy.rb +1 -0
  231. data/app/policies/pageflow/application_policy.rb +2 -0
  232. data/app/policies/pageflow/entry_policy.rb +7 -1
  233. data/app/policies/pageflow/entry_template_policy.rb +2 -1
  234. data/app/policies/pageflow/file_policy.rb +4 -7
  235. data/app/policies/pageflow/folder_policy.rb +18 -8
  236. data/app/policies/pageflow/membership_policy.rb +6 -4
  237. data/app/policies/pageflow/site_policy.rb +10 -3
  238. data/app/policies/pageflow/user_policy.rb +6 -4
  239. data/app/state_machines/pageflow/image_and_text_track_processing_state_machine.rb +3 -2
  240. data/app/state_machines/pageflow/media_encoding_state_machine.rb +5 -4
  241. data/app/views/admin/accounts/_entry_template_details.html.arb +2 -2
  242. data/app/views/admin/entries/_attributes_table.html.arb +6 -5
  243. data/app/views/admin/entries/_form.html.erb +2 -1
  244. data/app/views/admin/entries/_permalink_inputs.html.erb +9 -2
  245. data/app/views/admin/entry_templates/_form.html.erb +1 -3
  246. data/app/views/admin/site_root_entry/choose.html.erb +19 -0
  247. data/app/views/admin/sites/_fields.html.erb +14 -1
  248. data/app/views/admin/translations/_form.html.erb +31 -0
  249. data/app/views/admin/users/_attributes_table.html.arb +13 -0
  250. data/app/views/components/pageflow/admin/add_membership_button.rb +13 -12
  251. data/app/views/components/pageflow/admin/custom_scopes_renderer.rb +1 -0
  252. data/app/views/components/pageflow/admin/embed_code_field.rb +1 -0
  253. data/app/views/components/pageflow/admin/embedded_index_table.rb +9 -10
  254. data/app/views/components/pageflow/admin/entries_tab.rb +1 -0
  255. data/app/views/components/pageflow/admin/entry_publication_state_indicator.rb +6 -5
  256. data/app/views/components/pageflow/admin/entry_templates_tab.rb +2 -1
  257. data/app/views/components/pageflow/admin/entry_translations_tab.rb +102 -0
  258. data/app/views/components/pageflow/admin/entry_user_badge_list.rb +1 -0
  259. data/app/views/components/pageflow/admin/extensible_attributes_table.rb +9 -8
  260. data/app/views/components/pageflow/admin/features_tab.rb +1 -0
  261. data/app/views/components/pageflow/admin/grouped_folder_list.rb +1 -0
  262. data/app/views/components/pageflow/admin/icon_link_to.rb +1 -0
  263. data/app/views/components/pageflow/admin/members_tab.rb +4 -3
  264. data/app/views/components/pageflow/admin/membership_role_with_tooltip.rb +3 -2
  265. data/app/views/components/pageflow/admin/revisions_tab.rb +14 -10
  266. data/app/views/components/pageflow/admin/sites_tab.rb +1 -0
  267. data/app/views/components/pageflow/admin/tabs_view.rb +1 -0
  268. data/app/views/components/pageflow/admin/timestamp.rb +6 -5
  269. data/app/views/components/pageflow/admin/user_account_badge_list.rb +2 -3
  270. data/app/views/components/pageflow/admin/user_accounts_tab.rb +1 -0
  271. data/app/views/components/pageflow/admin/user_entries_tab.rb +1 -0
  272. data/app/views/components/pageflow/admin/users_tab.rb +1 -0
  273. data/app/views/pageflow/audio_files/_audio_file.json.jbuilder +0 -1
  274. data/app/views/pageflow/editor/config/_seeds.json.jbuilder +5 -3
  275. data/app/views/pageflow/editor/entries/_entry.json.jbuilder +2 -1
  276. data/app/views/pageflow/editor/entries/index.json.jbuilder +1 -1
  277. data/app/views/pageflow/editor/entries/seed.json.erb +1 -0
  278. data/app/views/pageflow/editor/entries/show.json.jbuilder +1 -1
  279. data/app/views/pageflow/editor/entry_publications/check.json.jbuilder +2 -2
  280. data/app/views/pageflow/editor/file_folders/_file_folder.json.jbuilder +5 -0
  281. data/app/views/pageflow/editor/file_folders/create.json.jbuilder +1 -0
  282. data/app/views/pageflow/editor/file_folders/index.json.jbuilder +3 -0
  283. data/app/views/pageflow/editor/files/_file.json.jbuilder +7 -14
  284. data/app/views/pageflow/editor/files/create.json.jbuilder +1 -1
  285. data/app/views/pageflow/editor/files/index.json.jbuilder +1 -1
  286. data/app/views/pageflow/editor/image_files/_image_file.json.jbuilder +3 -0
  287. data/app/views/pageflow/editor/sites/_site.json.jbuilder +1 -0
  288. data/app/views/pageflow/editor/video_files/_video_file.json.jbuilder +4 -3
  289. data/app/views/pageflow/entries/share_menu/_bluesky_link.html.erb +8 -0
  290. data/app/views/pageflow/entries/share_menu/_threads_link.html.erb +8 -0
  291. data/app/views/pageflow/files/_file.json.jbuilder +5 -3
  292. data/app/views/pageflow/image_files/_image_file.json.jbuilder +0 -1
  293. data/app/views/pageflow/review/comment_threads/_comment_thread.json.jbuilder +20 -0
  294. data/app/views/pageflow/review/comment_threads/create.json.jbuilder +2 -0
  295. data/app/views/pageflow/review/comment_threads/index.json.jbuilder +13 -0
  296. data/app/views/pageflow/review/comments/_comment.json.jbuilder +13 -0
  297. data/app/views/pageflow/review/comments/create.json.jbuilder +1 -0
  298. data/app/views/pageflow/sitemaps/index.xml.builder +9 -1
  299. data/app/views/pageflow/social_share/_entry_meta_tags.html.erb +1 -1
  300. data/app/views/pageflow/social_share/_page_meta_tags.html.erb +1 -1
  301. data/app/views/pageflow/structured_data/_entry.json.jbuilder +2 -3
  302. data/app/views/pageflow/video_files/_video_file.json.jbuilder +0 -1
  303. data/config/initializers/active_admin_patches.rb +3 -6
  304. data/config/initializers/admin_resource_tabs.rb +3 -0
  305. data/config/initializers/paperclip.rb +1 -0
  306. data/config/initializers/symmetric_encryption.rb +1 -1
  307. data/config/initializers/zencoder.rb +24 -13
  308. data/config/locales/de.yml +256 -12
  309. data/config/locales/en.yml +253 -15
  310. data/config/routes.rb +29 -13
  311. data/config/spring.rb +2 -1
  312. data/db/migrate/20140418225525_setup_schema.rb +2 -2
  313. data/db/migrate/20190306161431_copy_file_attributes_of_failed_uploads.rb +2 -2
  314. data/db/migrate/20190820152900_drop_accounts_themes.rb +2 -1
  315. data/db/migrate/20191202145757_create_pageflow_scrolled_sections.rb +11 -11
  316. data/db/migrate/20191202150657_create_pageflow_scrolled_chapters.rb +1 -1
  317. data/db/migrate/20191202154723_create_pageflow_scrolled_content_elements.rb +9 -9
  318. data/db/migrate/20191219143450_add_position_to_content_elements.rb +2 -1
  319. data/db/migrate/20200117133200_change_revision_appearance_option_default_and_null.rb +2 -1
  320. data/db/migrate/20200122115400_create_pageflow_entry_templates.rb +25 -25
  321. data/db/migrate/20200206134400_convert_legacy_scrolled_content_element_types.rb +3 -3
  322. data/db/migrate/20221215120856_associate_entry_templates_with_sites.rb +2 -2
  323. data/db/migrate/20230120092923_create_other_files.rb +2 -1
  324. data/db/migrate/20230419083307_create_pageflow_entry_translation_group.rb +9 -0
  325. data/db/migrate/20240612110434_add_cutoff_mode_name_to_sites.rb +5 -0
  326. data/db/migrate/20240918084059_create_pageflow_permalink_redirects.rb +14 -0
  327. data/db/migrate/20250508172234_ensure_scrolled_entries_have_main_storyline.rb +14 -0
  328. data/db/migrate/20250617090048_add_custom404_entry_to_sites.rb +5 -0
  329. data/db/migrate/20250617100000_add_perma_id_counter_to_entries.rb +28 -0
  330. data/db/migrate/20250722174123_add_perma_id_to_chapters.rb +10 -0
  331. data/db/migrate/20250725080603_add_perma_id_indexes_to_revision_components.rb +13 -0
  332. data/db/migrate/20250726000000_add_display_name_to_file_usages.rb +5 -0
  333. data/db/migrate/20251015000000_add_structured_data_type_name_to_revisions.rb +5 -0
  334. data/db/migrate/20251029142849_convert_legacy_social_embeds_to_unified_social_embed.rb +38 -0
  335. data/db/migrate/20251119083347_fix_main_storyline_positions.rb +16 -0
  336. data/db/migrate/20251119083348_ensure_scrolled_entries_have_excursion_storyline.rb +15 -0
  337. data/db/migrate/20260303000000_add_layout_version_to_revisions.rb +6 -0
  338. data/db/migrate/20260323000000_create_comment_threads_and_comments.rb +30 -0
  339. data/db/migrate/20260414000000_add_subject_range_to_comment_threads.rb +5 -0
  340. data/db/migrate/20260415000000_add_section_perma_id_to_comment_threads.rb +5 -0
  341. data/db/migrate/20260727000000_add_quote_to_comments.rb +5 -0
  342. data/db/migrate/20260728000000_create_file_folders.rb +17 -0
  343. data/db/migrate/20260805000000_add_attribute_translations_to_sites.rb +5 -0
  344. data/db/migrate/20260806000000_add_edited_at_to_comments.rb +5 -0
  345. data/db/migrate/20260810000000_create_pageflow_scrolled_lottie_files.rb +24 -0
  346. data/db/migrate/20260817000000_create_comment_thread_reads.rb +16 -0
  347. data/db/migrate/20260819000000_add_unread_comments_since_at_to_users.rb +18 -0
  348. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/editor.js +12599 -5398
  349. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/frontend.js +1275 -4560
  350. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/react-client.js +20204 -22
  351. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/react-server.js +18657 -19
  352. data/entry_types/paged/app/controllers/pageflow_paged/entries_controller.rb +1 -0
  353. data/entry_types/paged/app/helpers/pageflow_paged/page_background_asset_helper.rb +1 -1
  354. data/entry_types/paged/app/helpers/pageflow_paged/third_party_embed_consent_helper.rb +7 -7
  355. data/entry_types/paged/app/views/pageflow_paged/editor/entries/_seed.json.jbuilder +1 -0
  356. data/entry_types/paged/app/views/pageflow_paged/entries/show.html.erb +1 -0
  357. data/entry_types/paged/lib/pageflow_paged/plugin.rb +4 -0
  358. data/entry_types/paged/lib/pageflow_paged/react/page_type.rb +1 -1
  359. data/entry_types/paged/lib/pageflow_paged/react/widget_type.rb +3 -3
  360. data/entry_types/paged/lib/pageflow_paged.rb +1 -1
  361. data/entry_types/scrolled/app/assets/stylesheets/pageflow_scrolled/ui.scss +2 -0
  362. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/chapters_controller.rb +5 -3
  363. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/content_elements_controller.rb +35 -5
  364. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/sections_controller.rb +4 -5
  365. data/entry_types/scrolled/app/controllers/pageflow_scrolled/entries_controller.rb +23 -2
  366. data/entry_types/scrolled/app/helpers/pageflow_scrolled/cache_helper.rb +3 -3
  367. data/entry_types/scrolled/app/helpers/pageflow_scrolled/editor/entry_json_seed_helper.rb +8 -5
  368. data/entry_types/scrolled/app/helpers/pageflow_scrolled/editor/seed_html_helper.rb +7 -3
  369. data/entry_types/scrolled/app/helpers/pageflow_scrolled/entry_json_seed_helper.rb +72 -10
  370. data/entry_types/scrolled/app/helpers/pageflow_scrolled/i18n_helper.rb +28 -13
  371. data/entry_types/scrolled/app/helpers/pageflow_scrolled/packs_helper.rb +41 -12
  372. data/entry_types/scrolled/app/helpers/pageflow_scrolled/react_server_side_rendering_helper.rb +23 -25
  373. data/entry_types/scrolled/app/helpers/pageflow_scrolled/sprockets_helper.rb +16 -0
  374. data/entry_types/scrolled/app/helpers/pageflow_scrolled/themes_helper.rb +189 -3
  375. data/entry_types/scrolled/app/models/pageflow_scrolled/chapter.rb +15 -14
  376. data/entry_types/scrolled/app/models/pageflow_scrolled/content_element.rb +61 -7
  377. data/entry_types/scrolled/app/models/pageflow_scrolled/lottie_file.rb +6 -0
  378. data/entry_types/scrolled/app/models/pageflow_scrolled/lottie_file_url_templates.rb +16 -0
  379. data/entry_types/scrolled/app/models/pageflow_scrolled/section.rb +12 -1
  380. data/entry_types/scrolled/app/models/pageflow_scrolled/storyline.rb +20 -1
  381. data/entry_types/scrolled/app/views/pageflow_scrolled/editor/entries/_head.html.erb +1 -0
  382. data/entry_types/scrolled/app/views/pageflow_scrolled/editor/sections/_section_with_content_elements.json.jbuilder +2 -2
  383. data/entry_types/scrolled/app/views/pageflow_scrolled/entries/show.html.erb +15 -12
  384. data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_entry.json.jbuilder +45 -17
  385. data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_entry_translations.json.jbuilder +14 -0
  386. data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_theme.json.jbuilder +34 -5
  387. data/entry_types/scrolled/app/views/pageflow_scrolled/favicons/_entry.html.erb +1 -1
  388. data/entry_types/scrolled/app/views/pageflow_scrolled/storylines/_storyline.json.jbuilder +7 -0
  389. data/entry_types/scrolled/config/configuration_schemas/pageflow-scrolled.json +414 -0
  390. data/entry_types/scrolled/config/locales/de.yml +1094 -78
  391. data/entry_types/scrolled/config/locales/en.yml +1083 -78
  392. data/entry_types/scrolled/config/routes.rb +18 -8
  393. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/install_generator.rb +11 -11
  394. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/logoDarkVariantDesktop.svg +56 -0
  395. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/logoDarkVariantMobile.svg +22 -0
  396. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/themes_plugin.rb.tt +26 -11
  397. data/entry_types/scrolled/lib/pageflow_scrolled/additional_packs.rb +27 -8
  398. data/entry_types/scrolled/lib/pageflow_scrolled/additional_seed_data.rb +2 -2
  399. data/entry_types/scrolled/lib/pageflow_scrolled/additional_theme_assets.rb +27 -0
  400. data/entry_types/scrolled/lib/pageflow_scrolled/configuration.rb +67 -10
  401. data/entry_types/scrolled/lib/pageflow_scrolled/configuration_schemas.rb +91 -0
  402. data/entry_types/scrolled/lib/pageflow_scrolled/content_element_consent_vendors.rb +1 -1
  403. data/entry_types/scrolled/lib/pageflow_scrolled/engine.rb +2 -1
  404. data/entry_types/scrolled/lib/pageflow_scrolled/entry_file_reference_locations.rb +71 -0
  405. data/entry_types/scrolled/lib/pageflow_scrolled/entry_structured_data_types/faq_page.rb +58 -0
  406. data/entry_types/scrolled/lib/pageflow_scrolled/file_reference_locations.rb +69 -0
  407. data/entry_types/scrolled/lib/pageflow_scrolled/plugin.rb +222 -19
  408. data/entry_types/scrolled/lib/pageflow_scrolled/react_widget_type.rb +2 -4
  409. data/entry_types/scrolled/lib/pageflow_scrolled/seeds.rb +76 -54
  410. data/entry_types/scrolled/lib/pageflow_scrolled/theme_options_default_scale.rb +35 -0
  411. data/entry_types/scrolled/lib/pageflow_scrolled.rb +14 -1
  412. data/entry_types/scrolled/lib/tasks/pageflow_scrolled/storybook.rake +24 -5
  413. data/entry_types/scrolled/package/config/configurationSchemas.js +70 -0
  414. data/entry_types/scrolled/package/config/rollup/configurationSchemas.js +19 -0
  415. data/entry_types/scrolled/package/config/webpack.js +94 -0
  416. data/entry_types/scrolled/package/contentElements/hotspots-frontend.css +1 -0
  417. data/entry_types/scrolled/package/contentElements/hotspots-frontend.js +1795 -0
  418. data/entry_types/scrolled/package/contentElements/inlineBeforeAfter-frontend.css +1 -0
  419. data/entry_types/scrolled/package/contentElements/inlineBeforeAfter-frontend.js +219 -0
  420. data/entry_types/scrolled/package/contentElements/lottieAnimation-frontend.css +1 -0
  421. data/entry_types/scrolled/package/contentElements/lottieAnimation-frontend.js +244 -0
  422. data/entry_types/scrolled/package/contentElements/socialEmbed-frontend.css +1 -0
  423. data/entry_types/scrolled/package/contentElements/socialEmbed-frontend.js +823 -0
  424. data/entry_types/scrolled/package/contentElements/tikTokEmbed-frontend.css +1 -0
  425. data/entry_types/scrolled/package/contentElements/tikTokEmbed-frontend.js +109 -0
  426. data/entry_types/scrolled/package/contentElements/twitterEmbed-frontend.css +1 -0
  427. data/entry_types/scrolled/package/contentElements/twitterEmbed-frontend.js +277 -0
  428. data/entry_types/scrolled/package/contentElements/videoEmbed-frontend.css +1 -0
  429. data/entry_types/scrolled/package/contentElements/videoEmbed-frontend.js +244 -0
  430. data/entry_types/scrolled/package/contentElements-editor.js +3155 -583
  431. data/entry_types/scrolled/package/contentElements-frontend.css +1 -1
  432. data/entry_types/scrolled/package/contentElements-frontend.js +3375 -1585
  433. data/entry_types/scrolled/package/editor.css +1 -0
  434. data/entry_types/scrolled/package/editor.js +8452 -2867
  435. data/entry_types/scrolled/package/entryState.js +1600 -0
  436. data/entry_types/scrolled/package/frontend/FloatingPortalRootProvider-20c600de.js +1979 -0
  437. data/entry_types/scrolled/package/frontend/FloatingPortalRootProvider-58189220.js +2538 -0
  438. data/entry_types/scrolled/package/frontend/{PhonePlatformContext-4ec6b2de.js → PhonePlatformContext-035a99fa.js} +9 -15
  439. data/entry_types/scrolled/package/frontend/PhonePlatformContext-9da43797.js +33 -0
  440. data/entry_types/scrolled/package/frontend/Placeholder.module-bf0966b4.js +5267 -0
  441. data/entry_types/scrolled/package/frontend/Placeholder.module-d22a9335.js +4180 -0
  442. data/entry_types/scrolled/package/frontend/ThemeIcon-ab834849.js +754 -0
  443. data/entry_types/scrolled/package/frontend/ThemeIcon-f6cb3a8f.js +773 -0
  444. data/entry_types/scrolled/package/frontend/ToggleFullscreenCornerButton-30fd1124.js +39 -0
  445. data/entry_types/scrolled/package/frontend/ToggleFullscreenCornerButton-61c25224.js +72 -0
  446. data/entry_types/scrolled/package/frontend/Viewer-1074fd59.js +147 -0
  447. data/entry_types/scrolled/package/frontend/Viewer-1482ca34.js +480 -0
  448. data/entry_types/scrolled/package/frontend/Viewer-70504231.js +210 -0
  449. data/entry_types/scrolled/package/frontend/{Viewer-1bb5597c.js → Viewer-cc8d4072.js} +100 -135
  450. data/entry_types/scrolled/package/frontend/Wavesurfer-656e3c36.js +302 -0
  451. data/entry_types/scrolled/package/frontend/Wavesurfer-b753b838.js +385 -0
  452. data/entry_types/scrolled/package/frontend/commenting.css +1 -0
  453. data/entry_types/scrolled/package/frontend/extensions-167ae143.js +1455 -0
  454. data/entry_types/scrolled/package/frontend/extensions-2318f92b.js +5918 -0
  455. data/entry_types/scrolled/package/frontend/extensions-a461fd13.js +4890 -0
  456. data/entry_types/scrolled/package/frontend/extensions-c98269fd.js +1982 -0
  457. data/entry_types/scrolled/package/frontend/i18n-493cd2a6.js +93 -0
  458. data/entry_types/scrolled/package/frontend/i18n-e06cac14.js +100 -0
  459. data/entry_types/scrolled/package/frontend/{index-11f32f10.js → index-2e5546f7.js} +39 -54
  460. data/entry_types/scrolled/package/frontend/index-de2b418d.js +130 -0
  461. data/entry_types/scrolled/package/frontend/index.css +1 -1
  462. data/entry_types/scrolled/package/frontend/index.js +1976 -1367
  463. data/entry_types/scrolled/package/frontend/inlineEditing.css +1 -0
  464. data/entry_types/scrolled/package/frontend/useContentElementEditorState-a084912e.js +25 -0
  465. data/entry_types/scrolled/package/frontend/useDelayedBoolean-a387d85b.js +24 -0
  466. data/entry_types/scrolled/package/frontend/usePhonePlatform-4ecb96d4.js +8 -0
  467. data/entry_types/scrolled/package/frontend/usePhonePlatform-ce9ff08d.js +8 -0
  468. data/entry_types/scrolled/package/frontend-server.js +20 -210
  469. data/entry_types/scrolled/package/package.json +22 -12
  470. data/entry_types/scrolled/package/review.css +1 -0
  471. data/entry_types/scrolled/package/review.js +3306 -0
  472. data/entry_types/scrolled/package/testHelpers.js +952 -239
  473. data/entry_types/scrolled/package/values/widgets.module.css +18 -0
  474. data/entry_types/scrolled/package/widgets/consentBar.css +1 -1
  475. data/entry_types/scrolled/package/widgets/consentBar.js +275 -315
  476. data/entry_types/scrolled/package/widgets/defaultNavigation.css +2 -2
  477. data/entry_types/scrolled/package/widgets/defaultNavigation.js +961 -432
  478. data/entry_types/scrolled/package/widgets/excursionSheet.css +1 -0
  479. data/entry_types/scrolled/package/widgets/excursionSheet.js +225 -0
  480. data/entry_types/scrolled/package/widgets/iconInlineFileRights.css +1 -1
  481. data/entry_types/scrolled/package/widgets/iconInlineFileRights.js +62 -32
  482. data/entry_types/scrolled/package/widgets/iconScrollIndicator.css +1 -0
  483. data/entry_types/scrolled/package/widgets/iconScrollIndicator.js +67 -0
  484. data/entry_types/scrolled/package/widgets/mainStorylineSheet.css +1 -0
  485. data/entry_types/scrolled/package/widgets/mainStorylineSheet.js +100 -0
  486. data/entry_types/scrolled/package/widgets/textInlineFileRights.css +1 -1
  487. data/entry_types/scrolled/package/widgets/textInlineFileRights.js +48 -26
  488. data/entry_types/scrolled/package/widgets-server.js +2 -0
  489. data/entry_types/scrolled/spec/factories/chapters.rb +14 -1
  490. data/entry_types/scrolled/spec/factories/content_elements.rb +1 -1
  491. data/entry_types/scrolled/spec/factories/lottie_files.rb +29 -0
  492. data/entry_types/scrolled/spec/fixtures/animation.lottie +0 -0
  493. data/entry_types/scrolled/spec/fixtures/font.woff +0 -0
  494. data/entry_types/scrolled/spec/fixtures/font.woff2 +0 -0
  495. data/lib/generators/pageflow/active_admin_initializer/active_admin_initializer_generator.rb +5 -3
  496. data/lib/generators/pageflow/assets/assets_generator.rb +7 -5
  497. data/lib/generators/pageflow/cancan/cancan_generator.rb +2 -1
  498. data/lib/generators/pageflow/cancan/templates/ability.rb +1 -1
  499. data/lib/generators/pageflow/error_pages/error_pages_generator.rb +2 -1
  500. data/lib/generators/pageflow/initializer/initializer_generator.rb +3 -2
  501. data/lib/generators/pageflow/install/install_generator.rb +2 -2
  502. data/lib/generators/pageflow/procfile/procfile_generator.rb +2 -1
  503. data/lib/generators/pageflow/resque/resque_generator.rb +4 -4
  504. data/lib/generators/pageflow/resque/templates/resque.rake +1 -1
  505. data/lib/generators/pageflow/routes/routes_generator.rb +4 -2
  506. data/lib/generators/pageflow/seeds/seeds_generator.rb +3 -2
  507. data/lib/generators/pageflow/seeds/templates/seeds.rb +6 -6
  508. data/lib/generators/pageflow/theme/theme_generator.rb +2 -1
  509. data/lib/generators/pageflow/user/user_generator.rb +2 -1
  510. data/lib/pageflow/ability_mixin.rb +25 -15
  511. data/lib/pageflow/active_admin_patches/views/attributes_table.rb +1 -0
  512. data/lib/pageflow/active_admin_patches/views/pages/base.rb +3 -2
  513. data/lib/pageflow/active_admin_patches/views/table_for.rb +1 -0
  514. data/lib/pageflow/additional_headers.rb +27 -0
  515. data/lib/pageflow/admin/attributes_table_rows.rb +3 -3
  516. data/lib/pageflow/admin/tabs.rb +1 -1
  517. data/lib/pageflow/built_in_file_type.rb +1 -1
  518. data/lib/pageflow/built_in_page_types_plugin.rb +1 -1
  519. data/lib/pageflow/built_in_widget_type.rb +2 -2
  520. data/lib/pageflow/built_in_widget_types_plugin.rb +2 -1
  521. data/lib/pageflow/configuration.rb +183 -18
  522. data/lib/pageflow/cutoff_modes.rb +39 -0
  523. data/lib/pageflow/deprecation.rb +19 -0
  524. data/lib/pageflow/editor_controller.rb +6 -10
  525. data/lib/pageflow/engine.rb +5 -6
  526. data/lib/pageflow/entries_controller_env_helper.rb +32 -2
  527. data/lib/pageflow/entry_export_import/attachment_files.rb +1 -1
  528. data/lib/pageflow/entry_export_import/entry_serialization.rb +9 -8
  529. data/lib/pageflow/entry_export_import/file_mappings.rb +1 -0
  530. data/lib/pageflow/entry_export_import/page_type_versions.rb +2 -2
  531. data/lib/pageflow/entry_export_import/revision_serialization/import.rb +11 -1
  532. data/lib/pageflow/entry_export_import/revision_serialization.rb +3 -0
  533. data/lib/pageflow/entry_export_import.rb +3 -3
  534. data/lib/pageflow/entry_structured_data_types.rb +43 -0
  535. data/lib/pageflow/entry_type_configuration.rb +1 -0
  536. data/lib/pageflow/entry_types.rb +2 -2
  537. data/lib/pageflow/feature.rb +1 -1
  538. data/lib/pageflow/features.rb +4 -6
  539. data/lib/pageflow/file_importers.rb +4 -4
  540. data/lib/pageflow/file_type.rb +5 -5
  541. data/lib/pageflow/file_types.rb +4 -4
  542. data/lib/pageflow/global_config_api.rb +5 -6
  543. data/lib/pageflow/help_entries.rb +7 -7
  544. data/lib/pageflow/help_entry.rb +1 -1
  545. data/lib/pageflow/hooks.rb +1 -1
  546. data/lib/pageflow/nested_revision_component.rb +9 -27
  547. data/lib/pageflow/news_item_api.rb +1 -1
  548. data/lib/pageflow/oembed_providers.rb +42 -0
  549. data/lib/pageflow/page_type.rb +2 -3
  550. data/lib/pageflow/page_types.rb +3 -3
  551. data/lib/pageflow/paperclip_interpolations/support.rb +1 -1
  552. data/lib/pageflow/paperclip_processors/vtt.rb +1 -0
  553. data/lib/pageflow/paperclip_processors/webp.rb +2 -2
  554. data/lib/pageflow/partial_editor_fragment_renderer.rb +2 -2
  555. data/lib/pageflow/plugin.rb +1 -2
  556. data/lib/pageflow/primary_domain_entry_redirect.rb +6 -0
  557. data/lib/pageflow/quota.rb +9 -5
  558. data/lib/pageflow/quotas.rb +1 -1
  559. data/lib/pageflow/rails_version.rb +14 -2
  560. data/lib/pageflow/react.rb +1 -1
  561. data/lib/pageflow/revision_component.rb +8 -40
  562. data/lib/pageflow/revision_components.rb +16 -6
  563. data/lib/pageflow/seeds.rb +12 -16
  564. data/lib/pageflow/theme.rb +1 -1
  565. data/lib/pageflow/theme_customizations.rb +10 -10
  566. data/lib/pageflow/themes.rb +44 -3
  567. data/lib/pageflow/user_mixin.rb +18 -6
  568. data/lib/pageflow/version.rb +1 -1
  569. data/lib/pageflow/widget_type.rb +4 -4
  570. data/lib/pageflow/widget_types.rb +9 -9
  571. data/lib/pageflow/zencoder_api.rb +32 -42
  572. data/lib/pageflow/zencoder_audio_output_definition.rb +14 -13
  573. data/lib/pageflow/zencoder_meta_data_output_definition.rb +3 -2
  574. data/lib/pageflow/zencoder_output_definition.rb +16 -14
  575. data/lib/pageflow/zencoder_video_output_definition.rb +140 -88
  576. data/lib/pageflow.rb +8 -2
  577. data/lib/tasks/pageflow_tasks.rake +1 -1
  578. data/package/config/eslint-rules/documented-in-toc.js +125 -0
  579. data/package/config/jest/index.js +0 -1
  580. data/package/config/webpack.js +0 -1
  581. data/package/config/webpack5.js +0 -1
  582. data/package/editor.js +4880 -2313
  583. data/package/frontend.js +710 -1223
  584. data/package/package.json +3 -1
  585. data/package/review.js +384 -0
  586. data/package/testHelpers.js +257 -243
  587. data/package/ui.js +1487 -813
  588. data/package/vendor/stubs/wysihtml5.js +2 -0
  589. data/spec/factories/accounts.rb +37 -22
  590. data/spec/factories/audio_files.rb +2 -2
  591. data/spec/factories/authentication_tokens.rb +4 -4
  592. data/spec/factories/chapters.rb +4 -4
  593. data/spec/factories/comment_thread_reads.rb +10 -0
  594. data/spec/factories/comment_threads.rb +10 -0
  595. data/spec/factories/comments.rb +9 -0
  596. data/spec/factories/draft_entries.rb +14 -6
  597. data/spec/factories/edit_locks.rb +1 -1
  598. data/spec/factories/entries.rb +28 -19
  599. data/spec/factories/entry_translation_groups.rb +6 -0
  600. data/spec/factories/file_folders.rb +8 -0
  601. data/spec/factories/file_usages.rb +2 -1
  602. data/spec/factories/folders.rb +1 -1
  603. data/spec/factories/image_files.rb +2 -2
  604. data/spec/factories/pages.rb +3 -3
  605. data/spec/factories/published_entries.rb +28 -8
  606. data/spec/factories/revisions.rb +1 -1
  607. data/spec/factories/sites.rb +6 -0
  608. data/spec/factories/test_multi_attachment_files.rb +1 -1
  609. data/spec/factories/text_track_files.rb +1 -1
  610. data/spec/factories/uploadable_files.rb +1 -1
  611. data/spec/factories/users.rb +6 -6
  612. data/spec/factories/video_files.rb +2 -2
  613. data/spec/factories/widgets.rb +1 -1
  614. data/spec/fixtures/7x15_rotated.jpg +0 -0
  615. data/vendor/assets/javascripts/wysihtml-toolbar.js +19288 -0
  616. metadata +266 -92
  617. data/app/assets/stylesheets/pageflow/editor/select_button.scss +0 -51
  618. data/config/initializers/revision_components.rb +0 -5
  619. data/config/locales/twitter_to_x.de.yml +0 -6
  620. data/config/locales/twitter_to_x.en.yml +0 -6
  621. data/entry_types/scrolled/app/helpers/pageflow_scrolled/generated_media_queries_helper.rb +0 -55
  622. data/entry_types/scrolled/config/locales/twitter_to_x.de.yml +0 -12
  623. data/entry_types/scrolled/config/locales/twitter_to_x.en.yml +0 -12
  624. data/entry_types/scrolled/config/locales/vr_image_projection.de.yml +0 -24
  625. data/entry_types/scrolled/config/locales/vr_image_projection.en.yml +0 -24
  626. data/entry_types/scrolled/package/frontend/EditableInlineText.module-ebd22921.js +0 -5497
  627. data/entry_types/scrolled/package/frontend/ToggleFullscreenCornerButton-b79159cc.js +0 -107
  628. data/entry_types/scrolled/package/frontend/Viewer-1ecf3375.js +0 -154
  629. data/entry_types/scrolled/package/frontend/Wavesurfer-7d9cf1b7.js +0 -333
  630. data/entry_types/scrolled/package/frontend/arrowRight-62998af9.js +0 -77
  631. data/entry_types/scrolled/package/frontend/components-024a9893.js +0 -2853
  632. data/entry_types/scrolled/package/frontend/createSuper-d0f30da3.js +0 -115
  633. data/entry_types/scrolled/package/frontend/i18n-ce13a8bf.js +0 -1129
  634. data/entry_types/scrolled/package/frontend/useContentElementEditorState-4f4c3cf6.js +0 -52
  635. data/lib/generators/pageflow/resque/templates/resque_enqueue_after_commit_patch.rb +0 -25
  636. data/package/vendor/jquery.minicolors.js +0 -1108
@@ -1,35 +1,56 @@
1
1
  import $ from 'jquery';
2
2
  import _ from 'underscore';
3
- import { Object as Object$1 } from 'pageflow/ui';
3
+ import { Object } from 'pageflow/ui';
4
+ import { within } from '@testing-library/dom';
4
5
  import Backbone from 'backbone';
5
- import { Entry, Theme, FileTypes, FilesCollection, SubsetCollection, ImageFile, WidgetTypes, EditorApi, WidgetsCollection, VideoFile, TextTrackFile } from 'pageflow/editor';
6
- import { browser } from 'pageflow/frontend';
6
+ import { Entry, Theme, FileTypes, FilesCollection, SubsetCollection, ImageFile, WidgetTypes, EditorApi, FileFoldersCollection, WidgetsCollection, VideoFile, TextTrackFile } from 'pageflow/editor';
7
+ import { ReviewSession } from 'pageflow/review';
8
+ import { browser, features } from 'pageflow/frontend';
7
9
  import I18n from 'i18n-js';
8
10
 
9
- var Base = Object$1.extend({
10
- initialize: function initialize($el) {
11
- this.$el = $el;
11
+ let container;
12
+ afterEach(() => {
13
+ if (container) {
14
+ container.remove();
15
+ container = null;
12
16
  }
13
17
  });
18
+ function ensureContainer() {
19
+ if (!container) {
20
+ container = document.createElement('div');
21
+ document.body.appendChild(container);
22
+ }
23
+ }
24
+ function renderBackboneView(view) {
25
+ ensureContainer();
26
+ view.render();
27
+ container.appendChild(view.el);
28
+ if (view.onShow) {
29
+ view.onShow();
30
+ }
31
+ return within(view.el);
32
+ }
14
33
 
34
+ const Base = Object.extend({
35
+ initialize: function ($el) {
36
+ this.$el = $el;
37
+ }
38
+ });
15
39
  Base.classMethods = function (Constructor) {
16
40
  return {
17
- find: function find(viewOrParentElement) {
41
+ find: function (viewOrParentElement) {
18
42
  var selector = Constructor.prototype.selector;
19
43
  var parentElement = viewOrParentElement.$el || viewOrParentElement;
20
44
  var element = parentElement.find(selector);
21
-
22
45
  if (element.length > 1) {
23
46
  throw new Error('Selector "' + selector + '" matches multiple elements in view. Expected only one');
24
47
  }
25
-
26
48
  if (element.length === 0) {
27
49
  throw new Error('Selector "' + selector + '" did not match any elements in view.');
28
50
  }
29
-
30
51
  return new Constructor(element);
31
52
  },
32
- findAll: function findAll(viewOrParentElement) {
53
+ findAll: function (viewOrParentElement) {
33
54
  var selector = Constructor.prototype.selector;
34
55
  var parentElement = viewOrParentElement.$el || viewOrParentElement;
35
56
  var elements = parentElement.find(selector);
@@ -37,7 +58,7 @@ Base.classMethods = function (Constructor) {
37
58
  return new Constructor($(this));
38
59
  }).get();
39
60
  },
40
- findBy: function findBy(predicate, options) {
61
+ findBy: function (predicate, options) {
41
62
  var predicateString = options.predicateName ? ' filtered by ' + options.predicateName : '';
42
63
  var selector = Constructor.prototype.selector;
43
64
  var selectorString = 'Selector "' + selector + '"' + predicateString;
@@ -45,119 +66,126 @@ Base.classMethods = function (Constructor) {
45
66
  var element = elements.filter(function () {
46
67
  return predicate($(this));
47
68
  });
48
-
49
69
  if (element.length > 1) {
50
70
  throw new Error(selectorString + ' matches multiple elements in view. Expected only one');
51
71
  }
52
-
53
72
  if (element.length === 0) {
54
73
  throw new Error(selectorString + ' did not match any elements in view.');
55
74
  }
56
-
57
75
  return new Constructor(element);
58
76
  },
59
- render: function render(view, options) {
60
- view.render();
61
-
62
- if (options && options.appendTo) {
63
- options.appendTo.append(view.$el);
64
- }
65
-
77
+ render: function (view) {
78
+ renderBackboneView(view);
66
79
  return new Constructor(view.$el);
67
80
  }
68
81
  };
69
82
  };
70
-
71
- Base.extend = function () {
72
- var result = Object$1.extend.apply(this, arguments);
73
-
83
+ Base.extend = function /* arguments */
84
+ () {
85
+ var result = Object.extend.apply(this, arguments);
74
86
  _.extend(result, Base.classMethods(result));
75
-
76
87
  return result;
77
88
  };
78
89
 
79
- var DropDownButton = Base.extend({
90
+ const DropDownButton = Base.extend({
80
91
  selector: '.drop_down_button',
81
- menuItemNames: function menuItemNames() {
82
- return this.$el.find('li').map(function () {
92
+ menuItemNames: function () {
93
+ return this.$el.find('li:not(.is_hidden)').map(function () {
83
94
  return $(this).data('name');
84
95
  }).get();
85
96
  },
86
- menuItemLabels: function menuItemLabels() {
87
- return this.$el.find('li a').map(function () {
97
+ menuItemLabels: function () {
98
+ return this.$el.find('li:not(.is_hidden) a').map(function () {
88
99
  return $(this).text();
89
100
  }).get();
90
101
  },
91
- selectMenuItemByName: function selectMenuItemByName(name) {
92
- var menuItem = this.$el.find('li').filter(function () {
102
+ selectMenuItemByName: function (name) {
103
+ var menuItem = this.$el.find('li:not(.is_hidden)').filter(function () {
93
104
  return $(this).data('name') == name;
94
105
  });
95
-
96
106
  if (!menuItem.length) {
97
107
  throw new Error('Could not find menu item with name "' + name + '"');
98
108
  }
99
-
100
109
  menuItem.find('a').trigger('click');
101
110
  },
102
- selectMenuItemByLabel: function selectMenuItemByLabel(label) {
103
- var menuItemLink = this.$el.find('li a').filter(function () {
111
+ selectMenuItemByLabel: function (label) {
112
+ var menuItemLink = this.$el.find('li:not(.is_hidden) a').filter(function () {
104
113
  return $(this).text() == label;
105
114
  });
106
-
107
115
  if (!menuItemLink.length) {
108
116
  throw new Error('Could not find menu item with label "' + label + '"');
109
117
  }
110
-
111
118
  menuItemLink.trigger('click');
112
119
  }
113
120
  });
114
121
 
115
- var FileMetaDataTable = Base.extend({
122
+ const FileMetaDataTable = Base.extend({
116
123
  selector: '.file_meta_data table',
117
- values: function values() {
124
+ values: function () {
118
125
  return this.$el.find('.value').map(function () {
119
126
  return $(this).text();
120
127
  }).get();
121
128
  }
122
129
  });
123
130
 
124
- var FileStageItem = Base.extend({
131
+ const FileStageItem = Base.extend({
125
132
  selector: '.file_stage_item'
126
133
  });
127
134
 
128
- var FileThumbnail = Base.extend({
135
+ const FileThumbnail = Base.extend({
129
136
  selector: '.file_thumbnail',
130
- backgroundImage: function backgroundImage() {
137
+ backgroundImage: function () {
131
138
  return this.$el.css('backgroundImage');
132
139
  }
133
140
  });
134
141
 
135
- var ReferenceInput = Base.extend({
136
- clickChooseButton: function clickChooseButton() {
142
+ const Base$1 = Base.extend({
143
+ selector: '.input'
144
+ });
145
+ Base$1.findByPropertyName = function (propertyName, {
146
+ visible,
147
+ ...options
148
+ } = {}) {
149
+ return this.findBy(el => el.data('inputPropertyName') === propertyName && (!visible || !el.hasClass('hidden_via_binding')), {
150
+ predicateName: `${visible ? 'visible ' : ''}input property name '${propertyName}'`,
151
+ ...options
152
+ });
153
+ };
154
+
155
+ const FileInput = Base$1.extend({
156
+ menuItemNames: function () {
157
+ return DropDownButton.find(this.$el).menuItemNames();
158
+ },
159
+ selectMenuItemByName: function (name) {
160
+ DropDownButton.find(this.$el).selectMenuItemByName(name);
161
+ }
162
+ });
163
+
164
+ const ReferenceInput = Base.extend({
165
+ clickChooseButton: function () {
137
166
  this.$el.find('.choose').trigger('click');
138
167
  }
139
168
  });
140
169
 
141
- var StaticThumbnail = Base.extend({
170
+ const StaticThumbnail = Base.extend({
142
171
  selector: '.static_thumbnail',
143
- backgroundImage: function backgroundImage() {
172
+ backgroundImage: function () {
144
173
  return this.$el.css('backgroundImage');
145
174
  }
146
175
  });
147
176
 
148
- var ThemeItem = Base.extend({
177
+ const ThemeItem = Base.extend({
149
178
  selector: '.theme_item',
150
- hover: function hover() {
179
+ hover: function () {
151
180
  this.$el.trigger('mouseenter');
152
181
  },
153
- click: function click() {
182
+ click: function () {
154
183
  this.$el.trigger('click');
155
184
  },
156
- clickUseButton: function clickUseButton() {
185
+ clickUseButton: function () {
157
186
  this.$el.find('.use_theme').trigger('click');
158
187
  }
159
188
  });
160
-
161
189
  ThemeItem.findByName = function (themeName, options) {
162
190
  return this.findBy(function ($el) {
163
191
  return $el.data('themeName') === themeName;
@@ -166,180 +194,103 @@ ThemeItem.findByName = function (themeName, options) {
166
194
  }, options));
167
195
  };
168
196
 
169
- var ConfigurationEditorTab = Base.extend({
197
+ const ConfigurationEditorTab = Base.extend({
170
198
  selector: '.configuration_editor_tab',
171
- inputPropertyNames: function inputPropertyNames() {
199
+ inputPropertyNames: function () {
172
200
  return this.$el.find('.input').map(function () {
173
201
  return $(this).data('inputPropertyName');
174
202
  }).get();
175
203
  },
176
- visibleInputPropertyNames: function visibleInputPropertyNames() {
204
+ visibleInputPropertyNames: function () {
177
205
  return this.$el.find('.input:not(.hidden_via_binding)').map(function () {
178
206
  return $(this).data('inputPropertyName');
179
207
  }).get();
180
208
  },
181
- inputLabels: function inputLabels() {
209
+ inputLabels: function () {
182
210
  return this.$el.find('.input').map(function () {
183
211
  return $(this).data('labelText');
184
212
  }).get();
185
213
  },
186
- inlineHelpTexts: function inlineHelpTexts() {
214
+ inlineHelpTexts: function () {
187
215
  return this.$el.find('.input').map(function () {
188
216
  return $(this).data('inlineHelpText');
189
217
  }).get();
190
218
  }
191
219
  });
192
220
 
193
- var Tabs = Base.extend({
221
+ const Tabs = Base.extend({
194
222
  selector: '.tabs_view',
195
- tabNames: function tabNames() {
223
+ tabNames: function () {
196
224
  return this.$el.find('[data-tab-name]').map(function () {
197
225
  return $(this).data('tabName');
198
226
  }).get();
199
227
  },
200
- tabLabels: function tabLabels() {
228
+ tabLabels: function () {
201
229
  return this.$el.find('[data-tab-name]').map(function () {
202
230
  return $(this).text();
203
231
  }).get();
204
232
  }
205
233
  });
206
234
 
207
- var ConfigurationEditor = Base.extend({
235
+ const ConfigurationEditor = Base.extend({
208
236
  selector: '.configuration_editor',
209
- tabNames: function tabNames() {
237
+ tabNames: function () {
210
238
  return Tabs.find(this.$el).tabNames();
211
239
  },
212
- tabLabels: function tabLabels() {
240
+ tabLabels: function () {
213
241
  return Tabs.find(this.$el).tabLabels();
214
242
  },
215
- inputPropertyNames: function inputPropertyNames() {
243
+ inputPropertyNames: function () {
216
244
  return ConfigurationEditorTab.find(this.$el).inputPropertyNames();
217
245
  },
218
- visibleInputPropertyNames: function visibleInputPropertyNames() {
246
+ visibleInputPropertyNames: function () {
219
247
  return ConfigurationEditorTab.find(this.$el).visibleInputPropertyNames();
220
248
  },
221
- inputLabels: function inputLabels() {
249
+ inputLabels: function () {
222
250
  return ConfigurationEditorTab.find(this.$el).inputLabels();
223
251
  },
224
- inlineHelpTexts: function inlineHelpTexts() {
252
+ inlineHelpTexts: function () {
225
253
  return ConfigurationEditorTab.find(this.$el).inlineHelpTexts();
226
254
  }
227
255
  });
228
256
 
229
- var Table = Base.extend({
257
+ const Table = Base.extend({
230
258
  selector: '.table_view',
231
- columnNames: function columnNames() {
259
+ columnNames: function () {
232
260
  return this.$el.find('th').map(function () {
233
261
  return $(this).data('columnName');
234
262
  }).get();
235
263
  }
236
264
  });
237
265
 
238
- var ColorInput = Base.extend({
239
- value: function value() {
240
- return this._input().val();
241
- },
242
- fillIn: function fillIn(value, clock) {
243
- this._input().val(value);
244
-
245
- this._input().trigger('keyup');
246
-
247
- clock.tick(500);
248
- },
249
- swatches: function swatches() {
250
- return this.$el.find('.minicolors-swatches span').map(function () {
251
- return window.getComputedStyle(this)['background-color'];
252
- }).get();
253
- },
254
- _input: function _input() {
255
- return this.$el.find('input');
256
- }
257
- });
258
-
259
- function _defineProperty(obj, key, value) {
260
- if (key in obj) {
261
- Object.defineProperty(obj, key, {
262
- value: value,
263
- enumerable: true,
264
- configurable: true,
265
- writable: true
266
- });
267
- } else {
268
- obj[key] = value;
269
- }
270
-
271
- return obj;
272
- }
273
-
274
- function ownKeys(object, enumerableOnly) {
275
- var keys = Object.keys(object);
276
-
277
- if (Object.getOwnPropertySymbols) {
278
- var symbols = Object.getOwnPropertySymbols(object);
279
- if (enumerableOnly) symbols = symbols.filter(function (sym) {
280
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
281
- });
282
- keys.push.apply(keys, symbols);
283
- }
284
-
285
- return keys;
286
- }
287
-
288
- function _objectSpread2(target) {
289
- for (var i = 1; i < arguments.length; i++) {
290
- var source = arguments[i] != null ? arguments[i] : {};
291
-
292
- if (i % 2) {
293
- ownKeys(Object(source), true).forEach(function (key) {
294
- _defineProperty(target, key, source[key]);
295
- });
296
- } else if (Object.getOwnPropertyDescriptors) {
297
- Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
298
- } else {
299
- ownKeys(Object(source)).forEach(function (key) {
300
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
301
- });
302
- }
303
- }
304
-
305
- return target;
306
- }
307
-
308
- var Base$1 = Base.extend({
309
- selector: '.input'
310
- });
311
-
312
- Base$1.findByPropertyName = function (propertyName, options) {
313
- return this.findBy(function (el) {
314
- return el.data('inputPropertyName') === propertyName;
315
- }, _objectSpread2({
316
- predicateName: "input property name '".concat(propertyName, "'")
317
- }, options));
318
- };
319
-
320
- var RadioButtonGroupInput = Base$1.extend({
321
- values: function values() {
266
+ const RadioButtonGroupInput = Base$1.extend({
267
+ values: function () {
322
268
  return this.$el.find('input').map(function () {
323
269
  return $(this).attr('value');
324
270
  }).get();
325
271
  },
326
- enabledValues: function enabledValues() {
272
+ enabledValues: function () {
327
273
  return this.$el.find('input:not([disabled])').map(function () {
328
274
  return $(this).attr('value');
329
275
  }).get();
330
276
  }
331
277
  });
332
278
 
333
- var SelectInput = Base$1.extend({
334
- value: function value() {
279
+ const SelectInput = Base$1.extend({
280
+ value: function () {
335
281
  return this.$el.find('select').val();
336
282
  },
337
- values: function values() {
283
+ values: function () {
338
284
  return this.$el.find('option').map(function () {
339
285
  return $(this).attr('value');
340
286
  }).get();
341
287
  },
342
- enabledValues: function enabledValues() {
288
+ texts: function () {
289
+ return this.$el.find('option').map(function () {
290
+ return $(this).text();
291
+ }).get();
292
+ },
293
+ enabledValues: function () {
343
294
  return this.$el.find('option:not([disabled])').map(function () {
344
295
  return $(this).attr('value');
345
296
  }).get();
@@ -349,8 +300,7 @@ var SelectInput = Base$1.extend({
349
300
  /**
350
301
  * Build editor Backbone models for tests.
351
302
  */
352
-
353
- var factories = {
303
+ const factories = {
354
304
  /**
355
305
  * Build an entry model.
356
306
  *
@@ -375,33 +325,65 @@ var factories = {
375
325
  * }
376
326
  * });
377
327
  */
378
- entry: function entry(model, attributes) {
379
- var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
380
-
328
+ entry: function entry(model, attributes, options = {}) {
381
329
  if (typeof model !== 'function') {
382
330
  return factories.entry(Entry, model, attributes);
383
331
  }
384
-
385
332
  ensureFileTypes(options);
386
333
  ensureFilesCollections(options);
334
+ ensureFileFoldersCollection(options);
387
335
  ensureWidgetsCollections(options);
388
- var entry = new model(_objectSpread2({
389
- id: 1
390
- }, attributes), _.extend({
336
+ const entry = new model({
337
+ id: 1,
338
+ ...attributes
339
+ }, _.extend({
391
340
  storylines: new Backbone.Collection(),
392
341
  chapters: new Backbone.Collection()
393
342
  }, options));
394
-
395
343
  if (entry.setupFromEntryTypeSeed && options.entryTypeSeed) {
396
344
  entry.setupFromEntryTypeSeed(options.entryTypeSeed);
397
345
  }
398
-
399
346
  return entry;
400
347
  },
401
348
  theme: function theme(attributes, options) {
402
349
  return new Theme(attributes, options);
403
350
  },
404
-
351
+ /**
352
+ * Build a real `ReviewSession` pre-populated with state — suitable for
353
+ * Backbone view specs that would otherwise stub out the session.
354
+ *
355
+ * Commenting UI is always gated on a signed-in user; the `currentUser`
356
+ * default reflects that. Specs override it only when they care about
357
+ * the current user's identity (permissions, ownership, etc.).
358
+ *
359
+ * @param {Object} [options]
360
+ * @param {Object} [options.currentUser] - Current user exposed via `session.state.currentUser`.
361
+ * @param {Array} [options.commentThreads] - Seed threads exposed via `session.state.commentThreads`.
362
+ * @param {Object} [options.entryId] - Entry id used when constructing request URLs.
363
+ * @param {Function} [options.request] - Override the request function. Defaults to a jest mock resolving to the seeded state.
364
+ * @returns {ReviewSession}
365
+ */
366
+ reviewSession: function reviewSession({
367
+ currentUser = {
368
+ id: 1,
369
+ name: 'Test User'
370
+ },
371
+ commentThreads = [],
372
+ entryId = 1,
373
+ request
374
+ } = {}) {
375
+ return new ReviewSession({
376
+ entryId,
377
+ request: request || jest.fn().mockResolvedValue({
378
+ currentUser,
379
+ commentThreads
380
+ }),
381
+ initialState: {
382
+ currentUser,
383
+ commentThreads
384
+ }
385
+ });
386
+ },
405
387
  /**
406
388
  * Construct a file type registry that can be passed to {@link
407
389
  * #factoriesentry factories.entry}.
@@ -416,11 +398,11 @@ var factories = {
416
398
  * @param {Function} fn - Build function.
417
399
  * @returns {FileTypes} - A file Type registry
418
400
  */
419
- fileTypes: function fileTypes(fn) {
401
+ fileTypes: function (fn) {
420
402
  var fileTypes = new FileTypes();
421
403
  var fileTypesSetupArray = [];
422
404
  var builder = {
423
- withImageFileType: function withImageFileType(options) {
405
+ withImageFileType: function (options) {
424
406
  fileTypes.register('image_files', _.extend({
425
407
  model: ImageFile,
426
408
  matchUpload: /^image/,
@@ -433,7 +415,7 @@ var factories = {
433
415
  });
434
416
  return this;
435
417
  },
436
- withVideoFileType: function withVideoFileType(options) {
418
+ withVideoFileType: function (options) {
437
419
  fileTypes.register('video_files', _.extend({
438
420
  model: VideoFile,
439
421
  matchUpload: /^video/,
@@ -449,7 +431,7 @@ var factories = {
449
431
  });
450
432
  return this;
451
433
  },
452
- withAudioFileType: function withAudioFileType(options) {
434
+ withAudioFileType: function (options) {
453
435
  fileTypes.register('audio_files', _.extend({
454
436
  model: VideoFile,
455
437
  matchUpload: /^audio/,
@@ -465,7 +447,7 @@ var factories = {
465
447
  });
466
448
  return this;
467
449
  },
468
- withTextTrackFileType: function withTextTrackFileType(options) {
450
+ withTextTrackFileType: function (options) {
469
451
  fileTypes.register('text_track_files', _.extend({
470
452
  model: TextTrackFile,
471
453
  matchUpload: /vtt$/
@@ -482,7 +464,6 @@ var factories = {
482
464
  fileTypes.setup(fileTypesSetupArray);
483
465
  return fileTypes;
484
466
  },
485
-
486
467
  /**
487
468
  * Shorthand for calling {@link #factoriesfiletypes
488
469
  * factories.fileTypes} with a builder function that calls
@@ -491,26 +472,26 @@ var factories = {
491
472
  * @param {Object} options - File type options passed to withImageFileType,
492
473
  * @returns {FileTypes} - A file Type registry.
493
474
  */
494
- fileTypesWithImageFileType: function fileTypesWithImageFileType(options) {
475
+ fileTypesWithImageFileType: function (options) {
495
476
  return this.fileTypes(function () {
496
477
  this.withImageFileType(options);
497
478
  });
498
479
  },
499
- imageFileType: function imageFileType(options) {
480
+ imageFileType: function (options) {
500
481
  return factories.fileTypesWithImageFileType(options).first();
501
482
  },
502
- fileType: function fileType(options) {
483
+ fileType: function (options) {
503
484
  return factories.imageFileType(options);
504
485
  },
505
- filesCollection: function filesCollection(options) {
486
+ filesCollection: function (options) {
506
487
  return FilesCollection.createForFileType(options.fileType, [{}, {}]);
507
488
  },
508
- nestedFilesCollection: function nestedFilesCollection(options) {
489
+ nestedFilesCollection: function (options) {
509
490
  return new SubsetCollection({
510
491
  parentModel: factories.file({
511
492
  file_name: options.parentFileName
512
493
  }),
513
- filter: function filter() {
494
+ filter: function () {
514
495
  return true;
515
496
  },
516
497
  parent: factories.filesCollection({
@@ -518,7 +499,7 @@ var factories = {
518
499
  })
519
500
  });
520
501
  },
521
- videoFileWithTextTrackFiles: function videoFileWithTextTrackFiles(options) {
502
+ videoFileWithTextTrackFiles: function (options) {
522
503
  var fileTypes = this.fileTypes(function () {
523
504
  this.withVideoFileType(options.videoFileTypeOptions);
524
505
  this.withTextTrackFileType(options.textTrackFileTypeOptions);
@@ -548,7 +529,7 @@ var factories = {
548
529
  textTrackFiles: textTrackFiles
549
530
  };
550
531
  },
551
- imageFilesFixture: function imageFilesFixture(options) {
532
+ imageFilesFixture: function (options) {
552
533
  var fileTypes = this.fileTypes(function () {
553
534
  this.withImageFileType(options.fileTypeOptions);
554
535
  });
@@ -569,49 +550,44 @@ var factories = {
569
550
  imageFiles: imageFiles
570
551
  };
571
552
  },
572
- imageFile: function imageFile(attributes, options) {
553
+ imageFile: function (attributes, options) {
573
554
  return new ImageFile(attributes, _.extend({
574
555
  fileType: this.imageFileType()
575
556
  }, options));
576
557
  },
577
- file: function file(attributes, options) {
558
+ file: function (attributes, options) {
578
559
  return this.imageFile(attributes, options);
579
560
  },
580
- widgetTypes: function widgetTypes(attributesList, beforeSetup) {
561
+ widgetTypes: function (attributesList, beforeSetup) {
581
562
  var widgetTypes = new WidgetTypes();
582
563
  var attributesListsByRole = {};
583
-
584
564
  _(attributesList).each(function (attributes) {
585
565
  attributesListsByRole[attributes.role] = attributesListsByRole[attributes.role] || [];
586
566
  attributesListsByRole[attributes.role].push(_.extend({
587
567
  translationKey: 'widget_name.' + attributes.name
588
568
  }, attributes));
589
569
  });
590
-
591
570
  if (beforeSetup) {
592
571
  beforeSetup(widgetTypes);
593
572
  }
594
-
595
573
  widgetTypes.setup(attributesListsByRole);
596
574
  return widgetTypes;
597
575
  },
598
- editorApi: function editorApi(beforeSetup) {
576
+ editorApi: function (beforeSetup) {
599
577
  var api = new EditorApi({
600
578
  router: {
601
- navigate: function navigate(path, _ref) {
602
- var trigger = _ref.trigger;
603
-
579
+ navigate(path, {
580
+ trigger
581
+ }) {
604
582
  if (trigger) {
605
583
  api.trigger('navigate', path);
606
584
  }
607
585
  }
608
586
  }
609
587
  });
610
-
611
588
  if (beforeSetup) {
612
589
  beforeSetup(api);
613
590
  }
614
-
615
591
  api.pageTypes.setup(_.map(api.pageTypes.clientSideConfigs, function (config, name) {
616
592
  return {
617
593
  name: name,
@@ -624,27 +600,31 @@ var factories = {
624
600
  return api;
625
601
  }
626
602
  };
627
-
628
603
  function ensureFileTypes(options) {
629
604
  if (!options.fileTypes) {
630
605
  options.fileTypes = new FileTypes();
631
606
  options.fileTypes.setup([]);
632
607
  }
633
608
  }
634
-
635
609
  function ensureFilesCollections(options) {
636
610
  if (!options.files) {
637
611
  options.files = FilesCollection.createForFileTypes(options.fileTypes, options.filesAttributes);
638
612
  }
639
613
  }
640
-
614
+ function ensureFileFoldersCollection(options) {
615
+ if (!options.fileFolders) {
616
+ options.fileFolders = new FileFoldersCollection(options.fileFoldersAttributes);
617
+ }
618
+ }
641
619
  function ensureWidgetsCollections(options) {
642
620
  if (!options.widgets) {
643
- options.widgets = new WidgetsCollection(options.widgetsAttributes);
621
+ options.widgets = new WidgetsCollection(options.widgetsAttributes, {
622
+ widgetTypes: options.widgetTypes
623
+ });
644
624
  }
645
625
  }
646
626
 
647
- var userAgents = {
627
+ const userAgents = {
648
628
  'Safari on iPhone': 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_1 like Mac OS X) ' + 'AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0' + 'Mobile/14A403 Safari/602.1',
649
629
  'Safari on macOS': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14) ' + 'AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 ' + 'Safari/605.1.15',
650
630
  'Chrome on Android': 'Mozilla/5.0 (Linux; Android 10) ' + 'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106' + 'Mobile Safari/537.36',
@@ -653,13 +633,12 @@ var userAgents = {
653
633
  };
654
634
  function fakeBrowserAgent(name) {
655
635
  if (!userAgents[name]) {
656
- throw new Error("Unknown browser ".concat(name, "."));
636
+ throw new Error(`Unknown browser ${name}.`);
657
637
  }
658
-
659
638
  return new browser.Agent(userAgents[name]);
660
639
  }
661
640
 
662
- var state = window.pageflow || {};
641
+ const state = window.pageflow || {};
663
642
 
664
643
  /**
665
644
  * Setup global state for testing Backbone editor components.
@@ -673,42 +652,83 @@ var state = window.pageflow || {};
673
652
  * Properties to set on the global state. Functions as values will
674
653
  * be evaluated and the return value will be assigned instead.
675
654
  */
676
-
677
- var setupGlobals = function setupGlobals(mapping) {
678
- var globalsBackup;
679
- beforeEach(function () {
655
+ const setupGlobals = function (mapping) {
656
+ let globalsBackup;
657
+ beforeEach(() => {
680
658
  if (globalsBackup) {
681
659
  throw new Error('There can only be one setupGlobals call per test.');
682
660
  }
683
-
684
661
  globalsBackup = {};
685
662
  setGlobals(mapping);
686
663
  });
687
- afterEach(function () {
664
+ afterEach(() => {
688
665
  _.each(mapping, function (_, key) {
689
666
  state[key] = globalsBackup[key];
690
667
  });
691
-
692
668
  globalsBackup = null;
693
669
  });
694
-
695
670
  function setGlobals(mapping) {
696
671
  _.each(mapping, function (value, key) {
697
672
  globalsBackup[key] = state[key];
698
673
  state[key] = typeof value === 'function' ? value.call(this) : value;
699
674
  });
700
-
701
675
  return mapping;
702
676
  }
703
-
704
677
  return {
705
- setGlobals: setGlobals
678
+ setGlobals
706
679
  };
707
680
  };
708
681
 
682
+ /**
683
+ * Enable feature flags for the surrounding describe block.
684
+ *
685
+ * Each `beforeEach` calls `features.enable(scope, names)`, which both
686
+ * flips `features.isEnabled` to true for the given names and runs any
687
+ * functions registered via `features.register` for them. Each
688
+ * `afterEach` restores the set of enabled features to whatever was
689
+ * enabled before the helper was invoked, so suites do not leak state
690
+ * into each other.
691
+ *
692
+ * Multiple calls within the same describe block (or across nested
693
+ * describes) compose: each call adds its own features on top of
694
+ * whatever previous `useFakeFeatures` calls already enabled.
695
+ *
696
+ * @param {String} scope -
697
+ * Name of the scope to enable the features in (e.g. `'frontend'`,
698
+ * `'editor'`).
699
+ * @param {String[]} names -
700
+ * Feature names to enable in the given scope.
701
+ *
702
+ * @example
703
+ * import {useFakeFeatures} from 'pageflow/testHelpers';
704
+ * import {features} from 'pageflow/frontend';
705
+ *
706
+ * describe('...', () => {
707
+ * useFakeFeatures('frontend', ['commenting']);
708
+ *
709
+ * it('...', () => {
710
+ * expect(features.isEnabled('commenting')).toBe(true);
711
+ * });
712
+ * });
713
+ */
714
+ function useFakeFeatures(scope, names) {
715
+ let originalEnabledFeatureNames;
716
+ beforeEach(() => {
717
+ originalEnabledFeatureNames = features.enabledFeatureNames;
718
+ features.enable(scope, names);
719
+ });
720
+ afterEach(() => {
721
+ features.enabledFeatureNames = originalEnabledFeatureNames;
722
+ });
723
+ }
724
+
709
725
  /**
710
726
  * Define translations to use in tests.
711
727
  *
728
+ * Multiple calls within the same describe block (or across nested
729
+ * describes) compose: each call's translations are merged on top of
730
+ * whatever previous `useFakeTranslations` calls already provided.
731
+ *
712
732
  * @param {Object} translations -
713
733
  * A mapping of either the form `(translation key => translated
714
734
  * text)`. Translation keys can contains dots.
@@ -746,41 +766,35 @@ var setupGlobals = function setupGlobals(mapping) {
746
766
  * });
747
767
  * });
748
768
  */
749
-
750
- function useFakeTranslations(translations) {
751
- var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
752
- multiLocale = _ref.multiLocale;
753
-
754
- var originalTranslations;
769
+ function useFakeTranslations(translations, {
770
+ multiLocale
771
+ } = {}) {
772
+ let originalTranslations;
755
773
  beforeEach(function () {
756
774
  originalTranslations = I18n.translations;
757
-
775
+ const base = I18n.translations ? JSON.parse(JSON.stringify(I18n.translations)) : {};
758
776
  if (multiLocale) {
759
- I18n.translations = keysWithDotsToNestedObjects(translations);
777
+ applyTranslations(base, translations);
760
778
  } else {
761
- I18n.translations = {
762
- en: keysWithDotsToNestedObjects(translations)
763
- };
779
+ base.en = base.en || {};
780
+ applyTranslations(base.en, translations);
764
781
  }
782
+ I18n.translations = base;
765
783
  });
766
- afterEach(function () {
784
+ afterEach(() => {
767
785
  I18n.translations = originalTranslations;
768
786
  });
769
787
  }
770
-
771
- function keysWithDotsToNestedObjects(translations) {
772
- return _(translations).reduce(function (result, value, key) {
773
- var keys = key.split('.');
774
- var last = keys.pop();
775
-
776
- var inner = _(keys).reduce(function (r, key) {
777
- r[key] = r[key] || {};
778
- return r[key];
779
- }, result);
780
-
788
+ function applyTranslations(target, translations) {
789
+ _(translations).each((value, key) => {
790
+ const keys = key.split('.');
791
+ const last = keys.pop();
792
+ const inner = _(keys).reduce((r, k) => {
793
+ r[k] = r[k] || {};
794
+ return r[k];
795
+ }, target);
781
796
  inner[last] = value;
782
- return result;
783
- }, {});
797
+ });
784
798
  }
785
799
 
786
- export { ColorInput, ConfigurationEditor, ConfigurationEditorTab, DropDownButton, FileMetaDataTable, FileStageItem, FileThumbnail, RadioButtonGroupInput, ReferenceInput, SelectInput, StaticThumbnail, Table, Tabs, ThemeItem, factories, fakeBrowserAgent, setupGlobals, useFakeTranslations };
800
+ export { ConfigurationEditor, ConfigurationEditorTab, DropDownButton, FileInput, FileMetaDataTable, FileStageItem, FileThumbnail, Base$1 as Input, RadioButtonGroupInput, ReferenceInput, SelectInput, StaticThumbnail, Table, Tabs, ThemeItem, factories, fakeBrowserAgent, renderBackboneView, setupGlobals, useFakeFeatures, useFakeTranslations };