Sync hidden variant unit fields

This will be necessary for managing the 'display as' state.
..or is it?
This commit is contained in:
David Cook
2024-03-19 12:35:39 +11:00
parent 45b4e6c87c
commit a5741a1ca8
4 changed files with 95 additions and 1 deletions

View File

@@ -10,6 +10,8 @@
= f.text_field :sku, 'aria-label': t('admin.products_page.columns.sku')
= error_message_on product, :sku
%td.multi-field{ 'data-controller': 'toggle-control', 'data-toggle-control-match-value': 'items' }
= f.hidden_field :variant_unit
= f.hidden_field :variant_unit_scale
= f.select :variant_unit_with_scale,
options_for_select(WeightsAndMeasures.variant_unit_options, product.variant_unit_with_scale),
{},

View File

@@ -54,7 +54,7 @@
- products.each_with_index do |product, product_index|
= form.fields_for("products", product, index: product_index) do |product_form|
%tbody.relaxed.naked_inputs{ data: { 'record-id': product_form.object.id,
controller: "nested-form",
controller: "nested-form product",
action: 'rails-nested-form:add->bulk-form#registerElements' } }
%tr
= render partial: 'product_row', locals: { product:, f: product_form }

View File

@@ -0,0 +1,36 @@
import { Controller } from "stimulus";
// Dynamically update related Product unit fields (expected to move to Variant due to Product Refactor)
//
export default class ProductController extends Controller {
connect() {
// idea: create a helper that includes a nice getter/setter for Rails model attr values, just pass it the attribute name.
// It could automatically find (and cache a ref to) each dom element and get/set the values.
this.variantUnit = this.element.querySelector('[name$="[variant_unit]"]');
this.variantUnitScale = this.element.querySelector('[name$="[variant_unit_scale]"]');
this.variantUnitWithScale = this.element.querySelector('[name$="[variant_unit_with_scale]"]');
// on variant_unit_with_scale changed; update variant_unit and variant_unit_scale
this.variantUnitWithScale.addEventListener("change", this.#updateUnitAndScale.bind(this), {
passive: true,
});
}
// private
// Extract variant_unit and variant_unit_scale from dropdown variant_unit_with_scale,
// and update hidden product fields
#updateUnitAndScale(event) {
const variant_unit_with_scale = this.variantUnitWithScale.value;
const match = variant_unit_with_scale.match(/^([^_]+)_([\d\.]+)$/); // eg "weight_1000"
if (match) {
this.variantUnit.value = match[1];
this.variantUnitScale.value = parseFloat(match[2]);
} else {
// "items"
this.variantUnit.value = variant_unit_with_scale;
this.variantUnitScale.value = "";
}
}
}

View File

@@ -0,0 +1,56 @@
/**
* @jest-environment jsdom
*/
import { Application } from "stimulus";
import product_controller from "../../../app/webpacker/controllers/product_controller";
describe("ProductController", () => {
beforeAll(() => {
const application = Application.start();
application.register("product", product_controller);
});
describe("variant_unit_with_scale", () => {
beforeEach(() => {
document.body.innerHTML = `
<div data-controller="product">
<input id="variant_unit" name="[products][0][variant_unit]" value="weight">
<input id="variant_unit_scale" name="[products][0][variant_unit_scale]" value="1.0">
<select id="variant_unit_with_scale" name="[products][0][variant_unit_with_scale]">
<option selected="selected" value="weight_1">Weight (g)</option>
<option value="weight_1000">Weight (kg)</option>
<option value="volume_4.54609">Volume (gal)</option>
<option value="items">Items</option>
</select>
</div>
`;
});
describe("change", () => {
it("weight_1000", () => {
variant_unit_with_scale.selectedIndex = 1;
variant_unit_with_scale.dispatchEvent(new Event("change"));
expect(variant_unit.value).toBe("weight");
expect(variant_unit_scale.value).toBe("1000");
});
it("volume_4.54609", () => {
variant_unit_with_scale.selectedIndex = 2;
variant_unit_with_scale.dispatchEvent(new Event("change"));
expect(variant_unit.value).toBe("volume");
expect(variant_unit_scale.value).toBe("4.54609");
});
it("items", () => {
variant_unit_with_scale.selectedIndex = 3;
variant_unit_with_scale.dispatchEvent(new Event("change"));
expect(variant_unit.value).toBe("items");
expect(variant_unit_scale.value).toBe("");
});
})
});
});