@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
|
@@ -22,19 +22,19 @@ export var ProductConfigurationBubbleMode;
|
|
|
22
22
|
*/
|
|
23
23
|
ProductConfigurationBubbleMode["BubbleSelected"] = "BubbleSelected";
|
|
24
24
|
/**
|
|
25
|
-
* Bubble to the closest CfgProduct, let it revalidate, then that will continue
|
|
26
|
-
*
|
|
25
|
+
* Bubble to the closest CfgProduct, let it revalidate, then that will continue the bubble
|
|
26
|
+
* after validate.
|
|
27
27
|
*/
|
|
28
28
|
ProductConfigurationBubbleMode["Validate"] = "Validate";
|
|
29
29
|
/**
|
|
30
|
-
* Bubble to the closest CfgProduct, let it revalidate, then that will continue
|
|
31
|
-
*
|
|
30
|
+
* Bubble to the closest CfgProduct, let it revalidate, then that will continue the bubble
|
|
31
|
+
* after validate. If this is select it will turn on all ancestors all the way up.
|
|
32
32
|
* So with this mode it is possible to select an option where its parents are not selected.
|
|
33
33
|
*/
|
|
34
34
|
ProductConfigurationBubbleMode["ValidateAndBubbleSelected"] = "ValidateAndBubbleSelected";
|
|
35
35
|
/**
|
|
36
|
-
* Like ValidateAndBubbleSelected, but SyncGroups are applied after
|
|
37
|
-
*
|
|
36
|
+
* Like ValidateAndBubbleSelected, but SyncGroups are applied after ValidateAndBubbleSelected
|
|
37
|
+
* has been done
|
|
38
38
|
*/
|
|
39
39
|
ProductConfigurationBubbleMode["ValidateAndBubbleSelectedAndApplySyncGroups"] = "ValidateAndBubbleSelectedAndApplySyncGroups";
|
|
40
40
|
/**
|
|
@@ -75,10 +75,9 @@ function doesChildrenShareOptionsCode(features) {
|
|
|
75
75
|
return false;
|
|
76
76
|
}
|
|
77
77
|
/**
|
|
78
|
-
* This class is meant to
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* should be used and interacted with.
|
|
78
|
+
* This class is only meant to be used through CfgOption. It should never be instantiated on its
|
|
79
|
+
* own. Normally the internal state of this class should never be directly modified. CfgOption is
|
|
80
|
+
* the class that should be used and interacted with.
|
|
82
81
|
*/
|
|
83
82
|
export class _CfgOptionInternal {
|
|
84
83
|
constructor(rawOption, allRawFeatures, siblingHasDuplicateDescription, parent, parentConfiguration, parentProduct, rootProduct) {
|
|
@@ -180,9 +179,8 @@ export class _CfgOptionInternal {
|
|
|
180
179
|
agg.push(...feature._internal._getFeaturesWithCode(code));
|
|
181
180
|
return agg;
|
|
182
181
|
}, []);
|
|
183
|
-
// Description based key helps when switching between
|
|
184
|
-
//
|
|
185
|
-
// to retain made selection
|
|
182
|
+
// Description based key helps when switching between products with similar feature-options
|
|
183
|
+
// tree and trying to retain made selection.
|
|
186
184
|
this.key =
|
|
187
185
|
this.description +
|
|
188
186
|
(this.description === "" || siblingHasDuplicateDescription ? this.code : "");
|
|
@@ -229,9 +227,9 @@ export class _CfgOptionInternal {
|
|
|
229
227
|
this._numericValue = val;
|
|
230
228
|
change = true;
|
|
231
229
|
}
|
|
232
|
-
// It could be that even though our value did not change some sibling value did, and
|
|
233
|
-
// could make it needed to bubble later. Maybe. A bit uncertain about why I did
|
|
234
|
-
// this in the if-statement above //Linus
|
|
230
|
+
// It could be that even though our value did not change some sibling value did, and
|
|
231
|
+
// this could make it needed to bubble later. Maybe. A bit uncertain about why I did
|
|
232
|
+
// not put this in the if-statement above //Linus
|
|
235
233
|
if (yield this.parent.pushStretch()) {
|
|
236
234
|
change = true;
|
|
237
235
|
}
|
|
@@ -258,6 +256,20 @@ export class _CfgOptionInternal {
|
|
|
258
256
|
get selected() {
|
|
259
257
|
return this.parent.isSelected(this);
|
|
260
258
|
}
|
|
259
|
+
get selectedChangeInProgress() {
|
|
260
|
+
const syncGroupHandler = this.rootProduct.syncGroupHandler;
|
|
261
|
+
if (syncGroupHandler === undefined) {
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
const inProgressOption = syncGroupHandler.pending;
|
|
265
|
+
if (inProgressOption === this) {
|
|
266
|
+
return true;
|
|
267
|
+
}
|
|
268
|
+
if (!(this.selected && this.parent.selectionType === SelectionType.SelectOne)) {
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
return this.parent.options.some((o) => o._internal === inProgressOption);
|
|
272
|
+
}
|
|
261
273
|
get ancestorsSelected() {
|
|
262
274
|
return this.selected && this.parent.ancestorsSelected;
|
|
263
275
|
}
|
|
@@ -310,23 +322,6 @@ export class _CfgOptionInternal {
|
|
|
310
322
|
}
|
|
311
323
|
return this._features;
|
|
312
324
|
}
|
|
313
|
-
get path() {
|
|
314
|
-
return [...this.parent.path, this.code];
|
|
315
|
-
}
|
|
316
|
-
getFromPath(path) {
|
|
317
|
-
path = path.slice();
|
|
318
|
-
const s = path.shift();
|
|
319
|
-
switch (s) {
|
|
320
|
-
case undefined:
|
|
321
|
-
return this;
|
|
322
|
-
default:
|
|
323
|
-
const feature = this.features.find((o) => o.code === s);
|
|
324
|
-
if (feature === undefined) {
|
|
325
|
-
throw new Error(`Feature not found ${s}, ${path.join(", ")}`);
|
|
326
|
-
}
|
|
327
|
-
return feature._internal.getFromPath(path);
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
325
|
_freshRefDescendants() {
|
|
331
326
|
const features = this._features || [];
|
|
332
327
|
for (let i = 0; i < features.length; i++) {
|
|
@@ -347,7 +342,7 @@ export class CfgOption {
|
|
|
347
342
|
this.isBackedBySame = (other) => this._internal === other._internal;
|
|
348
343
|
this.setNumericValue = (val, doSelectOption) => __awaiter(this, void 0, void 0, function* () { return yield this._internal.setNumericValue(val, doSelectOption); });
|
|
349
344
|
this.isAllowedNumericValue = (val) => this._internal.isAllowedNumericValue(val);
|
|
350
|
-
|
|
345
|
+
/**
|
|
351
346
|
* Selects this Option.
|
|
352
347
|
* Only Options belonging to Features that are "select many" can be deselected.
|
|
353
348
|
* Calling this will cause a validation call to the server.
|
|
@@ -402,6 +397,16 @@ export class CfgOption {
|
|
|
402
397
|
get selected() {
|
|
403
398
|
return this._internal.selected;
|
|
404
399
|
}
|
|
400
|
+
/**
|
|
401
|
+
* Selection state is in progress to be changed. This can be used in GUI
|
|
402
|
+
* to display the state as transitioning, or as already changed.
|
|
403
|
+
* If selectedChangeInProgress and:
|
|
404
|
+
* selected is true, it means that this is about to get unselected
|
|
405
|
+
* selected is false, it means that this is about to get selected
|
|
406
|
+
*/
|
|
407
|
+
get selectedChangeInProgress() {
|
|
408
|
+
return this._internal.selectedChangeInProgress;
|
|
409
|
+
}
|
|
405
410
|
/** Are all ancestors up to the CfgProductConfiguration selected? Includes self. */
|
|
406
411
|
get ancestorsSelected() {
|
|
407
412
|
return this._internal.ancestorsSelected;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { LengthUnit, Observable, SingleArgCallback } from "@configura/web-utilities";
|
|
2
2
|
import { Feature, FeatureRef, SelectedOption } from "../CatalogueAPI.js";
|
|
3
|
-
import {
|
|
3
|
+
import { CfgProduct, _CfgProductInternal } from "../CfgProduct.js";
|
|
4
4
|
import { CfgFeature, _CfgFeatureInternal } from "./CfgFeature.js";
|
|
5
|
-
import { ProductConfigurationBubbleMode
|
|
5
|
+
import { ProductConfigurationBubbleMode } from "./CfgOption.js";
|
|
6
6
|
export declare type ProductConfigurationChangeNotification = {
|
|
7
7
|
freshRef: CfgProductConfiguration;
|
|
8
8
|
};
|
|
@@ -43,8 +43,6 @@ export declare class _CfgProductConfigurationInternal {
|
|
|
43
43
|
* outside we want notifications to bubble all the way to the root.
|
|
44
44
|
*/
|
|
45
45
|
setApiSelection: (selectedOptions: SelectedOption[], bubbleToRoot: boolean) => Promise<boolean>;
|
|
46
|
-
get path(): CfgPath;
|
|
47
|
-
getFromPath(path: CfgPath): _CfgProductConfigurationInternal | _CfgFeatureInternal | _CfgOptionInternal;
|
|
48
46
|
structureCompare: (other: _CfgProductConfigurationInternal, strictOrder?: boolean, descriptionMatch?: boolean) => boolean;
|
|
49
47
|
/**
|
|
50
48
|
* When used internally the notifications are taken care off by the caller, but if set from
|
|
@@ -215,23 +215,6 @@ export class _CfgProductConfigurationInternal {
|
|
|
215
215
|
features[i] = CfgFeature._makeNewRefFrom(featureInternal);
|
|
216
216
|
}
|
|
217
217
|
}
|
|
218
|
-
get path() {
|
|
219
|
-
return [...this.parentProduct.path, "c"];
|
|
220
|
-
}
|
|
221
|
-
getFromPath(path) {
|
|
222
|
-
path = path.slice();
|
|
223
|
-
const s = path.shift();
|
|
224
|
-
switch (s) {
|
|
225
|
-
case undefined:
|
|
226
|
-
return this;
|
|
227
|
-
default:
|
|
228
|
-
const feature = this.features.find((f) => f.code === s);
|
|
229
|
-
if (feature === undefined) {
|
|
230
|
-
throw new Error(`Feature not found ${s}, ${path.join(", ")}`);
|
|
231
|
-
}
|
|
232
|
-
return feature._internal.getFromPath(path);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
218
|
}
|
|
236
219
|
export class CfgProductConfiguration {
|
|
237
220
|
/**
|
|
@@ -12,5 +12,5 @@ export declare function applyProductRefFilters(filters: Filters<ProductRefParams
|
|
|
12
12
|
* @param prdRefsFilter Products not in this array are removed
|
|
13
13
|
* @param showEmpty Shall empty levels be shown?
|
|
14
14
|
*/
|
|
15
|
-
export declare function cloneFilterSortLevels(levels: Level[], prdRefsFilter: ProductRef[], showEmpty: boolean): Level[] | undefined;
|
|
15
|
+
export declare function cloneFilterSortLevels(levels: Level[], prdRefsFilter: ProductRef[], showEmpty: boolean, doSort?: boolean): Level[] | undefined;
|
|
16
16
|
//# sourceMappingURL=filters.d.ts.map
|
|
@@ -34,13 +34,13 @@ export function applyProductRefFilters(filters, productRefs) {
|
|
|
34
34
|
* @param prdRefsFilter Products not in this array are removed
|
|
35
35
|
* @param showEmpty Shall empty levels be shown?
|
|
36
36
|
*/
|
|
37
|
-
export function cloneFilterSortLevels(levels, prdRefsFilter, showEmpty) {
|
|
37
|
+
export function cloneFilterSortLevels(levels, prdRefsFilter, showEmpty, doSort = true) {
|
|
38
38
|
const newLevels = [];
|
|
39
39
|
for (const level of levels) {
|
|
40
40
|
// recursively fetch the next levels
|
|
41
41
|
let nextLevels;
|
|
42
42
|
if (level.lvls !== undefined) {
|
|
43
|
-
nextLevels = cloneFilterSortLevels(level.lvls, prdRefsFilter, showEmpty);
|
|
43
|
+
nextLevels = cloneFilterSortLevels(level.lvls, prdRefsFilter, showEmpty, doSort);
|
|
44
44
|
}
|
|
45
45
|
// filter out products
|
|
46
46
|
let newPrdRefs;
|
|
@@ -63,5 +63,8 @@ export function cloneFilterSortLevels(levels, prdRefsFilter, showEmpty) {
|
|
|
63
63
|
newLevels.push(newLevel);
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
|
-
|
|
66
|
+
if (doSort) {
|
|
67
|
+
return newLevels.sort((l1, l2) => l1.description.toLocaleLowerCase().localeCompare(l2.description.toLocaleLowerCase()));
|
|
68
|
+
}
|
|
69
|
+
return newLevels;
|
|
67
70
|
}
|
|
@@ -88,7 +88,7 @@ class SyncStateOnto {
|
|
|
88
88
|
// All settled, continue to pullPhase
|
|
89
89
|
return yield OntoSyncState.rootProduct(transaction);
|
|
90
90
|
}
|
|
91
|
-
if (transaction.
|
|
91
|
+
if (transaction.isClosed) {
|
|
92
92
|
// We could exit in more places when the transaction has been aborted,
|
|
93
93
|
// but as revalidate is really the only thing that could be expensive /
|
|
94
94
|
// time consuming we only check here.
|
|
@@ -106,7 +106,7 @@ class SyncStateOnto {
|
|
|
106
106
|
// could accumulate and what is cause and effect be hard to know.
|
|
107
107
|
if (!revalidationResults.every((r) => r.requestDidValidate) ||
|
|
108
108
|
revalidationResults.every((r) => r.wasAborted)) {
|
|
109
|
-
transaction.
|
|
109
|
+
transaction.close();
|
|
110
110
|
return false;
|
|
111
111
|
}
|
|
112
112
|
// Apply over again, to settle deeper down. Our theory is that the front of
|
|
@@ -412,17 +412,18 @@ class OntoSyncState {
|
|
|
412
412
|
if (optionCode === currentSyncGroupOptionCode) {
|
|
413
413
|
return false;
|
|
414
414
|
}
|
|
415
|
-
// featureDidJustComeIntoScope, in CET there is a feature that if a feature appears which
|
|
416
|
-
// to the current sync group value, then it will set in the opposite
|
|
417
|
-
// empty. To avoid bouncing back and forth we will
|
|
418
|
-
// once per transaction
|
|
415
|
+
// featureDidJustComeIntoScope, in CET there is a feature that if a feature appears which
|
|
416
|
+
// can not be set to the current sync group value, then it will set in the opposite
|
|
417
|
+
// direction. Like if the sync group was empty. To avoid bouncing back and forth we will
|
|
418
|
+
// need to enforce that a sync group can only be updated once per transaction
|
|
419
419
|
if (!(activeSelectionForce ||
|
|
420
420
|
currentSyncGroupOptionCode === undefined ||
|
|
421
421
|
(featureDidJustComeIntoScope &&
|
|
422
422
|
feature.options.every((o) => currentSyncGroupOptionCode !== o.code)))) {
|
|
423
423
|
return false;
|
|
424
424
|
}
|
|
425
|
-
|
|
425
|
+
// TODO: Remove
|
|
426
|
+
//syncState.logDebug();
|
|
426
427
|
transaction.addSyncGroupAffectedForSelectOne(syncCode);
|
|
427
428
|
syncState.setForSelectOne(syncCode, optionCode);
|
|
428
429
|
return true;
|
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The SyncGroupsApplyMode controls how many SyncGroups can be updated in the SyncState for one
|
|
3
|
-
* run of rootProductOntoSyncState
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
3
|
+
* run of rootProductOntoSyncState.
|
|
4
|
+
*
|
|
5
|
+
* "Fast" will update any SyncGroup that should be updated before running syncStateOntoRootProduct
|
|
6
|
+
* This way several SyncGroups can be applied in one go before sending the validation calls to the * server, making the whole process faster.
|
|
7
|
+
*
|
|
8
|
+
* The downside of this is that is not exactly how CET (the desktop software) works. CET will
|
|
9
|
+
* instead apply Features to the SyncState as soon as it gets the chance.
|
|
10
|
+
*
|
|
11
|
+
* "Strict" tries to behave exactly as CET. This will potentially generate a lot more validate
|
|
12
|
+
* calls, increasing delay and cost.
|
|
13
|
+
*
|
|
14
|
+
* Strict is the safer option of the two, but we still recommend trying out Fast since it should
|
|
15
|
+
* work fine in most cases.
|
|
10
16
|
*/
|
|
11
17
|
export declare enum SyncGroupsApplyMode {
|
|
12
|
-
|
|
13
|
-
|
|
18
|
+
Strict = "Strict",
|
|
19
|
+
Fast = "Fast"
|
|
14
20
|
}
|
|
15
21
|
//# sourceMappingURL=SyncGroupsApplyMode.d.ts.map
|
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The SyncGroupsApplyMode controls how many SyncGroups can be updated in the SyncState for one
|
|
3
|
-
* run of rootProductOntoSyncState
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
3
|
+
* run of rootProductOntoSyncState.
|
|
4
|
+
*
|
|
5
|
+
* "Fast" will update any SyncGroup that should be updated before running syncStateOntoRootProduct
|
|
6
|
+
* This way several SyncGroups can be applied in one go before sending the validation calls to the * server, making the whole process faster.
|
|
7
|
+
*
|
|
8
|
+
* The downside of this is that is not exactly how CET (the desktop software) works. CET will
|
|
9
|
+
* instead apply Features to the SyncState as soon as it gets the chance.
|
|
10
|
+
*
|
|
11
|
+
* "Strict" tries to behave exactly as CET. This will potentially generate a lot more validate
|
|
12
|
+
* calls, increasing delay and cost.
|
|
13
|
+
*
|
|
14
|
+
* Strict is the safer option of the two, but we still recommend trying out Fast since it should
|
|
15
|
+
* work fine in most cases.
|
|
10
16
|
*/
|
|
11
17
|
export var SyncGroupsApplyMode;
|
|
12
18
|
(function (SyncGroupsApplyMode) {
|
|
13
|
-
SyncGroupsApplyMode["Fast"] = "Fast";
|
|
14
19
|
SyncGroupsApplyMode["Strict"] = "Strict";
|
|
20
|
+
SyncGroupsApplyMode["Fast"] = "Fast";
|
|
15
21
|
})(SyncGroupsApplyMode || (SyncGroupsApplyMode = {}));
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AggregatedLoadingObservable } from "@configura/web-utilities";
|
|
2
|
+
import { _CfgProductInternal } from "../CfgProduct.js";
|
|
3
|
+
import { _CfgOptionInternal } from "../productConfiguration/CfgOption.js";
|
|
2
4
|
import { ProductLoader } from "../productLoader.js";
|
|
3
5
|
import { SyncGroupsApplyMode } from "./SyncGroupsApplyMode.js";
|
|
4
6
|
import { SyncGroupsTransaction } from "./SyncGroupsTransaction.js";
|
|
@@ -11,9 +13,13 @@ export declare type OptionCode = string;
|
|
|
11
13
|
export declare class SyncGroupsHandler {
|
|
12
14
|
private _syncState;
|
|
13
15
|
readonly updateMode: SyncGroupsApplyMode;
|
|
16
|
+
private readonly _loadingObservable;
|
|
14
17
|
private _currentTransaction;
|
|
15
|
-
static make(updateMode?: SyncGroupsApplyMode): SyncGroupsHandler;
|
|
18
|
+
static make(updateMode?: SyncGroupsApplyMode, loadingObservable?: AggregatedLoadingObservable): SyncGroupsHandler;
|
|
16
19
|
private constructor();
|
|
20
|
+
/**
|
|
21
|
+
* Please note that clones will use the same loadingObservable as their source
|
|
22
|
+
*/
|
|
17
23
|
clone(): SyncGroupsHandler;
|
|
18
24
|
/**
|
|
19
25
|
* Used to initially apply the sync state onto a new product so that it is "in sync"
|
|
@@ -23,8 +29,12 @@ export declare class SyncGroupsHandler {
|
|
|
23
29
|
* Used when an Option is selected or deselected to apply all consequences of the sync groups.
|
|
24
30
|
* Can cause multiple extra validation calls to the server.
|
|
25
31
|
*/
|
|
26
|
-
selectOption(product: _CfgProductInternal,
|
|
32
|
+
selectOption(product: _CfgProductInternal, option: _CfgOptionInternal, on: boolean, productLoader: ProductLoader): Promise<boolean>;
|
|
33
|
+
private _pending;
|
|
34
|
+
private setPending;
|
|
35
|
+
get pending(): _CfgOptionInternal | undefined;
|
|
27
36
|
newTransaction(product: _CfgProductInternal, productLoader: ProductLoader, assumeNoStartProductState: boolean): Promise<SyncGroupsTransaction>;
|
|
37
|
+
private closeTransaction;
|
|
28
38
|
applyTransaction(transaction: SyncGroupsTransaction): Promise<void>;
|
|
29
39
|
}
|
|
30
40
|
//# sourceMappingURL=SyncGroupsHandler.d.ts.map
|