pageflow 15.2.2 → 15.6.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of pageflow might be problematic. Click here for more details.

Files changed (213) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -118
  3. data/README.md +2 -3
  4. data/admins/pageflow/accounts.rb +1 -98
  5. data/admins/pageflow/entry.rb +21 -1
  6. data/admins/pageflow/entry_templates.rb +140 -0
  7. data/admins/pageflow/membership.rb +12 -0
  8. data/admins/pageflow/user.rb +5 -5
  9. data/app/assets/javascripts/pageflow/admin/entries.js +65 -0
  10. data/app/assets/javascripts/pageflow/admin/users.js +1 -1
  11. data/app/assets/javascripts/pageflow/asset_urls.js.erb +1 -0
  12. data/app/assets/javascripts/pageflow/base.js +0 -12
  13. data/app/assets/javascripts/pageflow/components.js +2 -6
  14. data/app/assets/javascripts/pageflow/dist/ui.js +178 -55
  15. data/app/assets/javascripts/pageflow/editor/vendor.js +1 -0
  16. data/app/assets/javascripts/pageflow/vendor.js +12 -10
  17. data/app/assets/stylesheets/pageflow/base.scss +0 -7
  18. data/app/assets/stylesheets/pageflow/editor/base.scss +5 -2
  19. data/app/assets/stylesheets/pageflow/editor/composables.scss +5 -1
  20. data/app/assets/stylesheets/pageflow/editor/drop_down_button.scss +1 -1
  21. data/app/assets/stylesheets/pageflow/editor/emulation_mode_button.scss +44 -55
  22. data/app/assets/stylesheets/pageflow/editor/help.scss +2 -2
  23. data/app/assets/stylesheets/pageflow/editor/select_button.scss +1 -1
  24. data/app/assets/stylesheets/pageflow/editor/sidebar_footer.scss +1 -1
  25. data/app/assets/stylesheets/pageflow/entries.scss +1 -1
  26. data/app/assets/stylesheets/pageflow/loading_spinner.scss +4 -1
  27. data/app/assets/stylesheets/pageflow/navigation_mobile.scss +4 -4
  28. data/app/assets/stylesheets/pageflow/themes/default/anchors.scss +1 -1
  29. data/app/assets/stylesheets/pageflow/themes/default/logo/variant/watermark.scss +1 -1
  30. data/app/assets/stylesheets/pageflow/themes/default/page.scss +7 -0
  31. data/app/assets/stylesheets/pageflow/themes/default/page/anchors.scss +1 -1
  32. data/app/assets/stylesheets/pageflow/themes/default/player_controls/classic/control_bar.scss +1 -1
  33. data/app/assets/stylesheets/pageflow/themes/default/player_controls/classic/info_box.scss +1 -1
  34. data/app/assets/stylesheets/pageflow/themes/default/player_controls/shared/menu_bar.scss +2 -2
  35. data/app/assets/stylesheets/pageflow/themes/default/player_controls/slim/control_bar.scss +2 -2
  36. data/app/assets/stylesheets/pageflow/themes/default/player_controls/slim/info_box.scss +1 -1
  37. data/app/assets/stylesheets/pageflow/themes/default/player_controls/slim/quality_menu.scss +2 -2
  38. data/app/assets/stylesheets/pageflow/themes/default/player_controls/waveform/wave.scss +1 -1
  39. data/app/assets/stylesheets/pageflow/ui/forms.scss +9 -2
  40. data/app/assets/stylesheets/pageflow/ui/input/extended_select_input.scss +2 -2
  41. data/app/assets/stylesheets/pageflow/ui/tooltip.scss +17 -3
  42. data/app/helpers/pageflow/admin/entries_helper.rb +16 -0
  43. data/app/helpers/pageflow/structured_data_helper.rb +0 -2
  44. data/app/models/pageflow/account.rb +21 -1
  45. data/app/models/pageflow/account_role_query.rb +1 -1
  46. data/app/models/pageflow/chapter.rb +3 -9
  47. data/app/models/pageflow/entry.rb +9 -2
  48. data/app/models/pageflow/entry_duplicate.rb +1 -0
  49. data/app/models/pageflow/entry_template.rb +16 -2
  50. data/app/models/pageflow/managed_user_query.rb +1 -1
  51. data/app/models/pageflow/page.rb +1 -4
  52. data/app/models/pageflow/revision.rb +0 -4
  53. data/app/models/pageflow/storyline.rb +2 -9
  54. data/app/policies/pageflow/account_policy.rb +10 -0
  55. data/app/policies/pageflow/entry_template_policy.rb +5 -1
  56. data/app/policies/pageflow/folder_policy.rb +2 -2
  57. data/app/policies/pageflow/membership_policy.rb +2 -2
  58. data/app/policies/pageflow/theming_policy.rb +2 -2
  59. data/app/policies/pageflow/user_policy.rb +1 -1
  60. data/app/views/admin/accounts/_entry_template_details.html.arb +7 -5
  61. data/app/views/admin/accounts/_form.html.erb +3 -49
  62. data/app/views/admin/entries/_attributes_table.html.arb +5 -0
  63. data/app/views/admin/entries/_not_allowed_to_see_entry_types.json.jbuilder +2 -0
  64. data/app/views/admin/entries/entry_types.json.jbuilder +4 -0
  65. data/app/views/admin/entry_templates/_form.html.erb +58 -0
  66. data/app/views/admin/users/_not_allowed_to_see_user_quota.html.erb +3 -0
  67. data/app/views/components/pageflow/admin/entry_templates_tab.rb +48 -0
  68. data/app/views/pageflow/admin/initial_passwords/edit.html.erb +2 -1
  69. data/app/views/pageflow/admin/users/_quota_exhausted.html.erb +1 -1
  70. data/app/views/pageflow/themes/_theme.json.jbuilder +1 -1
  71. data/app/views/pageflow/video_files/_video_file.json.jbuilder +8 -1
  72. data/config/initializers/admin_resource_tabs.rb +5 -0
  73. data/config/initializers/help_entries.rb +1 -5
  74. data/config/initializers/revision_components.rb +5 -0
  75. data/config/locales/de.yml +88 -155
  76. data/config/locales/en.yml +79 -143
  77. data/db/migrate/20200515112500_add_constraints_to_entry_templates.rb +21 -0
  78. data/db/migrate/20200807135200_rename_pageflow_entry_template_entry_type_to_entry_type_name.rb +7 -0
  79. data/entry_types/paged/app/assets/javascripts/pageflow_paged/components.js +7 -0
  80. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/editor.js +1528 -1349
  81. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/frontend.js +9258 -0
  82. data/{app/assets/javascripts/pageflow → entry_types/paged/app/assets/javascripts/pageflow_paged}/dist/react-client.js +1 -1
  83. data/{app/assets/javascripts/pageflow → entry_types/paged/app/assets/javascripts/pageflow_paged}/dist/react-server.js +3 -3
  84. data/entry_types/paged/app/assets/javascripts/pageflow_paged/frontend.js +6 -0
  85. data/entry_types/paged/app/assets/javascripts/pageflow_paged/server_rendering.js +9 -0
  86. data/entry_types/paged/app/assets/javascripts/pageflow_paged/vendor.js +9 -0
  87. data/entry_types/paged/app/assets/javascripts/pageflow_paged/videojs.js +6 -0
  88. data/entry_types/paged/app/controllers/pageflow_paged/application_controller.rb +2 -2
  89. data/{app/helpers/pageflow → entry_types/paged/app/helpers/pageflow_paged}/page_background_asset_helper.rb +4 -3
  90. data/{app/helpers/pageflow → entry_types/paged/app/helpers/pageflow_paged}/react_server_side_rendering_helper.rb +23 -2
  91. data/entry_types/paged/app/views/layouts/pageflow_paged/_loading_spinner_inline_script.html.erb +1 -0
  92. data/entry_types/paged/app/views/layouts/pageflow_paged/application.html.erb +3 -3
  93. data/entry_types/paged/app/views/pageflow_paged/editor/entries/_head.html.erb +4 -2
  94. data/entry_types/paged/app/views/pageflow_paged/entries/_entry.html.erb +1 -1
  95. data/{app/views/pageflow → entry_types/paged/app/views/pageflow_paged}/page_background_asset/_element.html.erb +0 -0
  96. data/{app/views/pageflow → entry_types/paged/app/views/pageflow_paged}/react/_widget.html.erb +0 -0
  97. data/{app/views/pageflow → entry_types/paged/app/views/pageflow_paged}/react/page.html.erb +0 -0
  98. data/entry_types/paged/config/initializers/features.rb +1 -1
  99. data/entry_types/paged/config/initializers/help_entries.rb +17 -0
  100. data/entry_types/paged/config/locales/new/help.de.yml +162 -0
  101. data/entry_types/paged/config/locales/new/help.en.yml +153 -0
  102. data/entry_types/paged/lib/pageflow_paged/engine.rb +13 -0
  103. data/entry_types/paged/lib/pageflow_paged/plugin.rb +5 -1
  104. data/entry_types/paged/lib/pageflow_paged/react.rb +12 -0
  105. data/{lib/pageflow → entry_types/paged/lib/pageflow_paged}/react/page_type.rb +2 -2
  106. data/{lib/pageflow → entry_types/paged/lib/pageflow_paged}/react/widget_type.rb +2 -2
  107. data/entry_types/paged/lib/tasks/pageflow_paged_tasks.rake +7 -0
  108. data/entry_types/paged/vendor/assets/javascripts/development/pageflow_paged/vendor/react-server.js +20613 -0
  109. data/entry_types/paged/vendor/assets/javascripts/development/pageflow_paged/vendor/react.js +21495 -0
  110. data/{vendor/assets/javascripts → entry_types/paged/vendor/assets/javascripts/pageflow_paged/vendor}/dash.all.min.js +0 -0
  111. data/{vendor/assets/javascripts → entry_types/paged/vendor/assets/javascripts/pageflow_paged/vendor}/videojs-dash.js +0 -0
  112. data/{vendor/assets/javascripts → entry_types/paged/vendor/assets/javascripts/pageflow_paged/vendor}/videojs.js +0 -0
  113. data/entry_types/paged/vendor/assets/javascripts/production/pageflow_paged/vendor/react-server.js +24 -0
  114. data/entry_types/paged/vendor/assets/javascripts/production/pageflow_paged/vendor/react.js +24 -0
  115. data/entry_types/scrolled/app/assets/javascripts/pageflow_scrolled/legacy.js +0 -0
  116. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/chapters_controller.rb +2 -2
  117. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/content_elements_controller.rb +14 -4
  118. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/sections_controller.rb +2 -2
  119. data/entry_types/scrolled/app/controllers/pageflow_scrolled/entries_controller.rb +10 -0
  120. data/entry_types/scrolled/app/helpers/pageflow_scrolled/editor/seed_html_helper.rb +7 -0
  121. data/entry_types/scrolled/app/helpers/pageflow_scrolled/entry_json_seed_helper.rb +2 -0
  122. data/entry_types/scrolled/app/helpers/pageflow_scrolled/favicon_helper.rb +21 -0
  123. data/entry_types/scrolled/app/helpers/pageflow_scrolled/react_server_side_rendering_helper.rb +40 -0
  124. data/entry_types/scrolled/app/helpers/pageflow_scrolled/themes_helper.rb +36 -0
  125. data/entry_types/scrolled/app/models/pageflow_scrolled/chapter.rb +3 -9
  126. data/entry_types/scrolled/app/models/pageflow_scrolled/content_element.rb +37 -2
  127. data/entry_types/scrolled/app/models/pageflow_scrolled/section.rb +3 -9
  128. data/entry_types/scrolled/app/models/pageflow_scrolled/storyline.rb +1 -9
  129. data/entry_types/scrolled/app/views/pageflow_scrolled/editor/content_elements/batch.json.jbuilder +2 -0
  130. data/entry_types/scrolled/app/views/pageflow_scrolled/editor/entries/_head.html.erb +1 -7
  131. data/entry_types/scrolled/app/views/pageflow_scrolled/entries/_global_notices.html.erb +10 -0
  132. data/entry_types/scrolled/app/views/pageflow_scrolled/entries/show.html.erb +28 -11
  133. data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_entry.json.jbuilder +3 -0
  134. data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_theme.json.jbuilder +8 -0
  135. data/entry_types/scrolled/app/views/pageflow_scrolled/favicons/_entry.html.erb +10 -0
  136. data/entry_types/scrolled/config/initializers/help_entries.rb +16 -0
  137. data/entry_types/scrolled/config/locales/de.yml +669 -0
  138. data/entry_types/scrolled/config/locales/en.yml +488 -0
  139. data/entry_types/scrolled/config/routes.rb +1 -0
  140. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/install_generator.rb +76 -6
  141. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/favicons/android-chrome-192x192.png +0 -0
  142. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/favicons/android-chrome-512x512.png +0 -0
  143. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/favicons/apple-touch-icon.png +0 -0
  144. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/favicons/browserconfig.xml +9 -0
  145. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/favicons/favicon-16x16.png +0 -0
  146. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/favicons/favicon-32x32.png +0 -0
  147. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/favicons/favicon.ico +0 -0
  148. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/favicons/mstile-150x150.png +0 -0
  149. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/favicons/safari-pinned-tab.svg +46 -0
  150. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/favicons/site.webmanifest +19 -0
  151. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/logoDesktop.svg +56 -0
  152. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/logoMobile.svg +22 -0
  153. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/unmute.mp3 +0 -0
  154. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/themes_plugin.rb.tt +26 -0
  155. data/entry_types/scrolled/lib/pageflow_scrolled/engine.rb +6 -0
  156. data/entry_types/scrolled/lib/pageflow_scrolled/plugin.rb +3 -1
  157. data/entry_types/scrolled/lib/pageflow_scrolled/seeds.rb +90 -30
  158. data/entry_types/scrolled/lib/tasks/pageflow_scrolled/create_bundle_symlinks_for_yarn.rake +33 -0
  159. data/entry_types/scrolled/lib/tasks/pageflow_scrolled/dummy.rake +8 -0
  160. data/entry_types/scrolled/lib/tasks/pageflow_scrolled/storybook.rake +173 -0
  161. data/entry_types/scrolled/package/config/webpack.js +11 -0
  162. data/entry_types/scrolled/package/contentElements-editor.js +316 -185
  163. data/entry_types/scrolled/package/contentElements-frontend.css +1 -0
  164. data/entry_types/scrolled/package/contentElements-frontend.js +940 -304
  165. data/entry_types/scrolled/package/editor.js +2930 -371
  166. data/entry_types/scrolled/package/frontend-server.js +228 -0
  167. data/entry_types/scrolled/package/frontend/EditableText-7093fd0e.js +1071 -0
  168. data/entry_types/scrolled/package/frontend/Viewer-e49e7807.js +387 -0
  169. data/entry_types/scrolled/package/frontend/Wavesurfer-0adf5667.js +375 -0
  170. data/entry_types/scrolled/package/frontend/components-6a6793ca.js +2534 -0
  171. data/entry_types/scrolled/package/frontend/getPrototypeOf-63c7c8e8.js +86 -0
  172. data/entry_types/scrolled/package/frontend/i18n-4dc6c377.js +1092 -0
  173. data/entry_types/scrolled/package/frontend/index.css +9 -0
  174. data/entry_types/scrolled/package/frontend/index.js +5686 -0
  175. data/entry_types/scrolled/package/frontend/useBrowserFeature-91a4c29d.js +33 -0
  176. data/entry_types/scrolled/package/package.json +30 -9
  177. data/entry_types/scrolled/spec/fixtures/audio.m4a +0 -0
  178. data/entry_types/scrolled/spec/fixtures/video.mp4 +0 -0
  179. data/lib/generators/pageflow/initializer/templates/pageflow.rb +14 -9
  180. data/lib/pageflow/ability_mixin.rb +14 -2
  181. data/lib/pageflow/configuration.rb +6 -5
  182. data/lib/pageflow/entry_export_import/revision_serialization.rb +15 -13
  183. data/lib/pageflow/entry_export_import/revision_serialization/import.rb +18 -26
  184. data/lib/pageflow/entry_type_configuration.rb +2 -0
  185. data/lib/pageflow/global_config_api.rb +5 -4
  186. data/lib/pageflow/nested_revision_component.rb +49 -0
  187. data/lib/pageflow/react.rb +4 -2
  188. data/lib/pageflow/revision_component.rb +6 -2
  189. data/lib/pageflow/themes.rb +4 -0
  190. data/lib/pageflow/user_mixin.rb +2 -1
  191. data/lib/pageflow/version.rb +1 -1
  192. data/{packages/pageflow → package}/config/jest/index.js +8 -2
  193. data/{packages/pageflow → package}/config/jest/transformers/jst.js +0 -0
  194. data/{packages/pageflow → package}/config/jest/transformers/upwardBabel.js +0 -0
  195. data/{packages/pageflow → package}/config/webpack.js +7 -0
  196. data/{packages/pageflow → package}/editor.js +482 -1130
  197. data/package/frontend.js +2553 -0
  198. data/{packages/pageflow → package}/package.json +3 -0
  199. data/{packages/pageflow → package}/testHelpers.js +114 -13
  200. data/{packages/pageflow → package}/ui.js +178 -55
  201. data/spec/factories/accounts.rb +3 -1
  202. data/spec/factories/entry_templates.rb +1 -0
  203. data/spec/factories/published_entries.rb +6 -1
  204. data/spec/factories/test_revision_components.rb +4 -0
  205. metadata +95 -36
  206. data/app/assets/javascripts/pageflow/dist/frontend.js +0 -5800
  207. data/app/assets/javascripts/pageflow/videojs.js +0 -6
  208. data/config/initializers/entry_types.rb +0 -4
  209. data/entry_types/scrolled/config/locales/new/de.yml +0 -269
  210. data/entry_types/scrolled/config/locales/new/en.yml +0 -264
  211. data/entry_types/scrolled/lib/tasks/pageflow_scrolled_tasks.rake +0 -96
  212. data/entry_types/scrolled/package/frontend.js +0 -2879
  213. data/packages/pageflow/config/jest/transformers/cssModules.js +0 -1
@@ -0,0 +1,33 @@
1
+ namespace :pageflow_scrolled do
2
+ desc <<-DESC
3
+ Make Yarn use packages embedded in gems.
4
+
5
+ For each package.json dependency of the form
6
+
7
+ .bundle/for-yarn/gem-name/package/path
8
+
9
+ create a symlink in the Git ignored directory .bundle/for-yarn which
10
+ points to the location of the gem as reported by `bundle show`.
11
+
12
+ This script is executed as preinstall script when running `yarn
13
+ install`.
14
+ DESC
15
+ task :create_bundle_symlinks_for_yarn, [:package_path] do |_t, args|
16
+ package_json_path = File.join(args.fetch(:package_path, '.'), 'package.json')
17
+ referenced_gems =
18
+ File.read(package_json_path).scan(%r{.bundle/for-yarn/([a-z_-]+)}).flatten.uniq
19
+
20
+ FileUtils.rm_rf '.bundle/for-yarn'
21
+ FileUtils.mkdir_p '.bundle/for-yarn'
22
+
23
+ puts 'Creating symlinks for .bundle entries in package.json:'
24
+
25
+ referenced_gems.each do |gem|
26
+ symlink = ".bundle/for-yarn/#{gem}"
27
+ gem_location = `bundle show #{gem}`.strip
28
+
29
+ puts "#{symlink} -> #{gem_location}"
30
+ FileUtils.ln_s gem_location, symlink
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,8 @@
1
+ namespace :pageflow_scrolled do
2
+ desc 'Generate dummy app for current Rails version.'
3
+ task :dummy do
4
+ require 'pageflow/support'
5
+ ENV['PAGEFLOW_INSTALL_WEBPACKER'] = 'true'
6
+ Pageflow::Dummy.setup
7
+ end
8
+ end
@@ -0,0 +1,173 @@
1
+ namespace :pageflow_scrolled do
2
+ namespace :storybook do
3
+ namespace :seed do
4
+ desc 'Recreate storybook entry and set up storybook JSON seed/preview-head.html from it'
5
+ task :setup, [:output_dir] => [:destroy_entry, :create_entry,
6
+ :generate_json, :generate_head_html]
7
+
8
+ desc 'Destroy entry to generate Storybook entry JSON seed from'
9
+ task destroy_entry: :environment do
10
+ entry = Pageflow::Entry.find_by_title('Storybook seed')
11
+
12
+ if entry
13
+ puts "Destroying entry 'Storybook seed'"
14
+ entry.destroy
15
+ end
16
+ end
17
+
18
+ desc 'Create entry to generate Storybook entry JSON seed from'
19
+ task create_entry: :environment do
20
+ seeds = Module.new do
21
+ extend Pageflow::Seeds
22
+ extend PageflowScrolled::Seeds
23
+ end
24
+
25
+ if ENV['PAGEFLOW_PAPERCLIP_S3_ROOT']
26
+ Pageflow.config.paperclip_s3_root = ENV['PAGEFLOW_PAPERCLIP_S3_ROOT']
27
+ end
28
+
29
+ if ENV['PAGEFLOW_SCROLLED_DB_SEED_SKIP_FILES'] == 'true'
30
+ puts 'Skipping file uploads to S3.'
31
+ Paperclip::Storage::S3.class_eval { def flush_writes; end }
32
+ end
33
+
34
+ account = seeds.account(name: 'Storybook seed') do |account_in_progress|
35
+ account_in_progress.features_configuration =
36
+ account_in_progress.features_configuration.merge('scrolled_entry_type' => true)
37
+ end
38
+
39
+ seeds.sample_scrolled_entry(
40
+ attributes: {
41
+ title: 'Storybook seed',
42
+ account: account,
43
+ chapters: [],
44
+ image_files: {
45
+ turtle: {
46
+ url: 'https://s3-eu-west-1.amazonaws.com/de.codevise.pageflow.development/pageflow-next/seed-assets/images/04_turtle.jpg',
47
+ configuration: {
48
+ focusX: 24,
49
+ focusY: 40,
50
+ testReferenceName: 'turtle'
51
+ }
52
+ }.stringify_keys,
53
+ churchAfter: {
54
+ url: 'https://s3-eu-west-1.amazonaws.com/de.codevise.pageflow.development/pageflow-next/seed-assets/images/17_haldern_church_after.jpg',
55
+ configuration: {
56
+ testReferenceName: 'churchAfter'
57
+ }
58
+ }.stringify_keys,
59
+ churchBefore: {
60
+ url: 'https://s3-eu-west-1.amazonaws.com/de.codevise.pageflow.development/pageflow-next/seed-assets/images/16_haldern_church_before.jpg',
61
+ configuration: {
62
+ testReferenceName: 'churchBefore'
63
+ }
64
+ }.stringify_keys,
65
+ equirectangularMono: {
66
+ url: 'https://s3-eu-west-1.amazonaws.com/de.codevise.pageflow.development/pageflow-next/seed-assets/images/equirectangular_mono.jpg',
67
+ configuration: {
68
+ testReferenceName: 'equirectangularMono',
69
+ projection: 'equirectangular_mono'
70
+ }
71
+ }.stringify_keys,
72
+ equirectangularStereo: {
73
+ url: 'https://s3-eu-west-1.amazonaws.com/de.codevise.pageflow.development/pageflow-next/seed-assets/images/equirectangular_stereo.png',
74
+ configuration: {
75
+ testReferenceName: 'equirectangularStereo',
76
+ projection: 'equirectangular_stereo'
77
+ }
78
+ }.stringify_keys
79
+ },
80
+ video_files: {
81
+ interview_toni: {
82
+ url: 'https://s3-eu-west-1.amazonaws.com/de.codevise.pageflow.development/pageflow-next/seed-assets/videos/08_interview_toni.mp4',
83
+ width: 1920,
84
+ height: 1080,
85
+ configuration: {
86
+ testReferenceName: 'interview_toni'
87
+ }
88
+ }.stringify_keys
89
+ },
90
+ audio_files: {
91
+ quicktime_jingle: {
92
+ url: 'https://s3-eu-west-1.amazonaws.com/de.codevise.pageflow.development/pageflow-next/seed-assets/audios/quicktime_jingle.m4a',
93
+ configuration: {
94
+ testReferenceName: 'quicktime_jingle'
95
+ }
96
+ }.stringify_keys
97
+ }.stringify_keys,
98
+ text_track_files: {
99
+ sample: {
100
+ url: 'https://s3-eu-west-1.amazonaws.com/de.codevise.pageflow.development/pageflow-next/seed-assets/text_tracks/sample.vtt',
101
+ parent_file_id: 'quicktime_jingle',
102
+ parent_file_model_type: 'Pageflow::AudioFile'
103
+ }.stringify_keys
104
+ }
105
+ },
106
+ options: {
107
+ skip_encoding: ENV.fetch('PAGEFLOW_SKIP_ENCODING_STORYBOOK_FILES', false)
108
+ }
109
+ )
110
+ end
111
+
112
+ desc 'Generate Storybook entry JSON seed'
113
+ task :generate_json, [:output_dir] => :environment do |_t, args|
114
+ entry = Pageflow::Entry.find_by_title('Storybook seed')
115
+
116
+ unless entry
117
+ puts 'Seed entry does not exist. Run pageflow_scrolled:storybook:seed:create_entry first.'
118
+ exit 1
119
+ end
120
+
121
+ if args[:output_dir].blank?
122
+ puts 'Missing argument: Pass output directory via '\
123
+ '`rake pageflow_scrolled:storybook:seed:setup[some/directory]`'
124
+ exit 1
125
+ end
126
+
127
+ draft_entry = Pageflow::DraftEntry.new(entry)
128
+
129
+ seed =
130
+ I18n.with_locale(draft_entry.locale) do
131
+ PageflowScrolled::EntriesController
132
+ .render(inline: 'scrolled_entry_json_seed(json, entry, ' \
133
+ 'translations: {include_inline_editing: true})',
134
+ type: :jbuilder,
135
+ locals: {entry: draft_entry})
136
+ end
137
+
138
+ output = File.join(args[:output_dir], 'seed.json')
139
+ File.write(output, seed)
140
+ puts "Wrote #{output}"
141
+ end
142
+
143
+ desc 'Generate Storybook preview-head.html'
144
+ task :generate_head_html, [:output_dir] => :environment do |_t, args|
145
+ entry = Pageflow::Entry.find_by_title('Storybook seed')
146
+
147
+ unless entry
148
+ puts 'Seed entry does not exist. Run pageflow_scrolled:storybook:seed:create_entry first.'
149
+ exit 1
150
+ end
151
+
152
+ if args[:output_dir].blank?
153
+ puts 'Missing argument: Pass output directory via '\
154
+ '`rake pageflow_scrolled:storybook:seed:setup[some/directory]`'
155
+ exit 1
156
+ end
157
+
158
+ draft_entry = Pageflow::DraftEntry.new(entry)
159
+
160
+ html =
161
+ File.read(File.join(__dir__, '..', '..', '..', 'package', '.storybook',
162
+ 'preview-head.html.template')) +
163
+ PageflowScrolled::EntriesController.render(inline: <<-ERB, locals: {entry: draft_entry})
164
+ <%= scrolled_theme_properties_style_tag(entry.theme) %>
165
+ ERB
166
+
167
+ output = File.join(args[:output_dir], 'preview-head.html')
168
+ File.write(output, html)
169
+ puts "Wrote #{output}"
170
+ end
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,11 @@
1
+ module.exports = {
2
+ resolve: {
3
+ alias: {
4
+ // By default Video.js now includes the http-streaming
5
+ // plugin. To reduce bundle size on mobile devices, we load it
6
+ // dynamically in src/frontend/dash only if HLS is not natively
7
+ // supported by the browser.
8
+ 'video.js$': 'video.js/core.es.js'
9
+ },
10
+ }
11
+ };
@@ -1,33 +1,116 @@
1
- import { editor as editor$1 } from 'pageflow-scrolled/editor';
2
- import { TextInputView, TextAreaInputView, SliderInputView, CheckBoxInputView, UrlInputView, SelectInputView, cssModulesUtils, ConfigurationEditorView } from 'pageflow/ui';
3
- import { FileInputView, ColorInputView, ListView, transientReferences } from 'pageflow/editor';
1
+ import { editor, NoOptionsHintView, buttonStyles } from 'pageflow-scrolled/editor';
2
+ import { FileInputView, CheckBoxInputView, ColorInputView as ColorInputView$1, editor as editor$1, transientReferences, ListView, SliderInputView as SliderInputView$1, SelectInputView as SelectInputView$1, EnumTableCellView } from 'pageflow/editor';
3
+ import { SelectInputView, ColorInputView, TextInputView, SliderInputView, CheckBoxInputView as CheckBoxInputView$1, UrlInputView, ConfigurationEditorView, cssModulesUtils } from 'pageflow/ui';
4
4
  import Marionette from 'backbone.marionette';
5
- import _ from 'underscore';
5
+ import I18n from 'i18n-js';
6
6
  import Backbone from 'backbone';
7
- import I18n$1 from 'i18n-js';
7
+ import _ from 'underscore';
8
8
 
9
- editor$1.contentElementTypes.register('heading', {
9
+ editor.contentElementTypes.register('heading', {
10
+ supportedPositions: ['inline', 'wide'],
11
+ defaultConfig: {
12
+ position: 'wide'
13
+ },
10
14
  configurationEditor: function configurationEditor() {
11
15
  this.tab('general', function () {
12
- this.input('children', TextInputView);
16
+ this.group('ContentElementPosition');
13
17
  });
14
18
  }
15
19
  });
16
20
 
17
- editor$1.contentElementTypes.register('textBlock', {
21
+ function _defineProperty(obj, key, value) {
22
+ if (key in obj) {
23
+ Object.defineProperty(obj, key, {
24
+ value: value,
25
+ enumerable: true,
26
+ configurable: true,
27
+ writable: true
28
+ });
29
+ } else {
30
+ obj[key] = value;
31
+ }
32
+
33
+ return obj;
34
+ }
35
+
36
+ function ownKeys(object, enumerableOnly) {
37
+ var keys = Object.keys(object);
38
+
39
+ if (Object.getOwnPropertySymbols) {
40
+ var symbols = Object.getOwnPropertySymbols(object);
41
+ if (enumerableOnly) symbols = symbols.filter(function (sym) {
42
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
43
+ });
44
+ keys.push.apply(keys, symbols);
45
+ }
46
+
47
+ return keys;
48
+ }
49
+
50
+ function _objectSpread2(target) {
51
+ for (var i = 1; i < arguments.length; i++) {
52
+ var source = arguments[i] != null ? arguments[i] : {};
53
+
54
+ if (i % 2) {
55
+ ownKeys(Object(source), true).forEach(function (key) {
56
+ _defineProperty(target, key, source[key]);
57
+ });
58
+ } else if (Object.getOwnPropertyDescriptors) {
59
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
60
+ } else {
61
+ ownKeys(Object(source)).forEach(function (key) {
62
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
63
+ });
64
+ }
65
+ }
66
+
67
+ return target;
68
+ }
69
+
70
+ editor.contentElementTypes.register('textBlock', {
71
+ supportedPositions: ['inline'],
18
72
  configurationEditor: function configurationEditor() {
19
73
  this.tab('general', function () {
20
- this.input('children', TextAreaInputView);
74
+ this.view(NoOptionsHintView);
21
75
  });
76
+ },
77
+ split: function split(configuration, insertIndex) {
78
+ return [_objectSpread2(_objectSpread2({}, configuration), {}, {
79
+ value: configuration.value.slice(0, insertIndex)
80
+ }), _objectSpread2(_objectSpread2({}, configuration), {}, {
81
+ value: configuration.value.slice(insertIndex)
82
+ })];
83
+ },
84
+ merge: function merge(configurationA, configurationB) {
85
+ // Value might still be empty if text block has not been edited
86
+ var value = (configurationA.value || []).concat(configurationB.value || []);
87
+ return _objectSpread2(_objectSpread2({}, configurationA), {}, {
88
+ // Slate.js does not like empty arrays as value.
89
+ // `inlineEditing/EditableText` sets default value, but only if
90
+ // `value` is falsy.
91
+ value: value.length ? value : undefined
92
+ });
93
+ },
94
+ handleDestroy: function handleDestroy(contentElement) {
95
+ var transientState = contentElement.get('transientState') || {};
96
+
97
+ if (!transientState.editableTextIsSingleBlock) {
98
+ contentElement.postCommand({
99
+ type: 'REMOVE'
100
+ });
101
+ return false;
102
+ }
22
103
  }
23
104
  });
24
105
 
25
- editor$1.contentElementTypes.register('inlineImage', {
106
+ editor.contentElementTypes.register('inlineImage', {
107
+ supportedPositions: ['inline', 'sticky', 'left', 'right', 'wide', 'full'],
26
108
  configurationEditor: function configurationEditor() {
27
109
  this.tab('general', function () {
28
110
  this.input('id', FileInputView, {
29
111
  collection: 'image_files',
30
- fileSelectionHandler: 'contentElementConfiguration'
112
+ fileSelectionHandler: 'contentElementConfiguration',
113
+ positioning: false
31
114
  });
32
115
  this.group('ContentElementCaption');
33
116
  this.group('ContentElementPosition');
@@ -35,13 +118,68 @@ editor$1.contentElementTypes.register('inlineImage', {
35
118
  }
36
119
  });
37
120
 
38
- editor$1.contentElementTypes.register('inlineVideo', {
121
+ editor.contentElementTypes.register('inlineVideo', {
122
+ supportedPositions: ['inline', 'sticky', 'left', 'right', 'full'],
39
123
  configurationEditor: function configurationEditor() {
40
- this.tab('general', function () {});
124
+ this.tab('general', function () {
125
+ this.input('id', FileInputView, {
126
+ collection: 'video_files',
127
+ fileSelectionHandler: 'contentElementConfiguration',
128
+ positioning: false,
129
+ defaultTextTrackFilePropertyName: 'defaultTextTrackFileId'
130
+ });
131
+ this.input('posterId', FileInputView, {
132
+ collection: 'image_files',
133
+ fileSelectionHandler: 'contentElementConfiguration',
134
+ positioning: false
135
+ });
136
+ this.input('autoplay', CheckBoxInputView);
137
+ this.input('atmoDuringPlayback', SelectInputView, {
138
+ values: ['play', 'mute', 'turnDown']
139
+ });
140
+ this.group('ContentElementCaption');
141
+ this.group('ContentElementPosition');
142
+ });
143
+ }
144
+ });
145
+
146
+ editor.contentElementTypes.register('inlineAudio', {
147
+ supportedPositions: ['inline', 'sticky', 'left', 'right', 'full'],
148
+ configurationEditor: function configurationEditor(_ref) {
149
+ var entry = _ref.entry;
150
+ this.tab('general', function () {
151
+ this.input('id', FileInputView, {
152
+ collection: 'audio_files',
153
+ fileSelectionHandler: 'contentElementConfiguration',
154
+ positioning: false,
155
+ defaultTextTrackFilePropertyName: 'defaultTextTrackFileId'
156
+ });
157
+ this.input('posterId', FileInputView, {
158
+ collection: 'image_files',
159
+ fileSelectionHandler: 'contentElementConfiguration',
160
+ positioning: false
161
+ });
162
+ this.input('autoplay', CheckBoxInputView);
163
+ this.input('playerControlVariant', SelectInputView, {
164
+ values: ['classic', 'waveform'],
165
+ ensureValueDefined: true
166
+ });
167
+ this.input('waveformColor', ColorInputView, {
168
+ visibleBinding: 'playerControlVariant',
169
+ visibleBindingValue: 'waveform',
170
+ defaultValue: entry.getTheme().get('options').colors.accent
171
+ });
172
+ this.input('atmoDuringPlayback', SelectInputView, {
173
+ values: ['play', 'mute', 'turnDown']
174
+ });
175
+ this.group('ContentElementCaption');
176
+ this.group('ContentElementPosition');
177
+ });
41
178
  }
42
179
  });
43
180
 
44
- editor$1.contentElementTypes.register('inlineBeforeAfter', {
181
+ editor.contentElementTypes.register('inlineBeforeAfter', {
182
+ supportedPositions: ['inline'],
45
183
  configurationEditor: function configurationEditor() {
46
184
  this.tab('general', function () {
47
185
  this.input('before_id', FileInputView, {
@@ -57,11 +195,11 @@ editor$1.contentElementTypes.register('inlineBeforeAfter', {
57
195
  });
58
196
  this.input('after_label', TextInputView);
59
197
  this.input('initial_slider_position', SliderInputView);
60
- this.input('slider', CheckBoxInputView);
61
- this.input('slider_handle', CheckBoxInputView, {
198
+ this.input('slider', CheckBoxInputView$1);
199
+ this.input('slider_handle', CheckBoxInputView$1, {
62
200
  visibleBinding: 'slider'
63
201
  });
64
- this.input('slider_color', ColorInputView, {
202
+ this.input('slider_color', ColorInputView$1, {
65
203
  visibleBinding: 'slider'
66
204
  });
67
205
  this.group('ContentElementPosition');
@@ -74,23 +212,27 @@ editor$1.contentElementTypes.register('inlineBeforeAfter', {
74
212
  }
75
213
  });
76
214
 
77
- editor$1.contentElementTypes.register('soundDisclaimer', {
215
+ editor.contentElementTypes.register('soundDisclaimer', {
216
+ supportedPositions: ['inline'],
78
217
  configurationEditor: function configurationEditor() {
79
- this.tab('general', function () {});
218
+ this.tab('general', function () {
219
+ this.view(NoOptionsHintView);
220
+ });
80
221
  }
81
222
  });
82
223
 
83
- editor$1.contentElementTypes.register('videoEmbed', {
224
+ editor.contentElementTypes.register('videoEmbed', {
225
+ supportedPositions: ['inline', 'sticky', 'left', 'right', 'full'],
84
226
  configurationEditor: function configurationEditor() {
85
227
  this.tab('general', function () {
86
228
  this.input('videoSource', UrlInputView, {
87
229
  supportedHosts: ['http://youtu.be', 'https://youtu.be', 'http://www.youtube.com', 'https://www.youtube.com', 'http://vimeo.com', 'https://vimeo.com', 'http://www.facebook.com', 'https://www.facebook.com'],
88
- displayPropertyName: 'videoSource',
230
+ displayPropertyName: 'displayVideoSource',
89
231
  required: true,
90
232
  permitHttps: true
91
233
  });
92
- this.input('hideInfo', CheckBoxInputView);
93
- this.input('hideControls', CheckBoxInputView);
234
+ this.input('hideInfo', CheckBoxInputView$1);
235
+ this.input('hideControls', CheckBoxInputView$1);
94
236
  this.input('aspectRatio', SelectInputView, {
95
237
  values: ['wide', 'narrow', 'square', 'portrait']
96
238
  });
@@ -102,99 +244,10 @@ editor$1.contentElementTypes.register('videoEmbed', {
102
244
 
103
245
  var SidebarRouter = Marionette.AppRouter.extend({
104
246
  appRoutes: {
105
- 'scrolled/external_links/:id/': 'links',
106
247
  'scrolled/external_links/:id/:link_id': 'link'
107
248
  }
108
249
  });
109
250
 
110
- function styleInject(css, ref) {
111
- if ( ref === void 0 ) ref = {};
112
- var insertAt = ref.insertAt;
113
-
114
- if (!css || typeof document === 'undefined') { return; }
115
-
116
- var head = document.head || document.getElementsByTagName('head')[0];
117
- var style = document.createElement('style');
118
- style.type = 'text/css';
119
-
120
- if (insertAt === 'top') {
121
- if (head.firstChild) {
122
- head.insertBefore(style, head.firstChild);
123
- } else {
124
- head.appendChild(style);
125
- }
126
- } else {
127
- head.appendChild(style);
128
- }
129
-
130
- if (style.styleSheet) {
131
- style.styleSheet.cssText = css;
132
- } else {
133
- style.appendChild(document.createTextNode(css));
134
- }
135
- }
136
-
137
- var css = ".SidebarListView-module_container__2j0sq {\n margin-top: 30px;\n}\n.SidebarListView-module_add__138Ey{\n border: 1px solid #1c86fe;\n border-radius: 3px;\n box-shadow: inset 0 1px 0 0 #b6d5f8;\n color: white !important;\n display: inline-block;\n font-size: 11px;\n font-weight: bold;\n background-color: #6aacf7;\n background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #6aacf7), color-stop(100%, #2b8efe));\n background-image: -webkit-linear-gradient(#6aacf7, #2b8efe);\n background-image: linear-gradient(#6aacf7, #2b8efe) !important;\n padding: 7px 18px;\n text-decoration: none !important;\n text-shadow: 0 1px 0 #067bff;\n background-clip: padding-box;\n padding-top: 5px;\n padding-bottom: 4px;\n padding-left: 12px\n}\n\n.SidebarListView-module_add__138Ey::before{\n font-family: 'entypo';\n content: \"\\2795\"\n}\n\n.SidebarListView-module_add__138Ey:hover:not(:disabled):not(.SidebarListView-module_disabled__2s_kN) {\n box-shadow: inset 0 1px 0 0 #87baf4;\n cursor: pointer;\n background-color: #559ff2;\n background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #559ff2), color-stop(100%, #1d86fc));\n background-image: -webkit-linear-gradient(#559ff2, #1d86fc);\n background-image: linear-gradient(#559ff2, #1d86fc)\n}\n\n.SidebarListView-module_add__138Ey:active:not(:disabled):not(.SidebarListView-module_disabled__2s_kN) {\n border: 1px solid #1c86fe;\n box-shadow: inset 0 0 8px 4px #0f7efb, inset 0 0 8px 4px #0f7efb, 0 1px 1px 0 #eee\n}\n\n.SidebarListView-module_header__fxwPU{\n display: 'block';\n}\n\n\n.SidebarListView-module_links_container__XDAeC {\n margin-top: 10px;\n}";
138
- var styles = {"container":"SidebarListView-module_container__2j0sq","add":"SidebarListView-module_add__138Ey","disabled":"SidebarListView-module_disabled__2s_kN","header":"SidebarListView-module_header__fxwPU","links_container":"SidebarListView-module_links_container__XDAeC"};
139
- styleInject(css);
140
-
141
- var SidebarListView = Marionette.Layout.extend({
142
- template: function template(data) {
143
- return "\n <a class=\"back\">".concat(I18n.t('pageflow_scrolled.editor.content_elements.externalLinkList.outline'), "</a>\n <a class=\"destroy\">").concat(I18n.t('pageflow_scrolled.editor.content_elements.externalLinkList.destroy'), "</a>\n <div class=\"").concat(styles.container, "\">\n <label class=\"").concat(styles.header, "\">\n <span class=\"name\">").concat(I18n.t('pageflow_scrolled.editor.content_elements.externalLinkList.name'), "</span>\n </label>\n <div class='").concat(styles.links_container, "'></div>\n <a class=\"").concat(styles.add, "\" href=\"\">").concat(I18n.t('pageflow_scrolled.editor.content_elements.externalLinkList.add'), "</a>\n </div>\n ");
144
- },
145
- className: 'manage_external_links',
146
- regions: {
147
- linksContainer: '.' + styles.links_container
148
- },
149
- ui: cssModulesUtils.ui(styles, 'add', 'header'),
150
- events: function events() {
151
- var eventObject = {
152
- 'click a.back': 'goBack',
153
- 'click a.destroy': 'destroyElement'
154
- };
155
- eventObject['click a.' + styles.add] = 'addElement';
156
- return eventObject;
157
- },
158
- initialize: function initialize(options) {
159
- this.listenTo(options.contentElement.configuration, 'change', function () {
160
- this.render();
161
- });
162
- },
163
- onRender: function onRender() {
164
- this.linksContainer.show(new ListView({
165
- collection: this.model,
166
- onEdit: _.bind(this.onEdit, this),
167
- onRemove: _.bind(this.onRemove, this),
168
- contentElement: this.options.contentElement
169
- }));
170
- },
171
- goBack: function goBack() {
172
- editor$1.navigate('', {
173
- trigger: true
174
- });
175
- },
176
- destroyElement: function destroyElement() {
177
- if (confirm(I18n.t('pageflow_scrolled.editor.content_elements.externalLinkList.confirm_delete'))) {
178
- this.options.contentElement.destroy();
179
- this.goBack();
180
- }
181
- },
182
- addElement: function addElement() {
183
- var newModel = this.model.addNewLink();
184
- this.onEdit(newModel);
185
- },
186
- onEdit: function onEdit(linkModel) {
187
- editor$1.navigate("/scrolled/external_links/".concat(this.options.contentElement.get('id'), "/").concat(linkModel.get('id')), {
188
- trigger: true
189
- });
190
- },
191
- onRemove: function onRemove(linkModel) {
192
- if (confirm(I18n.t('pageflow_scrolled.editor.content_elements.externalLinkList.confirm_delete_link'))) {
193
- this.model.remove(linkModel);
194
- }
195
- }
196
- });
197
-
198
251
  var SidebarEditLinkView = Marionette.Layout.extend({
199
252
  template: function template(data) {
200
253
  return "\n <a class=\"back\">".concat(I18n.t('pageflow_scrolled.editor.content_elements.externalLinkList.back'), "</a>\n <a class=\"destroy\">").concat(I18n.t('pageflow_scrolled.editor.content_elements.externalLinkList.destroy'), "</a>\n\n <div class='form_container'></div>\n ");
@@ -219,7 +272,7 @@ var SidebarEditLinkView = Marionette.Layout.extend({
219
272
  this.input('url', TextInputView, {
220
273
  required: true
221
274
  });
222
- this.input('open_in_new_tab', CheckBoxInputView);
275
+ this.input('open_in_new_tab', CheckBoxInputView$1);
223
276
  this.input('thumbnail', FileInputView, {
224
277
  collection: 'image_files',
225
278
  fileSelectionHandler: 'contentElement.externalLinks.link',
@@ -231,20 +284,17 @@ var SidebarEditLinkView = Marionette.Layout.extend({
231
284
  this.input('title', TextInputView, {
232
285
  required: true
233
286
  });
234
- this.input('description', TextAreaInputView, {
235
- size: 'short',
236
- disableLinks: true
237
- });
287
+ this.input('description', TextInputView);
238
288
  });
239
289
  this.formContainer.show(configurationEditor);
240
290
  },
241
291
  goBack: function goBack() {
242
- editor.navigate("/scrolled/external_links/".concat(this.options.contentElement.get('id'), "/"), {
292
+ editor$1.navigate("/scrolled/content_elements/".concat(this.options.contentElement.get('id')), {
243
293
  trigger: true
244
294
  });
245
295
  },
246
296
  destroyLink: function destroyLink() {
247
- if (confirm('pageflow_scrolled.editor.content_elements.externalLinkList.confirm_delete_link')) {
297
+ if (window.confirm(I18n.t('pageflow_scrolled.editor.content_elements.externalLinkList.confirm_delete_link'))) {
248
298
  this.options.collection.remove(this.model);
249
299
  this.goBack();
250
300
  }
@@ -255,7 +305,6 @@ var ExternalLinkModel = Backbone.Model.extend({
255
305
  modelName: 'ExternalLink',
256
306
  i18nKey: 'external_link',
257
307
  mixins: [transientReferences],
258
- initialize: function initialize(options) {},
259
308
  thumbnailUrl: function thumbnailUrl() {
260
309
  var image = this.collection.entry.imageFiles.getByPermaId(this.get('thumbnail'));
261
310
  return image ? image.get('thumbnail_url') : '';
@@ -278,17 +327,7 @@ var ExternalLinkCollection = Backbone.Collection.extend({
278
327
  return attrs.id;
279
328
  },
280
329
  updateConfiguration: function updateConfiguration() {
281
- var _this = this;
282
-
283
- this.configuration.set('links', this.toJSON(), {
284
- silent: true
285
- });
286
- setTimeout(function () {
287
- //triggering change event inside this timeout block because otherwise due to
288
- //some unknown reason page navigates to window.location.origin+window.location.pathname
289
- //ignoring the hash thus causing the page to refresh.
290
- _this.configuration.trigger('change');
291
- }, 0);
330
+ this.configuration.set('links', this.toJSON());
292
331
  },
293
332
  addNewLink: function addNewLink() {
294
333
  var newLink = {
@@ -304,83 +343,118 @@ var ExternalLinkCollection = Backbone.Collection.extend({
304
343
  }
305
344
  });
306
345
 
346
+ ExternalLinkCollection.forContentElement = function (contentElement, entry) {
347
+ return new ExternalLinkCollection(contentElement.configuration.get('links') || [], {
348
+ entry: entry,
349
+ configuration: contentElement.configuration
350
+ });
351
+ };
352
+
307
353
  var SidebarController = Marionette.Controller.extend({
308
354
  initialize: function initialize(options) {
355
+ this.entry = options.entry;
309
356
  this.region = options.region;
310
357
  },
311
- links: function links(id) {
312
- var _this = this;
313
-
314
- this.setModel(id); //if not done without timeout another empty tab view is shown in the sidebar
315
- //to me it seems to be the problem of some method call ordering which gets fixed with this
316
- //hack but in future it should be fixed without having to use setTimeout
317
-
318
- setTimeout(function () {
319
- _this.region.show(new SidebarListView({
320
- model: _this.linksCollection,
321
- contentElement: _this.model,
322
- entry: _this.options.entry
323
- }));
324
- }, 0);
325
- },
326
- link: function link(id, link_id) {
327
- var _this2 = this;
328
-
329
- this.setModel(id);
330
- setTimeout(function () {
331
- _this2.region.show(new SidebarEditLinkView({
332
- model: _this2.linksCollection.get(link_id),
333
- collection: _this2.linksCollection,
334
- contentElement: _this2.model,
335
- entry: _this2.options.entry
336
- }));
337
- }, 0);
338
- },
339
- setModel: function setModel(id) {
340
- this.model = this.options.entry.contentElements.get(id);
341
- var configuration = this.model.configuration;
358
+ link: function link(id, linkId) {
359
+ var contentElement = this.entry.contentElements.get(id);
360
+ var linksCollection = ExternalLinkCollection.forContentElement(contentElement, this.entry);
361
+ this.region.show(new SidebarEditLinkView({
362
+ model: linksCollection.get(linkId),
363
+ collection: linksCollection,
364
+ contentElement: contentElement
365
+ }));
366
+ }
367
+ });
368
+
369
+ function styleInject(css, ref) {
370
+ if ( ref === void 0 ) ref = {};
371
+ var insertAt = ref.insertAt;
372
+
373
+ if (!css || typeof document === 'undefined') { return; }
374
+
375
+ var head = document.head || document.getElementsByTagName('head')[0];
376
+ var style = document.createElement('style');
377
+ style.type = 'text/css';
342
378
 
343
- if (!configuration.get('links')) {
344
- configuration.set('links', []);
379
+ if (insertAt === 'top') {
380
+ if (head.firstChild) {
381
+ head.insertBefore(style, head.firstChild);
382
+ } else {
383
+ head.appendChild(style);
345
384
  }
385
+ } else {
386
+ head.appendChild(style);
387
+ }
346
388
 
347
- this.linksCollection = new ExternalLinkCollection(configuration.get('links'), {
348
- entry: this.options.entry,
349
- configuration: configuration
389
+ if (style.styleSheet) {
390
+ style.styleSheet.cssText = css;
391
+ } else {
392
+ style.appendChild(document.createTextNode(css));
393
+ }
394
+ }
395
+
396
+ var css = ".SidebarListView-module_linksContainer__HvWq- {\n}\n";
397
+ var styles = {"linksContainer":"SidebarListView-module_linksContainer__HvWq-"};
398
+ styleInject(css);
399
+
400
+ var SidebarListView = Marionette.Layout.extend({
401
+ template: function template(data) {
402
+ return "\n <div class='".concat(styles.linksContainer, "'></div>\n <button class=\"").concat(buttonStyles.addButton, "\">\n ").concat(I18n.t('pageflow_scrolled.editor.content_elements.externalLinkList.add'), "\n </button>\n ");
403
+ },
404
+ regions: cssModulesUtils.ui(styles, 'linksContainer'),
405
+ events: cssModulesUtils.events(buttonStyles, {
406
+ 'click addButton': 'addElement'
407
+ }),
408
+ onRender: function onRender() {
409
+ this.linksContainer.show(new ListView({
410
+ collection: this.collection,
411
+ onEdit: _.bind(this.onEdit, this),
412
+ onRemove: _.bind(this.onRemove, this)
413
+ }));
414
+ },
415
+ addElement: function addElement() {
416
+ var newModel = this.collection.addNewLink();
417
+ this.onEdit(newModel);
418
+ },
419
+ onEdit: function onEdit(linkModel) {
420
+ editor.navigate("/scrolled/external_links/".concat(this.options.contentElement.id, "/").concat(linkModel.id), {
421
+ trigger: true
350
422
  });
423
+ },
424
+ onRemove: function onRemove(linkModel) {
425
+ if (window.confirm(I18n.t('pageflow_scrolled.editor.content_elements.externalLinkList.confirm_delete_link'))) {
426
+ this.collection.remove(linkModel);
427
+ }
351
428
  }
352
429
  });
353
430
 
354
431
  //router defines the URL hash path mapping and controller provides functions for the paths
355
432
 
356
- editor$1.registerSideBarRouting({
433
+ editor.registerSideBarRouting({
357
434
  router: SidebarRouter,
358
435
  controller: SidebarController
359
436
  }); // register external link list content element configuration editor for sidebar
360
437
 
361
- editor$1.contentElementTypes.register('externalLinkList', {
362
- configurationEditor: function configurationEditor() {
438
+ editor.contentElementTypes.register('externalLinkList', {
439
+ supportedPositions: ['inline'],
440
+ configurationEditor: function configurationEditor(_ref) {
441
+ var entry = _ref.entry;
363
442
  this.tab('general', function () {
364
- var externalListModel = this.model.parent; //redirect to special hash path that is specific to external links only
365
-
366
- editor$1.navigate("/scrolled/external_links/".concat(externalListModel.get('id'), "/"), {
367
- trigger: true
443
+ this.view(SidebarListView, {
444
+ contentElement: this.model.parent,
445
+ collection: ExternalLinkCollection.forContentElement(this.model.parent, entry)
368
446
  });
369
447
  });
370
448
  }
371
449
  }); // register file handler for thumbnail of external link
372
450
 
373
- editor$1.registerFileSelectionHandler('contentElement.externalLinks.link', function (options) {
451
+ editor.registerFileSelectionHandler('contentElement.externalLinks.link', function (options) {
374
452
  var contentElement = options.entry.contentElements.get(options.contentElementId);
375
- var links = contentElement.configuration.get('links');
453
+ var links = ExternalLinkCollection.forContentElement(contentElement, options.entry);
376
454
 
377
455
  this.call = function (file) {
378
- var link = links.find(function (link) {
379
- return link.id == options.id;
380
- });
381
- link.thumbnail = file.get('perma_id');
382
- contentElement.configuration.set('links', links);
383
- contentElement.configuration.trigger('change', contentElement.configuration);
456
+ var link = links.get(options.id);
457
+ link.setReference('thumbnail', file);
384
458
  };
385
459
 
386
460
  this.getReferer = function () {
@@ -390,21 +464,78 @@ editor$1.registerFileSelectionHandler('contentElement.externalLinks.link', funct
390
464
 
391
465
  var DatawrapperAdView = Marionette.ItemView.extend({
392
466
  template: function template(data) {
393
- return "\n <form action=\"https://datawrapper.de/chart/create\" method=\"POST\" target=\"_blank\">\n <input type=\"hidden\" name=\"theme\" value=\"pageflow\" />\n <input type=\"submit\" value=\"".concat(I18n$1.t('pageflow_scrolled.editor.content_elements.dataWrapperChart.attributes.create_chart.label'), "\" />\n </form>\n ");
467
+ return "\n <form action=\"https://datawrapper.de/chart/create\" method=\"POST\" target=\"_blank\">\n <input type=\"hidden\" name=\"theme\" value=\"pageflow\" />\n <input type=\"submit\" value=\"".concat(I18n.t('pageflow_scrolled.editor.content_elements.dataWrapperChart.attributes.create_chart.label'), "\" />\n </form>\n ");
394
468
  },
395
469
  className: 'datawrapper_ad'
396
470
  });
397
471
 
398
- editor$1.contentElementTypes.register('dataWrapperChart', {
472
+ editor.contentElementTypes.register('dataWrapperChart', {
473
+ supportedPositions: ['inline', 'sticky', 'left', 'right', 'full'],
399
474
  configurationEditor: function configurationEditor() {
400
475
  this.tab('general', function () {
401
476
  this.input('url', UrlInputView, {
402
477
  supportedHosts: ['http://cf.datawrapper.de', 'https://cf.datawrapper.de', 'http://datawrapper.dwcdn.de', 'https://datawrapper.dwcdn.de', 'http://datawrapper.dwcdn.net', 'https://datawrapper.dwcdn.net', 'http://charts.datawrapper.de', 'https://charts.datawrapper.de'],
403
- displayPropertyName: 'url',
478
+ displayPropertyName: 'displayUrl',
404
479
  required: true,
405
480
  permitHttps: true
406
481
  });
407
482
  this.view(DatawrapperAdView);
483
+ this.input('title', TextInputView, {
484
+ placeholder: I18n.t('pageflow_scrolled.public.chart.default_title')
485
+ });
486
+ this.input('backgroundColor', ColorInputView, {
487
+ defaultValue: '#323d4d'
488
+ });
489
+ this.group('ContentElementCaption');
490
+ this.group('ContentElementPosition');
491
+ });
492
+ }
493
+ });
494
+
495
+ editor.contentElementTypes.register('vrImage', {
496
+ configurationEditor: function configurationEditor() {
497
+ this.tab('general', function () {
498
+ this.input('image', FileInputView, {
499
+ collection: 'image_files',
500
+ fileSelectionHandler: 'contentElementConfiguration',
501
+ filter: 'with_projection',
502
+ positioning: false
503
+ });
504
+ this.input('initialYaw', SliderInputView$1, {
505
+ unit: '°',
506
+ minValue: -180,
507
+ maxValue: 180
508
+ });
509
+ this.input('initialPitch', SliderInputView$1, {
510
+ unit: '°',
511
+ minValue: -60,
512
+ maxValue: 60
513
+ });
514
+ this.group('ContentElementCaption');
515
+ this.group('ContentElementPosition');
408
516
  });
409
517
  }
410
518
  });
519
+ editor.fileTypes.modify('image_files', {
520
+ configurationEditorInputs: function configurationEditorInputs(model) {
521
+ var values = ['equirectangular_mono', 'equirectangular_stereo'];
522
+ return [{
523
+ name: 'projection',
524
+ inputView: SelectInputView$1,
525
+ inputViewOptions: {
526
+ includeBlank: true,
527
+ values: values
528
+ }
529
+ }];
530
+ },
531
+ confirmUploadTableColumns: [{
532
+ name: 'projection',
533
+ cellView: EnumTableCellView
534
+ }],
535
+ filters: [{
536
+ name: 'with_projection',
537
+ matches: function matches(file) {
538
+ return !!file.configuration.get('projection');
539
+ }
540
+ }]
541
+ });