pageflow 16.0.0 → 16.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +86 -33
  3. data/README.md +6 -6
  4. data/Rakefile +1 -1
  5. data/admins/pageflow/entry.rb +0 -1
  6. data/admins/pageflow/sites.rb +3 -0
  7. data/app/assets/images/pageflow/admin/icons/published_with_noindex.svg +4 -0
  8. data/app/assets/javascripts/pageflow/dist/ui.js +299 -72
  9. data/app/assets/stylesheets/pageflow/admin/active_admin_patches.scss +1 -1
  10. data/app/assets/stylesheets/pageflow/admin/entries.scss +4 -0
  11. data/app/assets/stylesheets/pageflow/admin/permalink_input.scss +10 -0
  12. data/app/assets/stylesheets/pageflow/admin/publication_state_indicator.scss +4 -0
  13. data/app/assets/stylesheets/pageflow/editor/base.scss +0 -1
  14. data/app/assets/stylesheets/pageflow/editor/drop_down_button.scss +61 -7
  15. data/app/assets/stylesheets/pageflow/editor/file_meta_data.scss +12 -1
  16. data/app/assets/stylesheets/pageflow/editor/file_thumbnails.scss +4 -0
  17. data/app/assets/stylesheets/pageflow/editor/help.scss +3 -3
  18. data/app/assets/stylesheets/pageflow/editor/info_box.scss +7 -0
  19. data/app/assets/stylesheets/pageflow/editor/inputs/file_input.scss +0 -5
  20. data/app/assets/stylesheets/pageflow/ui/forms.scss +4 -4
  21. data/app/assets/stylesheets/pageflow/{editor/wysihtml5.scss → ui/input/text_area_input.scss} +13 -1
  22. data/app/assets/stylesheets/pageflow/ui.scss +1 -0
  23. data/app/controllers/pageflow/chapters_controller.rb +2 -2
  24. data/app/controllers/pageflow/editor/entry_publications_controller.rb +5 -1
  25. data/app/controllers/pageflow/editor/file_import_controller.rb +1 -1
  26. data/app/controllers/pageflow/editor/files_controller.rb +1 -1
  27. data/app/controllers/pageflow/entries_controller.rb +12 -2
  28. data/app/controllers/pageflow/feeds_controller.rb +18 -0
  29. data/app/controllers/pageflow/pages_controller.rb +2 -2
  30. data/app/controllers/pageflow/sitemaps_controller.rb +15 -0
  31. data/app/controllers/pageflow/storylines_controller.rb +2 -2
  32. data/app/helpers/pageflow/entries_helper.rb +4 -1
  33. data/app/helpers/pageflow/feeds_helper.rb +66 -0
  34. data/app/helpers/pageflow/meta_tags_helper.rb +2 -1
  35. data/app/helpers/pageflow/page_types_helper.rb +10 -10
  36. data/app/helpers/pageflow/revision_file_helper.rb +3 -3
  37. data/app/helpers/pageflow/social_share_helper.rb +2 -2
  38. data/app/inputs/pageflow_permalink_input.rb +15 -3
  39. data/app/models/concerns/pageflow/entry_publication_states.rb +9 -0
  40. data/app/models/concerns/pageflow/reusable_file.rb +3 -3
  41. data/app/models/concerns/pageflow/uploadable_file.rb +5 -0
  42. data/app/models/pageflow/account.rb +8 -0
  43. data/app/models/pageflow/audio_file_url_templates.rb +2 -1
  44. data/app/models/pageflow/draft_entry.rb +1 -1
  45. data/app/models/pageflow/entries_feed.rb +32 -0
  46. data/app/models/pageflow/entry.rb +7 -5
  47. data/app/models/pageflow/entry_at_revision.rb +2 -0
  48. data/app/models/pageflow/image_file.rb +34 -8
  49. data/app/models/pageflow/image_file_url_templates.rb +7 -1
  50. data/app/models/pageflow/membership.rb +3 -2
  51. data/app/models/pageflow/other_file.rb +5 -0
  52. data/app/models/pageflow/other_file_url_templates.rb +16 -0
  53. data/app/models/pageflow/published_entry.rb +6 -0
  54. data/app/models/pageflow/revision.rb +6 -0
  55. data/app/models/pageflow/site.rb +8 -0
  56. data/app/models/pageflow/sitemaps.rb +14 -0
  57. data/app/models/pageflow/used_file.rb +10 -2
  58. data/app/models/pageflow/video_file_url_templates.rb +3 -1
  59. data/app/models/pageflow/widget.rb +9 -1
  60. data/app/views/admin/entries/_permalink_inputs.html.erb +1 -2
  61. data/app/views/admin/sites/_attributes_table.html.arb +3 -0
  62. data/app/views/admin/sites/_fields.html.erb +6 -0
  63. data/app/views/components/pageflow/admin/extensible_attributes_table.rb +2 -2
  64. data/app/views/components/pageflow/admin/revisions_tab.rb +8 -0
  65. data/app/views/components/pageflow/admin/sites_tab.rb +3 -0
  66. data/app/views/pageflow/editor/config/_seeds.json.jbuilder +2 -0
  67. data/app/views/pageflow/editor/entries/_entry.json.jbuilder +1 -0
  68. data/app/views/pageflow/editor/entry_publications/check.json.jbuilder +1 -0
  69. data/app/views/pageflow/feeds/index.atom.builder +20 -0
  70. data/app/views/pageflow/image_files/_image_file.json.jbuilder +1 -0
  71. data/app/views/pageflow/meta_tags/_entry.html.erb +1 -0
  72. data/app/views/pageflow/sitemaps/index.xml.builder +9 -0
  73. data/config/initializers/features.rb +3 -0
  74. data/config/initializers/paperclip.rb +8 -0
  75. data/config/locales/de.yml +77 -6
  76. data/config/locales/en.yml +79 -4
  77. data/config/routes.rb +3 -0
  78. data/config/spring.rb +1 -1
  79. data/db/migrate/20230120092923_create_other_files.rb +23 -0
  80. data/db/migrate/20230323115745_add_feeds_enabled_to_sites.rb +5 -0
  81. data/db/migrate/20230323154323_add_sitemap_enabled_to_sites.rb +5 -0
  82. data/db/migrate/20230331103823_add_title_to_sites.rb +5 -0
  83. data/db/migrate/20230405103612_add_custom_feed_url_to_sites.rb +5 -0
  84. data/db/migrate/20231024062501_add_output_presences_to_image_files.rb +5 -0
  85. data/db/migrate/20231128124523_add_noindex_to_revisions.rb +5 -0
  86. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/editor.js +710 -259
  87. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/frontend.js +34 -5
  88. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/react-client.js +1 -1
  89. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/react-server.js +1 -1
  90. data/entry_types/paged/app/controllers/pageflow_paged/editor/entries_controller.rb +0 -2
  91. data/entry_types/paged/app/controllers/pageflow_paged/entries_controller.rb +2 -1
  92. data/entry_types/paged/app/views/pageflow_paged/entries/show.html.erb +1 -0
  93. data/entry_types/paged/config/initializers/features.rb +0 -1
  94. data/entry_types/paged/lib/pageflow_paged/engine.rb +13 -1
  95. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/chapters_controller.rb +2 -2
  96. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/content_elements_controller.rb +3 -4
  97. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/sections_controller.rb +13 -6
  98. data/entry_types/scrolled/app/controllers/pageflow_scrolled/entries_controller.rb +11 -3
  99. data/entry_types/scrolled/app/helpers/pageflow_scrolled/cache_helper.rb +11 -0
  100. data/entry_types/scrolled/app/helpers/pageflow_scrolled/editor/entry_json_seed_helper.rb +42 -0
  101. data/entry_types/scrolled/app/helpers/pageflow_scrolled/editor/seed_html_helper.rb +8 -5
  102. data/entry_types/scrolled/app/helpers/pageflow_scrolled/packs_helper.rb +17 -12
  103. data/entry_types/scrolled/app/helpers/pageflow_scrolled/react_server_side_rendering_helper.rb +9 -1
  104. data/entry_types/scrolled/app/helpers/pageflow_scrolled/themes_helper.rb +1 -1
  105. data/entry_types/scrolled/app/models/pageflow_scrolled/chapter.rb +23 -0
  106. data/entry_types/scrolled/app/views/pageflow_scrolled/editor/entries/_head.html.erb +1 -1
  107. data/entry_types/scrolled/app/views/pageflow_scrolled/editor/entries/_seed.json.jbuilder +1 -5
  108. data/entry_types/scrolled/app/views/pageflow_scrolled/editor/sections/_section_with_content_elements.json.jbuilder +10 -0
  109. data/entry_types/scrolled/app/views/pageflow_scrolled/entries/show.html.erb +44 -41
  110. data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_consent_vendors.json.jbuilder +16 -0
  111. data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_entry.json.jbuilder +7 -0
  112. data/entry_types/scrolled/config/initializers/features.rb +5 -0
  113. data/entry_types/scrolled/config/locales/consent_widget.de.yml +4 -0
  114. data/entry_types/scrolled/config/locales/consent_widget.en.yml +4 -0
  115. data/entry_types/scrolled/config/locales/de.yml +225 -8
  116. data/entry_types/scrolled/config/locales/en.yml +239 -2
  117. data/entry_types/scrolled/config/routes.rb +4 -0
  118. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/install_generator.rb +69 -44
  119. data/entry_types/scrolled/lib/pageflow_scrolled/additional_packs.rb +2 -1
  120. data/entry_types/scrolled/lib/pageflow_scrolled/additional_seed_data.rb +1 -1
  121. data/entry_types/scrolled/lib/pageflow_scrolled/configuration.rb +96 -0
  122. data/entry_types/scrolled/lib/pageflow_scrolled/content_element_consent_vendors.rb +38 -0
  123. data/entry_types/scrolled/lib/pageflow_scrolled/engine.rb +13 -1
  124. data/entry_types/scrolled/lib/pageflow_scrolled/plugin.rb +30 -0
  125. data/entry_types/scrolled/lib/pageflow_scrolled/react_widget_type.rb +6 -1
  126. data/entry_types/scrolled/lib/pageflow_scrolled/web_app_manifest.rb +1 -1
  127. data/entry_types/scrolled/lib/tasks/pageflow_scrolled/dummy.rake +1 -1
  128. data/entry_types/scrolled/lib/tasks/pageflow_scrolled/storybook.rake +1 -2
  129. data/entry_types/scrolled/package/config/webpack.js +26 -0
  130. data/entry_types/scrolled/package/contentElements-editor.js +330 -32
  131. data/entry_types/scrolled/package/contentElements-frontend.css +1 -1
  132. data/entry_types/scrolled/package/contentElements-frontend.js +920 -145
  133. data/entry_types/scrolled/package/editor.js +819 -239
  134. data/entry_types/scrolled/package/frontend/{EditableInlineText.module-14c7b097.js → EditableInlineText.module-6ee0e024.js} +1975 -1792
  135. data/entry_types/scrolled/package/frontend/PhonePlatformContext-b28d991a.js +32 -0
  136. data/entry_types/scrolled/package/frontend/ToggleFullscreenCornerButton-8242f213.js +107 -0
  137. data/entry_types/scrolled/package/frontend/Viewer-32cd1ac1.js +154 -0
  138. data/entry_types/scrolled/package/frontend/{Viewer-b6becc57.js → Viewer-6e4d14ed.js} +32 -161
  139. data/entry_types/scrolled/package/frontend/arrowRight-e42e6011.js +77 -0
  140. data/entry_types/scrolled/package/frontend/{components-b3160dd7.js → components-24363f97.js} +188 -47
  141. data/entry_types/scrolled/package/frontend/{PhonePlatformContext-f6093cc6.js → i18n-71c39823.js} +191 -111
  142. data/entry_types/scrolled/package/frontend/index-fc4b13e6.js +118 -0
  143. data/entry_types/scrolled/package/frontend/index.css +1 -1
  144. data/entry_types/scrolled/package/frontend/index.js +252 -76
  145. data/entry_types/scrolled/package/frontend/useContentElementEditorState-245f1986.js +52 -0
  146. data/entry_types/scrolled/package/package.json +6 -4
  147. data/entry_types/scrolled/package/testHelpers.js +11 -2
  148. data/entry_types/scrolled/package/values/colors.module.css +15 -0
  149. data/entry_types/scrolled/package/widgets/consentBar.css +1 -0
  150. data/entry_types/scrolled/package/widgets/consentBar.js +426 -0
  151. data/entry_types/scrolled/package/widgets/defaultNavigation.css +2 -2
  152. data/entry_types/scrolled/package/widgets/defaultNavigation.js +39 -4
  153. data/entry_types/scrolled/package/widgets/iconInlineFileRights.css +1 -0
  154. data/entry_types/scrolled/package/widgets/iconInlineFileRights.js +49 -0
  155. data/entry_types/scrolled/package/widgets/textInlineFileRights.css +1 -0
  156. data/entry_types/scrolled/package/widgets/textInlineFileRights.js +37 -0
  157. data/lib/generators/pageflow/resque/resque_generator.rb +1 -1
  158. data/lib/generators/pageflow/resque/templates/resque.rake +1 -1
  159. data/lib/generators/pageflow/resque/templates/resque.rb +1 -1
  160. data/lib/generators/pageflow/routes/routes_generator.rb +1 -1
  161. data/lib/pageflow/ability_mixin.rb +5 -5
  162. data/lib/pageflow/active_admin_can_can_fix.rb +2 -2
  163. data/lib/pageflow/built_in_file_type.rb +7 -0
  164. data/lib/pageflow/configuration.rb +29 -1
  165. data/lib/pageflow/engine.rb +18 -40
  166. data/lib/pageflow/entry_export_import/revision_serialization.rb +1 -1
  167. data/lib/pageflow/file_type.rb +2 -2
  168. data/lib/pageflow/global_config_api.rb +2 -2
  169. data/lib/pageflow/nested_revision_component.rb +23 -5
  170. data/lib/pageflow/page_type.rb +1 -1
  171. data/lib/pageflow/paperclip_processors/webp.rb +63 -0
  172. data/lib/pageflow/rails_version.rb +19 -0
  173. data/lib/pageflow/seeds.rb +10 -7
  174. data/lib/pageflow/user_mixin.rb +1 -1
  175. data/lib/pageflow/version.rb +1 -1
  176. data/lib/pageflow/widget_types.rb +4 -0
  177. data/package/config/jest/index.js +3 -1
  178. data/package/config/webpack5.js +14 -0
  179. data/package/editor.js +410 -181
  180. data/package/frontend.js +34 -4
  181. data/package/testHelpers.js +1 -1
  182. data/package/ui.js +297 -71
  183. data/spec/factories/entries.rb +34 -3
  184. data/spec/factories/sites.rb +3 -0
  185. data/vendor/assets/javascripts/iscroll.js +4 -7
  186. metadata +118 -80
  187. data/app/helpers/pageflow/admin/permalinks_helper.rb +0 -15
  188. data/entry_types/scrolled/package/frontend/arrowRight-78a7cee4.js +0 -42
@@ -15,6 +15,10 @@
15
15
  @include note-icon;
16
16
  }
17
17
 
18
+ &.other {
19
+ @include fa-cloud-download-icon;
20
+ }
21
+
18
22
  &.uploading {
19
23
  @include up-bold-icon;
20
24
  }
@@ -162,11 +162,11 @@
162
162
  }
163
163
 
164
164
  .editor .help_button {
165
- @include background-icon-right($color: var(--ui-primary-color),
166
- $font-size: 16px, $right: 5px, $top: 5px);
165
+ @include background-icon-left($color: var(--ui-primary-color),
166
+ $font-size: 16px, $left: 5px, $top: 50%);
167
167
  @include help-circled-icon;
168
168
 
169
- padding: 7px 30px 0 5px;
169
+ padding: 7px 5px 0 28px;
170
170
  float: right;
171
171
  height: 20px;
172
172
  cursor: pointer;
@@ -3,6 +3,13 @@
3
3
  margin-bottom: 1em;
4
4
  }
5
5
 
6
+ &.error {
7
+ color: var(--ui-on-error-surface-color);
8
+ background-color: var(--ui-error-surface-color);
9
+ border-radius: rounded();
10
+ padding: space(3);
11
+ }
12
+
6
13
  .shortcuts {
7
14
  dt {
8
15
  display: block;
@@ -38,11 +38,6 @@
38
38
  }
39
39
 
40
40
  .drop_down_button {
41
- button {
42
- @include fa-ellipsis-v-icon;
43
- width: 31px;
44
- }
45
-
46
41
  position: absolute;
47
42
  bottom: 0;
48
43
  left: 70px;
@@ -14,7 +14,7 @@ label {
14
14
 
15
15
  /** Make sure the label is on top when an inline help text is displayed */
16
16
  label:hover span.name {
17
- z-index: 4;
17
+ z-index: 5;
18
18
  position: relative;
19
19
  }
20
20
 
@@ -91,7 +91,7 @@ textarea.short {
91
91
 
92
92
  // Make sure the input is on top when an inline help text is displayed
93
93
  &:hover input {
94
- z-index: 4;
94
+ z-index: 5;
95
95
  position: relative;
96
96
  }
97
97
 
@@ -207,7 +207,7 @@ textarea.short {
207
207
  border-radius: rounded(sm);
208
208
  width: 100%;
209
209
  height: auto;
210
- z-index: 3;
210
+ z-index: 4;
211
211
  }
212
212
 
213
213
  font-weight: normal;
@@ -219,7 +219,7 @@ textarea.short {
219
219
  text-decoration: underline;
220
220
  }
221
221
 
222
- .input-hidden_via_binding {
222
+ .hidden_via_binding {
223
223
  display: none;
224
224
  }
225
225
 
@@ -1,4 +1,4 @@
1
- .toolbar {
1
+ .text_area_input .toolbar {
2
2
  margin-left: -2px;
3
3
  margin-top: 3px;
4
4
  position: relative;
@@ -174,4 +174,16 @@
174
174
  border-bottom: solid 9px var(--ui-surface-color);
175
175
  border-left: solid 9px transparent;
176
176
  }
177
+
178
+ // Hide inline help text that only makes sense when editing a
179
+ // Pageflow entry outside the editor
180
+ .open_in_new_tab_section .inline_help {
181
+ display: none;
182
+ }
183
+ }
184
+
185
+ .editor .text_area_input {
186
+ .open_in_new_tab_section .inline_help {
187
+ display: block;
188
+ }
177
189
  }
@@ -19,3 +19,4 @@
19
19
 
20
20
  @import "./ui/input/extended_select_input";
21
21
  @import "./ui/input/check_box_group_input";
22
+ @import "./ui/input/text_area_input";
@@ -31,7 +31,7 @@ module Pageflow
31
31
 
32
32
  authorize!(:update, chapter)
33
33
  verify_edit_lock!(chapter.entry)
34
- chapter.update_attributes(chapter_params)
34
+ chapter.update(chapter_params)
35
35
 
36
36
  respond_with(chapter)
37
37
  end
@@ -43,7 +43,7 @@ module Pageflow
43
43
  authorize!(:edit_outline, storyline.entry)
44
44
  verify_edit_lock!(storyline.entry)
45
45
  params.require(:ids).each_with_index do |id, index|
46
- entry.chapters.update(id, storyline_id: storyline.id, position: index)
46
+ entry.chapters.find(id).update(storyline_id: storyline.id, position: index)
47
47
  end
48
48
 
49
49
  head :no_content
@@ -39,7 +39,11 @@ module Pageflow
39
39
  end
40
40
 
41
41
  def entry_publication_params
42
- params.fetch(:entry_publication, {}).permit(:published_until, :password, :password_protected)
42
+ params
43
+ .fetch(:entry_publication, {})
44
+ .permit(:published_until,
45
+ :password, :password_protected,
46
+ :noindex)
43
47
  end
44
48
 
45
49
  def published_entries_quota(entry)
@@ -59,7 +59,7 @@ module Pageflow
59
59
  :content_type,
60
60
  :file_size,
61
61
  :url,
62
- configuration: :alt])
62
+ configuration: [:alt, :source_url]])
63
63
  .require(:files)
64
64
  end
65
65
 
@@ -72,7 +72,7 @@ module Pageflow
72
72
  file = entry.find_file(file_type.model, params[:id])
73
73
 
74
74
  authorize!(:update, file.to_model)
75
- file.update_attributes!(update_params)
75
+ file.update!(update_params)
76
76
 
77
77
  head(:no_content)
78
78
  end
@@ -8,7 +8,7 @@ module Pageflow
8
8
  def index
9
9
  site = Site.for_request(request).with_home_url.first!
10
10
 
11
- redirect_to(site.home_url)
11
+ redirect_to(site.home_url, allow_other_host: true)
12
12
  end
13
13
 
14
14
  def show
@@ -73,7 +73,7 @@ module Pageflow
73
73
  def redirect_according_to_entry_redirect(entry)
74
74
  return unless (redirect_location = entry_redirect(entry))
75
75
 
76
- redirect_to(redirect_location, status: :moved_permanently)
76
+ redirect_to(redirect_location, status: :moved_permanently, allow_other_host: true)
77
77
  end
78
78
 
79
79
  def entry_redirect(entry)
@@ -85,11 +85,21 @@ module Pageflow
85
85
 
86
86
  delegate_to_rack_app!(entry.entry_type.frontend_app) do |_status, headers, _body|
87
87
  allow_iframe_for_embed(headers)
88
+ apply_cache_control(entry, headers)
88
89
  end
89
90
  end
90
91
 
91
92
  def allow_iframe_for_embed(headers)
92
93
  headers.except!('X-Frame-Options') if params[:embed]
93
94
  end
95
+
96
+ def apply_cache_control(entry, headers)
97
+ config = Pageflow.config_for(entry)
98
+
99
+ return if config.public_entry_cache_control_header.blank?
100
+ return if entry.password_protected?
101
+
102
+ headers['Cache-Control'] = config.public_entry_cache_control_header
103
+ end
94
104
  end
95
105
  end
@@ -0,0 +1,18 @@
1
+ module Pageflow
2
+ # @api private
3
+ class FeedsController < Pageflow::ApplicationController
4
+ def index
5
+ site = Site.for_request(request).first!
6
+ return head 404 unless site.feeds_enabled?
7
+
8
+ @feed = EntriesFeed.for(
9
+ site: site,
10
+ locale: params[:locale]
11
+ )
12
+
13
+ respond_to do |format|
14
+ format.atom
15
+ end
16
+ end
17
+ end
18
+ end
@@ -20,7 +20,7 @@ module Pageflow
20
20
 
21
21
  authorize!(:update, page)
22
22
  verify_edit_lock!(page.chapter.entry)
23
- page.update_attributes(page_params)
23
+ page.update(page_params)
24
24
 
25
25
  respond_with(page)
26
26
  end
@@ -32,7 +32,7 @@ module Pageflow
32
32
  authorize!(:edit_outline, entry.to_model)
33
33
  verify_edit_lock!(chapter.entry)
34
34
  params.require(:ids).each_with_index do |id, index|
35
- entry.pages.update(id, :chapter_id => chapter.id, :position => index)
35
+ entry.pages.find(id).update(chapter_id: chapter.id, position: index)
36
36
  end
37
37
 
38
38
  head :no_content
@@ -0,0 +1,15 @@
1
+ module Pageflow
2
+ # @api private
3
+ class SitemapsController < Pageflow::ApplicationController
4
+ def index
5
+ site = Site.for_request(request).first!
6
+ return head 404 unless site.sitemap_enabled?
7
+
8
+ @entries = Sitemaps.entries_for(site: site)
9
+
10
+ respond_to do |format|
11
+ format.xml
12
+ end
13
+ end
14
+ end
15
+ end
@@ -31,7 +31,7 @@ module Pageflow
31
31
 
32
32
  authorize!(:update, storyline)
33
33
  verify_edit_lock!(storyline.entry)
34
- storyline.update_attributes(storyline_params)
34
+ storyline.update(storyline_params)
35
35
 
36
36
  respond_with(storyline)
37
37
  end
@@ -42,7 +42,7 @@ module Pageflow
42
42
  authorize!(:edit_outline, entry.to_model)
43
43
  verify_edit_lock!(entry)
44
44
  params.require(:ids).each_with_index do |id, index|
45
- entry.storylines.update(id, position: index)
45
+ entry.storylines.find(id).update(position: index)
46
46
  end
47
47
 
48
48
  head :no_content
@@ -1,7 +1,10 @@
1
1
  module Pageflow
2
2
  module EntriesHelper
3
3
  def pretty_entry_title(entry)
4
- [entry.title, entry.site.cname_domain.presence].compact.join(' - ')
4
+ return entry.title if entry.site.title == ' '
5
+
6
+ [entry.title,
7
+ entry.site.title.presence || entry.site.cname_domain.presence].compact.join(' - ')
5
8
  end
6
9
 
7
10
  def pretty_entry_url(entry, options = {})
@@ -0,0 +1,66 @@
1
+ module Pageflow
2
+ # Helpers to render alternate links to atom feeds.
3
+ #
4
+ # @since 16.1
5
+ module FeedsHelper
6
+ # Render alternate links to atom feed of entries in the same site
7
+ # using the same locale.
8
+ def feed_link_tags_for_entry(entry)
9
+ return '' unless entry.site.feeds_enabled?
10
+
11
+ href =
12
+ entry.site.custom_feed_url.presence&.gsub(':locale', entry.locale) ||
13
+ pageflow.feed_url(
14
+ {
15
+ locale: entry.locale,
16
+ format: 'atom'
17
+ }.merge(Pageflow.config.site_url_options(entry.site) || {})
18
+ )
19
+
20
+ tag(:link,
21
+ rel: 'alternate',
22
+ type: 'application/atom+xml',
23
+ title: 'Feed',
24
+ href: href)
25
+ end
26
+
27
+ # @api private
28
+ def feed_entry_content(entry)
29
+ FeedContent.new(self, entry).build
30
+ end
31
+
32
+ # @api private
33
+ FeedContent = Struct.new(:template, :entry) do
34
+ def build
35
+ [image_html, summary_html, link_html].compact.join
36
+ end
37
+
38
+ private
39
+
40
+ def image_html
41
+ return if entry.thumbnail_file.blank?
42
+
43
+ template.content_tag(
44
+ :p,
45
+ template.tag(
46
+ :img,
47
+ src: entry.thumbnail_file.thumbnail_url(:thumbnail_large),
48
+ width: 560, height: 315
49
+ )
50
+ )
51
+ end
52
+
53
+ def summary_html
54
+ template.content_tag(:p, template.raw(entry.summary))
55
+ end
56
+
57
+ def link_html
58
+ template.content_tag(
59
+ :p,
60
+ template.link_to(template.t('pageflow.public.read_more'),
61
+ template.social_share_entry_url(entry))
62
+ )
63
+ end
64
+ end
65
+ end
66
+ end
@@ -9,7 +9,8 @@ module Pageflow
9
9
  {
10
10
  keywords: entry.keywords,
11
11
  author: entry.author,
12
- publisher: entry.publisher
12
+ publisher: entry.publisher,
13
+ noindex: entry.noindex?
13
14
  }
14
15
  end
15
16
  end
@@ -15,18 +15,18 @@ module Pageflow
15
15
  end
16
16
 
17
17
  def page_type_templates(entry)
18
+ # Required by RevisionFileHelper#find_file_in_entry
19
+ @entry = entry
20
+
18
21
  safe_join(Pageflow.config.page_types.map do |page_type|
19
22
  content_tag(:script,
20
- render_to_string(template: page_type.template_path,
21
- locals: {
22
- configuration: {},
23
- page: Page.new,
24
- entry: entry,
25
-
26
- # Required by RevisionFileHelper#find_file_in_entry
27
- :@entry => entry
28
- },
29
- layout: false).to_str,
23
+ render(template: page_type.template_path,
24
+ locals: {
25
+ configuration: {},
26
+ page: Page.new,
27
+ entry: entry
28
+ },
29
+ layout: false).to_str,
30
30
  type: 'text/html', data: {template: "#{page_type.name}_page"})
31
31
  end)
32
32
  end
@@ -19,9 +19,9 @@ module Pageflow
19
19
  #
20
20
  # @since 15.0
21
21
  # @returns UsedFile
22
- def find_file_in_entry(file_type, file_perma_id)
23
- raise 'No entry of type PublishedEntry or DraftEntry set.' unless @entry.present?
24
- @entry.find_file_by_perma_id(file_type, file_perma_id)
22
+ def find_file_in_entry(file_type, file_perma_id, entry = @entry)
23
+ raise 'No entry of type PublishedEntry or DraftEntry set.' unless entry.present?
24
+ entry.find_file_by_perma_id(file_type, file_perma_id)
25
25
  end
26
26
  end
27
27
  end
@@ -8,7 +8,7 @@ module Pageflow
8
8
  if target.is_a?(Page)
9
9
  render('pageflow/social_share/page_meta_tags', entry: @entry, page: @entry.share_target)
10
10
  else
11
- render('pageflow/social_share/entry_meta_tags', entry: @entry)
11
+ render('pageflow/social_share/entry_meta_tags', entry: target)
12
12
  end
13
13
  end
14
14
 
@@ -55,7 +55,7 @@ module Pageflow
55
55
 
56
56
  def social_share_entry_image_tags(entry)
57
57
  share_images = []
58
- image_file = find_file_in_entry(ImageFile, entry.share_image_id)
58
+ image_file = find_file_in_entry(ImageFile, entry.share_image_id, entry)
59
59
 
60
60
  if image_file
61
61
  image_url = image_file.thumbnail_url(:medium)
@@ -27,9 +27,9 @@ class PageflowPermalinkInput
27
27
  end
28
28
 
29
29
  def permalink_inputs_html
30
- return '' if options[:directory_collection].empty?
30
+ return '' if options[:site].permalink_directories.empty?
31
31
 
32
- builder.select(:directory_id, options[:directory_collection]) <<
32
+ builder.select(:directory_id, directory_select_options) <<
33
33
  builder.text_field(:slug, placeholder: options[:slug_placeholder])
34
34
  end
35
35
 
@@ -38,10 +38,22 @@ class PageflowPermalinkInput
38
38
  end
39
39
 
40
40
  def wrapper_html_options
41
- if options[:directory_collection].empty?
41
+ if options[:site].permalink_directories.empty?
42
42
  super.merge(style: 'display: none')
43
+ elsif options[:site].permalink_directories.one?
44
+ result = super
45
+ result.merge(class: "#{result[:class]} no_directories")
43
46
  else
44
47
  super
45
48
  end
46
49
  end
50
+
51
+ def directory_select_options
52
+ template.options_from_collection_for_select(
53
+ options[:site].permalink_directories,
54
+ 'id',
55
+ 'path',
56
+ builder.object.directory_id
57
+ )
58
+ end
47
59
  end
@@ -11,6 +11,9 @@ module Pageflow
11
11
  scope(:published_with_password_protection,
12
12
  -> { published.merge(Revision.with_password_protection) })
13
13
 
14
+ scope(:published_without_noindex,
15
+ -> { published.merge(Revision.without_noindex) })
16
+
14
17
  scope(:not_published,
15
18
  lambda do
16
19
  includes(:published_revision)
@@ -22,6 +25,8 @@ module Pageflow
22
25
  def publication_state
23
26
  if published_with_password_protection?
24
27
  'published_with_password_protection'
28
+ elsif published? && published_revision.noindex?
29
+ 'published_with_noindex'
25
30
  elsif published?
26
31
  'published_without_password_protection'
27
32
  else
@@ -45,6 +50,10 @@ module Pageflow
45
50
  published? ? published_revision.published_until : nil
46
51
  end
47
52
 
53
+ def last_published_with_noindex?
54
+ !!revisions.publications.first&.noindex
55
+ end
56
+
48
57
  module ClassMethods
49
58
  def with_publication_state(state)
50
59
  case state
@@ -30,8 +30,8 @@ module Pageflow
30
30
  file_type_of_parent = Pageflow.config.file_types.find_by_model!(parent_class)
31
31
  models_of_nested_file_types = file_type_of_parent.nested_file_types.map(&:model)
32
32
  unless models_of_nested_file_types.include?(self.class)
33
- errors[:base] << 'File type of provided parent file does not permit nesting files of '\
34
- "type #{self.class.name}"
33
+ errors.add(:base, 'File type of provided parent file does not permit nesting files of '\
34
+ "type #{self.class.name}")
35
35
  end
36
36
  end
37
37
  end
@@ -39,7 +39,7 @@ module Pageflow
39
39
  def parent_belongs_to_same_entry
40
40
  if parent_file.present?
41
41
  unless parent_file.using_entries.include?(entry)
42
- errors[:base] << 'Parent file does not belong to same entry as nested file'
42
+ errors.add(:base, 'Parent file does not belong to same entry as nested file')
43
43
  end
44
44
  end
45
45
  end
@@ -38,6 +38,11 @@ module Pageflow
38
38
  end
39
39
  end
40
40
 
41
+ # see https://github.com/rails/rails/issues/50048
42
+ def file_name
43
+ attachment_on_s3_file_name
44
+ end
45
+
41
46
  def attachment
42
47
  attachment_on_s3
43
48
  end
@@ -27,5 +27,13 @@ module Pageflow
27
27
  def blacklist_for_serialization
28
28
  [:features_configuration]
29
29
  end
30
+
31
+ def self.ransackable_attributes(_auth_object = nil)
32
+ %w[id name]
33
+ end
34
+
35
+ def self.ransackable_associations(_auth_object = nil)
36
+ []
37
+ end
30
38
  end
31
39
  end
@@ -2,6 +2,7 @@ module Pageflow
2
2
  class AudioFileUrlTemplates
3
3
  def call
4
4
  {
5
+ original: url_template(:attachment, :original),
5
6
  m4a: url_template(:m4a),
6
7
  mp3: url_template(:mp3),
7
8
  ogg: url_template(:ogg),
@@ -17,7 +18,7 @@ module Pageflow
17
18
 
18
19
  def example_file
19
20
  @example_file ||= AudioFile.new(id: 0,
20
- file_name: ':basename.mp3',
21
+ file_name: ':basename.:extension',
21
22
  peak_data_file_name: 'audio.json')
22
23
  end
23
24
  end
@@ -52,7 +52,7 @@ module Pageflow
52
52
  end
53
53
 
54
54
  def update_meta_data!(attributes)
55
- draft.update_attributes!(attributes)
55
+ draft.update!(attributes)
56
56
  end
57
57
 
58
58
  def self.find(id)
@@ -0,0 +1,32 @@
1
+ module Pageflow
2
+ # @api private
3
+ EntriesFeed = Struct.new(:title, :locale, :custom_url, :root_url, :entries) do
4
+ def updated_at
5
+ entries.map(&:published_at).max
6
+ end
7
+
8
+ class << self
9
+ def for(site:, locale:)
10
+ new(
11
+ site.title.presence || site.host,
12
+ locale,
13
+ site.custom_feed_url&.gsub(':locale', locale),
14
+ site.canonical_entry_url_prefix&.gsub(':locale', locale),
15
+ find_entries(site, locale)
16
+ )
17
+ end
18
+
19
+ private
20
+
21
+ def find_entries(site, locale)
22
+ Pageflow::PublishedEntry.wrap_all(
23
+ site
24
+ .entries
25
+ .published_without_password_protection
26
+ .where(pageflow_revisions: {locale: locale})
27
+ .order('first_published_at DESC')
28
+ )
29
+ end
30
+ end
31
+ end
32
+ end
@@ -29,8 +29,8 @@ module Pageflow
29
29
 
30
30
  has_many :imports, class_name: 'Pageflow::FileImport', dependent: :destroy
31
31
 
32
- has_one :draft, -> { editable }, :class_name => 'Revision'
33
- has_one :published_revision, -> { published }, :class_name => 'Revision'
32
+ has_one :draft, -> { editable }, class_name: 'Revision', inverse_of: :entry
33
+ has_one :published_revision, -> { published }, class_name: 'Revision', inverse_of: :entry
34
34
 
35
35
  has_one :edit_lock, :dependent => :destroy
36
36
 
@@ -88,6 +88,7 @@ module Pageflow
88
88
  revision.published_at = Time.now
89
89
  revision.published_until = options[:published_until]
90
90
  revision.password_protected = options[:password_protected]
91
+ revision.noindex = !!options[:noindex]
91
92
  end
92
93
  end
93
94
  end
@@ -111,6 +112,7 @@ module Pageflow
111
112
  revision.published_at = nil
112
113
  revision.published_until = nil
113
114
  revision.password_protected = nil
115
+ revision.noindex = nil
114
116
  end
115
117
  end
116
118
 
@@ -130,15 +132,15 @@ module Pageflow
130
132
  title.to_s.parameterize
131
133
  end
132
134
 
133
- def self.ransackable_attributes(_auth_object)
135
+ def self.ransackable_attributes(_auth_object = nil)
134
136
  %w[title type_name created_at edited_at first_published_at]
135
137
  end
136
138
 
137
- def self.ransackable_associations(_auth_object)
139
+ def self.ransackable_associations(_auth_object = nil)
138
140
  %w[account published_revision]
139
141
  end
140
142
 
141
- def self.ransackable_scopes(_)
143
+ def self.ransackable_scopes(_auth_object = nil)
142
144
  [:with_publication_state, :published]
143
145
  end
144
146