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,9 +1,9 @@
1
1
  module Pageflow
2
2
  # @api private
3
3
  class CustomizedTheme < SimpleDelegator
4
- def initialize(theme, overrides, files)
4
+ def initialize(theme, transformed_options, overrides, files)
5
5
  super(theme)
6
- @options = __getobj__.options.deep_merge(overrides || {})
6
+ @options = transformed_options.deep_merge(overrides || {})
7
7
  @files = files
8
8
  end
9
9
 
@@ -11,8 +11,8 @@ module Pageflow
11
11
 
12
12
  def self.find(entry:, theme:)
13
13
  build(
14
- entry: entry,
15
- theme: theme,
14
+ entry:,
15
+ theme:,
16
16
  theme_customization: Pageflow.theme_customizations.get(
17
17
  site: entry.site,
18
18
  entry_type_name: entry.type_name
@@ -24,15 +24,16 @@ module Pageflow
24
24
  config = Pageflow.config_for(entry)
25
25
 
26
26
  new(theme,
27
+ config.themes.apply_default_options(theme.options, entry:),
27
28
  config.transform_theme_customization_overrides.call(
28
29
  theme_customization.overrides,
29
- entry: entry,
30
- theme: theme
30
+ entry:,
31
+ theme:
31
32
  ),
32
33
  config.transform_theme_customization_files.call(
33
34
  theme_customization.selected_files.transform_values(&:urls),
34
- entry: entry,
35
- theme: theme
35
+ entry:,
36
+ theme:
36
37
  ))
37
38
  end
38
39
  end
@@ -1,3 +1,5 @@
1
+ require 'securerandom'
2
+
1
3
  module Pageflow
2
4
  # A merged view of an entry and its draft revision
3
5
  class DraftEntry < EntryAtRevision
@@ -14,20 +16,38 @@ module Pageflow
14
16
  entry.title
15
17
  end
16
18
 
19
+ def translations(scope = -> { self }, **)
20
+ return [] unless entry.translation_group
21
+
22
+ PublishedEntry.wrap_all_drafts(
23
+ entry.translation_group.entries.instance_exec(&scope)
24
+ )
25
+ end
26
+
27
+ def cutoff_mode_enabled_for?(_request)
28
+ false
29
+ end
30
+
17
31
  def create_file!(file_type, attributes)
18
32
  check_foreign_key_custom_attributes(file_type.custom_attributes, attributes)
19
33
 
20
- file = file_type.model.create!(attributes.except(:configuration)) do |f|
21
- f.entry = entry
34
+ file_attributes = attributes.except(:configuration, :display_name, :folder_perma_id)
35
+
36
+ if file_name_attribute?(file_type)
37
+ file_attributes[:file_name] = generate_file_name(attributes[:display_name])
22
38
  end
23
39
 
24
- usage = revision.file_usages.create_with_lock!(file: file,
25
- configuration: attributes[:configuration])
40
+ file = file_type.model.create!(file_attributes) { |f| f.entry = entry }
41
+
42
+ usage = revision.file_usages.create!(file:,
43
+ configuration: attributes[:configuration],
44
+ display_name: attributes[:display_name],
45
+ folder_perma_id: attributes[:folder_perma_id])
26
46
  UsedFile.new(file, usage)
27
47
  end
28
48
 
29
- def remove_file(file)
30
- draft.file_usages.where(file: file).destroy_all
49
+ def remove_file(file) # rubocop:todo Metrics/AbcSize
50
+ draft.file_usages.where(file:).destroy_all
31
51
 
32
52
  file.file_type.nested_file_types.each do |nested_file_type|
33
53
  nested_file_ids = file.nested_files(nested_file_type.model).map(&:id)
@@ -42,9 +62,15 @@ module Pageflow
42
62
  file.destroy if file.usages.reload.empty?
43
63
  end
44
64
 
45
- def use_file(file)
65
+ def create_folder!(attributes)
66
+ draft.file_folders.create!(attributes)
67
+ end
68
+
69
+ def use_file(file, folder_perma_id: nil)
46
70
  draft.file_usages.create!(file: file.to_model,
47
- configuration: file.configuration)
71
+ configuration: file.configuration,
72
+ display_name: file.display_name,
73
+ folder_perma_id:)
48
74
  end
49
75
 
50
76
  def save!
@@ -77,6 +103,10 @@ module Pageflow
77
103
  draft.cache_key
78
104
  end
79
105
 
106
+ def published_revision?
107
+ false
108
+ end
109
+
80
110
  private
81
111
 
82
112
  def check_foreign_key_custom_attributes(custom_attributes, attributes)
@@ -93,8 +123,18 @@ module Pageflow
93
123
  end
94
124
  end
95
125
 
126
+ def file_name_attribute?(file_type)
127
+ file_type.model.new.respond_to?(:file_name=)
128
+ end
129
+
130
+ def generate_file_name(file_name)
131
+ return nil if file_name.blank?
132
+
133
+ "#{SecureRandom.alphanumeric(8).downcase}#{File.extname(file_name)}"
134
+ end
135
+
96
136
  def file_is_used(file_type, file_id)
97
- draft.file_usages.where(file_type: file_type, file_id: file_id).exists?
137
+ draft.file_usages.where(file_type:, file_id:).exists?
98
138
  end
99
139
  end
100
140
  end
@@ -1,17 +1,17 @@
1
1
  module Pageflow
2
- class EditLock < ApplicationRecord
2
+ class EditLock < ApplicationRecord # rubocop:todo Style/Documentation
3
3
  scope :active, (lambda do
4
4
  time = Time.now - EditLock.time_to_live
5
5
  where('pageflow_edit_locks.updated_at >= ?', time)
6
6
  end)
7
7
 
8
- class Error < RuntimeError
8
+ class Error < RuntimeError # rubocop:todo Style/Documentation
9
9
  def code
10
10
  self.class.name.split('::').last.underscore
11
11
  end
12
12
  end
13
13
 
14
- class HeldByOtherUserError < Error
14
+ class HeldByOtherUserError < Error # rubocop:todo Style/Documentation
15
15
  attr_reader :user
16
16
 
17
17
  def initialize(user)
@@ -23,7 +23,7 @@ module Pageflow
23
23
  class NotHeldError < Error; end
24
24
 
25
25
  belongs_to :user
26
- belongs_to :entry, :inverse_of => :edit_lock
26
+ belongs_to :entry, inverse_of: :edit_lock
27
27
 
28
28
  def self.time_to_live
29
29
  timer_tolerance = 2.3
@@ -45,33 +45,32 @@ module Pageflow
45
45
  def acquire(current_user, options = {})
46
46
  verify!(current_user, options)
47
47
  rescue Error
48
- if options[:force] || timed_out?
49
- entry.create_edit_lock(:user => current_user)
50
- else
51
- raise
52
- end
48
+ raise unless options[:force] || timed_out?
49
+
50
+ entry.create_edit_lock(user: current_user)
53
51
  end
54
52
 
55
53
  def release(current_user)
56
- if user == current_user
57
- destroy
58
- end
54
+ return unless user == current_user
55
+
56
+ destroy
59
57
  end
60
58
 
61
59
  def verify!(current_user, options)
62
- raise HeldByOtherUserError.new(user) unless held_by?(current_user)
60
+ raise HeldByOtherUserError, user unless held_by?(current_user)
63
61
  raise HeldByOtherSessionError unless matches?(options[:id])
62
+
64
63
  touch
65
64
  end
66
65
 
67
- class Null
66
+ class Null # rubocop:todo Style/Documentation
68
67
  attr_reader :entry
69
68
 
70
69
  def initialize(entry)
71
70
  @entry = entry
72
71
  end
73
72
 
74
- def held_by?(user)
73
+ def held_by?(_user)
75
74
  false
76
75
  end
77
76
 
@@ -79,15 +78,14 @@ module Pageflow
79
78
  true
80
79
  end
81
80
 
82
- def acquire(user, options = {})
83
- entry.create_edit_lock!(:user => user)
81
+ def acquire(user, _options = {})
82
+ entry.create_edit_lock!(user:)
84
83
  end
85
84
 
86
- def release(user)
87
- end
85
+ def release(user); end
88
86
 
89
- def verify!(user, options = {})
90
- raise NotHeldError.new
87
+ def verify!(_user, _options = {})
88
+ raise NotHeldError
91
89
  end
92
90
  end
93
91
  end
@@ -1,5 +1,5 @@
1
1
  module Pageflow
2
- class EncodingConfirmation
2
+ class EncodingConfirmation # rubocop:todo Style/Documentation
3
3
  class QuotaExceededError < RuntimeError
4
4
  end
5
5
 
@@ -29,7 +29,7 @@ module Pageflow
29
29
  end
30
30
 
31
31
  def assumed_quota
32
- @assumed_quota ||= encoding_quota.assume(files: files)
32
+ @assumed_quota ||= encoding_quota.assume(files:)
33
33
  end
34
34
 
35
35
  def files
@@ -1,6 +1,6 @@
1
1
  module Pageflow
2
2
  # @api private
3
- EntriesFeed = Struct.new(:title, :locale, :custom_url, :root_url, :entries) do
3
+ EntriesFeed = Struct.new(:title, :locale, :custom_url, :root_url, :entries) do # rubocop:disable Lint/StructNewOverride
4
4
  def updated_at
5
5
  entries.map(&:published_at).max
6
6
  end
@@ -23,7 +23,7 @@ module Pageflow
23
23
  site
24
24
  .entries
25
25
  .published_without_password_protection
26
- .where(pageflow_revisions: {locale: locale})
26
+ .where(pageflow_revisions: {locale:})
27
27
  .order('first_published_at DESC')
28
28
  )
29
29
  end
@@ -1,5 +1,5 @@
1
1
  module Pageflow
2
- class Entry < ApplicationRecord
2
+ class Entry < ApplicationRecord # rubocop:todo Style/Documentation
3
3
  class PasswordMissingError < StandardError
4
4
  end
5
5
 
@@ -7,9 +7,11 @@ module Pageflow
7
7
  include EntryPublicationStates
8
8
  include Permalinkable
9
9
  include SerializationBlacklist
10
+ include Translatable
10
11
 
11
12
  extend FriendlyId
12
- friendly_id :slug_candidates, :use => [:finders, :slugged]
13
+
14
+ friendly_id :slug_candidates, use: [:finders, :slugged]
13
15
 
14
16
  belongs_to :account, counter_cache: true
15
17
  belongs_to :folder, optional: true
@@ -17,11 +19,13 @@ module Pageflow
17
19
 
18
20
  has_many :revisions, -> { order('frozen_at DESC') }
19
21
 
20
- has_many :chapters, -> { order('pageflow_chapters.position ASC') }, :through => :revisions
21
- has_many :pages, -> { order('pageflow_chapters.position ASC, pageflow_pages.position ASC') }, :through => :chapters
22
+ has_many :chapters, -> { order('pageflow_chapters.position ASC') }, through: :revisions
23
+ has_many :pages, lambda {
24
+ order('pageflow_chapters.position ASC, pageflow_pages.position ASC')
25
+ }, through: :chapters
22
26
 
23
27
  has_many :memberships, as: :entity, dependent: :destroy
24
- has_many :users, :through => :memberships, :class_name => '::User'
28
+ has_many :users, through: :memberships, class_name: '::User'
25
29
 
26
30
  has_many :image_files
27
31
  has_many :video_files
@@ -29,14 +33,16 @@ module Pageflow
29
33
 
30
34
  has_many :imports, class_name: 'Pageflow::FileImport', dependent: :destroy
31
35
 
36
+ has_many :comment_thread_reads, dependent: :destroy
37
+
32
38
  has_one :draft, -> { editable }, class_name: 'Revision', inverse_of: :entry
33
39
  has_one :published_revision, -> { published }, class_name: 'Revision', inverse_of: :entry
34
40
 
35
- has_one :edit_lock, :dependent => :destroy
41
+ has_one :edit_lock, dependent: :destroy
36
42
 
37
43
  has_secure_password validations: false
38
44
 
39
- validates :account, :site, :presence => true
45
+ validates :account, :site, presence: true
40
46
  validates :title, presence: true
41
47
  validate :entry_type_is_available_for_account
42
48
  validate :folder_belongs_to_same_account
@@ -52,7 +58,7 @@ module Pageflow
52
58
 
53
59
  after_create unless: :skip_draft_creation do
54
60
  create_draft!
55
- draft.storylines.create!(configuration: {main: true})
61
+ create_default_revision_components
56
62
  entry_template.copy_defaults_to(draft)
57
63
  end
58
64
 
@@ -74,8 +80,8 @@ module Pageflow
74
80
  account.feature_state(name)
75
81
  end
76
82
 
77
- def publish(options = {})
78
- ActiveRecord::Base.transaction do
83
+ def publish(options = {}) # rubocop:todo Metrics/AbcSize
84
+ transaction do
79
85
  self.first_published_at ||= Time.now
80
86
  update_password!(options.slice(:password, :password_protected))
81
87
 
@@ -94,25 +100,30 @@ module Pageflow
94
100
  end
95
101
 
96
102
  def snapshot(options)
97
- draft.copy do |revision|
98
- revision.creator = options[:creator]
99
- revision.frozen_at = Time.now
100
- revision.snapshot_type = options.fetch(:type, 'auto')
103
+ transaction do
104
+ draft.copy do |revision|
105
+ revision.creator = options[:creator]
106
+ revision.frozen_at = Time.now
107
+ revision.snapshot_type = options.fetch(:type, 'auto')
108
+ end
101
109
  end
102
110
  end
103
111
 
104
112
  def restore(options)
105
- restored_revision = options.fetch(:revision)
106
- draft.update!(:frozen_at => Time.now, :creator => options[:creator], :snapshot_type => 'before_restore')
107
-
108
- restored_revision.copy do |revision|
109
- revision.restored_from = restored_revision
110
- revision.frozen_at = nil
111
- revision.snapshot_type = nil
112
- revision.published_at = nil
113
- revision.published_until = nil
114
- revision.password_protected = nil
115
- revision.noindex = nil
113
+ transaction do
114
+ restored_revision = options.fetch(:revision)
115
+ draft.update!(frozen_at: Time.now, creator: options[:creator],
116
+ snapshot_type: 'before_restore')
117
+
118
+ restored_revision.copy do |revision|
119
+ revision.restored_from = restored_revision
120
+ revision.frozen_at = nil
121
+ revision.snapshot_type = nil
122
+ revision.published_at = nil
123
+ revision.published_until = nil
124
+ revision.password_protected = nil
125
+ revision.noindex = nil
126
+ end
116
127
  end
117
128
  end
118
129
 
@@ -151,19 +162,24 @@ module Pageflow
151
162
  private
152
163
 
153
164
  def folder_belongs_to_same_account
154
- errors.add(:folder, :must_be_same_account) if folder.present? && folder.account_id != account_id
165
+ return unless folder.present? && folder.account_id != account_id
166
+
167
+ errors.add(:folder,
168
+ :must_be_same_account)
155
169
  end
156
170
 
157
171
  def entry_type_is_available_for_account
158
172
  return if Pageflow.config_for(account).entry_types.map(&:name).include?(type_name)
159
173
 
160
- errors.add(:type_name, :must_be_available_for_account, type_name: type_name)
174
+ errors.add(:type_name, :must_be_available_for_account, type_name:)
175
+ end
176
+
177
+ def create_default_revision_components
178
+ Pageflow.config_for(self).revision_components.create_defaults(draft)
161
179
  end
162
180
 
163
181
  def update_password!(options)
164
- if options[:password].present?
165
- self.password = options[:password]
166
- end
182
+ self.password = options[:password] if options[:password].present?
167
183
 
168
184
  if options[:password_protected]
169
185
  raise PasswordMissingError if password_digest.blank?
@@ -26,18 +26,22 @@ module Pageflow
26
26
  :type_name,
27
27
  to: :entry)
28
28
 
29
- delegate(:title, :summary, :credits,
29
+ delegate(:layout_version,
30
+ :title, :summary, :credits,
30
31
  :widgets,
31
32
  :storylines, :main_storyline_chapters, :chapters, :pages,
32
33
  :share_url, :share_image_id, :share_image_x, :share_image_y,
33
34
  :share_providers, :active_share_providers,
34
35
  :find_files, :find_file, :find_file_by_perma_id,
36
+ :file_folders,
35
37
  :image_files, :video_files, :audio_files,
36
38
  :locale,
37
39
  :author, :publisher, :keywords,
38
40
  :published_at,
39
41
  :noindex?,
42
+ :comment_threads,
40
43
  :configuration,
44
+ :structured_data_type_name,
41
45
  to: :revision)
42
46
 
43
47
  def resolve_widgets(options = {})
@@ -45,7 +49,11 @@ module Pageflow
45
49
  end
46
50
 
47
51
  def theme
48
- @theme ||= CustomizedTheme.find(entry: entry, theme: revision.theme)
52
+ @theme ||= CustomizedTheme.find(entry: self, theme: revision.theme)
53
+ end
54
+
55
+ def legal_info
56
+ @legal_info ||= site.legal_info(locale:)
49
57
  end
50
58
 
51
59
  def home_button
@@ -67,5 +75,9 @@ module Pageflow
67
75
  def emphasize_new_pages
68
76
  revision.configuration['emphasize_new_pages']
69
77
  end
78
+
79
+ def self.wrap_all_drafts(entries)
80
+ entries.includes(:draft).map { |entry| new(entry, entry.draft) }
81
+ end
70
82
  end
71
83
  end
@@ -0,0 +1,114 @@
1
+ module Pageflow
2
+ # Counts of comment topics and of activity the user has not seen, for
3
+ # displaying an indicator next to an entry in lists of entries.
4
+ #
5
+ # Built for a whole page of entries at once: rendering a list must not
6
+ # query per row.
7
+ #
8
+ # @api private
9
+ class EntryCommentSummary
10
+ attr_reader :topic_count, :unread_topic_count, :unread_reply_count, :unread_resolution_count
11
+
12
+ def self.for_entries(entries, user:)
13
+ entries = entries.to_a
14
+ return {} if entries.empty?
15
+
16
+ threads = threads_by_entry_id(entries)
17
+ read_at = read_at_by_entry_id(entries, user)
18
+
19
+ entries.to_h do |entry|
20
+ [entry.id, build(threads.fetch(entry.id, []),
21
+ read_at: read_at.fetch(entry.id, {}),
22
+ user:)]
23
+ end
24
+ end
25
+
26
+ def initialize(topic_count:, unread_topic_count:, unread_reply_count:,
27
+ unread_resolution_count: 0)
28
+ @topic_count = topic_count
29
+ @unread_topic_count = unread_topic_count
30
+ @unread_reply_count = unread_reply_count
31
+ @unread_resolution_count = unread_resolution_count
32
+ end
33
+
34
+ # Unread activity shows even where no topic is left open: the last
35
+ # one being resolved is exactly what the user should not miss.
36
+ def any?
37
+ topic_count.positive? || unread?
38
+ end
39
+
40
+ def unread?
41
+ unread_topic_count.positive? ||
42
+ unread_reply_count.positive? ||
43
+ unread_resolution_count.positive?
44
+ end
45
+
46
+ # Comment threads live on the draft revision, so entries are reached
47
+ # through their editable revision rather than directly. Resolved ones
48
+ # come along: somebody resolving a thread is activity of its own.
49
+ def self.threads_by_entry_id(entries)
50
+ entry_id_by_revision_id =
51
+ Revision.editable.where(entry_id: entries.map(&:id)).pluck(:id, :entry_id).to_h
52
+
53
+ CommentThread
54
+ .where(revision_id: entry_id_by_revision_id.keys)
55
+ .includes(:comments)
56
+ .group_by { |thread| entry_id_by_revision_id[thread.revision_id] }
57
+ end
58
+ private_class_method :threads_by_entry_id
59
+
60
+ def self.read_at_by_entry_id(entries, user)
61
+ CommentThreadRead
62
+ .where(user:, entry_id: entries.map(&:id))
63
+ .pluck(:entry_id, :comment_thread_perma_id, :read_at)
64
+ .group_by(&:first)
65
+ .transform_values do |rows|
66
+ rows.to_h { |(_entry_id, perma_id, read_at)| [perma_id, read_at] }
67
+ end
68
+ end
69
+ private_class_method :read_at_by_entry_id
70
+
71
+ def self.build(threads, read_at:, user:)
72
+ unread = threads.map { |thread| unread_activity(thread, read_at:, user:) }
73
+
74
+ new(topic_count: threads.count { |thread| thread.resolved_at.nil? },
75
+ unread_topic_count: unread.count { |kinds| kinds.include?(:topic) },
76
+ unread_reply_count: unread.sum { |kinds| kinds.count(:reply) },
77
+ unread_resolution_count: unread.count { |kinds| kinds.include?(:resolution) })
78
+ end
79
+ private_class_method :build
80
+
81
+ # What the user has not seen in a thread, as one symbol per event.
82
+ # The resolution goes by the thread's read mark like the comments do,
83
+ # having none of its own.
84
+ def self.unread_activity(thread, read_at:, user:)
85
+ seen_up_to = [read_at[thread.perma_id], user.unread_comments_since_at].compact.max
86
+ first, *replies = thread.comments.sort_by(&:id)
87
+
88
+ unread_replies = replies.count do |reply|
89
+ unread?(reply.creator_id, reply.created_at, seen_up_to, user)
90
+ end
91
+
92
+ kinds = Array.new(unread_replies, :reply)
93
+ kinds << :topic if first && unread?(first.creator_id, first.created_at, seen_up_to, user)
94
+ kinds << :resolution if unread_resolution?(thread, seen_up_to, user)
95
+ kinds
96
+ end
97
+ private_class_method :unread_activity
98
+
99
+ def self.unread_resolution?(thread, seen_up_to, user)
100
+ thread.resolved_at &&
101
+ unread?(thread.resolved_by_id, thread.resolved_at, seen_up_to, user)
102
+ end
103
+ private_class_method :unread_resolution?
104
+
105
+ # Mirrors the unread rule of the review interface: the user's own
106
+ # activity never counts, and neither does anything from before their
107
+ # baseline. Kept in sync with isUnread in
108
+ # entry_types/scrolled/package/src/review/unreadActivity.js.
109
+ def self.unread?(creator_id, created_at, seen_up_to, user)
110
+ creator_id != user.id && (seen_up_to.nil? || created_at > seen_up_to)
111
+ end
112
+ private_class_method :unread?
113
+ end
114
+ end
@@ -1,11 +1,13 @@
1
1
  module Pageflow
2
- class EntryDuplicate < Struct.new(:original_entry)
2
+ EntryDuplicate = Struct.new(:original_entry) do
3
3
  def create!
4
- create_entry
4
+ ActiveRecord::Base.transaction do
5
+ create_entry
5
6
 
6
- copy_permalink
7
- copy_draft
8
- copy_memberships
7
+ copy_permalink
8
+ copy_draft
9
+ copy_memberships
10
+ end
9
11
 
10
12
  new_entry
11
13
  end
@@ -47,6 +49,7 @@ module Pageflow
47
49
  account: original_entry.account,
48
50
  site: original_entry.site,
49
51
  features_configuration: original_entry.features_configuration,
52
+ perma_id_counter: original_entry.perma_id_counter,
50
53
 
51
54
  skip_draft_creation: true
52
55
  }
@@ -1,5 +1,5 @@
1
1
  module Pageflow
2
- class EntryPublication
2
+ class EntryPublication # rubocop:todo Style/Documentation
3
3
  attr_reader :entry, :attributes, :quota, :user
4
4
 
5
5
  def initialize(entry, attributes, published_entries_quota, user)
@@ -17,7 +17,7 @@ module Pageflow
17
17
  assumed_quota.verify_not_exceeded!
18
18
  entry.publish(attributes.merge(creator: user))
19
19
 
20
- Pageflow.config.hooks.invoke(:entry_published, entry: entry)
20
+ Pageflow.config.hooks.invoke(:entry_published, entry:)
21
21
  end
22
22
 
23
23
  private
@@ -1,6 +1,6 @@
1
1
  module Pageflow
2
- class EntryRoleQuery < ApplicationQuery
3
- class Scope < Scope
2
+ class EntryRoleQuery < ApplicationQuery # rubocop:todo Style/Documentation
3
+ class Scope < Scope # rubocop:todo Style/Documentation
4
4
  attr_reader :user, :scope
5
5
 
6
6
  def initialize(user, scope, table_alias_prefix: nil)
@@ -68,14 +68,14 @@ module Pageflow
68
68
  def entry_account_membership_has_at_least_role(role)
69
69
  membership_has_at_least_role(
70
70
  table_alias: table_alias_for('entry_account'),
71
- role: role
71
+ role:
72
72
  )
73
73
  end
74
74
 
75
75
  def entry_membership_has_at_least_role(role)
76
76
  membership_has_at_least_role(
77
77
  table_alias: table_alias_for('entry'),
78
- role: role
78
+ role:
79
79
  )
80
80
  end
81
81
 
@@ -1,5 +1,5 @@
1
1
  module Pageflow
2
- class EntryTemplate < ApplicationRecord
2
+ class EntryTemplate < ApplicationRecord # rubocop:todo Style/Documentation
3
3
  include ThemeReferencer
4
4
  include SerializedConfiguration
5
5
 
@@ -55,8 +55,8 @@ module Pageflow
55
55
  publisher: default_publisher.presence || Pageflow.config.default_publisher_meta_tag,
56
56
  keywords: default_keywords.presence || Pageflow.config.default_keywords_meta_tag,
57
57
  share_providers: default_share_providers,
58
- theme_name: theme_name,
59
- configuration: configuration,
58
+ theme_name:,
59
+ configuration:,
60
60
  locale: default_locale
61
61
  )
62
62
  end
@@ -66,7 +66,7 @@ module Pageflow
66
66
  end
67
67
 
68
68
  def hashify_provider_array(arr)
69
- Hash[arr.reject(&:blank?).map { |v| [v.to_s, true] }]
69
+ arr.reject(&:blank?).to_h { |v| [v.to_s, true] }
70
70
  end
71
71
  end
72
72
  end