maglevcms 1.8.0 → 2.0.0.beta1
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.
- checksums.yaml +4 -4
- data/.yarn/install-state.gz +0 -0
- data/README.md +4 -4
- data/Rakefile +2 -1
- data/app/components/maglev/block_component.rb +1 -1
- data/app/components/maglev/content/base.rb +1 -1
- data/app/components/maglev/content/link.rb +4 -0
- data/app/components/maglev/section_component.rb +2 -2
- data/app/controllers/concerns/maglev/fetchers_concern.rb +3 -1
- data/app/controllers/concerns/maglev/resource_id_concern.rb +10 -0
- data/app/controllers/concerns/maglev/standalone_sections_concern.rb +6 -0
- data/app/controllers/concerns/maglev/{ui_locale_concern.rb → user_interface_locale_concern.rb} +1 -1
- data/app/controllers/maglev/api/collection_items_controller.rb +7 -0
- data/app/controllers/maglev/api/page_clones_controller.rb +1 -2
- data/app/controllers/maglev/api_controller.rb +1 -1
- data/app/controllers/maglev/application_controller.rb +1 -5
- data/app/controllers/maglev/assets/active_storage_proxy_controller.rb +17 -0
- data/app/controllers/maglev/assets/proxy_controller.rb +21 -0
- data/app/controllers/maglev/editor_controller.rb +1 -1
- data/app/controllers/maglev/page_preview_controller.rb +3 -3
- data/app/frontend/admin/controllers/screenshot_controller.js +29 -1
- data/app/frontend/editor/assets/remixicons/clipboard-line.svg +1 -0
- data/app/frontend/editor/assets/remixicons/ri-draggable.svg +1 -0
- data/app/frontend/editor/assets/remixicons/ri-folders-line.svg +1 -0
- data/app/frontend/editor/assets/remixicons/ri-more-fill.svg +1 -0
- data/app/frontend/editor/assets/remixicons/ri-shadow-line.svg +1 -0
- data/app/frontend/editor/components/errors/forbidden.vue +24 -0
- data/app/frontend/editor/components/errors/stale-record.vue +2 -2
- data/app/frontend/editor/components/header-nav/device-toggler.vue +6 -3
- data/app/frontend/editor/components/header-nav/index.vue +13 -42
- data/app/frontend/editor/components/header-nav/locale-toggler/index.vue +1 -1
- data/app/frontend/editor/components/header-nav/page-info.vue +41 -0
- data/app/frontend/editor/components/header-nav/preview-button.vue +6 -1
- data/app/frontend/editor/components/header-nav/separator.vue +1 -1
- data/app/frontend/editor/components/image-library/index.vue +26 -29
- data/app/frontend/editor/components/kit/collection-item-input.vue +9 -0
- data/app/frontend/editor/components/kit/copy-paste-button.vue +26 -0
- data/app/frontend/editor/components/kit/dropdown.vue +5 -0
- data/app/frontend/editor/components/kit/icon-button.vue +24 -0
- data/app/frontend/editor/components/kit/icon.vue +2 -3
- data/app/frontend/editor/components/kit/index.js +4 -2
- data/app/frontend/editor/components/kit/link-input.vue +1 -1
- data/app/frontend/editor/components/kit/modal.vue +1 -1
- data/app/frontend/editor/components/kit/page-icon.vue +1 -1
- data/app/frontend/editor/components/kit/rich-text-input/link-buttons.vue +1 -1
- data/app/frontend/editor/components/kit/select-input.vue +4 -2
- data/app/frontend/editor/components/link-picker/actions.vue +1 -1
- data/app/frontend/editor/components/link-picker/index.vue +1 -1
- data/app/frontend/editor/components/link-picker/page.vue +2 -0
- data/app/frontend/editor/components/page/form/main.vue +1 -1
- data/app/frontend/editor/components/page/list/actions-button.vue +159 -0
- data/app/frontend/editor/components/page/list/index.vue +15 -24
- data/app/frontend/editor/components/page/list/list-item.vue +10 -61
- data/app/frontend/editor/components/section-highlighter/index.vue +47 -46
- data/app/frontend/editor/components/section-list/add-button.vue +39 -0
- data/app/frontend/editor/components/section-list/index.vue +30 -15
- data/app/frontend/editor/components/section-list/list-item.vue +23 -8
- data/app/frontend/editor/components/section-pane/block-list/index.vue +1 -0
- data/app/frontend/editor/components/section-pane/block-list/list-item.vue +9 -6
- data/app/frontend/editor/components/section-pane/block-tree/new-nested-block-button.vue +2 -2
- data/app/frontend/editor/components/section-pane/block-tree/tree-node.vue +2 -2
- data/app/frontend/editor/components/sidebar-nav/index.vue +102 -0
- data/app/frontend/editor/components/sidebar-nav/link.vue +60 -0
- data/app/frontend/editor/components/theme-section-list/category.vue +47 -0
- data/app/frontend/editor/components/theme-section-list/index.vue +7 -31
- data/app/frontend/editor/components/theme-section-list/list-item.vue +10 -3
- data/app/frontend/editor/design/components/modal.scss +1 -1
- data/app/frontend/editor/design/components/tooltip.scss +6 -0
- data/app/frontend/editor/design/transitions.scss +1 -1
- data/app/frontend/editor/layouts/app.vue +1 -1
- data/app/frontend/editor/layouts/default.vue +2 -2
- data/app/frontend/editor/layouts/slide-pane.vue +1 -1
- data/app/frontend/editor/locales/editor.ar.json +265 -0
- data/app/frontend/editor/locales/editor.en.json +23 -15
- data/app/frontend/editor/locales/editor.es.json +18 -10
- data/app/frontend/editor/locales/editor.fr.json +28 -13
- data/app/frontend/editor/locales/editor.pt-BR.json +18 -10
- data/app/frontend/editor/locales/index.js +3 -0
- data/app/frontend/editor/mixins/error-modal.js +7 -2
- data/app/frontend/editor/mixins/preview-transformation.js +0 -1
- data/app/frontend/editor/plugins/i18n.js +2 -17
- data/app/frontend/editor/services/__tests__/section.spec.js +6 -0
- data/app/frontend/editor/services/collection-item.js +8 -0
- data/app/frontend/editor/services/page.js +1 -1
- data/app/frontend/editor/services/section.js +30 -0
- data/app/frontend/editor/services/site.js +4 -4
- data/app/frontend/editor/services/theme.js +1 -0
- data/app/frontend/editor/spec/__mocks__/page.js +3 -1
- data/app/frontend/editor/spec/__mocks__/services.js +1 -0
- data/app/frontend/editor/store/__tests__/getters.spec.js +56 -1
- data/app/frontend/editor/store/actions/index.js +1 -0
- data/app/frontend/editor/store/actions/site.js +8 -4
- data/app/frontend/editor/store/getters.js +11 -0
- data/app/frontend/editor/views/page-preview.vue +2 -1
- data/app/frontend/images/favicon.svg +11 -0
- data/app/frontend/images/logo.svg +14 -0
- data/app/frontend/live-preview-client/iframe-decorator.js +17 -15
- data/app/frontend/live-preview-client/rails.js +1 -1
- data/app/helpers/maglev/application_helper.rb +7 -2
- data/app/helpers/maglev/editor_helper.rb +12 -5
- data/app/models/concerns/maglev/sections_concern.rb +4 -0
- data/app/models/maglev/asset.rb +13 -14
- data/app/models/maglev/page/path_concern.rb +23 -8
- data/app/models/maglev/page.rb +17 -18
- data/app/models/maglev/page_path.rb +18 -18
- data/app/models/maglev/section/setting.rb +1 -1
- data/app/models/maglev/section.rb +18 -9
- data/app/models/maglev/setting_types/link.rb +1 -1
- data/app/models/maglev/site.rb +13 -24
- data/app/services/maglev/app_container.rb +2 -2
- data/app/services/maglev/extract_locale.rb +3 -2
- data/app/services/maglev/fetch_page.rb +2 -0
- data/app/services/maglev/fetch_theme_layout.rb +2 -0
- data/app/services/maglev/get_page_fullpath.rb +1 -2
- data/app/services/maglev/remove_section_type.rb +50 -0
- data/app/services/maglev/rename_section_type.rb +57 -0
- data/app/services/maglev/search_pages.rb +2 -1
- data/app/views/layouts/maglev/admin/application.html.erb +1 -1
- data/app/views/maglev/admin/sections/previews/show.html.erb +16 -1
- data/app/views/maglev/api/collection_items/show.json.jbuilder +7 -0
- data/app/views/maglev/api/page_clones/create.json.jbuilder +3 -0
- data/app/views/maglev/editor/show.html.erb +6 -5
- data/config/locales/activerecord.ar.yml +13 -0
- data/config/locales/activerecord.en.yml +8 -2
- data/config/locales/activerecord.es.yml +4 -0
- data/config/locales/activerecord.fr.yml +6 -2
- data/config/locales/activerecord.pt-BR.yml +13 -0
- data/config/routes.rb +3 -4
- data/db/migrate/20200831101942_create_maglev_section_content.rb +10 -2
- data/db/migrate/20210819092740_switch_to_localized_page_fields.rb +13 -3
- data/db/migrate/20211008064437_add_locales_to_sites.rb +7 -1
- data/db/migrate/20211013210954_translate_section_content.rb +16 -2
- data/db/migrate/20211203224112_add_open_graph_tags_to_pages.rb +9 -3
- data/db/migrate/20220612092235_add_style_to_sites.rb +5 -1
- data/lib/commands/maglev/change_site_locales_command.rb +61 -0
- data/lib/commands/maglev/create_site_command.rb +28 -0
- data/lib/commands/maglev/sections/remove_command.rb +48 -0
- data/lib/commands/maglev/sections/rename_command.rb +49 -0
- data/lib/generators/maglev/templates/install/config/initializers/maglev.rb +4 -1
- data/lib/generators/maglev/templates/theme/app/views/theme/layout.html.erb.tt +8 -2
- data/lib/maglev/errors.rb +1 -0
- data/lib/maglev/preview_constraint.rb +5 -1
- data/lib/maglev/theme_filesystem_loader.rb +7 -0
- data/lib/maglev/version.rb +1 -1
- data/lib/maglev.rb +13 -3
- data/lib/tasks/maglev/icons.rake +123 -0
- data/lib/tasks/maglev/vite.rake +62 -0
- data/lib/tasks/maglev_tasks.rake +9 -107
- data/tailwind.config.js +1 -0
- metadata +48 -33
- data/app/controllers/maglev/assets_controller.rb +0 -10
- data/app/frontend/editor/components/kit/list-item-button.vue +0 -16
- data/app/frontend/editor/components/sidebar-nav.vue +0 -125
- data/app/frontend/editor/plugins/maglev_dummy.js +0 -2
- data/app/frontend/images/favicon.png +0 -0
- data/app/frontend/images/logo.png +0 -0
@@ -4,22 +4,32 @@
|
|
4
4
|
module Maglev::Page::PathConcern
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
|
+
COMMON_ASSOCIATION_PATH_OPTIONS = {
|
8
|
+
class_name: '::Maglev::PagePath',
|
9
|
+
foreign_key: 'maglev_page_id',
|
10
|
+
inverse_of: :page
|
11
|
+
}.freeze
|
12
|
+
|
7
13
|
included do
|
8
14
|
## associations ##
|
9
15
|
has_many :paths,
|
10
|
-
|
16
|
+
**COMMON_ASSOCIATION_PATH_OPTIONS,
|
11
17
|
dependent: :delete_all,
|
12
|
-
foreign_key: 'maglev_page_id',
|
13
|
-
inverse_of: :page,
|
14
18
|
autosave: true
|
15
19
|
|
20
|
+
# rubocop:disable Rails/HasManyOrHasOneDependent, Rails/InverseOf
|
21
|
+
has_many :canonical_paths,
|
22
|
+
-> { where(canonical: true) },
|
23
|
+
**COMMON_ASSOCIATION_PATH_OPTIONS
|
24
|
+
# rubocop:enable Rails/HasManyOrHasOneDependent, Rails/InverseOf
|
25
|
+
|
16
26
|
## callbacks ##
|
17
27
|
before_validation { path } # force the initialization of a new path if it doesn't exist
|
18
28
|
before_save :spawn_redirection, if: :spawn_redirection?
|
19
29
|
end
|
20
30
|
|
21
31
|
def default_path
|
22
|
-
@default_path ||=
|
32
|
+
@default_path ||= path_hash[Maglev::I18n.default_locale]
|
23
33
|
end
|
24
34
|
|
25
35
|
def path
|
@@ -38,13 +48,18 @@ module Maglev::Page::PathConcern
|
|
38
48
|
end
|
39
49
|
|
40
50
|
def current_path
|
41
|
-
locale = Maglev::I18n.current_locale
|
42
|
-
|
43
|
-
|
51
|
+
locale = Maglev::I18n.current_locale
|
52
|
+
canonical_path_hash[locale] ||= paths.build(locale: locale, canonical: true)
|
53
|
+
end
|
54
|
+
|
55
|
+
def canonical_path_hash
|
56
|
+
@canonical_path_hash ||= canonical_paths.to_a.each_with_object({}.with_indifferent_access) do |path, memo|
|
57
|
+
memo[path.locale] ||= path
|
58
|
+
end
|
44
59
|
end
|
45
60
|
|
46
61
|
def path_hash
|
47
|
-
|
62
|
+
canonical_path_hash.transform_values(&:value)
|
48
63
|
end
|
49
64
|
|
50
65
|
def disable_spawn_redirection
|
data/app/models/maglev/page.rb
CHANGED
@@ -1,5 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# == Schema Information
|
4
|
+
#
|
5
|
+
# Table name: maglev_pages
|
6
|
+
#
|
7
|
+
# id :bigint not null, primary key
|
8
|
+
# lock_version :integer
|
9
|
+
# meta_description_translations :jsonb
|
10
|
+
# og_description_translations :jsonb
|
11
|
+
# og_image_url_translations :jsonb
|
12
|
+
# og_title_translations :jsonb
|
13
|
+
# sections_translations :jsonb
|
14
|
+
# seo_title_translations :jsonb
|
15
|
+
# title_translations :jsonb
|
16
|
+
# visible :boolean default(TRUE)
|
17
|
+
# created_at :datetime not null
|
18
|
+
# updated_at :datetime not null
|
19
|
+
#
|
3
20
|
module Maglev
|
4
21
|
class Page < ApplicationRecord
|
5
22
|
## concerns ##
|
@@ -42,21 +59,3 @@ module Maglev
|
|
42
59
|
end
|
43
60
|
end
|
44
61
|
end
|
45
|
-
|
46
|
-
# == Schema Information
|
47
|
-
#
|
48
|
-
# Table name: maglev_pages
|
49
|
-
#
|
50
|
-
# id :bigint not null, primary key
|
51
|
-
# lock_version :integer
|
52
|
-
# meta_description_translations :jsonb
|
53
|
-
# og_description_translations :jsonb
|
54
|
-
# og_image_url_translations :jsonb
|
55
|
-
# og_title_translations :jsonb
|
56
|
-
# sections_translations :jsonb
|
57
|
-
# seo_title_translations :jsonb
|
58
|
-
# title_translations :jsonb
|
59
|
-
# visible :boolean default(TRUE)
|
60
|
-
# created_at :datetime not null
|
61
|
-
# updated_at :datetime not null
|
62
|
-
#
|
@@ -1,5 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# == Schema Information
|
4
|
+
#
|
5
|
+
# Table name: maglev_page_paths
|
6
|
+
#
|
7
|
+
# id :bigint not null, primary key
|
8
|
+
# canonical :boolean default(TRUE)
|
9
|
+
# locale :string not null
|
10
|
+
# value :string not null
|
11
|
+
# maglev_page_id :bigint
|
12
|
+
#
|
13
|
+
# Indexes
|
14
|
+
#
|
15
|
+
# canonical_speed (canonical,locale,value)
|
16
|
+
# index_maglev_page_paths_on_maglev_page_id (maglev_page_id)
|
17
|
+
# scoped_canonical_speed (canonical,maglev_page_id,locale)
|
18
|
+
#
|
3
19
|
module Maglev
|
4
20
|
class PagePath < ApplicationRecord
|
5
21
|
## associations ##
|
@@ -13,6 +29,7 @@ module Maglev
|
|
13
29
|
## validations ##
|
14
30
|
validates :value, presence: true, exclusion: { in: Maglev.config.reserved_paths }
|
15
31
|
validates :value, uniqueness: { scope: %i[locale canonical] }, if: :canonical?
|
32
|
+
validates :value, format: { without: /\s/, message: :invalid_path }
|
16
33
|
validates :canonical, uniqueness: { scope: %i[locale maglev_page_id] }, if: :canonical?
|
17
34
|
|
18
35
|
## callbacks ##
|
@@ -23,7 +40,7 @@ module Maglev
|
|
23
40
|
|
24
41
|
## class methods ##
|
25
42
|
|
26
|
-
def self.
|
43
|
+
def self.canonical_value_hash(page_id = nil)
|
27
44
|
query = page_id ? where(maglev_page_id: page_id) : all
|
28
45
|
query.canonical.pluck(:locale, :value).to_h
|
29
46
|
end
|
@@ -44,20 +61,3 @@ module Maglev
|
|
44
61
|
end
|
45
62
|
end
|
46
63
|
end
|
47
|
-
|
48
|
-
# == Schema Information
|
49
|
-
#
|
50
|
-
# Table name: maglev_page_paths
|
51
|
-
#
|
52
|
-
# id :bigint not null, primary key
|
53
|
-
# canonical :boolean default(TRUE)
|
54
|
-
# locale :string not null
|
55
|
-
# value :string not null
|
56
|
-
# maglev_page_id :bigint
|
57
|
-
#
|
58
|
-
# Indexes
|
59
|
-
#
|
60
|
-
# canonical_speed (canonical,locale,value)
|
61
|
-
# index_maglev_page_paths_on_maglev_page_id (maglev_page_id)
|
62
|
-
# scoped_canonical_speed (canonical,maglev_page_id,locale)
|
63
|
-
#
|
@@ -12,7 +12,7 @@ class Maglev::Section::Setting
|
|
12
12
|
attr_accessor :id, :label, :type, :default, :options
|
13
13
|
|
14
14
|
## validations ##
|
15
|
-
validates :id, :label, :type,
|
15
|
+
validates :id, :label, :type, 'maglev/presence': true
|
16
16
|
validates :type, inclusion: { in: REGISTERED_TYPES }
|
17
17
|
|
18
18
|
## methods ##
|
@@ -35,19 +35,28 @@ module Maglev
|
|
35
35
|
!!viewport_fixed_position?
|
36
36
|
end
|
37
37
|
|
38
|
+
def assign_attributes_from_yaml(hash)
|
39
|
+
attributes = prepare_default_attributes(hash).merge(
|
40
|
+
settings: ::Maglev::Section::Setting.build_many(hash['settings']),
|
41
|
+
blocks: ::Maglev::Section::Block.build_many(hash['blocks'])
|
42
|
+
)
|
43
|
+
|
44
|
+
assign_attributes(attributes)
|
45
|
+
end
|
46
|
+
|
38
47
|
## class methods ##
|
39
|
-
def self.build(hash)
|
40
|
-
attributes = prepare_attributes(hash)
|
41
48
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
)
|
47
|
-
)
|
49
|
+
def self.build(hash)
|
50
|
+
new.tap do |section|
|
51
|
+
section.assign_attributes_from_yaml(hash)
|
52
|
+
end
|
48
53
|
end
|
49
54
|
|
50
|
-
|
55
|
+
## private methods ##
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def prepare_default_attributes(hash)
|
51
60
|
attributes = hash.slice(*HASH_ATTRIBUTES)
|
52
61
|
|
53
62
|
%w[site_scoped singleton viewport_fixed_position max_width_pane].each do |name|
|
@@ -5,7 +5,7 @@ class Maglev::SettingTypes::Link < Maglev::SettingTypes::Base
|
|
5
5
|
def cast_value(value)
|
6
6
|
if value.is_a?(String)
|
7
7
|
{ text: 'Link', link_type: 'url', href: value }
|
8
|
-
|
8
|
+
elsif value
|
9
9
|
{ text: 'Link', link_type: 'url', href: '#' }.merge(value.symbolize_keys)
|
10
10
|
end
|
11
11
|
end
|
data/app/models/maglev/site.rb
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# == Schema Information
|
4
|
+
#
|
5
|
+
# Table name: maglev_sites
|
6
|
+
#
|
7
|
+
# id :bigint not null, primary key
|
8
|
+
# locales :jsonb
|
9
|
+
# lock_version :integer
|
10
|
+
# name :string
|
11
|
+
# sections_translations :jsonb
|
12
|
+
# style :jsonb
|
13
|
+
# created_at :datetime not null
|
14
|
+
# updated_at :datetime not null
|
15
|
+
#
|
3
16
|
module Maglev
|
4
17
|
class Site < ApplicationRecord
|
5
18
|
## concerns ##
|
@@ -27,27 +40,3 @@ module Maglev
|
|
27
40
|
end
|
28
41
|
end
|
29
42
|
end
|
30
|
-
|
31
|
-
# == Schema Information
|
32
|
-
#
|
33
|
-
# Table name: maglev_sites
|
34
|
-
#
|
35
|
-
# id :bigint not null, primary key
|
36
|
-
# domain :string
|
37
|
-
# handle :string
|
38
|
-
# locales :jsonb
|
39
|
-
# lock_version :integer
|
40
|
-
# name :string
|
41
|
-
# navigation :jsonb
|
42
|
-
# sections_translations :jsonb
|
43
|
-
# siteable_type :string
|
44
|
-
# style :jsonb
|
45
|
-
# created_at :datetime not null
|
46
|
-
# updated_at :datetime not null
|
47
|
-
# siteable_id :bigint
|
48
|
-
# theme_id :string
|
49
|
-
#
|
50
|
-
# Indexes
|
51
|
-
#
|
52
|
-
# index_maglev_sites_on_siteable (siteable_type,siteable_id)
|
53
|
-
#
|
@@ -23,7 +23,7 @@ module Maglev
|
|
23
23
|
|
24
24
|
dependency :fetch_collection_items, class: Maglev::FetchCollectionItems, depends_on: %i[fetch_site config]
|
25
25
|
dependency :fetch_static_pages, class: Maglev::FetchStaticPages, depends_on: %i[config]
|
26
|
-
dependency :search_pages, class: Maglev::SearchPages, depends_on: %i[fetch_site fetch_static_pages]
|
26
|
+
dependency :search_pages, class: Maglev::SearchPages, depends_on: %i[fetch_site fetch_static_pages context]
|
27
27
|
|
28
28
|
dependency :get_base_url, class: Maglev::GetBaseUrl, depends_on: %i[context fetch_site]
|
29
29
|
dependency :extract_locale, class: Maglev::ExtractLocale
|
@@ -34,7 +34,7 @@ module Maglev
|
|
34
34
|
dependency :add_site_locale, class: Maglev::AddSiteLocale
|
35
35
|
dependency :change_site_locales, class: Maglev::ChangeSiteLocales
|
36
36
|
|
37
|
-
dependency :fetch_page, class: Maglev::FetchPage, depends_on:
|
37
|
+
dependency :fetch_page, class: Maglev::FetchPage, depends_on: %i[context fetch_site]
|
38
38
|
dependency :get_page_fullpath, class: Maglev::GetPageFullpath, depends_on: %i[fetch_site get_base_url]
|
39
39
|
dependency :get_page_sections, class: Maglev::GetPageSections,
|
40
40
|
depends_on: %i[fetch_site fetch_theme
|
@@ -22,9 +22,10 @@ module Maglev
|
|
22
22
|
protected
|
23
23
|
|
24
24
|
def extract_locale
|
25
|
-
|
25
|
+
path = params[:path] || 'index'
|
26
|
+
segments = path.split('/')
|
26
27
|
|
27
|
-
return [default_locale,
|
28
|
+
return [default_locale, path] unless locales.include?(segments[0]&.to_sym)
|
28
29
|
|
29
30
|
[segments.shift, segments.empty? ? 'index' : segments.join('/')]
|
30
31
|
end
|
@@ -38,8 +38,7 @@ module Maglev
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def fetch_paths
|
41
|
-
|
42
|
-
Maglev::PagePath.build_hash(page_id)
|
41
|
+
page.respond_to?(:path_hash) ? page.path_hash : Maglev::PagePath.canonical_value_hash(page)
|
43
42
|
end
|
44
43
|
|
45
44
|
def build_fullpath(base_url, path)
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Maglev
|
4
|
+
# Remove all sections of a specific type across a site and its pages
|
5
|
+
class RemoveSectionType
|
6
|
+
include Injectable
|
7
|
+
|
8
|
+
argument :site
|
9
|
+
argument :type
|
10
|
+
|
11
|
+
def call
|
12
|
+
@removed_count = 0
|
13
|
+
|
14
|
+
remove_sections
|
15
|
+
|
16
|
+
@removed_count
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def remove_sections
|
22
|
+
ActiveRecord::Base.transaction do
|
23
|
+
remove_resource_sections(site)
|
24
|
+
site_pages.find_each do |page|
|
25
|
+
remove_resource_sections(page)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def remove_resource_sections(resource)
|
31
|
+
site.each_locale do
|
32
|
+
@removed_count += remove_sections_of_type(resource.sections, type)
|
33
|
+
end
|
34
|
+
|
35
|
+
resource.save!
|
36
|
+
end
|
37
|
+
|
38
|
+
def remove_sections_of_type(sections, type)
|
39
|
+
return 0 if sections.blank?
|
40
|
+
|
41
|
+
original_size = sections.size
|
42
|
+
sections.reject! { |section| section['type'] == type }
|
43
|
+
original_size - sections.size
|
44
|
+
end
|
45
|
+
|
46
|
+
def site_pages
|
47
|
+
Maglev::Page
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Maglev
|
4
|
+
# Rename all sections of a specific type to a new type across a site and its pages
|
5
|
+
class RenameSectionType
|
6
|
+
include Injectable
|
7
|
+
|
8
|
+
argument :site
|
9
|
+
argument :theme
|
10
|
+
argument :old_type
|
11
|
+
argument :new_type
|
12
|
+
|
13
|
+
def call
|
14
|
+
validate_section_types!
|
15
|
+
|
16
|
+
ActiveRecord::Base.transaction do
|
17
|
+
rename_resource_sections(site)
|
18
|
+
site_pages.find_each do |page|
|
19
|
+
rename_resource_sections(page)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
true
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def validate_section_types!
|
29
|
+
return if theme.sections.find(new_type)
|
30
|
+
|
31
|
+
raise Maglev::Errors::UnknownSection,
|
32
|
+
"New section type '#{new_type}' doesn't exist in the theme"
|
33
|
+
end
|
34
|
+
|
35
|
+
def rename_resource_sections(resource)
|
36
|
+
site.each_locale do |locale|
|
37
|
+
Maglev::I18n.with_locale(locale) do
|
38
|
+
change_section_type(resource.sections, old_type, new_type)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
resource.save!
|
43
|
+
end
|
44
|
+
|
45
|
+
def change_section_type(sections, old_type, new_type)
|
46
|
+
return if sections.blank?
|
47
|
+
|
48
|
+
sections.each do |section|
|
49
|
+
section['type'] = new_type if section['type'] == old_type
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def site_pages
|
54
|
+
Maglev::Page
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -9,6 +9,7 @@ module Maglev
|
|
9
9
|
|
10
10
|
dependency :fetch_site
|
11
11
|
dependency :fetch_static_pages
|
12
|
+
dependency :context
|
12
13
|
|
13
14
|
argument :id, default: nil
|
14
15
|
argument :q, default: nil
|
@@ -54,7 +55,7 @@ module Maglev
|
|
54
55
|
end
|
55
56
|
|
56
57
|
def resources
|
57
|
-
::Maglev::Page
|
58
|
+
::Maglev::Page.includes(:canonical_paths)
|
58
59
|
end
|
59
60
|
end
|
60
61
|
end
|
@@ -9,7 +9,7 @@
|
|
9
9
|
<%= vite_javascript_tag 'admin' %>
|
10
10
|
<%= vite_stylesheet_tag 'admin.scss' %>
|
11
11
|
|
12
|
-
<%= favicon_link_tag vite_asset_path 'images/favicon.
|
12
|
+
<%= favicon_link_tag vite_asset_path 'images/favicon.svg' %>
|
13
13
|
</head>
|
14
14
|
<body class="bg-gray-100">
|
15
15
|
<main role="main" class="container mx-auto">
|
@@ -12,11 +12,26 @@
|
|
12
12
|
Open in a new tab
|
13
13
|
<% end %>
|
14
14
|
<button
|
15
|
-
class="bg-purple-600 hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-purple-600 focus:ring-opacity-50 rounded text-white py-2 px-3"
|
15
|
+
class="bg-purple-600 hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-purple-600 focus:ring-opacity-50 rounded text-white py-2 px-3 mr-3"
|
16
16
|
data-action="click->screenshot#take"
|
17
17
|
>
|
18
18
|
Take screenshot
|
19
19
|
</button>
|
20
|
+
<div class="relative">
|
21
|
+
<button
|
22
|
+
class="bg-purple-600 hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-purple-600 focus:ring-opacity-50 rounded text-white py-2 px-3"
|
23
|
+
data-action="click->screenshot#triggerFileInput"
|
24
|
+
>
|
25
|
+
Upload screenshot
|
26
|
+
</button>
|
27
|
+
<input
|
28
|
+
type="file"
|
29
|
+
accept="image/*"
|
30
|
+
class="hidden"
|
31
|
+
data-screenshot-target="fileInput"
|
32
|
+
data-action="change->screenshot#handleFileUpload"
|
33
|
+
/>
|
34
|
+
</div>
|
20
35
|
</div>
|
21
36
|
</div>
|
22
37
|
<iframe
|
@@ -5,9 +5,10 @@
|
|
5
5
|
|
6
6
|
<%= csrf_meta_tags %>
|
7
7
|
<%= csp_meta_tag %>
|
8
|
-
|
9
|
-
|
8
|
+
|
9
|
+
<%= javascript_tag nonce: true do %>
|
10
10
|
window.locale = <%= h content_locale.to_json.html_safe %>;
|
11
|
+
window.uiLocale = <%= h editor_ui_locale.to_json.html_safe %>;
|
11
12
|
window.baseUrl = <%= h site_base_editor_path.to_json.html_safe %>;
|
12
13
|
window.leaveUrl = <%= site_leave_editor_path.to_json.html_safe %>;
|
13
14
|
window.apiBaseUrl = <%= h api_base_path.to_json.html_safe %>;
|
@@ -18,8 +19,8 @@
|
|
18
19
|
window.primaryColor = <%= editor_primary_hex_color.to_json.html_safe %>;
|
19
20
|
window.sitePublishable = <%= editor_site_publishable.to_json %>;
|
20
21
|
window.customTranslations = <%= h editor_custom_translations.to_json.html_safe %>
|
21
|
-
|
22
|
-
|
22
|
+
<% end %>
|
23
|
+
|
23
24
|
<%= vite_client_tag %>
|
24
25
|
<%= vite_javascript_tag 'editor' %>
|
25
26
|
|
@@ -32,7 +33,7 @@
|
|
32
33
|
}
|
33
34
|
</style>
|
34
35
|
|
35
|
-
<%= render 'header' %>
|
36
|
+
<%= render 'header' %>
|
36
37
|
</head>
|
37
38
|
<body class="h-full overflow-y-hidden font-nunito">
|
38
39
|
<div id="maglev-app"></div>
|
@@ -1,7 +1,13 @@
|
|
1
1
|
en:
|
2
2
|
activerecord:
|
3
3
|
attributes:
|
4
|
-
'maglev/page':
|
4
|
+
'maglev/page':
|
5
5
|
cloned_title: "%{title} COPY"
|
6
6
|
'maglev/page/paths':
|
7
|
-
value: Path
|
7
|
+
value: Path
|
8
|
+
errors:
|
9
|
+
models:
|
10
|
+
maglev/page_path:
|
11
|
+
attributes:
|
12
|
+
value:
|
13
|
+
invalid_path: "is not a valid path"
|
@@ -4,7 +4,7 @@ fr:
|
|
4
4
|
'maglev/page': Page
|
5
5
|
|
6
6
|
attributes:
|
7
|
-
'maglev/page':
|
7
|
+
'maglev/page':
|
8
8
|
title: Titre
|
9
9
|
cloned_title: "%{title} COPIE"
|
10
10
|
seo_title: Titre SEO
|
@@ -23,4 +23,8 @@ fr:
|
|
23
23
|
blank: doît être rempli
|
24
24
|
path:
|
25
25
|
taken: est déjà utilisé par une autre page
|
26
|
-
exclusion: est déjà utilisé par une autre page
|
26
|
+
exclusion: est déjà utilisé par une autre page
|
27
|
+
maglev/page_path:
|
28
|
+
attributes:
|
29
|
+
value:
|
30
|
+
invalid_path: "n'est pas un chemin valide"
|
data/config/routes.rb
CHANGED
@@ -12,9 +12,7 @@ Maglev::Engine.routes.draw do
|
|
12
12
|
end
|
13
13
|
resources :assets
|
14
14
|
resource :publication, only: %i[show create]
|
15
|
-
|
16
|
-
get '/', to: 'collection_items#index', as: :collection_items
|
17
|
-
end
|
15
|
+
resources :collection_items, path: 'collections/:collection_id', only: %i[index show]
|
18
16
|
end
|
19
17
|
end
|
20
18
|
|
@@ -52,6 +50,7 @@ Maglev::Engine.routes.draw do
|
|
52
50
|
post 'preview/(*path)', to: 'page_preview#create', defaults: { path: 'index', rendering_mode: :editor }
|
53
51
|
|
54
52
|
# Public Assets
|
55
|
-
get 'assets/:id(/:filename)', to:
|
53
|
+
get 'assets/:id(/:filename)', to: "#{Maglev.uploader_proxy_controller_name}#show",
|
54
|
+
as: :public_asset
|
56
55
|
end
|
57
56
|
# rubocop:enable Metrics/BlockLength
|
@@ -1,11 +1,19 @@
|
|
1
1
|
class CreateMaglevSectionContent < ActiveRecord::Migration[6.0]
|
2
2
|
def change
|
3
3
|
change_table :maglev_sites do |t|
|
4
|
-
t.
|
4
|
+
if t.respond_to? :jsonb
|
5
|
+
t.jsonb :sections, default: []
|
6
|
+
else
|
7
|
+
t.json :sections, default: []
|
8
|
+
end
|
5
9
|
end
|
6
10
|
|
7
11
|
change_table :maglev_pages do |t|
|
8
|
-
t.
|
12
|
+
if t.respond_to? :jsonb
|
13
|
+
t.jsonb :sections, default: []
|
14
|
+
else
|
15
|
+
t.json :sections, default: []
|
16
|
+
end
|
9
17
|
end
|
10
18
|
end
|
11
19
|
end
|