From efcaab5debb79c7180b6a50fb70df4e869d4f05c Mon Sep 17 00:00:00 2001 From: David Cook Date: Fri, 23 Jun 2023 16:02:53 +1000 Subject: [PATCH 1/7] Rename colour variables --- .../css/admin_v3/components/navigation.scss | 24 ++--- .../css/admin_v3/components/pagination.scss | 14 +-- .../css/admin_v3/globals/palette.scss | 29 ++++-- .../css/admin_v3/globals/variables.scss | 90 +++++++++---------- app/webpacker/css/admin_v3/shared/layout.scss | 12 +-- app/webpacker/css/admin_v3/shared/tables.scss | 30 +++---- 6 files changed, 105 insertions(+), 94 deletions(-) diff --git a/app/webpacker/css/admin_v3/components/navigation.scss b/app/webpacker/css/admin_v3/components/navigation.scss index 3291225c01..ba50629d03 100644 --- a/app/webpacker/css/admin_v3/components/navigation.scss +++ b/app/webpacker/css/admin_v3/components/navigation.scss @@ -23,13 +23,13 @@ nav.menu { } &.active a { - color: $color-2; + color: $green; border-left-width: 0; - border-bottom-color: $color-2; + border-bottom-color: $green; } &:hover a { - color: $color-2; + color: $green; } } } @@ -53,7 +53,7 @@ nav.menu { &:hover { i { - color: $color-2; + color: $green; } } } @@ -76,7 +76,7 @@ nav.menu { a { display: block; padding: 25px 5px; - color: $color-9 !important; + color: $dark-grey !important; position: relative; text-align: center; font-weight: 600; @@ -87,8 +87,8 @@ nav.menu { } &:hover { - color: $color-5 !important; - border-bottom: 2px solid $color-5; + color: $red !important; + border-bottom: 2px solid $red; } span.text { @@ -103,7 +103,7 @@ nav.menu { .dropdown { width: 300px; - background-color: $color-3; + background-color: $teal; width: 200px; z-index: 100000; @@ -124,13 +124,13 @@ nav.menu { #sub-menu { padding-bottom: 0; - box-shadow: 0px 1px 0px $color-7; + box-shadow: 0px 1px 0px $light-grey; li { a { display: block; padding: 12px 20px; - color: $color-9; + color: $dark-grey; text-align: center; position: relative; font-size: 14px; @@ -138,8 +138,8 @@ nav.menu { &.selected a, a:hover { - color: $color-5; - border-bottom: 2px solid $color-5; + color: $red; + border-bottom: 2px solid $red; } } } diff --git a/app/webpacker/css/admin_v3/components/pagination.scss b/app/webpacker/css/admin_v3/components/pagination.scss index 6c14a1e787..dc269c4227 100644 --- a/app/webpacker/css/admin_v3/components/pagination.scss +++ b/app/webpacker/css/admin_v3/components/pagination.scss @@ -3,7 +3,7 @@ margin: 2em 0 1em; padding: 10px 0; - background-color: $color-7; + background-color: $light-grey; .page { padding: 5px 8px; @@ -12,22 +12,22 @@ text-align: center; &.current { - background-color: $color-2; + background-color: $green; border-radius: 3px; - color: $color-1; + color: $white; } } button { margin: 0 0.35em; - background-color: $color-1; - color: $color-8; + background-color: $white; + color: $near-black; box-shadow: $color-btn-shadow; &.active { - color: $color-1; - background-color: $color-5; + color: $white; + background-color: $red; cursor: default; } diff --git a/app/webpacker/css/admin_v3/globals/palette.scss b/app/webpacker/css/admin_v3/globals/palette.scss index 6130500366..a5f0777b9b 100644 --- a/app/webpacker/css/admin_v3/globals/palette.scss +++ b/app/webpacker/css/admin_v3/globals/palette.scss @@ -1,10 +1,21 @@ // Basic color palette for admin styles v3 -$color-1: #ffffff !default; // White -$color-2: #9fc820 !default; // Green -$color-3: #008397 !default; // Teal (Allports) -$color-4: #004e5b !default; // Dark Blue (Sherpa) -$color-5: #c85136 !default; // Red/Orange (Mojo) -$color-6: #ff9300 !default; // Yellow -$color-7: #eff1f2 !default; // Light grey -$color-8: #191c1d !default; // Near-black -$color-9: #2e3132 !default; // Dark Grey +$white: #ffffff !default; // White +$green: #9fc820 !default; // Green +$teal: #008397 !default; // Teal (Allports) +$dark-blue: #004e5b !default; // Dark Blue (Sherpa) +$red: #c85136 !default; // Red/Orange (Mojo) +$yellow: #ff9300 !default; // Yellow +$light-grey: #eff1f2 !default; // Light grey +$near-black: #191c1d !default; // Near-black +$dark-grey: #2e3132 !default; // Dark Grey + +// Old colour variables for backwards compatibility +$color-1: $white; +$color-2: $green; +$color-3: $teal; +$color-4: $dark-blue; +$color-5: $red; +$color-6: $yellow; +$color-7: $light-grey; +$color-8: $near-black; +$color-9: $dark-grey; diff --git a/app/webpacker/css/admin_v3/globals/variables.scss b/app/webpacker/css/admin_v3/globals/variables.scss index c49ee66953..67a37c2f9f 100644 --- a/app/webpacker/css/admin_v3/globals/variables.scss +++ b/app/webpacker/css/admin_v3/globals/variables.scss @@ -10,32 +10,32 @@ $base-font-family: "Open Sans", "Helvetica Neue", "Helvetica", Helvetica, Arial, //-------------------------------------------------------------- // Body base colors -$color-body-bg: $color-1 !default; -$color-body-text: $color-8 !default; -$color-headers: $color-4 !default; -$color-link: $color-3 !default; +$color-body-bg: $white !default; +$color-body-text: $near-black !default; +$color-headers: $dark-blue !default; +$color-link: $teal !default; $color-link-hover: lighten($color-link, 2) !default; -$color-link-active: $color-2 !default; -$color-link-focus: $color-2 !default; -$color-link-visited: $color-3 !default; -$color-border: $color-7 !default; +$color-link-active: $green !default; +$color-link-focus: $green !default; +$color-link-visited: $teal !default; +$color-border: $light-grey !default; // Basic flash colors -$color-success: $color-2 !default; -$color-notice: $color-6 !default; -$color-error: $color-5 !default; +$color-success: $green !default; +$color-notice: $yellow !default; +$color-error: $red !default; // Table colors -$color-tbl-cell-bg: $color-1 !default; +$color-tbl-cell-bg: $white !default; $color-tbl-thead-txt: $color-headers !default; -$color-tbl-thead-bg: $color-7 !default; +$color-tbl-thead-bg: $light-grey !default; // Button colors -$color-btn-bg: $color-3 !default; -$color-btn-text: $color-1 !default; +$color-btn-bg: $teal !default; +$color-btn-text: $white !default; $color-btn-shadow: 0px 1px 0px rgba(0, 0, 0, 0.05), 0px 2px 2px rgba(0, 0, 0, 0.07) !default; $color-btn-hover-bg: lighten($color-btn-bg, 2) !default; -$color-btn-hover-text: $color-1 !default; +$color-btn-hover-text: $white !default; // Actions colors $color-action-edit-bg: very-light($color-success, 5 ) !default; @@ -56,65 +56,65 @@ $color-action-mail-bg: very-light($color-success, 5 ) !default; $color-action-mail-brd: very-light($color-success, 20 ) !default; // Select2 select field colors -$color-sel-bg: $color-3 !default; -$color-sel-text: $color-1 !default; +$color-sel-bg: $teal !default; +$color-sel-text: $white !default; $color-sel-hover-bg: lighten($color-sel-bg, 2) !default; -$color-sel-hover-text: $color-1 !default; +$color-sel-hover-text: $white !default; // Text inputs colors $color-txt-brd: $color-border !default; -$color-txt-text: $color-8 !default; -$color-txt-hover-brd: $color-3 !default; +$color-txt-text: $near-black !default; +$color-txt-hover-brd: $teal !default; // States label colors $color-ste-complete-bg: $color-success !default; -$color-ste-complete-text: $color-1 !default; +$color-ste-complete-text: $white !default; $color-ste-completed-bg: $color-success !default; -$color-ste-completed-text: $color-1 !default; +$color-ste-completed-text: $white !default; $color-ste-sold-bg: $color-success !default; -$color-ste-sold-text: $color-1 !default; +$color-ste-sold-text: $white !default; $color-ste-pending-bg: $color-notice !default; -$color-ste-pending-text: $color-1 !default; +$color-ste-pending-text: $white !default; $color-ste-requires_authorization-bg: $color-notice !default; -$color-ste-requires_authorization-text: $color-1 !default; +$color-ste-requires_authorization-text: $white !default; $color-ste-awaiting_return-bg: $color-notice !default; -$color-ste-awaiting_return-text: $color-1 !default; +$color-ste-awaiting_return-text: $white !default; $color-ste-returned-bg: $color-notice !default; -$color-ste-returned-text: $color-1 !default; +$color-ste-returned-text: $white !default; $color-ste-credit_owed-bg: $color-notice !default; -$color-ste-credit_owed-text: $color-1 !default; +$color-ste-credit_owed-text: $white !default; $color-ste-paid-bg: $color-success !default; -$color-ste-paid-text: $color-1 !default; +$color-ste-paid-text: $white !default; $color-ste-shipped-bg: $color-success !default; -$color-ste-shipped-text: $color-1 !default; +$color-ste-shipped-text: $white !default; $color-ste-balance_due-bg: $color-notice !default; -$color-ste-balance_due-text: $color-1 !default; +$color-ste-balance_due-text: $white !default; $color-ste-backorder-bg: $color-notice !default; -$color-ste-backorder-text: $color-1 !default; +$color-ste-backorder-text: $white !default; $color-ste-none-bg: $color-error !default; -$color-ste-none-text: $color-1 !default; +$color-ste-none-text: $white !default; $color-ste-ready-bg: $color-success !default; -$color-ste-ready-text: $color-1 !default; +$color-ste-ready-text: $white !default; $color-ste-void-bg: $color-error !default; -$color-ste-void-text: $color-1 !default; +$color-ste-void-text: $white !default; $color-ste-canceled-bg: $color-error !default; -$color-ste-canceled-text: $color-1 !default; +$color-ste-canceled-text: $white !default; $color-ste-address-bg: $color-error !default; -$color-ste-address-text: $color-1 !default; +$color-ste-address-text: $white !default; $color-ste-checkout-bg: $color-notice !default; -$color-ste-checkout-text: $color-1 !default; +$color-ste-checkout-text: $white !default; $color-ste-cart-bg: $color-notice !default; -$color-ste-cart-text: $color-1 !default; +$color-ste-cart-text: $white !default; $color-ste-payment-bg: $color-error !default; -$color-ste-payment-text: $color-1 !default; +$color-ste-payment-text: $white !default; $color-ste-delivery-bg: $color-success !default; -$color-ste-delivery-text: $color-1 !default; +$color-ste-delivery-text: $white !default; $color-ste-confirmation-bg: $color-error !default; -$color-ste-confirmation-text: $color-1 !default; +$color-ste-confirmation-text: $white !default; $color-ste-active-bg: $color-success !default; -$color-ste-active-text: $color-1 !default; +$color-ste-active-text: $white !default; $color-ste-inactive-bg: $color-notice !default; -$color-ste-inactive-text: $color-1 !default; +$color-ste-inactive-text: $white !default; // Available states $states: completed, complete, sold, pending, awaiting_return, returned, credit_owed, paid, shipped, balance_due, backorder, checkout, cart, address, delivery, payment, confirmation, canceled, ready, void, requires_authorization, active, inactive !default; diff --git a/app/webpacker/css/admin_v3/shared/layout.scss b/app/webpacker/css/admin_v3/shared/layout.scss index c5cd8c71e2..addd363521 100644 --- a/app/webpacker/css/admin_v3/shared/layout.scss +++ b/app/webpacker/css/admin_v3/shared/layout.scss @@ -12,19 +12,19 @@ margin-top: 25px; h1 { - color: $color-8; + color: $near-black; } .ofn-drop-down { border: 0; background-color: $spree-blue; - color: $color-1; + color: $white; float: none; margin-left: 3px; &:hover, &.expanded { border: 0; - color: $color-1; + color: $white; } } @@ -97,7 +97,7 @@ // Header //--------------------------------------------------- #header { - background-color: $color-1; + background-color: $white; padding: 5px 0; } @@ -107,14 +107,14 @@ .page-title { i { - color: $color-2; + color: $green; } } // Content //--------------------------------------------------- #content { - background-color: $color-1; + background-color: $white; position: relative; z-index: 0; padding: 0; diff --git a/app/webpacker/css/admin_v3/shared/tables.scss b/app/webpacker/css/admin_v3/shared/tables.scss index 923e0bd481..46b20cf789 100644 --- a/app/webpacker/css/admin_v3/shared/tables.scss +++ b/app/webpacker/css/admin_v3/shared/tables.scss @@ -44,7 +44,7 @@ table { [class*="icon-"].no-text { font-size: 120%; - background-color: very-light($color-3); + background-color: very-light($teal); border: 1px solid $color-border; border-radius: 15px; width: 29px; @@ -74,29 +74,29 @@ table { padding-left: 0px; &:hover { - background-color: $color-3; - color: $color-1; + background-color: $teal; + color: $white; } } .icon-trash:hover, .icon-void:hover { background-color: $color-error; - color: $color-1; + color: $white; } .icon-cancel:hover { background-color: $color-notice; - color: $color-1; + color: $white; } .icon-edit:hover, .icon-capture:hover, .icon-ok:hover, .icon-plus:hover { background-color: $color-success; - color: $color-1; + color: $white; } .icon-copy:hover { background-color: $color-notice; - color: $color-1; + color: $white; } } @@ -144,7 +144,7 @@ table { } &:hover td { - background-color: very-light($color-3, 5); + background-color: very-light($teal, 5); img { border: 1px solid $color-border; @@ -157,7 +157,7 @@ table { } &.ui-sortable-placeholder td { - border: 1px solid $color-2 !important; + border: 1px solid $green !important; visibility: visible !important; &.actions { @@ -165,7 +165,7 @@ table { border-right: none !important; border-top: none !important; border-bottom: none !important; - border-left: 1px solid $color-2 !important; + border-left: 1px solid $green !important; } } @@ -173,7 +173,7 @@ table { width: 100%; td { - background-color: lighten($color-3, 33); + background-color: lighten($teal, 33); border-bottom: 1px solid $color-border; &.actions { @@ -189,15 +189,15 @@ table { &.grand-total { td { - border-color: $color-2 !important; + border-color: $green !important; text-transform: uppercase; font-size: 110%; font-weight: 600; - background-color: lighten($color-2, 50); + background-color: lighten($green, 50); } .total { - background-color: $color-2; - color: $color-1; + background-color: $green; + color: $white; } } } From 841192fb962b077bcbdf8eeaac1abf910c9b7b10 Mon Sep 17 00:00:00 2001 From: David Cook Date: Fri, 23 Jun 2023 15:37:30 +1000 Subject: [PATCH 2/7] Add new products page Hidden behind admin_style_v3 feature toggle. --- app/controllers/admin/products_v3_controller.rb | 7 +++++++ app/views/admin/products_v3/index.html.haml | 9 +++++++++ config/locales/en.yml | 5 ++++- config/routes/admin.rb | 3 +++ 4 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 app/controllers/admin/products_v3_controller.rb create mode 100644 app/views/admin/products_v3/index.html.haml diff --git a/app/controllers/admin/products_v3_controller.rb b/app/controllers/admin/products_v3_controller.rb new file mode 100644 index 0000000000..ede851965d --- /dev/null +++ b/app/controllers/admin/products_v3_controller.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module Admin + class ProductsV3Controller < Spree::Admin::BaseController + def index; end + end +end diff --git a/app/views/admin/products_v3/index.html.haml b/app/views/admin/products_v3/index.html.haml new file mode 100644 index 0000000000..00c53d0557 --- /dev/null +++ b/app/views/admin/products_v3/index.html.haml @@ -0,0 +1,9 @@ +- content_for :page_title do + = t('.header.title') +- content_for :page_actions do + %div{ :class => "toolbar" } + %ul{ :class => "actions header-action-links inline-menu" } + %li#new_product_link + = button_link_to t(:new_product), "/admin/products/new", { :icon => 'icon-plus', :id => 'admin_new_product' } + += render partial: 'spree/admin/shared/product_sub_menu' diff --git a/config/locales/en.yml b/config/locales/en.yml index 22acda77a9..66d2b07a14 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -764,7 +764,10 @@ en: images: "Images" variants: "Variants" product_properties: "Product Properties" - + products_v3: + index: + header: + title: Bulk Edit Products product_import: title: Product Import file_not_found: File not found or could not be opened diff --git a/config/routes/admin.rb b/config/routes/admin.rb index 69e2186cd0..be892dfb77 100644 --- a/config/routes/admin.rb +++ b/config/routes/admin.rb @@ -72,6 +72,9 @@ Openfoodnetwork::Application.routes.draw do constraints FeatureToggleConstraint.new(:new_products_page) do get '/new_products', to: 'products#index' end + constraints FeatureToggleConstraint.new(:admin_style_v3) do + get '/products_v3', to: 'products_v3#index' + end resources :variant_overrides do post :bulk_update, on: :collection From 809c15b1972768558f204fbea2656ea9eae4984d Mon Sep 17 00:00:00 2001 From: David Cook Date: Fri, 23 Jun 2023 15:47:24 +1000 Subject: [PATCH 3/7] Load products page with reflex We will add the products in the next commit. --- app/reflexes/admin/products_v3_reflex.rb | 15 ++++ .../admin/products_v3/_content.html.haml | 7 ++ app/views/admin/products_v3/_table.html.haml | 1 + app/views/admin/products_v3/index.html.haml | 6 ++ .../controllers/productsV3_controller.js | 24 ++++++ .../css/admin_v3/components/spinner.scss | 73 +++++++++++++++++++ app/webpacker/packs/admin-style-v3.scss | 2 + config/locales/en.yml | 4 + 8 files changed, 132 insertions(+) create mode 100644 app/reflexes/admin/products_v3_reflex.rb create mode 100644 app/views/admin/products_v3/_content.html.haml create mode 100644 app/views/admin/products_v3/_table.html.haml create mode 100644 app/webpacker/controllers/productsV3_controller.js create mode 100644 app/webpacker/css/admin_v3/components/spinner.scss diff --git a/app/reflexes/admin/products_v3_reflex.rb b/app/reflexes/admin/products_v3_reflex.rb new file mode 100644 index 0000000000..2b507593fb --- /dev/null +++ b/app/reflexes/admin/products_v3_reflex.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Admin + class ProductsV3Reflex < ApplicationReflex + + def fetch + cable_ready.replace( + selector: "#products-content", + html: render(partial: "admin/products_v3/content") + ).broadcast + + morph :nothing + end + end +end diff --git a/app/views/admin/products_v3/_content.html.haml b/app/views/admin/products_v3/_content.html.haml new file mode 100644 index 0000000000..8a572543b3 --- /dev/null +++ b/app/views/admin/products_v3/_content.html.haml @@ -0,0 +1,7 @@ +#no-products + = t('.no_products_found') + #no-products-actions + %a{ href: "/admin/products/new", class: "button icon-plus", icon: "icon-plus" } + = t(:new_product) + %a{ href: "/admin/products/import", class: "button icon-upload secondary", icon: "icon-upload" } + = t(".import_products") diff --git a/app/views/admin/products_v3/_table.html.haml b/app/views/admin/products_v3/_table.html.haml new file mode 100644 index 0000000000..15db8e632c --- /dev/null +++ b/app/views/admin/products_v3/_table.html.haml @@ -0,0 +1 @@ +%table.products diff --git a/app/views/admin/products_v3/index.html.haml b/app/views/admin/products_v3/index.html.haml index 00c53d0557..6304780b1f 100644 --- a/app/views/admin/products_v3/index.html.haml +++ b/app/views/admin/products_v3/index.html.haml @@ -7,3 +7,9 @@ = button_link_to t(:new_product), "/admin/products/new", { :icon => 'icon-plus', :id => 'admin_new_product' } = render partial: 'spree/admin/shared/product_sub_menu' + +#products_v3_page{"data-controller": "productsV3"} + #loading-spinner.spinner-container{"data-productsV3-target": "loading"} + .spinner + = t('.loading') + #products-content diff --git a/app/webpacker/controllers/productsV3_controller.js b/app/webpacker/controllers/productsV3_controller.js new file mode 100644 index 0000000000..9a034b69e0 --- /dev/null +++ b/app/webpacker/controllers/productsV3_controller.js @@ -0,0 +1,24 @@ +import ApplicationController from "./application_controller"; + +export default class extends ApplicationController { + static targets = ["loading"]; + + connect() { + super.connect(); + // Fetch the products on page load + this.load(); + } + + load = () => { + this.showLoading(); + this.stimulate("Admin::ProductsV3#fetch").then(() => this.hideLoading()); + }; + + hideLoading = () => { + this.loadingTarget.classList.add("hidden"); + }; + + showLoading = () => { + this.loadingTarget.classList.remove("hidden"); + }; +} diff --git a/app/webpacker/css/admin_v3/components/spinner.scss b/app/webpacker/css/admin_v3/components/spinner.scss new file mode 100644 index 0000000000..1a965e3c22 --- /dev/null +++ b/app/webpacker/css/admin_v3/components/spinner.scss @@ -0,0 +1,73 @@ +.spinner-container { + position: absolute; + width: 100%; + height: 100%; + min-height: 200px; + display: flex; + justify-content: flex-start; + align-items: center; + flex-direction: column; + gap: 40px; + font-size: 24px; + background: rgba(255, 255, 255, 0.8); + + &.hidden { + display: none; + } + + > .spinner { + width: 56px; + height: 56px; + border-radius: 50%; + border: 9px solid $teal; + animation: spinner-bulqg1 0.8s infinite linear alternate, spinner-oaa3wk 1.6s infinite linear; + } +} + +@keyframes spinner-bulqg1 { + 0% { + clip-path: polygon(50% 50%, 0 0, 50% 0%, 50% 0%, 50% 0%, 50% 0%, 50% 0%); + } + + 12.5% { + clip-path: polygon(50% 50%, 0 0, 50% 0%, 100% 0%, 100% 0%, 100% 0%, 100% 0%); + } + + 25% { + clip-path: polygon(50% 50%, 0 0, 50% 0%, 100% 0%, 100% 100%, 100% 100%, 100% 100%); + } + + 50% { + clip-path: polygon(50% 50%, 0 0, 50% 0%, 100% 0%, 100% 100%, 50% 100%, 0% 100%); + } + + 62.5% { + clip-path: polygon(50% 50%, 100% 0, 100% 0%, 100% 0%, 100% 100%, 50% 100%, 0% 100%); + } + + 75% { + clip-path: polygon(50% 50%, 100% 100%, 100% 100%, 100% 100%, 100% 100%, 50% 100%, 0% 100%); + } + + 100% { + clip-path: polygon(50% 50%, 50% 100%, 50% 100%, 50% 100%, 50% 100%, 50% 100%, 0% 100%); + } +} + +@keyframes spinner-oaa3wk { + 0% { + transform: scaleY(1) rotate(0deg); + } + + 49.99% { + transform: scaleY(1) rotate(135deg); + } + + 50% { + transform: scaleY(-1) rotate(0deg); + } + + 100% { + transform: scaleY(-1) rotate(-135deg); + } +} diff --git a/app/webpacker/packs/admin-style-v3.scss b/app/webpacker/packs/admin-style-v3.scss index f06ef083d5..4cbab328cd 100644 --- a/app/webpacker/packs/admin-style-v3.scss +++ b/app/webpacker/packs/admin-style-v3.scss @@ -1 +1,3 @@ @import "../css/admin_v3/all.scss"; + +@import "../css/admin_v3/components/spinner.scss"; diff --git a/config/locales/en.yml b/config/locales/en.yml index 66d2b07a14..422f199e1b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -768,6 +768,10 @@ en: index: header: title: Bulk Edit Products + loading: Loading your products + content: + no_products_found: No products found + import_products: Import multiple products product_import: title: Product Import file_not_found: File not found or could not be opened From 6a2025b2712a25d152c1252a68efdef6e23572e9 Mon Sep 17 00:00:00 2001 From: David Cook Date: Fri, 23 Jun 2023 16:20:18 +1000 Subject: [PATCH 4/7] Add products table With ellipsis clipping for long lines. --- app/reflexes/admin/products_v3_reflex.rb | 35 ++++++++++++++- .../admin/products_v3/_content.html.haml | 17 ++++--- app/views/admin/products_v3/_table.html.haml | 38 ++++++++++++++++ app/webpacker/css/admin/products_v3.scss | 44 +++++++++++++++++++ .../css/admin_v3/globals/variables.scss | 4 +- app/webpacker/css/admin_v3/shared/tables.scss | 5 ++- app/webpacker/css/shared/utilities.scss | 11 +++++ 7 files changed, 144 insertions(+), 10 deletions(-) create mode 100644 app/webpacker/css/admin/products_v3.scss diff --git a/app/reflexes/admin/products_v3_reflex.rb b/app/reflexes/admin/products_v3_reflex.rb index 2b507593fb..0e36ae2762 100644 --- a/app/reflexes/admin/products_v3_reflex.rb +++ b/app/reflexes/admin/products_v3_reflex.rb @@ -2,14 +2,47 @@ module Admin class ProductsV3Reflex < ApplicationReflex + before_reflex :fetch_products, only: [:fetch] def fetch cable_ready.replace( selector: "#products-content", - html: render(partial: "admin/products_v3/content") + html: render(partial: "admin/products_v3/content", locals: { products: @products }) ).broadcast morph :nothing end + + private + + # copied from ProductsTableComponent + def fetch_products + product_query = OpenFoodNetwork::Permissions.new(current_user) + .editable_products.merge(product_scope) + @products = product_query.order(:name).limit(50) + end + + def product_scope + scope = if current_user.has_spree_role?("admin") || current_user.enterprises.present? + Spree::Product + else + Spree::Product.active + end + + scope.includes(product_query_includes) + end + + # Optimise by pre-loading required columns + def product_query_includes + # TODO: add other fields used in columns? (eg supplier: [:name]) + [ + # variants: [ + # :default_price, + # :stock_locations, + # :stock_items, + # :variant_overrides + # ] + ] + end end end diff --git a/app/views/admin/products_v3/_content.html.haml b/app/views/admin/products_v3/_content.html.haml index 8a572543b3..2c076973c6 100644 --- a/app/views/admin/products_v3/_content.html.haml +++ b/app/views/admin/products_v3/_content.html.haml @@ -1,7 +1,10 @@ -#no-products - = t('.no_products_found') - #no-products-actions - %a{ href: "/admin/products/new", class: "button icon-plus", icon: "icon-plus" } - = t(:new_product) - %a{ href: "/admin/products/import", class: "button icon-upload secondary", icon: "icon-upload" } - = t(".import_products") +- if products.any? + = render partial: 'table', locals: { products: products } +- else + #no-products + = t('.no_products_found') + #no-products-actions + %a{ href: "/admin/products/new", class: "button icon-plus", icon: "icon-plus" } + = t(:new_product) + %a{ href: "/admin/products/import", class: "button icon-upload secondary", icon: "icon-upload" } + = t(".import_products") diff --git a/app/views/admin/products_v3/_table.html.haml b/app/views/admin/products_v3/_table.html.haml index 15db8e632c..67ad3e8cd7 100644 --- a/app/views/admin/products_v3/_table.html.haml +++ b/app/views/admin/products_v3/_table.html.haml @@ -1 +1,39 @@ %table.products + %col{ width:"15%" } + %col{ width:"5%", style: "max-width:5em" } + %col{ width:"5%", style: "max-width:5em" } + %col{ width:"5%", style: "max-width:5em"} + - # producer + %col{ width:"10%" } + %col{ width:"10%" } + %col{ width:"5%" } + %col{ width:"5%", style: "max-width:5em" } + %thead + %tr + %th.align-left= t('admin.product.name') + %th.align-right= t('admin.sku') + %th.align-right= t('admin.unit') + %th.align-right= t('admin.on_hand') + %th.align-left= t('admin.producer') + %th.align-left= t('admin.category') + %th.align-left= t('admin.tax_category') + %th.align-left= t('admin.inherits_properties') + %tbody + - products.each do |product| + %tr + %td.align-left.header + .line-clamp-1= product.name + %td.align-right + .line-clamp-1= product.sku + %td.align-right + .line-clamp-1= "#{product.unit_value&.round(3)} #{product.variant_unit}" + %td.align-right + .line-clamp-1= product.on_hand || 0 + %td.align-left + .line-clamp-1= product.supplier.name + %td.align-left + .line-clamp-1= product.taxons.map(&:name).join(', ') + %td.align-left + .line-clamp-1= product.tax_category&.name + %td.align-left + .line-clamp-1= product.inherits_properties ? 'YES' : 'NO' #TODO: consider using https://github.com/RST-J/human_attribute_values diff --git a/app/webpacker/css/admin/products_v3.scss b/app/webpacker/css/admin/products_v3.scss new file mode 100644 index 0000000000..ea314b549a --- /dev/null +++ b/app/webpacker/css/admin/products_v3.scss @@ -0,0 +1,44 @@ +// Customisations for the new Bulk Edit Products page only +.products_v3_page { + // Hopefully these rules will be moved to component(s). + table.products { + table-layout: fixed; // Column widths are based solely on col definitions (not content). This allows more efficient rendering. + + background-color: $color-tbl-bg; + padding: 4px; + border-collapse: separate; // This is needed for the outer padding. Also should be helpful to give more flexibility of borders between rows. + + th, + td { + padding: $padding-tbl-cell; + border: none; + } + + th { + // Clip long content in headers, but allow wrapping + overflow: hidden; + text-overflow: clip; // If colums are so small that headers are clipping, ellipsis are more of a hindrance + } + + td { + background-color: $color-tbl-cell-bg; + } + } + + #no-products { + margin-top: 1em; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + font-size: $h3-size; + gap: 20px; + + #no-products-actions { + display: flex; + justify-content: center; + align-items: center; + gap: 20px; + } + } +} diff --git a/app/webpacker/css/admin_v3/globals/variables.scss b/app/webpacker/css/admin_v3/globals/variables.scss index 67a37c2f9f..494cb9ed5b 100644 --- a/app/webpacker/css/admin_v3/globals/variables.scss +++ b/app/webpacker/css/admin_v3/globals/variables.scss @@ -25,10 +25,12 @@ $color-success: $green !default; $color-notice: $yellow !default; $color-error: $red !default; -// Table colors +// Table styles +$color-tbl-bg: $light-grey !default; $color-tbl-cell-bg: $white !default; $color-tbl-thead-txt: $color-headers !default; $color-tbl-thead-bg: $light-grey !default; +$padding-tbl-cell: 12px 12px; // Button colors $color-btn-bg: $teal !default; diff --git a/app/webpacker/css/admin_v3/shared/tables.scss b/app/webpacker/css/admin_v3/shared/tables.scss index 46b20cf789..4b493c8acb 100644 --- a/app/webpacker/css/admin_v3/shared/tables.scss +++ b/app/webpacker/css/admin_v3/shared/tables.scss @@ -19,6 +19,10 @@ table { border-left: 4px solid $color-border; } + &.header { + font-weight: $font-weight-bold; + } + a { border-bottom: 1px dotted lighten($color-link, 10); @@ -132,7 +136,6 @@ table { border-bottom: none; background-color: $color-tbl-thead-bg; color: $color-tbl-thead-txt; - font-size: 13px; font-weight: $font-weight-bold; } } diff --git a/app/webpacker/css/shared/utilities.scss b/app/webpacker/css/shared/utilities.scss index d34b3b897f..7ee8d0802a 100644 --- a/app/webpacker/css/shared/utilities.scss +++ b/app/webpacker/css/shared/utilities.scss @@ -4,6 +4,17 @@ width: 100%; } +.line-clamp-1 { + // Clip content instead of wrapping to new line + overflow: hidden; + text-overflow: ellipsis; + + display: -webkit-box; + -webkit-line-clamp: 1; /* number of lines to show */ + line-clamp: 1; + -webkit-box-orient: vertical; +} + .no-wrap { white-space: nowrap; } From 9c573f823a1ca5f3a53137dc9a5b931dd79a8638 Mon Sep 17 00:00:00 2001 From: David Cook Date: Tue, 6 Jun 2023 16:28:09 +1000 Subject: [PATCH 5/7] Move .content under main content div The .content div provides overall page margins and a max width, and is already nested inside the nav menus (this allows the nav background to fill the full width of the page. The main content area should be structured the same way, so we can have flexibility needed to allow some screens to use the full page. This doesn't seem to change the layout of any screens in the admin interface. Now the table content can stretch full width --- app/views/admin/products_v3/index.html.haml | 2 ++ app/views/spree/layouts/_admin_body.html.haml | 19 ++++++++++--------- app/views/spree/layouts/admin.html.haml | 2 +- app/views/spree/layouts/bare_admin.html.haml | 6 +++--- app/webpacker/css/admin/products_v3.scss | 7 +++++++ app/webpacker/css/admin_v3/all.scss | 1 + spec/system/admin/order_cycles/simple_spec.rb | 3 ++- 7 files changed, 26 insertions(+), 14 deletions(-) diff --git a/app/views/admin/products_v3/index.html.haml b/app/views/admin/products_v3/index.html.haml index 6304780b1f..2cb442b141 100644 --- a/app/views/admin/products_v3/index.html.haml +++ b/app/views/admin/products_v3/index.html.haml @@ -1,3 +1,5 @@ +- content_for :body_class do + products_v3_page - content_for :page_title do = t('.header.title') - content_for :page_actions do diff --git a/app/views/spree/layouts/_admin_body.html.haml b/app/views/spree/layouts/_admin_body.html.haml index e0710fdf36..b7f91907be 100644 --- a/app/views/spree/layouts/_admin_body.html.haml +++ b/app/views/spree/layouts/_admin_body.html.haml @@ -40,18 +40,19 @@ %ul.admin__section-header__actions = yield :page_actions - .container + - content_class = content_for?(:sidebar) ? "with-sidebar" : "" + #content{class: content_class} .row - - content_class = content_for?(:sidebar) ? "with-sidebar" : "" - #content{:class => content_class} - - if content_for?(:table_filter) - - table_filter_class = content_for?(:sidebar) ? 'twelve columns' : 'sixteen columns' - #table-filter{:class => table_filter_class} - %fieldset - %legend{:align => "center"}= yield :table_filter_title - = yield :table_filter + .container - div_class = content_for?(:sidebar) ? 'twelve columns' : 'sixteen columns' %div{:class => div_class} + - if content_for?(:table_filter) + - table_filter_class = content_for?(:sidebar) ? 'twelve columns' : 'sixteen columns' + #table-filter{:class => table_filter_class} + %fieldset + %legend{:align => "center"}= yield :table_filter_title + = yield :table_filter + = yield - if content_for?(:sidebar) %aside#sidebar.four.columns diff --git a/app/views/spree/layouts/admin.html.haml b/app/views/spree/layouts/admin.html.haml index 98e7cb9ebd..db94f2a79a 100644 --- a/app/views/spree/layouts/admin.html.haml +++ b/app/views/spree/layouts/admin.html.haml @@ -3,7 +3,7 @@ %head = render :partial => 'spree/admin/shared/head' - %body.admin{ "data-turbo": "false" } + %body.admin{ "data-turbo": "false", class: yield(:body_class) } - if content_for?(:main_ng_app_name) - if content_for?(:main_ng_ctrl_name) %div{ "ng-app" => yield(:main_ng_app_name).strip.html_safe, "ng-controller" => yield(:main_ng_ctrl_name).strip.html_safe } diff --git a/app/views/spree/layouts/bare_admin.html.haml b/app/views/spree/layouts/bare_admin.html.haml index 39fe796f84..deeb7cbca8 100644 --- a/app/views/spree/layouts/bare_admin.html.haml +++ b/app/views/spree/layouts/bare_admin.html.haml @@ -13,9 +13,9 @@ %nav.columns.eleven.admin-login-navigation-bar = render partial: "spree/layouts/admin/login_nav" - .container + #content .row - #content + .container %div{:class => "sixteen columns"} = yield - %div \ No newline at end of file + %div diff --git a/app/webpacker/css/admin/products_v3.scss b/app/webpacker/css/admin/products_v3.scss index ea314b549a..1e0fd44683 100644 --- a/app/webpacker/css/admin/products_v3.scss +++ b/app/webpacker/css/admin/products_v3.scss @@ -1,5 +1,12 @@ // Customisations for the new Bulk Edit Products page only .products_v3_page { + #content .container { + // Allow table to extend to full width of available screen space + // TODO: move this to a generic rule, eg body.full-width{}. Then it can be included on any page. + // or even better, create a switch that allows you to yield the page content without the surrounding content class. then you still have control to add the .content div where needed. + max-width: none; + } + // Hopefully these rules will be moved to component(s). table.products { table-layout: fixed; // Column widths are based solely on col definitions (not content). This allows more efficient rendering. diff --git a/app/webpacker/css/admin_v3/all.scss b/app/webpacker/css/admin_v3/all.scss index a58c3491fa..2a56c8a6cc 100644 --- a/app/webpacker/css/admin_v3/all.scss +++ b/app/webpacker/css/admin_v3/all.scss @@ -105,6 +105,7 @@ @import "../admin/orders"; @import "../admin/product_import"; @import "../admin/products"; +@import "../admin/products_v3"; @import "../admin/question-mark-tooltip"; @import "../admin/relationships"; @import "../admin/reports"; diff --git a/spec/system/admin/order_cycles/simple_spec.rb b/spec/system/admin/order_cycles/simple_spec.rb index c05501d633..5718114c80 100644 --- a/spec/system/admin/order_cycles/simple_spec.rb +++ b/spec/system/admin/order_cycles/simple_spec.rb @@ -602,8 +602,9 @@ describe ' uncheck "order_cycle_incoming_exchange_0_variants_#{v2.id}" # And I add a fee and save - scroll_to(page.find_button("Add coordinator fee")) + scroll_to(page.find("save-bar")) click_button 'Add coordinator fee' + scroll_to(page.find("save-bar")) click_button 'Add coordinator fee' click_link 'order_cycle_coordinator_fee_1_remove' expect(page).to have_select 'order_cycle_coordinator_fee_0_id' From 2c14fe0434b6abef4772d0c00630b4b54080bed6 Mon Sep 17 00:00:00 2001 From: David Cook Date: Fri, 16 Jun 2023 15:57:02 +1000 Subject: [PATCH 6/7] Add variant rows and price column --- app/views/admin/products_v3/_table.html.haml | 50 ++++++++++++++++---- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/app/views/admin/products_v3/_table.html.haml b/app/views/admin/products_v3/_table.html.haml index 67ad3e8cd7..21021df320 100644 --- a/app/views/admin/products_v3/_table.html.haml +++ b/app/views/admin/products_v3/_table.html.haml @@ -1,34 +1,43 @@ %table.products %col{ width:"15%" } %col{ width:"5%", style: "max-width:5em" } - %col{ width:"5%", style: "max-width:5em" } + %col{ width:"8%" } %col{ width:"5%", style: "max-width:5em"} - - # producer - %col{ width:"10%" } + %col{ width:"5%", style: "max-width:5em"} + %col{ width:"10%" }= # producer %col{ width:"10%" } %col{ width:"5%" } %col{ width:"5%", style: "max-width:5em" } + %col{ width:"8%", style: "max-width:8em" } %thead %tr %th.align-left= t('admin.product.name') %th.align-right= t('admin.sku') %th.align-right= t('admin.unit') + %th.align-right= t('admin.price') %th.align-right= t('admin.on_hand') %th.align-left= t('admin.producer') %th.align-left= t('admin.category') %th.align-left= t('admin.tax_category') %th.align-left= t('admin.inherits_properties') - %tbody - - products.each do |product| + %th.align-right= t('admin.available_on') + - products.each do |product| + %tbody %tr %td.align-left.header .line-clamp-1= product.name %td.align-right .line-clamp-1= product.sku %td.align-right - .line-clamp-1= "#{product.unit_value&.round(3)} #{product.variant_unit}" + .line-clamp-1 + = product.variant_unit.upcase_first + / TODO: properly handle custom unit names + = WeightsAndMeasures::UNITS[product.variant_unit] && "(" + WeightsAndMeasures::UNITS[product.variant_unit][product.variant_unit_scale]["name"] + ")" %td.align-right - .line-clamp-1= product.on_hand || 0 + -# empty + %td.align-right + -# TODO: new requirement "DISPLAY ON DEMAND IF ALL VARIANTS ARE ON DEMAND". And translate value + .line-clamp-1= if product.variants.all?(&:on_demand) then "On demand" else product.on_hand || 0 end %td.align-left .line-clamp-1= product.supplier.name %td.align-left @@ -36,4 +45,29 @@ %td.align-left .line-clamp-1= product.tax_category&.name %td.align-left - .line-clamp-1= product.inherits_properties ? 'YES' : 'NO' #TODO: consider using https://github.com/RST-J/human_attribute_values + .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 + .line-clamp-1= product.available_on&.strftime('%F') + - product.variants.each do |variant| + %tr + %td.align-left + .line-clamp-1= variant.display_name + %td.align-right + .line-clamp-1= variant.sku + %td.align-right + .line-clamp-1= variant.unit_to_display + %td.align-right + .line-clamp-1= number_to_currency(variant.price) + %td.align-right + .line-clamp-1= variant.on_hand || 0 #TODO: spec for this according to requirements. + %td.align-left + .line-clamp-1= variant.product.supplier.name # same as product + %td.align-left + .line-clamp-1= variant.product.taxons.map(&:name).join(', ') # same as product + %td.align-left + .line-clamp-1= variant.tax_category&.name + %td.align-left + .line-clamp-1= variant.product.inherits_properties ? 'YES' : 'NO' # same as product + %td.align-right + .line-clamp-1= variant.available_on&.strftime('%F') + From f28088112615ff0206827305230ec4d6924fd8d7 Mon Sep 17 00:00:00 2001 From: David Cook Date: Thu, 22 Jun 2023 10:19:54 +1000 Subject: [PATCH 7/7] Style tables with relaxed and condensed rows * attempt with shadows, but they are between every row: http://jsfiddle.net/d872e3nb/ * another attempt at applying styles to tbody groups http://jsfiddle.net/sb38cLdu/ --- app/views/admin/products_v3/_table.html.haml | 4 +-- app/webpacker/css/admin/products_v3.scss | 30 +++++++++++++++++++ .../css/admin_v3/globals/variables.scss | 5 +++- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/app/views/admin/products_v3/_table.html.haml b/app/views/admin/products_v3/_table.html.haml index 21021df320..b582da532f 100644 --- a/app/views/admin/products_v3/_table.html.haml +++ b/app/views/admin/products_v3/_table.html.haml @@ -22,7 +22,7 @@ %th.align-left= t('admin.inherits_properties') %th.align-right= t('admin.available_on') - products.each do |product| - %tbody + %tbody.relaxed %tr %td.align-left.header .line-clamp-1= product.name @@ -49,7 +49,7 @@ %td.align-right .line-clamp-1= product.available_on&.strftime('%F') - product.variants.each do |variant| - %tr + %tr.condensed %td.align-left .line-clamp-1= variant.display_name %td.align-right diff --git a/app/webpacker/css/admin/products_v3.scss b/app/webpacker/css/admin/products_v3.scss index 1e0fd44683..7050cd9983 100644 --- a/app/webpacker/css/admin/products_v3.scss +++ b/app/webpacker/css/admin/products_v3.scss @@ -30,6 +30,36 @@ td { background-color: $color-tbl-cell-bg; } + + // "Relaxed" row groups, containing condensed rows. + // + // `display:table` enforces strict rules and won't allow border styles on tbody. + // So we emulate group styles on the cells themselves. + .relaxed { + th, + td { + padding: $padding-tbl-cell-relaxed; + } + + td { + border-bottom: 2px solid $color-tbl-bg; + } + + tr:first-child td { + border-top: 4px solid $color-tbl-bg; + } + tr:last-child td { + border-bottom: 1px solid $color-tbl-cell-shadow; + } + } + + // "Condensed" rows + .condensed { + td, + th { + padding: $padding-tbl-cell-condensed; + } + } } #no-products { diff --git a/app/webpacker/css/admin_v3/globals/variables.scss b/app/webpacker/css/admin_v3/globals/variables.scss index 494cb9ed5b..434042f31f 100644 --- a/app/webpacker/css/admin_v3/globals/variables.scss +++ b/app/webpacker/css/admin_v3/globals/variables.scss @@ -6,7 +6,7 @@ //-------------------------------------------------------------- $base-font-family: "Open Sans", "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; -// Colors +// Styles //-------------------------------------------------------------- // Body base colors @@ -28,9 +28,12 @@ $color-error: $red !default; // Table styles $color-tbl-bg: $light-grey !default; $color-tbl-cell-bg: $white !default; +$color-tbl-cell-shadow: rgb(0, 0, 0, 0.15) !default; $color-tbl-thead-txt: $color-headers !default; $color-tbl-thead-bg: $light-grey !default; $padding-tbl-cell: 12px 12px; +$padding-tbl-cell-condensed: 10px 12px; +$padding-tbl-cell-relaxed: 16px 12px; // Button colors $color-btn-bg: $teal !default;