maglevcms 1.8.0 → 2.0.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.
- 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 +14 -2
- 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/live-preview.js +11 -1
- 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 +20 -17
- data/app/frontend/live-preview-client/message.js +1 -0
- data/app/frontend/live-preview-client/rails.js +12 -2
- 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
@@ -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
|
@@ -1,15 +1,25 @@
|
|
1
1
|
class SwitchToLocalizedPageFields < ActiveRecord::Migration[6.1]
|
2
2
|
def up
|
3
3
|
remove_columns :maglev_pages, :title, :seo_title, :meta_description
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
|
5
|
+
change_table :maglev_pages do |t|
|
6
|
+
if t.respond_to? :jsonb
|
7
|
+
t.jsonb :title_translations, default: {}
|
8
|
+
t.jsonb :seo_title_translations, default: {}
|
9
|
+
t.jsonb :meta_description_translations, default: {}
|
10
|
+
else
|
11
|
+
t.json :title_translations, default: {}
|
12
|
+
t.json :seo_title_translations, default: {}
|
13
|
+
t.json :meta_description_translations, default: {}
|
14
|
+
end
|
15
|
+
end
|
7
16
|
end
|
8
17
|
|
9
18
|
def down
|
10
19
|
add_column :maglev_pages, :title, :string
|
11
20
|
add_column :maglev_pages, :seo_title, :string
|
12
21
|
add_column :maglev_pages, :meta_description, :string
|
22
|
+
|
13
23
|
remove_column :maglev_pages, :title_translations
|
14
24
|
remove_column :maglev_pages, :seo_title_translations
|
15
25
|
remove_column :maglev_pages, :meta_description_translations
|
@@ -1,5 +1,11 @@
|
|
1
1
|
class AddLocalesToSites < ActiveRecord::Migration[6.0]
|
2
2
|
def change
|
3
|
-
|
3
|
+
change_table :maglev_sites do |t|
|
4
|
+
if t.respond_to? :jsonb
|
5
|
+
t.jsonb :locales, default: []
|
6
|
+
else
|
7
|
+
t.json :locales, default: []
|
8
|
+
end
|
9
|
+
end
|
4
10
|
end
|
5
11
|
end
|
@@ -1,8 +1,22 @@
|
|
1
1
|
class TranslateSectionContent < ActiveRecord::Migration[6.0]
|
2
2
|
def change
|
3
3
|
remove_column :maglev_sites, :sections, :jsonb, default: []
|
4
|
-
add_column :maglev_sites, :sections_translations, :jsonb, default: {}
|
5
4
|
remove_column :maglev_pages, :sections, :jsonb, default: []
|
6
|
-
|
5
|
+
|
6
|
+
change_table :maglev_sites do |t|
|
7
|
+
if t.respond_to? :jsonb
|
8
|
+
t.jsonb :sections_translations, default: {}
|
9
|
+
else
|
10
|
+
t.json :sections_translations, default: {}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
change_table :maglev_pages do |t|
|
15
|
+
if t.respond_to? :jsonb
|
16
|
+
t.jsonb :sections_translations, default: {}
|
17
|
+
else
|
18
|
+
t.json :sections_translations, default: {}
|
19
|
+
end
|
20
|
+
end
|
7
21
|
end
|
8
22
|
end
|
@@ -1,9 +1,15 @@
|
|
1
1
|
class AddOpenGraphTagsToPages < ActiveRecord::Migration[6.0]
|
2
2
|
def change
|
3
3
|
change_table :maglev_pages do |t|
|
4
|
-
t.
|
5
|
-
|
6
|
-
|
4
|
+
if t.respond_to? :jsonb
|
5
|
+
t.jsonb :og_title_translations, default: {}
|
6
|
+
t.jsonb :og_description_translations, default: {}
|
7
|
+
t.jsonb :og_image_url_translations, default: {}
|
8
|
+
else
|
9
|
+
t.json :og_title_translations, default: {}
|
10
|
+
t.json :og_description_translations, default: {}
|
11
|
+
t.json :og_image_url_translations, default: {}
|
12
|
+
end
|
7
13
|
end
|
8
14
|
end
|
9
15
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails'
|
4
|
+
|
5
|
+
module Maglev
|
6
|
+
class ChangeSiteLocalesCommand < Rails::Command::Base
|
7
|
+
desc 'change_site_locales [LOCALES]', 'Change site locales (format: label:prefix)'
|
8
|
+
|
9
|
+
def self.banner
|
10
|
+
'bin/rails maglev:change_site_locales [label:prefix label2:prefix2 ...]'
|
11
|
+
end
|
12
|
+
|
13
|
+
def perform(*locale_args)
|
14
|
+
require File.expand_path('config/environment', Rails.root)
|
15
|
+
|
16
|
+
site = fetch_site
|
17
|
+
return if site.blank?
|
18
|
+
|
19
|
+
locales = build_locales(locale_args)
|
20
|
+
return if locales.empty?
|
21
|
+
|
22
|
+
update_site_locales(site, locales)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def fetch_site
|
28
|
+
Maglev::Site.first.tap do |site|
|
29
|
+
say("[Error] You don't seem to have an existing site. 🤔", :red) unless site
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def build_locales(locale_args)
|
34
|
+
build_custom_locales(locale_args).tap do |locales|
|
35
|
+
validate_locales(locales)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def build_custom_locales(locale_args)
|
40
|
+
(locale_args || []).map do |arg|
|
41
|
+
label, prefix = arg.split(':')
|
42
|
+
Maglev::Site::Locale.new(label: label, prefix: prefix)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def validate_locales(locales)
|
47
|
+
return true if !locales.empty? && locales.all?(&:valid?)
|
48
|
+
|
49
|
+
say("[Error] make sure your locales follow the 'label:prefix' pattern. 🤓", :red)
|
50
|
+
false
|
51
|
+
end
|
52
|
+
|
53
|
+
def update_site_locales(site, locales)
|
54
|
+
Maglev::ChangeSiteLocales.call(
|
55
|
+
site: site,
|
56
|
+
locales: locales
|
57
|
+
)
|
58
|
+
say('Success! 🎉🎉🎉', :green)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails'
|
4
|
+
|
5
|
+
module Maglev
|
6
|
+
class CreateSiteCommand < Rails::Command::Base
|
7
|
+
desc 'create_site', 'Create your site'
|
8
|
+
|
9
|
+
def self.banner
|
10
|
+
'bin/rails maglev:create_site'
|
11
|
+
end
|
12
|
+
|
13
|
+
def perform
|
14
|
+
require File.expand_path('config/environment')
|
15
|
+
|
16
|
+
if Maglev::Site.exists?
|
17
|
+
say '🤔 You already have a site. 🤔', :yellow
|
18
|
+
return
|
19
|
+
end
|
20
|
+
|
21
|
+
Maglev::GenerateSite.call(
|
22
|
+
theme: Maglev.local_themes.first
|
23
|
+
)
|
24
|
+
|
25
|
+
say '🎉 Your site has been created with success!'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails'
|
4
|
+
|
5
|
+
module Maglev
|
6
|
+
module Sections
|
7
|
+
class RemoveCommand < Rails::Command::Base
|
8
|
+
desc 'remove TYPE', 'Remove a section type across the site and its pages'
|
9
|
+
|
10
|
+
def self.banner
|
11
|
+
'bin/rails maglev:sections:remove TYPE'
|
12
|
+
end
|
13
|
+
|
14
|
+
def perform(type)
|
15
|
+
require File.expand_path('config/environment', Rails.root)
|
16
|
+
|
17
|
+
site = fetch_site
|
18
|
+
|
19
|
+
return if site.blank?
|
20
|
+
|
21
|
+
removed_count = Maglev::RemoveSectionType.call(
|
22
|
+
site: site,
|
23
|
+
type: type
|
24
|
+
)
|
25
|
+
|
26
|
+
display_final_message(removed_count, type)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def fetch_site
|
32
|
+
Maglev::Site.first.tap do |site|
|
33
|
+
say("[Error] You don't seem to have an existing site. 🤔", :red) unless site
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def display_final_message(removed_count, type)
|
38
|
+
if removed_count.zero?
|
39
|
+
say "No section of type '#{type}' found 🤔", :yellow
|
40
|
+
return
|
41
|
+
end
|
42
|
+
|
43
|
+
say "Successfully removed #{removed_count} #{'section'.pluralize(removed_count)} of type '#{type}' 🎉",
|
44
|
+
:green
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Maglev
|
4
|
+
module Sections
|
5
|
+
class RenameCommand < Rails::Command::Base
|
6
|
+
desc 'rename OLD_TYPE NEW_TYPE', 'Rename a section type across the site and its pages'
|
7
|
+
|
8
|
+
def self.banner
|
9
|
+
'bin/rails maglev:sections:rename OLD_TYPE NEW_TYPE'
|
10
|
+
end
|
11
|
+
|
12
|
+
def perform(old_type, new_type)
|
13
|
+
require File.expand_path('config/environment', Rails.root)
|
14
|
+
|
15
|
+
site = fetch_site
|
16
|
+
theme = fetch_theme
|
17
|
+
|
18
|
+
return if site.blank? || theme.blank?
|
19
|
+
|
20
|
+
rename_sections(site, theme, old_type, new_type)
|
21
|
+
|
22
|
+
say "Successfully renamed all '#{old_type}' sections to '#{new_type}' 🎉", :green
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def fetch_site
|
28
|
+
Maglev::Site.first.tap do |site|
|
29
|
+
say("[Error] You don't seem to have an existing site. 🤔", :red) unless site
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def fetch_theme
|
34
|
+
Maglev.local_themes&.first.tap do |theme|
|
35
|
+
say('[Error] No theme found. 🤔', :red) unless theme
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def rename_sections(site, theme, old_type, new_type)
|
40
|
+
Maglev::RenameSectionType.call(
|
41
|
+
site: site,
|
42
|
+
theme: theme,
|
43
|
+
old_type: old_type,
|
44
|
+
new_type: new_type
|
45
|
+
)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
Maglev.configure do |config|
|
4
4
|
# Title of the Editor window
|
5
5
|
# config.title = 'Maglev - Editor'
|
6
|
+
# config.title = ->(site) { "#{site.name} 👋" }
|
6
7
|
|
7
8
|
# Logo of the Editor (top left corner).
|
8
9
|
# Put your custom logo in the app/assets/images folder of your Rails application.
|
@@ -50,7 +51,9 @@ Maglev.configure do |config|
|
|
50
51
|
config.admin_username = Rails.env.production? ? ENV.fetch('MAGLEV_ADMIN_USERNAME') : nil
|
51
52
|
config.admin_password = Rails.env.production? ? ENV.fetch('MAGLEV_ADMIN_PASSWORD') : nil
|
52
53
|
|
53
|
-
# Uploader engine (:active_storage is
|
54
|
+
# Uploader engine (:active_storage is the default one)
|
55
|
+
# Checkout https://github.com/MarsBased/maglevcms-shrine for an example of a custom uploader
|
56
|
+
# config.uploader = 'Maglev::Shrine::Uploader'
|
54
57
|
config.uploader = :active_storage
|
55
58
|
|
56
59
|
# Collections mapping (https://docs.maglev.dev/guides/setup-collections)
|
@@ -4,7 +4,7 @@
|
|
4
4
|
<title><%%= maglev_page.seo_title.presence || maglev_site.name %></title>
|
5
5
|
<meta content="width=device-width, initial-scale=1" name="viewport">
|
6
6
|
|
7
|
-
<meta name="description" content="<%%= maglev_page.meta_description %>" />
|
7
|
+
<meta name="description" content="<%%= maglev_page.meta_description %>" />
|
8
8
|
<meta property="og:title" content="<%%= maglev_page.og_title %>" />
|
9
9
|
<meta property="og:description" content="<%%= maglev_page.og_description %>" />
|
10
10
|
<meta property="og:image" content="<%%= maglev_page.og_image_url %>" />
|
@@ -13,7 +13,13 @@
|
|
13
13
|
|
14
14
|
<%%= maglev_live_preview_client_javascript_tag %>
|
15
15
|
|
16
|
-
|
16
|
+
<%%=
|
17
|
+
javascript_include_tag(
|
18
|
+
"https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio",
|
19
|
+
nonce: true,
|
20
|
+
id: "tailwind-cdn"
|
21
|
+
)
|
22
|
+
%>
|
17
23
|
</head>
|
18
24
|
<body class="bg-white">
|
19
25
|
<main data-maglev-dropzone>
|
data/lib/maglev/errors.rb
CHANGED
@@ -13,7 +13,7 @@ module Maglev
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def matches?(request)
|
16
|
-
(accepted_format?(request) || crawler?(request)) && match_host?(request)
|
16
|
+
!websocket?(request) && (accepted_format?(request) || crawler?(request)) && match_host?(request)
|
17
17
|
end
|
18
18
|
|
19
19
|
protected
|
@@ -32,6 +32,10 @@ module Maglev
|
|
32
32
|
request.format.symbol.nil? && CRAWLER_USER_AGENTS.match?(request.user_agent)
|
33
33
|
end
|
34
34
|
|
35
|
+
def websocket?(request)
|
36
|
+
request.headers['HTTP_UPGRADE'] == 'websocket'
|
37
|
+
end
|
38
|
+
|
35
39
|
def match_host?(request)
|
36
40
|
!preview_host || preview_host == request.host
|
37
41
|
end
|
@@ -11,6 +11,7 @@ module Maglev
|
|
11
11
|
def call(path)
|
12
12
|
theme = add(YAML.safe_load(File.read(path.join('theme.yml')), aliases: true))
|
13
13
|
sections = load_sections(theme, Pathname.new(path).join('sections/**/*.yml'))
|
14
|
+
detect_duplicate_sections(sections)
|
14
15
|
theme.sections = Maglev::Section::Store.new(sections)
|
15
16
|
theme
|
16
17
|
rescue Errno::ENOENT
|
@@ -52,6 +53,12 @@ module Maglev
|
|
52
53
|
File.exist?(path) ? File.mtime(path).to_i : nil
|
53
54
|
end
|
54
55
|
|
56
|
+
def detect_duplicate_sections(sections)
|
57
|
+
sections.group_by(&:id).each do |id, list|
|
58
|
+
raise Maglev::Errors::DuplicateSectionDefinition, "Duplicate section definition: #{id}" if list.size > 1
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
55
62
|
def log_missing_theme_file(path)
|
56
63
|
# don't log the error if the ruby code is not executed inside
|
57
64
|
# the Rails console or when the Rails server is running
|
data/lib/maglev/version.rb
CHANGED
data/lib/maglev.rb
CHANGED
@@ -26,7 +26,7 @@ module Maglev
|
|
26
26
|
c.favicon = nil
|
27
27
|
c.logo = nil
|
28
28
|
c.primary_color = '#040712'
|
29
|
-
c.uploader =
|
29
|
+
c.uploader = :active_storage
|
30
30
|
c.site_publishable = false
|
31
31
|
c.preview_host = nil
|
32
32
|
c.asset_host = Rails.application.config.action_controller.asset_host
|
@@ -47,12 +47,22 @@ module Maglev
|
|
47
47
|
config.tap do
|
48
48
|
yield(config)
|
49
49
|
config.reserved_paths = Maglev::ReservedPaths.new(config.reserved_paths)
|
50
|
+
require_relative 'maglev/active_storage' if config.uploader == :active_storage
|
50
51
|
end
|
51
52
|
end
|
52
53
|
|
53
54
|
def uploader
|
54
|
-
|
55
|
-
const_get("::Maglev::#{config.uploader.to_s.classify}")
|
55
|
+
case config.uploader
|
56
|
+
when Symbol then const_get("::Maglev::#{config.uploader.to_s.classify}")
|
57
|
+
when String then const_get(config.uploader)
|
58
|
+
when Class then config.uploader
|
59
|
+
else
|
60
|
+
raise "Invalid or not set uploader: #{config.uploader}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def uploader_proxy_controller_name
|
65
|
+
config.uploader == :active_storage ? 'assets/active_storage_proxy' : 'assets/proxy'
|
56
66
|
end
|
57
67
|
|
58
68
|
def services(overrides = {})
|