alchemy_cms 8.0.11 → 8.1.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 +14 -10
- data/app/assets/builds/alchemy/admin.css +1 -1
- data/app/assets/builds/alchemy/dark-theme.css +1 -1
- data/app/assets/builds/alchemy/light-theme.css +1 -1
- data/app/assets/builds/alchemy/preview.min.js +1 -1
- data/app/assets/builds/alchemy/theme.css +1 -1
- data/app/{views/alchemy/admin/elements/_element.html.erb → components/alchemy/admin/element_editor.html.erb} +34 -29
- data/app/components/alchemy/admin/element_editor.rb +115 -0
- data/app/components/alchemy/admin/element_select.rb +12 -9
- data/app/components/alchemy/admin/ingredient_editor.rb +54 -0
- data/app/components/alchemy/admin/list_filter.rb +16 -5
- data/app/components/alchemy/admin/page_node.html.erb +214 -0
- data/app/components/alchemy/admin/page_node.rb +70 -0
- data/app/components/alchemy/admin/picture_thumbnail.rb +36 -0
- data/app/components/alchemy/admin/publish_page_button.html.erb +15 -0
- data/app/components/alchemy/admin/publish_page_button.rb +54 -0
- data/app/{helpers/alchemy/admin/tags_helper.rb → components/alchemy/admin/tags_list.rb} +19 -11
- data/app/components/alchemy/admin/toolbar_button.rb +17 -13
- data/app/components/alchemy/ingredients/audio_editor.rb +8 -0
- data/app/components/alchemy/ingredients/base_editor.rb +222 -0
- data/app/components/alchemy/ingredients/boolean_editor.rb +21 -0
- data/app/components/alchemy/ingredients/color_editor.rb +80 -0
- data/app/components/alchemy/ingredients/color_view.rb +13 -0
- data/app/components/alchemy/ingredients/datetime_editor.rb +28 -0
- data/app/components/alchemy/ingredients/file_editor.rb +69 -0
- data/app/components/alchemy/ingredients/headline_editor.rb +88 -0
- data/app/components/alchemy/ingredients/html_editor.rb +11 -0
- data/app/components/alchemy/ingredients/link_editor.rb +29 -0
- data/app/components/alchemy/ingredients/node_editor.rb +23 -0
- data/app/components/alchemy/ingredients/number_editor.rb +28 -0
- data/app/components/alchemy/ingredients/page_editor.rb +19 -0
- data/app/components/alchemy/ingredients/picture_editor.rb +81 -0
- data/app/components/alchemy/ingredients/richtext_editor.rb +31 -0
- data/app/components/alchemy/ingredients/select_editor.rb +37 -0
- data/app/components/alchemy/ingredients/select_view.rb +7 -0
- data/app/components/alchemy/ingredients/text_editor.rb +41 -0
- data/app/components/alchemy/ingredients/video_editor.rb +8 -0
- data/app/controllers/alchemy/admin/attachments_controller.rb +8 -6
- data/app/controllers/alchemy/admin/base_controller.rb +7 -18
- data/app/controllers/alchemy/admin/clipboard_controller.rb +15 -11
- data/app/controllers/alchemy/admin/dashboard_controller.rb +2 -2
- data/app/controllers/alchemy/admin/elements_controller.rb +34 -32
- data/app/controllers/alchemy/admin/ingredients_controller.rb +1 -0
- data/app/controllers/alchemy/admin/languages_controller.rb +0 -3
- data/app/controllers/alchemy/admin/layoutpages_controller.rb +2 -1
- data/app/controllers/alchemy/admin/legacy_page_urls_controller.rb +1 -1
- data/app/controllers/alchemy/admin/nodes_controller.rb +24 -1
- data/app/controllers/alchemy/admin/pages_controller.rb +36 -42
- data/app/controllers/alchemy/admin/pictures_controller.rb +2 -5
- data/app/controllers/alchemy/admin/resources_controller.rb +1 -1
- data/app/controllers/alchemy/api/ingredients_controller.rb +1 -1
- data/app/controllers/alchemy/api/pages_controller.rb +5 -3
- data/app/controllers/alchemy/base_controller.rb +6 -6
- data/app/controllers/alchemy/pages_controller.rb +12 -6
- data/app/controllers/concerns/alchemy/admin/archive_overlay.rb +0 -1
- data/app/controllers/concerns/alchemy/admin/clipboard.rb +57 -0
- data/app/controllers/concerns/alchemy/admin/uploader_responses.rb +2 -2
- data/app/controllers/concerns/alchemy/site_redirects.rb +1 -1
- data/app/decorators/alchemy/ingredient_editor.rb +37 -4
- data/app/helpers/alchemy/admin/base_helper.rb +10 -6
- data/app/helpers/alchemy/admin/ingredients_helper.rb +6 -3
- data/app/helpers/alchemy/base_helper.rb +1 -1
- data/app/helpers/alchemy/pages_helper.rb +1 -1
- data/app/javascript/alchemy_admin/components/action.js +5 -1
- data/app/javascript/alchemy_admin/components/color_select.js +73 -0
- data/app/javascript/alchemy_admin/components/element_editor/delete_element_button.js +11 -3
- data/app/javascript/alchemy_admin/components/element_editor/publish_element_button.js +7 -2
- data/app/javascript/alchemy_admin/components/element_editor.js +11 -12
- data/app/javascript/alchemy_admin/components/element_select.js +39 -17
- data/app/javascript/alchemy_admin/components/elements_window.js +0 -2
- data/app/javascript/alchemy_admin/components/file_editor.js +26 -0
- data/app/javascript/alchemy_admin/components/index.js +9 -0
- data/app/javascript/alchemy_admin/components/list_filter.js +57 -8
- data/app/javascript/alchemy_admin/components/message.js +9 -3
- data/app/javascript/alchemy_admin/components/page_node.js +119 -0
- data/app/javascript/alchemy_admin/{page_publication_fields.js → components/page_publication_fields.js} +9 -8
- data/app/javascript/alchemy_admin/{picture_editors.js → components/picture_editor.js} +30 -45
- data/app/javascript/alchemy_admin/components/picture_thumbnail.js +107 -0
- data/app/javascript/alchemy_admin/components/publish_page_button.js +41 -0
- data/app/javascript/alchemy_admin/components/select.js +3 -1
- data/app/javascript/alchemy_admin/components/sitemap.js +210 -0
- data/app/javascript/alchemy_admin/{sortable_elements.js → components/sortable_elements.js} +22 -25
- data/app/javascript/alchemy_admin/components/tinymce.js +10 -5
- data/app/javascript/alchemy_admin/components/uploader.js +30 -0
- data/app/javascript/alchemy_admin/image_overlay.js +0 -2
- data/app/javascript/alchemy_admin/initializer.js +0 -3
- data/app/javascript/alchemy_admin/link_dialog.js +1 -6
- data/app/javascript/alchemy_admin/templates/compiled.js +1 -1
- data/app/javascript/alchemy_admin/utils/ajax.js +15 -3
- data/app/javascript/alchemy_admin.js +0 -6
- data/app/models/alchemy/attachment.rb +4 -4
- data/app/models/alchemy/element/definitions.rb +1 -2
- data/app/models/alchemy/element/element_ingredients.rb +6 -2
- data/app/models/alchemy/element.rb +54 -13
- data/app/models/alchemy/element_definition.rb +4 -1
- data/app/models/alchemy/elements_repository.rb +6 -0
- data/app/models/alchemy/folded_page.rb +2 -2
- data/app/models/alchemy/ingredient.rb +38 -1
- data/app/models/alchemy/ingredient_definition.rb +4 -1
- data/app/models/alchemy/ingredient_validator.rb +6 -2
- data/app/models/alchemy/ingredients/color.rb +10 -0
- data/app/models/alchemy/ingredients/headline.rb +2 -17
- data/app/models/alchemy/ingredients/picture.rb +4 -4
- data/app/models/alchemy/ingredients/select.rb +19 -0
- data/app/models/alchemy/language/code.rb +0 -1
- data/app/models/alchemy/node.rb +28 -1
- data/app/models/alchemy/page/page_naming.rb +0 -7
- data/app/models/alchemy/page/page_natures.rb +7 -3
- data/app/models/alchemy/page/page_scopes.rb +13 -1
- data/app/models/alchemy/page/publisher.rb +14 -2
- data/app/models/alchemy/page.rb +102 -23
- data/app/models/alchemy/page_definition.rb +4 -1
- data/app/models/alchemy/page_version.rb +22 -6
- data/app/models/alchemy/picture.rb +10 -11
- data/app/models/alchemy/picture_variant.rb +1 -3
- data/app/models/alchemy/resource.rb +1 -1
- data/app/models/alchemy/storage_adapter/active_storage.rb +14 -2
- data/app/models/alchemy/storage_adapter/dragonfly.rb +12 -0
- data/app/models/alchemy/storage_adapter.rb +2 -0
- data/app/models/concerns/alchemy/picture_thumbnails.rb +4 -4
- data/app/models/concerns/alchemy/publishable.rb +54 -0
- data/app/serializers/alchemy/page_tree_serializer.rb +11 -31
- data/app/services/alchemy/copy_page.rb +17 -0
- data/app/services/alchemy/duplicate_element.rb +1 -1
- data/app/services/alchemy/page_tree_preloader.rb +105 -0
- data/app/stylesheets/alchemy/_extends.scss +3 -9
- data/app/stylesheets/alchemy/_mixins.scss +3 -1
- data/app/stylesheets/alchemy/_themes.scss +19 -10
- data/app/stylesheets/alchemy/admin/archive.scss +1 -0
- data/app/stylesheets/alchemy/admin/base.scss +5 -2
- data/app/stylesheets/alchemy/admin/buttons.scss +3 -3
- data/app/stylesheets/alchemy/admin/element-select.scss +18 -0
- data/app/stylesheets/alchemy/admin/elements.scss +123 -23
- data/app/stylesheets/alchemy/admin/errors.scss +1 -1
- data/app/stylesheets/alchemy/admin/flash.scss +6 -4
- data/app/stylesheets/alchemy/admin/images.scss +9 -5
- data/app/stylesheets/alchemy/admin/list_filter.scss +4 -4
- data/app/stylesheets/alchemy/admin/navigation.scss +1 -1
- data/app/stylesheets/alchemy/admin/notices.scss +1 -2
- data/app/stylesheets/alchemy/admin/selects.scss +36 -21
- data/app/stylesheets/alchemy/admin/shoelace.scss +14 -1
- data/app/stylesheets/alchemy/admin/sitemap.scss +11 -3
- data/app/stylesheets/alchemy/admin/tags.scss +3 -1
- data/app/stylesheets/alchemy/admin/toolbar.scss +1 -1
- data/app/views/alchemy/_edit_mode.html.erb +1 -1
- data/app/views/alchemy/_menubar.html.erb +1 -1
- data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +35 -31
- data/app/views/alchemy/admin/attachments/_library_sidebar.html.erb +6 -0
- data/app/views/alchemy/admin/attachments/_overlay_file_list.html.erb +1 -1
- data/app/views/alchemy/admin/attachments/_replace_button.html.erb +1 -8
- data/app/views/alchemy/admin/attachments/_sorting_select.html.erb +13 -0
- data/app/views/alchemy/admin/attachments/_tag_list.html.erb +2 -3
- data/app/views/alchemy/admin/attachments/index.html.erb +5 -11
- data/app/views/alchemy/admin/attachments/show.html.erb +1 -1
- data/app/views/alchemy/admin/clipboard/_button.html.erb +1 -0
- data/app/views/alchemy/admin/clipboard/index.html.erb +4 -5
- data/app/views/alchemy/admin/clipboard/insert.turbo_stream.erb +1 -1
- data/app/views/alchemy/admin/crop.html.erb +5 -7
- data/app/views/alchemy/admin/dashboard/widgets/_locked_pages.html.erb +1 -1
- data/app/views/alchemy/admin/elements/_add_nested_element_form.html.erb +6 -6
- data/app/views/alchemy/admin/elements/_fixed_element.html.erb +1 -1
- data/app/views/alchemy/admin/elements/_footer.html.erb +7 -1
- data/app/views/alchemy/admin/elements/_header.html.erb +5 -5
- data/app/views/alchemy/admin/elements/_toolbar.html.erb +33 -8
- data/app/views/alchemy/admin/elements/create.turbo_stream.erb +10 -10
- data/app/views/alchemy/admin/elements/index.html.erb +29 -16
- data/app/views/alchemy/admin/elements/new.html.erb +2 -2
- data/app/views/alchemy/admin/ingredients/update.turbo_stream.erb +3 -5
- data/app/views/alchemy/admin/leave.html.erb +1 -1
- data/app/views/alchemy/admin/nodes/_node.html.erb +19 -0
- data/app/views/alchemy/admin/nodes/edit.html.erb +1 -1
- data/app/views/alchemy/admin/nodes/index.html.erb +3 -1
- data/app/views/alchemy/admin/nodes/new.html.erb +14 -1
- data/app/views/alchemy/admin/pages/_current_page.html.erb +3 -1
- data/app/views/alchemy/admin/pages/_form.html.erb +21 -9
- data/app/views/alchemy/admin/pages/_page_status.html.erb +1 -1
- data/app/views/alchemy/admin/pages/_publication_fields.html.erb +28 -26
- data/app/views/alchemy/admin/pages/_table.html.erb +0 -7
- data/app/views/alchemy/admin/pages/_toolbar.html.erb +3 -6
- data/app/views/alchemy/admin/pages/edit.html.erb +5 -11
- data/app/views/alchemy/admin/pages/flush.turbo_stream.erb +2 -0
- data/app/views/alchemy/admin/pages/fold.turbo_stream.erb +5 -0
- data/app/views/alchemy/admin/pages/index.html.erb +5 -3
- data/app/views/alchemy/admin/pages/new.html.erb +2 -12
- data/app/views/alchemy/admin/pages/publish.turbo_stream.erb +12 -0
- data/app/views/alchemy/admin/pages/tree.html.erb +13 -0
- data/app/views/alchemy/admin/pages/update.turbo_stream.erb +5 -16
- data/app/views/alchemy/admin/partials/_flash_notices.html.erb +1 -1
- data/app/views/alchemy/admin/partials/{_remote_search_form.html.erb → _overlay_search_form.html.erb} +1 -2
- data/app/views/alchemy/admin/partials/_paste_from_clipboard_form.html.erb +12 -0
- data/app/views/alchemy/admin/pictures/_archive_overlay.html.erb +24 -21
- data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +18 -26
- data/app/views/alchemy/admin/pictures/_picture.html.erb +11 -15
- data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +3 -6
- data/app/views/alchemy/admin/pictures/_tag_list.html.erb +2 -3
- data/app/views/alchemy/admin/pictures/index.html.erb +0 -1
- data/app/views/alchemy/admin/pictures/update.turbo_stream.erb +1 -1
- data/app/views/alchemy/admin/resources/_resource_usage_info.html.erb +1 -1
- data/app/views/alchemy/admin/resources/_tag_list.html.erb +2 -3
- data/app/views/alchemy/admin/styleguide/index.html.erb +25 -20
- data/app/views/alchemy/admin/tags/edit.html.erb +1 -1
- data/app/views/alchemy/admin/tinymce/_setup.html.erb +2 -2
- data/app/views/alchemy/admin/uploader/_button.html.erb +1 -15
- data/app/views/alchemy/attachments/show.html.erb +1 -1
- data/app/views/alchemy/base/permission_denied.js.erb +1 -1
- data/app/views/alchemy/ingredients/shared/_anchor.html.erb +9 -7
- data/app/views/alchemy/ingredients/shared/_link_tools.html.erb +12 -5
- data/app/views/alchemy/ingredients/shared/_picture_tools.html.erb +10 -11
- data/app/views/alchemy/language_links/_spacer.html.erb +1 -1
- data/app/views/alchemy/messages_mailer/new.html.erb +1 -1
- data/app/views/alchemy/welcome.html.erb +1 -1
- data/config/locales/alchemy.en.yml +12 -3
- data/config/routes.rb +2 -2
- data/db/migrate/20230123112425_add_searchable_to_alchemy_pages.rb +1 -1
- data/db/migrate/20230505132743_add_indexes_to_alchemy_pictures.rb +1 -1
- data/db/migrate/20231113104432_create_page_mutexes.rb +1 -1
- data/db/migrate/20240314105244_create_alchemy_picture_descriptions.rb +1 -1
- data/db/migrate/20250626160259_add_unique_index_to_picture_descriptions.rb +1 -1
- data/db/migrate/20250905140323_add_created_at_index_to_pictures_and_attachments.rb +1 -1
- data/db/migrate/20251106150010_convert_select_value_for_multiple.rb +11 -0
- data/db/migrate/20260102121232_add_metadata_to_page_versions.rb +9 -0
- data/db/migrate/20260115164704_add_publication_timestamps_to_alchemy_elements.rb +30 -0
- data/db/migrate/20260115164705_add_index_to_element_publication_timestamps.rb +13 -0
- data/lib/alchemy/ability_helper.rb +1 -3
- data/lib/alchemy/auth_accessors.rb +51 -117
- data/lib/alchemy/configuration.rb +1 -0
- data/lib/alchemy/configurations/main.rb +63 -0
- data/lib/alchemy/controller_actions.rb +2 -3
- data/lib/alchemy/engine.rb +9 -12
- data/lib/alchemy/error_tracking/error_logger.rb +1 -1
- data/lib/alchemy/errors.rb +1 -1
- data/lib/alchemy/logger.rb +34 -4
- data/lib/alchemy/name_conversions.rb +0 -6
- data/lib/alchemy/seeder.rb +2 -2
- data/lib/alchemy/tasks/usage.rb +4 -4
- data/lib/alchemy/test_support/factories/page_version_factory.rb +3 -0
- data/lib/alchemy/test_support/having_picture_thumbnails_examples.rb +30 -0
- data/lib/alchemy/test_support/shared_ingredient_editor_examples.rb +26 -6
- data/lib/alchemy/test_support/shared_publishable_examples.rb +114 -0
- data/lib/alchemy/upgrader/eight_one.rb +56 -0
- data/lib/alchemy/upgrader.rb +9 -1
- data/lib/alchemy/version.rb +1 -1
- data/lib/alchemy.rb +1 -4
- data/lib/alchemy_cms.rb +0 -1
- data/lib/generators/alchemy/elements/templates/view.html.erb +3 -3
- data/lib/generators/alchemy/ingredient/ingredient_generator.rb +6 -8
- data/lib/generators/alchemy/ingredient/templates/editor_component.rb.tt +22 -0
- data/lib/generators/alchemy/page_layouts/templates/layout.html.erb +1 -1
- data/lib/generators/alchemy/site_layouts/templates/layout.html.erb +1 -1
- data/lib/tasks/alchemy/upgrade.rake +21 -7
- data/vendor/javascript/shoelace.min.js +713 -31
- data/vendor/javascript/tinymce.min.js +1 -1
- metadata +104 -84
- data/app/decorators/alchemy/element_editor.rb +0 -90
- data/app/helpers/alchemy/admin/pictures_helper.rb +0 -14
- data/app/javascript/alchemy_admin/file_editors.js +0 -28
- data/app/javascript/alchemy_admin/image_loader.js +0 -54
- data/app/javascript/alchemy_admin/page_sorter.js +0 -71
- data/app/javascript/alchemy_admin/sitemap.js +0 -154
- data/app/javascript/alchemy_admin/templates/page_folder.hbs +0 -3
- data/app/views/alchemy/admin/attachments/archive_overlay.js.erb +0 -4
- data/app/views/alchemy/admin/pages/_page.html.erb +0 -163
- data/app/views/alchemy/admin/pages/_sitemap.html.erb +0 -30
- data/app/views/alchemy/admin/pages/flush.js.erb +0 -2
- data/app/views/alchemy/admin/pictures/archive_overlay.js.erb +0 -5
- data/app/views/alchemy/admin/pictures/index.js.erb +0 -2
- data/app/views/alchemy/ingredients/_audio_editor.html.erb +0 -5
- data/app/views/alchemy/ingredients/_boolean_editor.html.erb +0 -11
- data/app/views/alchemy/ingredients/_datetime_editor.html.erb +0 -20
- data/app/views/alchemy/ingredients/_file_editor.html.erb +0 -52
- data/app/views/alchemy/ingredients/_headline_editor.html.erb +0 -44
- data/app/views/alchemy/ingredients/_html_editor.html.erb +0 -8
- data/app/views/alchemy/ingredients/_link_editor.html.erb +0 -30
- data/app/views/alchemy/ingredients/_node_editor.html.erb +0 -13
- data/app/views/alchemy/ingredients/_number_editor.html.erb +0 -24
- data/app/views/alchemy/ingredients/_page_editor.html.erb +0 -13
- data/app/views/alchemy/ingredients/_picture_editor.html.erb +0 -59
- data/app/views/alchemy/ingredients/_richtext_editor.html.erb +0 -15
- data/app/views/alchemy/ingredients/_select_editor.html.erb +0 -31
- data/app/views/alchemy/ingredients/_text_editor.html.erb +0 -29
- data/app/views/alchemy/ingredients/_video_editor.html.erb +0 -5
- data/lib/generators/alchemy/ingredient/templates/editor.html.erb +0 -14
- /data/{lib → app/models}/alchemy/permissions.rb +0 -0
|
@@ -4,10 +4,11 @@ module Alchemy
|
|
|
4
4
|
module Admin
|
|
5
5
|
class PagesController < ResourcesController
|
|
6
6
|
include OnPageLayout::CallbacksRunner
|
|
7
|
+
include Alchemy::Admin::Clipboard
|
|
7
8
|
|
|
8
9
|
helper "alchemy/pages"
|
|
9
10
|
|
|
10
|
-
before_action :load_resource, except: [:index, :flush, :new, :create, :copy_language_tree, :link]
|
|
11
|
+
before_action :load_resource, except: [:index, :flush, :new, :create, :copy_language_tree, :link, :tree]
|
|
11
12
|
|
|
12
13
|
authorize_resource class: Alchemy::Page, except: [:index]
|
|
13
14
|
|
|
@@ -20,13 +21,9 @@ module Alchemy
|
|
|
20
21
|
before_action :set_translation,
|
|
21
22
|
except: [:show]
|
|
22
23
|
|
|
23
|
-
before_action :set_root_page,
|
|
24
|
-
only: [:index, :show]
|
|
25
|
-
|
|
26
24
|
before_action :set_preview_mode, only: [:show]
|
|
27
25
|
|
|
28
26
|
before_action :load_languages_and_layouts,
|
|
29
|
-
unless: -> { @page_root },
|
|
30
27
|
only: [:index]
|
|
31
28
|
|
|
32
29
|
before_action :set_view, only: [:index, :update]
|
|
@@ -62,13 +59,17 @@ module Alchemy
|
|
|
62
59
|
|
|
63
60
|
items = items.page(params[:page] || 1).per(items_per_page)
|
|
64
61
|
@pages = items
|
|
62
|
+
elsif @current_language.root_page
|
|
63
|
+
@root_page = @current_language.root_page
|
|
65
64
|
end
|
|
66
65
|
end
|
|
67
66
|
|
|
68
|
-
# Returns all pages as a tree from the root given by the id parameter
|
|
69
|
-
#
|
|
70
67
|
def tree
|
|
71
|
-
|
|
68
|
+
@root_page = Alchemy::PageTreePreloader.new(
|
|
69
|
+
page: @current_language.root_page,
|
|
70
|
+
user: current_alchemy_user,
|
|
71
|
+
admin_includes: true
|
|
72
|
+
).call
|
|
72
73
|
end
|
|
73
74
|
|
|
74
75
|
# Used by page preview iframe in Page#edit view.
|
|
@@ -89,8 +90,6 @@ module Alchemy
|
|
|
89
90
|
def new
|
|
90
91
|
@page ||= Page.new(layoutpage: params[:layoutpage] == "true", parent_id: params[:parent_id])
|
|
91
92
|
@page_layouts = Page.layouts_for_select(@current_language.id, layoutpages: @page.layoutpage?)
|
|
92
|
-
@clipboard = get_clipboard("pages")
|
|
93
|
-
@clipboard_items = Page.all_from_clipboard_for_select(@clipboard, @current_language.id, layoutpages: @page.layoutpage?)
|
|
94
93
|
end
|
|
95
94
|
|
|
96
95
|
def create
|
|
@@ -144,12 +143,8 @@ module Alchemy
|
|
|
144
143
|
if @view == "list"
|
|
145
144
|
flash[:notice] = @notice
|
|
146
145
|
end
|
|
147
|
-
|
|
148
|
-
unless @while_page_edit
|
|
149
|
-
@tree = serialized_page_tree
|
|
150
|
-
end
|
|
151
146
|
else
|
|
152
|
-
render :configure, status:
|
|
147
|
+
render :configure, status: 422
|
|
153
148
|
end
|
|
154
149
|
end
|
|
155
150
|
|
|
@@ -159,8 +154,7 @@ module Alchemy
|
|
|
159
154
|
flash[:notice] = Alchemy.t("Page deleted", name: @page.name)
|
|
160
155
|
|
|
161
156
|
# Remove page from clipboard
|
|
162
|
-
|
|
163
|
-
clipboard.delete_if { |item| item["id"] == @page.id.to_s }
|
|
157
|
+
remove_resource_from_clipboard(@page)
|
|
164
158
|
else
|
|
165
159
|
flash[:warning] = @page.errors.full_messages.to_sentence
|
|
166
160
|
end
|
|
@@ -178,8 +172,22 @@ module Alchemy
|
|
|
178
172
|
|
|
179
173
|
def fold
|
|
180
174
|
# @page is fetched via before filter
|
|
181
|
-
@page.
|
|
182
|
-
|
|
175
|
+
was_folded = @page.folded?(current_alchemy_user.id)
|
|
176
|
+
@page.fold!(current_alchemy_user.id, !was_folded)
|
|
177
|
+
|
|
178
|
+
respond_to do |format|
|
|
179
|
+
format.turbo_stream do
|
|
180
|
+
if was_folded
|
|
181
|
+
@page = PageTreePreloader.new(
|
|
182
|
+
page: @page,
|
|
183
|
+
user: current_alchemy_user,
|
|
184
|
+
admin_includes: true
|
|
185
|
+
).call
|
|
186
|
+
else
|
|
187
|
+
head 200
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
183
191
|
end
|
|
184
192
|
|
|
185
193
|
# Leaves the page editing mode and unlocks the page for other users
|
|
@@ -205,9 +213,6 @@ module Alchemy
|
|
|
205
213
|
def publish
|
|
206
214
|
# fetching page via before filter
|
|
207
215
|
@page.publish!
|
|
208
|
-
|
|
209
|
-
flash[:notice] = Alchemy.t(:page_published, name: @page.name)
|
|
210
|
-
redirect_back(fallback_location: admin_pages_path)
|
|
211
216
|
end
|
|
212
217
|
|
|
213
218
|
def copy_language_tree
|
|
@@ -217,8 +222,12 @@ module Alchemy
|
|
|
217
222
|
end
|
|
218
223
|
|
|
219
224
|
def flush
|
|
220
|
-
|
|
221
|
-
|
|
225
|
+
@current_language.pages.flushables.update_all(published_at: Time.current)
|
|
226
|
+
# We need to ensure, that also all layoutpages get the +published_at+ timestamp set,
|
|
227
|
+
# but not set to public true, because the cache_key for an element is +published_at+
|
|
228
|
+
# and we don't want the layout pages to be present in +Page.published+ scope.
|
|
229
|
+
@current_language.pages.flushable_layoutpages.update_all(published_at: Time.current)
|
|
230
|
+
respond_to { |format| format.turbo_stream }
|
|
222
231
|
end
|
|
223
232
|
|
|
224
233
|
private
|
|
@@ -309,30 +318,15 @@ module Alchemy
|
|
|
309
318
|
@page.locker.try!(:id) != current_alchemy_user.try!(:id)
|
|
310
319
|
end
|
|
311
320
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
parent = Page.find_by(id: params[:page][:parent_id])
|
|
316
|
-
Page.copy_and_paste(source, parent, params[:page][:name])
|
|
317
|
-
end
|
|
318
|
-
end
|
|
319
|
-
|
|
320
|
-
def set_root_page
|
|
321
|
-
@page_root = @current_language.root_page
|
|
321
|
+
# Overridden from Alchemy::Admin::Clipboard concern
|
|
322
|
+
def clipboard_items
|
|
323
|
+
@clipboard_items ||= Page.all_from_clipboard_for_select(clipboard, @current_language.id, layoutpages: @page.layoutpage?)
|
|
322
324
|
end
|
|
323
325
|
|
|
324
326
|
def set_page_version
|
|
325
327
|
@page_version = @page.draft_version
|
|
326
328
|
end
|
|
327
329
|
|
|
328
|
-
def serialized_page_tree
|
|
329
|
-
PageTreeSerializer.new(
|
|
330
|
-
@page,
|
|
331
|
-
ability: current_ability,
|
|
332
|
-
user: current_alchemy_user
|
|
333
|
-
)
|
|
334
|
-
end
|
|
335
|
-
|
|
336
330
|
def load_languages_and_layouts
|
|
337
331
|
@language = @current_language
|
|
338
332
|
@languages_with_page_tree = Language.on_current_site.with_root_page
|
|
@@ -8,8 +8,6 @@ module Alchemy
|
|
|
8
8
|
include CurrentLanguage
|
|
9
9
|
include PictureDescriptionsFormHelper
|
|
10
10
|
|
|
11
|
-
helper "alchemy/admin/tags"
|
|
12
|
-
|
|
13
11
|
before_action :load_resource,
|
|
14
12
|
only: [:edit, :update, :url, :destroy]
|
|
15
13
|
|
|
@@ -45,7 +43,7 @@ module Alchemy
|
|
|
45
43
|
@previous = @pictures.prev_page
|
|
46
44
|
@next = @pictures.next_page
|
|
47
45
|
|
|
48
|
-
@assignments = @picture.related_ingredients.joins(element: :page).merge(PageVersion.
|
|
46
|
+
@assignments = @picture.related_ingredients.joins(element: :page).merge(PageVersion.draft)
|
|
49
47
|
@picture_description = @picture.descriptions.find_or_initialize_by(
|
|
50
48
|
language_id: Alchemy::Current.language.id
|
|
51
49
|
)
|
|
@@ -66,7 +64,6 @@ module Alchemy
|
|
|
66
64
|
|
|
67
65
|
def create
|
|
68
66
|
@picture = Picture.new(picture_params)
|
|
69
|
-
@picture.name = @picture.humanized_name
|
|
70
67
|
if @picture.save
|
|
71
68
|
render successful_uploader_response(file: @picture)
|
|
72
69
|
else
|
|
@@ -91,7 +88,7 @@ module Alchemy
|
|
|
91
88
|
type: "error"
|
|
92
89
|
}
|
|
93
90
|
end
|
|
94
|
-
render :update, status: (@message[:type] == "notice") ?
|
|
91
|
+
render :update, status: (@message[:type] == "notice") ? 200 : 422
|
|
95
92
|
end
|
|
96
93
|
|
|
97
94
|
def update_multiple
|
|
@@ -9,7 +9,7 @@ module Alchemy
|
|
|
9
9
|
extend Alchemy::Admin::ResourceName
|
|
10
10
|
include Alchemy::Admin::ResourceFilter
|
|
11
11
|
|
|
12
|
-
helper Alchemy::ResourcesHelper
|
|
12
|
+
helper Alchemy::ResourcesHelper
|
|
13
13
|
helper_method :resource_handler, :items_per_page, :items_per_page_options
|
|
14
14
|
|
|
15
15
|
before_action :load_resource,
|
|
@@ -12,7 +12,7 @@ module Alchemy
|
|
|
12
12
|
if params[:page_id].present?
|
|
13
13
|
@ingredients = @ingredients
|
|
14
14
|
.where(alchemy_page_versions: {page_id: params[:page_id]})
|
|
15
|
-
.merge(Alchemy::PageVersion.
|
|
15
|
+
.merge(Alchemy::PageVersion.draft)
|
|
16
16
|
.joins(element: :page_version)
|
|
17
17
|
end
|
|
18
18
|
|
|
@@ -28,12 +28,14 @@ module Alchemy
|
|
|
28
28
|
def nested
|
|
29
29
|
@page = Page.find_by(id: params[:page_id]) || Language.current_root_page
|
|
30
30
|
|
|
31
|
+
# Preload the full tree from this page
|
|
32
|
+
preloaded_page = PageTreePreloader.new(page: @page, user: current_alchemy_user).call
|
|
33
|
+
|
|
31
34
|
render json: PageTreeSerializer.new(
|
|
32
|
-
|
|
35
|
+
preloaded_page,
|
|
33
36
|
ability: current_ability,
|
|
34
37
|
user: current_alchemy_user,
|
|
35
|
-
elements: params[:elements]
|
|
36
|
-
full: true
|
|
38
|
+
elements: params[:elements]
|
|
37
39
|
)
|
|
38
40
|
end
|
|
39
41
|
|
|
@@ -48,13 +48,13 @@ module Alchemy
|
|
|
48
48
|
|
|
49
49
|
def permission_denied(exception = nil)
|
|
50
50
|
if exception
|
|
51
|
-
|
|
51
|
+
Logger.debug <<-WARN.strip_heredoc
|
|
52
52
|
/!\\ Failed to permit #{exception.action} on #{exception.subject.inspect} for:
|
|
53
53
|
#{current_alchemy_user.inspect}
|
|
54
54
|
WARN
|
|
55
55
|
end
|
|
56
56
|
if request.format.json?
|
|
57
|
-
render json: {message: Alchemy.t("You are not authorized")}, status:
|
|
57
|
+
render json: {message: Alchemy.t("You are not authorized")}, status: 401
|
|
58
58
|
elsif current_alchemy_user
|
|
59
59
|
handle_redirect_for_user
|
|
60
60
|
else
|
|
@@ -67,7 +67,7 @@ module Alchemy
|
|
|
67
67
|
if can?(:index, :alchemy_admin_dashboard)
|
|
68
68
|
redirect_or_render_notice
|
|
69
69
|
else
|
|
70
|
-
redirect_to Alchemy.unauthorized_path
|
|
70
|
+
redirect_to Alchemy.config.unauthorized_path
|
|
71
71
|
end
|
|
72
72
|
end
|
|
73
73
|
|
|
@@ -95,14 +95,14 @@ module Alchemy
|
|
|
95
95
|
render :permission_denied
|
|
96
96
|
else
|
|
97
97
|
store_location
|
|
98
|
-
redirect_to Alchemy.login_path
|
|
98
|
+
redirect_to Alchemy.config.login_path
|
|
99
99
|
end
|
|
100
100
|
end
|
|
101
101
|
|
|
102
102
|
# Logs the current exception to the error log.
|
|
103
103
|
def exception_logger(error)
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
Logger.error("\n#{error.class} #{error.message} in #{error.backtrace.first}")
|
|
105
|
+
Logger.error(error.backtrace[1..50].each { |line|
|
|
106
106
|
line.gsub(/#{Rails.root}/, "")
|
|
107
107
|
}.join("\n"))
|
|
108
108
|
end
|
|
@@ -157,7 +157,7 @@ module Alchemy
|
|
|
157
157
|
|
|
158
158
|
# Redirects to given url with 301 status
|
|
159
159
|
def redirect_permanently_to(url)
|
|
160
|
-
redirect_to url, status:
|
|
160
|
+
redirect_to url, status: 301
|
|
161
161
|
end
|
|
162
162
|
|
|
163
163
|
# Returns url parameters that are not internal show page params.
|
|
@@ -208,14 +208,20 @@ module Alchemy
|
|
|
208
208
|
end
|
|
209
209
|
|
|
210
210
|
def signup_required?
|
|
211
|
-
if Alchemy.user_class.respond_to?(:admins)
|
|
212
|
-
Alchemy.user_class.admins.empty?
|
|
211
|
+
if Alchemy.config.user_class.respond_to?(:admins)
|
|
212
|
+
Alchemy.config.user_class.admins.empty?
|
|
213
213
|
end
|
|
214
214
|
end
|
|
215
215
|
|
|
216
216
|
# Returns the etag used for response headers.
|
|
217
217
|
#
|
|
218
|
-
#
|
|
218
|
+
# The etag is composed of:
|
|
219
|
+
# - The page's cache key (includes updated_at timestamp)
|
|
220
|
+
# - Published element IDs (changes when elements enter/leave the published scope)
|
|
221
|
+
# - The current user's cache key (for user-specific content)
|
|
222
|
+
#
|
|
223
|
+
# This ensures HTTP caches invalidate when scheduled elements become visible
|
|
224
|
+
# or hidden, even though the page's updated_at hasn't changed.
|
|
219
225
|
#
|
|
220
226
|
# IMPORTANT:
|
|
221
227
|
#
|
|
@@ -224,7 +230,8 @@ module Alchemy
|
|
|
224
230
|
# Otherwise all users will see the same cached page, regardless of user's state.
|
|
225
231
|
#
|
|
226
232
|
def page_etag
|
|
227
|
-
|
|
233
|
+
elements_cache_key = @page.public_version&.elements&.published&.order(:id)&.pluck(:id)
|
|
234
|
+
[@page, elements_cache_key, current_alchemy_user]
|
|
228
235
|
end
|
|
229
236
|
|
|
230
237
|
# We only render the page if either the cache is disabled for this page
|
|
@@ -233,7 +240,6 @@ module Alchemy
|
|
|
233
240
|
def render_fresh_page?
|
|
234
241
|
must_not_cache? || stale?(
|
|
235
242
|
etag: page_etag,
|
|
236
|
-
last_modified: @page.last_modified_at,
|
|
237
243
|
public: !@page.restricted,
|
|
238
244
|
template: "pages/show"
|
|
239
245
|
)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Clipboard functionality for Alchemy admin controllers.
|
|
4
|
+
module Alchemy::Admin::Clipboard
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
helper_method :clipboard, :clipboard_empty?, :clipboard_items
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Checks if clipboard for given category is blank
|
|
12
|
+
def clipboard_empty?(category)
|
|
13
|
+
clipboard.blank?
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
# Returns clipboard items for given category
|
|
19
|
+
def get_clipboard(category)
|
|
20
|
+
session[:alchemy_clipboard] ||= {}
|
|
21
|
+
session[:alchemy_clipboard][category.to_s] ||= []
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def clipboard_type
|
|
25
|
+
controller_name
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def clipboard
|
|
29
|
+
@clipboard ||= get_clipboard(clipboard_type)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Overridden in some controllers which use a different scope/parameters
|
|
33
|
+
def clipboard_items
|
|
34
|
+
@clipboard_items ||= model_class.all_from_clipboard(clipboard)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def item_from_clipboard
|
|
38
|
+
@item_from_clipboard ||= clipboard.detect { |item| item["id"].to_i == params[:paste_from_clipboard].to_i }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def paste_from_clipboard
|
|
42
|
+
if params[:paste_from_clipboard]
|
|
43
|
+
source = model_class.find(params[:paste_from_clipboard])
|
|
44
|
+
parent = model_class.find_by(id: resource_params[:parent_id]) if resource_params[:parent_id]
|
|
45
|
+
model_class.copy_and_paste(source, parent, params.dig(clipboard_type.singularize.to_sym, :name))
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def model_class
|
|
50
|
+
"alchemy/#{clipboard_type.singularize}".classify.constantize
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def remove_resource_from_clipboard(resource)
|
|
54
|
+
clipboard = get_clipboard(clipboard_type)
|
|
55
|
+
clipboard.delete_if { |item| item["id"] == resource.id.to_s }
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -5,7 +5,7 @@ module Alchemy
|
|
|
5
5
|
module UploaderResponses
|
|
6
6
|
extend ActiveSupport::Concern
|
|
7
7
|
|
|
8
|
-
def successful_uploader_response(file:, status:
|
|
8
|
+
def successful_uploader_response(file:, status: 201)
|
|
9
9
|
message = Alchemy.t(:upload_success,
|
|
10
10
|
scope: [:uploader, file.class.model_name.i18n_key],
|
|
11
11
|
name: file.name)
|
|
@@ -24,7 +24,7 @@ module Alchemy
|
|
|
24
24
|
|
|
25
25
|
{
|
|
26
26
|
json: {message: message},
|
|
27
|
-
status:
|
|
27
|
+
status: 422
|
|
28
28
|
}
|
|
29
29
|
end
|
|
30
30
|
end
|
|
@@ -12,7 +12,7 @@ module Alchemy
|
|
|
12
12
|
private
|
|
13
13
|
|
|
14
14
|
def enforce_primary_host_for_site
|
|
15
|
-
redirect_to url_for(host: current_alchemy_site.host), status:
|
|
15
|
+
redirect_to url_for(host: current_alchemy_site.host), status: 301, allow_other_host: true
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def needs_redirect_to_primary_host?
|
|
@@ -4,9 +4,11 @@ module Alchemy
|
|
|
4
4
|
class IngredientEditor < SimpleDelegator
|
|
5
5
|
alias_method :ingredient, :__getobj__
|
|
6
6
|
|
|
7
|
+
# @deprecated
|
|
7
8
|
def to_partial_path
|
|
8
9
|
"alchemy/ingredients/#{partial_name}_editor"
|
|
9
10
|
end
|
|
11
|
+
deprecate :to_partial_path, deprecator: Alchemy::Deprecation
|
|
10
12
|
|
|
11
13
|
# Returns the translated role for displaying in labels
|
|
12
14
|
#
|
|
@@ -23,6 +25,7 @@ module Alchemy
|
|
|
23
25
|
# article:
|
|
24
26
|
# foo: Baz
|
|
25
27
|
#
|
|
28
|
+
# @deprecated
|
|
26
29
|
def translated_role
|
|
27
30
|
Alchemy.t(
|
|
28
31
|
role,
|
|
@@ -30,7 +33,9 @@ module Alchemy
|
|
|
30
33
|
default: Alchemy.t("ingredient_roles.#{role}", default: role.humanize)
|
|
31
34
|
)
|
|
32
35
|
end
|
|
36
|
+
deprecate translated_role: "Use Ingredient#translated_role instead", deprecator: Alchemy::Deprecation
|
|
33
37
|
|
|
38
|
+
# @deprecated
|
|
34
39
|
def css_classes
|
|
35
40
|
[
|
|
36
41
|
"ingredient-editor",
|
|
@@ -42,13 +47,16 @@ module Alchemy
|
|
|
42
47
|
settings[:anchor] ? "with-anchor" : nil
|
|
43
48
|
].compact
|
|
44
49
|
end
|
|
50
|
+
deprecate :css_classes, deprecator: Alchemy::Deprecation
|
|
45
51
|
|
|
52
|
+
# @deprecated
|
|
46
53
|
def data_attributes
|
|
47
54
|
{
|
|
48
55
|
ingredient_id: id,
|
|
49
56
|
ingredient_role: role
|
|
50
57
|
}
|
|
51
58
|
end
|
|
59
|
+
deprecate :data_attributes, deprecator: Alchemy::Deprecation
|
|
52
60
|
|
|
53
61
|
# Returns a string to be passed to Rails form field tags to ensure it can be used with Rails' nested attributes.
|
|
54
62
|
#
|
|
@@ -64,17 +72,20 @@ module Alchemy
|
|
|
64
72
|
#
|
|
65
73
|
# <%= text_field_tag text_editor.form_field_name(:link), text_editor.value %>
|
|
66
74
|
#
|
|
75
|
+
# @deprecated
|
|
67
76
|
def form_field_name(column = "value")
|
|
68
77
|
"element[ingredients_attributes][#{form_field_counter}][#{column}]"
|
|
69
78
|
end
|
|
79
|
+
deprecate :form_field_name, deprecator: Alchemy::Deprecation
|
|
70
80
|
|
|
71
81
|
# Returns a unique string to be passed to a form field id.
|
|
72
82
|
#
|
|
73
83
|
# @param column [String] A Ingredient column_name. Default is 'value'
|
|
74
|
-
#
|
|
84
|
+
# @deprecated
|
|
75
85
|
def form_field_id(column = "value")
|
|
76
86
|
"element_#{element.id}_ingredient_#{id}_#{column}"
|
|
77
87
|
end
|
|
88
|
+
deprecate :form_field_id, deprecator: Alchemy::Deprecation
|
|
78
89
|
|
|
79
90
|
# Fixes Rails partial renderer calling to_model on the object
|
|
80
91
|
# which reveals the delegated ingredient instead of this decorator.
|
|
@@ -84,29 +95,38 @@ module Alchemy
|
|
|
84
95
|
super
|
|
85
96
|
end
|
|
86
97
|
|
|
98
|
+
# @deprecated
|
|
87
99
|
def has_warnings?
|
|
88
100
|
definition.blank? || deprecated?
|
|
89
101
|
end
|
|
102
|
+
deprecate :has_warnings?, deprecator: Alchemy::Deprecation
|
|
90
103
|
|
|
104
|
+
# @deprecated
|
|
91
105
|
def linked?
|
|
92
106
|
link.try(:present?)
|
|
93
107
|
end
|
|
108
|
+
deprecate :linked?, deprecator: Alchemy::Deprecation
|
|
94
109
|
|
|
110
|
+
# @deprecated
|
|
95
111
|
def warnings
|
|
96
112
|
return unless has_warnings?
|
|
97
113
|
|
|
98
114
|
if definition.blank?
|
|
99
|
-
Logger.warn("ingredient #{role} is missing its definition"
|
|
115
|
+
Logger.warn("ingredient '#{role}' is missing its definition! Please check your element definitions.")
|
|
100
116
|
Alchemy.t(:ingredient_definition_missing)
|
|
101
117
|
else
|
|
102
118
|
definition.deprecation_notice(element_name: element&.name)
|
|
103
119
|
end
|
|
104
120
|
end
|
|
121
|
+
deprecate :warnings, deprecator: Alchemy::Deprecation
|
|
105
122
|
|
|
123
|
+
# @deprecated
|
|
106
124
|
def validations
|
|
107
125
|
definition.validate
|
|
108
126
|
end
|
|
127
|
+
deprecate :validations, deprecator: Alchemy::Deprecation
|
|
109
128
|
|
|
129
|
+
# @deprecated
|
|
110
130
|
def format_validation
|
|
111
131
|
format = validations.select { _1.is_a?(Hash) }.find { _1[:format] }&.fetch(:format)
|
|
112
132
|
return nil unless format
|
|
@@ -118,15 +138,28 @@ module Alchemy
|
|
|
118
138
|
format
|
|
119
139
|
end
|
|
120
140
|
end
|
|
141
|
+
deprecate :format_validation, deprecator: Alchemy::Deprecation
|
|
121
142
|
|
|
143
|
+
# @deprecated
|
|
122
144
|
def length_validation
|
|
123
145
|
validations.select { _1.is_a?(Hash) }.find { _1[:length] }&.fetch(:length)
|
|
124
146
|
end
|
|
147
|
+
deprecate :length_validation, deprecator: Alchemy::Deprecation
|
|
125
148
|
|
|
149
|
+
# @deprecated
|
|
126
150
|
def presence_validation?
|
|
127
|
-
validations.
|
|
128
|
-
|
|
151
|
+
validations.any? do |validation|
|
|
152
|
+
case validation
|
|
153
|
+
when :presence, "presence"
|
|
154
|
+
true
|
|
155
|
+
when Hash
|
|
156
|
+
validation[:presence] == true || validation["presence"] == true
|
|
157
|
+
else
|
|
158
|
+
false
|
|
159
|
+
end
|
|
160
|
+
end
|
|
129
161
|
end
|
|
162
|
+
deprecate :presence_validation?, deprecator: Alchemy::Deprecation
|
|
130
163
|
|
|
131
164
|
private
|
|
132
165
|
|
|
@@ -57,10 +57,14 @@ module Alchemy
|
|
|
57
57
|
if html_options[:title]
|
|
58
58
|
tooltip = html_options.delete(:title)
|
|
59
59
|
end
|
|
60
|
-
anchor =
|
|
61
|
-
"
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
anchor = if url.nil?
|
|
61
|
+
tag.a(content, class: "disabled #{html_options[:class]}".strip, tabindex: "-1")
|
|
62
|
+
else
|
|
63
|
+
link_to(content, url, html_options.merge(
|
|
64
|
+
"data-dialog-options" => options.to_json,
|
|
65
|
+
:is => "alchemy-dialog-link"
|
|
66
|
+
))
|
|
67
|
+
end
|
|
64
68
|
if tooltip
|
|
65
69
|
content_tag("sl-tooltip", anchor, content: tooltip)
|
|
66
70
|
else
|
|
@@ -285,9 +289,9 @@ module Alchemy
|
|
|
285
289
|
# @param icon: 'alert' [String] - Icon name
|
|
286
290
|
#
|
|
287
291
|
# @return [String]
|
|
288
|
-
def hint_with_tooltip(text, icon: "alert")
|
|
292
|
+
def hint_with_tooltip(text, icon: "alert", icon_class: nil)
|
|
289
293
|
content_tag :"sl-tooltip", class: "like-hint-tooltip", content: text, placement: "bottom" do
|
|
290
|
-
render_icon(icon)
|
|
294
|
+
render_icon(icon, class: icon_class)
|
|
291
295
|
end
|
|
292
296
|
end
|
|
293
297
|
|
|
@@ -9,8 +9,8 @@ module Alchemy
|
|
|
9
9
|
#
|
|
10
10
|
# Displays a warning icon if ingredient is missing its definition.
|
|
11
11
|
#
|
|
12
|
-
# Displays a mandatory field indicator, if the ingredient has
|
|
13
|
-
#
|
|
12
|
+
# Displays a mandatory field indicator, if the ingredient has a presence validation.
|
|
13
|
+
# @deprecated
|
|
14
14
|
def render_ingredient_role(ingredient)
|
|
15
15
|
if ingredient.blank?
|
|
16
16
|
warning("Ingredient is nil")
|
|
@@ -24,14 +24,16 @@ module Alchemy
|
|
|
24
24
|
content = "#{icon} #{content}".html_safe
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
if ingredient.
|
|
27
|
+
if ingredient.presence_validation?
|
|
28
28
|
"#{content}<span class='validation_indicator'>*</span>".html_safe
|
|
29
29
|
else
|
|
30
30
|
content
|
|
31
31
|
end
|
|
32
32
|
end
|
|
33
|
+
deprecate :render_ingredient_role, deprecator: Alchemy::Deprecation
|
|
33
34
|
|
|
34
35
|
# Renders the label and hint for a ingredient.
|
|
36
|
+
# @deprecated
|
|
35
37
|
def ingredient_label(ingredient, column = :value, html_options = {})
|
|
36
38
|
label_tag ingredient.form_field_id(column), html_options do
|
|
37
39
|
[
|
|
@@ -40,6 +42,7 @@ module Alchemy
|
|
|
40
42
|
].compact.join(" ").html_safe
|
|
41
43
|
end
|
|
42
44
|
end
|
|
45
|
+
deprecate :ingredient_label, deprecator: Alchemy::Deprecation
|
|
43
46
|
end
|
|
44
47
|
end
|
|
45
48
|
end
|
|
@@ -5,7 +5,7 @@ module Alchemy
|
|
|
5
5
|
# Logs a message in the Rails logger (warn level)
|
|
6
6
|
# and optionally displays an error message to the user.
|
|
7
7
|
def warning(message, text = nil)
|
|
8
|
-
Logger.warn(message
|
|
8
|
+
Logger.warn(message)
|
|
9
9
|
unless text.nil?
|
|
10
10
|
render_message(:warning) do
|
|
11
11
|
text.html_safe
|
|
@@ -2,6 +2,7 @@ import { reloadPreview } from "alchemy_admin/components/preview_window"
|
|
|
2
2
|
import { removeTab } from "alchemy_admin/fixed_elements"
|
|
3
3
|
import { closeCurrentDialog } from "alchemy_admin/dialog"
|
|
4
4
|
import IngredientAnchorLink from "alchemy_admin/ingredient_anchor_link"
|
|
5
|
+
import pleaseWaitOverlay from "alchemy_admin/please_wait_overlay"
|
|
5
6
|
|
|
6
7
|
class Action extends HTMLElement {
|
|
7
8
|
constructor() {
|
|
@@ -15,7 +16,10 @@ class Action extends HTMLElement {
|
|
|
15
16
|
closeCurrentDialog,
|
|
16
17
|
reloadPreview,
|
|
17
18
|
removeFixedElement: removeTab,
|
|
18
|
-
updateAnchorIcon: IngredientAnchorLink.updateIcon
|
|
19
|
+
updateAnchorIcon: IngredientAnchorLink.updateIcon,
|
|
20
|
+
hidePleaseWaitOverlay() {
|
|
21
|
+
pleaseWaitOverlay(false)
|
|
22
|
+
}
|
|
19
23
|
}
|
|
20
24
|
}
|
|
21
25
|
|