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,4 +1,5 @@
1
1
  module Pageflow
2
+ # @api private
2
3
  module QuotaVerification
3
4
  extend ActiveSupport::Concern
4
5
 
@@ -9,10 +10,10 @@ module Pageflow
9
10
  redirect_back fallback_location: admin_root_path, alert: t('pageflow.quotas.exhausted')
10
11
  end
11
12
  format.json do
12
- render(:status => :forbidden,
13
- :json => {
14
- :error_message => exception.message,
15
- :quota_name => exception.quota.name
13
+ render(status: :forbidden,
14
+ json: {
15
+ error_message: exception.message,
16
+ quota_name: exception.quota.name
16
17
  })
17
18
  end
18
19
  end
@@ -1,5 +1,6 @@
1
1
  module Pageflow
2
2
  module Admin
3
+ # @api private
3
4
  class InitialPasswordsController < Devise::PasswordsController
4
5
  layout 'active_admin_logged_out'
5
6
  helper ActiveAdmin::ViewHelpers
@@ -2,11 +2,15 @@ require 'cancan'
2
2
  require 'state_machines'
3
3
 
4
4
  module Pageflow
5
+ # @api private
5
6
  class ApplicationController < ActionController::Base
6
7
  layout 'pageflow/application'
7
8
 
8
9
  before_action do
9
- I18n.locale = current_user.try(:locale) || locale_from_accept_language_header || I18n.default_locale
10
+ I18n.locale =
11
+ current_user.try(:locale) ||
12
+ locale_from_accept_language_header ||
13
+ I18n.default_locale
10
14
  end
11
15
 
12
16
  # Prevent CSRF attacks by raising an exception.
@@ -22,15 +26,9 @@ module Pageflow
22
26
 
23
27
  rescue_from ActiveRecord::RecordNotFound do |exception|
24
28
  debug_log_with_backtrace(exception)
29
+
25
30
  respond_to do |format|
26
- format.html do
27
- begin
28
- render file: Rails.public_path.join('pageflow', 'error_pages', '404.html'), status: :not_found
29
- rescue ActionView::MissingTemplate => exception
30
- debug_log_with_backtrace(exception)
31
- head :not_found
32
- end
33
- end
31
+ format.html { render_static_404_error_page }
34
32
  format.any { head :not_found }
35
33
  end
36
34
  end
@@ -38,7 +36,7 @@ module Pageflow
38
36
  rescue_from CanCan::AccessDenied do |exception|
39
37
  debug_log_with_backtrace(exception)
40
38
  respond_to do |format|
41
- format.html { redirect_to main_app.admin_root_path, :alert => t('pageflow.unauthorized') }
39
+ format.html { redirect_to main_app.admin_root_path, alert: t('pageflow.unauthorized') }
42
40
  format.any(:json, :css) { head :forbidden }
43
41
  end
44
42
  end
@@ -46,7 +44,9 @@ module Pageflow
46
44
  rescue_from StateMachines::InvalidTransition do |exception|
47
45
  debug_log_with_backtrace(exception)
48
46
  respond_to do |format|
49
- format.html { redirect_to main_app.admin_root_path, :alert => t('pageflow.invalid_transition') }
47
+ format.html do
48
+ redirect_to main_app.admin_root_path, alert: t('pageflow.invalid_transition')
49
+ end
50
50
  format.json { head :bad_request }
51
51
  end
52
52
  end
@@ -57,18 +57,18 @@ module Pageflow
57
57
  @current_ability ||= Ability.new(current_user)
58
58
  end
59
59
 
60
- def after_sign_in_path_for(resource_or_scope)
61
- root_url(:protocol => 'http')
62
- end
63
-
64
- def after_sign_out_path_for(resource_or_scope)
65
- root_url(:protocol => 'http')
66
- end
67
-
68
60
  def locale_from_accept_language_header
69
61
  http_accept_language.compatible_language_from(I18n.available_locales)
70
62
  end
71
63
 
64
+ def render_static_404_error_page
65
+ render file: Rails.public_path.join('pageflow', 'error_pages', '404.html'),
66
+ status: :not_found
67
+ rescue ActionView::MissingTemplate => e
68
+ debug_log_with_backtrace(e)
69
+ head :not_found
70
+ end
71
+
72
72
  def debug_log_with_backtrace(exception)
73
73
  Rails.logger.debug exception
74
74
  backtrace = ''
@@ -1,4 +1,5 @@
1
1
  module Pageflow
2
+ # @api private
2
3
  class ChaptersController < Pageflow::ApplicationController
3
4
  respond_to :json
4
5
 
@@ -67,8 +68,8 @@ module Pageflow
67
68
  configuration = params.require(:chapter)[:configuration].try(:permit!) || {}
68
69
 
69
70
  params.require(:chapter)
70
- .permit(:position, :title)
71
- .merge(configuration: configuration)
71
+ .permit(:position, :title)
72
+ .merge(configuration:)
72
73
  end
73
74
  end
74
75
  end
@@ -1,4 +1,5 @@
1
1
  module Pageflow
2
+ # @api private
2
3
  class EditLocksController < Pageflow::ApplicationController
3
4
  before_action :authenticate_user!
4
5
 
@@ -11,7 +12,7 @@ module Pageflow
11
12
 
12
13
  entry.snapshot(creator: current_user) unless entry.feature_state('no_edit_lock_snapshot')
13
14
 
14
- respond_with(entry.reload.edit_lock, :location => entry_edit_lock_url(entry))
15
+ respond_with(entry.reload.edit_lock, location: entry_edit_lock_url(entry))
15
16
  end
16
17
 
17
18
  def update
@@ -30,7 +31,7 @@ module Pageflow
30
31
  protected
31
32
 
32
33
  def edit_lock_params
33
- params.permit(:edit_lock => [:force, :id]).fetch(:edit_lock, {})
34
+ params.permit(edit_lock: [:force, :id]).fetch(:edit_lock, {})
34
35
  end
35
36
  end
36
37
  end
@@ -1,5 +1,6 @@
1
1
  module Pageflow
2
2
  module Editor
3
+ # @api private
3
4
  class EncodingConfirmationsController < Pageflow::ApplicationController
4
5
  respond_to :json
5
6
 
@@ -1,5 +1,6 @@
1
1
  module Pageflow
2
2
  module Editor
3
+ # @api private
3
4
  class EntriesController < Pageflow::ApplicationController
4
5
  layout 'pageflow/editor'
5
6
 
@@ -49,8 +50,9 @@ module Pageflow
49
50
  .permit(:title, :summary, :credits,
50
51
  :share_url, :share_image_id, :share_image_x, :share_image_y,
51
52
  :locale, :author, :publisher, :keywords, :theme_name,
53
+ :structured_data_type_name,
52
54
  share_providers: {})
53
- .merge(configuration: configuration)
55
+ .merge(configuration:)
54
56
  end
55
57
  end
56
58
  end
@@ -1,5 +1,6 @@
1
1
  module Pageflow
2
2
  module Editor
3
+ # @api private
3
4
  class EntryPublicationsController < Pageflow::ApplicationController
4
5
  respond_to :json
5
6
 
@@ -0,0 +1,80 @@
1
+ module Pageflow
2
+ module Editor
3
+ # @api private
4
+ class FileFoldersController < Pageflow::ApplicationController
5
+ respond_to :json
6
+
7
+ before_action :authenticate_user!
8
+
9
+ def index
10
+ entry = DraftEntry.find(params[:entry_id])
11
+
12
+ authorize!(:use_files, entry.to_model)
13
+ @file_folders = folders(entry)
14
+
15
+ respond_with(:editor, @file_folders)
16
+ end
17
+
18
+ def create
19
+ entry = DraftEntry.find(params[:entry_id])
20
+ authorize!(:edit, entry.to_model)
21
+ verify_edit_lock!(entry)
22
+
23
+ @file_folder = entry.create_folder!(create_params)
24
+
25
+ respond_with(:editor, @file_folder)
26
+ rescue ActiveRecord::RecordInvalid => e
27
+ debug_log_with_backtrace(e)
28
+ head :unprocessable_entity
29
+ end
30
+
31
+ def update
32
+ entry = DraftEntry.find(params[:entry_id])
33
+ authorize!(:edit, entry.to_model)
34
+ verify_edit_lock!(entry)
35
+
36
+ folder(entry).update!(update_params)
37
+
38
+ head(:no_content)
39
+ rescue ActiveRecord::RecordInvalid => e
40
+ debug_log_with_backtrace(e)
41
+ head :unprocessable_entity
42
+ end
43
+
44
+ def destroy
45
+ entry = DraftEntry.find(params[:entry_id])
46
+ authorize!(:edit, entry.to_model)
47
+ verify_edit_lock!(entry)
48
+
49
+ folder = folder(entry)
50
+ return head(:unprocessable_entity) unless folder.empty?
51
+
52
+ folder.destroy
53
+
54
+ head(:no_content)
55
+ end
56
+
57
+ private
58
+
59
+ def folder(entry)
60
+ folders(entry).find(params[:id])
61
+ end
62
+
63
+ def folders(entry)
64
+ FileFolder.all_for_revision(entry.draft)
65
+ end
66
+
67
+ def create_params
68
+ file_folder_params.permit(:name, :parent_folder_perma_id)
69
+ end
70
+
71
+ def update_params
72
+ file_folder_params.permit(:name, :parent_folder_perma_id)
73
+ end
74
+
75
+ def file_folder_params
76
+ params.require(:file_folder)
77
+ end
78
+ end
79
+ end
80
+ end
@@ -26,7 +26,7 @@ module Pageflow
26
26
 
27
27
  FileImportJob.perform_later(file_import.id, file_importer_credentials)
28
28
 
29
- {file: file, source_url: file_params[:url]}
29
+ {file:, source_url: file_params[:url]}
30
30
  end
31
31
  end
32
32
 
@@ -54,12 +54,13 @@ module Pageflow
54
54
 
55
55
  def files_params
56
56
  params
57
- .permit(files: [:file_name,
57
+ .permit(files: [:display_name,
58
58
  :rights,
59
59
  :content_type,
60
60
  :file_size,
61
61
  :url,
62
- configuration: [:alt, :source_url]])
62
+ :folder_perma_id,
63
+ {configuration: [:alt, :source_url]}])
63
64
  .require(:files)
64
65
  end
65
66
 
@@ -1,5 +1,6 @@
1
1
  module Pageflow
2
2
  module Editor
3
+ # @api private
3
4
  class FilesController < Pageflow::ApplicationController
4
5
  respond_to :json
5
6
 
@@ -30,9 +31,7 @@ module Pageflow
30
31
 
31
32
  def reuse
32
33
  entry = DraftEntry.find(params[:entry_id])
33
- other_entry = DraftEntry.find(file_reuse_params[:other_entry_id])
34
-
35
- file_reuse = FileReuse.new(entry, other_entry, file_type, file_reuse_params[:file_id])
34
+ file_reuse = build_file_reuse(entry)
36
35
 
37
36
  authorize!(:edit, entry.to_model)
38
37
  authorize!(:use, file_reuse.file.to_model)
@@ -75,6 +74,9 @@ module Pageflow
75
74
  file.update!(update_params)
76
75
 
77
76
  head(:no_content)
77
+ rescue ActiveRecord::RecordInvalid => e
78
+ debug_log_with_backtrace(e)
79
+ head :unprocessable_entity
78
80
  end
79
81
 
80
82
  def destroy
@@ -91,18 +93,26 @@ module Pageflow
91
93
  private
92
94
 
93
95
  def create_params
94
- file_params.permit(:file_name, :content_type, :file_size)
95
- .merge(file_configuration_params)
96
- .merge(file_parent_file_params)
97
- .merge(file_custom_params)
96
+ file_params.permit(:display_name, :content_type, :file_size, :folder_perma_id)
97
+ .merge(file_configuration_params)
98
+ .merge(file_parent_file_params)
99
+ .merge(file_custom_params)
100
+ end
101
+
102
+ def build_file_reuse(entry)
103
+ FileReuse.new(entry,
104
+ DraftEntry.find(file_reuse_params[:other_entry_id]),
105
+ file_type,
106
+ file_reuse_params[:file_id],
107
+ folder_perma_id: file_reuse_params[:folder_perma_id])
98
108
  end
99
109
 
100
110
  def file_reuse_params
101
- params.require(:file_reuse).permit(:other_entry_id, :file_id)
111
+ params.require(:file_reuse).permit(:other_entry_id, :file_id, :folder_perma_id)
102
112
  end
103
113
 
104
114
  def update_params
105
- file_configuration_params
115
+ file_configuration_params.merge(file_params.permit(:display_name, :folder_perma_id))
106
116
  end
107
117
 
108
118
  def file_configuration_params
@@ -110,7 +120,7 @@ module Pageflow
110
120
 
111
121
  file_params
112
122
  .permit(:rights)
113
- .merge(configuration: configuration)
123
+ .merge(configuration:)
114
124
  end
115
125
 
116
126
  def file_parent_file_params
@@ -0,0 +1,21 @@
1
+ module Pageflow
2
+ module Editor
3
+ # @api private
4
+ class OembedsController < Pageflow::ApplicationController
5
+ respond_to :json
6
+
7
+ before_action :authenticate_user!
8
+
9
+ def show
10
+ provider = Pageflow.config.oembed_providers.find_by_name!(params[:provider])
11
+ oembed_response = provider.get(params[:url])
12
+
13
+ render json: oembed_response.fields
14
+ rescue Pageflow::OembedProviderNotFoundError
15
+ head :unprocessable_entity
16
+ rescue OEmbed::NotFound
17
+ head :not_found
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,5 +1,6 @@
1
1
  module Pageflow
2
2
  module Editor
3
+ # @api private
3
4
  class WidgetsController < Pageflow::ApplicationController
4
5
  respond_to :json
5
6
 
@@ -6,21 +6,37 @@ module Pageflow
6
6
  include EntryPasswordProtection
7
7
 
8
8
  def index
9
- site = Site.for_request(request).with_home_url.first!
9
+ site = Site.for_request(request).first!
10
10
 
11
- redirect_to(site.home_url, allow_other_host: true)
11
+ entry = PublishedEntry.find_by_permalink(
12
+ directory: '',
13
+ slug: '',
14
+ scope: site.entries
15
+ )
16
+
17
+ if entry
18
+ respond_to do |format|
19
+ format.html { handle_public_entry_request(entry) }
20
+ end
21
+ elsif site.home_url.present?
22
+ redirect_to(site.home_url, allow_other_host: true)
23
+ else
24
+ raise ActiveRecord::RecordNotFound
25
+ end
12
26
  end
13
27
 
14
28
  def show
15
29
  respond_to do |format|
16
30
  format.html do
17
- entry = find_by_permalink || find_by_slug
31
+ entry = find_by_permalink
18
32
 
19
- return if redirect_according_to_entry_redirect(entry)
20
- return if redirect_according_to_public_https_mode
21
- return unless check_entry_password_protection(entry)
33
+ return if !entry && redirect_according_to_permalink_redirect
22
34
 
23
- delegate_to_entry_type_frontend_app!(entry)
35
+ entry ||= find_by_slug!
36
+
37
+ handle_public_entry_request(entry)
38
+ rescue ActiveRecord::RecordNotFound
39
+ render_custom_or_static_404_error_page
24
40
  end
25
41
  end
26
42
  end
@@ -49,7 +65,7 @@ module Pageflow
49
65
  entry = PublishedEntry.find(params[:id], entry_request_scope)
50
66
  index = params[:page_index].split('-').first.to_i
51
67
 
52
- redirect_to(short_entry_path(entry.to_model, :anchor => entry.pages[index].try(:perma_id)))
68
+ redirect_to(short_entry_path(entry.to_model, anchor: entry.pages[index].try(:perma_id)))
53
69
  end
54
70
 
55
71
  protected
@@ -62,7 +78,7 @@ module Pageflow
62
78
  )
63
79
  end
64
80
 
65
- def find_by_slug
81
+ def find_by_slug!
66
82
  PublishedEntry.find(params[:id], entry_request_scope)
67
83
  end
68
84
 
@@ -70,22 +86,52 @@ module Pageflow
70
86
  Pageflow.config.public_entry_request_scope.call(Entry, request)
71
87
  end
72
88
 
73
- def redirect_according_to_entry_redirect(entry)
74
- return unless (redirect_location = entry_redirect(entry))
89
+ def handle_public_entry_request(entry)
90
+ config = Pageflow.config_for(entry)
91
+
92
+ return if redirect_according_to_entry_redirect(entry, config)
93
+ return if redirect_according_to_public_https_mode
94
+ return unless check_entry_password_protection(entry)
75
95
 
76
- redirect_to(redirect_location, status: :moved_permanently, allow_other_host: true)
96
+ delegate_to_entry_type_frontend_app!(entry, config:)
77
97
  end
78
98
 
79
- def entry_redirect(entry)
80
- Pageflow.config.public_entry_redirect.call(entry, request)
99
+ def redirect_according_to_permalink_redirect
100
+ entry = PublishedEntry.find_by_permalink_redirect(
101
+ directory: params[:directory],
102
+ slug: params[:id],
103
+ site: Site.for_request(request)
104
+ )
105
+
106
+ return false unless entry
107
+
108
+ redirect_to(EntriesHelper::PrettyUrl.build(pageflow, entry),
109
+ status: :moved_permanently,
110
+ allow_other_host: true)
111
+ true
81
112
  end
82
113
 
83
- def delegate_to_entry_type_frontend_app!(entry)
84
- EntriesControllerEnvHelper.add_entry_info_to_env(request.env, entry: entry, mode: :published)
114
+ def redirect_according_to_entry_redirect(entry, config)
115
+ return false unless (redirect_location = config.public_entry_redirect.call(entry, request))
116
+
117
+ redirect_to(redirect_location, status: :moved_permanently, allow_other_host: true)
118
+ true
119
+ end
120
+
121
+ def delegate_to_entry_type_frontend_app!(entry, config:, override_status: nil)
122
+ EntriesControllerEnvHelper.add_entry_info_to_env(request.env,
123
+ entry:,
124
+ mode: :published,
125
+ embed: params[:embed].present?)
126
+
127
+ delegate_to_rack_app!(entry.entry_type.frontend_app) do |result|
128
+ status, headers, body = result
85
129
 
86
- delegate_to_rack_app!(entry.entry_type.frontend_app) do |_status, headers, _body|
87
130
  allow_iframe_for_embed(headers)
88
- apply_cache_control(entry, headers)
131
+ apply_additional_headers(entry, config, headers)
132
+ apply_cache_control(entry, config, headers)
133
+
134
+ [override_status || status, headers, body]
89
135
  end
90
136
  end
91
137
 
@@ -93,13 +139,31 @@ module Pageflow
93
139
  headers.except!('X-Frame-Options') if params[:embed]
94
140
  end
95
141
 
96
- def apply_cache_control(entry, headers)
97
- config = Pageflow.config_for(entry)
98
-
142
+ def apply_cache_control(entry, config, headers)
99
143
  return if config.public_entry_cache_control_header.blank?
100
144
  return if entry.password_protected?
101
145
 
102
146
  headers['Cache-Control'] = config.public_entry_cache_control_header
103
147
  end
148
+
149
+ def apply_additional_headers(entry, config, headers)
150
+ headers.merge!(
151
+ config.additional_public_entry_headers.for(entry, request)
152
+ )
153
+ end
154
+
155
+ def render_custom_or_static_404_error_page
156
+ site = Site.for_request(request).first
157
+
158
+ if site&.custom_404_entry&.published_without_password_protection?
159
+ entry = PublishedEntry.new(site.custom_404_entry)
160
+ config = Pageflow.config_for(entry)
161
+
162
+ delegate_to_entry_type_frontend_app!(entry, config:, override_status: 404)
163
+ else
164
+ # Fallback to ApplicationController's handler method
165
+ render_static_404_error_page
166
+ end
167
+ end
104
168
  end
105
169
  end
@@ -6,7 +6,7 @@ module Pageflow
6
6
  return head 404 unless site.feeds_enabled?
7
7
 
8
8
  @feed = EntriesFeed.for(
9
- site: site,
9
+ site:,
10
10
  locale: params[:locale]
11
11
  )
12
12
 
@@ -1,4 +1,5 @@
1
1
  module Pageflow
2
+ # @api private
2
3
  class FilesController < Pageflow::ApplicationController
3
4
  include PublicHttpsMode
4
5
  include EntryPasswordProtection
@@ -1,4 +1,5 @@
1
1
  module Pageflow
2
+ # @api private
2
3
  class PagesController < Pageflow::ApplicationController
3
4
  respond_to :json
4
5
 
@@ -43,7 +44,7 @@ module Pageflow
43
44
 
44
45
  authorize!(:destroy, page)
45
46
  verify_edit_lock!(page.chapter.entry)
46
- page.chapter.entry.snapshot(:creator => current_user)
47
+ page.chapter.entry.snapshot(creator: current_user)
47
48
 
48
49
  page.destroy
49
50
 
@@ -54,7 +55,8 @@ module Pageflow
54
55
 
55
56
  def page_params
56
57
  configuration = params.require(:page)[:configuration].try(:permit!) || {}
57
- params.require(:page).permit(:template, :position, :title).merge(:configuration => configuration)
58
+ params.require(:page).permit(:template, :position,
59
+ :title).merge(configuration:)
58
60
  end
59
61
  end
60
62
  end
@@ -0,0 +1,30 @@
1
+ module Pageflow
2
+ module Review
3
+ # @api private
4
+ class CommentThreadReadsController < Pageflow::ApplicationController
5
+ respond_to :json
6
+ before_action :authenticate_user!
7
+
8
+ def create
9
+ entry = DraftEntry.find(params[:entry_id])
10
+ authorize!(:read, entry.to_model)
11
+
12
+ CommentThreadRead.mark(entry: entry.to_model,
13
+ user: current_user,
14
+ comment_thread_perma_ids: known_perma_ids(entry))
15
+
16
+ head :no_content
17
+ end
18
+
19
+ private
20
+
21
+ # Guards against read records piling up for comment threads that
22
+ # do not exist in the entry.
23
+ def known_perma_ids(entry)
24
+ entry.comment_threads
25
+ .where(perma_id: params.fetch(:comment_thread_perma_ids, []))
26
+ .pluck(:perma_id)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,60 @@
1
+ module Pageflow
2
+ module Review
3
+ # @api private
4
+ class CommentThreadsController < Pageflow::ApplicationController
5
+ respond_to :json
6
+ before_action :authenticate_user!
7
+
8
+ def index
9
+ entry = DraftEntry.find(params[:entry_id])
10
+ authorize!(:read, entry.to_model)
11
+
12
+ @comment_threads = entry.comment_threads.includes(:resolver, comments: :creator)
13
+ @read_at_by_perma_id =
14
+ CommentThreadRead.read_at_by_perma_id(entry: entry.to_model, user: current_user)
15
+ end
16
+
17
+ def create
18
+ entry = DraftEntry.find(params[:entry_id])
19
+ authorize!(:read, entry.to_model)
20
+
21
+ @comment_thread = entry.comment_threads.build(thread_params)
22
+ @comment_thread.creator = current_user
23
+
24
+ first_comment = @comment_thread.comments.build(first_comment_params)
25
+ first_comment.creator = current_user
26
+
27
+ @comment_thread.save!
28
+ render :create, status: :created
29
+ end
30
+
31
+ def update
32
+ entry = DraftEntry.find(params[:entry_id])
33
+ authorize!(:read, entry.to_model)
34
+
35
+ @comment_thread = entry.comment_threads.find(params[:id])
36
+
37
+ if ActiveModel::Type::Boolean.new.cast(params[:comment_thread][:resolved])
38
+ @comment_thread.resolve(current_user)
39
+ else
40
+ @comment_thread.unresolve
41
+ end
42
+
43
+ render :create
44
+ end
45
+
46
+ private
47
+
48
+ def thread_params
49
+ permitted = params.require(:comment_thread)
50
+ .permit(:subject_type, :subject_id, :section_perma_id)
51
+ permitted[:subject_range] = params[:comment_thread][:subject_range]&.permit!
52
+ permitted
53
+ end
54
+
55
+ def first_comment_params
56
+ params.require(:comment_thread).require(:comment).permit(:body, :quote)
57
+ end
58
+ end
59
+ end
60
+ end