@configura/web-api 1.6.1-alpha.0 → 1.6.1-alpha.1
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 +13 -13
- package/dist/CfgProduct.js +9 -70
- package/dist/productConfiguration/CfgFeature.d.ts +1 -3
- package/dist/productConfiguration/CfgFeature.js +4 -22
- package/dist/productConfiguration/CfgOption.d.ts +15 -13
- package/dist/productConfiguration/CfgOption.js +15 -34
- package/dist/productConfiguration/CfgProductConfiguration.d.ts +2 -4
- package/dist/productConfiguration/CfgProductConfiguration.js +0 -17
- package/dist/syncGroups/SyncGroupsApplier.js +6 -5
- package/dist/syncGroups/SyncGroupsApplyMode.d.ts +15 -9
- package/dist/syncGroups/SyncGroupsApplyMode.js +14 -8
- package/dist/syncGroups/SyncGroupsHandler.d.ts +2 -1
- package/dist/syncGroups/SyncGroupsHandler.js +1 -1
- package/dist/syncGroups/SyncGroupsPathHelper.d.ts +27 -0
- package/dist/syncGroups/SyncGroupsPathHelper.js +89 -0
- package/dist/syncGroups/SyncGroupsState.d.ts +1 -1
- package/dist/syncGroups/SyncGroupsState.js +53 -6
- package/dist/syncGroups/SyncGroupsTransaction.d.ts +2 -1
- package/dist/syncGroups/SyncGroupsTransaction.js +7 -13
- package/package.json +3 -3
package/dist/CfgProduct.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ import { AggregatedLoadingObservable, LengthUnit, Observable, SingleArgCallback
|
|
|
2
2
|
import { AdditionalProductConfiguration, 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";
|
|
@@ -27,9 +27,17 @@ export declare type CfgProductSettings = {
|
|
|
27
27
|
*/
|
|
28
28
|
strictSetApiSelectionMatch: boolean;
|
|
29
29
|
/**
|
|
30
|
-
* Controls if SyncGroups are applied
|
|
31
|
-
*
|
|
32
|
-
*
|
|
30
|
+
* Controls if SyncGroups are applied Faster or Stricter.
|
|
31
|
+
*
|
|
32
|
+
* Fast - Tries to minimize the number of validates calls to the AI lowering the response times
|
|
33
|
+
* for selecting options. Might not always give the expected result for complex products.
|
|
34
|
+
*
|
|
35
|
+
* Strict - Apply the SyncGroups rules in a stricter fashion to be as close to CET as possible,
|
|
36
|
+
* which might result in longer response times and more validation calls to the API when
|
|
37
|
+
* selecting options.
|
|
38
|
+
*
|
|
39
|
+
* The SDK will default to Strict, but we recommend that you try out Fast since cases where the
|
|
40
|
+
* results differ should be rare in most real uses cases and the speedup can be quite large.
|
|
33
41
|
*/
|
|
34
42
|
syncGroupsApplyMode: SyncGroupsApplyMode | undefined;
|
|
35
43
|
};
|
|
@@ -56,8 +64,6 @@ export declare type CfgPrice = {
|
|
|
56
64
|
currency: string;
|
|
57
65
|
fractionDigits: number;
|
|
58
66
|
};
|
|
59
|
-
export declare type CfgPathSegment = string;
|
|
60
|
-
export declare type CfgPath = CfgPathSegment[];
|
|
61
67
|
export declare type RevalidateResult = {
|
|
62
68
|
wasAborted: boolean;
|
|
63
69
|
requestDidValidate: boolean;
|
|
@@ -139,12 +145,6 @@ export declare class _CfgProductInternal {
|
|
|
139
145
|
copyFrom: (otherProduct: _CfgProductInternal, doValidate: boolean, productLoaderForGroupedLoad?: ProductLoader | undefined) => Promise<boolean>;
|
|
140
146
|
private _setApiSelectionWithOtherProduct;
|
|
141
147
|
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
148
|
structureCompare: (other: _CfgProductInternal, strictOrder?: boolean, descriptionMatch?: boolean) => boolean;
|
|
149
149
|
tryMatchSelection: (other: _CfgProductInternal, descriptionMatch?: boolean, productLoaderForGroupedLoad?: ProductLoader | undefined) => Promise<boolean>;
|
|
150
150
|
/** Only features in selected options and selected additional products. */
|
package/dist/CfgProduct.js
CHANGED
|
@@ -7,11 +7,10 @@ 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";
|
|
@@ -166,6 +165,7 @@ export class _CfgProductInternal {
|
|
|
166
165
|
let change = false;
|
|
167
166
|
if (sourceProduct !== undefined) {
|
|
168
167
|
this._rawProductData = sourceProduct.rawProductData;
|
|
168
|
+
this.configuration._internal.populateFeatures(sourceProduct.configuration.rootFeatureRefs);
|
|
169
169
|
change = true; // We can not know if this is an actual change, so we assume it is
|
|
170
170
|
}
|
|
171
171
|
const configurationChange = yield this.configuration._internal.setApiSelection(s.selOptions, false);
|
|
@@ -186,27 +186,19 @@ export class _CfgProductInternal {
|
|
|
186
186
|
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
187
|
}
|
|
188
188
|
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
|
-
}
|
|
189
|
+
assert(!sourceProductAdditionalProducts ||
|
|
190
|
+
additionalProductsCount === sourceProductAdditionalProducts.length, `Passed sourceProduct does not have the same number of additional products as this.`);
|
|
193
191
|
if ((yield Promise.all(apiSelectionAdditionalProducts.map((apiSelectionAdditionalProduct, index) => {
|
|
194
192
|
var _a;
|
|
195
193
|
const refKey = apiSelectionAdditionalProduct.refKey;
|
|
196
|
-
|
|
197
|
-
throw new Error("Additional product api configurations must have refKey.");
|
|
198
|
-
}
|
|
194
|
+
assertDefined(refKey, "Additional product api configurations must have refKey.");
|
|
199
195
|
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
|
-
}
|
|
196
|
+
assert(i !== -1, `Additional product not found. This product: "${this.key}". refKey of not found additional product: "${refKey}"`);
|
|
203
197
|
let sourceProductAdditionalProduct = undefined;
|
|
204
198
|
if (sourceProductAdditionalProducts !== undefined) {
|
|
205
199
|
sourceProductAdditionalProduct =
|
|
206
200
|
(_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
|
-
}
|
|
201
|
+
assertDefined(sourceProductAdditionalProduct, "Additional product not found in sourceProduct");
|
|
210
202
|
}
|
|
211
203
|
const additionalProduct = additionalProducts.splice(i, 1)[0]; // Splicing like this is okay because this is done synchronous. The setCon. is what is async.
|
|
212
204
|
return additionalProduct._internal._setApiSelectionWithOtherProduct(apiSelectionAdditionalProduct, doValidate, productLoaderForGroupedLoad, sourceProductAdditionalProduct);
|
|
@@ -540,59 +532,6 @@ export class _CfgProductInternal {
|
|
|
540
532
|
get syncGroupHandler() {
|
|
541
533
|
return this.root._syncGroupHandler;
|
|
542
534
|
}
|
|
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
535
|
}
|
|
597
536
|
_CfgProductInternal.make = (productLoaderRaw, productLoaderForGroupedLoad, // Used when instantiating the current product
|
|
598
537
|
lang, catId, partNumber, settings, optional, loadingObservable, refKey, refDescription, parent, root, transform, anchor) => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -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,11 +7,12 @@ 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";
|
|
14
14
|
import { wrapWithCache } from "../productLoader.js";
|
|
15
|
+
import { SyncGroupsPathHelper } from "../syncGroups/SyncGroupsPathHelper.js";
|
|
15
16
|
import { CfgOption, ProductConfigurationBubbleMode } from "./CfgOption.js";
|
|
16
17
|
import { _CfgProductConfigurationInternal } from "./CfgProductConfiguration.js";
|
|
17
18
|
import { getMtrlPreview } from "./utilitiesProductConfiguration.js";
|
|
@@ -311,10 +312,8 @@ export class _CfgFeatureInternal {
|
|
|
311
312
|
ProductConfigurationBubbleMode.ValidateAndBubbleSelectedAndApplySyncGroups) {
|
|
312
313
|
const product = this.rootProduct;
|
|
313
314
|
const syncGroupHandler = product.syncGroupHandler;
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
}
|
|
317
|
-
return yield syncGroupHandler.selectOption(product, optionInternal.path, on, wrapWithCache(product._productLoaderRaw));
|
|
315
|
+
assertDefined(syncGroupHandler, `Sync group handler is required for bubble mode ${ProductConfigurationBubbleMode.ValidateAndBubbleSelectedAndApplySyncGroups}`);
|
|
316
|
+
return yield syncGroupHandler.selectOption(product, SyncGroupsPathHelper.getPath(optionInternal), on, wrapWithCache(product._productLoaderRaw));
|
|
318
317
|
}
|
|
319
318
|
if (!on) {
|
|
320
319
|
if (this.selectionType === SelectionType.Group) {
|
|
@@ -502,23 +501,6 @@ export class _CfgFeatureInternal {
|
|
|
502
501
|
}
|
|
503
502
|
return this._options;
|
|
504
503
|
}
|
|
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
504
|
/**
|
|
523
505
|
* Make fresh references to all options on this feature.
|
|
524
506
|
* 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;
|
|
@@ -90,8 +89,6 @@ export declare class _CfgOptionInternal {
|
|
|
90
89
|
_childHasChanged: (freshRef: CfgFeature, bubbleMode: ProductConfigurationBubbleMode) => Promise<void>;
|
|
91
90
|
getApiSelection: () => SelectedOption;
|
|
92
91
|
setApiSelection: (apiOptionSelection: SelectedOption | undefined) => Promise<boolean>;
|
|
93
|
-
get path(): CfgPath;
|
|
94
|
-
getFromPath(path: CfgPath): _CfgFeatureInternal | _CfgOptionInternal;
|
|
95
92
|
structureCompare: (other: _CfgOptionInternal, strictOrder?: boolean, descriptionMatch?: boolean) => boolean;
|
|
96
93
|
tryMatchSelection: (other: CfgOption, descriptionMatch?: boolean) => Promise<boolean>;
|
|
97
94
|
keyMatch: (other: _CfgOptionInternal, descriptionMatch?: boolean) => boolean;
|
|
@@ -129,6 +126,11 @@ export declare class CfgOption {
|
|
|
129
126
|
get selected(): boolean;
|
|
130
127
|
/** Are all ancestors up to the CfgProductConfiguration selected? Includes self. */
|
|
131
128
|
get ancestorsSelected(): boolean;
|
|
129
|
+
/**
|
|
130
|
+
* Selects this Option.
|
|
131
|
+
* Only Options belonging to Features that are "select many" can be deselected.
|
|
132
|
+
* Calling this will cause a validation call to the server.
|
|
133
|
+
*/
|
|
132
134
|
setSelected: (on: boolean) => Promise<boolean>;
|
|
133
135
|
get thumbnail(): string | undefined;
|
|
134
136
|
get upcharge(): number | undefined;
|
|
@@ -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
|
}
|
|
@@ -310,23 +308,6 @@ export class _CfgOptionInternal {
|
|
|
310
308
|
}
|
|
311
309
|
return this._features;
|
|
312
310
|
}
|
|
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
311
|
_freshRefDescendants() {
|
|
331
312
|
const features = this._features || [];
|
|
332
313
|
for (let i = 0; i < features.length; i++) {
|
|
@@ -347,7 +328,7 @@ export class CfgOption {
|
|
|
347
328
|
this.isBackedBySame = (other) => this._internal === other._internal;
|
|
348
329
|
this.setNumericValue = (val, doSelectOption) => __awaiter(this, void 0, void 0, function* () { return yield this._internal.setNumericValue(val, doSelectOption); });
|
|
349
330
|
this.isAllowedNumericValue = (val) => this._internal.isAllowedNumericValue(val);
|
|
350
|
-
|
|
331
|
+
/**
|
|
351
332
|
* Selects this Option.
|
|
352
333
|
* Only Options belonging to Features that are "select many" can be deselected.
|
|
353
334
|
* Calling this will cause a validation call to the server.
|
|
@@ -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
|
/**
|
|
@@ -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,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _CfgProductInternal } from "../CfgProduct.js";
|
|
2
2
|
import { ProductLoader } from "../productLoader.js";
|
|
3
3
|
import { SyncGroupsApplyMode } from "./SyncGroupsApplyMode.js";
|
|
4
|
+
import { CfgPath } from "./SyncGroupsPathHelper.js";
|
|
4
5
|
import { SyncGroupsTransaction } from "./SyncGroupsTransaction.js";
|
|
5
6
|
export declare type SyncCode = string;
|
|
6
7
|
export declare type OptionCode = string;
|
|
@@ -19,7 +19,7 @@ export class SyncGroupsHandler {
|
|
|
19
19
|
this._syncState = _syncState;
|
|
20
20
|
this.updateMode = updateMode;
|
|
21
21
|
}
|
|
22
|
-
static make(updateMode = SyncGroupsApplyMode.
|
|
22
|
+
static make(updateMode = SyncGroupsApplyMode.Strict) {
|
|
23
23
|
return new SyncGroupsHandler(new SyncGroupsState(), updateMode);
|
|
24
24
|
}
|
|
25
25
|
clone() {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { _CfgProductInternal } from "../CfgProduct.js";
|
|
2
|
+
import { _CfgFeatureInternal } from "../productConfiguration/CfgFeature.js";
|
|
3
|
+
import { _CfgOptionInternal } from "../productConfiguration/CfgOption.js";
|
|
4
|
+
import { _CfgProductConfigurationInternal } from "../productConfiguration/CfgProductConfiguration.js";
|
|
5
|
+
export declare type CfgPathSegment = string;
|
|
6
|
+
/**
|
|
7
|
+
* Represents the path to a node in the configuration tree.
|
|
8
|
+
*
|
|
9
|
+
* The format consists of a number of CfgPathSegments, each of which is currently a string. The
|
|
10
|
+
* exact meaning of the strings vary depending on where they are located in the path.
|
|
11
|
+
*
|
|
12
|
+
* @warning
|
|
13
|
+
* The format is strictly internal and can change in later versions of the SDK.
|
|
14
|
+
* Data stored in a CfgPath should be thus be considered transient and never stored or transmitted.
|
|
15
|
+
*/
|
|
16
|
+
export declare type CfgPath = CfgPathSegment[];
|
|
17
|
+
declare type PathItemType = _CfgProductInternal | _CfgProductConfigurationInternal | _CfgFeatureInternal | _CfgOptionInternal;
|
|
18
|
+
export declare class SyncGroupsPathHelper {
|
|
19
|
+
static getPath(item: PathItemType): CfgPath;
|
|
20
|
+
static getFromPath(path: CfgPath, root: PathItemType): PathItemType;
|
|
21
|
+
static getProductFromPath(path: CfgPath, item: _CfgProductInternal): _CfgProductInternal;
|
|
22
|
+
static getProductConfigurationFromPath(path: CfgPath, item: _CfgProductInternal): _CfgProductConfigurationInternal;
|
|
23
|
+
static getFeatureFromPath(path: CfgPath, item: PathItemType): _CfgFeatureInternal;
|
|
24
|
+
static getOptionFromPath(path: CfgPath, item: PathItemType): _CfgOptionInternal;
|
|
25
|
+
}
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=SyncGroupsPathHelper.d.ts.map
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { assert, assertDefined } from "@configura/web-utilities";
|
|
2
|
+
import { _CfgProductInternal } from "../CfgProduct.js";
|
|
3
|
+
import { _CfgFeatureInternal } from "../productConfiguration/CfgFeature.js";
|
|
4
|
+
import { _CfgOptionInternal } from "../productConfiguration/CfgOption.js";
|
|
5
|
+
import { _CfgProductConfigurationInternal } from "../productConfiguration/CfgProductConfiguration.js";
|
|
6
|
+
export class SyncGroupsPathHelper {
|
|
7
|
+
static getPath(item) {
|
|
8
|
+
if (item instanceof _CfgProductInternal) {
|
|
9
|
+
const parent = item.parent;
|
|
10
|
+
const refKey = item.refKey;
|
|
11
|
+
if (parent === undefined || refKey === undefined) {
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
14
|
+
return [...this.getPath(parent), "p", refKey];
|
|
15
|
+
}
|
|
16
|
+
if (item instanceof _CfgProductConfigurationInternal) {
|
|
17
|
+
return [...this.getPath(item.parentProduct), "c"];
|
|
18
|
+
}
|
|
19
|
+
if (item instanceof _CfgFeatureInternal) {
|
|
20
|
+
return [...this.getPath(item.parent), item.code];
|
|
21
|
+
}
|
|
22
|
+
if (item instanceof _CfgOptionInternal) {
|
|
23
|
+
return [...this.getPath(item.parent), item.code];
|
|
24
|
+
}
|
|
25
|
+
throw new Error("This should not happen");
|
|
26
|
+
}
|
|
27
|
+
static getFromPath(path, root) {
|
|
28
|
+
path = path.slice();
|
|
29
|
+
let item = root;
|
|
30
|
+
while (path.length > 0) {
|
|
31
|
+
const segment = path.shift();
|
|
32
|
+
if (item instanceof _CfgProductInternal) {
|
|
33
|
+
switch (segment) {
|
|
34
|
+
case "p":
|
|
35
|
+
const refKey = path.shift();
|
|
36
|
+
const additional = item.additionalProducts.find((p) => p.refKey === refKey);
|
|
37
|
+
assertDefined(additional, `Additional product not found "p, ${refKey}, ${path.join(", ")}"`);
|
|
38
|
+
item = additional._internal;
|
|
39
|
+
break;
|
|
40
|
+
case "c":
|
|
41
|
+
assert(item instanceof _CfgProductInternal, "Was not product");
|
|
42
|
+
item = item.configuration._internal;
|
|
43
|
+
break;
|
|
44
|
+
default:
|
|
45
|
+
throw new Error(`Unexpected path segment ${segment}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else if (item instanceof _CfgProductConfigurationInternal) {
|
|
49
|
+
const feature = item.features.find((f) => f.code === segment);
|
|
50
|
+
assertDefined(feature, `Feature not found ${segment}, ${path.join(", ")}`);
|
|
51
|
+
item = feature._internal;
|
|
52
|
+
}
|
|
53
|
+
else if (item instanceof _CfgFeatureInternal) {
|
|
54
|
+
const option = item.options.find((o) => o.code === segment);
|
|
55
|
+
assertDefined(option, `Option not found ${segment}, ${path.join(", ")}`);
|
|
56
|
+
item = option._internal;
|
|
57
|
+
}
|
|
58
|
+
else if (item instanceof _CfgOptionInternal) {
|
|
59
|
+
const feature = item.features.find((o) => o.code === segment);
|
|
60
|
+
assertDefined(feature, `Feature not found ${segment}, ${path.join(", ")}`);
|
|
61
|
+
item = feature._internal;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
throw new Error("This should not happen (unexpected type)");
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return item;
|
|
68
|
+
}
|
|
69
|
+
static getProductFromPath(path, item) {
|
|
70
|
+
const p = this.getFromPath(path, item);
|
|
71
|
+
assert(p instanceof _CfgProductInternal, `Path did not lead to a Product`);
|
|
72
|
+
return p;
|
|
73
|
+
}
|
|
74
|
+
static getProductConfigurationFromPath(path, item) {
|
|
75
|
+
const c = this.getFromPath(path, item);
|
|
76
|
+
assert(c instanceof _CfgProductConfigurationInternal, `Path did not lead to a ProductConfiguration"`);
|
|
77
|
+
return c;
|
|
78
|
+
}
|
|
79
|
+
static getFeatureFromPath(path, item) {
|
|
80
|
+
const f = this.getFromPath(path, item);
|
|
81
|
+
assert(f instanceof _CfgFeatureInternal, `Path did not lead to a Feature`);
|
|
82
|
+
return f;
|
|
83
|
+
}
|
|
84
|
+
static getOptionFromPath(path, item) {
|
|
85
|
+
const o = this.getFromPath(path, item);
|
|
86
|
+
assert(o instanceof _CfgOptionInternal, `Path did not lead to a Option`);
|
|
87
|
+
return o;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -15,6 +15,6 @@ export declare class SyncGroupsState {
|
|
|
15
15
|
setForSelectMany(syncCode: SyncCode, optionCode: OptionCode, selected: boolean): void;
|
|
16
16
|
getForSelectOne(syncCode: SyncCode): OptionCode | undefined;
|
|
17
17
|
getForSelectMany(syncCode: SyncCode, optionCode: OptionCode): boolean | undefined;
|
|
18
|
-
logDebug(): void;
|
|
18
|
+
logDebug(group?: string, code?: string, selected?: boolean): void;
|
|
19
19
|
}
|
|
20
20
|
//# sourceMappingURL=SyncGroupsState.d.ts.map
|
|
@@ -31,7 +31,7 @@ export class SyncGroupsState {
|
|
|
31
31
|
}
|
|
32
32
|
setForSelectOne(syncCode, optionCode) {
|
|
33
33
|
this._selectOne.set(syncCode, optionCode);
|
|
34
|
-
this.logDebug();
|
|
34
|
+
this.logDebug(syncCode, optionCode);
|
|
35
35
|
}
|
|
36
36
|
setForSelectMany(syncCode, optionCode, selected) {
|
|
37
37
|
let forSyncCode = this._selectMany.get(syncCode);
|
|
@@ -40,7 +40,7 @@ export class SyncGroupsState {
|
|
|
40
40
|
this._selectMany.set(syncCode, forSyncCode);
|
|
41
41
|
}
|
|
42
42
|
forSyncCode.set(optionCode, selected);
|
|
43
|
-
this.logDebug();
|
|
43
|
+
this.logDebug(syncCode, optionCode, selected);
|
|
44
44
|
}
|
|
45
45
|
getForSelectOne(syncCode) {
|
|
46
46
|
return this._selectOne.get(syncCode);
|
|
@@ -49,13 +49,60 @@ export class SyncGroupsState {
|
|
|
49
49
|
var _a;
|
|
50
50
|
return (_a = this._selectMany.get(syncCode)) === null || _a === void 0 ? void 0 : _a.get(optionCode);
|
|
51
51
|
}
|
|
52
|
-
logDebug() {
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
logDebug(group, code, selected) {
|
|
53
|
+
const isMany = selected !== undefined;
|
|
54
|
+
const selectOne = Array.from(this._selectOne.entries());
|
|
55
|
+
const selectMany = Array.from(this._selectMany.entries()).reduce((a, [groupCode, optionCodeToSelected]) => {
|
|
55
56
|
for (const [optionCode, selected] of optionCodeToSelected) {
|
|
56
57
|
a.push([groupCode, optionCode, selected]);
|
|
57
58
|
}
|
|
58
59
|
return a;
|
|
59
|
-
}, [])
|
|
60
|
+
}, []);
|
|
61
|
+
let columnWidth = 1;
|
|
62
|
+
selectOne.forEach((e) => {
|
|
63
|
+
columnWidth = Math.max(columnWidth, e[0].length);
|
|
64
|
+
});
|
|
65
|
+
selectMany.forEach((e) => {
|
|
66
|
+
columnWidth = Math.max(columnWidth, e[0].length);
|
|
67
|
+
});
|
|
68
|
+
const padding = Array(columnWidth).join(" ");
|
|
69
|
+
const styleBold = "font-weight: bold";
|
|
70
|
+
const styleBoldThis = "color:blue; font-weight: bold";
|
|
71
|
+
const styleBoldOn = "color:green; font-weight: bold";
|
|
72
|
+
const styleBoldOff = "color:red; font-weight: bold";
|
|
73
|
+
const styleThis = "color:blue";
|
|
74
|
+
const styleOn = "color:green";
|
|
75
|
+
const styleOff = "color:red";
|
|
76
|
+
const output = [];
|
|
77
|
+
if (group === undefined) {
|
|
78
|
+
output.push("");
|
|
79
|
+
}
|
|
80
|
+
else if (isMany) {
|
|
81
|
+
output.push(...[
|
|
82
|
+
`%c${code} %cin %c${group} %cset to %c${selected ? "on" : "off"}\n`,
|
|
83
|
+
styleBoldThis,
|
|
84
|
+
"",
|
|
85
|
+
styleBoldThis,
|
|
86
|
+
"",
|
|
87
|
+
selected ? styleBoldOn : styleBoldOff,
|
|
88
|
+
]);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
output.push(...[`%c${group}%c set to %c${code}\n`, styleBoldThis, "", styleBoldThis]);
|
|
92
|
+
}
|
|
93
|
+
output[0] = output[0] + "%cSync State (single)";
|
|
94
|
+
output.push(styleBold);
|
|
95
|
+
selectOne.forEach((e) => {
|
|
96
|
+
output[0] = output[0] + `\n %c${(padding + e[0]).slice(-columnWidth)}: ${e[1]}`;
|
|
97
|
+
output.push(!isMany && group === e[0] ? styleThis : "");
|
|
98
|
+
});
|
|
99
|
+
output[0] = output[0] + "\n%cSync State (multi)";
|
|
100
|
+
output.push(styleBold);
|
|
101
|
+
selectMany.forEach((e) => {
|
|
102
|
+
output[0] = output[0] + `\n %c${(padding + e[0]).slice(-columnWidth)}: %c${e[1]}`;
|
|
103
|
+
output.push(isMany && group === e[0] ? styleThis : "");
|
|
104
|
+
output.push(e[2] === true ? styleOn : styleOff);
|
|
105
|
+
});
|
|
106
|
+
console.log(...output);
|
|
60
107
|
}
|
|
61
108
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _CfgProductInternal } from "../CfgProduct.js";
|
|
2
2
|
import { _CfgFeatureInternal } from "../productConfiguration/CfgFeature.js";
|
|
3
3
|
import { _CfgOptionInternal } from "../productConfiguration/CfgOption.js";
|
|
4
4
|
import { ProductLoader } from "../productLoader.js";
|
|
5
5
|
import { SyncGroupsApplyMode } from "./SyncGroupsApplyMode.js";
|
|
6
6
|
import { OptionCode, SyncCode } from "./SyncGroupsHandler.js";
|
|
7
|
+
import { CfgPath } from "./SyncGroupsPathHelper.js";
|
|
7
8
|
import { SyncGroupsState } from "./SyncGroupsState.js";
|
|
8
9
|
/**
|
|
9
10
|
* A transaction is normally limited to one user interaction. Like opening a product or
|
|
@@ -7,8 +7,10 @@ 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 { assert } from "@configura/web-utilities";
|
|
10
11
|
import { SelectionType } from "../productConfiguration/CfgFeature.js";
|
|
11
12
|
import { SyncGroupsApplier } from "./SyncGroupsApplier.js";
|
|
13
|
+
import { SyncGroupsPathHelper } from "./SyncGroupsPathHelper.js";
|
|
12
14
|
/**
|
|
13
15
|
* A transaction is normally limited to one user interaction. Like opening a product or
|
|
14
16
|
* selecting an option. This object is used to keep data for one transaction. In particular
|
|
@@ -57,32 +59,24 @@ export class SyncGroupsTransaction {
|
|
|
57
59
|
}
|
|
58
60
|
selectOption(optionPath, on) {
|
|
59
61
|
return __awaiter(this, void 0, void 0, function* () {
|
|
60
|
-
const targetOption =
|
|
62
|
+
const targetOption = SyncGroupsPathHelper.getOptionFromPath(optionPath, this.target);
|
|
61
63
|
return yield SyncGroupsApplier.selectOption(this, targetOption, on);
|
|
62
64
|
});
|
|
63
65
|
}
|
|
64
66
|
addSelectOneFeatureAffected(feature) {
|
|
65
|
-
|
|
66
|
-
throw new Error("Can only be used for SelectOne Feature");
|
|
67
|
-
}
|
|
67
|
+
assert(feature.selectionType === SelectionType.SelectOne, "Can only be used for SelectOne Feature");
|
|
68
68
|
this.affectedSelectOneFeatures.add(feature);
|
|
69
69
|
}
|
|
70
70
|
addSelectManyOptionAffected(option) {
|
|
71
|
-
|
|
72
|
-
throw new Error("Can only be used for option in SelectMany Feature");
|
|
73
|
-
}
|
|
71
|
+
assert(option.parent.selectionType === SelectionType.SelectMany, "Can only be used for option in SelectMany Feature");
|
|
74
72
|
this.affectedSelectManyOptions.add(option);
|
|
75
73
|
}
|
|
76
74
|
hasSelectOneFeatureBeenAffected(feature) {
|
|
77
|
-
|
|
78
|
-
throw new Error("Can only be used for SelectOne Feature");
|
|
79
|
-
}
|
|
75
|
+
assert(feature.selectionType === SelectionType.SelectOne, "Can only be used for SelectOne Feature");
|
|
80
76
|
return this.affectedSelectOneFeatures.has(feature);
|
|
81
77
|
}
|
|
82
78
|
hasSelectManyOptionBeenAffected(option) {
|
|
83
|
-
|
|
84
|
-
throw new Error("Can only be used for option in SelectMany Feature");
|
|
85
|
-
}
|
|
79
|
+
assert(option.parent.selectionType === SelectionType.SelectMany, "Can only be used for option in SelectMany Feature");
|
|
86
80
|
return this.affectedSelectManyOptions.has(option);
|
|
87
81
|
}
|
|
88
82
|
addSyncGroupAffectedForSelectOne(syncCode) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@configura/web-api",
|
|
3
|
-
"version": "1.6.1-alpha.
|
|
3
|
+
"version": "1.6.1-alpha.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"access": "public"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@configura/web-utilities": "^1.6.1-alpha.
|
|
26
|
+
"@configura/web-utilities": "^1.6.1-alpha.1"
|
|
27
27
|
},
|
|
28
|
-
"gitHead": "
|
|
28
|
+
"gitHead": "afaf1e342f0648246a1dcb6f7bc636d4d1979bec"
|
|
29
29
|
}
|