maglevcms 1.1.6 → 1.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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/app/components/maglev/content/image.rb +2 -0
  3. data/app/controllers/concerns/maglev/fetchers_concern.rb +1 -0
  4. data/app/controllers/concerns/maglev/standalone_sections_concern.rb +6 -0
  5. data/app/controllers/maglev/sitemap_controller.rb +31 -0
  6. data/app/frontend/editor/assets/remixicons/ri-palette-line.svg +1 -0
  7. data/app/frontend/editor/components/dynamic-form/dynamic-input.vue +2 -1
  8. data/app/frontend/editor/components/header-nav/publish-button.vue +1 -1
  9. data/app/frontend/editor/components/kit/collection-item-input.vue +5 -2
  10. data/app/frontend/editor/components/kit/color-input/core-input.vue +85 -0
  11. data/app/frontend/editor/components/kit/color-input/preset-button.vue +57 -0
  12. data/app/frontend/editor/components/kit/color-input/preset-dropdown.vue +46 -0
  13. data/app/frontend/editor/components/kit/color-input.vue +43 -0
  14. data/app/frontend/editor/components/kit/dropdown.vue +1 -0
  15. data/app/frontend/editor/components/kit/index.js +2 -2
  16. data/app/frontend/editor/components/kit/submit-button.vue +3 -3
  17. data/app/frontend/editor/components/kit/tabs.vue +2 -1
  18. data/app/frontend/editor/components/kit/text-input.vue +2 -2
  19. data/app/frontend/editor/misc/utils.js +32 -2
  20. data/app/frontend/editor/services/api.js +2 -2
  21. data/app/frontend/editor/spec/__mocks__/page.js +36 -36
  22. data/app/frontend/editor/spec/__mocks__/section.js +29 -29
  23. data/app/helpers/maglev/editor_helper.rb +1 -1
  24. data/app/helpers/maglev/page_preview_helper.rb +5 -1
  25. data/app/helpers/maglev/sitemap_helper.rb +13 -0
  26. data/app/models/concerns/maglev/sections_concern.rb +10 -0
  27. data/app/models/maglev/page/path_concern.rb +8 -1
  28. data/app/models/maglev/section/setting.rb +5 -0
  29. data/app/models/maglev/site/locales_concern.rb +8 -0
  30. data/app/services/concerns/maglev/get_page_sections/transform_collection_item_concern.rb +8 -1
  31. data/app/services/maglev/app_container.rb +2 -0
  32. data/app/services/maglev/fetch_collection_items.rb +6 -2
  33. data/app/services/maglev/persist_page.rb +23 -4
  34. data/app/services/maglev/setup_pages.rb +41 -5
  35. data/app/views/maglev/api/pages/_show.json.jbuilder +1 -2
  36. data/app/views/maglev/sitemap/index.xml.builder +21 -0
  37. data/config/routes.rb +1 -0
  38. data/db/migrate/20210830085101_create_maglev_page_paths.rb +1 -1
  39. data/db/migrate/20210906102712_add_canonical_to_pages.rb +1 -1
  40. data/db/migrate/20211008064437_add_locales_to_sites.rb +1 -1
  41. data/db/migrate/20211013210954_translate_section_content.rb +1 -1
  42. data/db/migrate/20211101205001_add_lock_version_to_maglev_pages.rb +1 -1
  43. data/db/migrate/20211116161121_better_page_path_canonical_indices.rb +1 -1
  44. data/db/migrate/20211124101005_fix_page_path_indices.rb +1 -1
  45. data/db/migrate/20211203224112_add_open_graph_tags_to_pages.rb +1 -1
  46. data/db/migrate/20220612092235_add_style_to_sites.rb +1 -1
  47. data/lib/generators/maglev/install_generator.rb +3 -2
  48. data/lib/generators/maglev/section_generator.rb +2 -1
  49. data/lib/generators/maglev/templates/section/app/theme/sections/%category%/%file_name%.yml.tt +13 -9
  50. data/lib/maglev/engine.rb +8 -2
  51. data/lib/maglev/version.rb +1 -1
  52. data/package.json +3 -3
  53. data/yarn.lock +799 -565
  54. metadata +14 -7
  55. data/app/frontend/editor/components/kit/color-picker.vue +0 -81
  56. /data/app/frontend/editor/assets/remixicons/{check-line.svg → ri-check-line.svg} +0 -0
@@ -9,7 +9,7 @@ export const pageSections = [
9
9
  settings: [
10
10
  {
11
11
  id: 'link',
12
- value: { href: '#', text: 'Home', link_type: 'url' },
12
+ value: { href: '#', text: 'Home', linkType: 'url' },
13
13
  },
14
14
  ],
15
15
  },
@@ -19,7 +19,7 @@ export const pageSections = [
19
19
  settings: [
20
20
  {
21
21
  id: 'link',
22
- value: { href: '#', text: 'About us', link_type: 'url' },
22
+ value: { href: '#', text: 'About us', linkType: 'url' },
23
23
  },
24
24
  ],
25
25
  },
@@ -33,11 +33,11 @@ export const pageSections = [
33
33
  href: '//contact',
34
34
  text: 'Contact',
35
35
  email: null,
36
- link_id: 9,
37
- link_type: 'page',
38
- link_label: 'Contact us',
39
- section_id: null,
40
- open_new_window: false,
36
+ linkId: 9,
37
+ linkType: 'page',
38
+ linkLabel: 'Contact us',
39
+ sectionId: null,
40
+ openNewWindow: false,
41
41
  },
42
42
  },
43
43
  ],
@@ -52,11 +52,11 @@ export const pageSections = [
52
52
  href: '/products',
53
53
  text: 'Products #1',
54
54
  email: null,
55
- link_id: 'd870133f9a075477a96a58e7639d40c5',
56
- link_type: 'page',
57
- link_label: 'Products',
58
- section_id: null,
59
- open_new_window: true,
55
+ linkId: 'd870133f9a075477a96a58e7639d40c5',
56
+ linkType: 'page',
57
+ linkLabel: 'Products',
58
+ sectionId: null,
59
+ openNewWindow: true,
60
60
  },
61
61
  },
62
62
  ],
@@ -71,7 +71,7 @@ export const pageSections = [
71
71
  width: 572,
72
72
  height: 290,
73
73
  filename: 'Screen Shot 2021-06-30 at 3.44.04 PM.png',
74
- byte_size: 35070,
74
+ byteSize: 35070,
75
75
  },
76
76
  },
77
77
  ],
@@ -96,7 +96,7 @@ export const pageSections = [
96
96
  width: 516,
97
97
  height: 320,
98
98
  filename: 'img-91-3.jpg',
99
- byte_size: 41683,
99
+ byteSize: 41683,
100
100
  },
101
101
  },
102
102
  { id: 'button', value: { url: '#', text: 'Click here' } },
@@ -119,7 +119,7 @@ export const pageSections = [
119
119
  width: 1920,
120
120
  height: 1200,
121
121
  filename: 'img-97.jpg',
122
- byte_size: 458107,
122
+ byteSize: 458107,
123
123
  },
124
124
  },
125
125
  ],
@@ -137,7 +137,7 @@ export const pageSections = [
137
137
  width: 516,
138
138
  height: 400,
139
139
  filename: 'inner-74-2.jpg',
140
- byte_size: 63881,
140
+ byteSize: 63881,
141
141
  },
142
142
  },
143
143
  ],
@@ -155,7 +155,7 @@ export const pageSections = [
155
155
  width: 516,
156
156
  height: 320,
157
157
  filename: 'img-91-4.jpg',
158
- byte_size: 21808,
158
+ byteSize: 21808,
159
159
  },
160
160
  },
161
161
  ],
@@ -173,7 +173,7 @@ export const pageSections = [
173
173
  width: 1920,
174
174
  height: 1200,
175
175
  filename: 'img-91.jpg',
176
- byte_size: 180178,
176
+ byteSize: 180178,
177
177
  },
178
178
  },
179
179
  ],
@@ -220,7 +220,7 @@ export const normalizedPage = {
220
220
  id: 'RiEo8C3f',
221
221
  type: 'navbar_item',
222
222
  settings: [
223
- { id: 'link', value: { href: '#', text: 'Home', link_type: 'url' } },
223
+ { id: 'link', value: { href: '#', text: 'Home', linkType: 'url' } },
224
224
  ],
225
225
  },
226
226
  P1fGieWs: {
@@ -229,7 +229,7 @@ export const normalizedPage = {
229
229
  settings: [
230
230
  {
231
231
  id: 'link',
232
- value: { href: '#', text: 'About us', link_type: 'url' },
232
+ value: { href: '#', text: 'About us', linkType: 'url' },
233
233
  },
234
234
  ],
235
235
  },
@@ -243,11 +243,11 @@ export const normalizedPage = {
243
243
  href: '//contact',
244
244
  text: 'Contact',
245
245
  email: null,
246
- link_id: 9,
247
- link_type: 'page',
248
- link_label: 'Contact us',
249
- section_id: null,
250
- open_new_window: false,
246
+ linkId: 9,
247
+ linkType: 'page',
248
+ linkLabel: 'Contact us',
249
+ sectionId: null,
250
+ openNewWindow: false,
251
251
  },
252
252
  },
253
253
  ],
@@ -262,11 +262,11 @@ export const normalizedPage = {
262
262
  href: '/products',
263
263
  text: 'Products #1',
264
264
  email: null,
265
- link_id: 'd870133f9a075477a96a58e7639d40c5',
266
- link_type: 'page',
267
- link_label: 'Products',
268
- section_id: null,
269
- open_new_window: true,
265
+ linkId: 'd870133f9a075477a96a58e7639d40c5',
266
+ linkType: 'page',
267
+ linkLabel: 'Products',
268
+ sectionId: null,
269
+ openNewWindow: true,
270
270
  },
271
271
  },
272
272
  ],
@@ -284,7 +284,7 @@ export const normalizedPage = {
284
284
  width: 1920,
285
285
  height: 1200,
286
286
  filename: 'img-97.jpg',
287
- byte_size: 458107,
287
+ byteSize: 458107,
288
288
  },
289
289
  },
290
290
  ],
@@ -302,7 +302,7 @@ export const normalizedPage = {
302
302
  width: 516,
303
303
  height: 400,
304
304
  filename: 'inner-74-2.jpg',
305
- byte_size: 63881,
305
+ byteSize: 63881,
306
306
  },
307
307
  },
308
308
  ],
@@ -320,7 +320,7 @@ export const normalizedPage = {
320
320
  width: 516,
321
321
  height: 320,
322
322
  filename: 'img-91-4.jpg',
323
- byte_size: 21808,
323
+ byteSize: 21808,
324
324
  },
325
325
  },
326
326
  ],
@@ -338,7 +338,7 @@ export const normalizedPage = {
338
338
  width: 1920,
339
339
  height: 1200,
340
340
  filename: 'img-91.jpg',
341
- byte_size: 180178,
341
+ byteSize: 180178,
342
342
  },
343
343
  },
344
344
  ],
@@ -358,7 +358,7 @@ export const normalizedPage = {
358
358
  width: 572,
359
359
  height: 290,
360
360
  filename: 'Screen Shot 2021-06-30 at 3.44.04 PM.png',
361
- byte_size: 35070,
361
+ byteSize: 35070,
362
362
  },
363
363
  },
364
364
  ],
@@ -383,7 +383,7 @@ export const normalizedPage = {
383
383
  width: 516,
384
384
  height: 320,
385
385
  filename: 'img-91-3.jpg',
386
- byte_size: 41683,
386
+ byteSize: 41683,
387
387
  },
388
388
  },
389
389
  { id: 'button', value: { url: '#', text: 'Click here' } },
@@ -18,7 +18,7 @@ export const simpleContentSection = {
18
18
  width: 516,
19
19
  height: 320,
20
20
  filename: 'img-91-3.jpg',
21
- byte_size: 41683,
21
+ byteSize: 41683,
22
22
  },
23
23
  },
24
24
  { id: 'button', value: { url: '#', text: 'Click here' } },
@@ -48,7 +48,7 @@ export const normalizedSimpleContentSection = {
48
48
  width: 516,
49
49
  height: 320,
50
50
  filename: 'img-91-3.jpg',
51
- byte_size: 41683,
51
+ byteSize: 41683,
52
52
  },
53
53
  },
54
54
  { id: 'button', value: { url: '#', text: 'Click here' } },
@@ -69,7 +69,7 @@ export const navContentSection = {
69
69
  settings: [
70
70
  {
71
71
  id: 'link',
72
- value: { href: '#', text: 'Home', link_type: 'url' },
72
+ value: { href: '#', text: 'Home', linkType: 'url' },
73
73
  },
74
74
  ],
75
75
  },
@@ -79,7 +79,7 @@ export const navContentSection = {
79
79
  settings: [
80
80
  {
81
81
  id: 'link',
82
- value: { href: '#', text: 'About us', link_type: 'url' },
82
+ value: { href: '#', text: 'About us', linkType: 'url' },
83
83
  },
84
84
  ],
85
85
  },
@@ -93,11 +93,11 @@ export const navContentSection = {
93
93
  href: '//contact',
94
94
  text: 'Contact',
95
95
  email: null,
96
- link_id: 9,
97
- link_type: 'page',
98
- link_label: 'Contact us',
99
- section_id: null,
100
- open_new_window: false,
96
+ linkId: 9,
97
+ linkType: 'page',
98
+ linkLabel: 'Contact us',
99
+ sectionId: null,
100
+ openNewWindow: false,
101
101
  },
102
102
  },
103
103
  ],
@@ -112,11 +112,11 @@ export const navContentSection = {
112
112
  href: '/products',
113
113
  text: 'Products #1',
114
114
  email: null,
115
- link_id: 'd870133f9a075477a96a58e7639d40c5',
116
- link_type: 'page',
117
- link_label: 'Products',
118
- section_id: null,
119
- open_new_window: true,
115
+ linkId: 'd870133f9a075477a96a58e7639d40c5',
116
+ linkType: 'page',
117
+ linkLabel: 'Products',
118
+ sectionId: null,
119
+ openNewWindow: true,
120
120
  },
121
121
  },
122
122
  ],
@@ -131,7 +131,7 @@ export const navContentSection = {
131
131
  width: 572,
132
132
  height: 290,
133
133
  filename: 'Screen Shot 2021-06-30 at 3.44.04 PM.png',
134
- byte_size: 35070,
134
+ byteSize: 35070,
135
135
  },
136
136
  },
137
137
  ],
@@ -144,7 +144,7 @@ export const normalizedNavContentSection = {
144
144
  id: 'RiEo8C3f',
145
145
  type: 'navbar_item',
146
146
  settings: [
147
- { id: 'link', value: { href: '#', text: 'Home', link_type: 'url' } },
147
+ { id: 'link', value: { href: '#', text: 'Home', linkType: 'url' } },
148
148
  ],
149
149
  },
150
150
  P1fGieWs: {
@@ -153,7 +153,7 @@ export const normalizedNavContentSection = {
153
153
  settings: [
154
154
  {
155
155
  id: 'link',
156
- value: { href: '#', text: 'About us', link_type: 'url' },
156
+ value: { href: '#', text: 'About us', linkType: 'url' },
157
157
  },
158
158
  ],
159
159
  },
@@ -167,11 +167,11 @@ export const normalizedNavContentSection = {
167
167
  href: '//contact',
168
168
  text: 'Contact',
169
169
  email: null,
170
- link_id: 9,
171
- link_type: 'page',
172
- link_label: 'Contact us',
173
- section_id: null,
174
- open_new_window: false,
170
+ linkId: 9,
171
+ linkType: 'page',
172
+ linkLabel: 'Contact us',
173
+ sectionId: null,
174
+ openNewWindow: false,
175
175
  },
176
176
  },
177
177
  ],
@@ -186,11 +186,11 @@ export const normalizedNavContentSection = {
186
186
  href: '/products',
187
187
  text: 'Products #1',
188
188
  email: null,
189
- link_id: 'd870133f9a075477a96a58e7639d40c5',
190
- link_type: 'page',
191
- link_label: 'Products',
192
- section_id: null,
193
- open_new_window: true,
189
+ linkId: 'd870133f9a075477a96a58e7639d40c5',
190
+ linkType: 'page',
191
+ linkLabel: 'Products',
192
+ sectionId: null,
193
+ openNewWindow: true,
194
194
  },
195
195
  },
196
196
  ],
@@ -210,7 +210,7 @@ export const normalizedNavContentSection = {
210
210
  width: 572,
211
211
  height: 290,
212
212
  filename: 'Screen Shot 2021-06-30 at 3.44.04 PM.png',
213
- byte_size: 35070,
213
+ byteSize: 35070,
214
214
  },
215
215
  },
216
216
  ],
@@ -226,7 +226,7 @@ export const navContentSectionBlock = {
226
226
  settings: [
227
227
  {
228
228
  id: 'link',
229
- value: { href: '#', text: 'Foo', link_type: 'url' },
229
+ value: { href: '#', text: 'Foo', linkType: 'url' },
230
230
  },
231
231
  ],
232
232
  }
@@ -16,7 +16,7 @@ module Maglev
16
16
  end
17
17
 
18
18
  def api_base_path
19
- "#{root_path}api"
19
+ api_root_path
20
20
  end
21
21
 
22
22
  def editor_window_title
@@ -16,11 +16,15 @@ module Maglev
16
16
  # rubocop:enable Rails/OutputSafety
17
17
 
18
18
  def render_maglev_section(type, site: nil, theme: nil, page: nil, page_sections: nil)
19
+ sections = (page_sections || maglev_page_sections).find_all do |section|
20
+ (section['type'] || section[:type]).start_with?(type.to_s)
21
+ end
22
+
19
23
  render_maglev_sections(
20
24
  site: site,
21
25
  theme: theme,
22
26
  page: page,
23
- page_sections: (page_sections || maglev_page_sections).find_all { |section| section['type'] == type.to_s }
27
+ page_sections: sections
24
28
  )
25
29
  end
26
30
 
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Maglev
4
+ module SitemapHelper
5
+ def sitemap_url(host, page, locale = nil)
6
+ path = maglev_services.get_page_fullpath.call(page: page, locale: locale)
7
+
8
+ return path if path =~ %r{^https?://}
9
+
10
+ [host, path].join
11
+ end
12
+ end
13
+ end
@@ -11,6 +11,16 @@ module Maglev::SectionsConcern
11
11
  end
12
12
  end
13
13
 
14
+ def prepare_sections_translations
15
+ return if sections_translations.blank?
16
+
17
+ sections_translations.each_key do |locale|
18
+ Maglev::I18n.with_locale(locale) do
19
+ prepare_sections
20
+ end
21
+ end
22
+ end
23
+
14
24
  private
15
25
 
16
26
  def prepare_section(section)
@@ -27,7 +27,14 @@ module Maglev::Page::PathConcern
27
27
  end
28
28
 
29
29
  def path=(value)
30
- current_path.value = value
30
+ unless value.respond_to?(:each_pair)
31
+ current_path.value = value
32
+ return
33
+ end
34
+
35
+ value.each_pair do |locale, new_path|
36
+ Maglev::I18n.with_locale(locale) { self.path = new_path }
37
+ end
31
38
  end
32
39
 
33
40
  def current_path
@@ -21,6 +21,7 @@ class Maglev::Section::Setting
21
21
  when :image then build_default_image_content(default)
22
22
  when :link then build_default_link_content(default)
23
23
  when :checkbox then build_default_checkbox_content(default)
24
+ when :collection_item then build_default_collection_item_content(default)
24
25
  else
25
26
  default || label
26
27
  end
@@ -42,6 +43,10 @@ class Maglev::Section::Setting
42
43
  default.presence || false
43
44
  end
44
45
 
46
+ def build_default_collection_item_content(default)
47
+ { id: default }
48
+ end
49
+
45
50
  ## class methods ##
46
51
  def self.build(hash)
47
52
  attributes = hash.slice('id', 'label', 'type', 'default')
@@ -24,6 +24,14 @@ module Maglev::Site::LocalesConcern
24
24
  locales.map { |locale| locale.prefix.to_sym }
25
25
  end
26
26
 
27
+ def each_locale
28
+ locale_prefixes.each do |locale|
29
+ Maglev::I18n.with_locale(locale) do
30
+ yield(locale)
31
+ end
32
+ end
33
+ end
34
+
27
35
  class LocalesSerializer
28
36
  def self.dump(array)
29
37
  (array || []).map(&:as_json)
@@ -3,7 +3,12 @@
3
3
  # rubocop:disable Style/ClassAndModuleChildren
4
4
  module Maglev::GetPageSections::TransformCollectionItemConcern
5
5
  def transform_collection_item_content_setting(content, setting)
6
- item_id = content.dig('value', 'id')
6
+ # the content might come from the default value of the collection_item setting
7
+ # rubocop:disable Style/StringHashKeys
8
+ content['value'] = { 'id' => 'any' } if content&.dig('value') == 'any'
9
+ # rubocop:enable Style/StringHashKeys
10
+
11
+ item_id = content&.dig('value', 'id')
7
12
  return if item_id.blank?
8
13
 
9
14
  item = fetch_collection_items.call(
@@ -11,6 +16,8 @@ module Maglev::GetPageSections::TransformCollectionItemConcern
11
16
  id: item_id
12
17
  )
13
18
 
19
+ return unless item
20
+
14
21
  content['value']['label'] = item.label
15
22
  content['value']['item'] = item.source
16
23
  end
@@ -31,6 +31,8 @@ module Maglev
31
31
  dependency :persist_section_screenshot, class: Maglev::PersistSectionScreenshot,
32
32
  depends_on: %i[fetch_theme fetch_section_screenshot_path]
33
33
 
34
+ dependency :change_site_locales, class: Maglev::ChangeSiteLocales
35
+
34
36
  dependency :fetch_page, class: Maglev::FetchPage, depends_on: :fetch_site
35
37
  dependency :get_page_fullpath, class: Maglev::GetPageFullpath, depends_on: %i[fetch_site get_base_url]
36
38
  dependency :get_page_sections, class: Maglev::GetPageSections,
@@ -33,7 +33,7 @@ module Maglev
33
33
 
34
34
  def fetch_item
35
35
  build_item(
36
- fetch_original_items.find_by(id: id)
36
+ id == 'any' ? fetch_original_items.first : fetch_original_items.find_by(id: id)
37
37
  )
38
38
  end
39
39
 
@@ -78,7 +78,11 @@ module Maglev
78
78
  end
79
79
 
80
80
  def collection
81
- config.collections[collection_id.to_sym]
81
+ config.collections[collection_id.to_sym].tap do |collection|
82
+ next if collection
83
+
84
+ raise "[Maglev] unregistered '#{collection_id}' collection in the Maglev configuration."
85
+ end
82
86
  end
83
87
 
84
88
  def build_item(original_item)
@@ -25,15 +25,31 @@ module Maglev
25
25
 
26
26
  def persist_page!
27
27
  page.attributes = page_attributes
28
- page.prepare_sections
28
+
29
+ # the sections_translations attribute is put by the SetupPages service
30
+ # when we generate a brand new site
31
+ if page_attributes.key?(:sections_translations)
32
+ page.prepare_sections_translations
33
+ else
34
+ page.prepare_sections
35
+ end
36
+
29
37
  page.save!
30
38
  end
31
39
 
32
40
  def persist_site!
33
41
  return unless can_persist_site?
34
42
 
35
- site.attributes = site_attributes_with_consistent_sections
36
- site.prepare_sections
43
+ # the sections_translations attribute is put by the SetupPages service
44
+ # when we generate a brand new site
45
+ if site_attributes.key?(:sections_translations)
46
+ site.attributes = site_attributes
47
+ site.prepare_sections_translations
48
+ else
49
+ site.attributes = site_attributes_with_consistent_sections
50
+ site.prepare_sections
51
+ end
52
+
37
53
  site.save!
38
54
  end
39
55
 
@@ -68,7 +84,10 @@ module Maglev
68
84
  end
69
85
 
70
86
  def can_persist_site?
71
- site_attributes.present? && site_attributes[:sections].present?
87
+ site_attributes.present? && (
88
+ site_attributes[:sections].present? ||
89
+ site_attributes[:sections_translations].present?
90
+ )
72
91
  end
73
92
  end
74
93
  end
@@ -13,7 +13,9 @@ module Maglev
13
13
 
14
14
  def call
15
15
  pages&.map do |page_attributes|
16
- create_page(page_attributes)
16
+ create_page(
17
+ attributes_in_all_locales(page_attributes.with_indifferent_access)
18
+ )
17
19
  end
18
20
  end
19
21
 
@@ -34,12 +36,46 @@ module Maglev
34
36
  end
35
37
 
36
38
  def site_attributes_from(page_attributes)
39
+ if page_attributes.include?(:sections_translations)
40
+ { sections_translations: site_sections_translations(page_attributes) }
41
+ else
42
+ { sections: select_site_scoped_sections(page_attributes[:sections]) }
43
+ end.compact || {}
44
+ end
45
+
46
+ def site_sections_translations(page_attributes)
47
+ sections_translations = page_attributes[:sections_translations].transform_values do |sections|
48
+ select_site_scoped_sections(sections)
49
+ end
50
+ sections_translations.any? { |_, sections| sections.blank? } ? nil : sections_translations
51
+ end
52
+
53
+ def attributes_in_all_locales(attributes)
37
54
  {
38
- sections: (page_attributes[:sections] || []).find_all do |section|
39
- definition = theme.sections.find(section['type'])
40
- definition.site_scoped?
41
- end
55
+ title_translations: value_in_all_locales(attributes[:title]),
56
+ sections_translations: value_in_all_locales(attributes[:sections]),
57
+ path: value_in_all_locales(attributes[:path])
42
58
  }
43
59
  end
60
+
61
+ def value_in_all_locales(value)
62
+ if value.respond_to?(:each_pair)
63
+ default_value = value[site.default_locale_prefix]
64
+ fill_translations(default_value).merge(value)
65
+ else
66
+ fill_translations(value)
67
+ end
68
+ end
69
+
70
+ def fill_translations(value)
71
+ site.locale_prefixes.index_with { |_locale| value }
72
+ end
73
+
74
+ def select_site_scoped_sections(sections)
75
+ (sections || []).find_all do |section|
76
+ definition = theme.sections.find(section['type'])
77
+ definition.site_scoped?
78
+ end
79
+ end
44
80
  end
45
81
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- json.sections services.get_page_sections.call(page: page)
4
-
5
3
  json.key_format! camelize: :lower
6
4
  json.deep_format_keys!
7
5
 
@@ -20,5 +18,6 @@ json.og_image_url page.og_image_url
20
18
  json.preview_url services.get_page_fullpath.call(page: page, preview_mode: true, locale: content_locale)
21
19
  json.live_url services.get_page_fullpath.call(page: page, preview_mode: false, locale: content_locale)
22
20
  json.section_names services.get_page_section_names.call(page: page)
21
+ json.sections services.get_page_sections.call(page: page)
23
22
  json.lock_version page.lock_version
24
23
  json.translated page.path.present?
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ xml.instruct!
4
+
5
+ xml.urlset xmlns: 'http://www.google.com/schemas/sitemap/0.9', "xmlns:xhtml": 'http://www.w3.org/1999/xhtml' do
6
+ @pages.each do |page|
7
+ xml.url do
8
+ xml.loc sitemap_url(@host, page, maglev_site.default_locale_prefix)
9
+ xml.lastmod page.updated_at.strftime('%Y-%m-%d')
10
+
11
+ if maglev_site.locales.size > 1
12
+ maglev_site.locales.each do |locale|
13
+ xml.xhtml :link,
14
+ rel: 'alternate',
15
+ hreflang: locale.prefix,
16
+ href: sitemap_url(@host, page, locale.prefix)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
data/config/routes.rb CHANGED
@@ -5,6 +5,7 @@ Maglev::Engine.routes.draw do
5
5
  # API
6
6
  constraints format: :json do
7
7
  namespace :api do
8
+ root to: proc { [200, {}, ['{}']] }
8
9
  resource :site, only: :show
9
10
  resources :pages do
10
11
  resources :clones, controller: :page_clones, only: :create
@@ -1,4 +1,4 @@
1
- class CreateMaglevPagePaths < ActiveRecord::Migration[6.1]
1
+ class CreateMaglevPagePaths < ActiveRecord::Migration[6.0]
2
2
  def change
3
3
  create_table :maglev_page_paths do |t|
4
4
  t.references :maglev_page