From 924701e1615be1febe94582adcc510b74acd2a84 Mon Sep 17 00:00:00 2001 From: David Cook Date: Tue, 26 Mar 2024 17:12:26 +1100 Subject: [PATCH] Load available units from system config I'm not sure what's the best way to load data into javascript.. this works. --- app/views/admin/products_v3/index.html.haml | 3 + app/views/admin/shared/_global_var_ofn.js.erb | 1 + .../js/services/option_value_namer.js | 7 +- .../js/services/variant_unit_manager.js | 112 +++++------------- 4 files changed, 37 insertions(+), 86 deletions(-) create mode 100644 app/views/admin/shared/_global_var_ofn.js.erb diff --git a/app/views/admin/products_v3/index.html.haml b/app/views/admin/products_v3/index.html.haml index 52ca21def8..f6d3be9f81 100644 --- a/app/views/admin/products_v3/index.html.haml +++ b/app/views/admin/products_v3/index.html.haml @@ -8,6 +8,9 @@ %li#new_product_link = button_link_to t(:new_product), "/admin/products/new", { :icon => 'icon-plus', :id => 'admin_new_product' } +%script= render partial: "admin/shared/global_var_ofn", formats: :js, + locals: { name: :available_units_sorted, value: WeightsAndMeasures.available_units_sorted } + = render partial: 'spree/admin/shared/product_sub_menu' #products_v3_page{ "data-controller": "products" } diff --git a/app/views/admin/shared/_global_var_ofn.js.erb b/app/views/admin/shared/_global_var_ofn.js.erb new file mode 100644 index 0000000000..7f897536b0 --- /dev/null +++ b/app/views/admin/shared/_global_var_ofn.js.erb @@ -0,0 +1 @@ +var ofn_<%= name %> = <%= value.to_json.html_safe %>; diff --git a/app/webpacker/js/services/option_value_namer.js b/app/webpacker/js/services/option_value_namer.js index 48564fecb7..dbf74a0dbe 100644 --- a/app/webpacker/js/services/option_value_namer.js +++ b/app/webpacker/js/services/option_value_namer.js @@ -4,6 +4,7 @@ import VariantUnitManager from "js/services/variant_unit_manager"; export default class OptionValueNamer { constructor(variant) { this.variant = variant; + this.variantUnitManager = new VariantUnitManager(); } name() { @@ -79,15 +80,15 @@ export default class OptionValueNamer { // If there is none available where this is true, use the smallest // available unit. const product = this.variant.product; - const scales = VariantUnitManager.compatibleUnitScales(product.variant_unit_scale, product.variant_unit); + const scales = this.variantUnitManager.compatibleUnitScales(product.variant_unit_scale, product.variant_unit); const variantUnitValue = this.variant.unit_value; // sets largestScale = last element in filtered scales array const largestScale = scales.filter(s => variantUnitValue / s >= 1).slice(-1)[0]; if (largestScale) { - return [largestScale, VariantUnitManager.getUnitName(largestScale, product.variant_unit)]; + return [largestScale, this.variantUnitManager.getUnitName(largestScale, product.variant_unit)]; } else { - return [scales[0], VariantUnitManager.getUnitName(scales[0], product.variant_unit)]; + return [scales[0], this.variantUnitManager.getUnitName(scales[0], product.variant_unit)]; } } } diff --git a/app/webpacker/js/services/variant_unit_manager.js b/app/webpacker/js/services/variant_unit_manager.js index 71859b2e30..b9aa344992 100644 --- a/app/webpacker/js/services/variant_unit_manager.js +++ b/app/webpacker/js/services/variant_unit_manager.js @@ -1,68 +1,11 @@ -// todo load availableUnits. Hmm why not just load from the dropdown? -export default class VariantUnitManager { - static availableUnits = 'g,kg,T,mL,L,gal,kL'; - // todo: load units from Ruby also? - static units = { - weight: { - 0.001: { - name: 'mg', - system: 'metric' - }, - 1.0: { - name: 'g', - system: 'metric' - }, - 1000.0: { - name: 'kg', - system: 'metric' - }, - 1000000.0: { - name: 'T', - system: 'metric' - }, - 453.6: { - name: 'lb', - system: 'imperial' - }, - 28.35: { - name: 'oz', - system: 'imperial' - } - }, - volume: { - 0.001: { - name: 'mL', - system: 'metric' - }, - 0.01: { - name: 'cL', - system: 'metric' - }, - 0.1: { - name: 'dL', - system: 'metric' - }, - 1.0: { - name: 'L', - system: 'metric' - }, - 1000.0: { - name: 'kL', - system: 'metric' - }, - 4.54609: { - name: 'gal', - system: 'metric' - } - }, - items: { - 1: { - name: 'items' - } - } - }; +// Requires global variable from page: ofn_available_units_sorted - static getUnitName = (scale, unitType) => { +export default class VariantUnitManager { + constructor() { + this.units = this.#loadUnits(ofn_available_units_sorted); + } + + getUnitName(scale, unitType) { if (this.units[unitType][scale]) { return this.units[unitType][scale]['name']; } else { @@ -70,24 +13,27 @@ export default class VariantUnitManager { } }; - // filter by system and format - static compatibleUnitScales = (scale, unitType) => { + // Filter by measurement system + compatibleUnitScales(scale, unitType) { const scaleSystem = this.units[unitType][scale]['system']; - if (this.availableUnits) { - const available = this.availableUnits.split(","); - return Object.entries(this.units[unitType]) - .filter(([scale, scaleInfo]) => { - return scaleInfo['system'] == scaleSystem && available.includes(scaleInfo['name']); - }) - .map(([scale, _]) => parseFloat(scale)) - .sort((a, b) => a - b); - } else { - return Object.entries(this.units[unitType]) - .filter(([scale, scaleInfo]) => { - return scaleInfo['system'] == scaleSystem; - }) - .map(([scale, _]) => parseFloat(scale)) - .sort((a, b) => a - b); - } - }; + + return Object.entries(this.units[unitType]) + .filter(([scale, scaleInfo]) => { + return scaleInfo['system'] == scaleSystem; + }) + .map(([scale, _]) => scale); + } + + // private + + #loadUnits(units) { + // Transform unit scale to a JS Number for compatibility. This would be way simpler in Ruby or Coffeescript!! + const unitsTransformed = Object.entries(units).map(([measurement, measurementInfo]) => { + const measurementInfoTransformed = Object.fromEntries(Object.entries(measurementInfo).map(([scale, unitInfo]) => + [ parseFloat(scale), unitInfo ] + )); + return [ measurement, measurementInfoTransformed ]; + }); + return Object.fromEntries(unitsTransformed); + } }