@configura/web-api 2.0.0-alpha.18 → 2.0.0-alpha.20
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 +47 -17
- package/dist/CatalogueAPI.js +61 -6
- package/dist/CfgProduct.d.ts +17 -6
- package/dist/CfgProduct.js +55 -14
- package/dist/CfgReferencePathHelper.d.ts +3 -3
- package/dist/productConfiguration/CfgFeature.d.ts +6 -4
- package/dist/productConfiguration/CfgFeature.js +13 -6
- package/dist/productConfiguration/CfgOption.d.ts +3 -3
- package/dist/productConfiguration/CfgOption.js +5 -5
- package/dist/productConfiguration/CfgProductConfiguration.d.ts +16 -7
- package/dist/productConfiguration/CfgProductConfiguration.js +41 -14
- package/dist/productConfiguration/filters.d.ts +2 -2
- package/dist/productConfiguration/productParamsGenerator.d.ts +3 -3
- package/dist/productConfiguration/utilitiesProductConfiguration.d.ts +1 -1
- package/dist/productConfiguration/utilitiesProductConfiguration.js +11 -4
- package/dist/productLoader.d.ts +3 -3
- package/dist/syncGroups/SyncGroupsHandler.d.ts +4 -1
- package/dist/syncGroups/SyncGroupsHandler.js +6 -2
- package/dist/syncGroups/SyncGroupsTransaction.js +34 -21
- package/dist/tasks/TaskHandler.d.ts +2 -2
- package/dist/tests/testData/dummyProductForTest.d.ts +2 -2
- package/dist/tests/testData/testDataAdditionalProductInAdditionalProductInProductForTest.js +1 -0
- package/dist/tests/testData/testDataCachedGetProduct.js +1 -0
- package/dist/tests/testData/testDataCachedPostValidate.js +1 -0
- package/dist/tests/testData/testDataProductAggregatedPrice.js +1 -0
- package/dist/tests/testData/testDataUpcharge.js +1 -0
- package/dist/utilitiesCatalogueData.d.ts +14 -9
- package/dist/utilitiesCatalogueData.js +7 -0
- package/dist/utilitiesCataloguePermission.d.ts +4 -4
- package/package.json +3 -3
|
@@ -17,15 +17,15 @@ export declare type StretchMap = Map<string, {
|
|
|
17
17
|
* modified. CfgProductConfiguration is the class that should be used and interacted with.
|
|
18
18
|
*/
|
|
19
19
|
export declare class _CfgProductConfigurationInternal {
|
|
20
|
-
readonly allRawFeatures: DtoFeature[];
|
|
21
20
|
readonly parentProduct: _CfgProductInternal;
|
|
22
21
|
readonly rootProduct: _CfgProductInternal;
|
|
23
22
|
private readonly _initialRootFeatureRefs;
|
|
24
|
-
static _makeUninitialized(rootFeatureRefs: DtoFeatureRef[],
|
|
23
|
+
static _makeUninitialized(rootFeatureRefs: DtoFeatureRef[], rawFeatures: DtoFeature[], // Flat packed. All the features that can currently appear anyplace in the selection tree.
|
|
25
24
|
parentProduct: _CfgProductInternal, rootProduct: _CfgProductInternal): _CfgProductConfigurationInternal;
|
|
26
25
|
private constructor();
|
|
27
26
|
readonly key = "~";
|
|
28
27
|
private _rootFeatureRefs;
|
|
28
|
+
readonly accumulatedRawFeatures: DtoFeature[];
|
|
29
29
|
private _features;
|
|
30
30
|
readonly stretchReferenceLengthsByMeasureParamCode: StretchMap;
|
|
31
31
|
readonly changeObservable: Observable<ProductConfigurationChangeNotification>;
|
|
@@ -51,13 +51,22 @@ export declare class _CfgProductConfigurationInternal {
|
|
|
51
51
|
tryMatchSelection: (other: _CfgProductConfigurationInternal, descriptionMatch: boolean | undefined, validate: boolean) => Promise<boolean>;
|
|
52
52
|
/** Only selected features. */
|
|
53
53
|
_getFeaturesWithCode: (code: string) => _CfgFeatureInternal[];
|
|
54
|
+
/**
|
|
55
|
+
* Extends the list of loaded potentially used features. Will warn for but ignore duplicates.
|
|
56
|
+
* Returns true if a change happened.
|
|
57
|
+
*/
|
|
58
|
+
addRawFeatures: (rawFeatures: DtoFeature[], warnForDuplicates: boolean) => boolean;
|
|
54
59
|
private _hasRootFeaturesChanged;
|
|
55
60
|
/**
|
|
56
61
|
* True if what root Features are used is not the same as at initial load.
|
|
57
62
|
* This means that functional selection has happened.
|
|
58
63
|
*/
|
|
59
64
|
get hasRootFeaturesChanged(): boolean;
|
|
60
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Populates _features based on the passed @param rootFeatureRefs .
|
|
67
|
+
* @return true if a change happened.
|
|
68
|
+
*/
|
|
69
|
+
populateFeatures: (rootFeatureRefs: DtoFeatureRef[]) => boolean;
|
|
61
70
|
setStretchReferenceLength: (measureParamCode: string, referenceLength: number | undefined, unit: LengthUnit) => Promise<boolean>;
|
|
62
71
|
}
|
|
63
72
|
export declare class CfgProductConfiguration {
|
|
@@ -67,7 +76,7 @@ export declare class CfgProductConfiguration {
|
|
|
67
76
|
* CfgProductConfiguration, but is not properly initialized until the initDone-callback
|
|
68
77
|
* has been called.
|
|
69
78
|
*/
|
|
70
|
-
static make(initSuccess: (c: CfgProductConfiguration) => void, initFail: (error: Error) => void, rootFeatureRefs: DtoFeatureRef[],
|
|
79
|
+
static make(initSuccess: (c: CfgProductConfiguration) => void, initFail: (error: Error) => void, rootFeatureRefs: DtoFeatureRef[], rawFeatures: DtoFeature[], // Flat packed. All the features that can currently appear anyplace in the selection tree.
|
|
71
80
|
apiSelection: DtoSelectedOption[], parentProduct: _CfgProductInternal, rootProduct: _CfgProductInternal): CfgProductConfiguration;
|
|
72
81
|
/**
|
|
73
82
|
* Makes an object wrapping the passed object. This is not a clone method, it is a method to
|
|
@@ -87,11 +96,11 @@ export declare class CfgProductConfiguration {
|
|
|
87
96
|
get rootProduct(): CfgProduct;
|
|
88
97
|
get key(): string;
|
|
89
98
|
/**
|
|
90
|
-
* Every (unprocessed) feature
|
|
91
|
-
*
|
|
99
|
+
* Every (unprocessed) feature that is currently loaded for this product. This can be extended
|
|
100
|
+
* by validation calls. What features are actually used is controlled by rootFeatureRefs and what
|
|
92
101
|
* options are selected.
|
|
93
102
|
*/
|
|
94
|
-
get
|
|
103
|
+
get rawFeatures(): DtoFeature[];
|
|
95
104
|
/** What features are used in the root of this. This can change with new validate calls. */
|
|
96
105
|
get rootFeatureRefs(): DtoFeatureRef[];
|
|
97
106
|
/** The root features at the root of the selection tree. */
|
|
@@ -19,14 +19,13 @@ import { syncCfgFeatures } from "./utilitiesProductConfiguration.js";
|
|
|
19
19
|
* modified. CfgProductConfiguration is the class that should be used and interacted with.
|
|
20
20
|
*/
|
|
21
21
|
export class _CfgProductConfigurationInternal {
|
|
22
|
-
constructor(
|
|
23
|
-
parentProduct, rootProduct, _initialRootFeatureRefs) {
|
|
24
|
-
this.allRawFeatures = allRawFeatures;
|
|
22
|
+
constructor(rawFeatures, parentProduct, rootProduct, _initialRootFeatureRefs) {
|
|
25
23
|
this.parentProduct = parentProduct;
|
|
26
24
|
this.rootProduct = rootProduct;
|
|
27
25
|
this._initialRootFeatureRefs = _initialRootFeatureRefs;
|
|
28
26
|
this.key = "~";
|
|
29
27
|
this._rootFeatureRefs = [];
|
|
28
|
+
this.accumulatedRawFeatures = []; // Flat packed. May be extended in validate calls.
|
|
30
29
|
this._features = [];
|
|
31
30
|
this.changeObservable = new Observable();
|
|
32
31
|
this._notifyAllOfChange = (bubbleMode, committed) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -114,11 +113,39 @@ export class _CfgProductConfigurationInternal {
|
|
|
114
113
|
agg.push(...feature._internal._getFeaturesWithCode(code));
|
|
115
114
|
return agg;
|
|
116
115
|
}, []);
|
|
116
|
+
/**
|
|
117
|
+
* Extends the list of loaded potentially used features. Will warn for but ignore duplicates.
|
|
118
|
+
* Returns true if a change happened.
|
|
119
|
+
*/
|
|
120
|
+
this.addRawFeatures = (rawFeatures, warnForDuplicates) => {
|
|
121
|
+
let change = false;
|
|
122
|
+
const accumulatedRawFeatures = this.accumulatedRawFeatures;
|
|
123
|
+
for (const rawFeature of rawFeatures) {
|
|
124
|
+
const code = rawFeature.code;
|
|
125
|
+
if (accumulatedRawFeatures.find((f) => code === f.code)) {
|
|
126
|
+
if (warnForDuplicates) {
|
|
127
|
+
console.warn(`Feature ${code} was already loaded. Will ignore it.`);
|
|
128
|
+
}
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
accumulatedRawFeatures.push(rawFeature);
|
|
132
|
+
change = true;
|
|
133
|
+
}
|
|
134
|
+
return change;
|
|
135
|
+
};
|
|
117
136
|
this._hasRootFeaturesChanged = false;
|
|
137
|
+
/**
|
|
138
|
+
* Populates _features based on the passed @param rootFeatureRefs .
|
|
139
|
+
* @return true if a change happened.
|
|
140
|
+
*/
|
|
118
141
|
this.populateFeatures = (rootFeatureRefs) => {
|
|
142
|
+
if (compareArrays(this._rootFeatureRefs, rootFeatureRefs, (l, r) => l.code === r.code, true)) {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
119
145
|
this._rootFeatureRefs = rootFeatureRefs;
|
|
120
146
|
this._hasRootFeaturesChanged = !compareArrays(this._initialRootFeatureRefs, rootFeatureRefs, (l, r) => l.code === r.code);
|
|
121
|
-
this._features = syncCfgFeatures(rootFeatureRefs, this._features, this.
|
|
147
|
+
this._features = syncCfgFeatures(rootFeatureRefs, this._features, this.accumulatedRawFeatures, this, this, this.parentProduct, this.rootProduct);
|
|
148
|
+
return true;
|
|
122
149
|
};
|
|
123
150
|
this.setStretchReferenceLength = (measureParamCode, referenceLength, unit) => __awaiter(this, void 0, void 0, function* () {
|
|
124
151
|
if (measureParamCode === "") {
|
|
@@ -163,6 +190,8 @@ export class _CfgProductConfigurationInternal {
|
|
|
163
190
|
console.log(`Use "window['${dbgName}']" or window.conf to access conf.`);
|
|
164
191
|
}
|
|
165
192
|
/* eslint-enable */
|
|
193
|
+
this.addRawFeatures(rawFeatures, true);
|
|
194
|
+
this.populateFeatures(_initialRootFeatureRefs);
|
|
166
195
|
/**
|
|
167
196
|
* Although the measurement-datas are also passed in validate-calls they are only used at
|
|
168
197
|
* initial product creation. The data is assumed to always be the same for a product, so
|
|
@@ -199,11 +228,9 @@ export class _CfgProductConfigurationInternal {
|
|
|
199
228
|
}
|
|
200
229
|
this.stretchReferenceLengthsByMeasureParamCode = stretchReferenceLengthsByMeasureParamCode;
|
|
201
230
|
}
|
|
202
|
-
static _makeUninitialized(rootFeatureRefs,
|
|
231
|
+
static _makeUninitialized(rootFeatureRefs, rawFeatures, // Flat packed. All the features that can currently appear anyplace in the selection tree.
|
|
203
232
|
parentProduct, rootProduct) {
|
|
204
|
-
|
|
205
|
-
configuration.populateFeatures(rootFeatureRefs);
|
|
206
|
-
return configuration;
|
|
233
|
+
return new this(rawFeatures, parentProduct, rootProduct, rootFeatureRefs);
|
|
207
234
|
}
|
|
208
235
|
get rootFeatureRefs() {
|
|
209
236
|
return this._rootFeatureRefs;
|
|
@@ -265,9 +292,9 @@ export class CfgProductConfiguration {
|
|
|
265
292
|
* CfgProductConfiguration, but is not properly initialized until the initDone-callback
|
|
266
293
|
* has been called.
|
|
267
294
|
*/
|
|
268
|
-
static make(initSuccess, initFail, rootFeatureRefs,
|
|
295
|
+
static make(initSuccess, initFail, rootFeatureRefs, rawFeatures, // Flat packed. All the features that can currently appear anyplace in the selection tree.
|
|
269
296
|
apiSelection, parentProduct, rootProduct) {
|
|
270
|
-
const internal = _CfgProductConfigurationInternal._makeUninitialized(rootFeatureRefs,
|
|
297
|
+
const internal = _CfgProductConfigurationInternal._makeUninitialized(rootFeatureRefs, rawFeatures, parentProduct, rootProduct);
|
|
271
298
|
const external = new this(internal);
|
|
272
299
|
// Note the async-callback at the end of the following line. The call is async.
|
|
273
300
|
internal
|
|
@@ -295,12 +322,12 @@ export class CfgProductConfiguration {
|
|
|
295
322
|
return this._internal.key;
|
|
296
323
|
}
|
|
297
324
|
/**
|
|
298
|
-
* Every (unprocessed) feature
|
|
299
|
-
*
|
|
325
|
+
* Every (unprocessed) feature that is currently loaded for this product. This can be extended
|
|
326
|
+
* by validation calls. What features are actually used is controlled by rootFeatureRefs and what
|
|
300
327
|
* options are selected.
|
|
301
328
|
*/
|
|
302
|
-
get
|
|
303
|
-
return this._internal.
|
|
329
|
+
get rawFeatures() {
|
|
330
|
+
return this._internal.accumulatedRawFeatures;
|
|
304
331
|
}
|
|
305
332
|
/** What features are used in the root of this. This can change with new validate calls. */
|
|
306
333
|
get rootFeatureRefs() {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Filters, Matches } from "@configura/web-utilities";
|
|
2
|
-
import {
|
|
3
|
-
export declare function applyCatalogueFilters<T extends
|
|
2
|
+
import { DtoCatalogueParams, DtoLevel, DtoProductRef } from "../CatalogueAPI.js";
|
|
3
|
+
export declare function applyCatalogueFilters<T extends DtoCatalogueParams>(filters: Filters<DtoCatalogueParams>, catalogues: T[]): [Matches<DtoCatalogueParams>, T[]];
|
|
4
4
|
export interface ProductRefParams {
|
|
5
5
|
partNr: string;
|
|
6
6
|
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { Filters } from "@configura/web-utilities";
|
|
2
|
-
import { CatalogueAPI, DtoApplicationAreasResponse,
|
|
2
|
+
import { CatalogueAPI, DtoApplicationAreasResponse, DtoCatalogueParamsWithCid, DtoCatalogueParamsWithCidAndLang } from "../CatalogueAPI.js";
|
|
3
3
|
import { CfgProduct, CfgProductSettings } from "../CfgProduct.js";
|
|
4
4
|
import { ProductRefParams } from "./filters.js";
|
|
5
5
|
export interface GeneratedProductConfiguration {
|
|
6
6
|
applicationAreasResponse: DtoApplicationAreasResponse;
|
|
7
7
|
catalogueCount: number;
|
|
8
8
|
catalogueIndex: number;
|
|
9
|
-
catalogueParams:
|
|
9
|
+
catalogueParams: DtoCatalogueParamsWithCidAndLang;
|
|
10
10
|
getProductDuration: number;
|
|
11
11
|
product: CfgProduct;
|
|
12
12
|
productCount: number;
|
|
13
13
|
productIndex: number;
|
|
14
14
|
}
|
|
15
|
-
export declare function generateProductConfigurations(api: CatalogueAPI, lang: string, catalogues:
|
|
15
|
+
export declare function generateProductConfigurations(api: CatalogueAPI, lang: string, catalogues: DtoCatalogueParamsWithCid[], filters: Filters<ProductRefParams>, settings?: Partial<CfgProductSettings>): AsyncIterableIterator<GeneratedProductConfiguration | Error>;
|
|
16
16
|
//# sourceMappingURL=productParamsGenerator.d.ts.map
|
|
@@ -8,7 +8,7 @@ import { CfgProductConfiguration, _CfgProductConfigurationInternal } from "./Cfg
|
|
|
8
8
|
* Returns a new array of CfgFeatures that maps to the newFeatureRefs array. Uses CfgFeatures from
|
|
9
9
|
* currentFeatures if they can be found, otherwise makes new.
|
|
10
10
|
*/
|
|
11
|
-
export declare function syncCfgFeatures(newFeatureRefs: DtoFeatureRef[], currentFeatures: CfgFeature[],
|
|
11
|
+
export declare function syncCfgFeatures(newFeatureRefs: DtoFeatureRef[], currentFeatures: CfgFeature[], rawFeatures: DtoFeature[], parent: _CfgProductConfigurationInternal | _CfgOptionInternal, parentConfiguration: _CfgProductConfigurationInternal, parentProduct: _CfgProductInternal, rootProduct: _CfgProductInternal): CfgFeature[];
|
|
12
12
|
export declare function getMtrlPreview(mtrlApplications: CfgMtrlApplication[] | undefined): string | undefined;
|
|
13
13
|
/**
|
|
14
14
|
* Recursively find all additional product references given a product configuration.
|
|
@@ -6,11 +6,11 @@ import { CfgProductConfiguration, } from "./CfgProductConfiguration.js";
|
|
|
6
6
|
* Returns a new array of CfgFeatures that maps to the newFeatureRefs array. Uses CfgFeatures from
|
|
7
7
|
* currentFeatures if they can be found, otherwise makes new.
|
|
8
8
|
*/
|
|
9
|
-
export function syncCfgFeatures(newFeatureRefs, currentFeatures,
|
|
9
|
+
export function syncCfgFeatures(newFeatureRefs, currentFeatures, rawFeatures, parent, parentConfiguration, parentProduct, rootProduct) {
|
|
10
10
|
const usedRawFeatures = newFeatureRefs
|
|
11
11
|
.map((r) => r.code)
|
|
12
12
|
.map((c) => {
|
|
13
|
-
const rawFeature =
|
|
13
|
+
const rawFeature = rawFeatures.find((f) => c === f.code);
|
|
14
14
|
if (rawFeature === undefined) {
|
|
15
15
|
throw new Error(`Feature not found. Requested feature code: "${c}".`);
|
|
16
16
|
}
|
|
@@ -38,12 +38,19 @@ export function syncCfgFeatures(newFeatureRefs, currentFeatures, allRawFeatures,
|
|
|
38
38
|
// products with similar feature-options tree and trying
|
|
39
39
|
// to retain made selections
|
|
40
40
|
const key = fDescription + (fDescription === "" || hasDuplicateDescription ? fCode : "");
|
|
41
|
-
const existingFeature = currentFeatures.find((cfgF) => cfgF.code === fCode
|
|
41
|
+
const existingFeature = currentFeatures.find((cfgF) => cfgF.code === fCode);
|
|
42
42
|
if (existingFeature !== undefined) {
|
|
43
|
+
if (hasDuplicateDescription) {
|
|
44
|
+
// HasDuplicateDescription could mean the key need to be more specific compared
|
|
45
|
+
// to the one we already have, so then we set it. An old duplicate description
|
|
46
|
+
// key will cause no harm as it is guaranteed to be at least as specific as this.
|
|
47
|
+
// Not changing the key will make React not rerender, so we don't change.
|
|
48
|
+
existingFeature._internal.key = key;
|
|
49
|
+
}
|
|
43
50
|
newFeatures.push(existingFeature);
|
|
44
51
|
continue;
|
|
45
52
|
}
|
|
46
|
-
newFeatures.push(CfgFeature.make(f,
|
|
53
|
+
newFeatures.push(CfgFeature.make(f, rawFeatures, key, parent, parentConfiguration, parentProduct, rootProduct));
|
|
47
54
|
}
|
|
48
55
|
return newFeatures;
|
|
49
56
|
}
|
package/dist/productLoader.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DtoProductParamsWithCidAndLang, DtoValidateRequest } from "./CatalogueAPI.js";
|
|
2
2
|
import { CfgProductResponse, CfgValidateResponse } from "./utilitiesCatalogueData.js";
|
|
3
|
-
export declare type GetProduct = (params:
|
|
4
|
-
export declare type PostValidate = (params:
|
|
3
|
+
export declare type GetProduct = (params: DtoProductParamsWithCidAndLang) => Promise<CfgProductResponse>;
|
|
4
|
+
export declare type PostValidate = (params: DtoProductParamsWithCidAndLang, body: DtoValidateRequest) => Promise<CfgValidateResponse>;
|
|
5
5
|
export declare type ProductLoader = {
|
|
6
6
|
getProduct: GetProduct;
|
|
7
7
|
postValidate: PostValidate;
|
|
@@ -24,7 +24,10 @@ export declare class SyncGroupsHandler {
|
|
|
24
24
|
clone(): SyncGroupsHandler;
|
|
25
25
|
get verboseLogging(): boolean;
|
|
26
26
|
set verboseLogging(v: boolean);
|
|
27
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* Used to initially apply the sync state onto a new product so that it is "in sync"
|
|
29
|
+
* and to reapply the sync state when an optional additional product is selected.
|
|
30
|
+
*/
|
|
28
31
|
init(product: _CfgProductInternal, productLoader: ProductLoader): Promise<void>;
|
|
29
32
|
/**
|
|
30
33
|
* Used when an Option is selected or deselected to apply all consequences of the sync groups.
|
|
@@ -123,7 +123,8 @@ import { SyncGroupsTransaction } from "./SyncGroupsTransaction.js";
|
|
|
123
123
|
* C) The SyncState has an option code for this SyncGroup.
|
|
124
124
|
* D) The option code in the SyncState for the SyncGroup is not the Option selected.
|
|
125
125
|
* E) The Feature has an Option with the right option code.
|
|
126
|
-
* F) The Feature has not previously been affected in this transaction
|
|
126
|
+
* F) The Feature has not previously been affected in this transaction, unless it was affected
|
|
127
|
+
* at Feature initialization.
|
|
127
128
|
*
|
|
128
129
|
* ...for SelectMany (done for every Option):
|
|
129
130
|
* C) The SyncState has a value (on or off) for this SyncGroup and option code.
|
|
@@ -275,7 +276,10 @@ export class SyncGroupsHandler {
|
|
|
275
276
|
set verboseLogging(v) {
|
|
276
277
|
this._syncState.verboseLogging = v;
|
|
277
278
|
}
|
|
278
|
-
/**
|
|
279
|
+
/**
|
|
280
|
+
* Used to initially apply the sync state onto a new product so that it is "in sync"
|
|
281
|
+
* and to reapply the sync state when an optional additional product is selected.
|
|
282
|
+
*/
|
|
279
283
|
init(product, productLoader) {
|
|
280
284
|
return __awaiter(this, void 0, void 0, function* () {
|
|
281
285
|
const transaction = yield this.newTransaction(product, productLoader, true);
|
|
@@ -13,6 +13,12 @@ import { SelectionType, } from "../productConfiguration/CfgFeature.js";
|
|
|
13
13
|
import { ProductConfigurationBubbleMode, } from "../productConfiguration/CfgOption.js";
|
|
14
14
|
import { SyncGroupsApplyMode } from "./SyncGroupsApplyMode.js";
|
|
15
15
|
import { SyncGroupsPathHelper } from "./SyncGroupsPathHelper.js";
|
|
16
|
+
var AffectedLevel;
|
|
17
|
+
(function (AffectedLevel) {
|
|
18
|
+
AffectedLevel[AffectedLevel["None"] = 0] = "None";
|
|
19
|
+
AffectedLevel[AffectedLevel["Initialized"] = 1] = "Initialized";
|
|
20
|
+
AffectedLevel[AffectedLevel["Set"] = 2] = "Set";
|
|
21
|
+
})(AffectedLevel || (AffectedLevel = {}));
|
|
16
22
|
/**
|
|
17
23
|
* The Transaction is a transient object used to track all the changes made to the supplied
|
|
18
24
|
* SyncGroupState as a result of a (normally) single initial event, like when opening a product
|
|
@@ -39,7 +45,7 @@ import { SyncGroupsPathHelper } from "./SyncGroupsPathHelper.js";
|
|
|
39
45
|
export class SyncGroupsTransaction {
|
|
40
46
|
constructor(syncState, updateMode, productLoader, original, target, initial) {
|
|
41
47
|
this._closed = false;
|
|
42
|
-
this.affectedSelectOneFeatures = new
|
|
48
|
+
this.affectedSelectOneFeatures = new Map();
|
|
43
49
|
this.affectedSelectManyOptions = new Set();
|
|
44
50
|
this.affectedSelectOneSyncGroups = new Set();
|
|
45
51
|
this.affectedSelectManySyncGroupsAndOptions = new Map();
|
|
@@ -104,7 +110,7 @@ export class SyncGroupsTransaction {
|
|
|
104
110
|
change = true;
|
|
105
111
|
switch (feature.selectionType) {
|
|
106
112
|
case SelectionType.SelectOne:
|
|
107
|
-
this.affectedSelectOneFeatures.
|
|
113
|
+
this.affectedSelectOneFeatures.set(feature, AffectedLevel.Set);
|
|
108
114
|
break;
|
|
109
115
|
case SelectionType.SelectMany:
|
|
110
116
|
this.affectedSelectManyOptions.add(option);
|
|
@@ -266,14 +272,19 @@ export class SyncGroupsTransaction {
|
|
|
266
272
|
return __awaiter(this, void 0, void 0, function* () {
|
|
267
273
|
const feature = featureWithInitial.target;
|
|
268
274
|
const featureDidJustComeIntoScope = featureWithInitial.initial === undefined;
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
//
|
|
275
|
+
const hasBeenAffectedLevel = this.affectedSelectOneFeatures.get(feature);
|
|
276
|
+
const syncGroupHasBeenUpdated = this.affectedSelectOneSyncGroups.has(syncCode);
|
|
277
|
+
if (hasBeenAffectedLevel === AffectedLevel.Set ||
|
|
278
|
+
(!syncGroupHasBeenUpdated && hasBeenAffectedLevel === AffectedLevel.Initialized)) {
|
|
279
|
+
// A feature can change value for two reasons:
|
|
280
|
+
// 1. The feature did just come into scope and loads from the sync group to set its "defaults"
|
|
281
|
+
// 2. The sync group has updated with a new value
|
|
282
|
+
// The rule is that in one sync group transaction the feature value is allowed to be updated
|
|
283
|
+
// once or twice. Once for initialization and once for new sync group value. But they have to
|
|
284
|
+
// happen in the right order.
|
|
274
285
|
return "recurseDown";
|
|
275
286
|
}
|
|
276
|
-
if (!featureDidJustComeIntoScope && !
|
|
287
|
+
if (!featureDidJustComeIntoScope && !syncGroupHasBeenUpdated) {
|
|
277
288
|
return "recurseDown";
|
|
278
289
|
}
|
|
279
290
|
const currentSyncGroupValue = this.syncState.getForSelectOne(syncCode);
|
|
@@ -295,7 +306,7 @@ export class SyncGroupsTransaction {
|
|
|
295
306
|
// Do not recurse further as we will change the state and so what is selected now won't be
|
|
296
307
|
// selected then.
|
|
297
308
|
yield feature.selectOption(optionToSelect._internal, true, ProductConfigurationBubbleMode.ToRoot);
|
|
298
|
-
this.affectedSelectOneFeatures.
|
|
309
|
+
this.affectedSelectOneFeatures.set(feature, syncGroupHasBeenUpdated ? AffectedLevel.Set : AffectedLevel.Initialized);
|
|
299
310
|
productsToValidate.add(feature.parentProduct);
|
|
300
311
|
return "stop";
|
|
301
312
|
});
|
|
@@ -435,7 +446,7 @@ export class SyncGroupsTransaction {
|
|
|
435
446
|
return change;
|
|
436
447
|
});
|
|
437
448
|
}
|
|
438
|
-
applySelectOneFeature(feature,
|
|
449
|
+
applySelectOneFeature(feature, userInitiated, featureDidJustComeIntoScope) {
|
|
439
450
|
const selectionType = feature.selectionType;
|
|
440
451
|
if (selectionType !== SelectionType.SelectOne) {
|
|
441
452
|
throw new Error("can only be used for selectOne");
|
|
@@ -453,7 +464,7 @@ export class SyncGroupsTransaction {
|
|
|
453
464
|
// Options with no default are never written
|
|
454
465
|
return false;
|
|
455
466
|
}
|
|
456
|
-
if (
|
|
467
|
+
if (userInitiated) {
|
|
457
468
|
// To make re-apply happen, even if it actually does not update the sync group
|
|
458
469
|
this.affectedSelectOneSyncGroups.add(syncCode);
|
|
459
470
|
}
|
|
@@ -464,7 +475,7 @@ export class SyncGroupsTransaction {
|
|
|
464
475
|
// can not be set to the current sync group value, then it will set in the opposite
|
|
465
476
|
// direction. Like if the sync group was empty. To avoid bouncing back and forth we will
|
|
466
477
|
// need to enforce that a sync group can only be updated once per transaction
|
|
467
|
-
if (!(
|
|
478
|
+
if (!(userInitiated ||
|
|
468
479
|
currentSyncGroupOptionCode === undefined ||
|
|
469
480
|
(featureDidJustComeIntoScope &&
|
|
470
481
|
feature.options.every((o) => currentSyncGroupOptionCode !== o.code)))) {
|
|
@@ -486,7 +497,7 @@ export class SyncGroupsTransaction {
|
|
|
486
497
|
}
|
|
487
498
|
return change;
|
|
488
499
|
}
|
|
489
|
-
applySelectManyOption(option,
|
|
500
|
+
applySelectManyOption(option, userInitiated) {
|
|
490
501
|
const feature = option.parent;
|
|
491
502
|
if (feature.selectionType !== SelectionType.SelectMany) {
|
|
492
503
|
throw new Error("can only be used for selectMany");
|
|
@@ -500,14 +511,14 @@ export class SyncGroupsTransaction {
|
|
|
500
511
|
}
|
|
501
512
|
const optionSelected = option.selected;
|
|
502
513
|
const currentSyncGroupValue = this.syncState.getForSelectMany(syncCode, option.code);
|
|
503
|
-
if (
|
|
514
|
+
if (userInitiated) {
|
|
504
515
|
// To make re-apply happen, even if it actually does not update the sync group
|
|
505
516
|
this.addSyncGroupAffectedForSelectMany(syncCode, option);
|
|
506
517
|
}
|
|
507
|
-
// We only initialize if the option
|
|
508
|
-
//
|
|
509
|
-
if (
|
|
510
|
-
!(
|
|
518
|
+
// We only initialize if the option has not been initiated or if it is userInitiated.
|
|
519
|
+
// userInitiated = active selection by the user.
|
|
520
|
+
if (currentSyncGroupValue !== undefined &&
|
|
521
|
+
!(userInitiated && currentSyncGroupValue !== optionSelected)) {
|
|
511
522
|
return false;
|
|
512
523
|
}
|
|
513
524
|
this.addSyncGroupAffectedForSelectMany(syncCode, option);
|
|
@@ -529,7 +540,9 @@ export class SyncGroupsTransaction {
|
|
|
529
540
|
}
|
|
530
541
|
function getAdditionalProducts(product) {
|
|
531
542
|
const initial = product.initial;
|
|
532
|
-
return product.target.additionalProducts
|
|
543
|
+
return product.target.additionalProducts
|
|
544
|
+
.filter((p) => p.selected)
|
|
545
|
+
.map((childTarget) => {
|
|
533
546
|
const refKey = childTarget.refKey;
|
|
534
547
|
const childInitial = initial === null || initial === void 0 ? void 0 : initial.additionalProducts.find((p) => refKey === p.refKey);
|
|
535
548
|
return {
|
|
@@ -558,8 +571,8 @@ function getOptions(feature) {
|
|
|
558
571
|
}
|
|
559
572
|
function pairFeatures(targets, initials) {
|
|
560
573
|
return targets.map((childTarget) => {
|
|
561
|
-
const
|
|
562
|
-
const childInitial = initials === null || initials === void 0 ? void 0 : initials.find((f) =>
|
|
574
|
+
const code = childTarget.code;
|
|
575
|
+
const childInitial = initials === null || initials === void 0 ? void 0 : initials.find((f) => code === f.code);
|
|
563
576
|
return {
|
|
564
577
|
target: childTarget._internal,
|
|
565
578
|
initial: childInitial === null || childInitial === void 0 ? void 0 : childInitial._internal,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Observable, SingleArgCallback } from "@configura/web-utilities";
|
|
2
|
-
import { CatalogueAPI, DtoAdditionalProductConfiguration, DtoExportStatus, DtoExportStatusStatus,
|
|
2
|
+
import { CatalogueAPI, DtoAdditionalProductConfiguration, DtoExportStatus, DtoExportStatusStatus, DtoProductParamsWithCidAndLang, DtoRenderStatus, DtoRenderStatusStatus, DtoTargetCameraArgs } from "../CatalogueAPI.js";
|
|
3
3
|
import { CfgProduct } from "../CfgProduct.js";
|
|
4
4
|
import { RenderOrExportFormat } from "./formats.js";
|
|
5
5
|
export declare type TasksChangeNotification = {
|
|
@@ -51,7 +51,7 @@ export declare abstract class Task<F extends RenderOrExportFormat> {
|
|
|
51
51
|
protected constructor(taskHandler: _TaskHandlerInternal, format: F, product: CfgProduct, getPreviewUrl: (() => Promise<string>) | undefined);
|
|
52
52
|
protected abstract postInit(): Promise<DtoRenderStatus | DtoExportStatus>;
|
|
53
53
|
protected abstract pollStatus(): Promise<DtoRenderStatus | DtoExportStatus>;
|
|
54
|
-
protected _productParams:
|
|
54
|
+
protected _productParams: DtoProductParamsWithCidAndLang;
|
|
55
55
|
protected _apiSelection: DtoAdditionalProductConfiguration;
|
|
56
56
|
private _status;
|
|
57
57
|
private _uuid;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DtoCatalogueParamsWithCidAndLang } from "../../CatalogueAPI.js";
|
|
2
2
|
import { CfgProduct } from "../../CfgProduct.js";
|
|
3
|
-
export declare const dummyCatId:
|
|
3
|
+
export declare const dummyCatId: DtoCatalogueParamsWithCidAndLang;
|
|
4
4
|
export declare const getDummyCfgProduct: () => Promise<CfgProduct>;
|
|
5
5
|
//# sourceMappingURL=dummyProductForTest.d.ts.map
|
|
@@ -254,6 +254,7 @@ export const cfgProductTest = (testFunc, prepFunc) => __awaiter(void 0, void 0,
|
|
|
254
254
|
uuid: "",
|
|
255
255
|
validated: true,
|
|
256
256
|
productData,
|
|
257
|
+
features: []
|
|
257
258
|
};
|
|
258
259
|
collect.pushNotification(`Validate ${params.enterprise} ${params.prdCat} ${params.prdCatVersion} ${params.priceList} ${params.vendor} ${params.partNumber}`);
|
|
259
260
|
return validateResponse;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { DtoAdditionalProductRef, DtoCatalogueParams,
|
|
1
|
+
import { DtoAdditionalProductRef, DtoCatalogueParams, DtoCatalogueParamsWithCid, DtoCatalogueParamsWithCidAndLang, DtoMeasureParam, DtoModel, DtoOrientation, DtoPartsData, DtoPrices, DtoProductData, DtoProductParamsWithCid, DtoProductParamsWithCidAndLang, DtoProductResponse, DtoSelectedOption, DtoTransform, DtoValidateResponse, DtoVector } from "./CatalogueAPI.js";
|
|
2
2
|
/**
|
|
3
3
|
* Makes a string from the params which can be used as a key in for example React. Language is not respected.
|
|
4
4
|
*/
|
|
5
|
-
export declare const makeCatalogueKey: (cat:
|
|
5
|
+
export declare const makeCatalogueKey: (cat: DtoCatalogueParamsWithCid) => string;
|
|
6
6
|
/**
|
|
7
7
|
* Makes a string from the params which can be used as a key in for example React. Language is not respected.
|
|
8
8
|
*/
|
|
9
|
-
export declare const makeProductKey: (prod:
|
|
9
|
+
export declare const makeProductKey: (prod: DtoProductParamsWithCid) => string;
|
|
10
10
|
/**
|
|
11
11
|
* Makes a string from selected options, can be used as a key for a selection.
|
|
12
12
|
*/
|
|
@@ -18,6 +18,11 @@ export declare type CfgProductData = Omit<Omit<DtoProductData, "models">, "parts
|
|
|
18
18
|
selOptions: DtoSelectedOption[];
|
|
19
19
|
};
|
|
20
20
|
};
|
|
21
|
+
/**
|
|
22
|
+
* Deep compare. Uses the JSON.stringify method for comparison
|
|
23
|
+
* @returns true if equal. Key and array order is respected.
|
|
24
|
+
*/
|
|
25
|
+
export declare function compareCfgProductData(pd1: CfgProductData, pd2: CfgProductData): boolean;
|
|
21
26
|
export declare type CfgProductResponse = Omit<DtoProductResponse, "productData"> & {
|
|
22
27
|
productData: CfgProductData;
|
|
23
28
|
};
|
|
@@ -27,17 +32,17 @@ export declare type CfgValidateResponse = Omit<DtoValidateResponse, "productData
|
|
|
27
32
|
};
|
|
28
33
|
export declare function isModel(arg: unknown): arg is DtoModel;
|
|
29
34
|
/** Replace empty strings with "-" for compatibility with the API. */
|
|
30
|
-
export declare function correctDefaultsOnCatalogueParams<T extends
|
|
35
|
+
export declare function correctDefaultsOnCatalogueParams<T extends DtoCatalogueParams>(catId: T): T;
|
|
31
36
|
export declare function recursivelyGetPriceCodeValue(priceCodes: string[], prices: DtoPrices | undefined): number | undefined;
|
|
32
37
|
export declare function comparePricesObjects(prices1: DtoPrices | undefined, prices2: DtoPrices | undefined): boolean;
|
|
33
|
-
export declare const decodeCatalogueParams: <T extends
|
|
34
|
-
export declare const decodeProductParams: <T extends
|
|
35
|
-
export declare function isSameCatalogueParams(left:
|
|
38
|
+
export declare const decodeCatalogueParams: <T extends DtoCatalogueParams>(params: T) => T;
|
|
39
|
+
export declare const decodeProductParams: <T extends DtoProductParamsWithCid>(params: T) => T;
|
|
40
|
+
export declare function isSameCatalogueParams(left: DtoCatalogueParams, right: DtoCatalogueParams): boolean;
|
|
36
41
|
export declare function isSameVector(left: DtoVector, right: DtoVector): boolean;
|
|
37
42
|
export declare function isSameOrientation(left: DtoOrientation, right: DtoOrientation): boolean;
|
|
38
43
|
export declare function isSameAnchor(left: DtoMeasureParam, right: DtoMeasureParam): boolean;
|
|
39
44
|
export declare function isSameTransform(left: DtoTransform, right: DtoTransform): boolean;
|
|
40
45
|
export declare function isSameProductRef(left: DtoAdditionalProductRef, right: DtoAdditionalProductRef): boolean;
|
|
41
|
-
export declare const isSameDtoCatalogueParamsWithLang: (left:
|
|
42
|
-
export declare const isSameDtoProductParamsWithLang: (left:
|
|
46
|
+
export declare const isSameDtoCatalogueParamsWithLang: (left: DtoCatalogueParamsWithCidAndLang, right: DtoCatalogueParamsWithCidAndLang) => boolean;
|
|
47
|
+
export declare const isSameDtoProductParamsWithLang: (left: DtoProductParamsWithCidAndLang, right: DtoProductParamsWithCidAndLang) => boolean;
|
|
43
48
|
//# sourceMappingURL=utilitiesCatalogueData.d.ts.map
|
|
@@ -25,6 +25,13 @@ export const makeSelOptionsKey = (options) => options.reduce((p, option) => {
|
|
|
25
25
|
p += "_}";
|
|
26
26
|
return p;
|
|
27
27
|
}, "");
|
|
28
|
+
/**
|
|
29
|
+
* Deep compare. Uses the JSON.stringify method for comparison
|
|
30
|
+
* @returns true if equal. Key and array order is respected.
|
|
31
|
+
*/
|
|
32
|
+
export function compareCfgProductData(pd1, pd2) {
|
|
33
|
+
return JSON.stringify(pd1) === JSON.stringify(pd2);
|
|
34
|
+
}
|
|
28
35
|
export function isModel(arg) {
|
|
29
36
|
return typeof arg === "object" && arg !== null && "cid" in arg && "uri" in arg;
|
|
30
37
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DtoCatalogueParamsWithCid, DtoCataloguePermission } from "./CatalogueAPI.js";
|
|
2
2
|
interface CataloguePermissionByEnterpriseKey {
|
|
3
3
|
[key: string]: DtoCataloguePermission[];
|
|
4
4
|
}
|
|
5
5
|
export declare const groupAndSortCataloguePermissions: (cataloguePermissions: DtoCataloguePermission[]) => CataloguePermissionByEnterpriseKey;
|
|
6
6
|
export declare const isParamSet: (param: string | undefined) => boolean;
|
|
7
|
-
export declare const createCataloguePermissionsFilter: (catParams: Partial<
|
|
7
|
+
export declare const createCataloguePermissionsFilter: (catParams: Partial<DtoCatalogueParamsWithCid>) => (perm: DtoCataloguePermission) => boolean;
|
|
8
8
|
/**
|
|
9
9
|
* Sometimes you will want to use the latest available prdCatVersion. This method will
|
|
10
10
|
* find the highest prdCatVersion version in the cataloguePermissions. If the versions are
|
|
@@ -25,7 +25,7 @@ export declare const getPrdCatVersionFromPermissions: (cataloguePermissions: Dto
|
|
|
25
25
|
* @param auth
|
|
26
26
|
* @param params
|
|
27
27
|
*/
|
|
28
|
-
export declare const getPrdCatVersionOrLatestFromPermissions: (params:
|
|
28
|
+
export declare const getPrdCatVersionOrLatestFromPermissions: (params: DtoCatalogueParamsWithCid, cataloguePermissions: DtoCataloguePermission[]) => string;
|
|
29
29
|
/**
|
|
30
30
|
* Sometimes you will want a missing prdCatVersion to represent "Get the current highest version".
|
|
31
31
|
* This method will, if the prdCatVersion is not set, fetch the highest available from the
|
|
@@ -34,6 +34,6 @@ export declare const getPrdCatVersionOrLatestFromPermissions: (params: DtoCatalo
|
|
|
34
34
|
* @param auth
|
|
35
35
|
* @param params
|
|
36
36
|
*/
|
|
37
|
-
export declare const fillMissingPrdCatVersionFromPermissions: <T extends
|
|
37
|
+
export declare const fillMissingPrdCatVersionFromPermissions: <T extends DtoCatalogueParamsWithCid>(params: T, cataloguePermissions: DtoCataloguePermission[]) => T;
|
|
38
38
|
export {};
|
|
39
39
|
//# sourceMappingURL=utilitiesCataloguePermission.d.ts.map
|