diff --git a/app/views/admin/products_v3/_table.html.haml b/app/views/admin/products_v3/_table.html.haml index 95dbf74398..b463b93adc 100644 --- a/app/views/admin/products_v3/_table.html.haml +++ b/app/views/admin/products_v3/_table.html.haml @@ -21,6 +21,7 @@ %col{ width:"10%" } %col{ width:"5%" } %col{ width:"5%", style: "max-width:5em" } + %col{ width:"5%", style: "max-width:5em" } %thead %tr %th.align-left.with-input= t('admin.products_page.columns.name') @@ -32,6 +33,7 @@ %th.align-left= t('admin.products_page.columns.category') %th.align-left= t('admin.products_page.columns.tax_category') %th.align-left= t('admin.products_page.columns.inherits_properties') + %th.align-right= t('admin.products_page.columns.actions') - products.each do |product| = form.fields_for("products", product, index: nil) do |product_form| %tbody.relaxed{ 'data-record-id': product_form.object.id } @@ -58,6 +60,8 @@ %td.align-left %td.align-left .line-clamp-1= product.inherits_properties ? 'YES' : 'NO' #TODO: consider using https://github.com/RST-J/human_attribute_values, else use I18n.t (also below) + %td.align-right + = render partial: 'admin/products_v3/components/product_actions', locals: { product: product } - product.variants.each do |variant| - prefix = "[products][][variants_attributes][]" # Couldn't convince the formbuilder to generate this for me, so for now we manually add the prefix = form.fields_for(variant) do |variant_form| @@ -81,3 +85,5 @@ .line-clamp-1= variant.tax_category&.name || "None" # TODO: convert to dropdown, else translate hardcoded string. %td.align-left -# empty + %td.align-right + = render partial: 'admin/products_v3/components/product_actions', locals: { product: product, variant: variant } diff --git a/app/views/admin/products_v3/components/_product_actions.html.haml b/app/views/admin/products_v3/components/_product_actions.html.haml new file mode 100644 index 0000000000..a465498eac --- /dev/null +++ b/app/views/admin/products_v3/components/_product_actions.html.haml @@ -0,0 +1,7 @@ +.vertical-ellipsis-menu{ "data-controller": "vertical-ellipsis-menu" } + %i.fa.fa-ellipsis-v{ "data-action": "click->vertical-ellipsis-menu#toggle" } + .vertical-ellipsis-menu-content{ "data-vertical-ellipsis-menu-target": "content" } + - if defined?(variant) + = link_to t('admin.products_page.actions.edit'), edit_admin_product_variant_path(product, variant), class: "vertical-ellipsis-menu-content-item" + - else + = link_to t('admin.products_page.actions.edit'), edit_admin_product_path(product), class: "vertical-ellipsis-menu-content-item" diff --git a/app/webpacker/controllers/vertical_ellipsis_menu_controller.js b/app/webpacker/controllers/vertical_ellipsis_menu_controller.js new file mode 100644 index 0000000000..c783adf170 --- /dev/null +++ b/app/webpacker/controllers/vertical_ellipsis_menu_controller.js @@ -0,0 +1,25 @@ +import { Controller } from "stimulus"; + +export default class extends Controller { + static targets = ["content"]; + + connect() { + super.connect(); + window.addEventListener("click", this.#hideIfClickedOutside); + } + + toggle() { + this.contentTarget.classList.toggle("show"); + } + + #hideIfClickedOutside = (event) => { + if (this.element.contains(event.target)) { + return; + } + this.#hide(); + }; + + #hide() { + this.contentTarget.classList.remove("show"); + } +} diff --git a/app/webpacker/css/admin_v3/all.scss b/app/webpacker/css/admin_v3/all.scss index d9358e7a1b..f2d6fe5bd4 100644 --- a/app/webpacker/css/admin_v3/all.scss +++ b/app/webpacker/css/admin_v3/all.scss @@ -113,6 +113,7 @@ @import "../admin/reports"; @import "components/select2"; // admin_v3 @import "components/sidebar-item"; // admin_v3 +@import "components/vertical_ellipsis_menu"; // admin_v3 and only V3 @import "../admin/side_menu"; @import "../admin/tables"; @import "../admin/tag_rules"; diff --git a/app/webpacker/css/admin_v3/components/vertical_ellipsis_menu.scss b/app/webpacker/css/admin_v3/components/vertical_ellipsis_menu.scss new file mode 100644 index 0000000000..de35c98455 --- /dev/null +++ b/app/webpacker/css/admin_v3/components/vertical_ellipsis_menu.scss @@ -0,0 +1,62 @@ +.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; + } + + .vertical-ellipsis-menu-content { + position: absolute; + top: 0; + right: 0; + padding-top: 5px; + padding-bottom: 5px; + background-color: white; + @include defaultBoxShadow; + border-radius: 3px; + min-width: 80px; + display: none; + z-index: 100; + + &.show { + display: block; + } + + .vertical-ellipsis-menu-content-item { + display: block; + padding: 5px 10px; + cursor: pointer; + text-align: left; + border-left: 3px solid white; + color: $near-black; + text-decoration: none; + border-bottom: none; + + &:hover { + background-color: $light-grey; + border-left: 3px solid $spree-blue; + } + + &.delete { + color: $red; + + &:hover { + border-left: 3px solid $red; + background-color: $fair-pink; + } + } + } + } +} + +table.products td .vertical-ellipsis-menu { + float: right; +} diff --git a/config/locales/en.yml b/config/locales/en.yml index 56aac72d3c..de1194ca81 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -550,6 +550,7 @@ en: tax_category: "Tax Category" inherits_properties: "Inherits Properties?" import_date: "Import Date" + actions: Actions columns_selector: unit: Unit price: Price @@ -561,6 +562,8 @@ en: tax_category: "Tax Category" inherits_properties: "Inherits Properties?" import_date: "Import Date" + actions: + edit: Edit adjustments: skipped_changing_canceled_order: "You can't change a cancelled order." # Common properties / models diff --git a/spec/javascripts/stimulus/vertical_ellipsis_menu_controller_test.js b/spec/javascripts/stimulus/vertical_ellipsis_menu_controller_test.js new file mode 100644 index 0000000000..da53c53a14 --- /dev/null +++ b/spec/javascripts/stimulus/vertical_ellipsis_menu_controller_test.js @@ -0,0 +1,48 @@ +/** + * @jest-environment jsdom + */ + +import { Application } from "stimulus"; +import vertical_ellipsis_menu_controller from "../../../app/webpacker/controllers/vertical_ellipsis_menu_controller"; + +describe("VerticalEllipsisMenuController test", () => { + beforeAll(() => { + const application = Application.start(); + application.register("vertical-ellipsis-menu", vertical_ellipsis_menu_controller); + }); + + beforeEach(() => { + document.body.innerHTML = ` +