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

Add Link button components #2655

Merged
merged 5 commits into from
Dec 28, 2023
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
75 changes: 16 additions & 59 deletions app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,6 @@
class window.Alchemy.LinkDialog extends Alchemy.Dialog

constructor: (@link_object) ->
if @link_object.dataset
parent_selector = @link_object.dataset.parentSelector
parent = document.querySelector(parent_selector)
@link_value_field = parent.querySelector("[data-link-value]")
@link_title_field = parent.querySelector("[data-link-title]")
@link_target_field = parent.querySelector("[data-link-target]")
@link_class_field = parent.querySelector("[data-link-class]")
@url = Alchemy.routes.link_admin_pages_path
@$link_object = $(@link_object)
@options =
Expand Down Expand Up @@ -40,11 +33,11 @@ class window.Alchemy.LinkDialog extends Alchemy.Dialog
@initPageSelect()
return

# Attaches click events to several buttons in the link dialog.
# Attaches click events to forms in the link dialog.
attachEvents: ->
# The ok buttons
$('.create-link.button', @dialog_body).click (e) =>
@link_type = $(e.target).data('link-type')
$('[data-link-form-type]', @dialog_body).on "submit", (e) =>
e.preventDefault()
@link_type = e.target.dataset.linkFormType
url = $("##{@link_type}_link").val()
if @link_type == 'internal' && @$element_anchor.val() != ''
url += "##{@$element_anchor.val()}"
Expand Down Expand Up @@ -136,12 +129,11 @@ class window.Alchemy.LinkDialog extends Alchemy.Dialog

# Sets the link either in TinyMCE or on an Ingredient.
setLink: (url, title, target) ->
element_editor = @$link_object[0].closest('alchemy-element-editor')
element_editor.setDirty()
if @link_object.editor
@setTinyMCELink(url, title, target)
else
@setLinkFields(url, title, target)
@link_object.setLink(url, title, target, @link_type)
return

# Sets a link in TinyMCE editor.
setTinyMCELink: (url, title, target) ->
Expand All @@ -155,23 +147,11 @@ class window.Alchemy.LinkDialog extends Alchemy.Dialog
editor.selection.collapse()
true

# Sets a link on an Ingredient (e.g. Picture).
setLinkFields: (url, title, target) ->
@link_value_field.value = url
@link_value_field.dispatchEvent(new Event("change"))
@link_title_field.value = title
@link_class_field.value = @link_type
@link_target_field.value = target
@link_object.classList.add("linked")
@link_object.nextElementSibling.classList.replace("disabled", "linked")
@link_object.nextElementSibling.removeAttribute("tabindex")
return

# Selects the correct tab for link type and fills all fields.
selectTab: ->
# Creating an temporary anchor node if we are linking an Picture Ingredient.
if (@link_object.nodeType)
@$link = @createTempLink()
if (@link_object.getAttribute("is") == "alchemy-link-button")
@$link = $(@createTempLink())
# Restoring the bookmarked selection inside the TinyMCE of an Richtext.
else if (@link_object.node.nodeName == 'A')
@$link = $(@link_object.node)
Expand Down Expand Up @@ -215,15 +195,15 @@ class window.Alchemy.LinkDialog extends Alchemy.Dialog
# store the anchor
@$element_anchor.val(url[1])

# Creates a temporay $('a') object that holds all values on it.
# Creates a temporay 'a' element that holds all values on it.
createTempLink: ->
@$tmp_link = $('<a/>')
@$tmp_link.attr('href', @link_value_field.value)
@$tmp_link.attr('title', @link_title_field.value)
@$tmp_link.attr('data-link-target', @link_target_field.value)
@$tmp_link.attr('target', if @link_target_field.value == 'blank' then '_blank' else null)
@$tmp_link.addClass(@link_class_field.value)
@$tmp_link
tmp_link = document.createElement("a")
tmp_link.setAttribute('href', @link_object.linkUrl)
tmp_link.setAttribute('title', @link_object.linkTitle)
tmp_link.setAttribute('data-link-target', @link_object.linkTarget)
tmp_link.setAttribute('target', if @link_object.target == 'blank' then '_blank' else "")
tmp_link.classList.add(@link_object.linkClass) if @link_object.linkClass != ''
tmp_link

# Validates url for beginning with an protocol.
validateURLFormat: (url) ->
Expand All @@ -247,26 +227,3 @@ class window.Alchemy.LinkDialog extends Alchemy.Dialog
else
@$anchor_link.html("<option>#{Alchemy.t('No anchors found')}</option>")
return

# Public class methods

# Removes link from Ingredient.
@removeLink = (link, parent_selector) ->
parent = document.querySelector(parent_selector)
link_value_field = parent.querySelector("[data-link-value]")
link_title_field = parent.querySelector("[data-link-title]")
link_target_field = parent.querySelector("[data-link-target]")
link_class_field = parent.querySelector("[data-link-class]")
link_value_field.value = ""
link_value_field.dispatchEvent(new Event("change"))
link_title_field.value = ""
link_class_field.value = ""
link_target_field.value = ""
if link.classList.contains('linked')
element_editor = link.closest('alchemy-element-editor')
element_editor.setDirty()
link.classList.replace('linked', 'disabled')
link.setAttribute('tabindex', '-1')
link.blur()
link.previousElementSibling.classList.remove("linked")
false
83 changes: 44 additions & 39 deletions app/assets/stylesheets/alchemy/elements.scss
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,13 @@ alchemy-tinymce {

.ingredient-editor.picture {
padding-right: 1px;

alchemy-link-buttons {
width: 33.333%;
flex-wrap: nowrap;
display: inline-flex;
justify-content: space-between;
}
}

.picture_thumbnail {
Expand Down Expand Up @@ -484,54 +491,52 @@ alchemy-publish-element-button {
right: 0;

.icon_button {
@include button-defaults(
$background-color: $medium-gray,
$hover-color: darken($medium-gray, 5%),
$border: 1px solid #c0c0c0,
$box-shadow: none,
$hover-border-color: #c0c0c0,
$line-height: 30px,
$padding: 0,
$margin: 0,
$border-radius: 0,
$focus-border-color: $focus-color,
$focus-box-shadow: 0 0 0 2px $focus-color
);
width: $form-field-addon-width;
height: $form-field-height;

&.disabled,
&.disabled:hover {
background-color: $form-field-disabled-bg-color;
}
&:not(.linked) {
background-color: $medium-gray;
border-color: $default-border-color;
border-width: $form-field-border-width;
border-style: $form-field-border-style;
box-shadow: none;
padding: 0;
margin: 0;
border-radius: 0;
width: $form-field-addon-width;
height: $form-field-height;

&.linked.link-ingredient {
@include linked-button(
$border-radius: 0,
$line-height: 30px,
$padding: 0
);
&:hover {
border-color: #c0c0c0;
}

&:focus {
border-radius: 0;
box-shadow: 0 0 0 2px $focus-color;
border-color: $focus-color;
}
}

&.linked.unlink-ingredient {
@include linked-button(
$border-radius: 0 $default-border-radius $default-border-radius 0,
$line-height: 30px,
$padding: 0
);
&[is="alchemy-unlink-button"] {
border-left-width: 0;
@extend .right-rounded-border;
}

&:focus {
border-radius: 0 $default-border-radius $default-border-radius 0;
&.disabled,
&.disabled:hover {
background-color: $form-field-disabled-bg-color;
}
}

&.unlink-ingredient {
border-left-width: 0;
@extend .right-rounded-border;
&.linked {
height: 31px;
padding: 0;
border-radius: 0;
border-color: rgba(187, 162, 102, 0.5);

&[is="alchemy-unlink-button"] {
border-radius: 0 $default-border-radius $default-border-radius 0;
border-left-width: 0;

&:focus {
border-radius: 0 $default-border-radius $default-border-radius 0;
}
}
}
}
}
Expand Down
10 changes: 5 additions & 5 deletions app/controllers/alchemy/admin/resources_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,16 @@ def index
respond_to do |format|
format.html do
items = items.page(params[:page] || 1).per(items_per_page)
instance_variable_set("@#{resource_handler.resources_name}", items)
instance_variable_set(:"@#{resource_handler.resources_name}", items)
end
format.csv do
instance_variable_set("@#{resource_handler.resources_name}", items)
instance_variable_set(:"@#{resource_handler.resources_name}", items)
end
end
end

def new
instance_variable_set("@#{resource_handler.resource_name}", resource_handler.model.new)
instance_variable_set(:"@#{resource_handler.resource_name}", resource_handler.model.new)
end

def show
Expand All @@ -54,7 +54,7 @@ def edit
end

def create
instance_variable_set("@#{resource_handler.resource_name}", resource_handler.model.new(resource_params))
instance_variable_set(:"@#{resource_handler.resource_name}", resource_handler.model.new(resource_params))
resource_instance_variable.save
render_errors_or_redirect(
resource_instance_variable,
Expand Down Expand Up @@ -169,7 +169,7 @@ def alchemy_module
end

def load_resource
instance_variable_set("@#{resource_handler.resource_name}", resource_handler.model.find(params[:id]))
instance_variable_set(:"@#{resource_handler.resource_name}", resource_handler.model.find(params[:id]))
end

def authorize_resource
Expand Down
1 change: 1 addition & 0 deletions app/javascript/alchemy_admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import "alchemy_admin/components/datepicker"
import "alchemy_admin/components/dialog_link"
import "alchemy_admin/components/element_editor"
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"
Expand Down
79 changes: 79 additions & 0 deletions app/javascript/alchemy_admin/components/link_buttons.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import "alchemy_admin/components/link_buttons/link_button"
import "alchemy_admin/components/link_buttons/unlink_button"

class LinkButtons extends HTMLElement {
constructor() {
super()
this.addEventListener("alchemy:link", this)
this.addEventListener("alchemy:unlink", this)
}

handleEvent(event) {
switch (event.type) {
case "alchemy:link":
this.setLink(event.detail)
break
case "alchemy:unlink":
this.removeLink()
}
event.stopPropagation()
}

setLink(data) {
this.linkUrlField.value = data.url
this.linkUrlField.dispatchEvent(new Event("change"))
this.linkTitleField.value = data.title
this.linkClassField.value = data.type
this.linkTargetField.value = data.target

this.unlinkButton.linked = true
this.elementEditor.setDirty()
}

removeLink() {
this.linkUrlField.value = ""
this.linkUrlField.dispatchEvent(new Event("change"))
this.linkTitleField.value = ""
this.linkClassField.value = ""
this.linkTargetField.value = ""

this.linkButton.classList.remove("linked")

this.elementEditor.setDirty()
}

get linkButton() {
return this.querySelector('[is="alchemy-link-button"]')
}

get unlinkButton() {
return this.querySelector('[is="alchemy-unlink-button"]')
}

get ingredientEditor() {
const ingredientId = this.dataset.ingredientId
return this.parentElement.closest(`[data-ingredient-id='${ingredientId}']`)
}

get elementEditor() {
return this.closest("alchemy-element-editor")
}

get linkUrlField() {
return this.ingredientEditor.querySelector("[data-link-value]")
}

get linkTitleField() {
return this.ingredientEditor.querySelector("[data-link-title]")
}

get linkTargetField() {
return this.ingredientEditor.querySelector("[data-link-target]")
}

get linkClassField() {
return this.ingredientEditor.querySelector("[data-link-class]")
}
}

customElements.define("alchemy-link-buttons", LinkButtons)
Loading
Loading