@configura/web-api 3.0.0-alpha.1 → 3.0.0-alpha.2
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 +68 -1
- package/dist/CatalogueAPI.js +184 -219
- package/dist/CfgMeasure.js +1 -2
- package/dist/CfgProduct.js +131 -159
- package/dist/io/CfgIOManager.js +2 -11
- package/dist/io/CfgIOProdConfConnector.js +14 -25
- package/dist/io/CfgObservableStateManager.js +1 -1
- package/dist/productConfiguration/CfgFeature.d.ts +5 -0
- package/dist/productConfiguration/CfgFeature.js +62 -52
- package/dist/productConfiguration/CfgOption.d.ts +8 -0
- package/dist/productConfiguration/CfgOption.js +67 -72
- package/dist/productConfiguration/CfgProductConfiguration.js +22 -34
- package/dist/productConfiguration/productParamsGenerator.js +43 -57
- package/dist/productLoader.js +2 -13
- package/dist/syncGroups/SyncGroupsHandler.js +60 -83
- package/dist/syncGroups/SyncGroupsPathHelper.js +5 -5
- package/dist/syncGroups/SyncGroupsState.js +4 -5
- package/dist/syncGroups/SyncGroupsTransaction.js +259 -303
- package/dist/tasks/TaskHandler.js +53 -64
- package/dist/tests/testData/dummyProductForTest.js +4 -1
- package/dist/tests/testData/testDataAdditionalProductInAdditionalProductInProductForTest.js +18 -21
- package/dist/tests/testData/testDataCachedGetProduct.js +20 -20
- package/dist/tests/testData/testDataCachedPostValidate.js +6 -15
- package/dist/tests/testData/testDataProductAggregatedPrice.js +21 -21
- package/dist/tests/testData/testDataUpcharge.js +31 -22
- package/dist/utilitiesCatalogueData.js +21 -9
- package/dist/utilitiesCataloguePermission.js +5 -2
- package/dist/utilitiesConfiguration.js +21 -23
- package/package.json +3 -3
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
import { Observable, compareArrays, count, } from "@configura/web-utilities";
|
|
11
2
|
import { CfgProduct } from "../CfgProduct.js";
|
|
12
3
|
import { CfgMtrlApplication } from "../material/CfgMtrlApplication.js";
|
|
@@ -89,7 +80,7 @@ export class _CfgOptionInternal {
|
|
|
89
80
|
this.rootProduct = rootProduct;
|
|
90
81
|
this.changeObservable = new Observable();
|
|
91
82
|
/** Called by child to tell its parent that it has changed. */
|
|
92
|
-
this._childHasChanged = (freshRef, bubbleMode, committed) =>
|
|
83
|
+
this._childHasChanged = async (freshRef, bubbleMode, committed) => {
|
|
93
84
|
const features = this._features;
|
|
94
85
|
if (features === undefined) {
|
|
95
86
|
throw Error("Child says it changed, but no children has actually been generated");
|
|
@@ -104,12 +95,12 @@ export class _CfgOptionInternal {
|
|
|
104
95
|
if (bubbleMode === ProductConfigurationBubbleMode.ValidateAndBubbleSelected ||
|
|
105
96
|
bubbleMode === ProductConfigurationBubbleMode.BubbleSelected) {
|
|
106
97
|
// selectOption takes care of the bubble
|
|
107
|
-
|
|
98
|
+
await this.parent.selectOption(this, true, bubbleMode);
|
|
108
99
|
}
|
|
109
100
|
else {
|
|
110
|
-
|
|
101
|
+
await this.parent._childHasChanged(this, bubbleMode, committed);
|
|
111
102
|
}
|
|
112
|
-
}
|
|
103
|
+
};
|
|
113
104
|
this.getDtoConf = (includeExtendedData) => {
|
|
114
105
|
const { features, isUseNumericValue, code, selected, numericValue } = this;
|
|
115
106
|
if (!selected) {
|
|
@@ -138,7 +129,7 @@ export class _CfgOptionInternal {
|
|
|
138
129
|
// way around. For that reason the get-method above uses the new format, and the set-method
|
|
139
130
|
// below the old format. As these functions are meant to only be used internally this should't
|
|
140
131
|
// cause too much confusion.
|
|
141
|
-
this.setApiSelection = (apiOptionSelection, apiOptionConstraint) =>
|
|
132
|
+
this.setApiSelection = async (apiOptionSelection, apiOptionConstraint) => {
|
|
142
133
|
let change = false;
|
|
143
134
|
const upcharge = this._calculateUpcharge();
|
|
144
135
|
if (this._upcharge !== upcharge) {
|
|
@@ -152,16 +143,15 @@ export class _CfgOptionInternal {
|
|
|
152
143
|
else {
|
|
153
144
|
features = this.features; // This will generate all children
|
|
154
145
|
}
|
|
155
|
-
if ((
|
|
146
|
+
if ((await Promise.all(features.map((f) => f._internal.setApiSelection(apiOptionSelection ? apiOptionSelection.next : undefined, apiOptionConstraint?.next)))).some((b) => b)) {
|
|
156
147
|
change = true;
|
|
157
148
|
}
|
|
158
149
|
return change;
|
|
159
|
-
}
|
|
150
|
+
};
|
|
160
151
|
this.getApiConstrained = (constrOptions) => {
|
|
161
|
-
var _a;
|
|
162
152
|
const next = {};
|
|
163
153
|
// use _features to avoid populating when the option is not selected
|
|
164
|
-
for (const feature of
|
|
154
|
+
for (const feature of this._features ?? []) {
|
|
165
155
|
feature._internal.addForApiConstrained(next);
|
|
166
156
|
}
|
|
167
157
|
return {
|
|
@@ -173,24 +163,22 @@ export class _CfgOptionInternal {
|
|
|
173
163
|
};
|
|
174
164
|
this.structureCompare = (other, strictOrder = true, descriptionMatch = false) => this.keyMatch(other, descriptionMatch) &&
|
|
175
165
|
compareArrays(this.features, other.features, (l, r) => l._internal.structureCompare(r._internal, strictOrder, descriptionMatch), strictOrder);
|
|
176
|
-
this.tryMatchSelection = (other, descriptionMatch = false) =>
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
}))()))).some((b) => b);
|
|
193
|
-
});
|
|
166
|
+
this.tryMatchSelection = async (other, descriptionMatch = false) => (await Promise.all(other.features.map((otherF) => (async () => {
|
|
167
|
+
if (1 <
|
|
168
|
+
count(other.features, (item) => item._internal.keyMatch(otherF._internal, descriptionMatch))) {
|
|
169
|
+
console.warn("tryMatchSelection will ignore items with same key");
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
const toSetFeatures = this.features.filter((f) => f._internal.keyMatch(otherF._internal, descriptionMatch));
|
|
173
|
+
if (1 < toSetFeatures.length) {
|
|
174
|
+
console.warn("tryMatchSelection will ignore items with same key");
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
if (toSetFeatures.length === 0) {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
return await toSetFeatures[0]._internal.tryMatchSelection(otherF._internal, descriptionMatch);
|
|
181
|
+
})()))).some((b) => b);
|
|
194
182
|
this.keyMatch = (other, descriptionMatch = false) => descriptionMatch
|
|
195
183
|
? this.description.toLowerCase() === other.description.toLowerCase()
|
|
196
184
|
: this.code === other.code;
|
|
@@ -231,12 +219,10 @@ export class _CfgOptionInternal {
|
|
|
231
219
|
return this.rawOption.code;
|
|
232
220
|
}
|
|
233
221
|
get notes() {
|
|
234
|
-
|
|
235
|
-
return this.parentProduct.getNotes((_a = this.rawOption.noteRefs) !== null && _a !== void 0 ? _a : []);
|
|
222
|
+
return this.parentProduct.getNotes(this.rawOption.noteRefs ?? []);
|
|
236
223
|
}
|
|
237
224
|
get miscFiles() {
|
|
238
|
-
|
|
239
|
-
return (_a = this.rawOption.miscFiles) !== null && _a !== void 0 ? _a : [];
|
|
225
|
+
return this.rawOption.miscFiles ?? [];
|
|
240
226
|
}
|
|
241
227
|
get isUseNumericValue() {
|
|
242
228
|
return this.parent.isUseNumericValue;
|
|
@@ -244,36 +230,34 @@ export class _CfgOptionInternal {
|
|
|
244
230
|
get numericValue() {
|
|
245
231
|
return this._numericValue;
|
|
246
232
|
}
|
|
247
|
-
setNumericValue(val, doSelectOption) {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
233
|
+
async setNumericValue(val, doSelectOption) {
|
|
234
|
+
if (!this.isAllowedNumericValue(val)) {
|
|
235
|
+
throw new Error(`The value ${val} is not allowed. This could be because: 1. There are no allowed ranges defined 2. The Feature is numeric selection and the value does not fit in the allowed values 3. The Feature is not numeric selection and the value is not the first in the allowed ranges.`);
|
|
236
|
+
}
|
|
237
|
+
let change = false;
|
|
238
|
+
if (this.isUseNumericValue) {
|
|
239
|
+
if (this._numericValue !== val) {
|
|
240
|
+
this._numericValue = val;
|
|
241
|
+
change = true;
|
|
251
242
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
}
|
|
258
|
-
// It could be that even though our value did not change some sibling value did, and
|
|
259
|
-
// this could make it needed to bubble later. Maybe. A bit uncertain about why I did
|
|
260
|
-
// not put this in the if-statement above //Linus
|
|
261
|
-
if (yield this.parent.pushStretch()) {
|
|
262
|
-
change = true;
|
|
263
|
-
}
|
|
243
|
+
// It could be that even though our value did not change some sibling value did, and
|
|
244
|
+
// this could make it needed to bubble later. Maybe. A bit uncertain about why I did
|
|
245
|
+
// not put this in the if-statement above //Linus
|
|
246
|
+
if (await this.parent.pushStretch()) {
|
|
247
|
+
change = true;
|
|
264
248
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
249
|
+
}
|
|
250
|
+
if (doSelectOption) {
|
|
251
|
+
if (await this.parent.selectOption(this, true, ProductConfigurationBubbleMode.Validate)) {
|
|
252
|
+
change = true;
|
|
269
253
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
if (change) {
|
|
257
|
+
await this.parent._childHasChanged(this, ProductConfigurationBubbleMode.Stop, false);
|
|
274
258
|
}
|
|
275
|
-
|
|
276
|
-
|
|
259
|
+
}
|
|
260
|
+
return change;
|
|
277
261
|
}
|
|
278
262
|
get unit() {
|
|
279
263
|
return this.parent.unit;
|
|
@@ -287,6 +271,12 @@ export class _CfgOptionInternal {
|
|
|
287
271
|
get disabled() {
|
|
288
272
|
return this.parent.isDisabled(this);
|
|
289
273
|
}
|
|
274
|
+
/**
|
|
275
|
+
* An option is unresolvable when it is constrained from any possible value.
|
|
276
|
+
*/
|
|
277
|
+
get unresolvable() {
|
|
278
|
+
return this.parent.isUnresolvable(this);
|
|
279
|
+
}
|
|
290
280
|
get selectedChangeInProgress() {
|
|
291
281
|
const syncGroupHandler = this.rootProduct.syncGroupHandler;
|
|
292
282
|
if (syncGroupHandler === undefined) {
|
|
@@ -352,8 +342,7 @@ export class _CfgOptionInternal {
|
|
|
352
342
|
* children until the sync process is complete.
|
|
353
343
|
*/
|
|
354
344
|
getFeaturesOutsideSync() {
|
|
355
|
-
|
|
356
|
-
return (_a = this._features) !== null && _a !== void 0 ? _a : [];
|
|
345
|
+
return this._features ?? [];
|
|
357
346
|
}
|
|
358
347
|
/**
|
|
359
348
|
* Get the child features that are contained within this option.
|
|
@@ -387,16 +376,16 @@ export class CfgOption {
|
|
|
387
376
|
constructor(_internal) {
|
|
388
377
|
this._internal = _internal;
|
|
389
378
|
this.isBackedBySame = (other) => this._internal === other._internal;
|
|
390
|
-
this.setNumericValue = (val, doSelectOption) =>
|
|
379
|
+
this.setNumericValue = async (val, doSelectOption) => await this._internal.setNumericValue(val, doSelectOption);
|
|
391
380
|
this.isAllowedNumericValue = (val) => this._internal.isAllowedNumericValue(val);
|
|
392
381
|
/**
|
|
393
382
|
* Selects this Option.
|
|
394
383
|
* Only Options belonging to Features that are "select many" can be deselected.
|
|
395
384
|
* Calling this will cause a validation call to the server.
|
|
396
385
|
*/
|
|
397
|
-
this.setSelected = (on) =>
|
|
398
|
-
return
|
|
399
|
-
}
|
|
386
|
+
this.setSelected = async (on) => {
|
|
387
|
+
return await this._internal.parent.selectOption(this._internal, on, ProductConfigurationBubbleMode.ValidateAndBubbleSelectedAndApplySyncGroups);
|
|
388
|
+
};
|
|
400
389
|
this.listenForChange = (l) => this._internal.changeObservable.listen(l);
|
|
401
390
|
this.stopListenForChange = (l) => this._internal.changeObservable.stopListen(l);
|
|
402
391
|
}
|
|
@@ -456,6 +445,12 @@ export class CfgOption {
|
|
|
456
445
|
get disabled() {
|
|
457
446
|
return this._internal.disabled;
|
|
458
447
|
}
|
|
448
|
+
/**
|
|
449
|
+
* An option is unresolvable when it is constrained from any possible value.
|
|
450
|
+
*/
|
|
451
|
+
get unresolvable() {
|
|
452
|
+
return this._internal.unresolvable;
|
|
453
|
+
}
|
|
459
454
|
/**
|
|
460
455
|
* Selection state is in progress to be changed. This can be used in GUI
|
|
461
456
|
* to display the state as transitioning, or as already changed.
|
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
import { compareArrays, count, isEqualLength, isLengthUnit, Observable, toError, toLengthUnit, } from "@configura/web-utilities";
|
|
11
2
|
import { CfgProduct } from "../CfgProduct.js";
|
|
12
3
|
import { convertDtoFeatureConfsToSelOptions } from "../utilitiesConfiguration.js";
|
|
@@ -27,7 +18,7 @@ export class _CfgProductConfigurationInternal {
|
|
|
27
18
|
this.accumulatedRawFeatures = []; // Flat packed. May be extended in validate calls.
|
|
28
19
|
this._features = [];
|
|
29
20
|
this.changeObservable = new Observable();
|
|
30
|
-
this._notifyAllOfChange = (bubbleMode, committed) =>
|
|
21
|
+
this._notifyAllOfChange = async (bubbleMode, committed) => {
|
|
31
22
|
if (bubbleMode === ProductConfigurationBubbleMode.Stop) {
|
|
32
23
|
return;
|
|
33
24
|
}
|
|
@@ -40,20 +31,20 @@ export class _CfgProductConfigurationInternal {
|
|
|
40
31
|
if (parent === undefined) {
|
|
41
32
|
return;
|
|
42
33
|
}
|
|
43
|
-
|
|
34
|
+
await parent._configurationHasChanged(freshRef, bubbleMode === ProductConfigurationBubbleMode.OneLevel
|
|
44
35
|
? ProductConfigurationBubbleMode.Stop
|
|
45
36
|
: bubbleMode, committed);
|
|
46
|
-
}
|
|
37
|
+
};
|
|
47
38
|
/** Called by child to tell its parent that it has changed. */
|
|
48
|
-
this._childHasChanged = (freshRef, bubbleMode, committed) =>
|
|
39
|
+
this._childHasChanged = async (freshRef, bubbleMode, committed) => {
|
|
49
40
|
const features = this._features;
|
|
50
41
|
const i = features.findIndex((a) => a.isBackedBySame(freshRef));
|
|
51
42
|
if (i === -1) {
|
|
52
43
|
throw Error("Child feature not found");
|
|
53
44
|
}
|
|
54
45
|
features[i] = freshRef;
|
|
55
|
-
|
|
56
|
-
}
|
|
46
|
+
await this._notifyAllOfChange(bubbleMode, committed);
|
|
47
|
+
};
|
|
57
48
|
this.getDtoConf = (includeExtendedData) => this._features.map((f) => f._internal.getDtoConf(includeExtendedData));
|
|
58
49
|
this.getApiSelection = () => convertDtoFeatureConfsToSelOptions(this.getDtoConf(false), true);
|
|
59
50
|
this.getApiConstrained = () => this._features.map((f) => {
|
|
@@ -70,7 +61,7 @@ export class _CfgProductConfigurationInternal {
|
|
|
70
61
|
* outside we want notifications to bubble all the way to the root.
|
|
71
62
|
* This method will not cause validation calls. Data is assumed to already be validated.
|
|
72
63
|
*/
|
|
73
|
-
this.setApiSelection = (selectedOptions, constrOptions, bubbleToRoot) =>
|
|
64
|
+
this.setApiSelection = async (selectedOptions, constrOptions, bubbleToRoot) => {
|
|
74
65
|
const featuresLength = this._features.length;
|
|
75
66
|
const selectedOptionsLength = selectedOptions.length;
|
|
76
67
|
if (featuresLength !== selectedOptionsLength) {
|
|
@@ -79,27 +70,24 @@ export class _CfgProductConfigurationInternal {
|
|
|
79
70
|
if (constrOptions && featuresLength !== constrOptions.length) {
|
|
80
71
|
throw new Error(`Wrong constraint feature count. Features on this configuration: ${featuresLength}. Passed constraint feature count: ${constrOptions.length}.`);
|
|
81
72
|
}
|
|
82
|
-
const change = (
|
|
83
|
-
var _a;
|
|
84
|
-
return f._internal.setApiSelection(selectedOptions[i].next, (_a = (constrOptions !== null && constrOptions !== void 0 ? constrOptions : [])[i]) === null || _a === void 0 ? void 0 : _a.next);
|
|
85
|
-
}))).some((b) => b);
|
|
73
|
+
const change = (await Promise.all(this._features.map((f, i) => f._internal.setApiSelection(selectedOptions[i].next, (constrOptions ?? [])[i]?.next)))).some((b) => b);
|
|
86
74
|
if (change) {
|
|
87
|
-
|
|
75
|
+
await this._notifyAllOfChange(bubbleToRoot
|
|
88
76
|
? ProductConfigurationBubbleMode.ToRoot
|
|
89
77
|
: ProductConfigurationBubbleMode.OneLevel, true);
|
|
90
78
|
}
|
|
91
79
|
return change;
|
|
92
|
-
}
|
|
80
|
+
};
|
|
93
81
|
this.structureCompare = (other, strictOrder, descriptionMatch) => compareArrays(this.features, other.features, (l, r) => l._internal.structureCompare(r._internal, strictOrder, descriptionMatch), strictOrder);
|
|
94
82
|
/**
|
|
95
83
|
* When used internally the notifications are taken care off by the caller, but if set from
|
|
96
84
|
* outside we want notifications to bubble all the way to the root.
|
|
97
85
|
*/
|
|
98
|
-
this.tryMatchSelection = (other, descriptionMatch = false, // Match on case insensitive description, not code
|
|
99
|
-
validate) =>
|
|
86
|
+
this.tryMatchSelection = async (other, descriptionMatch = false, // Match on case insensitive description, not code
|
|
87
|
+
validate) => {
|
|
100
88
|
const thisFeatures = this.features;
|
|
101
89
|
const otherFeatures = other.features;
|
|
102
|
-
const change = (
|
|
90
|
+
const change = (await Promise.all(otherFeatures.map((otherF) => (async () => {
|
|
103
91
|
if (1 <
|
|
104
92
|
count(otherFeatures, (item) => item._internal.keyMatch(otherF._internal, descriptionMatch))) {
|
|
105
93
|
console.warn("tryMatchSelection will ignore items with same key");
|
|
@@ -113,15 +101,15 @@ export class _CfgProductConfigurationInternal {
|
|
|
113
101
|
if (toSetFeatures.length === 0) {
|
|
114
102
|
return false;
|
|
115
103
|
}
|
|
116
|
-
return
|
|
117
|
-
})
|
|
104
|
+
return await toSetFeatures[0]._internal.tryMatchSelection(otherF._internal, descriptionMatch);
|
|
105
|
+
})()))).some((b) => b);
|
|
118
106
|
if (change) {
|
|
119
|
-
|
|
107
|
+
await this._notifyAllOfChange(validate
|
|
120
108
|
? ProductConfigurationBubbleMode.Validate
|
|
121
109
|
: ProductConfigurationBubbleMode.OneLevel, true);
|
|
122
110
|
}
|
|
123
111
|
return change;
|
|
124
|
-
}
|
|
112
|
+
};
|
|
125
113
|
/** Only selected features. */
|
|
126
114
|
this._getFeaturesWithCode = (code) => this._features.reduce((agg, feature) => {
|
|
127
115
|
agg.push(...feature._internal._getFeaturesWithCode(code));
|
|
@@ -161,7 +149,7 @@ export class _CfgProductConfigurationInternal {
|
|
|
161
149
|
this._features = syncCfgFeatures(rootFeatureRefs, this._features, this.accumulatedRawFeatures, this, this, this.parentProduct, this.rootProduct);
|
|
162
150
|
return true;
|
|
163
151
|
};
|
|
164
|
-
this.setStretchReferenceLength = (measureParamCode, referenceLength, unit) =>
|
|
152
|
+
this.setStretchReferenceLength = async (measureParamCode, referenceLength, unit) => {
|
|
165
153
|
if (measureParamCode === "") {
|
|
166
154
|
return false;
|
|
167
155
|
}
|
|
@@ -192,9 +180,9 @@ export class _CfgProductConfigurationInternal {
|
|
|
192
180
|
}
|
|
193
181
|
stretchReferenceLength.current = referenceLengthWithUnit;
|
|
194
182
|
}
|
|
195
|
-
|
|
183
|
+
await this._notifyAllOfChange(ProductConfigurationBubbleMode.ToRoot, false);
|
|
196
184
|
return true;
|
|
197
|
-
}
|
|
185
|
+
};
|
|
198
186
|
/* eslint-disable */
|
|
199
187
|
// Useful debug tool:
|
|
200
188
|
if (false) {
|
|
@@ -278,8 +266,8 @@ export class CfgProductConfiguration {
|
|
|
278
266
|
* This method does not propagate its selections.
|
|
279
267
|
* This method will cause validation calls.
|
|
280
268
|
*/
|
|
281
|
-
this.tryMatchSelection = (other, descriptionMatch = false // Match on case insensitive description, not code
|
|
282
|
-
) =>
|
|
269
|
+
this.tryMatchSelection = async (other, descriptionMatch = false // Match on case insensitive description, not code
|
|
270
|
+
) => await this._internal.tryMatchSelection(other._internal, descriptionMatch, true);
|
|
283
271
|
/**
|
|
284
272
|
* Set how stretched a certain measure should be measureParamCode is the measure to be
|
|
285
273
|
* stretched referenceLength is a value relative to the initial length of the measure. If the
|
|
@@ -1,65 +1,51 @@
|
|
|
1
|
-
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
|
|
2
|
-
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
|
|
3
|
-
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
4
|
-
var g = generator.apply(thisArg, _arguments || []), i, q = [];
|
|
5
|
-
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
|
|
6
|
-
function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
|
|
7
|
-
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
|
|
8
|
-
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
|
|
9
|
-
function fulfill(value) { resume("next", value); }
|
|
10
|
-
function reject(value) { resume("throw", value); }
|
|
11
|
-
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
|
|
12
|
-
};
|
|
13
1
|
import { toError } from "@configura/web-utilities";
|
|
14
2
|
import { CfgProduct } from "../CfgProduct.js";
|
|
15
3
|
import { applyProductRefFilters } from "./filters.js";
|
|
16
|
-
export function generateProductConfigurations(api, lang, catalogues, filters, settings) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
err.message = err.message.slice(0, split);
|
|
55
|
-
}
|
|
56
|
-
yield yield __await(toError(e));
|
|
4
|
+
export async function* generateProductConfigurations(api, lang, catalogues, filters, settings) {
|
|
5
|
+
const catalogueCount = catalogues.length;
|
|
6
|
+
const catalogueEntries = catalogues.entries();
|
|
7
|
+
for (const [catalogueIndex, catalogueParamsWithoutLang] of catalogueEntries) {
|
|
8
|
+
const catalogueParams = { ...catalogueParamsWithoutLang, lang };
|
|
9
|
+
try {
|
|
10
|
+
const [applicationAreasResponse, toc] = await Promise.all([
|
|
11
|
+
api.getApplicationAreas(catalogueParams),
|
|
12
|
+
api.getTocFlat(catalogueParams),
|
|
13
|
+
]);
|
|
14
|
+
const [, productRefs] = applyProductRefFilters(filters, toc?.prdRefs || []);
|
|
15
|
+
const productCount = productRefs.length;
|
|
16
|
+
const productEntries = productRefs.entries();
|
|
17
|
+
for (const [productIndex, prdRef] of productEntries) {
|
|
18
|
+
const startTime = performance.now();
|
|
19
|
+
try {
|
|
20
|
+
const product = await CfgProduct.make(api, { ...catalogueParams, partNumber: prdRef.partNr }, settings);
|
|
21
|
+
const getProductDuration = performance.now() - startTime;
|
|
22
|
+
yield {
|
|
23
|
+
applicationAreasResponse,
|
|
24
|
+
catalogueCount,
|
|
25
|
+
catalogueIndex,
|
|
26
|
+
catalogueParams,
|
|
27
|
+
getProductDuration,
|
|
28
|
+
product,
|
|
29
|
+
productCount,
|
|
30
|
+
productIndex,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
const err = e;
|
|
35
|
+
// Product load error, for example missing CmSym files.
|
|
36
|
+
// Safe to continue loading the next product.
|
|
37
|
+
const split = err.message.indexOf(", request ID: ");
|
|
38
|
+
if (split > -1) {
|
|
39
|
+
// The request ID part of the error from the server is mostly just spam and
|
|
40
|
+
// makes it harder to read list of errors, so remove it.
|
|
41
|
+
err.message = err.message.slice(0, split);
|
|
57
42
|
}
|
|
43
|
+
yield toError(e);
|
|
58
44
|
}
|
|
59
45
|
}
|
|
60
|
-
catch (e) {
|
|
61
|
-
yield yield __await(toError(e));
|
|
62
|
-
}
|
|
63
46
|
}
|
|
64
|
-
|
|
47
|
+
catch (e) {
|
|
48
|
+
yield toError(e);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
65
51
|
}
|
package/dist/productLoader.js
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
import { PromiseCache } from "@configura/web-utilities";
|
|
11
2
|
import { makeProductKey, makeSelOptionsKey, } from "./utilitiesCatalogueData.js";
|
|
12
3
|
/**
|
|
@@ -21,7 +12,7 @@ import { makeProductKey, makeSelOptionsKey, } from "./utilitiesCatalogueData.js"
|
|
|
21
12
|
*/
|
|
22
13
|
export function wrapWithGetProductCache(getProduct) {
|
|
23
14
|
const cache = new PromiseCache();
|
|
24
|
-
return (params) =>
|
|
15
|
+
return async (params) => cache.get(makeProductKey(params), () => getProduct(params));
|
|
25
16
|
}
|
|
26
17
|
/**
|
|
27
18
|
* Wraps a postValidate function so that it caches for the time it lives.
|
|
@@ -36,9 +27,7 @@ export function wrapWithGetProductCache(getProduct) {
|
|
|
36
27
|
*/
|
|
37
28
|
export function wrapWithPostValidateCache(postValidate) {
|
|
38
29
|
const cache = new PromiseCache();
|
|
39
|
-
return (params, body) =>
|
|
40
|
-
return cache.get(`${makeProductKey(params)}-${makeSelOptionsKey(body.selOptions)}-${body.knownFeatureCodes.join(",")}`, () => postValidate(params, body));
|
|
41
|
-
});
|
|
30
|
+
return async (params, body) => cache.get(`${makeProductKey(params)}-${makeSelOptionsKey(body.selOptions)}-${body.knownFeatureCodes.join(",")}`, () => postValidate(params, body));
|
|
42
31
|
}
|
|
43
32
|
/** Does both wrapWithGetProductCache and wrapWithPostValidateCache. */
|
|
44
33
|
export function wrapWithCache(loader) {
|