From e5f6f9c7831682ab972814458232965b76f949f7 Mon Sep 17 00:00:00 2001
From: Thomas von Deyen
Date: Fri, 22 Mar 2024 14:59:40 +0100
Subject: [PATCH] Use Turbo Frame for elements_window
For now we need to disable the submit buttons inside,
because we still use Rails UJS and the remote forms
feature that uses js.erb responses from the controller.
Those need to be refactored into Turbo Streams, but
this is too much for now.
---
app/assets/javascripts/alchemy/admin.js | 1 -
.../alchemy/alchemy.elements_window.js.coffee | 108 ------------------
app/assets/stylesheets/alchemy/elements.scss | 3 +-
app/javascript/alchemy_admin.js | 1 +
.../components/elements_window.js | 86 ++++++++++++++
.../_add_nested_element_form.html.erb | 2 +-
.../alchemy/admin/elements/_footer.html.erb | 2 +-
.../alchemy/admin/elements/_toolbar.html.erb | 3 +-
.../alchemy/admin/elements/index.html.erb | 104 +++++++++++------
app/views/alchemy/admin/pages/edit.html.erb | 46 +-------
10 files changed, 167 insertions(+), 189 deletions(-)
delete mode 100644 app/assets/javascripts/alchemy/alchemy.elements_window.js.coffee
create mode 100644 app/javascript/alchemy_admin/components/elements_window.js
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 %>
-
+
<%= Alchemy.t(:save) %>
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 %>
+
+
+ <% 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 %>