pageflow 15.2.2 → 15.3.0

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 (139) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +338 -85
  3. data/admins/pageflow/accounts.rb +1 -98
  4. data/admins/pageflow/entry.rb +21 -1
  5. data/admins/pageflow/entry_templates.rb +140 -0
  6. data/admins/pageflow/membership.rb +12 -0
  7. data/admins/pageflow/user.rb +5 -3
  8. data/app/assets/javascripts/pageflow/admin/entries.js +65 -0
  9. data/app/assets/javascripts/pageflow/admin/users.js +1 -1
  10. data/app/assets/javascripts/pageflow/asset_urls.js.erb +1 -0
  11. data/app/assets/javascripts/pageflow/base.js +0 -12
  12. data/app/assets/javascripts/pageflow/components.js +2 -6
  13. data/app/assets/javascripts/pageflow/dist/ui.js +47 -14
  14. data/app/assets/javascripts/pageflow/vendor.js +13 -10
  15. data/app/assets/stylesheets/pageflow/base.scss +0 -7
  16. data/app/assets/stylesheets/pageflow/editor/base.scss +2 -0
  17. data/app/assets/stylesheets/pageflow/editor/composables.scss +5 -1
  18. data/app/assets/stylesheets/pageflow/editor/emulation_mode_button.scss +44 -55
  19. data/app/assets/stylesheets/pageflow/editor/help.scss +2 -2
  20. data/app/assets/stylesheets/pageflow/ui/tooltip.scss +17 -3
  21. data/app/helpers/pageflow/admin/entries_helper.rb +16 -0
  22. data/app/helpers/pageflow/structured_data_helper.rb +0 -2
  23. data/app/models/pageflow/account.rb +21 -1
  24. data/app/models/pageflow/entry.rb +9 -2
  25. data/app/models/pageflow/entry_duplicate.rb +1 -0
  26. data/app/models/pageflow/entry_template.rb +16 -2
  27. data/app/policies/pageflow/account_policy.rb +10 -0
  28. data/app/policies/pageflow/entry_template_policy.rb +5 -1
  29. data/app/views/admin/accounts/_entry_template_details.html.arb +7 -5
  30. data/app/views/admin/accounts/_form.html.erb +3 -49
  31. data/app/views/admin/entries/_attributes_table.html.arb +5 -0
  32. data/app/views/admin/entries/_not_allowed_to_see_entry_types.json.jbuilder +2 -0
  33. data/app/views/admin/entries/entry_types.json.jbuilder +4 -0
  34. data/app/views/admin/entry_templates/_form.html.erb +58 -0
  35. data/app/views/admin/users/_not_allowed_to_see_user_quota.html.erb +3 -0
  36. data/app/views/components/pageflow/admin/entry_templates_tab.rb +48 -0
  37. data/app/views/pageflow/admin/users/_quota_exhausted.html.erb +1 -1
  38. data/config/initializers/admin_resource_tabs.rb +5 -0
  39. data/config/initializers/help_entries.rb +1 -5
  40. data/config/locales/de.yml +88 -155
  41. data/config/locales/en.yml +79 -143
  42. data/db/migrate/20200515112500_add_constraints_to_entry_templates.rb +21 -0
  43. data/db/migrate/20200807135200_rename_pageflow_entry_template_entry_type_to_entry_type_name.rb +7 -0
  44. data/entry_types/paged/app/assets/javascripts/pageflow_paged/components.js +7 -0
  45. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/editor.js +1479 -1391
  46. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/frontend.js +9218 -0
  47. data/{app/assets/javascripts/pageflow → entry_types/paged/app/assets/javascripts/pageflow_paged}/dist/react-client.js +1 -1
  48. data/{app/assets/javascripts/pageflow → entry_types/paged/app/assets/javascripts/pageflow_paged}/dist/react-server.js +3 -3
  49. data/entry_types/paged/app/assets/javascripts/pageflow_paged/frontend.js +6 -0
  50. data/entry_types/paged/app/assets/javascripts/pageflow_paged/server_rendering.js +9 -0
  51. data/entry_types/paged/app/assets/javascripts/pageflow_paged/vendor.js +8 -0
  52. data/entry_types/paged/app/controllers/pageflow_paged/application_controller.rb +2 -2
  53. data/{app/helpers/pageflow → entry_types/paged/app/helpers/pageflow_paged}/page_background_asset_helper.rb +4 -3
  54. data/{app/helpers/pageflow → entry_types/paged/app/helpers/pageflow_paged}/react_server_side_rendering_helper.rb +23 -2
  55. data/entry_types/paged/app/views/layouts/pageflow_paged/application.html.erb +2 -2
  56. data/entry_types/paged/app/views/pageflow_paged/editor/entries/_head.html.erb +2 -2
  57. data/entry_types/paged/app/views/pageflow_paged/entries/_entry.html.erb +1 -1
  58. data/{app/views/pageflow → entry_types/paged/app/views/pageflow_paged}/page_background_asset/_element.html.erb +0 -0
  59. data/{app/views/pageflow → entry_types/paged/app/views/pageflow_paged}/react/_widget.html.erb +0 -0
  60. data/{app/views/pageflow → entry_types/paged/app/views/pageflow_paged}/react/page.html.erb +0 -0
  61. data/entry_types/paged/config/initializers/features.rb +1 -1
  62. data/entry_types/paged/config/initializers/help_entries.rb +17 -0
  63. data/entry_types/paged/config/locales/new/help.de.yml +162 -0
  64. data/entry_types/paged/config/locales/new/help.en.yml +153 -0
  65. data/entry_types/paged/lib/pageflow_paged/engine.rb +13 -0
  66. data/entry_types/paged/lib/pageflow_paged/plugin.rb +5 -1
  67. data/entry_types/paged/lib/pageflow_paged/react.rb +12 -0
  68. data/{lib/pageflow → entry_types/paged/lib/pageflow_paged}/react/page_type.rb +2 -2
  69. data/{lib/pageflow → entry_types/paged/lib/pageflow_paged}/react/widget_type.rb +2 -2
  70. data/entry_types/paged/vendor/assets/javascripts/development/pageflow_paged/vendor/react-server.js +20613 -0
  71. data/entry_types/paged/vendor/assets/javascripts/development/pageflow_paged/vendor/react.js +21495 -0
  72. data/entry_types/paged/vendor/assets/javascripts/production/pageflow_paged/vendor/react-server.js +24 -0
  73. data/entry_types/paged/vendor/assets/javascripts/production/pageflow_paged/vendor/react.js +24 -0
  74. data/entry_types/scrolled/app/assets/javascripts/pageflow_scrolled/legacy.js +0 -0
  75. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/chapters_controller.rb +2 -2
  76. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/content_elements_controller.rb +14 -4
  77. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/sections_controller.rb +2 -2
  78. data/entry_types/scrolled/app/controllers/pageflow_scrolled/entries_controller.rb +8 -0
  79. data/entry_types/scrolled/app/helpers/pageflow_scrolled/editor/seed_html_helper.rb +6 -0
  80. data/entry_types/scrolled/app/helpers/pageflow_scrolled/entry_json_seed_helper.rb +2 -0
  81. data/entry_types/scrolled/app/helpers/pageflow_scrolled/react_server_side_rendering_helper.rb +33 -0
  82. data/entry_types/scrolled/app/helpers/pageflow_scrolled/themes_helper.rb +8 -0
  83. data/entry_types/scrolled/app/models/pageflow_scrolled/content_element.rb +38 -0
  84. data/entry_types/scrolled/app/views/pageflow_scrolled/editor/content_elements/batch.json.jbuilder +2 -0
  85. data/entry_types/scrolled/app/views/pageflow_scrolled/editor/entries/_head.html.erb +1 -7
  86. data/entry_types/scrolled/app/views/pageflow_scrolled/entries/show.html.erb +19 -3
  87. data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_entry.json.jbuilder +3 -0
  88. data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_theme.json.jbuilder +7 -0
  89. data/entry_types/scrolled/config/initializers/help_entries.rb +16 -0
  90. data/entry_types/scrolled/config/locales/new/de.yml +345 -13
  91. data/entry_types/scrolled/config/locales/new/en.yml +257 -14
  92. data/entry_types/scrolled/config/routes.rb +1 -0
  93. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/install_generator.rb +28 -0
  94. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/logoDesktop.svg +56 -0
  95. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/logoMobile.svg +22 -0
  96. data/entry_types/scrolled/lib/pageflow_scrolled/engine.rb +4 -0
  97. data/entry_types/scrolled/lib/pageflow_scrolled/plugin.rb +3 -1
  98. data/entry_types/scrolled/lib/pageflow_scrolled/seeds.rb +90 -30
  99. data/entry_types/scrolled/lib/tasks/pageflow_scrolled_tasks.rake +64 -27
  100. data/entry_types/scrolled/package/contentElements-editor.js +242 -183
  101. data/entry_types/scrolled/package/contentElements-frontend.css +1 -0
  102. data/entry_types/scrolled/package/contentElements-frontend.js +624 -279
  103. data/entry_types/scrolled/package/editor.js +2561 -363
  104. data/entry_types/scrolled/package/frontend-server.js +228 -0
  105. data/entry_types/scrolled/package/frontend/EditableText-4264c349.js +1993 -0
  106. data/entry_types/scrolled/package/frontend/Wavesurfer-c3c45324.js +378 -0
  107. data/entry_types/scrolled/package/frontend/components-cfe6a479.js +2115 -0
  108. data/entry_types/scrolled/package/frontend/getPrototypeOf-63c7c8e8.js +86 -0
  109. data/entry_types/scrolled/package/frontend/index.css +9 -0
  110. data/entry_types/scrolled/package/frontend/index.js +4425 -0
  111. data/entry_types/scrolled/package/package.json +17 -6
  112. data/entry_types/scrolled/spec/fixtures/audio.m4a +0 -0
  113. data/entry_types/scrolled/spec/fixtures/video.mp4 +0 -0
  114. data/lib/generators/pageflow/initializer/templates/pageflow.rb +20 -9
  115. data/lib/pageflow/ability_mixin.rb +14 -2
  116. data/lib/pageflow/configuration.rb +6 -5
  117. data/lib/pageflow/engine.rb +1 -0
  118. data/lib/pageflow/entry_type_configuration.rb +1 -0
  119. data/lib/pageflow/global_config_api.rb +5 -4
  120. data/lib/pageflow/react.rb +4 -2
  121. data/lib/pageflow/version.rb +1 -1
  122. data/{packages/pageflow → package}/config/jest/index.js +2 -1
  123. data/{packages/pageflow → package}/config/jest/transformers/jst.js +0 -0
  124. data/{packages/pageflow → package}/config/jest/transformers/upwardBabel.js +0 -0
  125. data/package/config/webpack.js +22 -0
  126. data/{packages/pageflow → package}/editor.js +480 -1129
  127. data/package/frontend.js +2525 -0
  128. data/{packages/pageflow → package}/package.json +3 -0
  129. data/{packages/pageflow → package}/testHelpers.js +114 -13
  130. data/{packages/pageflow → package}/ui.js +47 -14
  131. data/spec/factories/accounts.rb +3 -1
  132. data/spec/factories/entry_templates.rb +1 -0
  133. data/spec/factories/published_entries.rb +6 -1
  134. metadata +62 -26
  135. data/app/assets/javascripts/pageflow/dist/frontend.js +0 -5800
  136. data/config/initializers/entry_types.rb +0 -4
  137. data/entry_types/scrolled/package/frontend.js +0 -2879
  138. data/packages/pageflow/config/jest/transformers/cssModules.js +0 -1
  139. data/packages/pageflow/config/webpack.js +0 -14
@@ -0,0 +1,22 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Generator: Adobe Illustrator 20.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3
+ <svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4
+ viewBox="-50 -50 272.07254 338.90793" xml:space="preserve">
5
+ <style type="text/css">
6
+ .st0{fill:#343434;}
7
+ </style>
8
+ <title>Pageflow</title>
9
+ <path class="st0" d="M106.3,238.9l-86.7-86.7C-3.7,129-2,105.3,3.4,89.5c3.8-10.6,9.7-20.2,17.4-28.4l6.5,6.5
10
+ C20.5,74.8,15.3,83.4,12,92.8c-6.6,19.3-1.8,37.1,14,52.9l80.2,80.2l39.1-39.1l6.5,6.5L106.3,238.9z"/>
11
+ <path class="st0" d="M104.2,234.5c-23.2-23.2-21.8-46.8-16.5-62.4c3.6-10.5,9.4-20,17-28.1l42.3-42.3l6.5,6.5l-42.3,42.3
12
+ c-6.6,7.2-11.7,15.7-14.9,24.9c-6.3,19-1.5,36.8,14.3,52.6L104.2,234.5z"/>
13
+ <path class="st0" d="M61.3,193.9c-23.2-23.2-21.8-46.8-16.5-62.4c3.6-10.5,9.4-20,17-28.1l84-84l6.5,6.5l-84,84
14
+ c-6.6,7.2-11.7,15.7-14.9,24.9c-6.4,19.1-1.5,36.8,14.4,52.7L61.3,193.9z"/>
15
+ <path class="st0" d="M151.6,110.1l-6.5-6.5c6.7-7.2,11.8-15.7,15-25c6.4-19.1,1.6-36.9-14.3-52.7S112.1,5.4,92.6,12.2
16
+ C83.1,15.7,74.4,21,67,27.8L25.1,69.7l-6.5-6.5l41.9-41.9c8.3-7.8,18.1-13.8,28.8-17.7c16-5.6,39.9-7.5,63.1,15.8
17
+ s21.7,46.8,16.4,62.5C165.1,92.4,159.2,102,151.6,110.1z"/>
18
+ <path class="st0" d="M151.2,194l-6.5-6.5l3.2,3.2l-3.3-3.2c6.5-7.1,11.5-15.5,14.6-24.6c6.2-18.9,1.3-36.5-14.6-52.4l6.5-6.5
19
+ c23.2,23.2,21.9,46.6,16.8,62.1C164.5,176.5,158.7,186,151.2,194z"/>
20
+ <path class="st0" d="M102.2,69.6"/>
21
+ <path class="st0" d="M106.8,224.7"/>
22
+ </svg>
@@ -5,5 +5,9 @@ module PageflowScrolled
5
5
 
6
6
  config.paths.add('lib', eager_load: true)
7
7
  config.i18n.load_path += Dir[config.root.join('config', 'locales', '**', '*.yml').to_s]
8
+
9
+ initializer 'pageflow_scrolled.assets.precompile' do |app|
10
+ app.config.assets.precompile += %w[pageflow_scrolled/legacy.js]
11
+ end
8
12
  end
9
13
  end
@@ -2,7 +2,9 @@ module PageflowScrolled
2
2
  # @api private
3
3
  class Plugin < Pageflow::Plugin
4
4
  def configure(config)
5
- config.entry_types.register(PageflowScrolled.entry_type)
5
+ config.features.register('scrolled_entry_type') do |feature_config|
6
+ feature_config.entry_types.register(PageflowScrolled.entry_type)
7
+ end
6
8
 
7
9
  config.for_entry_type(PageflowScrolled.entry_type) do |c|
8
10
  c.file_types.register(Pageflow::BuiltInFileType.image)
@@ -20,9 +20,17 @@ module PageflowScrolled
20
20
  # to determine the React component used to render this content element.
21
21
  # @option attributes [Hash] :image_files A hash mapping image
22
22
  # names used in properties like `backdrop.image` to urls.
23
+ # @option attributes [Hash] :audio_files A hash mapping audio files to urls.
24
+ # @option attributes [Hash] :video_files A hash mapping video
25
+ # names used in properties like `backdrop.video` to urls.
26
+ # @option attributes [Hash] :text_track_files A hash mapping text track files to urls.
23
27
  # @yield [entry] a block to be called before the entry is saved
28
+ # @param [Hash] options options for entry and files creation
29
+ # @option options [Boolean] :skip_encoding
30
+ # Flag indicating whether to encode video and audio files on creation or set them directly to
31
+ # encoded
24
32
  # @return [Entry] newly created entry
25
- def sample_scrolled_entry(attributes)
33
+ def sample_scrolled_entry(attributes:, options: {})
26
34
  entry = Pageflow::Entry.where(type_name: 'scrolled')
27
35
  .where(attributes.slice(:account, :title))
28
36
  .first
@@ -30,18 +38,44 @@ module PageflowScrolled
30
38
  if entry.nil?
31
39
  entry = Pageflow::Entry.create!(type_name: 'scrolled',
32
40
  **attributes.except(:chapters,
33
- :image_files)) do |created_entry|
41
+ :image_files,
42
+ :video_files,
43
+ :audio_files,
44
+ :text_track_files)) do |created_entry|
34
45
  created_entry.theming = attributes.fetch(:account).default_theming
35
46
 
36
47
  say_creating_scrolled_entry(created_entry)
37
48
  yield(created_entry) if block_given?
38
49
  end
39
50
 
40
- image_files_by_name = create_image_files(Pageflow::DraftEntry.new(entry),
41
- attributes.fetch(:image_files, {}))
51
+ draft_entry = Pageflow::DraftEntry.new(entry)
52
+
53
+ image_files_by_name = create_files(draft_entry,
54
+ :image,
55
+ attributes.fetch(:image_files, {}))
56
+
57
+ video_files_by_name = create_files(draft_entry,
58
+ :video,
59
+ attributes.fetch(:video_files, {}),
60
+ options.fetch(:skip_encoding, false))
61
+
62
+ audio_files_by_name = create_files(draft_entry,
63
+ :audio,
64
+ attributes.fetch(:audio_files, {}),
65
+ options.fetch(:skip_encoding, false))
66
+
67
+ files_by_name = image_files_by_name.merge(video_files_by_name).merge(audio_files_by_name)
68
+
69
+ # rewrite parent file references to actual ids
70
+ text_tracks_by_name = attributes.fetch(:text_track_files, {})
71
+ text_tracks_by_name.each do |_name, text_track_config|
72
+ parent_file = files_by_name.fetch(text_track_config['parent_file_id'])
73
+ text_track_config['parent_file_id'] = parent_file.id
74
+ end
75
+ create_files(draft_entry, :text_track, text_tracks_by_name)
42
76
 
43
77
  attributes[:chapters].each_with_index do |chapter_config, i|
44
- create_chapter(entry, chapter_config, i, image_files_by_name)
78
+ create_chapter(entry, chapter_config, i, files_by_name)
45
79
  end
46
80
  end
47
81
 
@@ -58,18 +92,46 @@ module PageflowScrolled
58
92
  say(" sample scrolled entry '#{entry.title}'\n")
59
93
  end
60
94
 
61
- def create_image_files(draft_entry, image_file_data_by_name)
62
- image_file_data_by_name.transform_values do |data|
63
- say(" creating image file from #{data['url']}")
95
+ def create_files(draft_entry, file_type, file_data_by_name, skip_encoding = false)
96
+ file_data_by_name.transform_values do |data|
97
+ say(" creating #{file_type} file from #{data['url']}")
98
+
99
+ file_state = %i[image text_track].include?(file_type) ? 'processed' : 'uploading'
100
+ file = draft_entry.create_file!(Pageflow::BuiltInFileType.send(file_type),
101
+ state: file_state,
102
+ attachment: URI.parse(data['url']),
103
+ configuration: data['configuration'],
104
+ parent_file_model_type: data['parent_file_model_type'],
105
+ parent_file_id: data['parent_file_id'],
106
+ **data.slice('width', 'height').symbolize_keys)
107
+ if %i[audio video].include?(file_type)
108
+ if skip_encoding
109
+ file.update!(state: 'encoded')
110
+ if file_type.eql?(:video)
111
+ file.update!(output_presences: {
112
+ "dash-playlist" => true,
113
+ "hls-playlist" => true,
114
+ "dash-medium"=> true,
115
+ "hls-medium" => true,
116
+ "dash-high" => true,
117
+ "hls-high" => true,
118
+ "dash-low" => true,
119
+ "hls-low" => true,
120
+ "medium" => true,
121
+ "high" => true,
122
+ "low" => true
123
+ })
124
+ end
125
+ else
126
+ file.publish!
127
+ end
128
+ end
64
129
 
65
- draft_entry.create_file!(Pageflow::BuiltInFileType.image,
66
- state: 'processed',
67
- attachment: URI.parse(data['url']),
68
- configuration: data['configuration'])
130
+ file
69
131
  end
70
132
  end
71
133
 
72
- def create_chapter(entry, chapter_config, position, image_files_by_name)
134
+ def create_chapter(entry, chapter_config, position, files_by_name)
73
135
  section_configs = chapter_config.delete('sections') || []
74
136
  chapter = Chapter.create!(
75
137
  revision: entry.draft,
@@ -81,34 +143,33 @@ module PageflowScrolled
81
143
  )
82
144
 
83
145
  section_configs.each_with_index do |section_config, i|
84
- create_section(chapter, section_config, i, image_files_by_name)
146
+ create_section(chapter, section_config, i, files_by_name)
85
147
  end
86
148
  end
87
149
 
88
- def create_section(chapter, section_config, position, image_files_by_name)
150
+ def create_section(chapter, section_config, position, files_by_name)
89
151
  content_element_configs = section_config.delete('foreground') || []
90
152
 
91
153
  rewrite_file_references!(section_config['backdrop'],
92
- ['image', 'imageMobile'],
93
- image_files_by_name)
154
+ %w[image imageMobile video],
155
+ files_by_name)
94
156
 
95
157
  section = Section.create!(chapter: chapter,
96
158
  configuration: section_config,
97
159
  position: position)
98
160
 
99
161
  content_element_configs.each_with_index do |content_element_config, i|
100
- create_content_element(section, content_element_config, i, image_files_by_name)
162
+ create_content_element(section, content_element_config, i, files_by_name)
101
163
  end
102
164
  end
103
165
 
104
- def create_content_element(section, content_element_config, position, image_files_by_name)
105
- if %w[stickyImage inlineImage inlineBeforeAfter].include?(
106
- content_element_config['type']
107
- )
166
+ def create_content_element(section, content_element_config, position, files_by_name)
167
+ if %w[inlineAudio inlineBeforeAfter inlineImage inlineVideo stickyImage]
168
+ .include?(content_element_config['type'])
108
169
  rewrite_file_references!(
109
170
  content_element_config['props'],
110
- ['id', 'before_id', 'after_id'],
111
- image_files_by_name
171
+ %w[id before_id after_id],
172
+ files_by_name
112
173
  )
113
174
  end
114
175
 
@@ -119,20 +180,19 @@ module PageflowScrolled
119
180
  )
120
181
  end
121
182
 
122
- def rewrite_file_references!(hash, keys, image_files_by_name)
183
+ def rewrite_file_references!(hash, keys, files_by_name)
123
184
  return unless hash
124
185
 
125
186
  keys.each do |key|
126
187
  next unless hash[key]
127
- next if non_image_reference?(hash[key])
188
+ next if non_file_reference?(hash[key])
128
189
 
129
- hash[key] = image_files_by_name.fetch(hash[key]).perma_id
190
+ hash[key] = files_by_name.fetch(hash[key]).perma_id
130
191
  end
131
192
  end
132
193
 
133
- def non_image_reference?(value)
134
- value.starts_with?('#') ||
135
- value.starts_with?('video')
194
+ def non_file_reference?(value)
195
+ value.starts_with?('#')
136
196
  end
137
197
  end
138
198
  end
@@ -35,32 +35,68 @@ namespace :pageflow_scrolled do
35
35
  Paperclip::Storage::S3.class_eval { def flush_writes; end }
36
36
  end
37
37
 
38
- account = seeds.account(name: 'Storybook seed')
39
- seeds.sample_scrolled_entry(title: 'Storybook seed',
40
- account: account,
41
- chapters: [],
42
- image_files: {
43
- turtle: {
44
- url: 'https://s3-eu-west-1.amazonaws.com/de.codevise.pageflow.development/pageflow-next/seed-assets/images/04_turtle.jpg',
45
- configuration: {
46
- focusX: 24,
47
- focusY: 40,
48
- testReferenceName: 'turtle'
49
- }
50
- }.stringify_keys,
51
- churchAfter: {
52
- url: 'https://s3-eu-west-1.amazonaws.com/de.codevise.pageflow.development/pageflow-next/seed-assets/images/17_haldern_church_after.jpg',
53
- configuration: {
54
- testReferenceName: 'churchAfter'
55
- }
56
- }.stringify_keys,
57
- churchBefore: {
58
- url: 'https://s3-eu-west-1.amazonaws.com/de.codevise.pageflow.development/pageflow-next/seed-assets/images/16_haldern_church_before.jpg',
59
- configuration: {
60
- testReferenceName: 'churchBefore'
61
- }
62
- }.stringify_keys
63
- })
38
+ account = seeds.account(name: 'Storybook seed') do |account_in_progress|
39
+ account_in_progress.features_configuration =
40
+ account_in_progress.features_configuration.merge('scrolled_entry_type' => true)
41
+ end
42
+
43
+ seeds.sample_scrolled_entry(
44
+ attributes: {
45
+ title: 'Storybook seed',
46
+ account: account,
47
+ chapters: [],
48
+ image_files: {
49
+ turtle: {
50
+ url: 'https://s3-eu-west-1.amazonaws.com/de.codevise.pageflow.development/pageflow-next/seed-assets/images/04_turtle.jpg',
51
+ configuration: {
52
+ focusX: 24,
53
+ focusY: 40,
54
+ testReferenceName: 'turtle'
55
+ }
56
+ }.stringify_keys,
57
+ churchAfter: {
58
+ url: 'https://s3-eu-west-1.amazonaws.com/de.codevise.pageflow.development/pageflow-next/seed-assets/images/17_haldern_church_after.jpg',
59
+ configuration: {
60
+ testReferenceName: 'churchAfter'
61
+ }
62
+ }.stringify_keys,
63
+ churchBefore: {
64
+ url: 'https://s3-eu-west-1.amazonaws.com/de.codevise.pageflow.development/pageflow-next/seed-assets/images/16_haldern_church_before.jpg',
65
+ configuration: {
66
+ testReferenceName: 'churchBefore'
67
+ }
68
+ }.stringify_keys
69
+ },
70
+ video_files: {
71
+ interview_toni: {
72
+ url: 'https://s3-eu-west-1.amazonaws.com/de.codevise.pageflow.development/pageflow-next/seed-assets/videos/08_interview_toni.mp4',
73
+ width: 1920,
74
+ height: 1080,
75
+ configuration: {
76
+ testReferenceName: 'interview_toni'
77
+ }
78
+ }.stringify_keys
79
+ },
80
+ audio_files: {
81
+ quicktime_jingle: {
82
+ url: 'https://s3-eu-west-1.amazonaws.com/de.codevise.pageflow.development/pageflow-next/seed-assets/audios/quicktime_jingle.m4a',
83
+ configuration: {
84
+ testReferenceName: 'quicktime_jingle'
85
+ }
86
+ }.stringify_keys
87
+ }.stringify_keys,
88
+ text_track_files: {
89
+ sample: {
90
+ url: 'https://s3-eu-west-1.amazonaws.com/de.codevise.pageflow.development/pageflow-next/seed-assets/text_tracks/sample.vtt',
91
+ parent_file_id: 'quicktime_jingle',
92
+ parent_file_model_type: 'Pageflow::AudioFile'
93
+ }.stringify_keys
94
+ }
95
+ },
96
+ options: {
97
+ skip_encoding: ENV.fetch('PAGEFLOW_SKIP_ENCODING_STORYBOOK_FILES', false)
98
+ }
99
+ )
64
100
  end
65
101
 
66
102
  desc 'Generate Storybook entry JSON seed'
@@ -77,7 +113,8 @@ namespace :pageflow_scrolled do
77
113
  seed =
78
114
  I18n.with_locale(draft_entry.locale) do
79
115
  PageflowScrolled::EntriesController
80
- .render(inline: 'scrolled_entry_json_seed(json, entry)',
116
+ .render(inline: 'scrolled_entry_json_seed(json, entry, ' \
117
+ 'translations: {include_inline_editing: true})',
81
118
  type: :jbuilder,
82
119
  locals: {entry: draft_entry})
83
120
  end
@@ -1,33 +1,131 @@
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 } 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
+
9
+ editor.contentElementTypes.register('heading', {
10
+ supportedPositions: ['inline'],
11
+ configurationEditor: function configurationEditor() {
12
+ this.tab('general', function () {
13
+ this.view(NoOptionsHintView);
14
+ });
15
+ }
16
+ });
17
+
18
+ function _defineProperty(obj, key, value) {
19
+ if (key in obj) {
20
+ Object.defineProperty(obj, key, {
21
+ value: value,
22
+ enumerable: true,
23
+ configurable: true,
24
+ writable: true
25
+ });
26
+ } else {
27
+ obj[key] = value;
28
+ }
29
+
30
+ return obj;
31
+ }
32
+
33
+ function ownKeys(object, enumerableOnly) {
34
+ var keys = Object.keys(object);
35
+
36
+ if (Object.getOwnPropertySymbols) {
37
+ var symbols = Object.getOwnPropertySymbols(object);
38
+ if (enumerableOnly) symbols = symbols.filter(function (sym) {
39
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
40
+ });
41
+ keys.push.apply(keys, symbols);
42
+ }
43
+
44
+ return keys;
45
+ }
46
+
47
+ function _objectSpread2(target) {
48
+ for (var i = 1; i < arguments.length; i++) {
49
+ var source = arguments[i] != null ? arguments[i] : {};
50
+
51
+ if (i % 2) {
52
+ ownKeys(Object(source), true).forEach(function (key) {
53
+ _defineProperty(target, key, source[key]);
54
+ });
55
+ } else if (Object.getOwnPropertyDescriptors) {
56
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
57
+ } else {
58
+ ownKeys(Object(source)).forEach(function (key) {
59
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
60
+ });
61
+ }
62
+ }
63
+
64
+ return target;
65
+ }
8
66
 
9
- editor$1.contentElementTypes.register('heading', {
67
+ editor.contentElementTypes.register('textBlock', {
68
+ supportedPositions: ['inline'],
10
69
  configurationEditor: function configurationEditor() {
11
70
  this.tab('general', function () {
12
- this.input('children', TextInputView);
71
+ this.view(NoOptionsHintView);
13
72
  });
73
+ },
74
+ split: function split(configuration, insertIndex) {
75
+ return [_objectSpread2(_objectSpread2({}, configuration), {}, {
76
+ value: configuration.value.slice(0, insertIndex)
77
+ }), _objectSpread2(_objectSpread2({}, configuration), {}, {
78
+ value: configuration.value.slice(insertIndex)
79
+ })];
80
+ },
81
+ merge: function merge(configurationA, configurationB) {
82
+ return _objectSpread2(_objectSpread2({}, configurationA), {}, {
83
+ value: configurationA.value.concat(configurationB.value)
84
+ });
85
+ },
86
+ handleDestroy: function handleDestroy(contentElement) {
87
+ var transientState = contentElement.get('transientState') || {};
88
+
89
+ if (!transientState.editableTextIsSingleBlock) {
90
+ contentElement.postCommand({
91
+ type: 'REMOVE'
92
+ });
93
+ return false;
94
+ }
14
95
  }
15
96
  });
16
97
 
17
- editor$1.contentElementTypes.register('textBlock', {
98
+ editor.contentElementTypes.register('inlineImage', {
18
99
  configurationEditor: function configurationEditor() {
19
100
  this.tab('general', function () {
20
- this.input('children', TextAreaInputView);
101
+ this.input('id', FileInputView, {
102
+ collection: 'image_files',
103
+ fileSelectionHandler: 'contentElementConfiguration',
104
+ positioning: false
105
+ });
106
+ this.group('ContentElementCaption');
107
+ this.group('ContentElementPosition');
21
108
  });
22
109
  }
23
110
  });
24
111
 
25
- editor$1.contentElementTypes.register('inlineImage', {
112
+ editor.contentElementTypes.register('inlineVideo', {
26
113
  configurationEditor: function configurationEditor() {
27
114
  this.tab('general', function () {
28
115
  this.input('id', FileInputView, {
116
+ collection: 'video_files',
117
+ fileSelectionHandler: 'contentElementConfiguration',
118
+ positioning: false,
119
+ defaultTextTrackFilePropertyName: 'defaultTextTrackFileId'
120
+ });
121
+ this.input('posterId', FileInputView, {
29
122
  collection: 'image_files',
30
- fileSelectionHandler: 'contentElementConfiguration'
123
+ fileSelectionHandler: 'contentElementConfiguration',
124
+ positioning: false
125
+ });
126
+ this.input('autoplay', CheckBoxInputView);
127
+ this.input('atmoDuringPlayback', SelectInputView, {
128
+ values: ['play', 'mute', 'turnDown']
31
129
  });
32
130
  this.group('ContentElementCaption');
33
131
  this.group('ContentElementPosition');
@@ -35,13 +133,40 @@ editor$1.contentElementTypes.register('inlineImage', {
35
133
  }
36
134
  });
37
135
 
38
- editor$1.contentElementTypes.register('inlineVideo', {
136
+ editor.contentElementTypes.register('inlineAudio', {
39
137
  configurationEditor: function configurationEditor() {
40
- this.tab('general', function () {});
138
+ this.tab('general', function () {
139
+ this.input('id', FileInputView, {
140
+ collection: 'audio_files',
141
+ fileSelectionHandler: 'contentElementConfiguration',
142
+ positioning: false,
143
+ defaultTextTrackFilePropertyName: 'defaultTextTrackFileId'
144
+ });
145
+ this.input('posterId', FileInputView, {
146
+ collection: 'image_files',
147
+ fileSelectionHandler: 'contentElementConfiguration',
148
+ positioning: false
149
+ });
150
+ this.input('autoplay', CheckBoxInputView);
151
+ this.input('playerControlVariant', SelectInputView, {
152
+ values: ['classic', 'waveform'],
153
+ ensureValueDefined: true
154
+ });
155
+ this.input('waveformColor', ColorInputView, {
156
+ visibleBinding: 'playerControlVariant',
157
+ visibleBindingValue: 'waveform',
158
+ defaultValue: '#e10028'
159
+ });
160
+ this.input('atmoDuringPlayback', SelectInputView, {
161
+ values: ['play', 'mute', 'turnDown']
162
+ });
163
+ this.group('ContentElementCaption');
164
+ this.group('ContentElementPosition');
165
+ });
41
166
  }
42
167
  });
43
168
 
44
- editor$1.contentElementTypes.register('inlineBeforeAfter', {
169
+ editor.contentElementTypes.register('inlineBeforeAfter', {
45
170
  configurationEditor: function configurationEditor() {
46
171
  this.tab('general', function () {
47
172
  this.input('before_id', FileInputView, {
@@ -57,11 +182,11 @@ editor$1.contentElementTypes.register('inlineBeforeAfter', {
57
182
  });
58
183
  this.input('after_label', TextInputView);
59
184
  this.input('initial_slider_position', SliderInputView);
60
- this.input('slider', CheckBoxInputView);
61
- this.input('slider_handle', CheckBoxInputView, {
185
+ this.input('slider', CheckBoxInputView$1);
186
+ this.input('slider_handle', CheckBoxInputView$1, {
62
187
  visibleBinding: 'slider'
63
188
  });
64
- this.input('slider_color', ColorInputView, {
189
+ this.input('slider_color', ColorInputView$1, {
65
190
  visibleBinding: 'slider'
66
191
  });
67
192
  this.group('ContentElementPosition');
@@ -74,13 +199,16 @@ editor$1.contentElementTypes.register('inlineBeforeAfter', {
74
199
  }
75
200
  });
76
201
 
77
- editor$1.contentElementTypes.register('soundDisclaimer', {
202
+ editor.contentElementTypes.register('soundDisclaimer', {
203
+ supportedPositions: ['inline'],
78
204
  configurationEditor: function configurationEditor() {
79
- this.tab('general', function () {});
205
+ this.tab('general', function () {
206
+ this.view(NoOptionsHintView);
207
+ });
80
208
  }
81
209
  });
82
210
 
83
- editor$1.contentElementTypes.register('videoEmbed', {
211
+ editor.contentElementTypes.register('videoEmbed', {
84
212
  configurationEditor: function configurationEditor() {
85
213
  this.tab('general', function () {
86
214
  this.input('videoSource', UrlInputView, {
@@ -89,8 +217,8 @@ editor$1.contentElementTypes.register('videoEmbed', {
89
217
  required: true,
90
218
  permitHttps: true
91
219
  });
92
- this.input('hideInfo', CheckBoxInputView);
93
- this.input('hideControls', CheckBoxInputView);
220
+ this.input('hideInfo', CheckBoxInputView$1);
221
+ this.input('hideControls', CheckBoxInputView$1);
94
222
  this.input('aspectRatio', SelectInputView, {
95
223
  values: ['wide', 'narrow', 'square', 'portrait']
96
224
  });
@@ -102,99 +230,10 @@ editor$1.contentElementTypes.register('videoEmbed', {
102
230
 
103
231
  var SidebarRouter = Marionette.AppRouter.extend({
104
232
  appRoutes: {
105
- 'scrolled/external_links/:id/': 'links',
106
233
  'scrolled/external_links/:id/:link_id': 'link'
107
234
  }
108
235
  });
109
236
 
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
237
  var SidebarEditLinkView = Marionette.Layout.extend({
199
238
  template: function template(data) {
200
239
  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 +258,7 @@ var SidebarEditLinkView = Marionette.Layout.extend({
219
258
  this.input('url', TextInputView, {
220
259
  required: true
221
260
  });
222
- this.input('open_in_new_tab', CheckBoxInputView);
261
+ this.input('open_in_new_tab', CheckBoxInputView$1);
223
262
  this.input('thumbnail', FileInputView, {
224
263
  collection: 'image_files',
225
264
  fileSelectionHandler: 'contentElement.externalLinks.link',
@@ -231,20 +270,17 @@ var SidebarEditLinkView = Marionette.Layout.extend({
231
270
  this.input('title', TextInputView, {
232
271
  required: true
233
272
  });
234
- this.input('description', TextAreaInputView, {
235
- size: 'short',
236
- disableLinks: true
237
- });
273
+ this.input('description', TextInputView);
238
274
  });
239
275
  this.formContainer.show(configurationEditor);
240
276
  },
241
277
  goBack: function goBack() {
242
- editor.navigate("/scrolled/external_links/".concat(this.options.contentElement.get('id'), "/"), {
278
+ editor$1.navigate("/scrolled/content_elements/".concat(this.options.contentElement.get('id')), {
243
279
  trigger: true
244
280
  });
245
281
  },
246
282
  destroyLink: function destroyLink() {
247
- if (confirm('pageflow_scrolled.editor.content_elements.externalLinkList.confirm_delete_link')) {
283
+ if (window.confirm(I18n.t('pageflow_scrolled.editor.content_elements.externalLinkList.confirm_delete_link'))) {
248
284
  this.options.collection.remove(this.model);
249
285
  this.goBack();
250
286
  }
@@ -255,7 +291,6 @@ var ExternalLinkModel = Backbone.Model.extend({
255
291
  modelName: 'ExternalLink',
256
292
  i18nKey: 'external_link',
257
293
  mixins: [transientReferences],
258
- initialize: function initialize(options) {},
259
294
  thumbnailUrl: function thumbnailUrl() {
260
295
  var image = this.collection.entry.imageFiles.getByPermaId(this.get('thumbnail'));
261
296
  return image ? image.get('thumbnail_url') : '';
@@ -278,17 +313,7 @@ var ExternalLinkCollection = Backbone.Collection.extend({
278
313
  return attrs.id;
279
314
  },
280
315
  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);
316
+ this.configuration.set('links', this.toJSON());
292
317
  },
293
318
  addNewLink: function addNewLink() {
294
319
  var newLink = {
@@ -304,83 +329,117 @@ var ExternalLinkCollection = Backbone.Collection.extend({
304
329
  }
305
330
  });
306
331
 
332
+ ExternalLinkCollection.forContentElement = function (contentElement, entry) {
333
+ return new ExternalLinkCollection(contentElement.configuration.get('links') || [], {
334
+ entry: entry,
335
+ configuration: contentElement.configuration
336
+ });
337
+ };
338
+
307
339
  var SidebarController = Marionette.Controller.extend({
308
340
  initialize: function initialize(options) {
341
+ this.entry = options.entry;
309
342
  this.region = options.region;
310
343
  },
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;
344
+ link: function link(id, linkId) {
345
+ var contentElement = this.entry.contentElements.get(id);
346
+ var linksCollection = ExternalLinkCollection.forContentElement(contentElement, this.entry);
347
+ this.region.show(new SidebarEditLinkView({
348
+ model: linksCollection.get(linkId),
349
+ collection: linksCollection,
350
+ contentElement: contentElement
351
+ }));
352
+ }
353
+ });
342
354
 
343
- if (!configuration.get('links')) {
344
- configuration.set('links', []);
355
+ function styleInject(css, ref) {
356
+ if ( ref === void 0 ) ref = {};
357
+ var insertAt = ref.insertAt;
358
+
359
+ if (!css || typeof document === 'undefined') { return; }
360
+
361
+ var head = document.head || document.getElementsByTagName('head')[0];
362
+ var style = document.createElement('style');
363
+ style.type = 'text/css';
364
+
365
+ if (insertAt === 'top') {
366
+ if (head.firstChild) {
367
+ head.insertBefore(style, head.firstChild);
368
+ } else {
369
+ head.appendChild(style);
345
370
  }
371
+ } else {
372
+ head.appendChild(style);
373
+ }
374
+
375
+ if (style.styleSheet) {
376
+ style.styleSheet.cssText = css;
377
+ } else {
378
+ style.appendChild(document.createTextNode(css));
379
+ }
380
+ }
381
+
382
+ var css = ".SidebarListView-module_linksContainer__HvWq- {\n}\n";
383
+ var styles = {"linksContainer":"SidebarListView-module_linksContainer__HvWq-"};
384
+ styleInject(css);
346
385
 
347
- this.linksCollection = new ExternalLinkCollection(configuration.get('links'), {
348
- entry: this.options.entry,
349
- configuration: configuration
386
+ var SidebarListView = Marionette.Layout.extend({
387
+ template: function template(data) {
388
+ 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 ");
389
+ },
390
+ regions: cssModulesUtils.ui(styles, 'linksContainer'),
391
+ events: cssModulesUtils.events(buttonStyles, {
392
+ 'click addButton': 'addElement'
393
+ }),
394
+ onRender: function onRender() {
395
+ this.linksContainer.show(new ListView({
396
+ collection: this.collection,
397
+ onEdit: _.bind(this.onEdit, this),
398
+ onRemove: _.bind(this.onRemove, this)
399
+ }));
400
+ },
401
+ addElement: function addElement() {
402
+ var newModel = this.collection.addNewLink();
403
+ this.onEdit(newModel);
404
+ },
405
+ onEdit: function onEdit(linkModel) {
406
+ editor.navigate("/scrolled/external_links/".concat(this.options.contentElement.id, "/").concat(linkModel.id), {
407
+ trigger: true
350
408
  });
409
+ },
410
+ onRemove: function onRemove(linkModel) {
411
+ if (window.confirm(I18n.t('pageflow_scrolled.editor.content_elements.externalLinkList.confirm_delete_link'))) {
412
+ this.collection.remove(linkModel);
413
+ }
351
414
  }
352
415
  });
353
416
 
354
417
  //router defines the URL hash path mapping and controller provides functions for the paths
355
418
 
356
- editor$1.registerSideBarRouting({
419
+ editor.registerSideBarRouting({
357
420
  router: SidebarRouter,
358
421
  controller: SidebarController
359
422
  }); // register external link list content element configuration editor for sidebar
360
423
 
361
- editor$1.contentElementTypes.register('externalLinkList', {
362
- configurationEditor: function configurationEditor() {
424
+ editor.contentElementTypes.register('externalLinkList', {
425
+ configurationEditor: function configurationEditor(_ref) {
426
+ var entry = _ref.entry;
363
427
  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
428
+ this.view(SidebarListView, {
429
+ contentElement: this.model.parent,
430
+ collection: ExternalLinkCollection.forContentElement(this.model.parent, entry)
368
431
  });
369
432
  });
370
433
  }
371
434
  }); // register file handler for thumbnail of external link
372
435
 
373
- editor$1.registerFileSelectionHandler('contentElement.externalLinks.link', function (options) {
436
+ editor.registerFileSelectionHandler('contentElement.externalLinks.link', function (options) {
374
437
  var contentElement = options.entry.contentElements.get(options.contentElementId);
375
- var links = contentElement.configuration.get('links');
438
+ var links = ExternalLinkCollection.forContentElement(contentElement, options.entry);
376
439
 
377
440
  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);
441
+ var link = links.get(options.id);
442
+ link.setReference('thumbnail', file);
384
443
  };
385
444
 
386
445
  this.getReferer = function () {
@@ -390,12 +449,12 @@ editor$1.registerFileSelectionHandler('contentElement.externalLinks.link', funct
390
449
 
391
450
  var DatawrapperAdView = Marionette.ItemView.extend({
392
451
  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 ");
452
+ 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
453
  },
395
454
  className: 'datawrapper_ad'
396
455
  });
397
456
 
398
- editor$1.contentElementTypes.register('dataWrapperChart', {
457
+ editor.contentElementTypes.register('dataWrapperChart', {
399
458
  configurationEditor: function configurationEditor() {
400
459
  this.tab('general', function () {
401
460
  this.input('url', UrlInputView, {