Skip to content

Commit

Permalink
Merge pull request #2802 from AlchemyCMS/preview-window-component
Browse files Browse the repository at this point in the history
Convert Preview Window into web component
  • Loading branch information
tvdeyen authored Mar 25, 2024
2 parents 349b22a + 9de5715 commit f296074
Show file tree
Hide file tree
Showing 14 changed files with 190 additions and 131 deletions.
1 change: 0 additions & 1 deletion app/assets/javascripts/alchemy/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,3 @@
//= require alchemy/alchemy.fixed_elements
//= require alchemy/alchemy.image_overlay
//= require alchemy/alchemy.link_dialog
//= require alchemy/alchemy.preview_window
82 changes: 0 additions & 82 deletions app/assets/javascripts/alchemy/alchemy.preview_window.js.coffee

This file was deleted.

1 change: 1 addition & 0 deletions app/controllers/alchemy/admin/pages_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ def edit
klass.new(routes: Alchemy::Engine.routes).url_for(@page)
]
end
@preview_url = @preview_urls.first.last
@layoutpage = @page.layoutpage?
end

Expand Down
25 changes: 4 additions & 21 deletions app/javascript/alchemy_admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,10 @@ import Sitemap from "alchemy_admin/sitemap"
import SortableElements from "alchemy_admin/sortable_elements"
import Spinner from "alchemy_admin/spinner"
import PagePublicationFields from "alchemy_admin/page_publication_fields"
import { reloadPreview } from "alchemy_admin/components/preview_window"

// Web Components
import "alchemy_admin/components/button"
import "alchemy_admin/components/char_counter"
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"
import "alchemy_admin/components/ingredient_group"
import "alchemy_admin/components/link_buttons"
import "alchemy_admin/components/node_select"
import "alchemy_admin/components/uploader"
import "alchemy_admin/components/overlay"
import "alchemy_admin/components/page_select"
import "alchemy_admin/components/select"
import "alchemy_admin/components/spinner"
import "alchemy_admin/components/tags_autocomplete"
import "alchemy_admin/components/tinymce"
import "alchemy_admin/components"

import { setDefaultAnimation } from "shoelace"

Expand Down Expand Up @@ -85,7 +67,8 @@ Object.assign(Alchemy, {
Sitemap,
SortableElements,
Spinner,
PagePublicationFields
PagePublicationFields,
reloadPreview
})

Rails.start()
Expand Down
10 changes: 8 additions & 2 deletions app/javascript/alchemy_admin/components/element_editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export class ElementEditor extends HTMLElement {
}

focusElementPreview() {
Alchemy.PreviewWindow.postMessage({
this.previewWindow?.postMessage({
message: "Alchemy.focusElement",
element_id: this.elementId
})
Expand Down Expand Up @@ -141,7 +141,9 @@ export class ElementEditor extends HTMLElement {
this.elementErrors.classList.remove("hidden")
} else {
Alchemy.growl(data.notice)
Alchemy.PreviewWindow.refresh(() => this.focusElementPreview())
this.previewWindow?.refresh().then(() => {
this.focusElementPreview()
})
this.updateTitle(data.previewText)
data.ingredientAnchors.forEach((anchor) => {
IngredientAnchorLink.updateIcon(anchor.ingredientId, anchor.active)
Expand Down Expand Up @@ -547,6 +549,10 @@ export class ElementEditor extends HTMLElement {
get parentElementEditor() {
return this.parentElement?.closest("alchemy-element-editor")
}

get previewWindow() {
return document.getElementById("alchemy_preview_window")
}
}

customElements.define("alchemy-element-editor", ElementEditor)
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { patch } from "alchemy_admin/utils/ajax"
import { reloadPreview } from "alchemy_admin/components/preview_window"

export class PublishElementButton extends HTMLElement {
constructor() {
Expand All @@ -14,7 +15,7 @@ export class PublishElementButton extends HTMLElement {
.then((response) => {
this.elementEditor.published = response.data.public
this.tooltip.setAttribute("content", response.data.label)
Alchemy.reloadPreview()
reloadPreview()
})
.catch((error) => Alchemy.growl(error.message, "error"))
}
Expand Down
6 changes: 5 additions & 1 deletion app/javascript/alchemy_admin/components/elements_window.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ class ElementsWindow extends HTMLElement {
return document.querySelector("#element_window_button")
}

get previewWindow() {
return document.getElementById("alchemy_preview_window")
}

#attachEvents() {
this.collapseButton?.addEventListener("click", () => {
this.collapseAllElements()
Expand All @@ -72,7 +76,7 @@ class ElementsWindow extends HTMLElement {
this.querySelectorAll("alchemy-element-editor").forEach((editor) => {
editor.classList.remove("selected")
})
Alchemy.PreviewWindow.postMessage({ message: "Alchemy.blurElements" })
this.previewWindow?.postMessage({ message: "Alchemy.blurElements" })
}
})
}
Expand Down
21 changes: 21 additions & 0 deletions app/javascript/alchemy_admin/components/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import "alchemy_admin/components/button"
import "alchemy_admin/components/char_counter"
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"
import "alchemy_admin/components/ingredient_group"
import "alchemy_admin/components/link_buttons"
import "alchemy_admin/components/node_select"
import "alchemy_admin/components/uploader"
import "alchemy_admin/components/overlay"
import "alchemy_admin/components/page_select"
import "alchemy_admin/components/preview_window"
import "alchemy_admin/components/select"
import "alchemy_admin/components/spinner"
import "alchemy_admin/components/tags_autocomplete"
import "alchemy_admin/components/tinymce"
121 changes: 121 additions & 0 deletions app/javascript/alchemy_admin/components/preview_window.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
const MIN_WIDTH = 240

class PreviewWindow extends HTMLIFrameElement {
#afterLoad
#reloadIcon

constructor() {
super()
this.addEventListener("load", this)
}

handleEvent(evt) {
if (evt.type === "load") {
this.#stopSpinner()
this.#afterLoad?.call(this, evt)
}
}

connectedCallback() {
let url = this.url

this.#attachEvents()

if (window.localStorage.getItem("alchemy-preview-url")) {
url = window.localStorage.getItem("alchemy-preview-url")
this.previewUrlSelect.value = url
}

this.refresh(url)
}

disconnectedCallback() {
key.unbind("alt+r")
}

postMessage(data) {
this.contentWindow.postMessage(data, "*")
}

resize(width) {
if (width < MIN_WIDTH) {
width = MIN_WIDTH
}
this.style.width = `${width}px`
}

refresh(url) {
this.#startSpinner()

if (url) {
this.src = url
} else {
this.src = this.url
}

return new Promise((resolve) => {
this.#afterLoad = resolve
})
}

#attachEvents() {
this.reloadButton?.addEventListener("click", (evt) => {
evt.preventDefault()
this.refresh()
})

key("alt+r", () => this.refresh())

// Need to listen with jQuery here because select2 does not emit native events.
$(this.sizeSelect).on("change", (evt) => {
const select = evt.target
const width = select.value

if (width === "auto") {
this.style.width = null
} else {
this.resize(width)
}
})

this.previewUrlSelect?.addEventListener("change", (evt) => {
const url = evt.target.value
window.localStorage.setItem("alchemy-preview-url", url)
this.refresh(url)
})
}

#startSpinner() {
this.#reloadIcon = this.reloadButton.innerHTML
this.reloadButton.innerHTML = `<alchemy-spinner size="small"></alchemy-spinner>`
}

#stopSpinner() {
this.reloadButton.innerHTML = this.#reloadIcon
}

get url() {
return this.getAttribute("url")
}

get sizeSelect() {
return document.querySelector("select#preview_size")
}

get previewUrlSelect() {
return document.querySelector("select#preview_url")
}

get reloadButton() {
return document.querySelector("#reload_preview_button")
}
}

customElements.define("alchemy-preview-window", PreviewWindow, {
extends: "iframe"
})

export function reloadPreview() {
const previewWindow = document.getElementById("alchemy_preview_window")
previewWindow.refresh()
}
3 changes: 2 additions & 1 deletion app/javascript/alchemy_admin/sortable_elements.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Sortable from "sortablejs"
import { post } from "alchemy_admin/utils/ajax"
import { reloadPreview } from "alchemy_admin/components/preview_window"

const SORTABLE_OPTIONS = {
draggable: ".element-editor",
Expand Down Expand Up @@ -36,7 +37,7 @@ function onSort(event) {
post(Alchemy.routes.order_admin_elements_path, params).then((response) => {
const data = response.data
Alchemy.growl(data.message)
Alchemy.PreviewWindow.refresh()
reloadPreview()
item.updateTitle(data.preview_text)
})
}
Expand Down
Loading

0 comments on commit f296074

Please sign in to comment.