diff --git a/app/assets/javascripts/alchemy/admin.js b/app/assets/javascripts/alchemy/admin.js index 597bfed13d..98c553cc1a 100644 --- a/app/assets/javascripts/alchemy/admin.js +++ b/app/assets/javascripts/alchemy/admin.js @@ -6,7 +6,6 @@ //= require alchemy/templates //= require alchemy/alchemy.dialog //= require alchemy/alchemy.confirm_dialog -//= require alchemy/alchemy.elements_window //= require alchemy/alchemy.fixed_elements //= require alchemy/alchemy.image_overlay //= require alchemy/alchemy.link_dialog diff --git a/app/assets/javascripts/alchemy/alchemy.elements_window.js.coffee b/app/assets/javascripts/alchemy/alchemy.elements_window.js.coffee deleted file mode 100644 index cd0b617b20..0000000000 --- a/app/assets/javascripts/alchemy/alchemy.elements_window.js.coffee +++ /dev/null @@ -1,108 +0,0 @@ -window.Alchemy = {} if typeof(window.Alchemy) is 'undefined' - -# Adds buttons into a toolbar inside of overlay windows -Alchemy.ToolbarButton = (options) -> - $btn = $("") - if options.align - $btn.addClass(options.class) - if options.buttonId - $btn.attr(id: options.buttonId) - $lnk = $("") - if options.hotkey - $lnk.attr('data-alchemy-hotkey', options.hotkey) - $lnk.on "click", (e) -> - e.preventDefault() - options.onClick(e) - return - $lnk.append "" - $btn.append $lnk - $btn - -Alchemy.ElementsWindow = - - init: (url, options, callback) -> - @hidden = false - @$body = $('body') - @element_window = $('
') - @element_area = $('
') - @url = url - @options = options - @callback = callback - @element_window.append @createToolbar(options.toolbarButtons) - @element_window.append @element_area - Alchemy.GUI.init(@element_window) - @button = $('#element_window_button') - @button.on "click", => - @hide() - false - - window.requestAnimationFrame => - spinner = new Alchemy.Spinner('medium') - spinner.spin @element_area[0] - - window.addEventListener 'message', (event) => - data = event.data - if data?.message == 'Alchemy.focusElementEditor' - element = document.getElementById("element_#{data.element_id}") - Alchemy.ElementsWindow.show() - element?.focusElement() - true - - @$body.on "click", (evt) => - unless evt.target.closest(".element-editor") - @element_area.find('.element-editor').removeClass('selected') - Alchemy.PreviewWindow.postMessage(message: 'Alchemy.blurElements') - return - - $('#main_content').append(@element_window) - @show() - @reload() - - createToolbar: (buttons) -> - @toolbar = $('
') - buttons.push - label: Alchemy.t("Collapse all elements") - iconClass: "contract-up-down-line" - align: "end" - class: "right" - onClick: => - $("alchemy-element-editor:not([compact]):not([fixed])").each () -> - @collapse() - for btn in buttons - @toolbar.append Alchemy.ToolbarButton(btn) - @toolbar.append @collapseAllBtn - - reload: -> - $.get @url, (data) => - @element_area.html data - Alchemy.SortableElements() - if @callback - @callback.call() - .fail (xhr, status, error) => - Alchemy.Dialog::show_error(xhr, error, @element_area) - - hide: -> - @$body.removeClass('elements-window-visible'); - @hidden = true - @toggleButton() - - show: -> - @$body.addClass('elements-window-visible'); - @hidden = false - @toggleButton() - - toggleButton: -> - if @hidden - @button.find('label').text(@options.texts.showElements) - @button.find('alchemy-icon').attr("name", "menu-fold") - @button.off('click') - @button.on "click", => - @show() - false - else - @button.find('label').text(@options.texts.hideElements) - @button.find('alchemy-icon').attr("name", "menu-unfold") - @button.off('click') - @button.on "click", => - @hide() - false diff --git a/app/assets/stylesheets/alchemy/elements.scss b/app/assets/stylesheets/alchemy/elements.scss index 206cbc55a4..6677d68fa3 100644 --- a/app/assets/stylesheets/alchemy/elements.scss +++ b/app/assets/stylesheets/alchemy/elements.scss @@ -1,8 +1,9 @@ -#alchemy_elements_window { +alchemy-elements-window { position: absolute; right: 0; top: $top-menu-height; z-index: 20; + display: block; width: calc(100vw - #{$collapsed-main-menu-width}); height: calc(100vh - #{$top-menu-height}); border-left: $default-border; diff --git a/app/javascript/alchemy_admin.js b/app/javascript/alchemy_admin.js index 0e94f13757..be1a37835a 100644 --- a/app/javascript/alchemy_admin.js +++ b/app/javascript/alchemy_admin.js @@ -26,6 +26,7 @@ import "alchemy_admin/components/clipboard_button" import "alchemy_admin/components/datepicker" import "alchemy_admin/components/dialog_link" import "alchemy_admin/components/element_editor" +import "alchemy_admin/components/elements_window" import "alchemy_admin/components/message" import "alchemy_admin/components/growl" import "alchemy_admin/components/icon" diff --git a/app/javascript/alchemy_admin/components/elements_window.js b/app/javascript/alchemy_admin/components/elements_window.js new file mode 100644 index 0000000000..bbb09694eb --- /dev/null +++ b/app/javascript/alchemy_admin/components/elements_window.js @@ -0,0 +1,86 @@ +class ElementsWindow extends HTMLElement { + #visible = true + + constructor() { + super() + this.#attachEvents() + } + + connectedCallback() { + document.body.classList.add("elements-window-visible") + this.toggleButton?.addEventListener("click", (evt) => { + evt.preventDefault() + this.toggle() + }) + if (window.location.hash) { + document + .querySelector(window.location.hash) + ?.trigger("FocusElementEditor.Alchemy") + } + Alchemy.SortableElements() + } + + collapseAllElements() { + this.querySelectorAll( + "alchemy-element-editor:not([compact]):not([fixed])" + ).forEach((editor) => editor.collapse()) + } + + toggle() { + if (this.#visible) { + this.hide() + } else { + this.show() + } + } + + show() { + document.body.classList.add("elements-window-visible") + this.#visible = true + this.toggleButton.closest("sl-tooltip").content = Alchemy.t("Hide elements") + this.toggleButton + .querySelector("alchemy-icon") + .setAttribute("name", "menu-unfold") + } + + hide() { + document.body.classList.remove("elements-window-visible") + this.#visible = false + this.toggleButton.closest("sl-tooltip").content = Alchemy.t("Show elements") + this.toggleButton + .querySelector("alchemy-icon") + .setAttribute("name", "menu-fold") + } + + get collapseButton() { + return this.querySelector("#collapse-all-elements-button") + } + + get toggleButton() { + return document.querySelector("#element_window_button") + } + + #attachEvents() { + this.collapseButton?.addEventListener("click", () => { + this.collapseAllElements() + }) + window.addEventListener("message", (event) => { + const data = event.data + if (data?.message == "Alchemy.focusElementEditor") { + const element = document.getElementById(`element_${data.element_id}`) + this.show() + element?.focusElement() + } + }) + document.body.addEventListener("click", (evt) => { + if (!evt.target.closest("alchemy-element-editor")) { + this.querySelectorAll("alchemy-element-editor").forEach((editor) => { + editor.classList.remove("selected") + }) + Alchemy.PreviewWindow.postMessage({ message: "Alchemy.blurElements" }) + } + }) + } +} + +customElements.define("alchemy-elements-window", ElementsWindow) diff --git a/app/views/alchemy/admin/elements/_add_nested_element_form.html.erb b/app/views/alchemy/admin/elements/_add_nested_element_form.html.erb index 4b355ba722..b7dbb2fd3d 100644 --- a/app/views/alchemy/admin/elements/_add_nested_element_form.html.erb +++ b/app/views/alchemy/admin/elements/_add_nested_element_form.html.erb @@ -8,7 +8,7 @@ <%= f.hidden_field :name %> <%= f.hidden_field :page_version_id, value: element.page_version_id %> <%= f.hidden_field :parent_element_id, value: element.id %> - <% end %> diff --git a/app/views/alchemy/admin/elements/_footer.html.erb b/app/views/alchemy/admin/elements/_footer.html.erb index 43e9c03608..ce1eae67b7 100644 --- a/app/views/alchemy/admin/elements/_footer.html.erb +++ b/app/views/alchemy/admin/elements/_footer.html.erb @@ -5,7 +5,7 @@

<% end %> -
diff --git a/app/views/alchemy/admin/elements/_toolbar.html.erb b/app/views/alchemy/admin/elements/_toolbar.html.erb index d3387bcad9..e900d0433c 100644 --- a/app/views/alchemy/admin/elements/_toolbar.html.erb +++ b/app/views/alchemy/admin/elements/_toolbar.html.erb @@ -23,7 +23,8 @@ render_icon('delete-bin-2'), Alchemy.t(:confirm_to_delete_element), alchemy.admin_element_path(element), - class: "icon_button" + class: "icon_button", + data: {turbo: false} ) -%> diff --git a/app/views/alchemy/admin/elements/index.html.erb b/app/views/alchemy/admin/elements/index.html.erb index 41d1914bca..9ce2c9cd27 100644 --- a/app/views/alchemy/admin/elements/index.html.erb +++ b/app/views/alchemy/admin/elements/index.html.erb @@ -1,36 +1,72 @@ -<% if @fixed_elements.any? %> - - - <%= Alchemy.t(:main_content) %> - - <% @fixed_elements.each do |element| %> - - <%= element.display_name %> - +<%= turbo_frame_tag "alchemy_elements_window" do %> + +
+ <%= toolbar_button( + url: alchemy.new_admin_element_path(page_version_id: @page_version.id), + icon: :add, + hotkey: "alt+n", + label: Alchemy.t("New Element"), + dialog_options: { + title: Alchemy.t("New Element"), + size: "320x125" + }, + if_permitted_to: [:create, Alchemy::Element] + ) %> + <%= toolbar_button( + url: alchemy.admin_clipboard_path(remarkable_type: "elements"), + label: Alchemy.t("Show clipboard"), + icon: :clipboard, + icon_style: clipboard_empty?("elements") ? "line" : "fill", + dialog_options: { + title: Alchemy.t("Clipboard"), + size: "400x305" + }, + link_options: { + id: "clipboard_button" + }, + if_permitted_to: [:show, :alchemy_clipboard] + ) %> + " placement="top-end" class="right"> + + +
+ <% if @fixed_elements.any? %> + + + <%= Alchemy.t(:main_content) %> + + <% @fixed_elements.each do |element| %> + + <%= element.display_name %> + + <% end %> + + <%= render @elements.map { |element| Alchemy::ElementEditor.new(element) } %> + + <% @fixed_elements.each do |element| %> + + <%= render Alchemy::ElementEditor.new(element) %> + + <% end %> + + <% else %> +
+ <%= render @elements.map { |element| Alchemy::ElementEditor.new(element) } %> +
<% end %> - - <%= render @elements.map { |element| Alchemy::ElementEditor.new(element) } %> - - <% @fixed_elements.each do |element| %> - - <%= render Alchemy::ElementEditor.new(element) %> - - <% end %> -
-<% else %> -
- <%= render @elements.map { |element| Alchemy::ElementEditor.new(element) } %> -
+ <% end %> diff --git a/app/views/alchemy/admin/pages/edit.html.erb b/app/views/alchemy/admin/pages/edit.html.erb index 005ed85227..8083bb7c29 100644 --- a/app/views/alchemy/admin/pages/edit.html.erb +++ b/app/views/alchemy/admin/pages/edit.html.erb @@ -131,6 +131,10 @@ <% end %> +<%= turbo_frame_tag "alchemy_elements_window", src: alchemy.admin_elements_path(page_version_id: @page_version.id) do %> + +<% end %> + <% content_for :javascripts do %>