diff --git a/app/assets/javascripts/alchemy/admin.js b/app/assets/javascripts/alchemy/admin.js index 597bfed13d..f120a5ccf9 100644 --- a/app/assets/javascripts/alchemy/admin.js +++ b/app/assets/javascripts/alchemy/admin.js @@ -9,5 +9,4 @@ //= require alchemy/alchemy.elements_window //= require alchemy/alchemy.fixed_elements //= require alchemy/alchemy.image_overlay -//= require alchemy/alchemy.link_dialog //= require alchemy/alchemy.preview_window diff --git a/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee b/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee deleted file mode 100644 index bcc0144c95..0000000000 --- a/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +++ /dev/null @@ -1,83 +0,0 @@ -# Represents the link Dialog that appears, if a user clicks the link buttons -# in TinyMCE or on an Ingredient that has links enabled (e.g. Picture) -# -class window.Alchemy.LinkDialog extends Alchemy.Dialog - - constructor: (link) -> - url = new URL(Alchemy.routes.link_admin_pages_path, window.location) - parameterMapping = { url: link.url, selected_tab: link.type, link_title: link.title, link_target: link.target } - - # searchParams.set would also add undefined values - Object.keys(parameterMapping).forEach (key) => - url.searchParams.set(key, parameterMapping[key]) if parameterMapping[key] - - @options = - size: '600x320' - title: 'Link' - super(url.href, @options) - - # Called from Dialog class after the url was loaded - replace: (data) -> - # let Dialog class handle the content replacement - super(data) - # Store some jQuery objects for further reference - @$internal_link = $('#internal_link', @dialog_body) - @$element_anchor = $('#element_anchor', @dialog_body) - @linkForm = document.querySelector('[data-link-form-type="internal"]') - - # attach events we handle - @attachEvents() - - # make the open method a promise - # maybe in a future version the whole Dialog will respond with a promise result if the dialog is closing - open: () -> - super - new Promise (resolve) => - @resolve = resolve - - updatePage: (page) -> - @$internal_link.val(page?.url_path) - @linkForm.querySelector('alchemy-anchor-select').page = page?.id - - # Attaches click events to forms in the link dialog. - attachEvents: -> - # enable the dom selection in internal link tab - @linkForm.addEventListener "Alchemy.PageSelect.ItemRemoved", (e) => @updatePage() - @linkForm.addEventListener "Alchemy.PageSelect.ItemAdded", (e) => @updatePage(e.detail) - - $('[data-link-form-type]', @dialog_body).on "submit", (e) => - e.preventDefault() - @link_type = e.target.dataset.linkFormType - # get url and remove a possible hash fragment - url = $("##{@link_type}_link").val().replace(/#\w+$/, '') - if @link_type == 'internal' && @$element_anchor.val() != '' - url += "#" + @$element_anchor.val() - - # Create the link - @createLink - url: url - title: $("##{@link_type}_link_title").val() - target: $("##{@link_type}_link_target").val() - false - - # Creates a link if no validation errors are present. - # Otherwise shows an error notice. - createLink: (options) -> - if @link_type == 'external' - if options.url.match(Alchemy.link_url_regexp) - @setLink(options) - else - return @showValidationError() - else - @setLink(options) - @close() - - # Sets the link either in TinyMCE or on an Ingredient. - setLink: (options) -> - trimmedUrl = options.url.trim() - @resolve({url: trimmedUrl, title: options.title, target: options.target, type: @link_type}) - - # Shows validation errors - showValidationError: -> - $('#errors ul', @dialog_body).html("
  • #{Alchemy.t('url_validation_failed')}
  • ") - $('#errors', @dialog_body).show() diff --git a/app/javascript/alchemy_admin.js b/app/javascript/alchemy_admin.js index 37032a17ff..49ca7dda70 100644 --- a/app/javascript/alchemy_admin.js +++ b/app/javascript/alchemy_admin.js @@ -11,6 +11,7 @@ import IngredientAnchorLink from "alchemy_admin/ingredient_anchor_link" import ImageLoader from "alchemy_admin/image_loader" import ImageCropper from "alchemy_admin/image_cropper" import Initializer from "alchemy_admin/initializer" +import { LinkDialog } from "alchemy_admin/link_dialog" import ListFilter from "alchemy_admin/list_filter" import pictureSelector from "alchemy_admin/picture_selector" import pleaseWaitOverlay from "alchemy_admin/please_wait_overlay" @@ -79,6 +80,7 @@ Object.assign(Alchemy, { ImageCropper, Initializer, IngredientAnchorLink, + LinkDialog, ListFilter, pictureSelector, pleaseWaitOverlay, diff --git a/app/javascript/alchemy_admin/link_dialog.js b/app/javascript/alchemy_admin/link_dialog.js new file mode 100644 index 0000000000..8d694d7a0e --- /dev/null +++ b/app/javascript/alchemy_admin/link_dialog.js @@ -0,0 +1,118 @@ +// Represents the link Dialog that appears, if a user clicks the link buttons +// in TinyMCE or on an Ingredient that has links enabled (e.g. Picture) +// +export class LinkDialog extends Alchemy.Dialog { + constructor(link) { + const url = new URL(Alchemy.routes.link_admin_pages_path, window.location) + const parameterMapping = { + url: link.url, + selected_tab: link.type, + link_title: link.title, + link_target: link.target + } + + // searchParams.set would also add undefined values + Object.keys(parameterMapping).forEach((key) => { + if (parameterMapping[key]) { + url.searchParams.set(key, parameterMapping[key]) + } + }) + + super(url.href, { + size: "600x320", + title: "Link" + }) + } + + /** + * Called from Dialog class after the url was loaded + */ + replace(data) { + // let Dialog class handle the content replacement + super.replace(data) + // Store some jQuery objects for further reference + this.$internal_link = $("#internal_link", this.dialog_body) + this.$element_anchor = $("#element_anchor", this.dialog_body) + this.linkForm = document.querySelector('[data-link-form-type="internal"]') + + // attach events we handle + this.attachEvents() + } + + /** + * make the open method a promise + * maybe in a future version the whole Dialog will respond with a promise result if the dialog is closing + * @returns {Promise} + */ + open() { + super.open(...arguments) + return new Promise((resolve) => (this.resolve = resolve)) + } + + updatePage(page) { + this.$internal_link.val(page != null ? page.url_path : undefined)( + (this.linkForm.querySelector("alchemy-anchor-select").page = + page != null ? page.id : undefined) + ) + } + + // Attaches click events to forms in the link dialog. + attachEvents() { + // enable the dom selection in internal link tab + this.linkForm.addEventListener("Alchemy.PageSelect.ItemRemoved", (e) => + this.updatePage() + ) + this.linkForm.addEventListener("Alchemy.PageSelect.ItemAdded", (e) => + this.updatePage(e.detail) + ) + + $("[data-link-form-type]", this.dialog_body).on("submit", (e) => { + e.preventDefault() + this.link_type = e.target.dataset.linkFormType + // get url and remove a possible hash fragment + let url = $(`#${this.link_type}_link`).val().replace(/#\w+$/, "") + if (this.link_type === "internal" && this.$element_anchor.val() !== "") { + url += "#" + this.$element_anchor.val() + } + + // Create the link + this.createLink({ + url, + title: $(`#${this.link_type}_link_title`).val(), + target: $(`#${this.link_type}_link_target`).val() + }) + }) + } + + // Creates a link if no validation errors are present. + // Otherwise shows an error notice. + createLink(options) { + if ( + this.link_type === "external" && + !options.url.match(Alchemy.link_url_regexp) + ) { + this.showValidationError() + } else { + this.setLink(options) + this.close() + } + } + + // Sets the link either in TinyMCE or on an Ingredient. + setLink(options) { + this.resolve({ + url: options.url.trim(), + title: options.title, + target: options.target, + type: this.link_type + }) + } + + // Shows validation errors + showValidationError() { + $("#errors ul", this.dialog_body).html( + `
  • ${Alchemy.t("url_validation_failed")}
  • ` + ) + return $("#errors", this.dialog_body).show() + } +}