@configura/web-api 1.6.1-alpha.0 → 1.6.1-alpha.4
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/CfgProduct.d.ts +21 -27
- package/dist/CfgProduct.js +52 -90
- package/dist/productConfiguration/CfgFeature.d.ts +1 -3
- package/dist/productConfiguration/CfgFeature.js +3 -34
- package/dist/productConfiguration/CfgOption.d.ts +24 -13
- package/dist/productConfiguration/CfgOption.js +39 -34
- package/dist/productConfiguration/CfgProductConfiguration.d.ts +2 -4
- package/dist/productConfiguration/CfgProductConfiguration.js +0 -17
- package/dist/productConfiguration/filters.d.ts +1 -1
- package/dist/productConfiguration/filters.js +6 -3
- package/dist/syncGroups/SyncGroupsApplier.js +8 -7
- package/dist/syncGroups/SyncGroupsApplyMode.d.ts +15 -9
- package/dist/syncGroups/SyncGroupsApplyMode.js +14 -8
- package/dist/syncGroups/SyncGroupsHandler.d.ts +13 -3
- package/dist/syncGroups/SyncGroupsHandler.js +298 -17
- package/dist/syncGroups/SyncGroupsPathHelper.d.ts +27 -0
- package/dist/syncGroups/SyncGroupsPathHelper.js +89 -0
- package/dist/syncGroups/SyncGroupsState.d.ts +11 -5
- package/dist/syncGroups/SyncGroupsState.js +76 -26
- package/dist/syncGroups/SyncGroupsTransaction.d.ts +7 -6
- package/dist/syncGroups/SyncGroupsTransaction.js +14 -20
- package/dist/utilitiesCatalogueData.js +7 -5
- package/package.json +3 -3
package/dist/CfgProduct.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { AggregatedLoadingObservable, LengthUnit, Observable, SingleArgCallback } from "@configura/web-utilities";
|
|
2
|
-
import { AdditionalProductConfiguration, CatalogueParams, MeasureParam, MtrlApplication, Prices, Transform } from "./CatalogueAPI.js";
|
|
2
|
+
import { AdditionalProductConfiguration, AdditionalProductRef, CatalogueParams, MeasureParam, MtrlApplication, Prices, Transform } from "./CatalogueAPI.js";
|
|
3
3
|
import { CfgMeasureDefinition } from "./CfgMeasure.js";
|
|
4
4
|
import { _CfgFeatureInternal } from "./productConfiguration/CfgFeature.js";
|
|
5
|
-
import { ProductConfigurationBubbleMode
|
|
6
|
-
import { CfgProductConfiguration
|
|
5
|
+
import { ProductConfigurationBubbleMode } from "./productConfiguration/CfgOption.js";
|
|
6
|
+
import { CfgProductConfiguration } from "./productConfiguration/CfgProductConfiguration.js";
|
|
7
7
|
import { ProductLoader } from "./productLoader.js";
|
|
8
8
|
import { SyncGroupsApplyMode } from "./syncGroups/SyncGroupsApplyMode.js";
|
|
9
9
|
import { SyncGroupsHandler } from "./syncGroups/SyncGroupsHandler.js";
|
|
@@ -20,16 +20,17 @@ export declare type CfgProductSettings = {
|
|
|
20
20
|
*/
|
|
21
21
|
strictSelectOneSelectionCount: boolean;
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
23
|
+
* Controls if SyncGroups are applied Faster or Stricter.
|
|
24
|
+
*
|
|
25
|
+
* Fast - Tries to minimize the number of validates calls to the AI lowering the response times
|
|
26
|
+
* for selecting options. Might not always give the expected result for complex products.
|
|
27
|
+
*
|
|
28
|
+
* Strict - Apply the SyncGroups rules in a stricter fashion to be as close to CET as possible,
|
|
29
|
+
* which might result in longer response times and more validation calls to the API when
|
|
30
|
+
* selecting options.
|
|
31
|
+
*
|
|
32
|
+
* The SDK will default to Strict, but we recommend that you try out Fast since cases where the
|
|
33
|
+
* results differ should be rare in most real uses cases and the speedup can be quite large.
|
|
33
34
|
*/
|
|
34
35
|
syncGroupsApplyMode: SyncGroupsApplyMode | undefined;
|
|
35
36
|
};
|
|
@@ -56,8 +57,6 @@ export declare type CfgPrice = {
|
|
|
56
57
|
currency: string;
|
|
57
58
|
fractionDigits: number;
|
|
58
59
|
};
|
|
59
|
-
export declare type CfgPathSegment = string;
|
|
60
|
-
export declare type CfgPath = CfgPathSegment[];
|
|
61
60
|
export declare type RevalidateResult = {
|
|
62
61
|
wasAborted: boolean;
|
|
63
62
|
requestDidValidate: boolean;
|
|
@@ -77,13 +76,10 @@ export declare class _CfgProductInternal {
|
|
|
77
76
|
private readonly _rawUnit;
|
|
78
77
|
private _rawProductData;
|
|
79
78
|
readonly loadingObservable: AggregatedLoadingObservable;
|
|
80
|
-
readonly refKey: string | undefined;
|
|
81
|
-
readonly refDescription: string | undefined;
|
|
82
79
|
readonly parent: _CfgProductInternal | undefined;
|
|
83
|
-
|
|
84
|
-
anchor: MeasureParam | undefined;
|
|
80
|
+
private _additionalProductRef;
|
|
85
81
|
private readonly _syncGroupHandler;
|
|
86
|
-
static make: (productLoaderRaw: ProductLoader, productLoaderForGroupedLoad: ProductLoader | undefined, lang: string, catId: CatalogueParams, partNumber: string, settings: CfgProductSettings, optional: boolean, loadingObservable: AggregatedLoadingObservable,
|
|
82
|
+
static make: (productLoaderRaw: ProductLoader, productLoaderForGroupedLoad: ProductLoader | undefined, lang: string, catId: CatalogueParams, partNumber: string, settings: CfgProductSettings, optional: boolean, loadingObservable: AggregatedLoadingObservable, parent: _CfgProductInternal | undefined, root: _CfgProductInternal | undefined, additionalProductRef: AdditionalProductRef | undefined) => Promise<_CfgProductInternal>;
|
|
87
83
|
private constructor();
|
|
88
84
|
readonly root: _CfgProductInternal;
|
|
89
85
|
private _destroyed;
|
|
@@ -96,6 +92,7 @@ export declare class _CfgProductInternal {
|
|
|
96
92
|
readonly isAdditionalProduct: boolean;
|
|
97
93
|
clone(parent?: _CfgProductInternal, root?: _CfgProductInternal): Promise<_CfgProductInternal>;
|
|
98
94
|
destroy: () => void;
|
|
95
|
+
_updateAdditionalProdRef(p: AdditionalProductRef): void;
|
|
99
96
|
get description(): string | undefined;
|
|
100
97
|
get rootNodeSources(): RootNodeSource[] | undefined;
|
|
101
98
|
get mtrlApplications(): MtrlApplication[] | undefined;
|
|
@@ -105,6 +102,9 @@ export declare class _CfgProductInternal {
|
|
|
105
102
|
private _measureDefinitions;
|
|
106
103
|
get measureDefinitions(): CfgMeasureDefinition[];
|
|
107
104
|
private _unit;
|
|
105
|
+
get refKey(): string | undefined;
|
|
106
|
+
get transform(): Transform | undefined;
|
|
107
|
+
get anchor(): MeasureParam | undefined;
|
|
108
108
|
/** @throws an error if the actual unit sent by the server was not a LengthUnit */
|
|
109
109
|
get unit(): LengthUnit;
|
|
110
110
|
get aggregatedPrice(): CfgPrice;
|
|
@@ -136,15 +136,9 @@ export declare class _CfgProductInternal {
|
|
|
136
136
|
_configurationHasChanged: (freshRef: CfgProductConfiguration, bubbleMode: ProductConfigurationBubbleMode) => Promise<void>;
|
|
137
137
|
getApiSelection: () => AdditionalProductConfiguration;
|
|
138
138
|
setApiSelection: (s: AdditionalProductConfiguration, doValidate: boolean, productLoaderForGroupedLoad?: ProductLoader | undefined) => Promise<boolean>;
|
|
139
|
-
copyFrom: (
|
|
139
|
+
copyFrom: (source: _CfgProductInternal, doValidate: boolean, productLoaderForGroupedLoad?: ProductLoader | undefined) => Promise<boolean>;
|
|
140
140
|
private _setApiSelectionWithOtherProduct;
|
|
141
141
|
get syncGroupHandler(): SyncGroupsHandler | undefined;
|
|
142
|
-
get path(): CfgPath;
|
|
143
|
-
getFromPath(path: CfgPath): _CfgProductInternal | _CfgProductConfigurationInternal | _CfgFeatureInternal | _CfgOptionInternal;
|
|
144
|
-
getProductFromPath(path: CfgPath): _CfgProductInternal;
|
|
145
|
-
getProductConfigurationFromPath(path: CfgPath): _CfgProductConfigurationInternal;
|
|
146
|
-
getFeatureFromPath(path: CfgPath): _CfgFeatureInternal;
|
|
147
|
-
getOptionFromPath(path: CfgPath): _CfgOptionInternal;
|
|
148
142
|
structureCompare: (other: _CfgProductInternal, strictOrder?: boolean, descriptionMatch?: boolean) => boolean;
|
|
149
143
|
tryMatchSelection: (other: _CfgProductInternal, descriptionMatch?: boolean, productLoaderForGroupedLoad?: ProductLoader | undefined) => Promise<boolean>;
|
|
150
144
|
/** Only features in selected options and selected additional products. */
|
package/dist/CfgProduct.js
CHANGED
|
@@ -7,20 +7,18 @@ 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, toLengthUnit, } from "@configura/web-utilities";
|
|
10
|
+
import { AggregatedLoadingObservable, assert, assertDefined, compareArrays, count, Observable, toLengthUnit, } from "@configura/web-utilities";
|
|
11
11
|
import { CfgMeasureDefinition } from "./CfgMeasure.js";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { CfgProductConfiguration, _CfgProductConfigurationInternal, } from "./productConfiguration/CfgProductConfiguration.js";
|
|
12
|
+
import { ProductConfigurationBubbleMode } from "./productConfiguration/CfgOption.js";
|
|
13
|
+
import { CfgProductConfiguration } from "./productConfiguration/CfgProductConfiguration.js";
|
|
15
14
|
import { collectAdditionalProductRefs } from "./productConfiguration/utilitiesProductConfiguration.js";
|
|
16
15
|
import { wrapWithCache } from "./productLoader.js";
|
|
17
16
|
import { SyncGroupsHandler } from "./syncGroups/SyncGroupsHandler.js";
|
|
18
|
-
import { comparePricesObjects, correctDefaultsOnCatalogueParams, isSameProductRef, makeProductKey, } from "./utilitiesCatalogueData.js";
|
|
17
|
+
import { comparePricesObjects, correctDefaultsOnCatalogueParams, isSameCatalogueParams, isSameProductRef, makeProductKey, } from "./utilitiesCatalogueData.js";
|
|
19
18
|
function completeSettings(incompleteSettings) {
|
|
20
|
-
var _a
|
|
19
|
+
var _a;
|
|
21
20
|
return {
|
|
22
21
|
strictSelectOneSelectionCount: (_a = incompleteSettings === null || incompleteSettings === void 0 ? void 0 : incompleteSettings.strictSelectOneSelectionCount) !== null && _a !== void 0 ? _a : false,
|
|
23
|
-
strictSetApiSelectionMatch: (_b = incompleteSettings === null || incompleteSettings === void 0 ? void 0 : incompleteSettings.strictSetApiSelectionMatch) !== null && _b !== void 0 ? _b : false,
|
|
24
22
|
syncGroupsApplyMode: incompleteSettings === null || incompleteSettings === void 0 ? void 0 : incompleteSettings.syncGroupsApplyMode,
|
|
25
23
|
};
|
|
26
24
|
}
|
|
@@ -53,7 +51,8 @@ function isDescriptionMatch(l, r) {
|
|
|
53
51
|
* the class that should be used and interacted with.
|
|
54
52
|
*/
|
|
55
53
|
export class _CfgProductInternal {
|
|
56
|
-
constructor(initSuccess, initFail, _productLoaderRaw, lang, catId, partNumber, settings, optional, selected, rootFeatureRefs, allRawFeatures, uuid, _rawUnit, _rawProductData, apiSelection, loadingObservable,
|
|
54
|
+
constructor(initSuccess, initFail, _productLoaderRaw, lang, catId, partNumber, settings, optional, selected, rootFeatureRefs, allRawFeatures, uuid, _rawUnit, _rawProductData, apiSelection, loadingObservable, parent, root, _additionalProductRef, _syncGroupHandler) {
|
|
55
|
+
var _a;
|
|
57
56
|
this._productLoaderRaw = _productLoaderRaw;
|
|
58
57
|
this.lang = lang;
|
|
59
58
|
this.catId = catId;
|
|
@@ -63,11 +62,8 @@ export class _CfgProductInternal {
|
|
|
63
62
|
this._rawUnit = _rawUnit;
|
|
64
63
|
this._rawProductData = _rawProductData;
|
|
65
64
|
this.loadingObservable = loadingObservable;
|
|
66
|
-
this.refKey = refKey;
|
|
67
|
-
this.refDescription = refDescription;
|
|
68
65
|
this.parent = parent;
|
|
69
|
-
this.
|
|
70
|
-
this.anchor = anchor;
|
|
66
|
+
this._additionalProductRef = _additionalProductRef;
|
|
71
67
|
this._syncGroupHandler = _syncGroupHandler;
|
|
72
68
|
this._destroyed = false;
|
|
73
69
|
this.additionalProducts = [];
|
|
@@ -154,8 +150,8 @@ export class _CfgProductInternal {
|
|
|
154
150
|
this.setApiSelection = (s, doValidate, productLoaderForGroupedLoad) => __awaiter(this, void 0, void 0, function* () {
|
|
155
151
|
return this._setApiSelectionWithOtherProduct(s, doValidate, productLoaderForGroupedLoad, undefined);
|
|
156
152
|
});
|
|
157
|
-
this.copyFrom = (
|
|
158
|
-
return yield this._setApiSelectionWithOtherProduct(
|
|
153
|
+
this.copyFrom = (source, doValidate, productLoaderForGroupedLoad) => __awaiter(this, void 0, void 0, function* () {
|
|
154
|
+
return yield this._setApiSelectionWithOtherProduct(source.getApiSelection(), doValidate, productLoaderForGroupedLoad, source);
|
|
159
155
|
});
|
|
160
156
|
this._setApiSelectionWithOtherProduct = (s, doValidate, productLoaderForGroupedLoad, sourceProduct) => __awaiter(this, void 0, void 0, function* () {
|
|
161
157
|
// Wrap with cache will make getProduct for this function call use the same server call
|
|
@@ -166,6 +162,7 @@ export class _CfgProductInternal {
|
|
|
166
162
|
let change = false;
|
|
167
163
|
if (sourceProduct !== undefined) {
|
|
168
164
|
this._rawProductData = sourceProduct.rawProductData;
|
|
165
|
+
this.configuration._internal.populateFeatures(sourceProduct.configuration.rootFeatureRefs);
|
|
169
166
|
change = true; // We can not know if this is an actual change, so we assume it is
|
|
170
167
|
}
|
|
171
168
|
const configurationChange = yield this.configuration._internal.setApiSelection(s.selOptions, false);
|
|
@@ -186,27 +183,19 @@ export class _CfgProductInternal {
|
|
|
186
183
|
throw new Error(`Additional products are not same length. This product: "${this.key}". This product additional products count: ${additionalProductsCount}. Passed apiSelection additional products count: ${apiSelectionAdditionalProductsCount}`);
|
|
187
184
|
}
|
|
188
185
|
const sourceProductAdditionalProducts = sourceProduct === null || sourceProduct === void 0 ? void 0 : sourceProduct.additionalProducts;
|
|
189
|
-
|
|
190
|
-
additionalProductsCount
|
|
191
|
-
throw new Error(`Passed sourceProduct does not have the same number of additional products as this.`);
|
|
192
|
-
}
|
|
186
|
+
assert(!sourceProductAdditionalProducts ||
|
|
187
|
+
additionalProductsCount === sourceProductAdditionalProducts.length, `Passed sourceProduct does not have the same number of additional products as this.`);
|
|
193
188
|
if ((yield Promise.all(apiSelectionAdditionalProducts.map((apiSelectionAdditionalProduct, index) => {
|
|
194
189
|
var _a;
|
|
195
190
|
const refKey = apiSelectionAdditionalProduct.refKey;
|
|
196
|
-
|
|
197
|
-
throw new Error("Additional product api configurations must have refKey.");
|
|
198
|
-
}
|
|
191
|
+
assertDefined(refKey, "Additional product api configurations must have refKey.");
|
|
199
192
|
const i = additionalProducts.findIndex((a) => refKey === a.refKey);
|
|
200
|
-
|
|
201
|
-
throw new Error(`Additional product not found. This product: "${this.key}". refKey of not found additional product: "${refKey}"`);
|
|
202
|
-
}
|
|
193
|
+
assert(i !== -1, `Additional product not found. This product: "${this.key}". refKey of not found additional product: "${refKey}"`);
|
|
203
194
|
let sourceProductAdditionalProduct = undefined;
|
|
204
195
|
if (sourceProductAdditionalProducts !== undefined) {
|
|
205
196
|
sourceProductAdditionalProduct =
|
|
206
197
|
(_a = sourceProductAdditionalProducts.find((a) => refKey === a.refKey)) === null || _a === void 0 ? void 0 : _a._internal;
|
|
207
|
-
|
|
208
|
-
throw new Error("Additional product not found in sourceProduct");
|
|
209
|
-
}
|
|
198
|
+
assertDefined(sourceProductAdditionalProduct, "Additional product not found in sourceProduct");
|
|
210
199
|
}
|
|
211
200
|
const additionalProduct = additionalProducts.splice(i, 1)[0]; // Splicing like this is okay because this is done synchronous. The setCon. is what is async.
|
|
212
201
|
return additionalProduct._internal._setApiSelectionWithOtherProduct(apiSelectionAdditionalProduct, doValidate, productLoaderForGroupedLoad, sourceProductAdditionalProduct);
|
|
@@ -372,14 +361,19 @@ export class _CfgProductInternal {
|
|
|
372
361
|
let i = currentAdditionalProducts.length;
|
|
373
362
|
while (i--) {
|
|
374
363
|
const currentAdditionalProduct = currentAdditionalProducts[i];
|
|
375
|
-
const
|
|
376
|
-
|
|
364
|
+
const j = additionalProductRefs.findIndex((p) => {
|
|
365
|
+
const prodRef = p.prodRef;
|
|
366
|
+
return (prodRef.refKey === currentAdditionalProduct.refKey &&
|
|
367
|
+
prodRef.partNumber === currentAdditionalProduct.partNumber &&
|
|
368
|
+
isSameCatalogueParams(prodRef.catId, currentAdditionalProduct.catId));
|
|
369
|
+
});
|
|
377
370
|
if (j === -1) {
|
|
378
371
|
currentAdditionalProduct.destroy();
|
|
379
372
|
currentAdditionalProducts.splice(i, 1);
|
|
380
373
|
change = true;
|
|
381
374
|
}
|
|
382
375
|
else {
|
|
376
|
+
currentAdditionalProduct._internal._updateAdditionalProdRef(additionalProductRefs[j].prodRef);
|
|
383
377
|
additionalProductRefs.splice(j, 1);
|
|
384
378
|
}
|
|
385
379
|
}
|
|
@@ -392,7 +386,7 @@ export class _CfgProductInternal {
|
|
|
392
386
|
const additionalProductRef = p.prodRef;
|
|
393
387
|
return {
|
|
394
388
|
originalIndex: p.originalIndex,
|
|
395
|
-
product: CfgProduct._makeNewRefFrom(yield _CfgProductInternal.make(productLoaderRaw, productLoaderForGroupedLoad, lang, additionalProductRef.catId, additionalProductRef.partNumber, this.settings, additionalProductRef.optional === true, this.loadingObservable,
|
|
389
|
+
product: CfgProduct._makeNewRefFrom(yield _CfgProductInternal.make(productLoaderRaw, productLoaderForGroupedLoad, lang, additionalProductRef.catId, additionalProductRef.partNumber, this.settings, additionalProductRef.optional === true, this.loadingObservable, this, this.root, additionalProductRef)),
|
|
396
390
|
};
|
|
397
391
|
}))()));
|
|
398
392
|
if (this._destroyed) {
|
|
@@ -411,7 +405,7 @@ export class _CfgProductInternal {
|
|
|
411
405
|
}
|
|
412
406
|
});
|
|
413
407
|
this.root = root !== null && root !== void 0 ? root : this;
|
|
414
|
-
this.key = makeProductKey(catId,
|
|
408
|
+
this.key = makeProductKey(catId, (_a = _additionalProductRef === null || _additionalProductRef === void 0 ? void 0 : _additionalProductRef.refKey) !== null && _a !== void 0 ? _a : partNumber);
|
|
415
409
|
this._selected = optional ? selected : undefined;
|
|
416
410
|
this.isAdditionalProduct = parent !== undefined;
|
|
417
411
|
this._configuration = CfgProductConfiguration.make(initSuccess, initFail, rootFeatureRefs, allRawFeatures, apiSelection, this, this.root);
|
|
@@ -425,7 +419,7 @@ export class _CfgProductInternal {
|
|
|
425
419
|
var _a;
|
|
426
420
|
const p = new _CfgProductInternal(() => {
|
|
427
421
|
initSuccess(p);
|
|
428
|
-
}, 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(),
|
|
422
|
+
}, 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(), parent, root, this._additionalProductRef, (_a = this._syncGroupHandler) === null || _a === void 0 ? void 0 : _a.clone());
|
|
429
423
|
});
|
|
430
424
|
for (const additionalProduct of this.additionalProducts) {
|
|
431
425
|
product.additionalProducts.push(CfgProduct._makeNewRefFrom(yield additionalProduct._internal.clone(product, root || product)));
|
|
@@ -433,8 +427,15 @@ export class _CfgProductInternal {
|
|
|
433
427
|
return product;
|
|
434
428
|
});
|
|
435
429
|
}
|
|
430
|
+
_updateAdditionalProdRef(p) {
|
|
431
|
+
this._additionalProductRef = p;
|
|
432
|
+
if (p.optional !== this.optional) {
|
|
433
|
+
this._selected = p.optional ? false : undefined;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
436
|
get description() {
|
|
437
|
-
|
|
437
|
+
var _a, _b;
|
|
438
|
+
return (_b = (_a = this._additionalProductRef) === null || _a === void 0 ? void 0 : _a.refDescription) !== null && _b !== void 0 ? _b : this._rawProductData.description;
|
|
438
439
|
}
|
|
439
440
|
get rootNodeSources() {
|
|
440
441
|
return this._rawProductData.models;
|
|
@@ -460,6 +461,18 @@ export class _CfgProductInternal {
|
|
|
460
461
|
}
|
|
461
462
|
return this._measureDefinitions;
|
|
462
463
|
}
|
|
464
|
+
get refKey() {
|
|
465
|
+
var _a;
|
|
466
|
+
return (_a = this._additionalProductRef) === null || _a === void 0 ? void 0 : _a.refKey;
|
|
467
|
+
}
|
|
468
|
+
get transform() {
|
|
469
|
+
var _a;
|
|
470
|
+
return (_a = this._additionalProductRef) === null || _a === void 0 ? void 0 : _a.transform;
|
|
471
|
+
}
|
|
472
|
+
get anchor() {
|
|
473
|
+
var _a;
|
|
474
|
+
return (_a = this._additionalProductRef) === null || _a === void 0 ? void 0 : _a.anchor;
|
|
475
|
+
}
|
|
463
476
|
/** @throws an error if the actual unit sent by the server was not a LengthUnit */
|
|
464
477
|
get unit() {
|
|
465
478
|
if (this._unit === undefined) {
|
|
@@ -540,68 +553,17 @@ export class _CfgProductInternal {
|
|
|
540
553
|
get syncGroupHandler() {
|
|
541
554
|
return this.root._syncGroupHandler;
|
|
542
555
|
}
|
|
543
|
-
get path() {
|
|
544
|
-
if (this.parent === undefined || this.refKey === undefined) {
|
|
545
|
-
return [];
|
|
546
|
-
}
|
|
547
|
-
return [...this.parent.path, "p", this.refKey];
|
|
548
|
-
}
|
|
549
|
-
getFromPath(path) {
|
|
550
|
-
path = path.slice();
|
|
551
|
-
const s = path.shift();
|
|
552
|
-
switch (s) {
|
|
553
|
-
case undefined:
|
|
554
|
-
return this;
|
|
555
|
-
case "p":
|
|
556
|
-
const refKey = path.shift();
|
|
557
|
-
const additionalProduct = this.additionalProducts.find((p) => p.refKey === refKey);
|
|
558
|
-
if (additionalProduct === undefined) {
|
|
559
|
-
throw new Error(`Additional product not found "p, ${refKey}, ${path.join(", ")}"`);
|
|
560
|
-
}
|
|
561
|
-
return additionalProduct._internal.getFromPath(path);
|
|
562
|
-
case "c":
|
|
563
|
-
return this.configuration._internal.getFromPath(path);
|
|
564
|
-
default:
|
|
565
|
-
throw new Error(`Unexpected path segment ${s}`);
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
getProductFromPath(path) {
|
|
569
|
-
const p = this.getFromPath(path);
|
|
570
|
-
if (p instanceof _CfgProductInternal) {
|
|
571
|
-
return p;
|
|
572
|
-
}
|
|
573
|
-
throw new Error(`Path did not lead to a Product "${p.path.join(", ")}"`);
|
|
574
|
-
}
|
|
575
|
-
getProductConfigurationFromPath(path) {
|
|
576
|
-
const c = this.getFromPath(path);
|
|
577
|
-
if (c instanceof _CfgProductConfigurationInternal) {
|
|
578
|
-
return c;
|
|
579
|
-
}
|
|
580
|
-
throw new Error(`Path did not lead to a ProductConfiguration "${c.path.join(", ")}"`);
|
|
581
|
-
}
|
|
582
|
-
getFeatureFromPath(path) {
|
|
583
|
-
const f = this.getFromPath(path);
|
|
584
|
-
if (f instanceof _CfgFeatureInternal) {
|
|
585
|
-
return f;
|
|
586
|
-
}
|
|
587
|
-
throw new Error(`Path did not lead to a Feature "${f.path.join(", ")}"`);
|
|
588
|
-
}
|
|
589
|
-
getOptionFromPath(path) {
|
|
590
|
-
const o = this.getFromPath(path);
|
|
591
|
-
if (o instanceof _CfgOptionInternal) {
|
|
592
|
-
return o;
|
|
593
|
-
}
|
|
594
|
-
throw new Error(`Path did not lead to a Option "${o.path.join(", ")}"`);
|
|
595
|
-
}
|
|
596
556
|
}
|
|
597
557
|
_CfgProductInternal.make = (productLoaderRaw, productLoaderForGroupedLoad, // Used when instantiating the current product
|
|
598
|
-
lang, catId, partNumber, settings, optional, loadingObservable,
|
|
558
|
+
lang, catId, partNumber, settings, optional, loadingObservable, parent, root, additionalProductRef) => __awaiter(void 0, void 0, void 0, function* () {
|
|
599
559
|
// Wrap with cache will make getProduct for this function call use the same server call
|
|
600
560
|
// for the same product with the same params. Not retained for future calls, only used
|
|
601
561
|
// at this initial load.
|
|
602
562
|
productLoaderForGroupedLoad =
|
|
603
563
|
productLoaderForGroupedLoad || wrapWithCache(productLoaderRaw);
|
|
604
|
-
const syncGroupHandler = root === undefined
|
|
564
|
+
const syncGroupHandler = root === undefined
|
|
565
|
+
? SyncGroupsHandler.make(settings.syncGroupsApplyMode, loadingObservable)
|
|
566
|
+
: undefined;
|
|
605
567
|
const productResponse = yield productLoaderForGroupedLoad.getProduct(Object.assign(Object.assign({ lang }, correctDefaultsOnCatalogueParams(catId)), { partNumber }));
|
|
606
568
|
const { productData, rootFeatureRefs, features: allRawFeatures, uuid, unit, } = productResponse;
|
|
607
569
|
const product = yield new Promise((initSuccess, initFail) => {
|
|
@@ -610,7 +572,7 @@ lang, catId, partNumber, settings, optional, loadingObservable, refKey, refDescr
|
|
|
610
572
|
// But we can not set the api selection synchronously. And the product configuration needs "this". So we use this callback.
|
|
611
573
|
// Feel free to find a nicer more readable solution :)
|
|
612
574
|
initSuccess(p);
|
|
613
|
-
}, initFail, productLoaderRaw, lang, catId, partNumber, settings, optional, !optional, rootFeatureRefs, allRawFeatures, uuid, unit, productData, productData.partsData.selOptions || [], loadingObservable,
|
|
575
|
+
}, initFail, productLoaderRaw, lang, catId, partNumber, settings, optional, !optional, rootFeatureRefs, allRawFeatures, uuid, unit, productData, productData.partsData.selOptions || [], loadingObservable, parent, root, additionalProductRef, syncGroupHandler);
|
|
614
576
|
});
|
|
615
577
|
yield product._syncAndLoadAdditionalProducts(productLoaderForGroupedLoad);
|
|
616
578
|
// Product is guaranteed to be root
|
|
@@ -665,7 +627,7 @@ export class CfgProduct {
|
|
|
665
627
|
}
|
|
666
628
|
static make(productLoader, lang, catId, partNumber, settings) {
|
|
667
629
|
return __awaiter(this, void 0, void 0, function* () {
|
|
668
|
-
return this._makeNewRefFrom(yield _CfgProductInternal.make(productLoader, undefined, lang, catId, partNumber, completeSettings(settings), false, new AggregatedLoadingObservable(), undefined, undefined, undefined
|
|
630
|
+
return this._makeNewRefFrom(yield _CfgProductInternal.make(productLoader, undefined, lang, catId, partNumber, completeSettings(settings), false, new AggregatedLoadingObservable(), undefined, undefined, undefined));
|
|
669
631
|
});
|
|
670
632
|
}
|
|
671
633
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LengthUnit, Observable, SingleArgCallback } from "@configura/web-utilities";
|
|
2
2
|
import { Feature, SelectedOption, SyncGroup } from "../CatalogueAPI.js";
|
|
3
|
-
import {
|
|
3
|
+
import { CfgProduct, _CfgProductInternal } from "../CfgProduct.js";
|
|
4
4
|
import { CfgMtrlApplication } from "../material/CfgMtrlApplication.js";
|
|
5
5
|
import { CfgOption, ProductConfigurationBubbleMode, _CfgOptionInternal } from "./CfgOption.js";
|
|
6
6
|
import { _CfgProductConfigurationInternal } from "./CfgProductConfiguration.js";
|
|
@@ -96,8 +96,6 @@ export declare class _CfgFeatureInternal {
|
|
|
96
96
|
setApiSelection: (apiOptionSelectionMap: {
|
|
97
97
|
[index: string]: SelectedOption;
|
|
98
98
|
} | undefined) => Promise<boolean>;
|
|
99
|
-
get path(): CfgPath;
|
|
100
|
-
getFromPath(path: CfgPath): _CfgFeatureInternal | _CfgOptionInternal;
|
|
101
99
|
/** Pushes to refresh stretch. Does not cause validation. */
|
|
102
100
|
pushStretch: () => Promise<boolean>;
|
|
103
101
|
structureCompare: (other: _CfgFeatureInternal, strictOrder?: boolean, descriptionMatch?: boolean) => boolean;
|
|
@@ -7,7 +7,7 @@ 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 { compareArrays, convertLength, count, Observable, someMatch, toLengthUnit, } from "@configura/web-utilities";
|
|
10
|
+
import { assertDefined, compareArrays, convertLength, count, Observable, someMatch, toLengthUnit, } from "@configura/web-utilities";
|
|
11
11
|
import { CfgProduct } from "../CfgProduct.js";
|
|
12
12
|
import { CfgMtrlApplication } from "../material/CfgMtrlApplication.js";
|
|
13
13
|
import { CfgMtrlApplicationSource } from "../material/CfgMtrlApplicationSource.js";
|
|
@@ -189,18 +189,6 @@ export class _CfgFeatureInternal {
|
|
|
189
189
|
console.warn(wrongCountWarning);
|
|
190
190
|
}
|
|
191
191
|
}
|
|
192
|
-
if (!isGroup) {
|
|
193
|
-
const apiSelectionCount = Object.keys(apiOptionSelectionMap).length;
|
|
194
|
-
if (selectionCount !== apiSelectionCount) {
|
|
195
|
-
const wrongCountWarning = `All provided Options are expected to be selected. Feature key: "${this.key}". Expected: ${apiSelectionCount} Actual: ${selectionCount}`;
|
|
196
|
-
if (this.rootProduct.settings.strictSetApiSelectionMatch) {
|
|
197
|
-
throw new Error(wrongCountWarning);
|
|
198
|
-
}
|
|
199
|
-
else {
|
|
200
|
-
console.warn(wrongCountWarning);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
192
|
}
|
|
205
193
|
if (change) {
|
|
206
194
|
if (isAllOptionsAffectedByAnySelection) {
|
|
@@ -311,10 +299,8 @@ export class _CfgFeatureInternal {
|
|
|
311
299
|
ProductConfigurationBubbleMode.ValidateAndBubbleSelectedAndApplySyncGroups) {
|
|
312
300
|
const product = this.rootProduct;
|
|
313
301
|
const syncGroupHandler = product.syncGroupHandler;
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
}
|
|
317
|
-
return yield syncGroupHandler.selectOption(product, optionInternal.path, on, wrapWithCache(product._productLoaderRaw));
|
|
302
|
+
assertDefined(syncGroupHandler, `Sync group handler is required for bubble mode ${ProductConfigurationBubbleMode.ValidateAndBubbleSelectedAndApplySyncGroups}`);
|
|
303
|
+
return yield syncGroupHandler.selectOption(product, optionInternal, on, wrapWithCache(product._productLoaderRaw));
|
|
318
304
|
}
|
|
319
305
|
if (!on) {
|
|
320
306
|
if (this.selectionType === SelectionType.Group) {
|
|
@@ -502,23 +488,6 @@ export class _CfgFeatureInternal {
|
|
|
502
488
|
}
|
|
503
489
|
return this._options;
|
|
504
490
|
}
|
|
505
|
-
get path() {
|
|
506
|
-
return [...this.parent.path, this.code];
|
|
507
|
-
}
|
|
508
|
-
getFromPath(path) {
|
|
509
|
-
path = path.slice();
|
|
510
|
-
const s = path.shift();
|
|
511
|
-
switch (s) {
|
|
512
|
-
case undefined:
|
|
513
|
-
return this;
|
|
514
|
-
default:
|
|
515
|
-
const option = this.options.find((o) => o.code === s);
|
|
516
|
-
if (option === undefined) {
|
|
517
|
-
throw new Error(`Option not found ${s}, ${path.join(", ")}`);
|
|
518
|
-
}
|
|
519
|
-
return option._internal.getFromPath(path);
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
491
|
/**
|
|
523
492
|
* Make fresh references to all options on this feature.
|
|
524
493
|
* Also includes currently selected options.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LengthUnit, Observable, SingleArgCallback } from "@configura/web-utilities";
|
|
2
2
|
import { Feature, Option, SelectedOption } from "../CatalogueAPI.js";
|
|
3
|
-
import {
|
|
3
|
+
import { CfgProduct, _CfgProductInternal } from "../CfgProduct.js";
|
|
4
4
|
import { CfgMtrlApplication } from "../material/CfgMtrlApplication.js";
|
|
5
5
|
import { NumericValuesSelection } from "../utilitiesNumericValues.js";
|
|
6
6
|
import { CfgFeature, _CfgFeatureInternal } from "./CfgFeature.js";
|
|
@@ -14,19 +14,19 @@ export declare enum ProductConfigurationBubbleMode {
|
|
|
14
14
|
*/
|
|
15
15
|
BubbleSelected = "BubbleSelected",
|
|
16
16
|
/**
|
|
17
|
-
* Bubble to the closest CfgProduct, let it revalidate, then that will continue
|
|
18
|
-
*
|
|
17
|
+
* Bubble to the closest CfgProduct, let it revalidate, then that will continue the bubble
|
|
18
|
+
* after validate.
|
|
19
19
|
*/
|
|
20
20
|
Validate = "Validate",
|
|
21
21
|
/**
|
|
22
|
-
* Bubble to the closest CfgProduct, let it revalidate, then that will continue
|
|
23
|
-
*
|
|
22
|
+
* Bubble to the closest CfgProduct, let it revalidate, then that will continue the bubble
|
|
23
|
+
* after validate. If this is select it will turn on all ancestors all the way up.
|
|
24
24
|
* So with this mode it is possible to select an option where its parents are not selected.
|
|
25
25
|
*/
|
|
26
26
|
ValidateAndBubbleSelected = "ValidateAndBubbleSelected",
|
|
27
27
|
/**
|
|
28
|
-
* Like ValidateAndBubbleSelected, but SyncGroups are applied after
|
|
29
|
-
*
|
|
28
|
+
* Like ValidateAndBubbleSelected, but SyncGroups are applied after ValidateAndBubbleSelected
|
|
29
|
+
* has been done
|
|
30
30
|
*/
|
|
31
31
|
ValidateAndBubbleSelectedAndApplySyncGroups = "ValidateAndBubbleSelectedAndApplySyncGroups",
|
|
32
32
|
/**
|
|
@@ -53,10 +53,9 @@ export declare enum ProductConfigurationBubbleMode {
|
|
|
53
53
|
ToRoot = "ToRoot"
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
56
|
-
* This class is meant to
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* should be used and interacted with.
|
|
56
|
+
* This class is only meant to be used through CfgOption. It should never be instantiated on its
|
|
57
|
+
* own. Normally the internal state of this class should never be directly modified. CfgOption is
|
|
58
|
+
* the class that should be used and interacted with.
|
|
60
59
|
*/
|
|
61
60
|
export declare class _CfgOptionInternal {
|
|
62
61
|
readonly rawOption: Option;
|
|
@@ -80,6 +79,7 @@ export declare class _CfgOptionInternal {
|
|
|
80
79
|
get unit(): LengthUnit;
|
|
81
80
|
get description(): string;
|
|
82
81
|
get selected(): boolean;
|
|
82
|
+
get selectedChangeInProgress(): boolean;
|
|
83
83
|
get ancestorsSelected(): boolean;
|
|
84
84
|
get mtrlApplications(): CfgMtrlApplication[];
|
|
85
85
|
get thumbnail(): string | undefined;
|
|
@@ -90,8 +90,6 @@ export declare class _CfgOptionInternal {
|
|
|
90
90
|
_childHasChanged: (freshRef: CfgFeature, bubbleMode: ProductConfigurationBubbleMode) => Promise<void>;
|
|
91
91
|
getApiSelection: () => SelectedOption;
|
|
92
92
|
setApiSelection: (apiOptionSelection: SelectedOption | undefined) => Promise<boolean>;
|
|
93
|
-
get path(): CfgPath;
|
|
94
|
-
getFromPath(path: CfgPath): _CfgFeatureInternal | _CfgOptionInternal;
|
|
95
93
|
structureCompare: (other: _CfgOptionInternal, strictOrder?: boolean, descriptionMatch?: boolean) => boolean;
|
|
96
94
|
tryMatchSelection: (other: CfgOption, descriptionMatch?: boolean) => Promise<boolean>;
|
|
97
95
|
keyMatch: (other: _CfgOptionInternal, descriptionMatch?: boolean) => boolean;
|
|
@@ -127,8 +125,21 @@ export declare class CfgOption {
|
|
|
127
125
|
get unit(): LengthUnit;
|
|
128
126
|
get description(): string;
|
|
129
127
|
get selected(): boolean;
|
|
128
|
+
/**
|
|
129
|
+
* Selection state is in progress to be changed. This can be used in GUI
|
|
130
|
+
* to display the state as transitioning, or as already changed.
|
|
131
|
+
* If selectedChangeInProgress and:
|
|
132
|
+
* selected is true, it means that this is about to get unselected
|
|
133
|
+
* selected is false, it means that this is about to get selected
|
|
134
|
+
*/
|
|
135
|
+
get selectedChangeInProgress(): boolean;
|
|
130
136
|
/** Are all ancestors up to the CfgProductConfiguration selected? Includes self. */
|
|
131
137
|
get ancestorsSelected(): boolean;
|
|
138
|
+
/**
|
|
139
|
+
* Selects this Option.
|
|
140
|
+
* Only Options belonging to Features that are "select many" can be deselected.
|
|
141
|
+
* Calling this will cause a validation call to the server.
|
|
142
|
+
*/
|
|
132
143
|
setSelected: (on: boolean) => Promise<boolean>;
|
|
133
144
|
get thumbnail(): string | undefined;
|
|
134
145
|
get upcharge(): number | undefined;
|