Merge pull request #12760 from wandji20/wb-OFN-12744

UX improvements for creation of new products [OFN-12744]
This commit is contained in:
Konrad
2024-08-29 17:22:36 +02:00
committed by GitHub
10 changed files with 54 additions and 30 deletions

View File

@@ -11,7 +11,8 @@ class SearchableDropdownComponent < ViewComponent::Base
selected_option:,
placeholder_value:,
include_blank: false,
aria_label: ''
aria_label: '',
other_attrs: {}
)
@f = form
@name = name
@@ -20,11 +21,13 @@ class SearchableDropdownComponent < ViewComponent::Base
@placeholder_value = placeholder_value
@include_blank = include_blank
@aria_label = aria_label
@other_attrs = other_attrs
end
private
attr_reader :f, :name, :options, :selected_option, :placeholder_value, :include_blank, :aria_label
attr_reader :f, :name, :options, :selected_option, :placeholder_value, :include_blank,
:aria_label, :other_attrs
def classes
"fullwidth #{remove_search_plugin? ? 'no-input' : ''}"

View File

@@ -1 +1 @@
= f.select name, options_for_select(options, selected_option), { include_blank: }, class: classes, data:, 'aria-label': aria_label
= f.select name, options_for_select(options, selected_option), { include_blank: }, class: classes, data:, 'aria-label': aria_label, **other_attrs

View File

@@ -295,14 +295,8 @@ module Spree
# eg clone product. Will raise error if clonning a product with no variant
return if variants.first&.valid?
unless Spree::Taxon.find_by(id: primary_taxon_id)
errors.add(:primary_taxon_id,
I18n.t('activerecord.errors.models.spree/product.must_exist'))
end
return if Enterprise.find_by(id: supplier_id)
errors.add(:supplier_id,
I18n.t('activerecord.errors.models.spree/product.must_exist'))
errors.add(:primary_taxon_id, :blank) unless Spree::Taxon.find_by(id: primary_taxon_id)
errors.add(:supplier_id, :blank) unless Enterprise.find_by(id: supplier_id)
end
def update_units

View File

@@ -9,7 +9,7 @@ module PermittedAttributes
:unit_description, :variant_unit_name,
:display_as, :sku, :group_buy, :group_buy_unit_size,
:taxon_ids, :primary_taxon_id, :tax_category_id, :supplier_id,
:meta_keywords, :notes, :inherits_properties,
:meta_keywords, :notes, :inherits_properties, :shipping_category_id,
{ product_properties_attributes: [:id, :property_name, :value],
variants_attributes: [PermittedAttributes::Variant.attributes],
image_attributes: [:attachment] }

View File

@@ -1,6 +1,12 @@
= f.field_container :primary_taxon do
= f.field_container :primary_taxon_id do
= f.label :primary_taxon_id, t('.product_category')
%span.required *
%br
= f.collection_select(:primary_taxon_id, Spree::Taxon.order(:name), :id, :name, {:include_blank => true}, {:class => "select2 fullwidth"})
= render(SearchableDropdownComponent.new(form: f,
name: :primary_taxon_id,
aria_label: t('.product_category'),
options: Spree::Taxon.select(:name, :id).order(:name).pluck(:name, :id),
selected_option: @product.primary_taxon_id,
include_blank: true,
placeholder_value: t('.search_for_categories')))
= f.error_message_on :primary_taxon_id

View File

@@ -1,4 +1,4 @@
= f.field_container :shipping_categories do
= f.field_container :shipping_category_id do
= f.label :shipping_category_id, t(:shipping_category)
= f.collection_select(:shipping_category_id, Spree::ShippingCategory.all, :id, :name, {:include_blank => false}, {:class => 'select2 fullwidth'})
= f.error_message_on :shipping_category_id

View File

@@ -8,10 +8,16 @@
%legend{align: "center"}= t(".new_product")
.sixteen.columns.alpha
.eight.columns.alpha
= f.field_container :supplier do
= f.label :supplier, t(".supplier")
= f.field_container :supplier_id do
= f.label :supplier_id, t(".supplier")
%span.required *
= f.select :supplier_id, options_from_collection_for_select(@producers, :id, :name, @product.supplier_id), { include_blank: t("spree.admin.products.new.supplier_select_placeholder") }, { "data-controller": "tom-select", class: "primary" }
= render(SearchableDropdownComponent.new(form: f,
name: :supplier_id,
aria_label: t('.supplier'),
options: @producers.select(:name, :id).order(:name).pluck(:name, :id),
selected_option: @product.supplier_id,
include_blank: true,
placeholder_value: t('.search_for_suppliers')))
= f.error_message_on :supplier_id
.eight.columns.omega
= f.field_container :name do
@@ -25,8 +31,16 @@
= f.field_container :variant_unit do
= f.label :variant_unit, t(".units")
%span.required *
%select{id: 'product_variant_unit_with_scale', 'ng-model' => 'product.variant_unit_with_scale', 'ng-options' => 'unit[1] as unit[0] for unit in variant_unit_options', "data-controller": "tom-select","data-tom-select-options-value": '{"allowEmptyOption":false}', class: "primary"}
%option{'value' => '', 'ng-hide' => "hasUnit(product)"}
= f.select 'variant_unit', [],
{ include_blank: true },
{ id: 'product_variant_unit_with_scale',
name: 'product_variant_unit_with_scale',
'ng-model' => 'product.variant_unit_with_scale',
'ng-options' => 'unit[1] as unit[0] for unit in variant_unit_options',
"data-controller": "tom-select",
"data-tom-select-options-value": '{"allowEmptyOption":false}',
class: "primary",
}
%input{ type: 'hidden', 'ng-value': 'product.variant_unit', "ng-init": "product.variant_unit='#{@product.variant_unit}'", name: 'product[variant_unit]' }
%input{ type: 'hidden', 'ng-value': 'product.variant_unit_scale', "ng-init": "product.variant_unit_scale='#{@product.variant_unit_scale}'", name: 'product[variant_unit_scale]' }
= f.error_message_on :variant_unit
@@ -34,16 +48,17 @@
= f.field_container :unit_value do
= f.label :unit_value, t(".value"), 'ng-disabled' => "!hasUnit(product)"
%span.required *
%input.fullwidth{ id: 'product_unit_value', 'ng-model' => 'product.master.unit_value_with_description', :type => 'text', placeholder: "eg. 2", 'ng-disabled' => "!hasUnit(product)" }
= f.text_field :unit_value, placeholder: "eg. 2", 'ng-model' => 'product.master.unit_value_with_description', class: 'fullwidth', 'ng-disabled' => "!hasUnit(product)"
%input{ type: 'hidden', 'ng-value': 'product.master.unit_value', "ng-init": "product.master.unit_value='#{@product.unit_value}'", name: 'product[unit_value]' }
%input{ type: 'hidden', 'ng-value': 'product.master.unit_description', "ng-init": "product.master.unit_description='#{@product.unit_description}'", name: 'product[unit_description]' }
= f.error_message_on :unit_value
= render 'display_as', f: f
.six.columns.omega{ 'ng-show' => "product.variant_unit_with_scale == 'items'" }
= f.field_container :unit_name do
= f.label :product_variant_unit_name, t(".unit_name")
= f.field_container :variant_unit_name do
= f.label :variant_unit_name, t(".unit_name")
%span.required *
%input.fullwidth{ id: 'product_variant_unit_name','ng-model' => 'product.variant_unit_name', :name => 'product[variant_unit_name]', :placeholder => t('admin.products.unit_name_placeholder'), :type => 'text' }
= f.text_field :variant_unit_name, :placeholder => t('admin.products.unit_name_placeholder'), 'ng-model' => 'product.variant_unit_name', class: 'fullwidth', 'ng-init': "product.variant_unit_name='#{@product.variant_unit_name}'"
= f.error_message_on :variant_unit_name
.sixteen.columns.alpha
.eight.columns.alpha
= render 'spree/admin/products/primary_taxon_form', f: f

View File

@@ -2,9 +2,14 @@ import { Controller } from "stimulus";
export default class extends Controller {
connect() {
window.addEventListener("trix-change", this.#trixChange);
this.element.addEventListener("trix-change", this.#trixChange);
this.#trixInitialize();
window.addEventListener("trix-initialize", this.#trixInitialize);
this.element.addEventListener("trix-initialize", this.#trixInitialize);
}
disconnect() {
this.element.removeEventListener("trix-change", this.#trixChange);
this.element.removeEventListener("trix-initialize", this.#trixInitialize);
}
#trixChange = (event) => {

View File

@@ -120,8 +120,6 @@ en:
attributes:
base:
card_expired: "has expired"
spree/product:
must_exist: 'must exist'
order_cycle:
attributes:
orders_close_at:
@@ -4470,6 +4468,8 @@ See the %{link} to find out more about %{sitename}'s features and to start using
new_product: "New Product"
supplier: "Supplier"
supplier_select_placeholder: "Select a supplier"
search_for_suppliers: "Search for suppliers"
search_for_units: "Search for units"
product_name: "Product Name"
units: "Unit Size"
value: "Value"
@@ -4504,6 +4504,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using
product_name: Product Name
primary_taxon_form:
product_category: Product Category
search_for_categories: "Search for categories"
group_buy_form:
group_buy: "Group Buy?"
bulk_unit_size: Bulk unit size

View File

@@ -184,7 +184,7 @@ RSpec.describe '
click_button 'Create'
expect(current_path).to eq spree.admin_products_path
expect(page).to have_content "Product Category must exist"
expect(page).to have_content "Product Category can't be blank"
end
it "creating product with empty product supplier fails" do
@@ -201,7 +201,7 @@ RSpec.describe '
click_button 'Create'
expect(current_path).to eq spree.admin_products_path
expect(page).to have_content "Supplier must exist"
expect(page).to have_content "Supplier can't be blank"
end
describe "localization settings" do