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/reflexes/admin/products_v3_reflex.rb b/app/reflexes/admin/products_v3_reflex.rb new file mode 100644 index 0000000000..0e36ae2762 --- /dev/null +++ b/app/reflexes/admin/products_v3_reflex.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +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", 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 new file mode 100644 index 0000000000..2c076973c6 --- /dev/null +++ b/app/views/admin/products_v3/_content.html.haml @@ -0,0 +1,10 @@ +- 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 new file mode 100644 index 0000000000..b582da532f --- /dev/null +++ b/app/views/admin/products_v3/_table.html.haml @@ -0,0 +1,73 @@ +%table.products + %col{ width:"15%" } + %col{ width:"5%", style: "max-width:5em" } + %col{ width:"8%" } + %col{ width:"5%", style: "max-width:5em"} + %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') + %th.align-right= t('admin.available_on') + - products.each do |product| + %tbody.relaxed + %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.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 + -# 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 + .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, else use I18n.t (also below) + %td.align-right + .line-clamp-1= product.available_on&.strftime('%F') + - product.variants.each do |variant| + %tr.condensed + %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') + 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..2cb442b141 --- /dev/null +++ b/app/views/admin/products_v3/index.html.haml @@ -0,0 +1,17 @@ +- content_for :body_class do + products_v3_page +- 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' + +#products_v3_page{"data-controller": "productsV3"} + #loading-spinner.spinner-container{"data-productsV3-target": "loading"} + .spinner + = t('.loading') + #products-content 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/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/products_v3.scss b/app/webpacker/css/admin/products_v3.scss new file mode 100644 index 0000000000..7050cd9983 --- /dev/null +++ b/app/webpacker/css/admin/products_v3.scss @@ -0,0 +1,81 @@ +// 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. + + 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; + } + + // "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 { + 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/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/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/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/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..434042f31f 100644 --- a/app/webpacker/css/admin_v3/globals/variables.scss +++ b/app/webpacker/css/admin_v3/globals/variables.scss @@ -6,36 +6,41 @@ //-------------------------------------------------------------- $base-font-family: "Open Sans", "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; -// Colors +// Styles //-------------------------------------------------------------- // 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; +// 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: $color-7 !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: $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 +61,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..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); @@ -44,7 +48,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 +78,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; } } @@ -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; } } @@ -144,7 +147,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 +160,7 @@ table { } &.ui-sortable-placeholder td { - border: 1px solid $color-2 !important; + border: 1px solid $green !important; visibility: visible !important; &.actions { @@ -165,7 +168,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 +176,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 +192,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; } } } 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; } 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 22acda77a9..422f199e1b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -764,7 +764,14 @@ en: images: "Images" variants: "Variants" product_properties: "Product Properties" - + products_v3: + 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 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 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'