alchemy_cms 7.1.6 → 7.2.0.b
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/CHANGELOG.md +141 -0
- data/Gemfile +2 -2
- data/LICENSE +1 -1
- data/README.md +5 -6
- data/SECURITY.md +1 -1
- data/alchemy_cms.gemspec +3 -4
- data/app/assets/javascripts/alchemy/admin.js +0 -9
- data/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee +5 -15
- data/app/assets/javascripts/alchemy/alchemy.image_overlay.coffee +5 -4
- data/app/assets/javascripts/alchemy/templates/index.js +0 -1
- data/app/assets/javascripts/alchemy/templates/node_folder.hbs +1 -1
- data/app/assets/javascripts/alchemy/templates/page_folder.hbs +1 -1
- data/app/assets/javascripts/tinymce/plugins/alchemy_link/plugin.min.js +20 -7
- data/app/assets/stylesheets/alchemy/_custom-properties.scss +12 -0
- data/app/assets/stylesheets/alchemy/_mixins.scss +10 -6
- data/app/assets/stylesheets/alchemy/_variables.scss +3 -0
- data/app/assets/stylesheets/alchemy/admin.scss +2 -2
- data/app/assets/stylesheets/alchemy/archive.scss +4 -3
- data/app/assets/stylesheets/alchemy/attachment-select.scss +19 -0
- data/app/assets/stylesheets/alchemy/base.scss +31 -18
- data/app/assets/stylesheets/alchemy/buttons.scss +3 -4
- data/app/assets/stylesheets/alchemy/dashboard.scss +1 -1
- data/app/assets/stylesheets/alchemy/dialogs.scss +2 -5
- data/app/assets/stylesheets/alchemy/elements.scss +76 -46
- data/app/assets/stylesheets/alchemy/flash.scss +20 -70
- data/app/assets/stylesheets/alchemy/forms.scss +41 -36
- data/app/assets/stylesheets/alchemy/frame.scss +12 -3
- data/app/assets/stylesheets/alchemy/icons.scss +34 -2
- data/app/assets/stylesheets/alchemy/image_library.scss +18 -9
- data/app/assets/stylesheets/alchemy/{filter_field.scss → list_filter.scss} +8 -7
- data/app/assets/stylesheets/alchemy/lists.scss +1 -1
- data/app/assets/stylesheets/alchemy/navigation.scss +9 -12
- data/app/assets/stylesheets/alchemy/node-select.scss +1 -1
- data/app/assets/stylesheets/alchemy/nodes.scss +15 -13
- data/app/assets/stylesheets/alchemy/notices.scss +56 -39
- data/app/assets/stylesheets/alchemy/page-select.scss +1 -4
- data/app/assets/stylesheets/alchemy/pagination.scss +11 -1
- data/app/assets/stylesheets/alchemy/preview_window.scss +7 -3
- data/app/assets/stylesheets/alchemy/search.scss +4 -4
- data/app/assets/stylesheets/alchemy/selects.scss +13 -7
- data/app/assets/stylesheets/alchemy/shoelace.scss +33 -2
- data/app/assets/stylesheets/alchemy/sitemap.scss +155 -159
- data/app/assets/stylesheets/alchemy/tables.scss +49 -12
- data/app/assets/stylesheets/alchemy/tags.scss +17 -11
- data/app/assets/stylesheets/alchemy/toolbar.scss +2 -2
- data/app/assets/stylesheets/alchemy/typography.scss +41 -22
- data/app/assets/stylesheets/alchemy/upload.scss +5 -4
- data/app/components/alchemy/admin/attachment_select.rb +39 -0
- data/app/components/alchemy/admin/icon.rb +72 -0
- data/app/components/alchemy/admin/link_dialog/anchor_tab.rb +41 -0
- data/app/components/alchemy/admin/link_dialog/base_tab.rb +75 -0
- data/app/components/alchemy/admin/link_dialog/external_tab.rb +42 -0
- data/app/components/alchemy/admin/link_dialog/file_tab.rb +45 -0
- data/app/components/alchemy/admin/link_dialog/internal_tab.rb +66 -0
- data/app/components/alchemy/admin/link_dialog/tabs.rb +33 -0
- data/app/components/alchemy/admin/list_filter.rb +42 -0
- data/app/components/alchemy/admin/message.rb +19 -0
- data/app/components/alchemy/admin/tags_autocomplete.rb +25 -0
- data/app/components/alchemy/admin/toolbar_button.rb +111 -0
- data/app/components/alchemy/ingredients/audio_view.rb +1 -1
- data/app/components/alchemy/ingredients/base_view.rb +1 -1
- data/app/components/alchemy/ingredients/boolean_view.rb +1 -1
- data/app/components/alchemy/ingredients/datetime_view.rb +1 -1
- data/app/components/alchemy/ingredients/file_view.rb +1 -1
- data/app/components/alchemy/ingredients/headline_view.rb +16 -7
- data/app/components/alchemy/ingredients/link_view.rb +1 -7
- data/app/components/alchemy/ingredients/page_view.rb +1 -1
- data/app/components/alchemy/ingredients/picture_view.rb +3 -3
- data/app/components/alchemy/ingredients/richtext_view.rb +1 -1
- data/app/components/alchemy/ingredients/text_view.rb +2 -3
- data/app/components/alchemy/ingredients/video_view.rb +1 -1
- data/app/controllers/alchemy/admin/base_controller.rb +1 -1
- data/app/controllers/alchemy/admin/elements_controller.rb +4 -2
- data/app/controllers/alchemy/admin/ingredients_controller.rb +2 -0
- data/app/controllers/alchemy/admin/languages_controller.rb +1 -1
- data/app/controllers/alchemy/admin/legacy_page_urls_controller.rb +12 -4
- data/app/controllers/alchemy/admin/nodes_controller.rb +26 -0
- data/app/controllers/alchemy/admin/pages_controller.rb +11 -78
- data/app/controllers/alchemy/admin/picture_descriptions_controller.rb +15 -0
- data/app/controllers/alchemy/admin/pictures_controller.rb +18 -1
- data/app/controllers/alchemy/admin/resources_controller.rb +15 -10
- data/app/controllers/alchemy/api/attachments_controller.rb +44 -0
- data/app/controllers/alchemy/api/pages_controller.rb +10 -6
- data/app/controllers/alchemy/base_controller.rb +2 -2
- data/app/controllers/alchemy/messages_controller.rb +2 -2
- data/app/controllers/alchemy/pages_controller.rb +8 -6
- data/app/controllers/concerns/alchemy/admin/current_language.rb +1 -1
- data/app/controllers/concerns/alchemy/legacy_page_redirects.rb +1 -1
- data/app/decorators/alchemy/element_editor.rb +2 -2
- data/app/helpers/alchemy/admin/base_helper.rb +8 -60
- data/app/helpers/alchemy/admin/elements_helper.rb +1 -1
- data/app/helpers/alchemy/admin/ingredients_helper.rb +1 -1
- data/app/helpers/alchemy/base_helper.rb +9 -91
- data/app/helpers/alchemy/elements_helper.rb +3 -3
- data/app/helpers/alchemy/pages_helper.rb +16 -9
- data/app/javascript/alchemy_admin/components/attachment_select.js +24 -0
- data/app/javascript/alchemy_admin/components/button.js +3 -0
- data/app/javascript/alchemy_admin/components/clipboard_button.js +3 -2
- data/app/javascript/alchemy_admin/components/dialog_link.js +10 -7
- data/app/javascript/alchemy_admin/components/dom_id_select.js +69 -0
- data/app/javascript/alchemy_admin/components/element_editor/delete_element_button.js +42 -0
- data/app/javascript/alchemy_admin/components/element_editor/publish_element_button.js +4 -2
- data/app/javascript/alchemy_admin/components/element_editor.js +21 -13
- data/app/javascript/alchemy_admin/components/elements_window.js +87 -0
- data/app/javascript/alchemy_admin/components/growl.js +13 -0
- data/app/javascript/alchemy_admin/components/icon.js +51 -0
- data/app/javascript/alchemy_admin/components/index.js +24 -0
- data/app/javascript/alchemy_admin/components/ingredient_group.js +6 -0
- data/app/javascript/alchemy_admin/components/link_buttons/link_button.js +21 -11
- data/app/javascript/alchemy_admin/components/link_buttons/unlink_button.js +2 -1
- data/app/javascript/alchemy_admin/components/link_buttons.js +1 -0
- data/app/javascript/alchemy_admin/components/list_filter.js +68 -0
- data/app/javascript/alchemy_admin/components/message.js +69 -0
- data/app/javascript/alchemy_admin/components/node_select.js +1 -1
- data/app/javascript/alchemy_admin/components/overlay.js +6 -6
- data/app/javascript/alchemy_admin/components/page_select.js +3 -7
- data/app/javascript/alchemy_admin/components/preview_window.js +121 -0
- data/app/javascript/alchemy_admin/components/remote_select.js +4 -1
- data/app/javascript/alchemy_admin/components/select.js +37 -1
- data/app/javascript/alchemy_admin/components/tags_autocomplete.js +57 -0
- data/app/javascript/alchemy_admin/components/uploader/file_upload.js +4 -3
- data/app/javascript/alchemy_admin/components/uploader/progress.js +1 -1
- data/app/javascript/alchemy_admin/confirm_dialog.js +133 -0
- data/app/javascript/alchemy_admin/dirty.js +19 -14
- data/app/javascript/alchemy_admin/fixed_elements.js +24 -0
- data/app/javascript/alchemy_admin/growler.js +15 -0
- data/app/javascript/alchemy_admin/gui.js +2 -4
- data/app/javascript/alchemy_admin/hotkeys.js +60 -0
- data/app/javascript/alchemy_admin/image_loader.js +2 -2
- data/app/javascript/alchemy_admin/ingredient_anchor_link.js +2 -3
- data/app/javascript/alchemy_admin/initializer.js +1 -8
- data/app/javascript/alchemy_admin/link_dialog.js +131 -0
- data/app/javascript/alchemy_admin/locales/en.js +3 -0
- data/app/javascript/alchemy_admin/node_tree.js +4 -3
- data/app/javascript/alchemy_admin/page_sorter.js +23 -14
- data/app/javascript/alchemy_admin/picture_editors.js +3 -2
- data/app/javascript/alchemy_admin/shoelace_theme.js +60 -0
- data/app/javascript/alchemy_admin/sitemap.js +9 -3
- data/app/javascript/alchemy_admin/sortable_elements.js +4 -6
- data/app/javascript/alchemy_admin.js +18 -42
- data/app/models/alchemy/current.rb +26 -0
- data/app/models/alchemy/element.rb +1 -1
- data/app/models/alchemy/ingredients/headline.rb +8 -1
- data/app/models/alchemy/ingredients/picture.rb +6 -0
- data/app/models/alchemy/language.rb +8 -6
- data/app/models/alchemy/node.rb +2 -2
- data/app/models/alchemy/page/page_elements.rb +8 -8
- data/app/models/alchemy/page/page_layouts.rb +3 -3
- data/app/models/alchemy/page/page_natures.rb +13 -9
- data/app/models/alchemy/page/page_scopes.rb +2 -2
- data/app/models/alchemy/page/publisher.rb +1 -0
- data/app/models/alchemy/page.rb +15 -28
- data/app/models/alchemy/picture.rb +8 -0
- data/app/models/alchemy/picture_description.rb +8 -0
- data/app/models/alchemy/picture_variant.rb +1 -1
- data/app/models/alchemy/site.rb +10 -7
- data/app/serializers/alchemy/attachment_serializer.rb +8 -0
- data/app/serializers/alchemy/page_node_serializer.rb +9 -0
- data/app/views/alchemy/_menubar.html.erb +1 -1
- data/app/views/alchemy/_preview_mode_code.html.erb +1 -1
- data/app/views/alchemy/admin/attachments/_tag_list.html.erb +2 -2
- data/app/views/alchemy/admin/attachments/archive_overlay.js.erb +0 -1
- data/app/views/alchemy/admin/attachments/edit.html.erb +3 -4
- data/app/views/alchemy/admin/clipboard/clear.js.erb +1 -1
- data/app/views/alchemy/admin/clipboard/index.html.erb +1 -1
- data/app/views/alchemy/admin/clipboard/insert.js.erb +1 -1
- data/app/views/alchemy/admin/clipboard/remove.js.erb +1 -1
- data/app/views/alchemy/admin/dashboard/_locked_pages.html.erb +1 -1
- data/app/views/alchemy/admin/dashboard/_sites.html.erb +1 -1
- data/app/views/alchemy/admin/dashboard/help.html.erb +48 -12
- data/app/views/alchemy/admin/dashboard/index.html.erb +1 -1
- data/app/views/alchemy/admin/dashboard/info.html.erb +5 -8
- data/app/views/alchemy/admin/elements/_add_nested_element_form.html.erb +1 -1
- data/app/views/alchemy/admin/elements/_element.html.erb +5 -5
- data/app/views/alchemy/admin/elements/_footer.html.erb +1 -1
- data/app/views/alchemy/admin/elements/_header.html.erb +6 -2
- data/app/views/alchemy/admin/elements/_toolbar.html.erb +8 -6
- data/app/views/alchemy/admin/elements/create.js.erb +1 -5
- data/app/views/alchemy/admin/elements/index.html.erb +70 -34
- data/app/views/alchemy/admin/ingredients/_file_fields.html.erb +1 -2
- data/app/views/alchemy/admin/ingredients/_picture_fields.html.erb +3 -5
- data/app/views/alchemy/admin/languages/_language.html.erb +1 -1
- data/app/views/alchemy/admin/languages/index.html.erb +2 -2
- data/app/views/alchemy/admin/layoutpages/_layoutpage.html.erb +18 -18
- data/app/views/alchemy/admin/layoutpages/edit.html.erb +3 -4
- data/app/views/alchemy/admin/layoutpages/index.html.erb +2 -2
- data/app/views/alchemy/admin/legacy_page_urls/_legacy_page_url.html.erb +10 -11
- data/app/views/alchemy/admin/legacy_page_urls/_new.html.erb +15 -17
- data/app/views/alchemy/admin/legacy_page_urls/_table.html.erb +16 -0
- data/app/views/alchemy/admin/legacy_page_urls/_update.turbo_stream.erb +12 -0
- data/app/views/alchemy/admin/legacy_page_urls/create.turbo_stream.erb +8 -0
- data/app/views/alchemy/admin/legacy_page_urls/destroy.turbo_stream.erb +1 -0
- data/app/views/alchemy/admin/legacy_page_urls/edit.html.erb +27 -0
- data/app/views/alchemy/admin/legacy_page_urls/show.html.erb +1 -0
- data/app/views/alchemy/admin/legacy_page_urls/update.turbo_stream.erb +1 -0
- data/app/views/alchemy/admin/nodes/_form.html.erb +12 -11
- data/app/views/alchemy/admin/nodes/_label.html.erb +1 -0
- data/app/views/alchemy/admin/nodes/_node.html.erb +19 -19
- data/app/views/alchemy/admin/nodes/_page_nodes.html.erb +48 -0
- data/app/views/alchemy/admin/nodes/_update.turbo_stream.erb +9 -0
- data/app/views/alchemy/admin/nodes/create.turbo_stream.erb +1 -0
- data/app/views/alchemy/admin/nodes/destroy.turbo_stream.erb +1 -0
- data/app/views/alchemy/admin/nodes/index.html.erb +3 -3
- data/app/views/alchemy/admin/pages/_form.html.erb +3 -4
- data/app/views/alchemy/admin/pages/_legacy_urls.html.erb +4 -15
- data/app/views/alchemy/admin/pages/_page.html.erb +39 -39
- data/app/views/alchemy/admin/pages/_table_row.html.erb +3 -3
- data/app/views/alchemy/admin/pages/_toolbar.html.erb +2 -2
- data/app/views/alchemy/admin/pages/configure.html.erb +6 -0
- data/app/views/alchemy/admin/pages/edit.html.erb +15 -62
- data/app/views/alchemy/admin/pages/unlock.js.erb +2 -2
- data/app/views/alchemy/admin/partials/_autocomplete_tag_list.html.erb +3 -1
- data/app/views/alchemy/admin/partials/_flash_notices.html.erb +4 -2
- data/app/views/alchemy/admin/partials/_language_tree_select.html.erb +1 -1
- data/app/views/alchemy/admin/partials/_main_navigation_entry.html.erb +5 -2
- data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +2 -2
- data/app/views/alchemy/admin/partials/_search_form.html.erb +2 -2
- data/app/views/alchemy/admin/partials/_site_select.html.erb +1 -1
- data/app/views/alchemy/admin/picture_descriptions/_form.html.erb +11 -0
- data/app/views/alchemy/admin/picture_descriptions/edit.html.erb +6 -0
- data/app/views/alchemy/admin/pictures/_form.html.erb +4 -3
- data/app/views/alchemy/admin/pictures/_infos.html.erb +1 -1
- data/app/views/alchemy/admin/pictures/_picture_description_field.html.erb +29 -0
- data/app/views/alchemy/admin/pictures/_tag_list.html.erb +2 -2
- data/app/views/alchemy/admin/pictures/archive_overlay.js.erb +0 -2
- data/app/views/alchemy/admin/pictures/edit_multiple.html.erb +3 -3
- data/app/views/alchemy/admin/pictures/show.html.erb +3 -3
- data/app/views/alchemy/admin/resources/_form.html.erb +3 -4
- data/app/views/alchemy/admin/resources/_tag_list.html.erb +2 -2
- data/app/views/alchemy/admin/resources/index.html.erb +2 -2
- data/app/views/alchemy/admin/sites/index.html.erb +1 -1
- data/app/views/alchemy/admin/styleguide/index.html.erb +29 -24
- data/app/views/alchemy/admin/tags/_tag.html.erb +1 -1
- data/app/views/alchemy/admin/tags/edit.html.erb +1 -1
- data/app/views/alchemy/admin/tags/index.html.erb +1 -1
- data/app/views/alchemy/base/500.html.erb +7 -18
- data/app/views/alchemy/base/error_notice.html.erb +3 -1
- data/app/views/alchemy/ingredients/_boolean_editor.html.erb +1 -1
- data/app/views/alchemy/ingredients/_datetime_editor.html.erb +1 -1
- data/app/views/alchemy/ingredients/_headline_editor.html.erb +13 -8
- data/app/views/alchemy/ingredients/_picture_editor.html.erb +1 -1
- data/app/views/alchemy/ingredients/shared/_picture_tools.html.erb +1 -1
- data/app/views/alchemy/language_links/_language.html.erb +1 -1
- data/app/views/kaminari/alchemy/_first_page.html.erb +2 -2
- data/app/views/kaminari/alchemy/_gap.html.erb +1 -1
- data/app/views/kaminari/alchemy/_last_page.html.erb +2 -2
- data/app/views/kaminari/alchemy/_next_page.html.erb +2 -2
- data/app/views/kaminari/alchemy/_prev_page.html.erb +2 -2
- data/app/views/layouts/alchemy/admin.html.erb +2 -1
- data/bundles/shoelace.js +3 -1
- data/config/locales/alchemy.en.yml +16 -3
- data/config/routes.rb +3 -1
- data/db/migrate/20240314105244_create_alchemy_picture_descriptions.rb +11 -0
- data/lib/alchemy/configuration_methods.rb +1 -1
- data/lib/alchemy/controller_actions.rb +3 -3
- data/lib/alchemy/element_definition.rb +10 -6
- data/lib/alchemy/engine.rb +19 -2
- data/lib/alchemy/modules.rb +2 -2
- data/lib/alchemy/page_layout.rb +10 -6
- data/lib/alchemy/permissions.rb +3 -2
- data/lib/alchemy/seeder.rb +2 -2
- data/lib/alchemy/test_support/capybara_helpers.rb +4 -0
- data/lib/alchemy/test_support/factories/language_factory.rb +1 -1
- data/lib/alchemy/test_support/shared_contexts.rb +8 -0
- data/lib/alchemy/tinymce.rb +2 -1
- data/lib/alchemy/version.rb +1 -1
- data/lib/alchemy.rb +36 -0
- data/lib/alchemy_cms.rb +0 -1
- data/lib/generators/alchemy/menus/templates/node.html.erb +2 -2
- data/lib/generators/alchemy/menus/templates/node.html.haml +2 -2
- data/lib/generators/alchemy/menus/templates/node.html.slim +2 -2
- data/lib/generators/alchemy/menus/templates/wrapper.html.erb +1 -1
- data/lib/generators/alchemy/menus/templates/wrapper.html.haml +1 -1
- data/lib/generators/alchemy/menus/templates/wrapper.html.slim +1 -1
- data/lib/tasks/alchemy/sitemap.rake +97 -0
- data/package.json +8 -8
- data/vendor/assets/fonts/remixicon.symbol.svg +11 -0
- data/vendor/javascript/shoelace.min.js +333 -118
- data/vendor/javascript/sortable.min.js +1 -1
- data/vendor/javascript/tinymce.min.js +1 -1
- data/vendor/javascript/ungap-custom-elements.min.js +1 -1
- metadata +61 -54
- data/app/assets/javascripts/alchemy/alchemy.confirm_dialog.js.coffee +0 -85
- data/app/assets/javascripts/alchemy/alchemy.elements_window.js.coffee +0 -107
- data/app/assets/javascripts/alchemy/alchemy.file_progress.js.coffee +0 -66
- data/app/assets/javascripts/alchemy/alchemy.fixed_elements.js +0 -45
- data/app/assets/javascripts/alchemy/alchemy.growler.js.coffee +0 -24
- data/app/assets/javascripts/alchemy/alchemy.hotkeys.js.coffee +0 -49
- data/app/assets/javascripts/alchemy/alchemy.initializer.js.coffee +0 -0
- data/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +0 -230
- data/app/assets/javascripts/alchemy/alchemy.list_filter.js.coffee +0 -49
- data/app/assets/javascripts/alchemy/alchemy.preview_window.js.coffee +0 -82
- data/app/assets/javascripts/alchemy/alchemy.string_extension.js.coffee +0 -11
- data/app/assets/javascripts/alchemy/templates/page.hbs +0 -19
- data/app/javascript/alchemy_admin/tags_autocomplete.js +0 -46
- data/app/models/alchemy/tree_node.rb +0 -7
- data/app/views/alchemy/admin/elements/destroy.js.erb +0 -8
- data/app/views/alchemy/admin/legacy_page_urls/_form.html.erb +0 -5
- data/app/views/alchemy/admin/legacy_page_urls/create.js.erb +0 -9
- data/app/views/alchemy/admin/legacy_page_urls/destroy.js.erb +0 -6
- data/app/views/alchemy/admin/legacy_page_urls/update.js.erb +0 -2
- data/app/views/alchemy/admin/pages/_anchor_link.html.erb +0 -22
- data/app/views/alchemy/admin/pages/_external_link.html.erb +0 -31
- data/app/views/alchemy/admin/pages/_file_link.html.erb +0 -31
- data/app/views/alchemy/admin/pages/_internal_link.html.erb +0 -35
- data/app/views/alchemy/admin/pages/link.html.erb +0 -26
- data/app/views/alchemy/admin/partials/_flash.html.erb +0 -4
- data/app/views/alchemy/admin/partials/_toolbar_button.html.erb +0 -29
- data/vendor/assets/fonts/remixicon.eot +0 -0
- data/vendor/assets/fonts/remixicon.svg +0 -7816
- data/vendor/assets/fonts/remixicon.ttf +0 -0
- data/vendor/assets/fonts/remixicon.woff +0 -0
- data/vendor/assets/fonts/remixicon.woff2 +0 -0
- data/vendor/assets/stylesheets/remixicon.scss +0 -10480
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import Sortable from "sortablejs"
|
|
2
|
+
import { growl } from "alchemy_admin/growler"
|
|
2
3
|
import { patch } from "alchemy_admin/utils/ajax"
|
|
4
|
+
import pleaseWaitOverlay from "alchemy_admin/please_wait_overlay"
|
|
3
5
|
|
|
4
|
-
function
|
|
6
|
+
function onSort(evt) {
|
|
5
7
|
const pageId = evt.item.dataset.pageId
|
|
6
8
|
const url = Alchemy.routes.move_admin_page_path(pageId)
|
|
7
9
|
const data = {
|
|
@@ -9,19 +11,26 @@ function onFinishDragging(evt) {
|
|
|
9
11
|
new_position: evt.newIndex
|
|
10
12
|
}
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
if (evt.target === evt.to) {
|
|
15
|
+
pleaseWaitOverlay(true)
|
|
16
|
+
patch(url, data)
|
|
17
|
+
.then(async (response) => {
|
|
18
|
+
const pageData = await response.data
|
|
19
|
+
const pageEl = document.getElementById(`page_${pageId}`)
|
|
20
|
+
const urlPathEl = pageEl.querySelector(".sitemap_url")
|
|
17
21
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
growl(Alchemy.t("Successfully moved page"))
|
|
23
|
+
urlPathEl.textContent = pageData.url_path
|
|
24
|
+
displayPageFolders()
|
|
25
|
+
})
|
|
26
|
+
.catch((error) => {
|
|
27
|
+
growl(error.message || error, "error")
|
|
28
|
+
Alchemy.currentSitemap.reload()
|
|
29
|
+
})
|
|
30
|
+
.finally(() => {
|
|
31
|
+
pleaseWaitOverlay(false)
|
|
32
|
+
})
|
|
33
|
+
}
|
|
25
34
|
}
|
|
26
35
|
|
|
27
36
|
export function displayPageFolders() {
|
|
@@ -50,7 +59,7 @@ export function createSortables(sortables) {
|
|
|
50
59
|
fallbackOnBody: true,
|
|
51
60
|
swapThreshold: 0.65,
|
|
52
61
|
handle: ".handle",
|
|
53
|
-
|
|
62
|
+
onSort
|
|
54
63
|
})
|
|
55
64
|
})
|
|
56
65
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import debounce from "alchemy_admin/utils/debounce"
|
|
2
2
|
import max from "alchemy_admin/utils/max"
|
|
3
3
|
import { get } from "alchemy_admin/utils/ajax"
|
|
4
|
+
import { growl } from "alchemy_admin/growler"
|
|
4
5
|
import ImageLoader from "alchemy_admin/image_loader"
|
|
5
6
|
|
|
6
7
|
const UPDATE_DELAY = 125
|
|
7
|
-
const IMAGE_PLACEHOLDER = '<
|
|
8
|
+
const IMAGE_PLACEHOLDER = '<alchemy-icon name="image"></alchemy-icon>'
|
|
8
9
|
const THUMBNAIL_SIZE = "160x120"
|
|
9
10
|
|
|
10
11
|
class PictureEditor {
|
|
@@ -77,7 +78,7 @@ class PictureEditor {
|
|
|
77
78
|
})
|
|
78
79
|
.catch((error) => {
|
|
79
80
|
console.error(error.message || error)
|
|
80
|
-
|
|
81
|
+
growl(error.message || error, "error")
|
|
81
82
|
})
|
|
82
83
|
}
|
|
83
84
|
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { registerIconLibrary, setDefaultAnimation } from "shoelace"
|
|
2
|
+
|
|
3
|
+
// Change the default animation for all tooltips
|
|
4
|
+
setDefaultAnimation("tooltip.show", {
|
|
5
|
+
keyframes: [
|
|
6
|
+
{ transform: "translateY(10px)", opacity: "0" },
|
|
7
|
+
{ transform: "translateY(0)", opacity: "1" }
|
|
8
|
+
],
|
|
9
|
+
options: {
|
|
10
|
+
duration: 100
|
|
11
|
+
}
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
setDefaultAnimation("tooltip.hide", {
|
|
15
|
+
keyframes: [
|
|
16
|
+
{ transform: "translateY(0)", opacity: "1" },
|
|
17
|
+
{ transform: "translateY(10px)", opacity: "0" }
|
|
18
|
+
],
|
|
19
|
+
options: {
|
|
20
|
+
duration: 100
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
// Change the default animation for all dialogs
|
|
25
|
+
setDefaultAnimation("dialog.show", {
|
|
26
|
+
keyframes: [
|
|
27
|
+
{ transform: "scale(0.98)", opacity: "0" },
|
|
28
|
+
{ transform: "scale(1)", opacity: "1" }
|
|
29
|
+
],
|
|
30
|
+
options: {
|
|
31
|
+
duration: 150
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
setDefaultAnimation("dialog.hide", {
|
|
36
|
+
keyframes: [
|
|
37
|
+
{ transform: "scale(1)", opacity: "1" },
|
|
38
|
+
{ transform: "scale(0.98)", opacity: "0" }
|
|
39
|
+
],
|
|
40
|
+
options: {
|
|
41
|
+
duration: 150
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
const spriteUrl = document
|
|
46
|
+
.querySelector('meta[name="alchemy-icon-sprite"]')
|
|
47
|
+
.getAttribute("content")
|
|
48
|
+
|
|
49
|
+
const iconMap = {
|
|
50
|
+
"x-lg": "close"
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const options = {
|
|
54
|
+
resolver: (name) => `${spriteUrl}#ri-${iconMap[name] || name}-line`,
|
|
55
|
+
mutator: (svg) => svg.setAttribute("fill", "currentColor"),
|
|
56
|
+
spriteSheet: true
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
registerIconLibrary("default", options)
|
|
60
|
+
registerIconLibrary("system", options)
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import PageSorter from "alchemy_admin/page_sorter"
|
|
3
3
|
import { on } from "alchemy_admin/utils/events"
|
|
4
4
|
import { get, patch } from "alchemy_admin/utils/ajax"
|
|
5
|
+
import { growl } from "alchemy_admin/growler"
|
|
5
6
|
import { createSortables, displayPageFolders } from "alchemy_admin/page_sorter"
|
|
6
7
|
|
|
7
8
|
export default class Sitemap {
|
|
@@ -40,6 +41,11 @@ export default class Sitemap {
|
|
|
40
41
|
.catch(this.errorHandler)
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
// Reloads the sitemap
|
|
45
|
+
reload() {
|
|
46
|
+
this.load(this.options.page_root_id)
|
|
47
|
+
}
|
|
48
|
+
|
|
43
49
|
// Watch page folder clicks and re-render the page branch
|
|
44
50
|
handlePageFolders() {
|
|
45
51
|
on(
|
|
@@ -103,7 +109,6 @@ export default class Sitemap {
|
|
|
103
109
|
item.classList.remove("highlight")
|
|
104
110
|
}
|
|
105
111
|
})
|
|
106
|
-
this.filter_field_clear.style.display = "inline-block"
|
|
107
112
|
const { length } = results
|
|
108
113
|
|
|
109
114
|
if (length === 1) {
|
|
@@ -123,7 +128,6 @@ export default class Sitemap {
|
|
|
123
128
|
left: 0,
|
|
124
129
|
behavior: "smooth"
|
|
125
130
|
})
|
|
126
|
-
this.filter_field_clear.style.display = "none"
|
|
127
131
|
}
|
|
128
132
|
}
|
|
129
133
|
|
|
@@ -131,6 +135,8 @@ export default class Sitemap {
|
|
|
131
135
|
_observe() {
|
|
132
136
|
this.search_field.addEventListener("keyup", (evt) => {
|
|
133
137
|
const term = evt.target.value
|
|
138
|
+
this.filter_field_clear.style.visibility =
|
|
139
|
+
term == "" ? "hidden" : "visible"
|
|
134
140
|
this.filter(term.toLowerCase())
|
|
135
141
|
})
|
|
136
142
|
this.search_field.addEventListener("focus", () => key.setScope("search"))
|
|
@@ -142,7 +148,7 @@ export default class Sitemap {
|
|
|
142
148
|
}
|
|
143
149
|
|
|
144
150
|
errorHandler(error) {
|
|
145
|
-
|
|
151
|
+
growl(error.message || error, "error")
|
|
146
152
|
console.error(error)
|
|
147
153
|
}
|
|
148
154
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import Sortable from "sortablejs"
|
|
2
|
+
import { growl } from "alchemy_admin/growler"
|
|
2
3
|
import { post } from "alchemy_admin/utils/ajax"
|
|
4
|
+
import { reloadPreview } from "alchemy_admin/components/preview_window"
|
|
3
5
|
|
|
4
6
|
const SORTABLE_OPTIONS = {
|
|
5
7
|
draggable: ".element-editor",
|
|
@@ -35,8 +37,8 @@ function onSort(event) {
|
|
|
35
37
|
if (event.target === event.to) {
|
|
36
38
|
post(Alchemy.routes.order_admin_elements_path, params).then((response) => {
|
|
37
39
|
const data = response.data
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
growl(data.message)
|
|
41
|
+
reloadPreview()
|
|
40
42
|
item.updateTitle(data.preview_text)
|
|
41
43
|
})
|
|
42
44
|
}
|
|
@@ -76,8 +78,4 @@ export default function SortableElements(selector) {
|
|
|
76
78
|
})
|
|
77
79
|
|
|
78
80
|
sortable_areas.forEach((element) => createSortable(element))
|
|
79
|
-
|
|
80
|
-
document.querySelectorAll(".nested-elements").forEach((nestedElement) => {
|
|
81
|
-
createSortable(nestedElement)
|
|
82
|
-
})
|
|
83
81
|
}
|
|
@@ -1,62 +1,34 @@
|
|
|
1
1
|
import "@ungap/custom-elements"
|
|
2
2
|
import "@hotwired/turbo-rails"
|
|
3
|
-
import "keymaster"
|
|
4
3
|
|
|
5
4
|
import Rails from "@rails/ujs"
|
|
6
5
|
|
|
7
6
|
import GUI from "alchemy_admin/gui"
|
|
8
7
|
import { translate } from "alchemy_admin/i18n"
|
|
9
8
|
import Dirty from "alchemy_admin/dirty"
|
|
9
|
+
import * as FixedElements from "alchemy_admin/fixed_elements"
|
|
10
|
+
import { growl } from "alchemy_admin/growler"
|
|
10
11
|
import IngredientAnchorLink from "alchemy_admin/ingredient_anchor_link"
|
|
11
12
|
import ImageLoader from "alchemy_admin/image_loader"
|
|
12
13
|
import ImageCropper from "alchemy_admin/image_cropper"
|
|
13
14
|
import Initializer from "alchemy_admin/initializer"
|
|
15
|
+
import { LinkDialog } from "alchemy_admin/link_dialog"
|
|
14
16
|
import pictureSelector from "alchemy_admin/picture_selector"
|
|
15
17
|
import pleaseWaitOverlay from "alchemy_admin/please_wait_overlay"
|
|
16
18
|
import Sitemap from "alchemy_admin/sitemap"
|
|
17
|
-
import SortableElements from "alchemy_admin/sortable_elements"
|
|
18
19
|
import Spinner from "alchemy_admin/spinner"
|
|
19
20
|
import PagePublicationFields from "alchemy_admin/page_publication_fields"
|
|
21
|
+
import { reloadPreview } from "alchemy_admin/components/preview_window"
|
|
22
|
+
import {
|
|
23
|
+
openConfirmDialog,
|
|
24
|
+
confirmToDeleteDialog
|
|
25
|
+
} from "alchemy_admin/confirm_dialog"
|
|
20
26
|
|
|
21
27
|
// Web Components
|
|
22
|
-
import "alchemy_admin/components
|
|
23
|
-
import "alchemy_admin/components/char_counter"
|
|
24
|
-
import "alchemy_admin/components/clipboard_button"
|
|
25
|
-
import "alchemy_admin/components/datepicker"
|
|
26
|
-
import "alchemy_admin/components/dialog_link"
|
|
27
|
-
import "alchemy_admin/components/element_editor"
|
|
28
|
-
import "alchemy_admin/components/ingredient_group"
|
|
29
|
-
import "alchemy_admin/components/link_buttons"
|
|
30
|
-
import "alchemy_admin/components/node_select"
|
|
31
|
-
import "alchemy_admin/components/uploader"
|
|
32
|
-
import "alchemy_admin/components/overlay"
|
|
33
|
-
import "alchemy_admin/components/page_select"
|
|
34
|
-
import "alchemy_admin/components/select"
|
|
35
|
-
import "alchemy_admin/components/spinner"
|
|
36
|
-
import "alchemy_admin/components/tinymce"
|
|
28
|
+
import "alchemy_admin/components"
|
|
37
29
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
// Change the default animation for all dialogs
|
|
41
|
-
setDefaultAnimation("tooltip.show", {
|
|
42
|
-
keyframes: [
|
|
43
|
-
{ transform: "translateY(10px)", opacity: "0" },
|
|
44
|
-
{ transform: "translateY(0)", opacity: "1" }
|
|
45
|
-
],
|
|
46
|
-
options: {
|
|
47
|
-
duration: 100
|
|
48
|
-
}
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
setDefaultAnimation("tooltip.hide", {
|
|
52
|
-
keyframes: [
|
|
53
|
-
{ transform: "translateY(0)", opacity: "1" },
|
|
54
|
-
{ transform: "translateY(10px)", opacity: "0" }
|
|
55
|
-
],
|
|
56
|
-
options: {
|
|
57
|
-
duration: 100
|
|
58
|
-
}
|
|
59
|
-
})
|
|
30
|
+
// Shoelace Setup
|
|
31
|
+
import "alchemy_admin/shoelace_theme"
|
|
60
32
|
|
|
61
33
|
// Global Alchemy object
|
|
62
34
|
if (typeof window.Alchemy === "undefined") {
|
|
@@ -68,16 +40,20 @@ Object.assign(Alchemy, {
|
|
|
68
40
|
...Dirty,
|
|
69
41
|
GUI,
|
|
70
42
|
t: translate, // Global utility method for translating a given string
|
|
43
|
+
FixedElements,
|
|
44
|
+
growl,
|
|
71
45
|
ImageLoader: ImageLoader.init,
|
|
72
46
|
ImageCropper,
|
|
73
|
-
Initializer,
|
|
74
47
|
IngredientAnchorLink,
|
|
48
|
+
LinkDialog,
|
|
75
49
|
pictureSelector,
|
|
76
50
|
pleaseWaitOverlay,
|
|
77
51
|
Sitemap,
|
|
78
|
-
SortableElements,
|
|
79
52
|
Spinner,
|
|
80
|
-
PagePublicationFields
|
|
53
|
+
PagePublicationFields,
|
|
54
|
+
reloadPreview,
|
|
55
|
+
openConfirmDialog,
|
|
56
|
+
confirmToDeleteDialog
|
|
81
57
|
})
|
|
82
58
|
|
|
83
59
|
Rails.start()
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Alchemy
|
|
2
|
+
class Current < ActiveSupport::CurrentAttributes
|
|
3
|
+
attribute :preview_page, :page, :language, :site
|
|
4
|
+
|
|
5
|
+
def language
|
|
6
|
+
super || Language.default
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def site
|
|
10
|
+
super || Site.first
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def preview_page=(page)
|
|
14
|
+
super
|
|
15
|
+
|
|
16
|
+
self.page = page
|
|
17
|
+
self.language = page&.language
|
|
18
|
+
self.site = page&.site
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def preview_page?(page = Current.page)
|
|
22
|
+
return false if preview_page.nil?
|
|
23
|
+
preview_page == page
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -101,7 +101,7 @@ module Alchemy
|
|
|
101
101
|
scope :excluded, ->(names) { where.not(name: names) }
|
|
102
102
|
scope :fixed, -> { where(fixed: true) }
|
|
103
103
|
scope :unfixed, -> { where(fixed: false) }
|
|
104
|
-
scope :from_current_site, -> { where(Language.table_name => {site_id:
|
|
104
|
+
scope :from_current_site, -> { where(Language.table_name => {site_id: Current.site}).joins(page: "language") }
|
|
105
105
|
scope :folded, -> { where(folded: true) }
|
|
106
106
|
scope :expanded, -> { where(folded: false) }
|
|
107
107
|
scope :not_nested, -> { where(parent_element_id: nil) }
|
|
@@ -38,6 +38,12 @@ module Alchemy
|
|
|
38
38
|
upsample
|
|
39
39
|
]
|
|
40
40
|
|
|
41
|
+
def alt_text(language: Alchemy::Current.language)
|
|
42
|
+
alt_tag.presence ||
|
|
43
|
+
picture&.description_for(language) ||
|
|
44
|
+
picture&.name&.humanize
|
|
45
|
+
end
|
|
46
|
+
|
|
41
47
|
# The first 30 characters of the pictures name
|
|
42
48
|
#
|
|
43
49
|
# Used by the Element#preview_text method.
|
|
@@ -68,24 +68,26 @@ module Alchemy
|
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
def on_current_site
|
|
71
|
-
on_site(
|
|
71
|
+
on_site(Current.site)
|
|
72
72
|
end
|
|
73
73
|
|
|
74
74
|
# Store the current language in the current thread.
|
|
75
|
+
# @deprecated Use {Alchemy::Current#language=} instead.
|
|
75
76
|
def current=(language)
|
|
76
|
-
|
|
77
|
+
Current.language = language
|
|
77
78
|
end
|
|
79
|
+
deprecate "current=": :"Alchemy::Current.language=", deprecator: Alchemy::Deprecation
|
|
78
80
|
|
|
79
81
|
# Current language from current thread or default.
|
|
82
|
+
# @deprecated Use {Alchemy::Current#language} instead.
|
|
80
83
|
def current
|
|
81
|
-
|
|
84
|
+
Current.language
|
|
82
85
|
end
|
|
86
|
+
deprecate current: :"Alchemy::Current.language", deprecator: Alchemy::Deprecation
|
|
83
87
|
|
|
84
88
|
# The root page of the current language.
|
|
85
89
|
def current_root_page
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
current.pages.language_roots.first
|
|
90
|
+
Current.language&.pages&.language_roots&.first
|
|
89
91
|
end
|
|
90
92
|
|
|
91
93
|
# Default language for current site
|
data/app/models/alchemy/node.rb
CHANGED
|
@@ -37,9 +37,9 @@ module Alchemy
|
|
|
37
37
|
class << self
|
|
38
38
|
# Returns all root nodes for current language
|
|
39
39
|
def language_root_nodes
|
|
40
|
-
raise "No language found" if
|
|
40
|
+
raise "No language found" if Current.language.nil?
|
|
41
41
|
|
|
42
|
-
roots.where(language_id:
|
|
42
|
+
roots.where(language_id: Current.language.id)
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def available_menu_names
|
|
@@ -80,21 +80,21 @@ module Alchemy
|
|
|
80
80
|
# type: Richtext
|
|
81
81
|
#
|
|
82
82
|
def available_element_definitions(only_element_named = nil)
|
|
83
|
-
@
|
|
83
|
+
@_available_element_definitions ||= if only_element_named
|
|
84
84
|
definition = Element.definition_by_name(only_element_named)
|
|
85
85
|
element_definitions_by_name(definition["nestable_elements"])
|
|
86
86
|
else
|
|
87
|
-
element_definitions
|
|
87
|
+
element_definitions.dup
|
|
88
88
|
end
|
|
89
89
|
|
|
90
|
-
return [] if @
|
|
90
|
+
return [] if @_available_element_definitions.blank?
|
|
91
91
|
|
|
92
92
|
existing_elements = draft_version.elements.not_nested
|
|
93
93
|
@_existing_element_names = existing_elements.pluck(:name)
|
|
94
94
|
delete_unique_element_definitions!
|
|
95
95
|
delete_outnumbered_element_definitions!
|
|
96
96
|
|
|
97
|
-
@
|
|
97
|
+
@_available_element_definitions
|
|
98
98
|
end
|
|
99
99
|
|
|
100
100
|
# All names of elements that can actually be placed on current page.
|
|
@@ -186,18 +186,18 @@ module Alchemy
|
|
|
186
186
|
end
|
|
187
187
|
end
|
|
188
188
|
|
|
189
|
-
# Deletes unique and already present definitions from @
|
|
189
|
+
# Deletes unique and already present definitions from @_available_element_definitions.
|
|
190
190
|
#
|
|
191
191
|
def delete_unique_element_definitions!
|
|
192
|
-
@
|
|
192
|
+
@_available_element_definitions.delete_if do |element|
|
|
193
193
|
element["unique"] && @_existing_element_names.include?(element["name"])
|
|
194
194
|
end
|
|
195
195
|
end
|
|
196
196
|
|
|
197
|
-
# Deletes limited and outnumbered definitions from @
|
|
197
|
+
# Deletes limited and outnumbered definitions from @_available_element_definitions.
|
|
198
198
|
#
|
|
199
199
|
def delete_outnumbered_element_definitions!
|
|
200
|
-
@
|
|
200
|
+
@_available_element_definitions.delete_if do |element|
|
|
201
201
|
outnumbered = @_existing_element_names.select { |name| name == element["name"] }
|
|
202
202
|
element["amount"] && outnumbered.count >= element["amount"].to_i
|
|
203
203
|
end
|
|
@@ -103,10 +103,10 @@ module Alchemy
|
|
|
103
103
|
# page_layouts: [default_intro]
|
|
104
104
|
#
|
|
105
105
|
def available_on_site?(layout)
|
|
106
|
-
return false unless Alchemy::
|
|
106
|
+
return false unless Alchemy::Current.site
|
|
107
107
|
|
|
108
|
-
Alchemy::
|
|
109
|
-
Alchemy::
|
|
108
|
+
Alchemy::Current.site.definition.blank? ||
|
|
109
|
+
Alchemy::Current.site.definition.fetch("page_layouts", []).include?(layout["name"])
|
|
110
110
|
end
|
|
111
111
|
end
|
|
112
112
|
end
|
|
@@ -101,18 +101,22 @@ module Alchemy
|
|
|
101
101
|
page_layout.parameterize.underscore
|
|
102
102
|
end
|
|
103
103
|
|
|
104
|
-
# Returns the version that's taken for Rails' recycable cache key.
|
|
104
|
+
# Returns the version string that's taken for Rails' recycable cache key.
|
|
105
105
|
#
|
|
106
|
-
|
|
106
|
+
def cache_version
|
|
107
|
+
last_modified_at&.to_s
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Returns the timestamp that the page was last modified at, regardless of through
|
|
111
|
+
# publishing or editing page, or through a change of related objects through ingredients.
|
|
112
|
+
# Respects the public version not changing if editing a preview.
|
|
107
113
|
#
|
|
108
|
-
#
|
|
114
|
+
# In preview mode, it will take the draft version's updated_at timestamp.
|
|
115
|
+
# In public mode, it will take the public version's updated_at timestamp.
|
|
109
116
|
#
|
|
110
|
-
def
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
else
|
|
114
|
-
published_at.to_s
|
|
115
|
-
end
|
|
117
|
+
def last_modified_at
|
|
118
|
+
relevant_page_version = (Current.preview_page == self) ? draft_version : public_version
|
|
119
|
+
relevant_page_version&.updated_at
|
|
116
120
|
end
|
|
117
121
|
|
|
118
122
|
# Returns true if the page cache control headers should be set.
|
|
@@ -94,11 +94,11 @@ module Alchemy
|
|
|
94
94
|
#
|
|
95
95
|
scope :searchables, -> { not_restricted.published.contentpages }
|
|
96
96
|
|
|
97
|
-
# All pages from +Alchemy::
|
|
97
|
+
# All pages from +Alchemy::Current.site+
|
|
98
98
|
#
|
|
99
99
|
scope :from_current_site,
|
|
100
100
|
-> {
|
|
101
|
-
where(Language.table_name => {site_id:
|
|
101
|
+
where(Language.table_name => {site_id: Current.site}).joins(:language)
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
# All pages for xml sitemap
|
data/app/models/alchemy/page.rb
CHANGED
|
@@ -121,6 +121,8 @@ module Alchemy
|
|
|
121
121
|
has_one :draft_version, -> { drafts }, class_name: "Alchemy::PageVersion"
|
|
122
122
|
has_one :public_version, -> { published }, class_name: "Alchemy::PageVersion", autosave: -> { persisted? }
|
|
123
123
|
|
|
124
|
+
has_many :page_ingredients, class_name: "Alchemy::Ingredients::Page", foreign_key: :related_object_id, dependent: :nullify
|
|
125
|
+
|
|
124
126
|
before_validation :set_language,
|
|
125
127
|
if: -> { language.nil? }
|
|
126
128
|
|
|
@@ -198,17 +200,19 @@ module Alchemy
|
|
|
198
200
|
%w[name urlname title]
|
|
199
201
|
end
|
|
200
202
|
|
|
201
|
-
# Used to store the current page
|
|
202
|
-
#
|
|
203
|
+
# Used to store the current page previewed in the edit page template.
|
|
204
|
+
# @deprecated Use {Alchemy::Current#preview_page=} instead.
|
|
203
205
|
def current_preview=(page)
|
|
204
|
-
|
|
206
|
+
Current.preview_page = page
|
|
205
207
|
end
|
|
208
|
+
deprecate "current_preview=": :"Alchemy::Current.preview_page=", deprecator: Alchemy::Deprecation
|
|
206
209
|
|
|
207
|
-
# Returns the current page
|
|
208
|
-
#
|
|
210
|
+
# Returns the current page previewed in the edit page template.
|
|
211
|
+
# @deprecated Use {Alchemy::Current#preview_page} instead.
|
|
209
212
|
def current_preview
|
|
210
|
-
|
|
213
|
+
Current.preview_page
|
|
211
214
|
end
|
|
215
|
+
deprecate current_preview: :"Alchemy::Current.preview_page", deprecator: Alchemy::Deprecation
|
|
212
216
|
|
|
213
217
|
# @return the language root page for given language id.
|
|
214
218
|
# @param language_id [Fixnum]
|
|
@@ -269,8 +273,10 @@ module Alchemy
|
|
|
269
273
|
options = [[Alchemy.t(:default, scope: "link_target_options"), ""]]
|
|
270
274
|
link_target_options = Config.get(:link_target_options)
|
|
271
275
|
link_target_options.each do |option|
|
|
276
|
+
# add an underscore to the options to provide the default syntax
|
|
277
|
+
# @link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#target
|
|
272
278
|
options << [Alchemy.t(option, scope: "link_target_options",
|
|
273
|
-
default: option.to_s.humanize), option]
|
|
279
|
+
default: option.to_s.humanize), "_#{option}"]
|
|
274
280
|
end
|
|
275
281
|
options
|
|
276
282
|
end
|
|
@@ -373,7 +379,7 @@ module Alchemy
|
|
|
373
379
|
#
|
|
374
380
|
def unlock!
|
|
375
381
|
if update_columns(locked_at: nil, locked_by: nil)
|
|
376
|
-
|
|
382
|
+
Current.preview_page = nil
|
|
377
383
|
end
|
|
378
384
|
end
|
|
379
385
|
|
|
@@ -442,25 +448,6 @@ module Alchemy
|
|
|
442
448
|
|
|
443
449
|
delegate :public_until=, to: :public_version, allow_nil: true
|
|
444
450
|
|
|
445
|
-
# Updates an Alchemy::Page based on a new ordering to be applied to it
|
|
446
|
-
#
|
|
447
|
-
# Note: Page's urls should not be updated (and a legacy URL created) if nesting is OFF
|
|
448
|
-
# or if the URL is the same
|
|
449
|
-
#
|
|
450
|
-
# @param [TreeNode]
|
|
451
|
-
# A tree node with new lft, rgt, depth, url, parent_id and restricted indexes to be updated
|
|
452
|
-
#
|
|
453
|
-
def update_node!(node)
|
|
454
|
-
hash = {lft: node.left, rgt: node.right, parent_id: node.parent, depth: node.depth, restricted: node.restricted}
|
|
455
|
-
|
|
456
|
-
if urlname != node.url
|
|
457
|
-
LegacyPageUrl.create(page_id: id, urlname: urlname)
|
|
458
|
-
hash[:urlname] = node.url
|
|
459
|
-
end
|
|
460
|
-
|
|
461
|
-
update_columns(hash)
|
|
462
|
-
end
|
|
463
|
-
|
|
464
451
|
# Holds an instance of +FixedAttributes+
|
|
465
452
|
def fixed_attributes
|
|
466
453
|
@_fixed_attributes ||= FixedAttributes.new(self)
|
|
@@ -553,7 +540,7 @@ module Alchemy
|
|
|
553
540
|
end
|
|
554
541
|
|
|
555
542
|
def set_language
|
|
556
|
-
self.language = parent&.language ||
|
|
543
|
+
self.language = parent&.language || Current.language
|
|
557
544
|
set_language_code
|
|
558
545
|
end
|
|
559
546
|
|
|
@@ -55,6 +55,9 @@ module Alchemy
|
|
|
55
55
|
has_many :elements, through: :picture_ingredients
|
|
56
56
|
has_many :pages, through: :elements
|
|
57
57
|
has_many :thumbs, class_name: "Alchemy::PictureThumb", dependent: :destroy
|
|
58
|
+
has_many :descriptions, class_name: "Alchemy::PictureDescription", dependent: :destroy
|
|
59
|
+
|
|
60
|
+
accepts_nested_attributes_for :descriptions, allow_destroy: true, reject_if: ->(attr) { attr[:text].blank? }
|
|
58
61
|
|
|
59
62
|
# Raise error, if picture is in use (aka. assigned to an Picture ingredient)
|
|
60
63
|
#
|
|
@@ -231,6 +234,11 @@ module Alchemy
|
|
|
231
234
|
}
|
|
232
235
|
end
|
|
233
236
|
|
|
237
|
+
# Returns the picture description for a given language.
|
|
238
|
+
def description_for(language)
|
|
239
|
+
descriptions.find_by(language: language)&.text
|
|
240
|
+
end
|
|
241
|
+
|
|
234
242
|
# Returns an uri escaped name.
|
|
235
243
|
#
|
|
236
244
|
def urlname
|