diff --git a/app/components/confirm_modal_component/confirm_modal_component.html.haml b/app/components/confirm_modal_component/confirm_modal_component.html.haml index 5fe1d1300b..1184602a67 100644 --- a/app/components/confirm_modal_component/confirm_modal_component.html.haml +++ b/app/components/confirm_modal_component/confirm_modal_component.html.haml @@ -1,6 +1,6 @@ %div{ id: @id, "data-controller": "modal #{@controller}", "data-action": "keyup@document->modal#closeIfEscapeKey", "data-#{@controller}-reflex-value": @reflex } .reveal-modal-bg.fade{ "data-modal-target": "background", "data-action": "click->modal#close" } - .reveal-modal.fade.tiny.help-modal{ "data-modal-target": "modal" } + .reveal-modal.fade.tiny.modal-component{ "data-modal-target": "modal" } = content = render @message if @message diff --git a/app/components/help_modal_component/help_modal_component.html.haml b/app/components/help_modal_component/help_modal_component.html.haml index af7d602724..adc6c54822 100644 --- a/app/components/help_modal_component/help_modal_component.html.haml +++ b/app/components/help_modal_component/help_modal_component.html.haml @@ -1,6 +1,6 @@ %div{ id: @id, "data-controller": "help-modal", "data-action": "keyup@document->help-modal#closeIfEscapeKey" } .reveal-modal-bg.fade{ "data-help-modal-target": "background", "data-action": "click->help-modal#close" } - .reveal-modal.fade.small.help-modal{ "data-help-modal-target": "modal" } + .reveal-modal.fade.small.modal-component{ "data-help-modal-target": "modal" } = content - if close_button? diff --git a/app/components/modal_component.rb b/app/components/modal_component.rb index 70226295c7..a538eb19b1 100644 --- a/app/components/modal_component.rb +++ b/app/components/modal_component.rb @@ -1,9 +1,10 @@ # frozen_string_literal: true class ModalComponent < ViewComponent::Base - def initialize(id:, close_button: true) + def initialize(id:, close_button: true, instant: false) @id = id @close_button = close_button + @instant = instant end private diff --git a/app/components/modal_component/modal_component.html.haml b/app/components/modal_component/modal_component.html.haml new file mode 100644 index 0000000000..1677d71b3f --- /dev/null +++ b/app/components/modal_component/modal_component.html.haml @@ -0,0 +1,8 @@ +%div{ id: @id, "data-controller": "modal", "data-action": "keyup@document->modal#closeIfEscapeKey", "data-modal-instant-value": @instant } + .reveal-modal-bg.fade{ "data-modal-target": "background", "data-action": "click->modal#close" } + .reveal-modal.fade.small.modal-component{ "data-modal-target": "modal" } + = content + + - if close_button? + .text-center + %input{ class: "button icon-plus #{close_button_class}", type: 'button', value: t('js.admin.modals.close'), "data-action": "click->modal#close" } diff --git a/app/components/help_modal_component/help_modal_component.scss b/app/components/modal_component/modal_component.scss similarity index 57% rename from app/components/help_modal_component/help_modal_component.scss rename to app/components/modal_component/modal_component.scss index d323b47992..5e9f6ad8bd 100644 --- a/app/components/help_modal_component/help_modal_component.scss +++ b/app/components/modal_component/modal_component.scss @@ -1,10 +1,21 @@ -.help-modal { +// class name 'modal' is already taken by 'custom-alert' and 'custom-confirm'. +.modal-component { visibility: visible; position: fixed; top: 3em; &.in { padding: 1.2rem; } + + h1, + h2, + h3, + h4, + h5, + h6, + p { + margin-bottom: 0.5em; + } } /* prevent arrow on selected admin menu item appearing above modal */ diff --git a/app/components/vertical_ellipsis_menu/component.scss b/app/components/vertical_ellipsis_menu/component.scss index 03b5cb39d8..9e8bc9d878 100644 --- a/app/components/vertical_ellipsis_menu/component.scss +++ b/app/components/vertical_ellipsis_menu/component.scss @@ -1,16 +1,13 @@ .vertical-ellipsis-menu { position: relative; - width: $btn-relaxed-height; i.fa-ellipsis-v { cursor: pointer; display: block; - height: $btn-relaxed-height; - width: $btn-relaxed-height; - line-height: $btn-relaxed-height; text-align: center; border-radius: 3px; background-color: white; + padding: 10px 14px; } .vertical-ellipsis-menu-content { diff --git a/app/controllers/spree/admin/images_controller.rb b/app/controllers/spree/admin/images_controller.rb index 4fed1aba31..44b26278f8 100644 --- a/app/controllers/spree/admin/images_controller.rb +++ b/app/controllers/spree/admin/images_controller.rb @@ -32,7 +32,7 @@ module Spree if @object.save flash[:success] = flash_message_for(@object, :successfully_created) - redirect_to spree.admin_product_images_url(params[:product_id], @url_filters) + redirect_to location_after_save else respond_with(@object) end @@ -44,7 +44,7 @@ module Spree if @object.update(permitted_resource_params) flash[:success] = flash_message_for(@object, :successfully_updated) - redirect_to spree.admin_product_images_url(params[:product_id], @url_filters) + redirect_to location_after_save else respond_with(@object) end @@ -58,7 +58,7 @@ module Spree flash[:success] = flash_message_for(@object, :successfully_removed) end - redirect_to spree.admin_product_images_url(params[:product_id], @url_filters) + redirect_to location_after_save end private @@ -76,7 +76,7 @@ module Spree end def location_after_save - spree.admin_product_images_url(@product) + params[:return_url] || spree.admin_product_images_url(params[:product_id], @url_filters) end def load_data diff --git a/app/reflexes/products_reflex.rb b/app/reflexes/products_reflex.rb index 711f4a577c..ec6c28f9fd 100644 --- a/app/reflexes/products_reflex.rb +++ b/app/reflexes/products_reflex.rb @@ -74,6 +74,15 @@ class ProductsReflex < ApplicationReflex fetch_and_render_products_with_flash end + def edit_image + id = current_id_from_element(element) + product = product_finder(id).find_product + + morph "#modal-component", + render(partial: "admin/products_v3/edit_image", + locals: { product:, image: product.image, return_url: url }) + end + private def init_filters_params diff --git a/app/views/admin/products_v3/_edit_image.html.haml b/app/views/admin/products_v3/_edit_image.html.haml new file mode 100644 index 0000000000..7af268d64d --- /dev/null +++ b/app/views/admin/products_v3/_edit_image.html.haml @@ -0,0 +1,16 @@ += render ModalComponent.new id: "#modal_edit_product_image_#{image.id}", instant: true, close_button: false do + %h2= t(".title") + + %p= image_tag image.variant(:product) + + -# Submit to controller, because StimulusReflex doesn't support file uploads + = form_for [:admin, product, image], url: admin_product_image_path(product, image), + html: { multipart: true }, data: { controller: "form" } do |f| + %input{ type: :hidden, name: :return_url, value: return_url} + = f.hidden_field :viewable_id, value: product.id + + %p + %input{ class: "secondary", type: 'button', value: t('.close'), "data-action": "click->modal#close" } + -# label.button provides a handy shortcut to open the file selector on click. Unfortunately this trick isn't keyboard accessible though.. + = f.label :attachment, t(".upload"), class: "button primary icon-upload-alt" + = f.file_field :attachment, accept: "image/*", style: "display: none", "data-action": "change->form#submit" diff --git a/app/views/admin/products_v3/_table.html.haml b/app/views/admin/products_v3/_table.html.haml index dcdec95520..c508972722 100644 --- a/app/views/admin/products_v3/_table.html.haml +++ b/app/views/admin/products_v3/_table.html.haml @@ -48,11 +48,14 @@ = form.fields_for("products", product, index: product_index) do |product_form| %tbody.relaxed{ 'data-record-id': product_form.object.id } %tr - %td + %td.with-image - if product.image.present? + %a.image-field{ href: edit_admin_product_image_path(product, product.image), data: { controller: "modal", reflex: "click->products#edit_image", "current-id": product.id} } + = image_tag product.image&.url(:mini), width: 40, height: 40 + .button.secondary.mini= t('admin.products_page.image.edit') + - else .image-field - = image_tag product.image.url(:mini), width: 40 - = link_to t('admin.products_page.image.edit'), edit_admin_product_image_path(product, product.image), class: "button secondary mini" + = image_tag Spree::Image.default_image_url(:mini), width: 40, height: 40 %td.field.align-left.header = product_form.hidden_field :id = product_form.text_field :name, 'aria-label': t('admin.products_page.columns.name') diff --git a/app/views/admin/products_v3/index.html.haml b/app/views/admin/products_v3/index.html.haml index a7833c22df..52ca21def8 100644 --- a/app/views/admin/products_v3/index.html.haml +++ b/app/views/admin/products_v3/index.html.haml @@ -19,3 +19,5 @@ #products-content - %w[product variant].each do |object_type| = render partial: 'delete_modal', locals: { object_type: } + #modal-component + diff --git a/app/views/spree/admin/orders/bulk/_invoice_modal.html.haml b/app/views/spree/admin/orders/bulk/_invoice_modal.html.haml index 07c2f30121..53f7982f25 100644 --- a/app/views/spree/admin/orders/bulk/_invoice_modal.html.haml +++ b/app/views/spree/admin/orders/bulk/_invoice_modal.html.haml @@ -1,6 +1,6 @@ %div{ id: "bulk_invoices_modal", "data-controller": "modal", "data-modal-instant-value": true, "data-action": "keyup@document->modal#closeIfEscapeKey" } .reveal-modal-bg.fade{ "data-modal-target": "background", "data-action": "click->modal#remove" } - .reveal-modal.fade.tiny.help-modal{ "data-modal-target": "modal" } + .reveal-modal.fade.tiny.modal-component{ "data-modal-target": "modal" } %div.fullwidth.align-center %h4.modal-title = t('js.admin.orders.index.compiling_invoices') diff --git a/app/webpacker/controllers/form_controller.js b/app/webpacker/controllers/form_controller.js new file mode 100644 index 0000000000..aaac9db4ec --- /dev/null +++ b/app/webpacker/controllers/form_controller.js @@ -0,0 +1,7 @@ +import { Controller } from "stimulus"; + +export default class FormController extends Controller { + submit() { + this.element.submit(); + } +} diff --git a/app/webpacker/css/admin/all.scss b/app/webpacker/css/admin/all.scss index 56d522ae75..2cb175b8f7 100644 --- a/app/webpacker/css/admin/all.scss +++ b/app/webpacker/css/admin/all.scss @@ -124,6 +124,6 @@ @import "~tom-select/src/scss/tom-select.default"; @import "components/tom_select"; -@import "app/components/help_modal_component/help_modal_component"; +@import "app/components/modal_component/modal_component"; @import "app/components/confirm_modal_component/confirm_modal_component"; @import "app/webpacker/css/admin/trix.scss"; diff --git a/app/webpacker/css/admin/products_v3.scss b/app/webpacker/css/admin/products_v3.scss index 4d6450e23f..2ac6a85eff 100644 --- a/app/webpacker/css/admin/products_v3.scss +++ b/app/webpacker/css/admin/products_v3.scss @@ -88,10 +88,6 @@ height: 100%; } } - - .image-field .button { - display: block; - } } th, @@ -131,6 +127,10 @@ td { border-bottom: 2px solid $color-tbl-bg; + + &.with-image { + padding: 8px; + } } tr:first-child td { @@ -375,18 +375,29 @@ } } - .image-field { + a.image-field { position: relative; img { + display: block; border-radius: $border-radius; } .button { - display: none; // to be shown on tr:hover + display: none; // to be shown on hover position: absolute; bottom: 0; left: 0; } + + &:hover, + &:focus { + .button.secondary { + display: block; + background-color: $color-btn-secondary-hover-bg; + color: $color-btn-hover-bg; + border-color: $color-btn-hover-border; + } + } } } diff --git a/app/webpacker/css/admin_v3/all.scss b/app/webpacker/css/admin_v3/all.scss index 664a4fda11..274e76a76e 100644 --- a/app/webpacker/css/admin_v3/all.scss +++ b/app/webpacker/css/admin_v3/all.scss @@ -128,7 +128,7 @@ @import "~tom-select/src/scss/tom-select.default"; @import "components/tom_select"; // admin_v3 -@import "app/components/help_modal_component/help_modal_component"; +@import "app/components/modal_component/modal_component"; @import "app/components/confirm_modal_component/confirm_modal_component"; @import "app/components/vertical_ellipsis_menu/component"; // admin_v3 and only V3 @import "app/webpacker/css/admin/trix.scss"; diff --git a/app/webpacker/css/admin_v3/components/buttons.scss b/app/webpacker/css/admin_v3/components/buttons.scss index 37f3d9d929..0215f75952 100644 --- a/app/webpacker/css/admin_v3/components/buttons.scss +++ b/app/webpacker/css/admin_v3/components/buttons.scss @@ -54,20 +54,16 @@ button:not(.plain):not(.trix-button), &.secondary { background-color: $color-btn-secondary-bg; - border: 1px solid $color-btn-bg; - color: $color-btn-bg; + color: $color-link; &:hover { - background-color: $color-11; - border: 1px solid $color-btn-secondary-hover-bg; - color: $color-btn-secondary-hover-bg; + background-color: $color-btn-secondary-hover-bg; } - &:active, &:focus { - background-color: $color-11; - border: 1px solid $color-4; - color: $color-4; + background-color: $color-btn-secondary-hover-bg; + border-color: $color-link-focus; + color: $color-link-focus; } } diff --git a/app/webpacker/css/admin_v3/globals/variables.scss b/app/webpacker/css/admin_v3/globals/variables.scss index feff9ef373..29d4342278 100644 --- a/app/webpacker/css/admin_v3/globals/variables.scss +++ b/app/webpacker/css/admin_v3/globals/variables.scss @@ -54,7 +54,7 @@ $color-btn-disabled-text: $lighter-grey !default; $color-btn-red-bg: $red !default; $color-btn-red-hover-bg: $roof-terracotta !default; $color-btn-secondary-bg: $white !default; -$color-btn-secondary-hover-bg: $orient !default; +$color-btn-secondary-hover-bg: $mystic !default; // Actions colors $color-action-edit-bg: very-light($teal) !default; diff --git a/app/webpacker/css/darkswarm/all.scss b/app/webpacker/css/darkswarm/all.scss index a78b2c30e2..be25b548d5 100644 --- a/app/webpacker/css/darkswarm/all.scss +++ b/app/webpacker/css/darkswarm/all.scss @@ -77,5 +77,5 @@ ofn-modal { @import "../shared/question-mark-icon"; @import '../admin/shared/scroll_bar'; -@import 'app/components/help_modal_component/help_modal_component'; +@import 'app/components/modal_component/modal_component'; @import 'app/components/confirm_modal_component/confirm_modal_component'; diff --git a/config/locales/en.yml b/config/locales/en.yml index 1838426b45..bd1e28d44e 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -872,6 +872,10 @@ en: reset: Discard changes bulk_update: success: Changes saved + edit_image: + title: Edit product photo + close: Back + upload: Upload photo delete_product: success: Successfully deleted the product error: Unable to delete the product diff --git a/spec/javascripts/stimulus/help_modal_controller_test.js b/spec/javascripts/stimulus/help_modal_controller_test.js index 1120ede695..944cdea04c 100644 --- a/spec/javascripts/stimulus/help_modal_controller_test.js +++ b/spec/javascripts/stimulus/help_modal_controller_test.js @@ -34,7 +34,7 @@ describe("HelpModalController", () => { data-action="click->help-modal#close">