@configura/web-api 1.3.0-alpha.2 → 1.3.0-alpha.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/CatalogueAPI.d.ts +55 -1
- package/dist/CfgMeasure.d.ts +33 -0
- package/dist/CfgMeasure.js +30 -0
- package/dist/CfgProduct.d.ts +106 -5
- package/dist/CfgProduct.js +117 -71
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/material/CfgMaterialMapping.js +11 -6
- package/dist/material/CfgMtrlApplication.js +4 -4
- package/dist/productConfiguration/CfgFeature.d.ts +30 -4
- package/dist/productConfiguration/CfgFeature.js +162 -52
- package/dist/productConfiguration/CfgOption.d.ts +21 -5
- package/dist/productConfiguration/CfgOption.js +125 -24
- package/dist/productConfiguration/CfgProductConfiguration.d.ts +74 -4
- package/dist/productConfiguration/CfgProductConfiguration.js +158 -49
- package/dist/productConfiguration/utilitiesProductConfiguration.d.ts +9 -1
- package/dist/productConfiguration/utilitiesProductConfiguration.js +32 -13
- package/dist/productLoader.d.ts +22 -0
- package/dist/productLoader.js +22 -14
- package/dist/tests/testData/dummyProductForTest.js +1 -0
- package/dist/tests/testData/testDataAdditionalProductInAdditionalProductInProductForTest.js +13 -0
- package/dist/tests/testData/testDataCachedGetProduct.js +6 -0
- package/dist/tests/testData/testDataCachedPostValidate.js +6 -0
- package/dist/tests/testData/testDataNoAdditionalProductNoPropagateForTest.js +2 -0
- package/dist/tests/testData/testDataProductAggregatedPrice.js +6 -1
- package/dist/tests/testData/testDataUpcharge.js +4 -0
- package/dist/utilitiesCatalogueData.d.ts +5 -1
- package/dist/utilitiesCatalogueData.js +9 -1
- package/dist/utilitiesNumericValues.d.ts +25 -0
- package/dist/utilitiesNumericValues.js +109 -0
- package/package.json +3 -3
package/dist/CfgProduct.js
CHANGED
|
@@ -7,7 +7,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import { AggregatedLoadingObservable, compareArrays, count, Observable, } from "@configura/web-utilities";
|
|
10
|
+
import { AggregatedLoadingObservable, compareArrays, count, Observable, toLengthUnit, } from "@configura/web-utilities";
|
|
11
|
+
import { CfgMeasureDefinition } from "./CfgMeasure.js";
|
|
11
12
|
import { ProductConfigurationBubbleMode } from "./productConfiguration/CfgOption.js";
|
|
12
13
|
import { CfgProductConfiguration } from "./productConfiguration/CfgProductConfiguration.js";
|
|
13
14
|
import { collectAdditionalProductRefs } from "./productConfiguration/utilitiesProductConfiguration.js";
|
|
@@ -20,21 +21,22 @@ function completeSettings(uncompleteSettings) {
|
|
|
20
21
|
strictSetApiSelectionMatch: (_b = uncompleteSettings === null || uncompleteSettings === void 0 ? void 0 : uncompleteSettings.strictSetApiSelectionMatch) !== null && _b !== void 0 ? _b : false,
|
|
21
22
|
};
|
|
22
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* This enum is used internally in the SDK and is not expected by be used directly by integrators.
|
|
26
|
+
*/
|
|
23
27
|
export var CfgProductBubbleMode;
|
|
24
28
|
(function (CfgProductBubbleMode) {
|
|
25
|
-
|
|
26
|
-
/// This mode is support for internal functionality is not expected to be used by integrators
|
|
29
|
+
/** Stop bubbling. */
|
|
27
30
|
CfgProductBubbleMode["Stop"] = "Stop";
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Bubble to the parent CfgProduct up the tree.
|
|
33
|
+
* This makes the CfgProduct we we call from notify that it has changed, and the CfgProduct
|
|
34
|
+
* above switch out the reference to this.
|
|
35
|
+
*/
|
|
32
36
|
CfgProductBubbleMode["OneLevel"] = "OneLevel";
|
|
33
|
-
|
|
34
|
-
/// This mode is support for internal functionality is not expected to be used by integrators
|
|
37
|
+
/** Bubble to the root CfgProduct. */
|
|
35
38
|
CfgProductBubbleMode["ToRoot"] = "ToRoot";
|
|
36
|
-
|
|
37
|
-
/// This mode is support for internal functionality is not expected to be used by integrators
|
|
39
|
+
/** Bubble to the root CfgProduct and turn on all optional CfgProducts on the way up. */
|
|
38
40
|
CfgProductBubbleMode["ToRootAndBubbleSelected"] = "ToRootAndBubbleSelected";
|
|
39
41
|
})(CfgProductBubbleMode || (CfgProductBubbleMode = {}));
|
|
40
42
|
function isDescriptionMatch(l, r) {
|
|
@@ -42,24 +44,27 @@ function isDescriptionMatch(l, r) {
|
|
|
42
44
|
const rd = r.description;
|
|
43
45
|
return ld !== undefined && rd !== undefined && ld.toLowerCase() === rd.toLowerCase();
|
|
44
46
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
/**
|
|
48
|
+
* This class is meant to only be used through CfgProduct. It should never be instantiated on its
|
|
49
|
+
* own. Normally the internal state of this class should never be directly modified. CfgProduct is
|
|
50
|
+
* the class that should be used and interacted with.
|
|
51
|
+
*/
|
|
49
52
|
export class _CfgProductInternal {
|
|
50
|
-
constructor(initSuccess, initFail, _productLoaderRaw, lang, catId, partNumber, settings, optional, selected, rootFeatureRefs, allRawFeatures, uuid, _rawProductData, apiSelection, loadingObservable, refKey, refDescription, parent, root, transform) {
|
|
53
|
+
constructor(initSuccess, initFail, _productLoaderRaw, lang, catId, partNumber, settings, optional, selected, rootFeatureRefs, allRawFeatures, uuid, _rawUnit, _rawProductData, apiSelection, loadingObservable, refKey, refDescription, parent, root, transform, anchor) {
|
|
51
54
|
this._productLoaderRaw = _productLoaderRaw;
|
|
52
55
|
this.lang = lang;
|
|
53
56
|
this.catId = catId;
|
|
54
57
|
this.partNumber = partNumber;
|
|
55
58
|
this.settings = settings;
|
|
56
59
|
this.uuid = uuid;
|
|
60
|
+
this._rawUnit = _rawUnit;
|
|
57
61
|
this._rawProductData = _rawProductData;
|
|
58
62
|
this.loadingObservable = loadingObservable;
|
|
59
63
|
this.refKey = refKey;
|
|
60
64
|
this.refDescription = refDescription;
|
|
61
65
|
this.parent = parent;
|
|
62
66
|
this.transform = transform;
|
|
67
|
+
this.anchor = anchor;
|
|
63
68
|
this._destroyed = false;
|
|
64
69
|
this.additionalProducts = [];
|
|
65
70
|
this.changeObservable = new Observable();
|
|
@@ -84,7 +89,7 @@ export class _CfgProductInternal {
|
|
|
84
89
|
: bubbleMode);
|
|
85
90
|
}
|
|
86
91
|
});
|
|
87
|
-
|
|
92
|
+
/** Called when a child (additional product or the configuration) has changed. */
|
|
88
93
|
this._childHasChanged = (bubbleMode) => __awaiter(this, void 0, void 0, function* () {
|
|
89
94
|
if (bubbleMode === CfgProductBubbleMode.ToRootAndBubbleSelected &&
|
|
90
95
|
this.optional &&
|
|
@@ -94,7 +99,7 @@ export class _CfgProductInternal {
|
|
|
94
99
|
}
|
|
95
100
|
yield this._notifyAllOfChange(bubbleMode);
|
|
96
101
|
});
|
|
97
|
-
|
|
102
|
+
/** Called by child to tell its parent that it has changed. */
|
|
98
103
|
this._additionalProductHasChanged = (freshRef, bubbleMode) => __awaiter(this, void 0, void 0, function* () {
|
|
99
104
|
const i = this.additionalProducts.findIndex((a) => a.isBackedBySame(freshRef));
|
|
100
105
|
if (i !== -1) {
|
|
@@ -107,7 +112,7 @@ export class _CfgProductInternal {
|
|
|
107
112
|
}
|
|
108
113
|
yield this._childHasChanged(bubbleMode);
|
|
109
114
|
});
|
|
110
|
-
|
|
115
|
+
/** Called by the configuration to tell its parent that it has changed. */
|
|
111
116
|
this._configurationHasChanged = (freshRef, bubbleMode) => __awaiter(this, void 0, void 0, function* () {
|
|
112
117
|
this._configuration = freshRef;
|
|
113
118
|
switch (bubbleMode) {
|
|
@@ -246,17 +251,18 @@ export class _CfgProductInternal {
|
|
|
246
251
|
}
|
|
247
252
|
return change;
|
|
248
253
|
});
|
|
249
|
-
|
|
254
|
+
/** Only features in selected options and selected additional products. */
|
|
250
255
|
this._getDescendantFeaturesWithCode = (code) => this.additionalProducts.reduce((agg, additionalProduct) => {
|
|
251
256
|
if (additionalProduct.selected) {
|
|
252
257
|
agg.push(...additionalProduct._internal._getDescendantFeaturesWithCode(code));
|
|
253
258
|
}
|
|
254
259
|
return agg;
|
|
255
260
|
}, this._configuration._internal._getFeaturesWithCode(code));
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
261
|
+
/**
|
|
262
|
+
* Do a validate call for this product. It does not validate additional products, only this
|
|
263
|
+
* product in isolation. The validation result is applied on the configuration. Then additional
|
|
264
|
+
* products are synced (unloaded, loaded etc.) Finally the changes bubble up the tree.
|
|
265
|
+
*/
|
|
260
266
|
this._revalidate = (bubbleMode, productLoaderForGroupedLoad) => __awaiter(this, void 0, void 0, function* () {
|
|
261
267
|
const { _configuration: configuration } = this;
|
|
262
268
|
const token = this.loadingObservable.startChildLoading();
|
|
@@ -306,8 +312,10 @@ export class _CfgProductInternal {
|
|
|
306
312
|
this.loadingObservable.stopChildLoading(token);
|
|
307
313
|
}
|
|
308
314
|
});
|
|
309
|
-
|
|
310
|
-
|
|
315
|
+
/**
|
|
316
|
+
* Based on this configuration find what additional products should be shown and not, unload
|
|
317
|
+
* (i.e. destroy) those that should no longer be shown, load the new ones.
|
|
318
|
+
*/
|
|
311
319
|
this._syncAndLoadAdditionalProducts = (productLoaderForGroupedLoad) => __awaiter(this, void 0, void 0, function* () {
|
|
312
320
|
const { lang, _productLoaderRaw: productLoaderRaw, rawProductData: productData, configuration, additionalProducts: currentAdditionalProducts, } = this;
|
|
313
321
|
const additionalProductRefs = [
|
|
@@ -341,7 +349,7 @@ export class _CfgProductInternal {
|
|
|
341
349
|
const additionalProductRef = p.prodRef;
|
|
342
350
|
return {
|
|
343
351
|
originalIndex: p.originalIndex,
|
|
344
|
-
product: CfgProduct._makeNewRefFrom(yield _CfgProductInternal.make(productLoaderRaw, productLoaderForGroupedLoad, lang, additionalProductRef.catId, additionalProductRef.partNumber, this.settings, additionalProductRef.optional === true, this.loadingObservable, additionalProductRef.refKey, additionalProductRef.refDescription, this, this.root, additionalProductRef.transform)),
|
|
352
|
+
product: CfgProduct._makeNewRefFrom(yield _CfgProductInternal.make(productLoaderRaw, productLoaderForGroupedLoad, lang, additionalProductRef.catId, additionalProductRef.partNumber, this.settings, additionalProductRef.optional === true, this.loadingObservable, additionalProductRef.refKey, additionalProductRef.refDescription, this, this.root, additionalProductRef.transform, additionalProductRef.anchor)),
|
|
345
353
|
};
|
|
346
354
|
}))()));
|
|
347
355
|
if (this._destroyed) {
|
|
@@ -373,7 +381,7 @@ export class _CfgProductInternal {
|
|
|
373
381
|
const product = yield new Promise((initSuccess, initFail) => {
|
|
374
382
|
const p = new _CfgProductInternal(() => {
|
|
375
383
|
initSuccess(p);
|
|
376
|
-
}, initFail, this._productLoaderRaw, this.lang, this.catId, this.partNumber, this.settings, this.optional, this.selected, this._configuration.rootFeatureRefs, this._configuration.allRawFeatures, this.uuid, this._rawProductData, this.configuration.getApiSelection(), new AggregatedLoadingObservable(), this.refKey, this.refDescription, parent, root, this.transform);
|
|
384
|
+
}, initFail, this._productLoaderRaw, this.lang, this.catId, this.partNumber, this.settings, this.optional, this.selected, this._configuration.rootFeatureRefs, this._configuration.allRawFeatures, this.uuid, this._rawUnit, this._rawProductData, this.configuration.getApiSelection(), new AggregatedLoadingObservable(), this.refKey, this.refDescription, parent, root, this.transform, this.anchor);
|
|
377
385
|
});
|
|
378
386
|
for (const additionalProduct of this.additionalProducts) {
|
|
379
387
|
product.additionalProducts.push(CfgProduct._makeNewRefFrom(yield additionalProduct._internal.clone(product, root || product)));
|
|
@@ -399,6 +407,22 @@ export class _CfgProductInternal {
|
|
|
399
407
|
get prices() {
|
|
400
408
|
return this._rawProductData.partsData.prices;
|
|
401
409
|
}
|
|
410
|
+
get measureDefinitions() {
|
|
411
|
+
var _a;
|
|
412
|
+
if (this._measureDefinitions === undefined) {
|
|
413
|
+
this._measureDefinitions = ((_a = this._rawProductData.measurements) !== null && _a !== void 0 ? _a : [])
|
|
414
|
+
.map((m) => CfgMeasureDefinition.make(m))
|
|
415
|
+
.filter((m) => m !== undefined);
|
|
416
|
+
}
|
|
417
|
+
return this._measureDefinitions;
|
|
418
|
+
}
|
|
419
|
+
/** @throws an error if the actual unit sent by the server was not a LengthUnit */
|
|
420
|
+
get unit() {
|
|
421
|
+
if (this._unit === undefined) {
|
|
422
|
+
this._unit = toLengthUnit(this._rawUnit);
|
|
423
|
+
}
|
|
424
|
+
return this._unit;
|
|
425
|
+
}
|
|
402
426
|
get aggregatedPrice() {
|
|
403
427
|
const { currency, fractionDigits, rawProductData } = this;
|
|
404
428
|
const { partsData } = rawProductData;
|
|
@@ -448,20 +472,20 @@ export class _CfgProductInternal {
|
|
|
448
472
|
}
|
|
449
473
|
}
|
|
450
474
|
_CfgProductInternal.make = (productLoaderRaw, productLoaderForGroupedLoad, // Used when instantiating the current product
|
|
451
|
-
lang, catId, partNumber, settings, optional, loadingObservable, refKey, refDescription, parent, root, transform) => __awaiter(void 0, void 0, void 0, function* () {
|
|
475
|
+
lang, catId, partNumber, settings, optional, loadingObservable, refKey, refDescription, parent, root, transform, anchor) => __awaiter(void 0, void 0, void 0, function* () {
|
|
452
476
|
// wrap with cache will make getProduct for this function call use the same server call
|
|
453
477
|
// for the same product with the same params
|
|
454
478
|
productLoaderForGroupedLoad =
|
|
455
479
|
productLoaderForGroupedLoad || wrapWithCache(productLoaderRaw);
|
|
456
480
|
const productResponse = yield productLoaderForGroupedLoad.getProduct(Object.assign(Object.assign({ lang }, correctDefaultsOnCatalogueParams(catId)), { partNumber }));
|
|
457
|
-
const { productData, rootFeatureRefs, features: allRawFeatures, uuid } = productResponse;
|
|
481
|
+
const { productData, rootFeatureRefs, features: allRawFeatures, uuid, unit, } = productResponse;
|
|
458
482
|
const product = yield new Promise((initSuccess, initFail) => {
|
|
459
483
|
const p = new _CfgProductInternal(() => {
|
|
460
484
|
// We absolutely do not want anyone to assign to this._configuration. So we want that field private.
|
|
461
485
|
// But we can not set the api selection synchronously. And the product configuration needs "this". So we use this callback.
|
|
462
486
|
// Feel free to find a nicer more readable solution :)
|
|
463
487
|
initSuccess(p);
|
|
464
|
-
}, initFail, productLoaderRaw, lang, catId, partNumber, settings, optional, !optional, rootFeatureRefs, allRawFeatures, uuid, productData, productData.partsData.selOptions || [], loadingObservable, refKey, refDescription, parent, root, transform);
|
|
488
|
+
}, initFail, productLoaderRaw, lang, catId, partNumber, settings, optional, !optional, rootFeatureRefs, allRawFeatures, uuid, unit, productData, productData.partsData.selOptions || [], loadingObservable, refKey, refDescription, parent, root, transform, anchor);
|
|
465
489
|
});
|
|
466
490
|
yield product._syncAndLoadAdditionalProducts(productLoaderForGroupedLoad);
|
|
467
491
|
return product;
|
|
@@ -470,35 +494,40 @@ export class CfgProduct {
|
|
|
470
494
|
constructor(_internal) {
|
|
471
495
|
this._internal = _internal;
|
|
472
496
|
this.isBackedBySame = (other) => this._internal === other._internal;
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
497
|
+
/**
|
|
498
|
+
* Recursively marks this and descendants as destroyed so that late events are ignored
|
|
499
|
+
* correctly. If you destroy one shallow copy of this you destroy all.
|
|
500
|
+
*/
|
|
476
501
|
this.destroy = () => this._internal.destroy();
|
|
477
|
-
|
|
502
|
+
/** Makes a clone of this. It is disconnected from the original. */
|
|
478
503
|
this.clone = () => __awaiter(this, void 0, void 0, function* () { return CfgProduct._makeNewRefFrom(yield this._internal.clone()); });
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
504
|
+
/**
|
|
505
|
+
* Only applicable when this product is optional.
|
|
506
|
+
* Setting this does not cause a validation call as toggling an optional additional product is
|
|
507
|
+
* assumed to always be legal.
|
|
508
|
+
*/
|
|
482
509
|
this.setSelected = (v) => __awaiter(this, void 0, void 0, function* () { return yield this._internal.setSelected(v, CfgProductBubbleMode.ToRootAndBubbleSelected); });
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
510
|
+
/**
|
|
511
|
+
* Experimental. Additional products lacks descriptions or keys that are suitably for structure
|
|
512
|
+
* compare, so we use strict-order when trying to match the additional products. This makes
|
|
513
|
+
* this method work nicely for different products having pretty much the same child products.
|
|
514
|
+
*/
|
|
486
515
|
this.structureCompare = (other, strictOrder = true, descriptionMatch = false) => this._internal.structureCompare(other._internal, strictOrder, descriptionMatch);
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
516
|
+
/**
|
|
517
|
+
* Experimental. Additional products lacks descriptions or keys that are suitably for try
|
|
518
|
+
* match, so we use strict-order when trying to match the additional products. This makes
|
|
519
|
+
* this method work nicely for different products having pretty much the same child products.
|
|
520
|
+
* This method does not propagate its selections.
|
|
521
|
+
* This method will cause validation calls if something change.
|
|
522
|
+
*/
|
|
492
523
|
this.tryMatchSelection = (other, descriptionMatch = false // Match on case insensitive description, not code
|
|
493
524
|
) => __awaiter(this, void 0, void 0, function* () { return yield this._internal.tryMatchSelection(other._internal, descriptionMatch); });
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
525
|
+
/**
|
|
526
|
+
* Gets what selections has been made on the product, recursively including product
|
|
527
|
+
* configuration, optional products and additional products. Used when a full view of all
|
|
528
|
+
* selections on a product is needed, such as when doing Render or Export.
|
|
529
|
+
*/
|
|
497
530
|
this.getApiSelection = () => this._internal.getApiSelection();
|
|
498
|
-
/// Experimental. The API currently never sends ApiSelections for products with additional products
|
|
499
|
-
/// downstream, so this is only provided as a convenience function if someone would for instance want
|
|
500
|
-
/// to store previous selection states of a product by doing getApiSelection.
|
|
501
|
-
/// This method does not propagate its selections.
|
|
502
531
|
this.setApiSelection = (s, doValidate = false) => __awaiter(this, void 0, void 0, function* () { return yield this._internal.setApiSelection(s, doValidate); });
|
|
503
532
|
this.listenForChange = (l) => this._internal.changeObservable.listen(l);
|
|
504
533
|
this.stopListenForChange = (l) => this._internal.changeObservable.stopListen(l);
|
|
@@ -507,14 +536,31 @@ export class CfgProduct {
|
|
|
507
536
|
this.stopListenForLoading = (l) => this._internal.loadingObservable.stopListen(l);
|
|
508
537
|
this.stopAllListenForLoading = () => this._internal.loadingObservable.stopAllListen();
|
|
509
538
|
}
|
|
510
|
-
|
|
511
|
-
|
|
539
|
+
static make(productLoader, lang, catId, partNumber, settings) {
|
|
540
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
541
|
+
return this._makeNewRefFrom(yield _CfgProductInternal.make(productLoader, undefined, lang, catId, partNumber, completeSettings(settings), false, new AggregatedLoadingObservable(), undefined, undefined, undefined, undefined, undefined, undefined));
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Makes an object wrapping the passed object. This is not a clone method, it is a method to
|
|
546
|
+
* make a new outer reference. Like a shallow copy./ We use this to help frameworks that are
|
|
547
|
+
* build around using equals to detect change.
|
|
548
|
+
*/
|
|
549
|
+
static _makeNewRefFrom(source) {
|
|
550
|
+
return new this(source);
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* A client side only key that should uniquely identify this product amongst other additional
|
|
554
|
+
* products.
|
|
555
|
+
*/
|
|
512
556
|
get key() {
|
|
513
557
|
return this._internal.key;
|
|
514
558
|
}
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
559
|
+
/**
|
|
560
|
+
* Only used when this product is in additional product.
|
|
561
|
+
* As a product can have multiple instances of the same additional product this key exists.
|
|
562
|
+
* It will be unique amongst child products, but not globally unique.
|
|
563
|
+
*/
|
|
518
564
|
get refKey() {
|
|
519
565
|
return this._internal.refKey;
|
|
520
566
|
}
|
|
@@ -530,12 +576,14 @@ export class CfgProduct {
|
|
|
530
576
|
get isAdditionalProduct() {
|
|
531
577
|
return this._internal.isAdditionalProduct;
|
|
532
578
|
}
|
|
533
|
-
|
|
579
|
+
/** Only used when this product is an additional product. Root products are never optional. */
|
|
534
580
|
get optional() {
|
|
535
581
|
return this._internal.optional;
|
|
536
582
|
}
|
|
537
|
-
|
|
538
|
-
|
|
583
|
+
/**
|
|
584
|
+
* Only applicable when this product is optional. If this product is not optional this is
|
|
585
|
+
* always true.
|
|
586
|
+
*/
|
|
539
587
|
get selected() {
|
|
540
588
|
return this._internal.selected;
|
|
541
589
|
}
|
|
@@ -545,13 +593,16 @@ export class CfgProduct {
|
|
|
545
593
|
get uuid() {
|
|
546
594
|
return this._internal.uuid;
|
|
547
595
|
}
|
|
596
|
+
get unit() {
|
|
597
|
+
return this._internal.unit;
|
|
598
|
+
}
|
|
548
599
|
get sku() {
|
|
549
600
|
return this._internal.rawProductData.sku;
|
|
550
601
|
}
|
|
551
602
|
get styleNr() {
|
|
552
603
|
return this._internal.rawProductData.partsData.styleNr;
|
|
553
604
|
}
|
|
554
|
-
|
|
605
|
+
/** An URL. */
|
|
555
606
|
get preview() {
|
|
556
607
|
return this._internal.rawProductData.navImage;
|
|
557
608
|
}
|
|
@@ -570,8 +621,10 @@ export class CfgProduct {
|
|
|
570
621
|
get currency() {
|
|
571
622
|
return this._internal.currency;
|
|
572
623
|
}
|
|
573
|
-
|
|
574
|
-
|
|
624
|
+
/**
|
|
625
|
+
* If positive the number of fraction digits.
|
|
626
|
+
* If negative rounding (essentially the number of zeros to the right)
|
|
627
|
+
*/
|
|
575
628
|
get fractionDigits() {
|
|
576
629
|
return this._internal.fractionDigits;
|
|
577
630
|
}
|
|
@@ -579,10 +632,3 @@ export class CfgProduct {
|
|
|
579
632
|
return this._internal.aggregatedPrice;
|
|
580
633
|
}
|
|
581
634
|
}
|
|
582
|
-
CfgProduct.make = (productLoader, lang, catId, partNumber, settings) => __awaiter(void 0, void 0, void 0, function* () {
|
|
583
|
-
return CfgProduct._makeNewRefFrom(yield _CfgProductInternal.make(productLoader, undefined, lang, catId, partNumber, completeSettings(settings), false, new AggregatedLoadingObservable(), undefined, undefined, undefined, undefined, undefined));
|
|
584
|
-
});
|
|
585
|
-
/// Makes an object wrapping the passed object. This is not a clone method,
|
|
586
|
-
/// it is a method to make a new outer reference. Like a shallow copy.
|
|
587
|
-
/// We use this to help frameworks that are build around using equals to detect change.
|
|
588
|
-
CfgProduct._makeNewRefFrom = (source) => new CfgProduct(source);
|
package/dist/index.d.ts
CHANGED
|
@@ -13,4 +13,5 @@ export * from "./productConfiguration/productParamsGenerator.js";
|
|
|
13
13
|
export * from "./productLoader.js";
|
|
14
14
|
export * from "./utilitiesCatalogueData.js";
|
|
15
15
|
export * from "./utilitiesCataloguePermission.js";
|
|
16
|
+
export * from "./utilitiesNumericValues.js";
|
|
16
17
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -2,15 +2,19 @@ import { CfgMtrlSourceBuffer, CfgMtrlSourceUrl } from "./CfgMtrlSource.js";
|
|
|
2
2
|
// In this file an "application" is a combination of 0..1 Material (Mtrl) and 0..m AreaTags.
|
|
3
3
|
// These can exist on Catalogue-level (Application Areas), Product-level, in the Feature-Options
|
|
4
4
|
// tree (Configuration) and for the sake of debugging, locally as debug overrides.
|
|
5
|
+
//
|
|
5
6
|
// What this file is about is reducing/aggregating/compiling this to a simple map which says that
|
|
6
7
|
// Area1 should have material Jeans etc. The code is written to match the behavior in CET.
|
|
8
|
+
//
|
|
7
9
|
// Side note: There is no connection in material application between products
|
|
8
10
|
// in a product with additional products. So there exists no methods for
|
|
9
11
|
// aggregating over multiple products at all.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
/**
|
|
13
|
+
* When there are multiple applications on the same node we need to reduce these to what is
|
|
14
|
+
* actually applied. The cases where there multiple applications on the same node affecting the
|
|
15
|
+
* same thing are probably user errors i Catalogue Creator. However, Catalogue Creator allows the
|
|
16
|
+
* user to let them slip through, so we need to handle them the same way CET does.
|
|
17
|
+
*/
|
|
14
18
|
const reduceApplications = (applications, skipNoMtrl = false) => applications.reduce((acc, application) => {
|
|
15
19
|
const { areaTags, mtrl } = application;
|
|
16
20
|
// Applications which have a Mtrl but no AreaTags only have meaning on Option nodes. That
|
|
@@ -80,8 +84,9 @@ export function aggregateAllMaterialApplications(applicationAreas, productMtrlAp
|
|
|
80
84
|
}
|
|
81
85
|
return areasToMaterials;
|
|
82
86
|
}
|
|
83
|
-
|
|
84
|
-
|
|
87
|
+
/**
|
|
88
|
+
* For this Feature and it's descendants, compile the Applications into the passed areasToMaterials.
|
|
89
|
+
*/
|
|
85
90
|
function aggregateForFeature(feature, areasToMaterials, areasOpenForOverrideInOption = new Set()) {
|
|
86
91
|
const featureMtrlApplications = feature._internal.mtrlApplications;
|
|
87
92
|
for (const [areaTag, mtrlSource] of reduceApplications(featureMtrlApplications)) {
|
|
@@ -8,17 +8,17 @@ export class CfgMtrlApplication {
|
|
|
8
8
|
this._previewUrl = _previewUrl;
|
|
9
9
|
}
|
|
10
10
|
static fromUrlForDebug(areaTags, url) {
|
|
11
|
-
return
|
|
11
|
+
return this.fromMtrlSourceForDebug(areaTags, new CfgMtrlSourceUrl(url, "debug"));
|
|
12
12
|
}
|
|
13
13
|
static fromBufferForDebug(areaTags, fileName, buffer) {
|
|
14
|
-
return
|
|
14
|
+
return this.fromMtrlSourceForDebug(areaTags, new CfgMtrlSourceBuffer(fileName, buffer));
|
|
15
15
|
}
|
|
16
16
|
static fromMtrlSourceForDebug(areaTags, mtrlSource) {
|
|
17
17
|
const ts = areaTags.filter((t) => t.trim() !== "");
|
|
18
18
|
if (ts.length === 0) {
|
|
19
19
|
throw Error("No tags");
|
|
20
20
|
}
|
|
21
|
-
return new
|
|
21
|
+
return new this(CfgMtrlApplicationSource.Debug, areaTags, mtrlSource, undefined);
|
|
22
22
|
}
|
|
23
23
|
static fromMtrlLikeApplication(source, application) {
|
|
24
24
|
const materialUrl = application.material;
|
|
@@ -26,7 +26,7 @@ export class CfgMtrlApplication {
|
|
|
26
26
|
const url = materialUrl || previewUrl;
|
|
27
27
|
const urlIsFromProperty = materialUrl ? "material" : "preview";
|
|
28
28
|
const mtrl = url ? new CfgMtrlSourceUrl(url, urlIsFromProperty) : undefined;
|
|
29
|
-
return new
|
|
29
|
+
return new this(source, application.areas, mtrl, previewUrl);
|
|
30
30
|
}
|
|
31
31
|
get source() {
|
|
32
32
|
return this._source;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Observable, SingleArgCallback } from "@configura/web-utilities";
|
|
1
|
+
import { LengthUnit, Observable, SingleArgCallback } from "@configura/web-utilities";
|
|
2
2
|
import { Feature, SelectedOption } from "../CatalogueAPI.js";
|
|
3
3
|
import { CfgProduct, _CfgProductInternal } from "../CfgProduct.js";
|
|
4
4
|
import { CfgMtrlApplication } from "../material/CfgMtrlApplication.js";
|
|
@@ -33,10 +33,11 @@ export declare class _CfgFeatureInternal {
|
|
|
33
33
|
private readonly allRawFeatures;
|
|
34
34
|
readonly key: string;
|
|
35
35
|
readonly parent: _CfgProductConfigurationInternal | _CfgOptionInternal;
|
|
36
|
+
readonly parentConfiguration: _CfgProductConfigurationInternal;
|
|
36
37
|
readonly parentProduct: _CfgProductInternal;
|
|
37
38
|
readonly rootProduct: _CfgProductInternal;
|
|
38
39
|
constructor(rawFeature: Feature, allRawFeatures: Feature[], key: string, // Unique amongst siblings
|
|
39
|
-
parent: _CfgProductConfigurationInternal | _CfgOptionInternal, parentProduct: _CfgProductInternal, rootProduct: _CfgProductInternal);
|
|
40
|
+
parent: _CfgProductConfigurationInternal | _CfgOptionInternal, parentConfiguration: _CfgProductConfigurationInternal, parentProduct: _CfgProductInternal, rootProduct: _CfgProductInternal);
|
|
40
41
|
readonly selectionType: SelectionType;
|
|
41
42
|
private _options;
|
|
42
43
|
private readonly _selectedOptions;
|
|
@@ -45,7 +46,17 @@ export declare class _CfgFeatureInternal {
|
|
|
45
46
|
readonly changeObservable: Observable<FeatureChangeNotification>;
|
|
46
47
|
get code(): string;
|
|
47
48
|
get groupCode(): string | undefined;
|
|
49
|
+
get isUseNumericValue(): boolean;
|
|
50
|
+
get numericValue(): number | undefined;
|
|
51
|
+
setNumericValue: (val: number) => Promise<boolean>;
|
|
48
52
|
get description(): string;
|
|
53
|
+
/**
|
|
54
|
+
* The MeasureParam class is re-used for different purposes. In Features it is used
|
|
55
|
+
* to indicate which stretch measures inside Models shall be affected by this state
|
|
56
|
+
* of this Feature. Hence only the code property is used.
|
|
57
|
+
*/
|
|
58
|
+
get measureParamCodes(): string[] | undefined;
|
|
59
|
+
get unit(): LengthUnit;
|
|
49
60
|
get mtrlApplications(): CfgMtrlApplication[];
|
|
50
61
|
get selectedOptions(): CfgOption[];
|
|
51
62
|
get ancestorsSelected(): boolean;
|
|
@@ -72,6 +83,8 @@ export declare class _CfgFeatureInternal {
|
|
|
72
83
|
setApiSelection: (apiOptionSelectionMap: {
|
|
73
84
|
[index: string]: SelectedOption;
|
|
74
85
|
} | undefined) => Promise<boolean>;
|
|
86
|
+
/** Pushes to refresh stretch. Does not cause validation. */
|
|
87
|
+
pushStretch: () => Promise<boolean>;
|
|
75
88
|
structureCompare: (other: _CfgFeatureInternal, strictOrder?: boolean, descriptionMatch?: boolean) => boolean;
|
|
76
89
|
tryMatchSelection: (other: _CfgFeatureInternal, descriptionMatch?: boolean) => Promise<boolean>;
|
|
77
90
|
/**
|
|
@@ -94,13 +107,13 @@ export declare class _CfgFeatureInternal {
|
|
|
94
107
|
}
|
|
95
108
|
export declare class CfgFeature {
|
|
96
109
|
readonly _internal: _CfgFeatureInternal;
|
|
97
|
-
static make
|
|
110
|
+
static make(rawFeature: Feature, allRawFeatures: Feature[], key: string, parent: _CfgProductConfigurationInternal | _CfgOptionInternal, parentConfiguration: _CfgProductConfigurationInternal, parentProduct: _CfgProductInternal, rootProduct: _CfgProductInternal): CfgFeature;
|
|
98
111
|
/**
|
|
99
112
|
* Makes an object wrapping the passed object. This is not a clone method,
|
|
100
113
|
* it is a method to make a new outer reference. Like a shallow copy.
|
|
101
114
|
* We use this to help frameworks that are built around using equals to detect change.
|
|
102
115
|
*/
|
|
103
|
-
static _makeNewRefFrom
|
|
116
|
+
static _makeNewRefFrom(internal: _CfgFeatureInternal): CfgFeature;
|
|
104
117
|
/**
|
|
105
118
|
* Private constructor and make-method because make new ref requires the constructor to
|
|
106
119
|
* take an internal and we don't want those who instantiate CfgFeature to have to be aware
|
|
@@ -114,6 +127,19 @@ export declare class CfgFeature {
|
|
|
114
127
|
get key(): string;
|
|
115
128
|
get code(): string;
|
|
116
129
|
get groupCode(): string | undefined;
|
|
130
|
+
/**
|
|
131
|
+
* If true the options in the feature is selected by both sending its code and numeric value
|
|
132
|
+
* when selecting.
|
|
133
|
+
*/
|
|
134
|
+
get isUseNumericValue(): boolean;
|
|
135
|
+
/** This will read the numeric value of the selected option. */
|
|
136
|
+
get numericValue(): number | undefined;
|
|
137
|
+
/**
|
|
138
|
+
* This will find the first option allowing the value, set the value on it and select it.
|
|
139
|
+
* This is an implicit option-select.
|
|
140
|
+
*/
|
|
141
|
+
setNumericValue: (val: number) => Promise<boolean>;
|
|
142
|
+
get unit(): LengthUnit;
|
|
117
143
|
get description(): string;
|
|
118
144
|
get hasUpcharge(): boolean | undefined;
|
|
119
145
|
get selectedOptions(): CfgOption[];
|