Merge pull request #11123 from dacook/buu-products-table

[admin_style_v3] Products table with variants
This commit is contained in:
David Cook
2023-07-06 09:37:31 +10:00
committed by GitHub
23 changed files with 490 additions and 112 deletions

View File

@@ -0,0 +1,7 @@
# frozen_string_literal: true
module Admin
class ProductsV3Controller < Spree::Admin::BaseController
def index; end
end
end

View File

@@ -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

View File

@@ -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")

View File

@@ -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')

View File

@@ -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

View File

@@ -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

View File

@@ -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 }

View File

@@ -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
%div

View File

@@ -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");
};
}

View File

@@ -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;
}
}
}

View File

@@ -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";

View File

@@ -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;
}
}
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}
}
}

View File

@@ -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;
}

View File

@@ -1 +1,3 @@
@import "../css/admin_v3/all.scss";
@import "../css/admin_v3/components/spinner.scss";

View File

@@ -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

View File

@@ -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

View File

@@ -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'