@configura/web-api 2.0.0 → 2.1.0-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/CatalogueAPI.d.ts +10 -0
- package/dist/CfgProduct.d.ts +1 -1
- package/dist/CfgProduct.js +7 -8
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/io/CfgHistoryToProdConfConnector.js +2 -2
- package/dist/io/CfgIOProdConfConnector.d.ts +1 -11
- package/dist/io/CfgIOProdConfConnector.js +1 -13
- package/dist/io/CfgObservableStateToProdConfConnector.d.ts +2 -1
- package/dist/io/CfgObservableStateToProdConfConnector.js +2 -1
- package/dist/io/CfgWindowMessageToProdConfConnector.d.ts +2 -1
- package/dist/io/CfgWindowMessageToProdConfConnector.js +2 -1
- package/dist/productConfiguration/CfgFeature.d.ts +8 -1
- package/dist/productConfiguration/CfgFeature.js +30 -2
- package/dist/productConfiguration/CfgOption.d.ts +5 -2
- package/dist/productConfiguration/CfgOption.js +22 -2
- package/dist/productConfiguration/CfgProductConfiguration.d.ts +4 -3
- package/dist/productConfiguration/CfgProductConfiguration.js +20 -5
- package/dist/productConfiguration/filters.d.ts +5 -3
- package/dist/productConfiguration/filters.js +94 -23
- package/dist/tasks/TaskHandler.js +1 -1
- package/dist/tests/testData/testDataConstraints.d.ts +4 -0
- package/dist/tests/testData/testDataConstraints.js +174 -0
- package/dist/{ConfigurationConverter.d.ts → utilitiesConfiguration.d.ts} +13 -2
- package/dist/{ConfigurationConverter.js → utilitiesConfiguration.js} +36 -11
- package/package.json +3 -3
package/dist/CatalogueAPI.d.ts
CHANGED
|
@@ -300,9 +300,19 @@ export interface DtoPartsData {
|
|
|
300
300
|
listPrice: number;
|
|
301
301
|
pkgCount: number;
|
|
302
302
|
selOptions: Array<DtoPartsSelectedOption>;
|
|
303
|
+
constrOptions?: Array<DtoPartsConstrainedOption>;
|
|
303
304
|
styleNr: string;
|
|
304
305
|
prices?: DtoPrices;
|
|
305
306
|
}
|
|
307
|
+
/** PartsConstrainedOption */
|
|
308
|
+
export interface DtoPartsConstrainedOption {
|
|
309
|
+
code: string;
|
|
310
|
+
feature: string;
|
|
311
|
+
constrOptions?: Array<string>;
|
|
312
|
+
next?: {
|
|
313
|
+
[index: string]: DtoPartsConstrainedOption;
|
|
314
|
+
};
|
|
315
|
+
}
|
|
306
316
|
/** PartsSelectedOption */
|
|
307
317
|
export interface DtoPartsSelectedOption {
|
|
308
318
|
code: string;
|
package/dist/CfgProduct.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { AggregatedLoadingObservable, LengthUnit, Observable, SingleArgCallback } from "@configura/web-utilities";
|
|
2
2
|
import { DtoAdditionalProductConfiguration, DtoAdditionalProductRef, DtoCatalogueParamsWithCid, DtoMeasureParam, DtoMiscFile, DtoMtrlApplication, DtoNote, DtoPrices, DtoProductConf, DtoProductParamsWithCidAndLang, DtoTransform } from "./CatalogueAPI.js";
|
|
3
3
|
import { CfgMeasureDefinition } from "./CfgMeasure.js";
|
|
4
|
-
import { CfgProdConfParts } from "./index.js";
|
|
5
4
|
import { _CfgFeatureInternal } from "./productConfiguration/CfgFeature.js";
|
|
6
5
|
import { ProductConfigurationBubbleMode } from "./productConfiguration/CfgOption.js";
|
|
7
6
|
import { CfgProductConfiguration } from "./productConfiguration/CfgProductConfiguration.js";
|
|
@@ -9,6 +8,7 @@ import { ProductLoader } from "./productLoader.js";
|
|
|
9
8
|
import { SyncGroupsApplyMode } from "./syncGroups/SyncGroupsApplyMode.js";
|
|
10
9
|
import { SyncGroupsHandler } from "./syncGroups/SyncGroupsHandler.js";
|
|
11
10
|
import { CfgProductData, RootNodeSource } from "./utilitiesCatalogueData.js";
|
|
11
|
+
import { CfgProdConfParts } from "./utilitiesConfiguration.js";
|
|
12
12
|
/**
|
|
13
13
|
* @freshRef a new pointer to the same product, backed by the same original object
|
|
14
14
|
* @committed false is an indication that this is a potentially transient state. It could
|
package/dist/CfgProduct.js
CHANGED
|
@@ -9,14 +9,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import { AggregatedLoadingObservable, assert, assertDefined, augmentErrorMessage, compareArrays, count, Observable, toLengthUnit, } from "@configura/web-utilities";
|
|
11
11
|
import { CfgMeasureDefinition } from "./CfgMeasure.js";
|
|
12
|
-
import { convertDtoProductConfToV1, isAdditionalProductConfiguration, isProductConf, } from "./ConfigurationConverter.js";
|
|
13
|
-
import { CfgProdConfParts } from "./index.js";
|
|
14
12
|
import { ProductConfigurationBubbleMode } from "./productConfiguration/CfgOption.js";
|
|
15
13
|
import { CfgProductConfiguration } from "./productConfiguration/CfgProductConfiguration.js";
|
|
16
14
|
import { collectAdditionalProductRefs } from "./productConfiguration/utilitiesProductConfiguration.js";
|
|
17
15
|
import { wrapWithCache } from "./productLoader.js";
|
|
18
16
|
import { SyncGroupsHandler } from "./syncGroups/SyncGroupsHandler.js";
|
|
19
17
|
import { compareCfgProductData, correctDefaultsOnCatalogueParams, isSameCatalogueParams, isSameProductRef, makeProductKey, } from "./utilitiesCatalogueData.js";
|
|
18
|
+
import { CfgProdConfParts, convertDtoProductConfToV1, isAdditionalProductConfiguration, isProductConf, } from "./utilitiesConfiguration.js";
|
|
20
19
|
function completeSettings(incompleteSettings) {
|
|
21
20
|
var _a;
|
|
22
21
|
return {
|
|
@@ -53,7 +52,7 @@ function isDescriptionMatch(l, r) {
|
|
|
53
52
|
* the class that should be used and interacted with.
|
|
54
53
|
*/
|
|
55
54
|
export class _CfgProductInternal {
|
|
56
|
-
constructor(initSuccess, initFail, _productLoaderRaw, prodParams, settings, optional, selected, rootFeatureRefs, rawFeatures, notes, uuid, _rawUnit, _rawProductData, apiSelection, loadingObservable, parent, root, _additionalProductRef, _syncGroupHandler) {
|
|
55
|
+
constructor(initSuccess, initFail, _productLoaderRaw, prodParams, settings, optional, selected, rootFeatureRefs, rawFeatures, notes, uuid, _rawUnit, _rawProductData, apiSelection, apiConstraints, loadingObservable, parent, root, _additionalProductRef, _syncGroupHandler) {
|
|
57
56
|
var _a;
|
|
58
57
|
this._productLoaderRaw = _productLoaderRaw;
|
|
59
58
|
this.prodParams = prodParams;
|
|
@@ -236,7 +235,7 @@ export class _CfgProductInternal {
|
|
|
236
235
|
}
|
|
237
236
|
}
|
|
238
237
|
}
|
|
239
|
-
const configurationChange = yield this.configuration._internal.setApiSelection(productConfiguration.selOptions, false);
|
|
238
|
+
const configurationChange = yield this.configuration._internal.setApiSelection(productConfiguration.selOptions, sourceProduct === null || sourceProduct === void 0 ? void 0 : sourceProduct._rawProductData.partsData.constrOptions, false);
|
|
240
239
|
if (configurationChange) {
|
|
241
240
|
change = true;
|
|
242
241
|
}
|
|
@@ -394,7 +393,7 @@ export class _CfgProductInternal {
|
|
|
394
393
|
if (rootFeatureRefs !== undefined) {
|
|
395
394
|
configuration._internal.populateFeatures(rootFeatureRefs);
|
|
396
395
|
}
|
|
397
|
-
yield configuration._internal.setApiSelection(productData.partsData.selOptions || [], false);
|
|
396
|
+
yield configuration._internal.setApiSelection(productData.partsData.selOptions || [], productData.partsData.constrOptions, false);
|
|
398
397
|
yield this._syncAndLoadAdditionalProducts(productLoader, undefined);
|
|
399
398
|
if (this._destroyed) {
|
|
400
399
|
return false;
|
|
@@ -487,7 +486,7 @@ export class _CfgProductInternal {
|
|
|
487
486
|
if (notes !== undefined) {
|
|
488
487
|
this.addNotes(notes);
|
|
489
488
|
}
|
|
490
|
-
this._configuration = CfgProductConfiguration.make(initSuccess, initFail, rootFeatureRefs, rawFeatures, apiSelection, this, this.root);
|
|
489
|
+
this._configuration = CfgProductConfiguration.make(initSuccess, initFail, rootFeatureRefs, rawFeatures, apiSelection, apiConstraints, this, this.root);
|
|
491
490
|
}
|
|
492
491
|
get selected() {
|
|
493
492
|
return this._selected !== false;
|
|
@@ -504,7 +503,7 @@ export class _CfgProductInternal {
|
|
|
504
503
|
var _a;
|
|
505
504
|
const p = new _CfgProductInternal(() => {
|
|
506
505
|
initSuccess(p);
|
|
507
|
-
}, initFail, this._productLoaderRaw, this.prodParams, this.settings, this.optional, this.selected, this._configuration.rootFeatureRefs, this._configuration.rawFeatures, this._notes.values(), this.uuid, this._rawUnit, this._rawProductData, this.configuration._internal.getApiSelection(), new AggregatedLoadingObservable(), parent, root, this._additionalProductRef, (_a = this._syncGroupHandler) === null || _a === void 0 ? void 0 : _a.clone());
|
|
506
|
+
}, initFail, this._productLoaderRaw, this.prodParams, this.settings, this.optional, this.selected, this._configuration.rootFeatureRefs, this._configuration.rawFeatures, this._notes.values(), this.uuid, this._rawUnit, this._rawProductData, this.configuration._internal.getApiSelection(), this.configuration._internal.getApiConstrained(), new AggregatedLoadingObservable(), parent, root, this._additionalProductRef, (_a = this._syncGroupHandler) === null || _a === void 0 ? void 0 : _a.clone());
|
|
508
507
|
});
|
|
509
508
|
for (const additionalProduct of this.additionalProducts) {
|
|
510
509
|
product.additionalProducts.push(CfgProduct._makeNewRefFrom(yield additionalProduct._internal.clone(product, root || product)));
|
|
@@ -757,7 +756,7 @@ prodParams, settings, optional, loadingObservable, parent, root, additionalProdu
|
|
|
757
756
|
// But we can not set the api selection synchronously. And the product configuration needs "this". So we use this callback.
|
|
758
757
|
// Feel free to find a nicer more readable solution :)
|
|
759
758
|
initSuccess(p);
|
|
760
|
-
}, initFail, productLoaderRaw, prodParams, settings, optional, initiallySelected, rootFeatureRefs !== null && rootFeatureRefs !== void 0 ? rootFeatureRefs : [], rawFeatures, notes === null || notes === void 0 ? void 0 : notes.values(), uuid, unit, productData, (_a = productData.partsData.selOptions) !== null && _a !== void 0 ? _a : [], loadingObservable, parent, root, additionalProductRef, syncGroupHandler);
|
|
759
|
+
}, initFail, productLoaderRaw, prodParams, settings, optional, initiallySelected, rootFeatureRefs !== null && rootFeatureRefs !== void 0 ? rootFeatureRefs : [], rawFeatures, notes === null || notes === void 0 ? void 0 : notes.values(), uuid, unit, productData, (_a = productData.partsData.selOptions) !== null && _a !== void 0 ? _a : [], productData.partsData.constrOptions, loadingObservable, parent, root, additionalProductRef, syncGroupHandler);
|
|
761
760
|
});
|
|
762
761
|
yield product._syncAndLoadAdditionalProducts(productLoaderForGroupedLoad, initialProductConfigurationV1);
|
|
763
762
|
product._initialClone = yield product.clone();
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export * from "./CatalogueAPI.js";
|
|
2
2
|
export * from "./CfgProduct.js";
|
|
3
3
|
export * from "./CfgReferencePathHelper.js";
|
|
4
|
-
export * from "./ConfigurationConverter.js";
|
|
5
4
|
export * from "./io/index.js";
|
|
6
5
|
export * from "./material/CfgMaterialMapping.js";
|
|
7
6
|
export * from "./material/CfgMtrlApplication.js";
|
|
@@ -16,9 +15,11 @@ export * from "./productConfiguration/productParamsGenerator.js";
|
|
|
16
15
|
export * from "./productLoader.js";
|
|
17
16
|
export * from "./syncGroups/SyncGroupsApplyMode.js";
|
|
18
17
|
export * from "./syncGroups/SyncGroupsHandler.js";
|
|
18
|
+
export * from "./syncGroups/SyncGroupsPathHelper.js";
|
|
19
19
|
export * from "./tasks/formats.js";
|
|
20
20
|
export * from "./tasks/TaskHandler.js";
|
|
21
21
|
export * from "./utilitiesCatalogueData.js";
|
|
22
22
|
export * from "./utilitiesCataloguePermission.js";
|
|
23
|
+
export * from "./utilitiesConfiguration.js";
|
|
23
24
|
export * from "./utilitiesNumericValues.js";
|
|
24
25
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export * from "./CatalogueAPI.js";
|
|
2
2
|
export * from "./CfgProduct.js";
|
|
3
3
|
export * from "./CfgReferencePathHelper.js";
|
|
4
|
-
export * from "./ConfigurationConverter.js";
|
|
5
4
|
export * from "./io/index.js";
|
|
6
5
|
export * from "./material/CfgMaterialMapping.js";
|
|
7
6
|
export * from "./material/CfgMtrlApplication.js";
|
|
@@ -16,8 +15,10 @@ export * from "./productConfiguration/productParamsGenerator.js";
|
|
|
16
15
|
export * from "./productLoader.js";
|
|
17
16
|
export * from "./syncGroups/SyncGroupsApplyMode.js";
|
|
18
17
|
export * from "./syncGroups/SyncGroupsHandler.js";
|
|
18
|
+
export * from "./syncGroups/SyncGroupsPathHelper.js";
|
|
19
19
|
export * from "./tasks/formats.js";
|
|
20
20
|
export * from "./tasks/TaskHandler.js";
|
|
21
21
|
export * from "./utilitiesCatalogueData.js";
|
|
22
22
|
export * from "./utilitiesCataloguePermission.js";
|
|
23
|
+
export * from "./utilitiesConfiguration.js";
|
|
23
24
|
export * from "./utilitiesNumericValues.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { augmentErrorMessage } from "@configura/web-utilities";
|
|
2
|
-
import { compactStringToDtoProductConf, dtoProductConfigurationToCompactString, } from "../
|
|
2
|
+
import { CfgProdConfParts, compactStringToDtoProductConf, dtoProductConfigurationToCompactString, } from "../utilitiesConfiguration.js";
|
|
3
3
|
import { CfgHistoryManager } from "./CfgHistoryManager.js";
|
|
4
|
-
import { CfgIOProdConfConnector, CfgProdConfMessageVersions,
|
|
4
|
+
import { CfgIOProdConfConnector, CfgProdConfMessageVersions, getHighestVersionProdConfMessage, isCfgProdConfMessageV2, STAGE_PROD_CONF_MESSAGE_KEY, } from "./CfgIOProdConfConnector.js";
|
|
5
5
|
/**
|
|
6
6
|
* Instantiating this will make the browser history (and URL) update with the product configuration.
|
|
7
7
|
*/
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DtoAdditionalProductConfiguration, DtoProductConf } from "../CatalogueAPI.js";
|
|
2
2
|
import { CfgProduct, CfgProductChangeNotification } from "../CfgProduct.js";
|
|
3
|
+
import { CfgProdConfParts } from "../utilitiesConfiguration.js";
|
|
3
4
|
import { CfgIOManager } from "./CfgIOManager.js";
|
|
4
5
|
import { CfgIOWarningSupplier } from "./CfgIOWarningSupplier.js";
|
|
5
6
|
export declare const isCfgProdConfMessage: (data: unknown) => data is CfgProdConfMessageV1 | CfgProdConfMessageV2;
|
|
@@ -22,17 +23,6 @@ export declare enum CfgProdConfMessageVersions {
|
|
|
22
23
|
V1dot0 = 1,
|
|
23
24
|
V2dot0 = 2
|
|
24
25
|
}
|
|
25
|
-
/**
|
|
26
|
-
* @param ExtendedData Includes extra data, i.e. units and groupCodes
|
|
27
|
-
* @param ProductParams Includes what Product this was generated for, and the same for any Additional Products.
|
|
28
|
-
* @param SyncGroupState Includes the current sync group state
|
|
29
|
-
*/
|
|
30
|
-
export declare enum CfgProdConfParts {
|
|
31
|
-
NoExtra = 0,
|
|
32
|
-
ExtendedData = 1,
|
|
33
|
-
ProdParams = 2,
|
|
34
|
-
SyncGroupState = 4
|
|
35
|
-
}
|
|
36
26
|
export declare const STAGE_PROD_CONF_MESSAGE_KEY = "stageprodconf";
|
|
37
27
|
declare type ProdConfMessageCallback = (message: CfgProdConfMessage) => Promise<void>;
|
|
38
28
|
declare type ProdConfCallback = (conf: DtoProductConf) => Promise<void>;
|
|
@@ -7,7 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import { convertDtoProductConfToV1 } from "../
|
|
10
|
+
import { convertDtoProductConfToV1 } from "../utilitiesConfiguration.js";
|
|
11
11
|
export const isCfgProdConfMessage = (data) => typeof data === "object" && data !== null && "version" in data && "conf" in data;
|
|
12
12
|
export const isCfgProdConfMessageV1 = (data) => isCfgProdConfMessage(data) && data.version === "1.0";
|
|
13
13
|
export const isCfgProdConfMessageV2 = (data) => isCfgProdConfMessage(data) && data.version === "2.0";
|
|
@@ -19,18 +19,6 @@ export var CfgProdConfMessageVersions;
|
|
|
19
19
|
CfgProdConfMessageVersions[CfgProdConfMessageVersions["V1dot0"] = 1] = "V1dot0";
|
|
20
20
|
CfgProdConfMessageVersions[CfgProdConfMessageVersions["V2dot0"] = 2] = "V2dot0";
|
|
21
21
|
})(CfgProdConfMessageVersions || (CfgProdConfMessageVersions = {}));
|
|
22
|
-
/**
|
|
23
|
-
* @param ExtendedData Includes extra data, i.e. units and groupCodes
|
|
24
|
-
* @param ProductParams Includes what Product this was generated for, and the same for any Additional Products.
|
|
25
|
-
* @param SyncGroupState Includes the current sync group state
|
|
26
|
-
*/
|
|
27
|
-
export var CfgProdConfParts;
|
|
28
|
-
(function (CfgProdConfParts) {
|
|
29
|
-
CfgProdConfParts[CfgProdConfParts["NoExtra"] = 0] = "NoExtra";
|
|
30
|
-
CfgProdConfParts[CfgProdConfParts["ExtendedData"] = 1] = "ExtendedData";
|
|
31
|
-
CfgProdConfParts[CfgProdConfParts["ProdParams"] = 2] = "ProdParams";
|
|
32
|
-
CfgProdConfParts[CfgProdConfParts["SyncGroupState"] = 4] = "SyncGroupState";
|
|
33
|
-
})(CfgProdConfParts || (CfgProdConfParts = {}));
|
|
34
22
|
export const STAGE_PROD_CONF_MESSAGE_KEY = "stageprodconf";
|
|
35
23
|
/**
|
|
36
24
|
* Base class for connecting the product configuration to an IO channel
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DtoProductConf } from "../CatalogueAPI.js";
|
|
2
|
-
import {
|
|
2
|
+
import { CfgProdConfParts } from "../utilitiesConfiguration.js";
|
|
3
|
+
import { CfgIOProdConfConnector, CfgProdConfMessage, CfgProdConfMessageVersions } from "./CfgIOProdConfConnector.js";
|
|
3
4
|
import { CfgObservableStateManager } from "./CfgObservableStateManager.js";
|
|
4
5
|
/**
|
|
5
6
|
* Instantiating this will make the observable state update with the product configuration.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CfgProdConfParts } from "../utilitiesConfiguration.js";
|
|
2
|
+
import { CfgIOProdConfConnector, CfgProdConfMessageVersions, } from "./CfgIOProdConfConnector.js";
|
|
2
3
|
/**
|
|
3
4
|
* Instantiating this will make the observable state update with the product configuration.
|
|
4
5
|
* @param sendVersions What versions of the productConfiguration shall be sent? Multiple can be selected
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DtoProductConf } from "../CatalogueAPI.js";
|
|
2
|
-
import {
|
|
2
|
+
import { CfgProdConfParts } from "../utilitiesConfiguration.js";
|
|
3
|
+
import { CfgIOProdConfConnector, CfgProdConfMessage, CfgProdConfMessageVersions } from "./CfgIOProdConfConnector.js";
|
|
3
4
|
import { CfgWindowMessageManager } from "./CfgWindowMessageManager.js";
|
|
4
5
|
/**
|
|
5
6
|
* Instantiating this will make Stage send product configuration changes using the post message-API.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CfgProdConfParts } from "../utilitiesConfiguration.js";
|
|
2
|
+
import { CfgIOProdConfConnector, CfgProdConfMessageVersions, } from "./CfgIOProdConfConnector.js";
|
|
2
3
|
/**
|
|
3
4
|
* Instantiating this will make Stage send product configuration changes using the post message-API.
|
|
4
5
|
* It will also make Stage listen for incoming product configuration update messages.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LengthUnit, Observable, SingleArgCallback } from "@configura/web-utilities";
|
|
2
|
-
import { DtoFeature, DtoFeatureConf, DtoNote, DtoSelectedOption, DtoSyncGroup, DtoSyncGroupMethods } from "../CatalogueAPI.js";
|
|
2
|
+
import { DtoFeature, DtoFeatureConf, DtoNote, DtoPartsConstrainedOption, DtoSelectedOption, DtoSyncGroup, DtoSyncGroupMethods } from "../CatalogueAPI.js";
|
|
3
3
|
import { CfgProduct, _CfgProductInternal } from "../CfgProduct.js";
|
|
4
4
|
import { CfgMtrlApplication } from "../material/CfgMtrlApplication.js";
|
|
5
5
|
import { SyncCode } from "../syncGroups/SyncGroupsHandler.js";
|
|
@@ -43,6 +43,7 @@ export declare class _CfgFeatureInternal {
|
|
|
43
43
|
readonly selectionType: SelectionType;
|
|
44
44
|
private _options;
|
|
45
45
|
private readonly _selectedOptions;
|
|
46
|
+
private readonly _constrainedOptions;
|
|
46
47
|
private _mtrlApplications;
|
|
47
48
|
readonly hasUpcharge: boolean;
|
|
48
49
|
readonly changeObservable: Observable<FeatureChangeNotification>;
|
|
@@ -106,7 +107,12 @@ export declare class _CfgFeatureInternal {
|
|
|
106
107
|
getDtoConf: (includeExtendedData: boolean) => DtoFeatureConf;
|
|
107
108
|
setApiSelection: (apiOptionSelectionMap: {
|
|
108
109
|
[index: string]: DtoSelectedOption;
|
|
110
|
+
} | undefined, apiOptionConstraintMap: {
|
|
111
|
+
[index: string]: DtoPartsConstrainedOption;
|
|
109
112
|
} | undefined) => Promise<boolean>;
|
|
113
|
+
addForApiConstrained: (next: {
|
|
114
|
+
[key: string]: DtoPartsConstrainedOption;
|
|
115
|
+
}) => void;
|
|
110
116
|
/** Pushes to refresh stretch. Does not cause validation. */
|
|
111
117
|
pushStretch: () => Promise<boolean>;
|
|
112
118
|
structureCompare: (other: _CfgFeatureInternal, strictOrder?: boolean, descriptionMatch?: boolean) => boolean;
|
|
@@ -119,6 +125,7 @@ export declare class _CfgFeatureInternal {
|
|
|
119
125
|
*/
|
|
120
126
|
selectOption: (optionInternal: _CfgOptionInternal, on: boolean, bubbleMode: ProductConfigurationBubbleMode) => Promise<boolean>;
|
|
121
127
|
isSelected: (option: _CfgOptionInternal) => boolean;
|
|
128
|
+
isDisabled: (option: _CfgOptionInternal) => boolean;
|
|
122
129
|
keyMatch: (other: _CfgFeatureInternal, descriptionMatch?: boolean) => boolean;
|
|
123
130
|
/** Only in selected options */
|
|
124
131
|
_getFeaturesWithCode: (code: string) => _CfgFeatureInternal[];
|
|
@@ -72,6 +72,7 @@ export class _CfgFeatureInternal {
|
|
|
72
72
|
this.parentProduct = parentProduct;
|
|
73
73
|
this.rootProduct = rootProduct;
|
|
74
74
|
this._selectedOptions = [];
|
|
75
|
+
this._constrainedOptions = [];
|
|
75
76
|
this.changeObservable = new Observable();
|
|
76
77
|
this.setNumericValue = (val) => __awaiter(this, void 0, void 0, function* () {
|
|
77
78
|
if (this.selectionType !== SelectionType.SelectOne) {
|
|
@@ -114,6 +115,7 @@ export class _CfgFeatureInternal {
|
|
|
114
115
|
}
|
|
115
116
|
yield this._notifyAllOfChange(bubbleMode, committed);
|
|
116
117
|
});
|
|
118
|
+
// Keep in sync with stripExtendedDataFromDtoFeatureConf
|
|
117
119
|
this.getDtoConf = (includeExtendedData) => {
|
|
118
120
|
const result = {
|
|
119
121
|
code: this.code,
|
|
@@ -134,7 +136,8 @@ export class _CfgFeatureInternal {
|
|
|
134
136
|
// way around. For that reason the get-method above uses the new format, and the set-method
|
|
135
137
|
// below the old format. As these functions are meant to only be used internally this should't
|
|
136
138
|
// cause too much confusion.
|
|
137
|
-
this.setApiSelection = (apiOptionSelectionMap) => __awaiter(this, void 0, void 0, function* () {
|
|
139
|
+
this.setApiSelection = (apiOptionSelectionMap, apiOptionConstraintMap) => __awaiter(this, void 0, void 0, function* () {
|
|
140
|
+
var _a, _b;
|
|
138
141
|
const selectionType = this.selectionType;
|
|
139
142
|
const isGroup = selectionType === SelectionType.Group;
|
|
140
143
|
const isSelectOne = selectionType === SelectionType.SelectOne;
|
|
@@ -149,11 +152,29 @@ export class _CfgFeatureInternal {
|
|
|
149
152
|
options = this.options; // This will generate all children
|
|
150
153
|
}
|
|
151
154
|
let change = false;
|
|
155
|
+
const constraintMap = apiOptionConstraintMap !== null && apiOptionConstraintMap !== void 0 ? apiOptionConstraintMap : {};
|
|
156
|
+
// The first value that belongs to this features options is used as the key to look up constrained options
|
|
157
|
+
const featureConstrainedOptions = (_b = (_a = options.map((o) => constraintMap[o.code]).find((o) => !!o)) === null || _a === void 0 ? void 0 : _a.constrOptions) !== null && _b !== void 0 ? _b : [];
|
|
152
158
|
for (let i = 0; i < options.length; i++) {
|
|
153
159
|
const option = options[i];
|
|
154
160
|
const apiOptionSelection = apiOptionSelectionMap[option.code];
|
|
161
|
+
const isConstrained = featureConstrainedOptions.indexOf(option.code) >= 0;
|
|
155
162
|
const selectedIndex = this._selectedOptions.findIndex(getOptionFilter(option._internal));
|
|
163
|
+
const constrainedIndex = this._constrainedOptions.findIndex(getOptionFilter(option._internal));
|
|
156
164
|
const isOn = isGroup || apiOptionSelection;
|
|
165
|
+
if (isConstrained) {
|
|
166
|
+
if (constrainedIndex === -1) {
|
|
167
|
+
doFreshRefOptionAtIndex(options, i, committed, (freshRef) => this._constrainedOptions.push(freshRef));
|
|
168
|
+
change = true;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
if (constrainedIndex !== -1) {
|
|
173
|
+
this._constrainedOptions.splice(constrainedIndex, 1);
|
|
174
|
+
doFreshRefOptionAtIndex(options, i, committed);
|
|
175
|
+
change = true;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
157
178
|
if (isOn) {
|
|
158
179
|
if (isSelectOne) {
|
|
159
180
|
if (this.isUseNumericValue) {
|
|
@@ -188,7 +209,7 @@ export class _CfgFeatureInternal {
|
|
|
188
209
|
change = true;
|
|
189
210
|
}
|
|
190
211
|
}
|
|
191
|
-
if (yield option._internal.setApiSelection(apiOptionSelection)) {
|
|
212
|
+
if (yield option._internal.setApiSelection(apiOptionSelection, constraintMap[option.code])) {
|
|
192
213
|
change = true;
|
|
193
214
|
}
|
|
194
215
|
}
|
|
@@ -221,6 +242,12 @@ export class _CfgFeatureInternal {
|
|
|
221
242
|
}
|
|
222
243
|
return change;
|
|
223
244
|
});
|
|
245
|
+
this.addForApiConstrained = (next) => {
|
|
246
|
+
const constrOptions = this._constrainedOptions;
|
|
247
|
+
for (const so of this._selectedOptions) {
|
|
248
|
+
next[so.code] = so._internal.getApiConstrained(constrOptions);
|
|
249
|
+
}
|
|
250
|
+
};
|
|
224
251
|
/** Pushes to refresh stretch. Does not cause validation. */
|
|
225
252
|
this.pushStretch = () => __awaiter(this, void 0, void 0, function* () {
|
|
226
253
|
if (this.selectionType !== SelectionType.SelectOne) {
|
|
@@ -387,6 +414,7 @@ export class _CfgFeatureInternal {
|
|
|
387
414
|
});
|
|
388
415
|
this.isSelected = (option) => this.selectionType === SelectionType.Group ||
|
|
389
416
|
this._selectedOptions.some(getOptionFilter(option));
|
|
417
|
+
this.isDisabled = (option) => this._constrainedOptions.some(getOptionFilter(option));
|
|
390
418
|
this.keyMatch = (other, descriptionMatch = false) => descriptionMatch
|
|
391
419
|
? this.description.toLowerCase() === other.description.toLowerCase()
|
|
392
420
|
: this.code === other.code;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LengthUnit, Observable, SingleArgCallback } from "@configura/web-utilities";
|
|
2
|
-
import { DtoFeature, DtoMiscFile, DtoNote, DtoOption, DtoOptionConf, DtoSelectedOption } from "../CatalogueAPI.js";
|
|
2
|
+
import { DtoFeature, DtoMiscFile, DtoNote, DtoOption, DtoOptionConf, DtoPartsConstrainedOption, DtoSelectedOption } from "../CatalogueAPI.js";
|
|
3
3
|
import { CfgProduct, _CfgProductInternal } from "../CfgProduct.js";
|
|
4
4
|
import { CfgMtrlApplication } from "../material/CfgMtrlApplication.js";
|
|
5
5
|
import { NumericValuesSelection } from "../utilitiesNumericValues.js";
|
|
@@ -83,6 +83,7 @@ export declare class _CfgOptionInternal {
|
|
|
83
83
|
get unit(): LengthUnit;
|
|
84
84
|
get description(): string;
|
|
85
85
|
get selected(): boolean;
|
|
86
|
+
get disabled(): boolean;
|
|
86
87
|
get selectedChangeInProgress(): boolean;
|
|
87
88
|
get ancestorsSelected(): boolean;
|
|
88
89
|
get mtrlApplications(): CfgMtrlApplication[];
|
|
@@ -94,7 +95,8 @@ export declare class _CfgOptionInternal {
|
|
|
94
95
|
/** Called by child to tell its parent that it has changed. */
|
|
95
96
|
_childHasChanged: (freshRef: CfgFeature, bubbleMode: ProductConfigurationBubbleMode, committed: boolean) => Promise<void>;
|
|
96
97
|
getDtoConf: (includeExtendedData: boolean) => DtoOptionConf;
|
|
97
|
-
setApiSelection: (apiOptionSelection: DtoSelectedOption | undefined) => Promise<boolean>;
|
|
98
|
+
setApiSelection: (apiOptionSelection: DtoSelectedOption | undefined, apiOptionConstraint: DtoPartsConstrainedOption | undefined) => Promise<boolean>;
|
|
99
|
+
getApiConstrained: (constrOptions: CfgOption[]) => DtoPartsConstrainedOption;
|
|
98
100
|
structureCompare: (other: _CfgOptionInternal, strictOrder?: boolean, descriptionMatch?: boolean) => boolean;
|
|
99
101
|
tryMatchSelection: (other: CfgOption, descriptionMatch?: boolean) => Promise<boolean>;
|
|
100
102
|
keyMatch: (other: _CfgOptionInternal, descriptionMatch?: boolean) => boolean;
|
|
@@ -132,6 +134,7 @@ export declare class CfgOption {
|
|
|
132
134
|
get unit(): LengthUnit;
|
|
133
135
|
get description(): string;
|
|
134
136
|
get selected(): boolean;
|
|
137
|
+
get disabled(): boolean;
|
|
135
138
|
/**
|
|
136
139
|
* Selection state is in progress to be changed. This can be used in GUI
|
|
137
140
|
* to display the state as transitioning, or as already changed.
|
|
@@ -138,7 +138,7 @@ export class _CfgOptionInternal {
|
|
|
138
138
|
// way around. For that reason the get-method above uses the new format, and the set-method
|
|
139
139
|
// below the old format. As these functions are meant to only be used internally this should't
|
|
140
140
|
// cause too much confusion.
|
|
141
|
-
this.setApiSelection = (apiOptionSelection) => __awaiter(this, void 0, void 0, function* () {
|
|
141
|
+
this.setApiSelection = (apiOptionSelection, apiOptionConstraint) => __awaiter(this, void 0, void 0, function* () {
|
|
142
142
|
let change = false;
|
|
143
143
|
const upcharge = this._calculateUpcharge();
|
|
144
144
|
if (this._upcharge !== upcharge) {
|
|
@@ -152,11 +152,25 @@ export class _CfgOptionInternal {
|
|
|
152
152
|
else {
|
|
153
153
|
features = this.features; // This will generate all children
|
|
154
154
|
}
|
|
155
|
-
if ((yield Promise.all(features.map((f) => f._internal.setApiSelection(apiOptionSelection ? apiOptionSelection.next : undefined)))).some((b) => b)) {
|
|
155
|
+
if ((yield Promise.all(features.map((f) => f._internal.setApiSelection(apiOptionSelection ? apiOptionSelection.next : undefined, apiOptionConstraint === null || apiOptionConstraint === void 0 ? void 0 : apiOptionConstraint.next)))).some((b) => b)) {
|
|
156
156
|
change = true;
|
|
157
157
|
}
|
|
158
158
|
return change;
|
|
159
159
|
});
|
|
160
|
+
this.getApiConstrained = (constrOptions) => {
|
|
161
|
+
var _a;
|
|
162
|
+
const next = {};
|
|
163
|
+
// use _features to avoid populating when the option is not selected
|
|
164
|
+
for (const feature of (_a = this._features) !== null && _a !== void 0 ? _a : []) {
|
|
165
|
+
feature._internal.addForApiConstrained(next);
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
code: this.code,
|
|
169
|
+
feature: this.parent.code,
|
|
170
|
+
constrOptions: constrOptions.map((o) => o.code),
|
|
171
|
+
next,
|
|
172
|
+
};
|
|
173
|
+
};
|
|
160
174
|
this.structureCompare = (other, strictOrder = true, descriptionMatch = false) => this.keyMatch(other, descriptionMatch) &&
|
|
161
175
|
compareArrays(this.features, other.features, (l, r) => l._internal.structureCompare(r._internal, strictOrder, descriptionMatch), strictOrder);
|
|
162
176
|
this.tryMatchSelection = (other, descriptionMatch = false) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -270,6 +284,9 @@ export class _CfgOptionInternal {
|
|
|
270
284
|
get selected() {
|
|
271
285
|
return this.parent.isSelected(this);
|
|
272
286
|
}
|
|
287
|
+
get disabled() {
|
|
288
|
+
return this.parent.isDisabled(this);
|
|
289
|
+
}
|
|
273
290
|
get selectedChangeInProgress() {
|
|
274
291
|
const syncGroupHandler = this.rootProduct.syncGroupHandler;
|
|
275
292
|
if (syncGroupHandler === undefined) {
|
|
@@ -415,6 +432,9 @@ export class CfgOption {
|
|
|
415
432
|
get selected() {
|
|
416
433
|
return this._internal.selected;
|
|
417
434
|
}
|
|
435
|
+
get disabled() {
|
|
436
|
+
return this._internal.disabled;
|
|
437
|
+
}
|
|
418
438
|
/**
|
|
419
439
|
* Selection state is in progress to be changed. This can be used in GUI
|
|
420
440
|
* to display the state as transitioning, or as already changed.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LengthUnit, LengthValue, Observable, SingleArgCallback } from "@configura/web-utilities";
|
|
2
|
-
import { DtoFeature, DtoFeatureConf, DtoFeatureRef, DtoSelectedOption } from "../CatalogueAPI.js";
|
|
2
|
+
import { DtoFeature, DtoFeatureConf, DtoFeatureRef, DtoPartsConstrainedOption, DtoSelectedOption } from "../CatalogueAPI.js";
|
|
3
3
|
import { CfgProduct, _CfgProductInternal } from "../CfgProduct.js";
|
|
4
4
|
import { CfgFeature, _CfgFeatureInternal } from "./CfgFeature.js";
|
|
5
5
|
import { ProductConfigurationBubbleMode } from "./CfgOption.js";
|
|
@@ -36,12 +36,13 @@ export declare class _CfgProductConfigurationInternal {
|
|
|
36
36
|
_childHasChanged: (freshRef: CfgFeature, bubbleMode: ProductConfigurationBubbleMode, committed: boolean) => Promise<void>;
|
|
37
37
|
getDtoConf: (includeExtendedData: boolean) => DtoFeatureConf[];
|
|
38
38
|
getApiSelection: () => DtoSelectedOption[];
|
|
39
|
+
getApiConstrained: () => DtoPartsConstrainedOption[];
|
|
39
40
|
/**
|
|
40
41
|
* When used internally the notifications are taken care off by the caller, but if set from
|
|
41
42
|
* outside we want notifications to bubble all the way to the root.
|
|
42
43
|
* This method will not cause validation calls. Data is assumed to already be validated.
|
|
43
44
|
*/
|
|
44
|
-
setApiSelection: (selectedOptions: DtoSelectedOption[], bubbleToRoot: boolean) => Promise<boolean>;
|
|
45
|
+
setApiSelection: (selectedOptions: DtoSelectedOption[], constrOptions: readonly DtoPartsConstrainedOption[] | undefined, bubbleToRoot: boolean) => Promise<boolean>;
|
|
45
46
|
structureCompare: (other: _CfgProductConfigurationInternal, strictOrder: boolean, descriptionMatch: boolean) => boolean;
|
|
46
47
|
/**
|
|
47
48
|
* When used internally the notifications are taken care off by the caller, but if set from
|
|
@@ -76,7 +77,7 @@ export declare class CfgProductConfiguration {
|
|
|
76
77
|
* has been called.
|
|
77
78
|
*/
|
|
78
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.
|
|
79
|
-
apiSelection: DtoSelectedOption[], parentProduct: _CfgProductInternal, rootProduct: _CfgProductInternal): CfgProductConfiguration;
|
|
80
|
+
apiSelection: DtoSelectedOption[], apiConstraints: readonly DtoPartsConstrainedOption[] | undefined, parentProduct: _CfgProductInternal, rootProduct: _CfgProductInternal): CfgProductConfiguration;
|
|
80
81
|
/**
|
|
81
82
|
* Makes an object wrapping the passed object. This is not a clone method, it is a method to
|
|
82
83
|
* make a new outer reference. Like a shallow copy.
|
|
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import { compareArrays, count, isEqualLength, isLengthUnit, Observable, toError, toLengthUnit, } from "@configura/web-utilities";
|
|
11
11
|
import { CfgProduct } from "../CfgProduct.js";
|
|
12
|
-
import { convertDtoFeatureConfsToSelOptions } from "../
|
|
12
|
+
import { convertDtoFeatureConfsToSelOptions } from "../utilitiesConfiguration.js";
|
|
13
13
|
import { ProductConfigurationBubbleMode } from "./CfgOption.js";
|
|
14
14
|
import { syncCfgFeatures } from "./utilitiesProductConfiguration.js";
|
|
15
15
|
/**
|
|
@@ -56,18 +56,33 @@ export class _CfgProductConfigurationInternal {
|
|
|
56
56
|
});
|
|
57
57
|
this.getDtoConf = (includeExtendedData) => this._features.map((f) => f._internal.getDtoConf(includeExtendedData));
|
|
58
58
|
this.getApiSelection = () => convertDtoFeatureConfsToSelOptions(this.getDtoConf(false), true);
|
|
59
|
+
this.getApiConstrained = () => this._features.map((f) => {
|
|
60
|
+
const next = {};
|
|
61
|
+
f._internal.addForApiConstrained(next);
|
|
62
|
+
return {
|
|
63
|
+
code: "!~!",
|
|
64
|
+
feature: "",
|
|
65
|
+
next,
|
|
66
|
+
};
|
|
67
|
+
});
|
|
59
68
|
/**
|
|
60
69
|
* When used internally the notifications are taken care off by the caller, but if set from
|
|
61
70
|
* outside we want notifications to bubble all the way to the root.
|
|
62
71
|
* This method will not cause validation calls. Data is assumed to already be validated.
|
|
63
72
|
*/
|
|
64
|
-
this.setApiSelection = (selectedOptions, bubbleToRoot) => __awaiter(this, void 0, void 0, function* () {
|
|
73
|
+
this.setApiSelection = (selectedOptions, constrOptions, bubbleToRoot) => __awaiter(this, void 0, void 0, function* () {
|
|
65
74
|
const featuresLength = this._features.length;
|
|
66
75
|
const selectedOptionsLength = selectedOptions.length;
|
|
67
76
|
if (featuresLength !== selectedOptionsLength) {
|
|
68
77
|
throw new Error(`Wrong selection count. Features on this configuration: ${featuresLength}. Passed feature count: ${selectedOptionsLength}.`);
|
|
69
78
|
}
|
|
70
|
-
|
|
79
|
+
if (constrOptions && featuresLength !== constrOptions.length) {
|
|
80
|
+
throw new Error(`Wrong constraint feature count. Features on this configuration: ${featuresLength}. Passed constraint feature count: ${constrOptions.length}.`);
|
|
81
|
+
}
|
|
82
|
+
const change = (yield Promise.all(this._features.map((f, i) => {
|
|
83
|
+
var _a;
|
|
84
|
+
return f._internal.setApiSelection(selectedOptions[i].next, (_a = (constrOptions !== null && constrOptions !== void 0 ? constrOptions : [])[i]) === null || _a === void 0 ? void 0 : _a.next);
|
|
85
|
+
}))).some((b) => b);
|
|
71
86
|
if (change) {
|
|
72
87
|
yield this._notifyAllOfChange(bubbleToRoot
|
|
73
88
|
? ProductConfigurationBubbleMode.ToRoot
|
|
@@ -284,12 +299,12 @@ export class CfgProductConfiguration {
|
|
|
284
299
|
* has been called.
|
|
285
300
|
*/
|
|
286
301
|
static make(initSuccess, initFail, rootFeatureRefs, rawFeatures, // Flat packed. All the features that can currently appear anyplace in the selection tree.
|
|
287
|
-
apiSelection, parentProduct, rootProduct) {
|
|
302
|
+
apiSelection, apiConstraints, parentProduct, rootProduct) {
|
|
288
303
|
const internal = _CfgProductConfigurationInternal._makeUninitialized(rootFeatureRefs, rawFeatures, parentProduct, rootProduct);
|
|
289
304
|
const external = new this(internal);
|
|
290
305
|
// Note the async-callback at the end of the following line. The call is async.
|
|
291
306
|
internal
|
|
292
|
-
.setApiSelection(apiSelection, false)
|
|
307
|
+
.setApiSelection(apiSelection, apiConstraints, false)
|
|
293
308
|
.then(() => initSuccess(external))
|
|
294
309
|
.catch((e) => initFail(toError(e)));
|
|
295
310
|
return external;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { Filters
|
|
1
|
+
import { Filters } from "@configura/web-utilities";
|
|
2
2
|
import { DtoCatalogueParams, DtoLevel, DtoProductRef } from "../CatalogueAPI.js";
|
|
3
|
-
export declare function applyCatalogueFilters<T extends DtoCatalogueParams>(filters: Filters<DtoCatalogueParams>, catalogues: T[]): [
|
|
3
|
+
export declare function applyCatalogueFilters<T extends DtoCatalogueParams>(filters: Filters<DtoCatalogueParams>, catalogues: T[]): [{
|
|
4
|
+
[K in keyof DtoCatalogueParams]: string[];
|
|
5
|
+
}, T[]];
|
|
4
6
|
export interface ProductRefParams {
|
|
5
7
|
partNr: string;
|
|
6
8
|
}
|
|
7
|
-
export declare function applyProductRefFilters(filters: Filters<ProductRefParams>, productRefs: DtoProductRef[]): [
|
|
9
|
+
export declare function applyProductRefFilters(filters: Filters<ProductRefParams>, productRefs: DtoProductRef[]): [string[], DtoProductRef[]];
|
|
8
10
|
/**
|
|
9
11
|
* Clones the table of content levels tree.
|
|
10
12
|
* Filters to only include passed products.
|
|
@@ -1,31 +1,102 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { shuffle } from "@configura/web-utilities";
|
|
2
|
+
function filterAndSort(propertyValuesToT, property, filtersByProperty, availablePropertyValuesByProperty) {
|
|
3
|
+
const availablePropertyValues = availablePropertyValuesByProperty[property];
|
|
4
|
+
for (const key of propertyValuesToT.keys()) {
|
|
5
|
+
availablePropertyValues.add(key);
|
|
6
|
+
}
|
|
7
|
+
let items;
|
|
8
|
+
const filter = filtersByProperty[property];
|
|
9
|
+
if (filter.mode === "exact") {
|
|
10
|
+
const { value: key } = filter;
|
|
11
|
+
if (key !== "-") {
|
|
12
|
+
const item = propertyValuesToT.get(key);
|
|
13
|
+
if (item === undefined) {
|
|
14
|
+
items = [];
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
items = [item];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (items === undefined) {
|
|
22
|
+
if (filter.mode === "random") {
|
|
23
|
+
items = shuffle(Array.from(propertyValuesToT.values()));
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
items = Array.from(propertyValuesToT.entries())
|
|
27
|
+
.sort((l, r) => l[0].localeCompare(r[0], undefined, { sensitivity: "base" }))
|
|
28
|
+
.map((item) => item[1]);
|
|
29
|
+
}
|
|
30
|
+
if (filter.value > 0 && (filter.mode === "first" || filter.mode === "random")) {
|
|
31
|
+
items = items.slice(0, filter.value);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return items;
|
|
35
|
+
}
|
|
36
|
+
function stringSetToSortedArray(s) {
|
|
37
|
+
return Array.from(s).sort((l, r) => l.localeCompare(r, undefined, { sensitivity: "base" }));
|
|
38
|
+
}
|
|
2
39
|
export function applyCatalogueFilters(filters, catalogues) {
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
prdCatVersion
|
|
17
|
-
|
|
18
|
-
|
|
40
|
+
const cataloguesAsTree = new Map();
|
|
41
|
+
for (const catalogueParams of catalogues) {
|
|
42
|
+
const { enterprise, prdCat, prdCatVersion, vendor, priceList } = catalogueParams;
|
|
43
|
+
let byEnterprise = cataloguesAsTree.get(enterprise);
|
|
44
|
+
if (byEnterprise === undefined) {
|
|
45
|
+
byEnterprise = new Map();
|
|
46
|
+
cataloguesAsTree.set(enterprise, byEnterprise);
|
|
47
|
+
}
|
|
48
|
+
let byPrdCat = byEnterprise.get(prdCat);
|
|
49
|
+
if (byPrdCat === undefined) {
|
|
50
|
+
byPrdCat = new Map();
|
|
51
|
+
byEnterprise.set(prdCat, byPrdCat);
|
|
52
|
+
}
|
|
53
|
+
let byPrdCatVersion = byPrdCat.get(prdCatVersion);
|
|
54
|
+
if (byPrdCatVersion === undefined) {
|
|
55
|
+
byPrdCatVersion = new Map();
|
|
56
|
+
byPrdCat.set(prdCatVersion, byPrdCatVersion);
|
|
57
|
+
}
|
|
58
|
+
let byVendor = byPrdCatVersion.get(vendor);
|
|
59
|
+
if (byVendor === undefined) {
|
|
60
|
+
byVendor = new Map();
|
|
61
|
+
byPrdCatVersion.set(vendor, byVendor);
|
|
62
|
+
}
|
|
63
|
+
if (byVendor.has(priceList)) {
|
|
64
|
+
console.warn(`Duplicate catalogue ${enterprise} ${prdCat} ${prdCatVersion} ${vendor} ${priceList}`);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
byVendor.set(priceList, catalogueParams);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const filteredCatalogues = [];
|
|
71
|
+
const availablePropertyValues = {
|
|
72
|
+
enterprise: new Set(),
|
|
73
|
+
prdCat: new Set(),
|
|
74
|
+
prdCatVersion: new Set(),
|
|
75
|
+
vendor: new Set(),
|
|
76
|
+
priceList: new Set(),
|
|
19
77
|
};
|
|
20
|
-
|
|
78
|
+
filterAndSort(cataloguesAsTree, "enterprise", filters, availablePropertyValues).map((item) => filterAndSort(item, "prdCat", filters, availablePropertyValues).map((item) => filterAndSort(item, "prdCatVersion", filters, availablePropertyValues).map((item) => filterAndSort(item, "vendor", filters, availablePropertyValues).map((item) => filterAndSort(item, "priceList", filters, availablePropertyValues).forEach((item) => {
|
|
79
|
+
filteredCatalogues.push(item);
|
|
80
|
+
})))));
|
|
81
|
+
const availablePropertyValuesAsSortedArrays = {
|
|
82
|
+
enterprise: stringSetToSortedArray(availablePropertyValues.enterprise),
|
|
83
|
+
prdCat: stringSetToSortedArray(availablePropertyValues.prdCat),
|
|
84
|
+
prdCatVersion: stringSetToSortedArray(availablePropertyValues.prdCatVersion),
|
|
85
|
+
vendor: stringSetToSortedArray(availablePropertyValues.vendor),
|
|
86
|
+
priceList: stringSetToSortedArray(availablePropertyValues.priceList),
|
|
87
|
+
};
|
|
88
|
+
return [availablePropertyValuesAsSortedArrays, filteredCatalogues];
|
|
21
89
|
}
|
|
22
90
|
export function applyProductRefFilters(filters, productRefs) {
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
91
|
+
const map = new Map();
|
|
92
|
+
for (const productRef of productRefs) {
|
|
93
|
+
map.set(productRef.partNr, productRef);
|
|
94
|
+
}
|
|
95
|
+
const availablePropertyValues = {
|
|
96
|
+
partNr: new Set(),
|
|
27
97
|
};
|
|
28
|
-
|
|
98
|
+
const filtered = filterAndSort(map, "partNr", filters, availablePropertyValues);
|
|
99
|
+
return [stringSetToSortedArray(availablePropertyValues.partNr), filtered];
|
|
29
100
|
}
|
|
30
101
|
/**
|
|
31
102
|
* Clones the table of content levels tree.
|
|
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import { augmentErrorMessage, Observable } from "@configura/web-utilities";
|
|
11
11
|
import { dtoExportFormatNames, dtoRenderFormatNames, } from "../CatalogueAPI.js";
|
|
12
|
-
import { convertDtoProductConfToV1 } from "../
|
|
12
|
+
import { convertDtoProductConfToV1 } from "../utilitiesConfiguration.js";
|
|
13
13
|
import { isExportFormat, isRenderFormat } from "./formats.js";
|
|
14
14
|
export class _TaskHandlerInternal {
|
|
15
15
|
constructor(api) {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { DtoPartsConstrainedOption } from "../../CatalogueAPI";
|
|
2
|
+
export declare const testConstrOptions: readonly DtoPartsConstrainedOption[];
|
|
3
|
+
export declare const testUpdatedConstrOptions: readonly DtoPartsConstrainedOption[];
|
|
4
|
+
//# sourceMappingURL=testDataConstraints.d.ts.map
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
export const testConstrOptions = Object.freeze([
|
|
2
|
+
{
|
|
3
|
+
code: "!~!",
|
|
4
|
+
feature: "",
|
|
5
|
+
next: {
|
|
6
|
+
"option-ab": {
|
|
7
|
+
code: "option-ab",
|
|
8
|
+
feature: "feature-a",
|
|
9
|
+
constrOptions: ["option-aa"],
|
|
10
|
+
next: {
|
|
11
|
+
"option-multi-nested-a": {
|
|
12
|
+
feature: "feature-multiple-nested",
|
|
13
|
+
code: "option-multi-nested-a",
|
|
14
|
+
constrOptions: [],
|
|
15
|
+
next: { "option-ca": { code: "option-ca", feature: "feature-c", constrOptions: [], next: {} } }
|
|
16
|
+
},
|
|
17
|
+
"option-multi-nested-b": {
|
|
18
|
+
feature: "feature-multiple-nested",
|
|
19
|
+
code: "option-multi-nested-b",
|
|
20
|
+
constrOptions: [],
|
|
21
|
+
next: { "option-optional-b": { code: "option-optional-b", feature: "feature-optional", constrOptions: [], next: {} } }
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
code: "!~!",
|
|
29
|
+
feature: "",
|
|
30
|
+
next: {
|
|
31
|
+
"option-bb": {
|
|
32
|
+
feature: "feature-b",
|
|
33
|
+
code: "option-bb",
|
|
34
|
+
constrOptions: [],
|
|
35
|
+
next: {
|
|
36
|
+
"option-multi-nested-a": {
|
|
37
|
+
code: "option-multi-nested-a",
|
|
38
|
+
feature: "feature-multiple-nested",
|
|
39
|
+
constrOptions: [],
|
|
40
|
+
next: { "option-ca": { feature: "feature-c", code: "option-ca", constrOptions: [], next: {} } }
|
|
41
|
+
},
|
|
42
|
+
"option-multi-nested-b": {
|
|
43
|
+
feature: "feature-multiple-nested",
|
|
44
|
+
code: "option-multi-nested-b",
|
|
45
|
+
constrOptions: [],
|
|
46
|
+
next: {}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
code: "!~!",
|
|
54
|
+
feature: "",
|
|
55
|
+
next: {
|
|
56
|
+
"option-multi-a": {
|
|
57
|
+
feature: "feature-multiple",
|
|
58
|
+
code: "option-multi-a",
|
|
59
|
+
constrOptions: ["option-multi-b"],
|
|
60
|
+
next: {
|
|
61
|
+
"option-db": { code: "option-db", feature: "feature-d", constrOptions: ["option-da"], next: {} },
|
|
62
|
+
"option-ea": { code: "option-ea", feature: "feature-e", constrOptions: ["option-eb"], next: {} }
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"option-multi-b": {
|
|
66
|
+
feature: "feature-multiple",
|
|
67
|
+
code: "option-multi-b",
|
|
68
|
+
constrOptions: ["option-multi-b"],
|
|
69
|
+
next: {
|
|
70
|
+
"option-ga": { code: "option-ga", feature: "feature-g", constrOptions: ["option-gb"], next: {} },
|
|
71
|
+
"option-1h": { code: "option-1h", feature: "feature-h", constrOptions: ["option-2h"], next: {} }
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
code: "!~!",
|
|
78
|
+
feature: "",
|
|
79
|
+
next: {
|
|
80
|
+
"option-optional-a": { code: "option-optional-a", feature: "feature-optional", constrOptions: [], next: {} }
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
]);
|
|
84
|
+
export const testUpdatedConstrOptions = Object.freeze([
|
|
85
|
+
{
|
|
86
|
+
code: "!~!",
|
|
87
|
+
feature: "",
|
|
88
|
+
next: {
|
|
89
|
+
"option-ab": {
|
|
90
|
+
code: "option-ab",
|
|
91
|
+
feature: "feature-a",
|
|
92
|
+
constrOptions: [],
|
|
93
|
+
next: {
|
|
94
|
+
"option-multi-nested-a": {
|
|
95
|
+
feature: "feature-multiple-nested",
|
|
96
|
+
code: "option-multi-nested-a",
|
|
97
|
+
constrOptions: [],
|
|
98
|
+
next: { "option-ca": { code: "option-ca", feature: "feature-c", constrOptions: [], next: {} } }
|
|
99
|
+
},
|
|
100
|
+
"option-multi-nested-b": {
|
|
101
|
+
feature: "feature-multiple-nested",
|
|
102
|
+
code: "option-multi-nested-b",
|
|
103
|
+
constrOptions: [],
|
|
104
|
+
next: {
|
|
105
|
+
"option-optional-a": { code: "option-optional-a", feature: "feature-optional", constrOptions: [], next: {} },
|
|
106
|
+
"option-optional-b": { code: "option-optional-b", feature: "feature-optional", constrOptions: [], next: {} }
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
code: "!~!",
|
|
115
|
+
feature: "",
|
|
116
|
+
next: {
|
|
117
|
+
"option-bb": {
|
|
118
|
+
feature: "feature-b",
|
|
119
|
+
code: "option-bb",
|
|
120
|
+
constrOptions: [],
|
|
121
|
+
next: {
|
|
122
|
+
"option-multi-nested-a": {
|
|
123
|
+
code: "option-multi-nested-a",
|
|
124
|
+
feature: "feature-multiple-nested",
|
|
125
|
+
constrOptions: [],
|
|
126
|
+
next: {
|
|
127
|
+
"option-cb": { feature: "feature-c", code: "option-cb", constrOptions: [], next: {} }
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
"option-multi-nested-b": {
|
|
131
|
+
feature: "feature-multiple-nested",
|
|
132
|
+
code: "option-multi-nested-b",
|
|
133
|
+
constrOptions: [],
|
|
134
|
+
next: {
|
|
135
|
+
"option-optional-b": { feature: "feature-optional", code: "option-optional-b", constrOptions: [], next: {} }
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
code: "!~!",
|
|
144
|
+
feature: "",
|
|
145
|
+
next: {
|
|
146
|
+
"option-multi-a": {
|
|
147
|
+
feature: "feature-multiple",
|
|
148
|
+
code: "option-multi-a",
|
|
149
|
+
constrOptions: [],
|
|
150
|
+
next: {
|
|
151
|
+
"option-da": { code: "option-da", feature: "feature-d", constrOptions: [], next: {} },
|
|
152
|
+
"option-eb": { code: "option-eb", feature: "feature-e", constrOptions: [], next: {} }
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
"option-multi-b": {
|
|
156
|
+
feature: "feature-multiple",
|
|
157
|
+
code: "option-multi-b",
|
|
158
|
+
constrOptions: [],
|
|
159
|
+
next: {
|
|
160
|
+
"option-ga": { code: "option-ga", feature: "feature-g", constrOptions: [], next: {} },
|
|
161
|
+
"option-1h": { code: "option-1h", feature: "feature-h", constrOptions: [], next: {} }
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
code: "!~!",
|
|
168
|
+
feature: "",
|
|
169
|
+
next: {
|
|
170
|
+
"option-optional-a": { code: "option-optional-a", feature: "feature-optional", constrOptions: [], next: {} },
|
|
171
|
+
"option-optional-b": { code: "option-optional-b", feature: "feature-optional", constrOptions: [], next: {} },
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
]);
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
import { DtoAdditionalProductConf, DtoAdditionalProductConfiguration, DtoFeatureConf, DtoProductConf, DtoSelectedOption } from "./CatalogueAPI.js";
|
|
2
|
+
/**
|
|
3
|
+
* @param ExtendedData Extra data, i.e. units and groupCodes
|
|
4
|
+
* @param ProductParams What Product the conf is for, and the same for any Additional Products.
|
|
5
|
+
* @param SyncGroupState The current sync group state
|
|
6
|
+
*/
|
|
7
|
+
export declare enum CfgProdConfParts {
|
|
8
|
+
NoExtra = 0,
|
|
9
|
+
ExtendedData = 1,
|
|
10
|
+
ProdParams = 2,
|
|
11
|
+
SyncGroupState = 4
|
|
12
|
+
}
|
|
2
13
|
/** Is the newer version of product configuration */
|
|
3
14
|
export declare const isProductConf: (value: DtoAdditionalProductConfiguration | DtoProductConf) => value is DtoAdditionalProductConf;
|
|
4
15
|
/** Is the older version of product configuration */
|
|
@@ -14,5 +25,5 @@ export declare const dtoProductConfigurationToCompactString: (conf: DtoProductCo
|
|
|
14
25
|
* Deserializes and inflates the configuration from the compacted format
|
|
15
26
|
*/
|
|
16
27
|
export declare const compactStringToDtoProductConf: (versionAndConf: string) => DtoProductConf;
|
|
17
|
-
export declare const stripExtendedDataFromDtoProductConf: (conf: DtoProductConf) => DtoProductConf;
|
|
18
|
-
//# sourceMappingURL=
|
|
28
|
+
export declare const stripExtendedDataFromDtoProductConf: (conf: DtoProductConf, toStrip: CfgProdConfParts) => DtoProductConf;
|
|
29
|
+
//# sourceMappingURL=utilitiesConfiguration.d.ts.map
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param ExtendedData Extra data, i.e. units and groupCodes
|
|
3
|
+
* @param ProductParams What Product the conf is for, and the same for any Additional Products.
|
|
4
|
+
* @param SyncGroupState The current sync group state
|
|
5
|
+
*/
|
|
6
|
+
export var CfgProdConfParts;
|
|
7
|
+
(function (CfgProdConfParts) {
|
|
8
|
+
CfgProdConfParts[CfgProdConfParts["NoExtra"] = 0] = "NoExtra";
|
|
9
|
+
CfgProdConfParts[CfgProdConfParts["ExtendedData"] = 1] = "ExtendedData";
|
|
10
|
+
CfgProdConfParts[CfgProdConfParts["ProdParams"] = 2] = "ProdParams";
|
|
11
|
+
CfgProdConfParts[CfgProdConfParts["SyncGroupState"] = 4] = "SyncGroupState";
|
|
12
|
+
})(CfgProdConfParts || (CfgProdConfParts = {}));
|
|
1
13
|
/** Is the newer version of product configuration */
|
|
2
14
|
export const isProductConf = (value) => !("selOptions" in value);
|
|
3
15
|
/** Is the older version of product configuration */
|
|
@@ -149,27 +161,40 @@ export const compactStringToDtoProductConf = (versionAndConf) => {
|
|
|
149
161
|
}
|
|
150
162
|
return JSON.parse(expandDtoProductConfJsonKeys(jsonStringSwapCharsForUrl(conf)));
|
|
151
163
|
};
|
|
152
|
-
export const stripExtendedDataFromDtoProductConf = (conf) => {
|
|
164
|
+
export const stripExtendedDataFromDtoProductConf = (conf, toStrip) => {
|
|
153
165
|
var _a, _b;
|
|
154
|
-
|
|
155
|
-
features: (_a = conf.features) === null || _a === void 0 ? void 0 : _a.map(stripExtendedDataFromDtoFeatureConf),
|
|
166
|
+
const stripped = {
|
|
167
|
+
features: (_a = conf.features) === null || _a === void 0 ? void 0 : _a.map((f) => stripExtendedDataFromDtoFeatureConf(f, toStrip)),
|
|
156
168
|
additionalProducts: (_b = conf.additionalProducts) === null || _b === void 0 ? void 0 : _b.map(stripExtendedDataFromDtoAdditionalProductConfiguration),
|
|
157
|
-
}
|
|
169
|
+
};
|
|
170
|
+
if ((toStrip & CfgProdConfParts.SyncGroupState) !== CfgProdConfParts.SyncGroupState) {
|
|
171
|
+
stripped.syncGroupState = conf.syncGroupState;
|
|
172
|
+
}
|
|
173
|
+
if ((toStrip & CfgProdConfParts.ProdParams) !== CfgProdConfParts.ProdParams) {
|
|
174
|
+
stripped.prodParams = conf.prodParams;
|
|
175
|
+
}
|
|
176
|
+
return stripped;
|
|
158
177
|
};
|
|
159
|
-
const stripExtendedDataFromDtoAdditionalProductConfiguration = (conf) => (Object.assign(Object.assign({}, stripExtendedDataFromDtoProductConf(conf)), { refKey: conf.refKey, selected: conf.selected }));
|
|
160
|
-
const stripExtendedDataFromDtoFeatureConf = (conf) => {
|
|
178
|
+
const stripExtendedDataFromDtoAdditionalProductConfiguration = (conf, toStrip) => (Object.assign(Object.assign({}, stripExtendedDataFromDtoProductConf(conf, toStrip)), { refKey: conf.refKey, selected: conf.selected }));
|
|
179
|
+
const stripExtendedDataFromDtoFeatureConf = (conf, toStrip) => {
|
|
161
180
|
var _a;
|
|
162
|
-
|
|
181
|
+
const stripped = {
|
|
163
182
|
code: conf.code,
|
|
164
|
-
options: (_a = conf.options) === null || _a === void 0 ? void 0 : _a.map(stripExtendedDataFromDtoOptionConf),
|
|
165
|
-
}
|
|
183
|
+
options: (_a = conf.options) === null || _a === void 0 ? void 0 : _a.map((o) => stripExtendedDataFromDtoOptionConf(o, toStrip)),
|
|
184
|
+
};
|
|
185
|
+
if ((toStrip & CfgProdConfParts.ExtendedData) !== CfgProdConfParts.ExtendedData) {
|
|
186
|
+
// Keep in sync with getDtoConf in CfgFeature
|
|
187
|
+
stripped.groupCode = conf.groupCode;
|
|
188
|
+
stripped.unit = conf.unit;
|
|
189
|
+
}
|
|
190
|
+
return stripped;
|
|
166
191
|
};
|
|
167
|
-
const stripExtendedDataFromDtoOptionConf = (conf) => {
|
|
192
|
+
const stripExtendedDataFromDtoOptionConf = (conf, toStrip) => {
|
|
168
193
|
var _a;
|
|
169
194
|
return ({
|
|
170
195
|
code: conf.code,
|
|
171
196
|
selected: conf.selected,
|
|
172
197
|
numericValue: conf.numericValue,
|
|
173
|
-
features: (_a = conf.features) === null || _a === void 0 ? void 0 : _a.map(stripExtendedDataFromDtoFeatureConf),
|
|
198
|
+
features: (_a = conf.features) === null || _a === void 0 ? void 0 : _a.map((f) => stripExtendedDataFromDtoFeatureConf(f, toStrip)),
|
|
174
199
|
});
|
|
175
200
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@configura/web-api",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.1.0-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": "2.0.
|
|
26
|
+
"@configura/web-utilities": "2.1.0-alpha.1"
|
|
27
27
|
},
|
|
28
|
-
"gitHead": "
|
|
28
|
+
"gitHead": "0eec1ba88fc2fa4d0f3f9a36173818f721752786"
|
|
29
29
|
}
|