Skip to content

Commit

Permalink
Merge pull request #2818 from AlchemyCMS/delete-element-button
Browse files Browse the repository at this point in the history
Add delete-element-button
  • Loading branch information
tvdeyen authored Apr 4, 2024
2 parents 08d6a85 + 5e789e0 commit f0b0403
Show file tree
Hide file tree
Showing 11 changed files with 202 additions and 118 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 @@ -5,6 +5,5 @@
//= require handlebars
//= require alchemy/templates
//= require alchemy/alchemy.dialog
//= require alchemy/alchemy.confirm_dialog
//= require alchemy/alchemy.fixed_elements
//= require alchemy/alchemy.image_overlay
85 changes: 0 additions & 85 deletions app/assets/javascripts/alchemy/alchemy.confirm_dialog.js.coffee

This file was deleted.

9 changes: 9 additions & 0 deletions app/assets/stylesheets/alchemy/elements.scss
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,15 @@ alchemy-tinymce {
}
}

&.dismiss {
opacity: 0;
transform: scale(0);
transform-origin: top center;
transition:
opacity $transition-duration ease-out,
transform 1s ease-in;
}

.element-body {
margin: 2 * $default-padding;
}
Expand Down
6 changes: 4 additions & 2 deletions app/controllers/alchemy/admin/elements_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,11 @@ def update
end

def destroy
@richtext_ids = @element.richtext_ingredients_ids
@element.destroy
@notice = Alchemy.t("Successfully deleted element") % {element: @element.display_name}

render json: {
message: Alchemy.t("Successfully deleted element") % {element: @element.display_name}
}
end

def publish
Expand Down
8 changes: 7 additions & 1 deletion app/javascript/alchemy_admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ import Sitemap from "alchemy_admin/sitemap"
import Spinner from "alchemy_admin/spinner"
import PagePublicationFields from "alchemy_admin/page_publication_fields"
import { reloadPreview } from "alchemy_admin/components/preview_window"
import {
openConfirmDialog,
confirmToDeleteDialog
} from "alchemy_admin/confirm_dialog"

// Web Components
import "alchemy_admin/components"
Expand Down Expand Up @@ -65,7 +69,9 @@ Object.assign(Alchemy, {
Sitemap,
Spinner,
PagePublicationFields,
reloadPreview
reloadPreview,
openConfirmDialog,
confirmToDeleteDialog
})

Rails.start()
Expand Down
1 change: 1 addition & 0 deletions app/javascript/alchemy_admin/components/element_editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { createHtmlElement } from "alchemy_admin/utils/dom_helpers"
import { growl } from "alchemy_admin/growler"

import "alchemy_admin/components/element_editor/publish_element_button"
import "alchemy_admin/components/element_editor/delete_element_button"

export class ElementEditor extends HTMLElement {
constructor() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { growl } from "alchemy_admin/growler"
import { reloadPreview } from "alchemy_admin/components/preview_window"
import { confirmToDeleteDialog } from "alchemy_admin/confirm_dialog"

export class DeleteElementButton extends HTMLElement {
constructor() {
super()
this.addEventListener("click", this)
}

handleEvent() {
confirmToDeleteDialog(this.url, { message: this.message }).then(
(response) => {
this.#removeElement(response)
}
)
}

#removeElement(response) {
const elementEditor = this.closest("alchemy-element-editor")
elementEditor.addEventListener("transitionend", () => {
if (elementEditor.fixed) {
Alchemy.FixedElements.removeTab(elementEditor.elementId)
}
elementEditor.remove()
})
elementEditor.classList.add("dismiss")
growl(response.message)
reloadPreview()
}

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

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

customElements.define("alchemy-delete-element-button", DeleteElementButton)
113 changes: 113 additions & 0 deletions app/javascript/alchemy_admin/confirm_dialog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { growl } from "alchemy_admin/growler"
import pleaseWaitOverlay from "alchemy_admin/please_wait_overlay"

Alchemy.Dialog = window.Alchemy.Dialog || class Dialog {}

class ConfirmDialog extends Alchemy.Dialog {
constructor(message, options = {}) {
const DEFAULTS = {
size: "300x100",
title: "Please confirm",
ok_label: "Yes",
cancel_label: "No",
on_ok() {}
}

options = { ...DEFAULTS, ...options }

super("", options)
this.message = message
this.options = options
}

load() {
this.dialog_title.text(this.options.title)
this.dialog_body.html(`<p>${this.message}</p>`)
this.dialog_body.append(this.build_buttons())
this.bind_buttons()
}

build_buttons() {
const $btn_container = $('<div class="alchemy-dialog-buttons" />')
this.cancel_button = $(
`<button class=\"cancel secondary\">${this.options.cancel_label}</button>`
)
this.ok_button = $(
`<button class=\"confirm\">${this.options.ok_label}</button>`
)
$btn_container.append(this.cancel_button)
$btn_container.append(this.ok_button)
return $btn_container
}

bind_buttons() {
this.cancel_button.trigger("focus")
this.cancel_button.on("click", () => {
this.close()
return false
})
this.ok_button.on("click", () => {
this.close()
this.options.on_ok()
return false
})
}
}

// Opens a confirm dialog
//
// Arguments:
//
// message - The message that will be displayed to the user (String)
//
// Options:
//
// title: '' - The title of the overlay window (String)
// cancel_label: '' - The label of the cancel button (String)
// ok_label: '' - The label of the ok button (String)
// on_ok: null - The function to invoke on confirmation (Function)
//
export function openConfirmDialog(message, options = {}) {
const dialog = new ConfirmDialog(message, options)
dialog.open()
return dialog
}

// Opens a confirm to delete dialog
//
// Arguments:
//
// url - The url to the server delete action. Uses DELETE as HTTP method. (String)
// opts - An options object (Object)
//
// Options:
//
// title: '' - The title of the confirmation window (String)
// message: '' - The message that will be displayed to the user (String)
// ok_label: '' - The label for the ok button (String)
// cancel_label: '' - The label for the cancel button (String)
//
export function confirmToDeleteDialog(url, opts = {}) {
return new Promise((resolve, reject) => {
const options = {
on_ok() {
pleaseWaitOverlay()
$.ajax({
url,
type: "DELETE",
error(xhr, _status, error) {
const type = xhr.status === 403 ? "warning" : "error"
growl(xhr.responseText || error, type)
reject(error)
},
complete(response) {
pleaseWaitOverlay(false)
resolve(response)
}
})
}
}

openConfirmDialog(opts.message, { ...options, ...opts })
})
}
33 changes: 19 additions & 14 deletions app/javascript/alchemy_admin/dirty.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
function isPageDirty() {
return $("#element_area").find("alchemy-element-editor.dirty").length > 0
}
import { openConfirmDialog } from "alchemy_admin/confirm_dialog"
import { translate } from "alchemy_admin/i18n"
import pleaseWaitOverlay from "alchemy_admin/please_wait_overlay"

function checkPageDirtyness(element) {
let callback = () => {}
Expand All @@ -13,18 +13,21 @@ function checkPageDirtyness(element) {
$form.append($(element).find("input"))
$form.appendTo("body")

Alchemy.pleaseWaitOverlay()
$form.submit()
pleaseWaitOverlay()
$form.trigger("submit")
}
} else if ($(element).is("a")) {
callback = () => Turbo.visit(element.pathname)
}

if (isPageDirty()) {
Alchemy.openConfirmDialog(Alchemy.t("page_dirty_notice"), {
title: Alchemy.t("warning"),
ok_label: Alchemy.t("ok"),
cancel_label: Alchemy.t("cancel"),
const isPageDirty =
document.querySelectorAll("alchemy-element-editor.dirty").length > 0

if (isPageDirty) {
openConfirmDialog(translate("page_dirty_notice"), {
title: translate("warning"),
ok_label: translate("ok"),
cancel_label: translate("cancel"),
on_ok: function () {
window.onbeforeunload = void 0
callback()
Expand All @@ -36,10 +39,12 @@ function checkPageDirtyness(element) {
}

function PageLeaveObserver() {
$("#main_navi a").on("click", function (event) {
if (!checkPageDirtyness(event.currentTarget)) {
event.preventDefault()
}
document.querySelectorAll("#main_navi a").forEach((element) => {
element.addEventListener("click", (event) => {
if (!checkPageDirtyness(event.currentTarget)) {
event.preventDefault()
}
})
})
}

Expand Down
15 changes: 8 additions & 7 deletions app/views/alchemy/admin/elements/_toolbar.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@
) %>
</sl-tooltip>
<sl-tooltip content="<%= Alchemy.t("Delete element") %>">
<%= link_to_confirm_dialog(
render_icon('delete-bin-2'),
Alchemy.t(:confirm_to_delete_element),
alchemy.admin_element_path(element),
class: "icon_button",
data: {turbo: false}
) -%>
<alchemy-delete-element-button
href="<%= alchemy.admin_element_path(element) %>"
message="<%= Alchemy.t(:confirm_to_delete_element) %>"
>
<button type="button" class="icon_button" data-turbo="false">
<%= render_icon('delete-bin-2') %>
</button>
</alchemy-delete-element-button>
</sl-tooltip>
<sl-tooltip content="<%= element.public? ? Alchemy.t(:hide_element) : Alchemy.t(:show_element) %>" placement="top-end">
<alchemy-publish-element-button>
Expand Down
8 changes: 0 additions & 8 deletions app/views/alchemy/admin/elements/destroy.js.erb

This file was deleted.

0 comments on commit f0b0403

Please sign in to comment.