maglevcms 3.0.0.beta2 → 3.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/README.md +16 -53
- data/Rakefile +3 -1
- data/app/assets/builds/maglev/tailwind.css +681 -11670
- data/app/assets/config/maglev_manifest.js +3 -2
- data/app/assets/javascripts/maglev/client/dom-operations.js +5 -5
- data/app/assets/javascripts/maglev/client/iframe-decorator.js +24 -0
- data/app/assets/javascripts/maglev/client/incoming-messages.js +13 -3
- data/app/assets/javascripts/maglev/client/index.js +3 -2
- data/app/assets/javascripts/maglev/client/utils.js +22 -0
- data/app/assets/javascripts/maglev/editor/controllers/app/forms/section_form_controller.js +4 -3
- data/app/assets/javascripts/maglev/editor/controllers/app/forms/style_form_controller.js +2 -1
- data/app/assets/javascripts/maglev/editor/controllers/app/page_preview_controller.js +96 -5
- data/app/assets/javascripts/maglev/editor/controllers/app/preview_notification_center_controller.js +105 -23
- data/app/assets/javascripts/maglev/editor/controllers/app/setting_controller.js +3 -2
- data/app/assets/javascripts/maglev/editor/controllers/shared/copy_to_clipboard_controller.js +2 -1
- data/app/assets/javascripts/maglev/editor/controllers/shared/submit_button_controller.js +29 -5
- data/app/assets/javascripts/maglev/editor/controllers/utils.js +38 -0
- data/app/assets/javascripts/maglev/editor/index.js +5 -44
- data/app/assets/javascripts/maglev/editor/patches/page_renderer_patch.js +47 -0
- data/app/assets/javascripts/maglev/editor/patches/turbo_delayed_streams.js +35 -0
- data/app/assets/javascripts/maglev/editor/patches/turbo_stream_patch.js +50 -0
- data/app/assets/stylesheets/maglev/application.css +0 -2
- data/app/assets/stylesheets/maglev/tailwind.css.erb +11 -2
- data/app/components/maglev/content/link.rb +1 -1
- data/app/components/maglev/editor/settings/link/link_component.rb +7 -1
- data/app/components/maglev/section_component.rb +11 -1
- data/app/components/maglev/uikit/app_layout/sidebar/link_component.html.erb +1 -1
- data/app/components/maglev/uikit/app_layout/sidebar/link_component.rb +35 -5
- data/app/components/maglev/uikit/app_layout/sidebar_component.html.erb +3 -4
- data/app/components/maglev/uikit/app_layout/topbar/logo_component.html.erb +1 -1
- data/app/components/maglev/uikit/app_layout/topbar/page_info_component.html.erb +1 -1
- data/app/components/maglev/uikit/app_layout/topbar_component.html.erb +1 -1
- data/app/components/maglev/uikit/app_layout/topbar_component.rb +1 -1
- data/app/components/maglev/uikit/button_group_component/button_group_component.html.erb +5 -0
- data/app/components/maglev/uikit/button_group_component.rb +70 -0
- data/app/components/maglev/uikit/device_toggler_component.rb +10 -1
- data/app/components/maglev/uikit/dropdown_component/dropdown_component.html.erb +2 -2
- data/app/components/maglev/uikit/dropdown_component/dropdown_controller.js +6 -1
- data/app/components/maglev/uikit/dropdown_component.rb +6 -1
- data/app/components/maglev/uikit/form/color_field_component.html.erb +1 -1
- data/app/components/maglev/uikit/form/combobox_component.html.erb +1 -0
- data/app/components/maglev/uikit/form/link_component.rb +5 -1
- data/app/components/maglev/uikit/form/richtext_controller.js +5 -4
- data/app/components/maglev/uikit/form/search_form_component.html.erb +1 -0
- data/app/components/maglev/uikit/icon_component.rb +3 -0
- data/app/components/maglev/uikit/image_library/uploader_controller.js +3 -2
- data/app/components/maglev/uikit/list/list_item_component.html.erb +36 -19
- data/app/components/maglev/uikit/list/list_item_component.rb +19 -5
- data/app/components/maglev/uikit/locale_switcher_component/locale_switcher_component.html.erb +6 -10
- data/app/components/maglev/uikit/menu_dropdown_component/menu_dropdown_component.html.erb +6 -2
- data/app/components/maglev/uikit/menu_dropdown_component.rb +244 -7
- data/app/components/maglev/uikit/page_actions_dropdown_component/page_actions_dropdown_component.html.erb +39 -46
- data/app/components/maglev/uikit/pagination_component/pagination_component.html.erb +9 -12
- data/app/components/maglev/uikit/pagination_component.rb +6 -1
- data/app/components/maglev/uikit/section_toolbar/bottom_component.html.erb +1 -1
- data/app/components/maglev/uikit/tabs_component/tabs_component.html.erb +7 -4
- data/app/components/maglev/uikit/tabs_component.rb +23 -4
- data/app/components/maglev/uikit/well/simple_well_component.html.erb +15 -0
- data/app/components/maglev/uikit/well/simple_well_component.rb +13 -0
- data/app/controllers/concerns/maglev/editor/errors_concern.rb +9 -9
- data/app/controllers/concerns/maglev/editor/preview_urls_concern.rb +32 -0
- data/app/controllers/concerns/maglev/editor/turbo_concern.rb +29 -0
- data/app/controllers/concerns/maglev/errors_concern.rb +17 -0
- data/app/controllers/concerns/maglev/flash_i18n_concern.rb +1 -0
- data/app/controllers/maglev/application_controller.rb +2 -1
- data/app/controllers/maglev/assets/active_storage_proxy_controller.rb +2 -1
- data/app/controllers/maglev/editor/assets_controller.rb +1 -1
- data/app/controllers/maglev/editor/base_controller.rb +6 -32
- data/app/controllers/maglev/editor/pages/clone_controller.rb +22 -0
- data/app/controllers/maglev/editor/pages/discard_draft_controller.rb +17 -0
- data/app/controllers/maglev/editor/pages_controller.rb +26 -7
- data/app/controllers/maglev/editor/section_blocks_controller.rb +13 -9
- data/app/controllers/maglev/editor/sections_controller.rb +26 -7
- data/app/controllers/maglev/published_page_preview_controller.rb +4 -0
- data/app/controllers/maglev/site_controller.rb +15 -0
- data/app/helpers/maglev/application_helper.rb +26 -8
- data/app/helpers/maglev/editor/section_blocks_helper.rb +2 -2
- data/app/models/maglev/page/publishable_concern.rb +69 -0
- data/app/models/maglev/page.rb +3 -0
- data/app/models/maglev/section/block.rb +4 -0
- data/app/models/maglev/section/content_concern.rb +3 -1
- data/app/models/maglev/section.rb +21 -1
- data/app/models/maglev/sections_content_store.rb +1 -3
- data/app/models/maglev/site.rb +5 -0
- data/app/services/concerns/maglev/content/helpers_concern.rb +5 -8
- data/app/services/maglev/app_container.rb +4 -2
- data/app/services/maglev/discard_page_draft_service.rb +45 -0
- data/app/services/maglev/fetch_section_screenshot_url.rb +12 -1
- data/app/services/maglev/fetch_site.rb +3 -1
- data/app/services/maglev/get_published_page_sections_service.rb +1 -1
- data/app/services/maglev/has_unpublished_changes.rb +21 -0
- data/app/services/maglev/publish_service.rb +18 -2
- data/app/views/layouts/maglev/editor/_sidebar.html.erb +8 -2
- data/app/views/layouts/maglev/editor/_topbar.html.erb +6 -23
- data/app/views/layouts/maglev/editor/application.html.erb +6 -0
- data/app/views/layouts/maglev/editor/topbar/_page_info.html.erb +11 -0
- data/app/views/layouts/maglev/editor/topbar/_publish_button.html.erb +35 -0
- data/app/views/maglev/editor/assets/index.html.erb +1 -0
- data/app/views/maglev/editor/home/index.html.erb +1 -1
- data/app/views/maglev/editor/links/edit/_email.html.erb +1 -1
- data/app/views/maglev/editor/links/edit/_url.html.erb +1 -1
- data/app/views/maglev/editor/pages/_list.html.erb +25 -21
- data/app/views/maglev/editor/pages/_preview.html.erb +6 -6
- data/app/views/maglev/editor/pages/_preview_empty_message.html.erb +13 -10
- data/app/views/maglev/editor/pages/discard_draft/create.turbo_stream.erb +16 -0
- data/app/views/maglev/editor/pages/index.html.erb +8 -1
- data/app/views/maglev/editor/publication/create.turbo_stream.erb +3 -1
- data/app/views/maglev/editor/section_blocks/_form.html.erb +5 -13
- data/app/views/maglev/editor/section_blocks/_form_with_tabs.html.erb +15 -0
- data/app/views/maglev/editor/section_blocks/_new.html.erb +1 -1
- data/app/views/maglev/editor/section_blocks/edit.html.erb +2 -2
- data/app/views/maglev/editor/section_blocks/index/_list.html.erb +2 -2
- data/app/views/maglev/editor/section_blocks/index/_tree.html.erb +1 -1
- data/app/views/maglev/editor/section_blocks/update.turbo_stream.erb +9 -1
- data/app/views/maglev/editor/sections/_form.html.erb +6 -20
- data/app/views/maglev/editor/sections/_form_with_tabs.html.erb +21 -0
- data/app/views/maglev/editor/sections/_list.html.erb +1 -1
- data/app/views/maglev/editor/sections/edit.html.erb +3 -3
- data/app/views/maglev/editor/sections/index.html.erb +1 -1
- data/app/views/maglev/editor/sections/new.html.erb +18 -1
- data/app/views/maglev/editor/sections/theme/_empty_list.html.erb +3 -0
- data/app/views/maglev/editor/sections/theme/_list.html.erb +35 -0
- data/app/views/maglev/editor/sections/theme/_screenshot_placeholder.html.erb +6 -0
- data/app/views/maglev/editor/sections/theme/_search.html.erb +22 -0
- data/app/views/maglev/editor/sections/update.turbo_stream.erb +9 -1
- data/app/views/maglev/editor/shared/_button_label.html.erb +4 -4
- data/app/views/maglev/editor/style/edit.html.erb +1 -0
- data/app/views/maglev/errors/site_not_found.html.erb +33 -0
- data/config/editor_importmap.rb +16 -13
- data/config/locales/editor.ar.yml +12 -4
- data/config/locales/editor.en.yml +31 -23
- data/config/locales/editor.es.yml +12 -4
- data/config/locales/editor.fr.yml +12 -4
- data/config/locales/editor.pt-BR.yml +12 -4
- data/config/routes/maglev/assets.rb +4 -0
- data/config/routes/maglev/editor.rb +38 -0
- data/config/routes/maglev/preview.rb +8 -0
- data/config/routes/maglev/public_preview.rb +6 -0
- data/config/routes.rb +8 -44
- data/db/migrate/20211013210954_translate_section_content.rb +1 -0
- data/db/migrate/20251116171603_add_published_at_to_sites_and_pages.rb +6 -0
- data/db/migrate/20260114112058_add_published_payload_to_pages.rb +14 -0
- data/exe/tailwind-cli +1 -1
- data/lib/generators/maglev/install_generator.rb +9 -7
- data/lib/generators/maglev/templates/install/config/initializers/maglev.rb +10 -3
- data/lib/maglev/active_storage/serving_blob.rb +29 -0
- data/lib/maglev/active_storage.rb +2 -0
- data/lib/maglev/config.rb +22 -3
- data/lib/maglev/engine.rb +15 -10
- data/lib/maglev/errors.rb +1 -0
- data/lib/maglev/version.rb +1 -1
- data/lib/maglev.rb +18 -3
- data/lib/tasks/db_test_all.rake +290 -0
- data/lib/tasks/maglev/tailwindcss.rake +1 -0
- metadata +55 -19
- data/app/controllers/maglev/editor/page_clone_controller.rb +0 -20
- data/app/views/maglev/editor/sections/_theme_list.html.erb +0 -32
- /data/vendor/javascript/{@floating-ui--core.js → maglev/@floating-ui--core.js} +0 -0
- /data/vendor/javascript/{@floating-ui--dom.js → maglev/@floating-ui--dom.js} +0 -0
- /data/vendor/javascript/{@floating-ui--utils--dom.js → maglev/@floating-ui--utils--dom.js} +0 -0
- /data/vendor/javascript/{@floating-ui--utils.js → maglev/@floating-ui--utils.js} +0 -0
- /data/vendor/javascript/{@hotwired--stimulus.js → maglev/@hotwired--stimulus.js} +0 -0
- /data/vendor/javascript/{@hotwired--turbo-rails.js → maglev/@hotwired--turbo-rails.js} +0 -0
- /data/vendor/javascript/{@hotwired--turbo.js → maglev/@hotwired--turbo.js} +0 -0
- /data/vendor/javascript/{@rails--actioncable--src.js → maglev/@rails--actioncable--src.js} +0 -0
- /data/vendor/javascript/{@rails--request.js.js → maglev/@rails--request.js.js} +0 -0
- /data/vendor/javascript/{@shopify--draggable.js → maglev/@shopify--draggable.js} +0 -0
- /data/vendor/javascript/{el-transition.js → maglev/el-transition.js} +0 -0
- /data/vendor/javascript/{stimulus-use.js → maglev/stimulus-use.js} +0 -0
- /data/vendor/javascript/{tiptap.bundle.js → maglev/tiptap.bundle.js} +0 -0
|
@@ -1,56 +1,49 @@
|
|
|
1
|
-
<%= render Maglev::Uikit::MenuDropdownComponent.new(icon_name: icon_name) do |
|
|
2
|
-
<%
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
<span class="ml-2 whitespace-nowrap truncate overflow-hidden"><%= t('maglev.editor.pages.actions.edit') %></span>
|
|
6
|
-
<% end %>
|
|
1
|
+
<%= render Maglev::Uikit::MenuDropdownComponent.new(icon_name: icon_name) do |menu_dropdown| %>
|
|
2
|
+
<% menu_dropdown.with_item_link_to(paths[:edit], data: { turbo_frame: '_top' }) do |menu_item| %>
|
|
3
|
+
<% menu_item.with_icon_content('settings') %>
|
|
4
|
+
<% menu_item.with_label_content(t('maglev.editor.pages.actions.edit')) %>
|
|
7
5
|
<% end if allow?(:edit) %>
|
|
8
6
|
|
|
9
|
-
<%
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
<%
|
|
17
|
-
<% sub_menu.with_item do %>
|
|
18
|
-
<%= link_to t('maglev.editor.pages.actions.draft_preview'), paths[:preview], class: sub_menu.item_classes, target: '_blank' %>
|
|
19
|
-
<% end %>
|
|
20
|
-
<% sub_menu.with_item do %>
|
|
21
|
-
<%= link_to t('maglev.editor.pages.actions.live_preview'), live_url, class: sub_menu.item_classes, target: '_blank' %>
|
|
22
|
-
<% end %>
|
|
7
|
+
<% menu_dropdown.with_item_divider if allow?(:edit) %>
|
|
8
|
+
|
|
9
|
+
<% menu_dropdown.with_item_nested_menu(placement: 'right-start') do |menu_item| %>
|
|
10
|
+
<% menu_item.with_icon_content('preview') %>
|
|
11
|
+
<% menu_item.with_label_content(t('maglev.editor.pages.actions.preview')) %>
|
|
12
|
+
|
|
13
|
+
<% menu_item.with_item_link_to(paths[:preview], target: '_blank') do |sub_menu_item| %>
|
|
14
|
+
<% sub_menu_item.with_label_content(t('maglev.editor.pages.actions.draft_preview')) %>
|
|
23
15
|
<% end %>
|
|
24
|
-
<% end if allow?(:preview) %>
|
|
25
16
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
17
|
+
<% menu_item.with_item_link_to(live_url, target: '_blank') do |sub_menu_item| %>
|
|
18
|
+
<% sub_menu_item.with_label_content(t('maglev.editor.pages.actions.live_preview')) %>
|
|
19
|
+
<% end if live_url.present? %>
|
|
20
|
+
|
|
21
|
+
<% menu_item.with_item_text(variant: 'subdued') do |text_item| %>
|
|
22
|
+
<% text_item.with_label_content(t('maglev.editor.pages.actions.no_live_preview')) %>
|
|
23
|
+
<% end if live_url.blank? %>
|
|
24
|
+
<% end %>
|
|
25
|
+
|
|
26
|
+
<% menu_dropdown.with_item_wrapper(data: { controller: 'copy-to-clipboard', copy_to_clipboard_source_value: live_url }) do |wrapper_item| %>
|
|
27
|
+
<% wrapper_item.with_item_button(data: { copy_to_clipboard_target: 'text', action: 'click->copy-to-clipboard#copy:prevent' }) do |menu_item| %>
|
|
28
|
+
<% menu_item.with_icon_content('clipboard') %>
|
|
29
|
+
<% menu_item.with_label_content(t('maglev.editor.pages.actions.copy_url_to_clipboard')) %>
|
|
30
30
|
<% end %>
|
|
31
|
-
<% end if allow?(:clone) %>
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
<span class="ml-2 whitespace-nowrap truncate overflow-hidden">
|
|
38
|
-
<%= t('maglev.editor.pages.actions.copy_url_to_clipboard') %>
|
|
39
|
-
</span>
|
|
40
|
-
<% end %>
|
|
41
|
-
<div class="<%= dropdown.item_classes %> hidden" data-copy-to-clipboard-target="success">
|
|
42
|
-
<%= render Maglev::Uikit::IconComponent.new(name: 'checkbox_circle', class_names: 'text-green-500 shrink-0') %>
|
|
43
|
-
<span class="ml-2 whitespace-nowrap truncate overflow-hidden text-green-500">
|
|
44
|
-
<%= t('maglev.editor.pages.actions.copy_url_to_clipboard_success') %>
|
|
45
|
-
</span>
|
|
46
|
-
</div>
|
|
47
|
-
</div>
|
|
32
|
+
<% wrapper_item.with_item_button(class: 'hidden text-green-500', data: { copy_to_clipboard_target: 'success' }) do |menu_item| %>
|
|
33
|
+
<% menu_item.with_icon_content('checkbox_circle') %>
|
|
34
|
+
<% menu_item.with_label_content(t('maglev.editor.pages.actions.copy_url_to_clipboard_success')) %>
|
|
35
|
+
<% end %>
|
|
48
36
|
<% end if allow?(:copy_url_to_clipboard) %>
|
|
49
37
|
|
|
50
|
-
<%
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
<%
|
|
38
|
+
<% menu_dropdown.with_item_divider if allow?(:clone) || allow?(:delete) %>
|
|
39
|
+
|
|
40
|
+
<% menu_dropdown.with_item_button_to(paths[:clone], data: { turbo_frame: '_top' }) do |menu_item| %>
|
|
41
|
+
<% menu_item.with_icon_content('clone') %>
|
|
42
|
+
<% menu_item.with_label_content(t('maglev.editor.pages.actions.clone')) %>
|
|
43
|
+
<% end if allow?(:clone) %>
|
|
44
|
+
|
|
45
|
+
<% menu_dropdown.with_item_button_to(paths[:delete], method: :delete, variant: 'danger', data: { turbo_confirm: t('maglev.editor.pages.actions.confirm_delete'), turbo_frame: '_top' }) do |menu_item| %>
|
|
46
|
+
<% menu_item.with_icon_content('delete_bin') %>
|
|
47
|
+
<% menu_item.with_label_content(t('maglev.editor.pages.actions.delete')) %>
|
|
55
48
|
<% end if allow?(:delete) %>
|
|
56
49
|
<% end %>
|
|
@@ -27,20 +27,17 @@
|
|
|
27
27
|
<% end %>
|
|
28
28
|
</div>
|
|
29
29
|
|
|
30
|
-
<div class="hidden sm:flex sm:flex-1 sm:items-center sm:justify-between">
|
|
31
|
-
|
|
32
|
-
<p class="text-sm">
|
|
30
|
+
<div class="hidden sm:flex sm:flex-1 sm:items-center <%= show_info? ? 'sm:justify-between' : 'sm:justify-center' %>">
|
|
31
|
+
<p class="text-sm <%= 'hidden' unless show_info? %>">
|
|
33
32
|
<%== pagy_info(pagy, item_name: item_name) %>
|
|
34
|
-
</p>
|
|
35
|
-
</div>
|
|
33
|
+
</p>
|
|
36
34
|
|
|
37
|
-
<div class="<%= 'hidden' if pagy.series.size == 1 %>">
|
|
38
35
|
<nav class="isolate inline-flex gap-1" aria-label="Pages">
|
|
39
36
|
<%# Previous page link %>
|
|
40
37
|
<% if pagy.prev %>
|
|
41
|
-
<%== a.(pagy.prev, left_arrow, aria_label: 'Previous', classes: 'relative inline-flex items-center rounded-
|
|
38
|
+
<%== a.(pagy.prev, left_arrow, aria_label: 'Previous', classes: 'relative inline-flex items-center rounded-xs px-1 py-1 text-gray-400 hover:bg-gray-100 focus:z-20 focus:outline-offset-0') %>
|
|
42
39
|
<% else %>
|
|
43
|
-
<a role="link" aria-disabled="true" aria-label="Previous" class="relative inline-flex items-center rounded-
|
|
40
|
+
<a role="link" aria-disabled="true" aria-label="Previous" class="relative inline-flex items-center rounded-xs px-1 py-1 text-gray-400 hover:bg-gray-100 focus:z-20 focus:outline-offset-0">
|
|
44
41
|
<%= left_arrow %>
|
|
45
42
|
</a>
|
|
46
43
|
<% end %>
|
|
@@ -48,9 +45,9 @@
|
|
|
48
45
|
<%# Page links (series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]) %>
|
|
49
46
|
<% pagy.series.each do |item| %>
|
|
50
47
|
<% if item.is_a?(Integer) %>
|
|
51
|
-
<%== a.(item, classes: 'relative inline-flex items-center px-2.5 py-1 text-sm font-semibold text-gray-900 hover:bg-gray-100 focus:z-20 focus:outline-offset-0') %>
|
|
48
|
+
<%== a.(item, classes: 'relative inline-flex items-center px-2.5 py-1 text-sm font-semibold text-gray-900 rounded-xs hover:bg-gray-100 focus:z-20 focus:outline-offset-0') %>
|
|
52
49
|
<% elsif item.is_a?(String) %>
|
|
53
|
-
<a role="link" aria-disabled="true" aria-current="page" class="relative z-10 inline-flex items-center bg-editor-primary px-2.5 py-1 text-sm font-semibold text-white focus:z-20"><%= item %></a>
|
|
50
|
+
<a role="link" aria-disabled="true" aria-current="page" class="relative z-10 inline-flex items-center rounded-xs bg-editor-primary px-2.5 py-1 text-sm font-semibold text-white focus:z-20"><%= item %></a>
|
|
54
51
|
<% elsif item == :gap %>
|
|
55
52
|
<a role="link" aria-disabled="true" class="relative inline-flex items-center px-2.5 py-1 text-sm font-semibold text-gray-700 focus:outline-offset-0">…</a>
|
|
56
53
|
<% end %>
|
|
@@ -58,9 +55,9 @@
|
|
|
58
55
|
|
|
59
56
|
<%# Next page link %>
|
|
60
57
|
<% if pagy.next %>
|
|
61
|
-
<%== a.(pagy.next, right_arrow, aria_label: 'Next', classes: 'relative inline-flex items-center rounded-
|
|
58
|
+
<%== a.(pagy.next, right_arrow, aria_label: 'Next', classes: 'relative inline-flex items-center rounded-xs px-1 py-1 text-gray-400 hover:bg-gray-100 focus:z-20 focus:outline-offset-0') %>
|
|
62
59
|
<% else %>
|
|
63
|
-
<a role="link" aria-disabled="true" aria-label="Next" class="relative inline-flex items-center rounded-
|
|
60
|
+
<a role="link" aria-disabled="true" aria-label="Next" class="relative inline-flex items-center rounded-xs px-1 py-1 text-gray-400 hover:bg-gray-100 focus:z-20 focus:outline-offset-0">
|
|
64
61
|
<%= right_arrow %>
|
|
65
62
|
</a>
|
|
66
63
|
<% end %>
|
|
@@ -7,10 +7,11 @@ module Maglev
|
|
|
7
7
|
|
|
8
8
|
attr_reader :pagy, :hidden_if_single_page
|
|
9
9
|
|
|
10
|
-
def initialize(pagy:, item_name: 'item', hidden_if_single_page: true)
|
|
10
|
+
def initialize(pagy:, item_name: 'item', hidden_if_single_page: true, show_info: true)
|
|
11
11
|
@pagy = pagy
|
|
12
12
|
@hidden_if_single_page = hidden_if_single_page
|
|
13
13
|
@item_name = item_name
|
|
14
|
+
@show_info = show_info
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
def item_name
|
|
@@ -20,6 +21,10 @@ module Maglev
|
|
|
20
21
|
def render?
|
|
21
22
|
!(hidden_if_single_page && pagy.pages < 2)
|
|
22
23
|
end
|
|
24
|
+
|
|
25
|
+
def show_info?
|
|
26
|
+
@show_info
|
|
27
|
+
end
|
|
23
28
|
end
|
|
24
29
|
end
|
|
25
30
|
end
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
data-transition-leave-start="translate-y-0 opacity-100"
|
|
8
8
|
data-transition-leave-end="translate-y-[50%] opacity-0"
|
|
9
9
|
>
|
|
10
|
-
<%= link_to paths[:add], class: button_classes, data: { turbo_frame: '
|
|
10
|
+
<%= link_to paths[:add], class: button_classes, data: { turbo_frame: 'modal' } do %>
|
|
11
11
|
<%= render Maglev::Uikit::IconComponent.new(name: 'add') %>
|
|
12
12
|
<% end if insert_button? %>
|
|
13
13
|
</div>
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
<input type="hidden" name="active_tab" value="<%= active_tab_index %>" data-uikit-tabs-target="hiddenInput" />
|
|
9
9
|
|
|
10
10
|
<nav>
|
|
11
|
-
<ul class="flex flex-
|
|
11
|
+
<ul class="flex flex-row">
|
|
12
12
|
<% tabs.each_with_index do |tab, index| %>
|
|
13
|
-
<li>
|
|
13
|
+
<li class="shrink-0">
|
|
14
14
|
<% if tab.link? %>
|
|
15
15
|
<%= link_to tab.label, tab.link[:url], class: label_classes(active: tab.active?), **tab.link_html_options %>
|
|
16
16
|
<% else %>
|
|
@@ -25,11 +25,14 @@
|
|
|
25
25
|
</ul>
|
|
26
26
|
</nav>
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
<% if variant == :default %>
|
|
29
|
+
<div class="relative -mt-0.5"><div class="w-full border-gray-200 border-t-2 h-0"></div></div>
|
|
30
|
+
<% end %>
|
|
29
31
|
|
|
30
32
|
<% tabs.each_with_index do |tab, index| %>
|
|
33
|
+
<% next unless tab.block? %>
|
|
31
34
|
<div data-uikit-tabs-target="tabContent" class="flex-1 mt-4 pt-2 pb-4 overflow-y-auto overflow-x-visible <%= 'hidden' unless tab.active? %>">
|
|
32
|
-
<%= capture(&tab.block)
|
|
35
|
+
<%= capture(&tab.block) %>
|
|
33
36
|
</div>
|
|
34
37
|
<% end %>
|
|
35
38
|
</div>
|
|
@@ -7,16 +7,21 @@ module Maglev
|
|
|
7
7
|
Tab.new(self, label: label, active: active, link: link, block: block)
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
attr_reader :container_classes, :active_tab, :active_tab_index, :disable_inputs
|
|
10
|
+
attr_reader :container_classes, :active_tab, :active_tab_index, :disable_inputs, :variant
|
|
11
11
|
|
|
12
12
|
# disable_inputs: true | false (default: false) if true, the inputs of hidden tabs will not be submitted
|
|
13
|
-
def initialize(container_classes: nil, active_tab_index: nil, disable_inputs: false)
|
|
13
|
+
def initialize(container_classes: nil, active_tab_index: nil, disable_inputs: false, variant: :default)
|
|
14
14
|
@container_classes = container_classes
|
|
15
15
|
@active_tab_index = active_tab_index
|
|
16
16
|
@disable_inputs = disable_inputs
|
|
17
|
+
@variant = variant
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
def label_classes(...)
|
|
21
|
+
variant == :pills ? pills_label_classes(...) : default_label_classes(...)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def default_label_classes(...)
|
|
20
25
|
class_variants(
|
|
21
26
|
base: %(
|
|
22
27
|
relative py-1 pb-0 px-4 block focus:outline-none border-b-2
|
|
@@ -29,9 +34,23 @@ module Maglev
|
|
|
29
34
|
).render(...)
|
|
30
35
|
end
|
|
31
36
|
|
|
37
|
+
def pills_label_classes(...)
|
|
38
|
+
class_variants(
|
|
39
|
+
base: %(rounded-md px-3 py-2 text-sm),
|
|
40
|
+
variants: {
|
|
41
|
+
active: 'rounded-md bg-editor-primary/10 font-semibold text-editor-primary',
|
|
42
|
+
'!active': 'text-gray-500 hover:text-gray-700 font-medium'
|
|
43
|
+
}
|
|
44
|
+
).render(...)
|
|
45
|
+
end
|
|
46
|
+
|
|
32
47
|
def before_render
|
|
33
|
-
@active_tab = tabs.find(&:active?)
|
|
34
|
-
|
|
48
|
+
@active_tab = tabs.find(&:active?)
|
|
49
|
+
|
|
50
|
+
return unless !@active_tab && active_tab_index != -1
|
|
51
|
+
|
|
52
|
+
@active_tab = tabs[active_tab_index.to_i]
|
|
53
|
+
@active_tab&.active = true
|
|
35
54
|
end
|
|
36
55
|
|
|
37
56
|
def disable_inputs?
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<div class="bg-gray-50 sm:rounded-lg">
|
|
2
|
+
<div class="px-4 py-5 sm:p-6">
|
|
3
|
+
<h3 class="text-base font-semibold text-gray-900">
|
|
4
|
+
<%= title %>
|
|
5
|
+
</h3>
|
|
6
|
+
<div class="mt-2 max-w-xl text-sm text-gray-500 space-y-2">
|
|
7
|
+
<%= description %>
|
|
8
|
+
</div>
|
|
9
|
+
<% if action? %>
|
|
10
|
+
<div class="mt-5">
|
|
11
|
+
<%= action %>
|
|
12
|
+
</div>
|
|
13
|
+
<% end %>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
@@ -7,23 +7,16 @@ module Maglev
|
|
|
7
7
|
|
|
8
8
|
included do
|
|
9
9
|
around_action :handle_editor_errors
|
|
10
|
-
|
|
11
|
-
rescue_from ActiveRecord::StaleObjectError, with: :handle_stale_object
|
|
12
10
|
end
|
|
13
11
|
|
|
14
12
|
private
|
|
15
13
|
|
|
16
|
-
def handle_stale_object
|
|
17
|
-
respond_to do |format|
|
|
18
|
-
format.turbo_stream { render 'maglev/editor/shared/errors/stale_object_error' }
|
|
19
|
-
format.html { redirect_to editor_root_path }
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
23
14
|
def handle_editor_errors
|
|
24
15
|
yield
|
|
25
16
|
rescue Maglev::Errors::NotAuthorized
|
|
26
17
|
raise # Let the main app handle this one
|
|
18
|
+
rescue ActiveRecord::StaleObjectError
|
|
19
|
+
handle_stale_object
|
|
27
20
|
rescue StandardError => e
|
|
28
21
|
respond_to do |format|
|
|
29
22
|
format.turbo_stream { render_turbo_stream_standard_error(e) }
|
|
@@ -31,6 +24,13 @@ module Maglev
|
|
|
31
24
|
end
|
|
32
25
|
end
|
|
33
26
|
|
|
27
|
+
def handle_stale_object
|
|
28
|
+
respond_to do |format|
|
|
29
|
+
format.turbo_stream { render 'maglev/editor/shared/errors/stale_object_error' }
|
|
30
|
+
format.html { redirect_to editor_root_path }
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
34
|
def render_turbo_stream_standard_error(error)
|
|
35
35
|
track_maglev_error(error)
|
|
36
36
|
render 'maglev/editor/shared/errors/standard_error', status: :internal_server_error
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Maglev
|
|
4
|
+
module Editor
|
|
5
|
+
module PreviewUrlsConcern
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
included do
|
|
9
|
+
helper_method :current_maglev_page_urls, :maglev_page_live_url, :maglev_page_preview_url
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def current_maglev_page_urls
|
|
15
|
+
{
|
|
16
|
+
path: maglev_services.get_page_fullpath.call(page: current_maglev_page, preview_mode: false,
|
|
17
|
+
locale: content_locale),
|
|
18
|
+
preview: maglev_page_preview_url(current_maglev_page),
|
|
19
|
+
live: maglev_page_live_url(current_maglev_page)
|
|
20
|
+
}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def maglev_page_live_url(page)
|
|
24
|
+
maglev_services.get_page_fullpath.call(page: page, preview_mode: false, locale: content_locale)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def maglev_page_preview_url(page)
|
|
28
|
+
maglev_services.get_page_fullpath.call(page: page, preview_mode: true, locale: content_locale)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Maglev
|
|
4
|
+
module Editor
|
|
5
|
+
module TurboConcern
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
included do
|
|
9
|
+
helper_method :maglev_disable_turbo_cache?
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def maglev_disable_turbo_cache
|
|
15
|
+
@maglev_disable_turbo_cache = true
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def maglev_disable_turbo_cache?
|
|
19
|
+
!!@maglev_disable_turbo_cache
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def ensure_turbo_frame_request
|
|
23
|
+
return if turbo_frame_request?
|
|
24
|
+
|
|
25
|
+
redirect_to editor_root_path
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Maglev
|
|
4
|
+
module ErrorsConcern
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
rescue_from ::Maglev::Errors::SiteNotFound, with: :handle_site_not_found if Rails.env.development?
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def handle_site_not_found
|
|
14
|
+
render 'maglev/errors/site_not_found', layout: nil, status: :not_found
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Maglev
|
|
4
|
-
class ApplicationController <
|
|
4
|
+
class ApplicationController < Maglev.parent_controller_class
|
|
5
5
|
include Maglev::ServicesConcern
|
|
6
6
|
include Maglev::ResourceIdConcern
|
|
7
|
+
include Maglev::ErrorsConcern
|
|
7
8
|
|
|
8
9
|
protect_from_forgery with: :exception
|
|
9
10
|
|
|
@@ -8,7 +8,8 @@ module Maglev
|
|
|
8
8
|
private
|
|
9
9
|
|
|
10
10
|
def set_blob
|
|
11
|
-
|
|
11
|
+
blob = Maglev::Asset.find(resource_id).file.blob
|
|
12
|
+
@blob = Maglev::ActiveStorage::ServingBlob.new(blob)
|
|
12
13
|
rescue ActiveRecord::RecordNotFound
|
|
13
14
|
head :not_found
|
|
14
15
|
end
|
|
@@ -13,6 +13,8 @@ module Maglev
|
|
|
13
13
|
include Maglev::ServicesConcern
|
|
14
14
|
include Maglev::FlashI18nConcern
|
|
15
15
|
include Maglev::Editor::ErrorsConcern
|
|
16
|
+
include Maglev::Editor::TurboConcern
|
|
17
|
+
include Maglev::Editor::PreviewUrlsConcern
|
|
16
18
|
|
|
17
19
|
before_action :fetch_maglev_site
|
|
18
20
|
before_action :fetch_maglev_page
|
|
@@ -20,9 +22,8 @@ module Maglev
|
|
|
20
22
|
|
|
21
23
|
helper Maglev::ApplicationHelper
|
|
22
24
|
helper_method :maglev_site, :maglev_theme,
|
|
23
|
-
:current_maglev_page, :current_maglev_sections,
|
|
24
|
-
:maglev_editing_route_context, :
|
|
25
|
-
:maglev_page_live_url, :maglev_page_preview_url
|
|
25
|
+
:current_maglev_page, :current_maglev_sections,
|
|
26
|
+
:maglev_editing_route_context, :unpublished_changes?
|
|
26
27
|
|
|
27
28
|
private
|
|
28
29
|
|
|
@@ -61,21 +62,8 @@ module Maglev
|
|
|
61
62
|
)
|
|
62
63
|
end
|
|
63
64
|
|
|
64
|
-
def
|
|
65
|
-
|
|
66
|
-
path: maglev_services.get_page_fullpath.call(page: current_maglev_page, preview_mode: false,
|
|
67
|
-
locale: content_locale),
|
|
68
|
-
preview: maglev_page_preview_url(current_maglev_page),
|
|
69
|
-
live: maglev_page_live_url(current_maglev_page)
|
|
70
|
-
}
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def maglev_page_live_url(page)
|
|
74
|
-
maglev_services.get_page_fullpath.call(page: page, preview_mode: false, locale: content_locale)
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def maglev_page_preview_url(page)
|
|
78
|
-
maglev_services.get_page_fullpath.call(page: page, preview_mode: true, locale: content_locale)
|
|
65
|
+
def unpublished_changes?
|
|
66
|
+
maglev_services.has_unpublished_changes.call(site: maglev_site, page: current_maglev_page, theme: maglev_theme)
|
|
79
67
|
end
|
|
80
68
|
|
|
81
69
|
def maglev_theme
|
|
@@ -89,20 +77,6 @@ module Maglev
|
|
|
89
77
|
}.compact_blank
|
|
90
78
|
end
|
|
91
79
|
|
|
92
|
-
def maglev_disable_turbo_cache
|
|
93
|
-
@maglev_disable_turbo_cache = true
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def maglev_disable_turbo_cache?
|
|
97
|
-
!!@maglev_disable_turbo_cache
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
def ensure_turbo_frame_request
|
|
101
|
-
return if turbo_frame_request?
|
|
102
|
-
|
|
103
|
-
redirect_to editor_root_path
|
|
104
|
-
end
|
|
105
|
-
|
|
106
80
|
def redirect_to_real_root
|
|
107
81
|
redirect_to editor_real_root_path(maglev_editing_route_context)
|
|
108
82
|
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Maglev
|
|
4
|
+
module Editor
|
|
5
|
+
module Pages
|
|
6
|
+
class CloneController < Maglev::Editor::BaseController
|
|
7
|
+
def create
|
|
8
|
+
@source_page = maglev_page_resources.find(params[:id])
|
|
9
|
+
@page = clone_page(@source_page)
|
|
10
|
+
edit_cloned_page_path = edit_editor_page_path(@page, maglev_editing_route_context(page: @page))
|
|
11
|
+
redirect_to edit_cloned_page_path, notice: flash_t(:success), status: :see_other
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def clone_page(page)
|
|
17
|
+
services.clone_page.call(page: page)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Maglev
|
|
4
|
+
module Editor
|
|
5
|
+
module Pages
|
|
6
|
+
class DiscardDraftController < Maglev::Editor::BaseController
|
|
7
|
+
def create
|
|
8
|
+
page = maglev_page_resources.find(params[:id])
|
|
9
|
+
services.discard_page_draft.call(
|
|
10
|
+
site: maglev_site,
|
|
11
|
+
page: page
|
|
12
|
+
)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -3,16 +3,16 @@
|
|
|
3
3
|
module Maglev
|
|
4
4
|
module Editor
|
|
5
5
|
class PagesController < Maglev::Editor::BaseController
|
|
6
|
+
include ::Pagy::Backend
|
|
7
|
+
|
|
6
8
|
before_action :set_page, only: %i[edit update destroy]
|
|
7
9
|
before_action :maglev_disable_turbo_cache, only: %i[edit update new create]
|
|
8
10
|
|
|
9
11
|
helper_method :query_params
|
|
10
12
|
|
|
11
13
|
def index
|
|
12
|
-
@pages =
|
|
13
|
-
|
|
14
|
-
with_static_pages: false,
|
|
15
|
-
index_first: true)
|
|
14
|
+
@pages = fetch_pages
|
|
15
|
+
@pagy, @pages = pagy(@pages, limit: per_page, page_param: 'offset') if pagination_enabled?
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def new
|
|
@@ -58,6 +58,10 @@ module Maglev
|
|
|
58
58
|
@page = maglev_page_resources.find(params[:id])
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
+
def build_page_resource
|
|
62
|
+
maglev_page_resources.build(page_params)
|
|
63
|
+
end
|
|
64
|
+
|
|
61
65
|
def page_params
|
|
62
66
|
params.require(:page).permit(:title, :path,
|
|
63
67
|
:seo_title, :meta_description,
|
|
@@ -66,11 +70,26 @@ module Maglev
|
|
|
66
70
|
end
|
|
67
71
|
|
|
68
72
|
def query_params(from_list: false)
|
|
69
|
-
{ q: params[:q], from_list: params[:from_list] || from_list }
|
|
73
|
+
base = { q: params[:q], from_list: params[:from_list] || from_list }
|
|
74
|
+
(pagination_enabled? ? base.merge(offset: params[:offset]) : base).compact_blank
|
|
70
75
|
end
|
|
71
76
|
|
|
72
|
-
def
|
|
73
|
-
|
|
77
|
+
def fetch_pages
|
|
78
|
+
services.search_pages.call(
|
|
79
|
+
q: params[:q],
|
|
80
|
+
content_locale: content_locale,
|
|
81
|
+
default_locale: default_content_locale,
|
|
82
|
+
with_static_pages: false,
|
|
83
|
+
index_first: true
|
|
84
|
+
)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def pagination_enabled?
|
|
88
|
+
maglev_config.pagination?(:pages)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def per_page
|
|
92
|
+
maglev_config.per_page(:pages)
|
|
74
93
|
end
|
|
75
94
|
end
|
|
76
95
|
end
|