maglevcms 1.5.1 → 1.6.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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/app/components/maglev/page_component.rb +9 -7
  3. data/app/components/maglev/section_component.rb +34 -4
  4. data/app/controllers/concerns/maglev/content_locale_concern.rb +3 -1
  5. data/app/controllers/concerns/maglev/services_concern.rb +2 -1
  6. data/app/controllers/maglev/page_preview_controller.rb +2 -0
  7. data/app/frontend/admin/controllers/iframe_controller.js +1 -1
  8. data/app/frontend/admin/index.js +1 -1
  9. data/app/frontend/editor/components/kit/color-input/core-input.vue +2 -0
  10. data/app/frontend/editor/components/kit/color-input.vue +1 -1
  11. data/app/frontend/editor/components/kit/icon-input.vue +2 -2
  12. data/app/frontend/editor/components/kit/image-input.vue +2 -2
  13. data/app/frontend/editor/components/kit/link-input.vue +6 -2
  14. data/app/frontend/editor/components/kit/rich-text-input.vue +2 -2
  15. data/app/frontend/editor/components/kit/search-input.vue +1 -0
  16. data/app/frontend/editor/components/kit/select-input.vue +24 -20
  17. data/app/frontend/editor/components/kit/tabs.vue +12 -2
  18. data/app/frontend/editor/components/kit/text-input.vue +3 -2
  19. data/app/frontend/editor/components/kit/textarea-input.vue +4 -2
  20. data/app/frontend/editor/components/link-picker/index.vue +1 -1
  21. data/app/frontend/editor/components/page/edit.vue +2 -1
  22. data/app/frontend/editor/components/page/new.vue +2 -1
  23. data/app/frontend/editor/components/section-pane/index.vue +2 -1
  24. data/app/frontend/editor/services/section.js +1 -1
  25. data/app/frontend/editor/views/pages/edit.vue +1 -1
  26. data/app/frontend/live-preview-client/index.js +0 -1
  27. data/app/helpers/maglev/application_helper.rb +2 -1
  28. data/app/helpers/maglev/page_preview_helper.rb +14 -3
  29. data/app/models/maglev/setting_types/collection_item.rb +1 -1
  30. data/app/models/maglev/site/locales_concern.rb +1 -1
  31. data/app/services/maglev/fetch_site.rb +1 -1
  32. data/app/services/maglev/setup_pages.rb +3 -0
  33. data/app/views/maglev/admin/themes/_sections.html.erb +3 -3
  34. data/lib/generators/maglev/templates/install/config/initializers/maglev.rb +1 -1
  35. data/lib/maglev/version.rb +1 -1
  36. data/lib/maglev.rb +1 -1
  37. data/package.json +3 -3
  38. data/tailwind.config.js +10 -2
  39. data/yarn.lock +261 -14
  40. metadata +4 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8f2ab19ced5aac5add6f9567d35c4ff2afd691a9df28d6427848add5b4e485c8
4
- data.tar.gz: 275f52591a49d27d99af9cd7d1d9e31204318c818cbc82bc02c7aba266336f23
3
+ metadata.gz: 45b336e791f110d5c7c1982631955c14664c2a66184b44b83a31f5689800d1d0
4
+ data.tar.gz: 65ea43f9f7006d128a21adad2c832f896d314715d83bc47283070ae60fb41dff
5
5
  SHA512:
6
- metadata.gz: d12fbd67952a61a321f253d6ec8ac8c97f981b880572bf3d8f1d65a95a825d29adba0041c53929c26a631a7f8e1f99e9bfbd907d82a53a263777ed9a751334f0
7
- data.tar.gz: 0a149c32927a7f9f478f489b281957a1f7ec32b5c2ee2ac3f08cfd6fad1d51ac59a6bca6f660af64f35bdc7833bec98443f23d9807ef5e515a22d112dee01f4a
6
+ metadata.gz: 17be0c14ba106d648cf9fa13953adff4e63f342a6d7d6acaa215cc6200f41c8d710e2d0b3c14d803f92ee4521c977f03b8c8389cd5351eb60bd87c23fbe50d73
7
+ data.tar.gz: 0adbc6d304a7b46cf1f4b1b6640fde924bad6d456931f0527adba2b01bcf3f06211f2cbe14f80c0fa93950f05d64eb01c7fb67cd136988d756103b2346b7c177
@@ -2,18 +2,19 @@
2
2
 
3
3
  module Maglev
4
4
  class PageComponent < BaseComponent
5
- attr_reader :site, :theme, :page, :page_sections, :templates_root_path, :config
5
+ attr_reader :site, :theme, :page, :page_sections, :templates_root_path, :config, :rendering_mode
6
6
 
7
- # rubocop:disable Lint/MissingSuper, Metrics/ParameterLists
8
- def initialize(site:, theme:, page:, page_sections:, templates_root_path:, config:)
7
+ # rubocop:disable Lint/MissingSuper
8
+ def initialize(site:, theme:, page:, page_sections:, context:)
9
9
  @site = site
10
10
  @theme = theme
11
11
  @page = page
12
12
  @page_sections = page_sections
13
- @templates_root_path = templates_root_path
14
- @config = config
13
+ @templates_root_path = context[:templates_root_path]
14
+ @config = context[:config]
15
+ @rendering_mode = context[:rendering_mode]
15
16
  end
16
- # rubocop:enable Lint/MissingSuper, Metrics/ParameterLists
17
+ # rubocop:enable Lint/MissingSuper
17
18
 
18
19
  # Sections within a dropzone
19
20
  def sections
@@ -37,7 +38,8 @@ module Maglev
37
38
  parent: self,
38
39
  definition: definition,
39
40
  attributes: attributes.deep_transform_keys! { |k| k.to_s.underscore.to_sym },
40
- templates_root_path: templates_root_path
41
+ templates_root_path: templates_root_path,
42
+ rendering_mode: rendering_mode
41
43
  )
42
44
  end
43
45
  end
@@ -7,16 +7,17 @@ module Maglev
7
7
  extend Forwardable
8
8
  def_delegators :parent, :site, :config
9
9
 
10
- attr_reader :parent, :id, :type, :settings, :attributes, :definition, :templates_root_path
10
+ attr_reader :parent, :id, :type, :settings, :attributes, :definition, :templates_root_path, :rendering_mode
11
11
 
12
12
  # rubocop:disable Lint/MissingSuper
13
- def initialize(parent:, attributes:, definition:, templates_root_path:)
13
+ def initialize(parent:, attributes:, definition:, templates_root_path:, rendering_mode:)
14
14
  @parent = parent # aka a PageComponent
15
15
  @id = attributes[:id]
16
16
  @type = attributes[:type]
17
17
  @definition = definition
18
18
  @attributes = attributes
19
19
  @templates_root_path = templates_root_path
20
+ @rendering_mode = rendering_mode
20
21
 
21
22
  @settings = settings_proxy(
22
23
  build_settings_map(attributes[:settings])
@@ -30,12 +31,12 @@ module Maglev
30
31
 
31
32
  # rubocop:disable Rails/OutputSafety
32
33
  def dom_data
33
- "data-maglev-section-id=\"#{id}\"".html_safe
34
+ "data-maglev-section-id=\"#{id}\" data-maglev-section-type=\"#{type}\"".html_safe
34
35
  end
35
36
  # rubocop:enable Rails/OutputSafety
36
37
 
37
38
  def tag_data
38
- { maglev_section_id: id }
39
+ { maglev_section_id: id, maglev_section_type: type }
39
40
  end
40
41
 
41
42
  def blocks
@@ -53,6 +54,8 @@ module Maglev
53
54
  template: "#{templates_root_path}/sections/#{definition.category}/#{type}",
54
55
  locals: { section: self, maglev_section: self }
55
56
  )
57
+ rescue StandardError => e
58
+ handle_error(e)
56
59
  end
57
60
 
58
61
  private
@@ -92,5 +95,32 @@ module Maglev
92
95
  attributes: block_attributes
93
96
  )
94
97
  end
98
+
99
+ def handle_error(exception)
100
+ throw exception if %i[live section].include?(rendering_mode) || Rails.env.test?
101
+
102
+ Rails.logger.error [
103
+ "⚠️ [Maglev] Error when rendering a \"#{type}\" type section ⚠️",
104
+ exception.message,
105
+ *exception.backtrace
106
+ ].join($INPUT_RECORD_SEPARATOR)
107
+
108
+ render_error
109
+ end
110
+
111
+ def render_error
112
+ <<~HTML
113
+ <div #{dom_data} style="padding: 5rem 0;">
114
+ <div style="max-width: 40rem; margin: 0 auto; background-color: rgb(254 242 242); color: rgb(153 27 27); padding: 1rem; border-radius: 0.375rem;">
115
+ <h3 style="font-weight: 500; color: rgb(153 27 27); font-size: 0.875rem; line-height: 1.25rem;">
116
+ We've encountered an error while rendering the <strong>"#{type}"</strong> section.
117
+ </h3>
118
+ <p style="margin-top: 0.5rem; font-size: 0.775rem; line-height: 1.25rem; color: rgb(185 28 28);">
119
+ Check out your application logs for more details.
120
+ </p>
121
+ </div>
122
+ </div>
123
+ HTML
124
+ end
95
125
  end
96
126
  end
@@ -5,7 +5,9 @@ module Maglev
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  included do
8
- helper_method :content_locale
8
+ alias_method :maglev_content_locale, :content_locale
9
+
10
+ helper_method :maglev_content_locale, :content_locale
9
11
  end
10
12
 
11
13
  private
@@ -24,7 +24,8 @@ module Maglev
24
24
  def build_maglev_service_context
25
25
  ::Maglev::ServiceContext.new(
26
26
  rendering_mode: maglev_rendering_mode,
27
- controller: self
27
+ controller: self,
28
+ site: nil
28
29
  )
29
30
  end
30
31
 
@@ -23,6 +23,8 @@ module Maglev
23
23
  super.tap do |site|
24
24
  raise ActiveRecord::RecordNotFound if site.nil?
25
25
 
26
+ maglev_services.context.site = site
27
+
26
28
  site.style = JSON.parse(params[:style]) if params[:style]
27
29
  end
28
30
  end
@@ -5,7 +5,7 @@ export default class extends Controller {
5
5
  this.element.addEventListener('load', () => {
6
6
  setTimeout(() => {
7
7
  let height =
8
- this.element.contentDocument.querySelector('body').clientHeight
8
+ this.element.contentDocument.querySelector('[data-maglev-section-id]').clientHeight
9
9
 
10
10
  if (height < 200) height = 200
11
11
 
@@ -4,7 +4,7 @@ import { Application } from 'stimulus'
4
4
  import { registerControllers } from 'stimulus-vite-helpers'
5
5
 
6
6
  const application = Application.start()
7
- const controllers = import.meta.globEager('./**/*_controller.js')
7
+ const controllers = import.meta.glob('./**/*_controller.js', { eager: true })
8
8
  registerControllers(application, controllers)
9
9
 
10
10
  window.stimulusApplication = application
@@ -11,6 +11,7 @@
11
11
  >
12
12
 
13
13
  <input
14
+ :id="name"
14
15
  type="text"
15
16
  :value="inputColor"
16
17
  @input="updateInput"
@@ -42,6 +43,7 @@ export default {
42
43
  name: 'CoreInput',
43
44
  components: { PresetDropdown },
44
45
  props: {
46
+ name: { type: String, default: 'color' },
45
47
  value: { type: String },
46
48
  presets: {
47
49
  type: Array,
@@ -6,7 +6,7 @@
6
6
  v-if="showLabel"
7
7
  >
8
8
  <span class="pr-2">{{ label }}</span>
9
- <core-input :presets="presets" v-model="updatableValue" />
9
+ <core-input :name="name" :presets="presets" v-model="updatableValue" />
10
10
  </label>
11
11
  </div>
12
12
  </template>
@@ -1,8 +1,8 @@
1
1
  <template>
2
2
  <div>
3
- <label class="block font-semibold text-gray-800" :for="name">
3
+ <div class="block font-semibold text-gray-800" @click="focus()">
4
4
  {{ label }}
5
- </label>
5
+ </div>
6
6
  <div class="mt-1">
7
7
  <div
8
8
  class="flex items-center justify-center bg-gray-100 h-24 rounded"
@@ -1,8 +1,8 @@
1
1
  <template>
2
2
  <div>
3
- <label class="block font-semibold text-gray-800" :for="name">
3
+ <div class="block font-semibold text-gray-800" @click="focus()">
4
4
  {{ label }}
5
- </label>
5
+ </div>
6
6
  <div class="mt-1">
7
7
  <div
8
8
  class="flex items-center justify-center bg-gray-100 h-48 rounded"
@@ -1,10 +1,11 @@
1
1
  <template>
2
2
  <div>
3
- <label class="block font-semibold text-gray-800" :for="name">
3
+ <div class="block font-semibold text-gray-800" @click="focus()">
4
4
  {{ label }}
5
- </label>
5
+ </div>
6
6
 
7
7
  <uikit-text-input
8
+ :name="name"
8
9
  v-model="textInput"
9
10
  :showLabel="false"
10
11
  :placeholder="$t('linkInput.nestedTextPlaceholder')"
@@ -82,6 +83,9 @@ export default {
82
83
  },
83
84
  },
84
85
  methods: {
86
+ focus() {
87
+ this.openLinkPickerModal()
88
+ },
85
89
  setLink(link) {
86
90
  this.$emit('input', {
87
91
  ...pick(
@@ -1,12 +1,12 @@
1
1
  <template>
2
2
  <div>
3
- <label
3
+ <div
4
4
  class="block font-semibold text-gray-800"
5
5
  :for="name"
6
6
  @click="focus()"
7
7
  >
8
8
  {{ label }}
9
- </label>
9
+ </div>
10
10
  <div class="mt-1">
11
11
  <editor-menu-bar :editor="editor" v-slot="{ commands, isActive }">
12
12
  <div class="flex sticky top-0 z-10 pb-2 bg-white space-x-1">
@@ -8,6 +8,7 @@
8
8
  </button>
9
9
 
10
10
  <input
11
+ name="search-input"
11
12
  type="text"
12
13
  v-model="query"
13
14
  class="block w-full border-0 bg-transparent focus:outline-none placeholder-gray-500"
@@ -1,12 +1,12 @@
1
1
  <template>
2
2
  <div>
3
- <label
3
+ <div
4
4
  class="block font-semibold text-gray-800"
5
- :for="name"
5
+ @click="focus()"
6
6
  v-if="withLabel"
7
7
  >
8
8
  {{ label }}
9
- </label>
9
+ </div>
10
10
  <div class="relative">
11
11
  <button
12
12
  class="text-left block w-full mt-1 py-2 px-3 rounded bg-gray-100 text-gray-800 focus:outline-none focus:ring"
@@ -51,6 +51,7 @@
51
51
  >
52
52
  <div class="px-3 pt-1 pb-3" v-if="searchEnabled">
53
53
  <input
54
+ :id="name"
54
55
  class="block mt-1 px-3 py-1 w-full border rounded border-gray-300 bg-gray-100 placeholder-gray-500 focus:ring focus:ring"
55
56
  type="text"
56
57
  v-model="q"
@@ -70,16 +71,16 @@
70
71
  class="py-1 px-4 cursor-pointer"
71
72
  :class="{
72
73
  'rounded-b': index === list.length - 1,
73
- 'bg-editor-primary text-white': index === focus,
74
+ 'bg-editor-primary text-white': index === focusIndex,
74
75
  }"
75
- @mouseover="focus = index"
76
- @mouseleave="focus = undefined"
76
+ @mouseover="focusIndex = index"
77
+ @mouseleave="focusIndex = undefined"
77
78
  @click="select(item)"
78
79
  >
79
80
  <slot
80
81
  name="item"
81
82
  v-bind:item="item"
82
- v-bind:hovered="index === focus"
83
+ v-bind:hovered="index === focusIndex"
83
84
  />
84
85
  </div>
85
86
  </div>
@@ -111,7 +112,7 @@ export default {
111
112
  isOpen: false,
112
113
  q: undefined,
113
114
  list: undefined,
114
- focus: undefined,
115
+ focusIndex: undefined,
115
116
  }
116
117
  },
117
118
  created() {
@@ -126,13 +127,16 @@ export default {
126
127
  },
127
128
  },
128
129
  methods: {
130
+ focus() {
131
+ this.toggle();
132
+ },
129
133
  toggle() {
130
134
  this.isOpen = !this.isOpen
131
135
  },
132
136
  fetch() {
133
137
  this.fetchList(this.q).then((list) => {
134
138
  this.list = list
135
- this.focus = list && list.length > 0 ? 0 : null
139
+ this.focusIndex = list && list.length > 0 ? 0 : null
136
140
  })
137
141
  },
138
142
  select(value) {
@@ -147,24 +151,24 @@ export default {
147
151
  if (!this) return
148
152
  switch (event.keyCode) {
149
153
  case 13:
150
- if (this.focus !== undefined) {
151
- this.select(this.list[this.focus])
154
+ if (this.focusIndex !== undefined) {
155
+ this.select(this.list[this.focusIndex])
152
156
  }
153
157
  event.stopPropagation() & event.preventDefault()
154
158
  break
155
159
  case 38:
156
- if (!this.focus) {
157
- this.focus = 0
158
- } else if (this.focus > 0) {
159
- this.focus--
160
+ if (!this.focusIndex) {
161
+ this.focusIndex = 0
162
+ } else if (this.focusIndex > 0) {
163
+ this.focusIndex--
160
164
  }
161
165
  event.stopPropagation() & event.preventDefault()
162
166
  break
163
167
  case 40:
164
- if (!this.focus) {
165
- this.focus = 0
166
- } else if (this.focus < this.list.length - 1) {
167
- this.focus++
168
+ if (!this.focusIndex) {
169
+ this.focusIndex = 0
170
+ } else if (this.focusIndex < this.list.length - 1) {
171
+ this.focusIndex++
168
172
  }
169
173
  event.stopPropagation() & event.preventDefault()
170
174
  break
@@ -174,7 +178,7 @@ export default {
174
178
  this.isOpen = false
175
179
  this.q = null
176
180
  this.list = undefined
177
- this.focus = undefined
181
+ this.focusIndex = undefined
178
182
  },
179
183
  },
180
184
  watch: {
@@ -3,7 +3,10 @@
3
3
  class="flex flex-col flex-1"
4
4
  :class="{ 'overflow-y-hidden': enableOverflow }"
5
5
  >
6
- <nav class="flex flex-col sm:flex-row" :class="sharedClass">
6
+ <nav class="flex flex-col sm:flex-row" :class="{
7
+ [sharedClass]: !isBlank(sharedClass),
8
+ [navClass]: !isBlank(navClass)
9
+ }">
7
10
  <button
8
11
  v-for="(tab, index) in tabs"
9
12
  :key="`tab-${index}`"
@@ -19,13 +22,17 @@
19
22
  {{ tab.name }}
20
23
  </button>
21
24
  </nav>
22
- <div class="relative -mt-1/2" :class="sharedClass">
25
+ <div class="relative -mt-1/2" :class="{
26
+ [sharedClass]: !isBlank(sharedClass),
27
+ [navClass]: !isBlank(navClass)
28
+ }">
23
29
  <div class="w-full border-gray-200 border-t-2 h-0"></div>
24
30
  </div>
25
31
  <div
26
32
  class="flex-1 mt-4 pb-4"
27
33
  :class="{
28
34
  [sharedClass]: !isBlank(sharedClass),
35
+ [panelClass]: !isBlank(panelClass),
29
36
  'overflow-y-auto': enableOverflow,
30
37
  }"
31
38
  >
@@ -35,6 +42,7 @@
35
42
  :key="currentTabKey"
36
43
  v-on="$listeners"
37
44
  v-bind="{ ...otherProps, ...currentTabProps }"
45
+ class="px-1"
38
46
  />
39
47
  </transition>
40
48
  </div>
@@ -48,6 +56,8 @@ export default {
48
56
  tabs: { type: Array, default: () => [] },
49
57
  firstIndex: { type: Number, default: 0 },
50
58
  otherProps: { type: Object, default: () => ({}) },
59
+ navClass: { type: String, default: null },
60
+ panelClass: { type: String, default: null },
51
61
  sharedClass: { type: String, default: null },
52
62
  enableOverflow: { type: Boolean, default: true },
53
63
  },
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="space-y-1">
2
+ <div class="space-y-1 flex flex-col">
3
3
  <label
4
4
  class="block font-semibold text-gray-800"
5
5
  :for="name"
@@ -15,12 +15,13 @@
15
15
  </transition>
16
16
  </label>
17
17
  <input
18
+ :id="name"
18
19
  type="text"
19
20
  :value="value"
20
21
  :placeholder="placeholder"
21
22
  @blur="blur()"
22
23
  @input="updateInput"
23
- class="block w-full py-2 px-3 rounded bg-gray-100 text-gray-800 focus:outline-none focus:ring placeholder-gray-500"
24
+ class="block py-2 px-3 rounded bg-gray-100 text-gray-800 focus:outline-none focus:ring placeholder-gray-500"
24
25
  autocomplete="off"
25
26
  ref="input"
26
27
  />
@@ -1,6 +1,7 @@
1
1
  <template>
2
- <div>
2
+ <div class="space-y-1 flex flex-col">
3
3
  <label
4
+ :for="name"
4
5
  class="block font-semibold text-gray-800 flex justify-between items-center"
5
6
  >
6
7
  <span>{{ label }}</span>
@@ -15,10 +16,11 @@
15
16
  >
16
17
  </label>
17
18
  <textarea
19
+ :id="name"
18
20
  :value="value"
19
21
  @blur="blur()"
20
22
  @input="updateInput"
21
- class="block w-full mt-1 py-2 px-3 rounded bg-gray-100 text-gray-800 focus:outline-none focus:ring"
23
+ class="block mt-1 py-2 px-3 rounded bg-gray-100 text-gray-800 focus:outline-none focus:ring"
22
24
  autocomplete="off"
23
25
  ref="input"
24
26
  :rows="rows"
@@ -4,7 +4,7 @@
4
4
  :tabs="tabs"
5
5
  :firstIndex="firstTabIndex"
6
6
  :otherProps="{ currentLink: link }"
7
- sharedClass="px-1/2"
7
+ navClass="px-1"
8
8
  :enableOverflow="false"
9
9
  @select-tab="onTabSelected"
10
10
  @change="onChange"
@@ -3,7 +3,8 @@
3
3
  <uikit-tabs
4
4
  :tabs="tabs"
5
5
  :otherProps="{ page: editedPage, errors }"
6
- sharedClass="px-1/2"
6
+ navClass="mx-4"
7
+ panelClass="mx-3"
7
8
  class="overflow-y-hidden pb-4"
8
9
  @on-change="onChange"
9
10
  />
@@ -3,7 +3,8 @@
3
3
  <uikit-tabs
4
4
  :tabs="tabs"
5
5
  :otherProps="{ page, errors }"
6
- sharedClass="px-1/2"
6
+ navClass="mx-1"
7
+ panelClass=""
7
8
  class="overflow-y-hidden pb-4"
8
9
  @on-change="onChange"
9
10
  />
@@ -4,7 +4,8 @@
4
4
  :firstIndex="tabIndexFromRoute"
5
5
  :otherProps="{ sectionId: currentSection.id, settingId }"
6
6
  class="overflow-y-hidden"
7
- sharedClass="px-4"
7
+ navClass="px-4"
8
+ panelClass="px-3"
8
9
  ref="tabs"
9
10
  />
10
11
  </template>
@@ -85,7 +85,7 @@ const buildSetting = (setting, sampleContent) => {
85
85
  let value = sampleContent ?? setting.default
86
86
  switch (setting.type) {
87
87
  case 'image':
88
- value = typeof value === 'string' ? { url: value } : {}
88
+ value = typeof value === 'string' ? { url: value } : value || {}
89
89
  break
90
90
  case 'link':
91
91
  value =
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <layout :title="$t('page.edit.currentPage.title')" :overflowY="false">
3
- <div class="flex flex-col flex-1 mx-4 pb-4 overflow-y-hidden">
3
+ <div class="flex flex-col flex-1 pb-4 overflow-y-hidden">
4
4
  <edit-page
5
5
  :page="currentPage"
6
6
  v-if="currentPage"
@@ -2,7 +2,6 @@ import { listenMessages } from './message'
2
2
 
3
3
  const start = () => {
4
4
  if (window.location === window.parent.location) {
5
- console.log('🚨 not in the Maglev editor')
6
5
  return false
7
6
  }
8
7
  listenMessages()
@@ -17,7 +17,8 @@ module Maglev
17
17
 
18
18
  entries = maglev_asset_manifest.resolve_entries(*%w[live-preview-rails-client], type: :javascript)
19
19
 
20
- javascript_include_tag(*entries.fetch(:scripts).flatten.uniq, crossorigin: 'anonymous', type: 'module')
20
+ javascript_include_tag(*entries.fetch(:scripts).flatten.uniq, crossorigin: 'anonymous', type: 'module',
21
+ defer: true)
21
22
  end
22
23
 
23
24
  def maglev_asset_manifest
@@ -9,8 +9,7 @@ module Maglev
9
9
  theme: theme || maglev_theme,
10
10
  page: page || maglev_page,
11
11
  page_sections: page_sections || maglev_page_sections,
12
- templates_root_path: maglev_sections_path,
13
- config: maglev_config
12
+ context: maglev_rendering_context
14
13
  ).tap { |component| component.view_context = self }.render.html_safe
15
14
  end
16
15
  # rubocop:enable Rails/OutputSafety
@@ -44,7 +43,7 @@ module Maglev
44
43
 
45
44
  def maglev_alt_link(locale, links: nil)
46
45
  links ||= maglev_page_fullpaths
47
- link = links[locale]
46
+ link = links[locale.to_sym]
48
47
  return nil if link.nil?
49
48
 
50
49
  "#{request.base_url}#{link}"
@@ -54,6 +53,18 @@ module Maglev
54
53
  maglev_site_root_fullpath
55
54
  end
56
55
 
56
+ def maglev_current_locale?(locale)
57
+ locale.to_sym == maglev_content_locale
58
+ end
59
+
60
+ def maglev_rendering_context
61
+ {
62
+ templates_root_path: maglev_sections_path,
63
+ rendering_mode: maglev_rendering_mode,
64
+ config: maglev_config
65
+ }
66
+ end
67
+
57
68
  def rendering_maglev_page?
58
69
  controller.class.module_parent.to_s == 'Maglev'
59
70
  end
@@ -4,7 +4,7 @@
4
4
  class Maglev::SettingTypes::CollectionItem < Maglev::SettingTypes::Base
5
5
  def cast_value(value)
6
6
  if value.is_a?(String)
7
- { id: default }
7
+ { id: value }
8
8
  else
9
9
  value
10
10
  end
@@ -6,7 +6,7 @@ module Maglev::Site::LocalesConcern
6
6
 
7
7
  included do
8
8
  ## serializers ##
9
- if Rails::VERSION::MAJOR > 6
9
+ if Rails::VERSION::MAJOR >= 7 && Rails::VERSION::MINOR.positive?
10
10
  serialize :locales, coder: LocalesSerializer
11
11
  else
12
12
  serialize :locales, LocalesSerializer
@@ -6,7 +6,7 @@ module Maglev
6
6
  include Injectable
7
7
 
8
8
  def call
9
- Maglev::Site.first.tap do |site|
9
+ @site ||= Maglev::Site.first.tap do |site|
10
10
  change_default_locales(site)
11
11
  end
12
12
  end
@@ -74,6 +74,9 @@ module Maglev
74
74
  def select_site_scoped_sections(sections)
75
75
  (sections || []).find_all do |section|
76
76
  definition = theme.sections.find(section['type'])
77
+
78
+ raise "[Maglev] Unknown section type: #{section['type']}" unless definition
79
+
77
80
  definition.site_scoped?
78
81
  end
79
82
  end