Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert Preview Window into web component #2802

Merged
merged 5 commits into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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