pageflow 16.0.0 → 16.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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