@configura/web-api 1.6.1-alpha.7 → 2.0.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/.eslintrc.json +18 -0
- package/LICENSE +201 -201
- package/README.md +1 -1
- package/dist/CatalogueAPI.d.ts +551 -512
- package/dist/CatalogueAPI.js +293 -277
- package/dist/CfgMeasure.d.ts +32 -32
- package/dist/CfgMeasure.js +30 -30
- package/dist/CfgProduct.d.ts +268 -239
- package/dist/CfgProduct.js +778 -668
- package/dist/CfgReferencePathHelper.d.ts +14 -0
- package/dist/CfgReferencePathHelper.js +13 -0
- package/dist/ConfigurationConverter.d.ts +5 -0
- package/dist/ConfigurationConverter.js +72 -0
- package/dist/index.d.ts +23 -18
- package/dist/index.js +23 -18
- package/dist/io/CfgHistoryManager.d.ts +51 -0
- package/dist/io/CfgHistoryManager.js +82 -0
- package/dist/io/CfgHistoryToProdConfConnector.d.ts +21 -0
- package/dist/io/CfgHistoryToProdConfConnector.js +56 -0
- package/dist/io/CfgIOManager.d.ts +49 -0
- package/dist/io/CfgIOManager.js +115 -0
- package/dist/io/CfgIOProdConfConnector.d.ts +53 -0
- package/dist/io/CfgIOProdConfConnector.js +141 -0
- package/dist/io/CfgObservableStateManager.d.ts +22 -0
- package/dist/io/CfgObservableStateManager.js +65 -0
- package/dist/io/CfgObservableStateToProdConfConnector.d.ts +15 -0
- package/dist/io/CfgObservableStateToProdConfConnector.js +16 -0
- package/dist/io/CfgWindowEventManager.d.ts +22 -0
- package/dist/io/CfgWindowEventManager.js +38 -0
- package/dist/io/CfgWindowMessageManager.d.ts +41 -0
- package/dist/io/CfgWindowMessageManager.js +84 -0
- package/dist/io/CfgWindowMessageToProdConfConnector.d.ts +17 -0
- package/dist/io/CfgWindowMessageToProdConfConnector.js +18 -0
- package/dist/io/index.d.ts +9 -0
- package/dist/io/index.js +8 -0
- package/dist/material/CfgMaterialMapping.d.ts +7 -7
- package/dist/material/CfgMaterialMapping.js +181 -181
- package/dist/material/CfgMtrlApplication.d.ts +18 -18
- package/dist/material/CfgMtrlApplication.js +43 -43
- package/dist/material/CfgMtrlApplicationSource.d.ts +7 -7
- package/dist/material/CfgMtrlApplicationSource.js +8 -8
- package/dist/material/CfgMtrlSource.d.ts +19 -19
- package/dist/material/CfgMtrlSource.js +40 -40
- package/dist/material/CfgMtrlSourceWithMetaData.d.ts +7 -7
- package/dist/material/CfgMtrlSourceWithMetaData.js +1 -1
- package/dist/productConfiguration/CfgFeature.d.ts +187 -178
- package/dist/productConfiguration/CfgFeature.js +645 -611
- package/dist/productConfiguration/CfgOption.d.ts +151 -128
- package/dist/productConfiguration/CfgOption.js +416 -394
- package/dist/productConfiguration/CfgProductConfiguration.d.ts +117 -120
- package/dist/productConfiguration/CfgProductConfiguration.js +307 -307
- package/dist/productConfiguration/filters.d.ts +15 -15
- package/dist/productConfiguration/filters.js +70 -70
- package/dist/productConfiguration/productParamsGenerator.d.ts +15 -15
- package/dist/productConfiguration/productParamsGenerator.js +51 -51
- package/dist/productConfiguration/utilitiesProductConfiguration.d.ts +17 -17
- package/dist/productConfiguration/utilitiesProductConfiguration.js +80 -80
- package/dist/productLoader.d.ts +33 -33
- package/dist/productLoader.js +49 -49
- package/dist/syncGroups/SyncGroupsApplyMode.d.ts +21 -0
- package/dist/syncGroups/SyncGroupsApplyMode.js +21 -0
- package/dist/syncGroups/SyncGroupsHandler.d.ts +41 -0
- package/dist/syncGroups/SyncGroupsHandler.js +359 -0
- package/dist/syncGroups/SyncGroupsPathHelper.d.ts +27 -0
- package/dist/syncGroups/SyncGroupsPathHelper.js +90 -0
- package/dist/syncGroups/SyncGroupsState.d.ts +36 -0
- package/dist/syncGroups/SyncGroupsState.js +125 -0
- package/dist/syncGroups/SyncGroupsTransaction.d.ts +155 -0
- package/dist/syncGroups/SyncGroupsTransaction.js +576 -0
- package/dist/tasks/TaskHandler.d.ts +77 -78
- package/dist/tasks/TaskHandler.js +275 -265
- package/dist/tasks/formats.d.ts +4 -4
- package/dist/tasks/formats.js +7 -7
- package/dist/tests/testData/collectorForTest.d.ts +73 -73
- package/dist/tests/testData/collectorForTest.js +194 -195
- package/dist/tests/testData/dummyProductForTest.d.ts +4 -4
- package/dist/tests/testData/dummyProductForTest.js +32 -36
- package/dist/tests/testData/testDataAdditionalProductInAdditionalProductInProductForTest.d.ts +11 -32
- package/dist/tests/testData/testDataAdditionalProductInAdditionalProductInProductForTest.js +277 -348
- package/dist/tests/testData/testDataCachedGetProduct.d.ts +5 -5
- package/dist/tests/testData/testDataCachedGetProduct.js +185 -196
- package/dist/tests/testData/testDataCachedPostValidate.d.ts +7 -7
- package/dist/tests/testData/testDataCachedPostValidate.js +183 -183
- package/dist/tests/testData/testDataNoAdditionalProductNoPropagateForTest.d.ts +3 -3
- package/dist/tests/testData/testDataNoAdditionalProductNoPropagateForTest.js +1099 -1099
- package/dist/tests/testData/testDataOptions.d.ts +13 -0
- package/dist/tests/testData/testDataOptions.js +60 -0
- package/dist/tests/testData/testDataProductAggregatedPrice.d.ts +6 -6
- package/dist/tests/testData/testDataProductAggregatedPrice.js +187 -198
- package/dist/tests/testData/testDataUpcharge.d.ts +8 -29
- package/dist/tests/testData/testDataUpcharge.js +119 -151
- package/dist/utilitiesCatalogueData.d.ts +33 -25
- package/dist/utilitiesCatalogueData.js +164 -66
- package/dist/utilitiesCataloguePermission.d.ts +32 -39
- package/dist/utilitiesCataloguePermission.js +76 -84
- package/dist/utilitiesNumericValues.d.ts +24 -24
- package/dist/utilitiesNumericValues.js +109 -109
- package/package.json +3 -3
|
@@ -1,84 +1,76 @@
|
|
|
1
|
-
export const groupAndSortCataloguePermissions = (cataloguePermissions) => {
|
|
2
|
-
const cataloguePermissionByEnterpriseKey = {};
|
|
3
|
-
cataloguePermissions
|
|
4
|
-
// Sort by enterprise
|
|
5
|
-
.sort((a, b) => a.enterprise.toLocaleLowerCase().localeCompare(b.enterprise.toLocaleLowerCase()))
|
|
6
|
-
.forEach((c) => {
|
|
7
|
-
const enterprise = c.enterprise.toLowerCase();
|
|
8
|
-
if (cataloguePermissionByEnterpriseKey[enterprise] === undefined) {
|
|
9
|
-
cataloguePermissionByEnterpriseKey[enterprise] = [];
|
|
10
|
-
}
|
|
11
|
-
cataloguePermissionByEnterpriseKey[enterprise].push(c);
|
|
12
|
-
});
|
|
13
|
-
// Sort by prdcat
|
|
14
|
-
Object.keys(cataloguePermissionByEnterpriseKey).forEach((enterprise) => cataloguePermissionByEnterpriseKey[enterprise].sort((a, b) => a.prdCat.toLocaleLowerCase().localeCompare(b.prdCat.toLocaleLowerCase())));
|
|
15
|
-
return cataloguePermissionByEnterpriseKey;
|
|
16
|
-
};
|
|
17
|
-
export const isParamSet = (param) => param !== "" && param !== "-";
|
|
18
|
-
export const createCataloguePermissionsFilter = (enterprise, prdCat, prdCatVersion, priceList, vendor) =>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
* cataloguePermissions and insert it into a copy of the original params. If it fails to find any
|
|
78
|
-
* applicable auth-permissions the original value is returned.
|
|
79
|
-
* @param auth
|
|
80
|
-
* @param params
|
|
81
|
-
*/
|
|
82
|
-
export const fillMissingPrdCatVersionFromPermissions = (params, cataloguePermissions) => {
|
|
83
|
-
return Object.assign(Object.assign({}, params), { prdCatVersion: getPrdCatVersionOrLatestFromPermissions(params, cataloguePermissions) });
|
|
84
|
-
};
|
|
1
|
+
export const groupAndSortCataloguePermissions = (cataloguePermissions) => {
|
|
2
|
+
const cataloguePermissionByEnterpriseKey = {};
|
|
3
|
+
cataloguePermissions
|
|
4
|
+
// Sort by enterprise
|
|
5
|
+
.sort((a, b) => a.enterprise.toLocaleLowerCase().localeCompare(b.enterprise.toLocaleLowerCase()))
|
|
6
|
+
.forEach((c) => {
|
|
7
|
+
const enterprise = c.enterprise.toLowerCase();
|
|
8
|
+
if (cataloguePermissionByEnterpriseKey[enterprise] === undefined) {
|
|
9
|
+
cataloguePermissionByEnterpriseKey[enterprise] = [];
|
|
10
|
+
}
|
|
11
|
+
cataloguePermissionByEnterpriseKey[enterprise].push(c);
|
|
12
|
+
});
|
|
13
|
+
// Sort by prdcat
|
|
14
|
+
Object.keys(cataloguePermissionByEnterpriseKey).forEach((enterprise) => cataloguePermissionByEnterpriseKey[enterprise].sort((a, b) => a.prdCat.toLocaleLowerCase().localeCompare(b.prdCat.toLocaleLowerCase())));
|
|
15
|
+
return cataloguePermissionByEnterpriseKey;
|
|
16
|
+
};
|
|
17
|
+
export const isParamSet = (param) => param !== undefined && param !== "" && param !== "-";
|
|
18
|
+
export const createCataloguePermissionsFilter = (cid, enterprise, prdCat, prdCatVersion, priceList, vendor) => (perm) => (cid === undefined || cid === perm.cid) &&
|
|
19
|
+
(!isParamSet(enterprise) || enterprise === perm.enterprise) &&
|
|
20
|
+
(!isParamSet(prdCat) || prdCat === perm.prdCat) &&
|
|
21
|
+
(!isParamSet(prdCatVersion) || prdCatVersion === perm.prdCatVersion) &&
|
|
22
|
+
(!isParamSet(vendor) ||
|
|
23
|
+
perm.vendors === undefined ||
|
|
24
|
+
perm.vendors.some((v) => vendor === v)) &&
|
|
25
|
+
(!isParamSet(priceList) ||
|
|
26
|
+
perm.priceLists === undefined ||
|
|
27
|
+
perm.priceLists.some((p) => priceList === p));
|
|
28
|
+
/**
|
|
29
|
+
* Sometimes you will want to use the latest available prdCatVersion. This method will
|
|
30
|
+
* find the highest prdCatVersion version in the cataloguePermissions. If the versions are
|
|
31
|
+
* numeric ("1", "4.3", "0.2") they will be numerically compared, otherwise non localized
|
|
32
|
+
* string compare.
|
|
33
|
+
*/
|
|
34
|
+
export const getPrdCatVersionFromPermissions = (cataloguePermissions, cid, enterprise, prdCat, priceList, vendor) => {
|
|
35
|
+
const filter = createCataloguePermissionsFilter(cid, enterprise, prdCat, "-", priceList, vendor);
|
|
36
|
+
const applicablePermissions = cataloguePermissions.filter(filter);
|
|
37
|
+
return applicablePermissions.reduce((pVersion, c) => {
|
|
38
|
+
const cVersion = c.prdCatVersion;
|
|
39
|
+
if (pVersion === undefined) {
|
|
40
|
+
return cVersion;
|
|
41
|
+
}
|
|
42
|
+
const pNum = parseFloat(pVersion);
|
|
43
|
+
const cNum = parseFloat(cVersion);
|
|
44
|
+
if (isNaN(pNum) || isNaN(cNum)) {
|
|
45
|
+
return pVersion < cVersion ? cVersion : pVersion;
|
|
46
|
+
}
|
|
47
|
+
return pNum < cNum ? cVersion : pVersion;
|
|
48
|
+
}, undefined);
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Sometimes you will want a missing prdCatVersion to represent "Get the current highest version".
|
|
52
|
+
* This method will, if the prdCatVersion is not set, fetch the highest available from the catalogue
|
|
53
|
+
* permissions. If it fails to find any applicable permissions the original value is returned.
|
|
54
|
+
* @param auth
|
|
55
|
+
* @param params
|
|
56
|
+
*/
|
|
57
|
+
export const getPrdCatVersionOrLatestFromPermissions = (params, cataloguePermissions) => {
|
|
58
|
+
const { cid, enterprise, prdCat, prdCatVersion, priceList, vendor } = params;
|
|
59
|
+
if (isParamSet(prdCatVersion)) {
|
|
60
|
+
return prdCatVersion;
|
|
61
|
+
}
|
|
62
|
+
const highestFoundVersion = getPrdCatVersionFromPermissions(cataloguePermissions, cid, enterprise, prdCat, priceList, vendor);
|
|
63
|
+
if (highestFoundVersion === undefined) {
|
|
64
|
+
return prdCatVersion;
|
|
65
|
+
}
|
|
66
|
+
return highestFoundVersion;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Sometimes you will want a missing prdCatVersion to represent "Get the current highest version".
|
|
70
|
+
* This method will, if the prdCatVersion is not set, fetch the highest available from the
|
|
71
|
+
* cataloguePermissions and insert it into a copy of the original params. If it fails to find any
|
|
72
|
+
* applicable auth-permissions the original value is returned.
|
|
73
|
+
* @param auth
|
|
74
|
+
* @param params
|
|
75
|
+
*/
|
|
76
|
+
export const fillMissingPrdCatVersionFromPermissions = (params, cataloguePermissions) => (Object.assign(Object.assign({}, params), { prdCatVersion: getPrdCatVersionOrLatestFromPermissions(params, cataloguePermissions) }));
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare class NumericValuesSelection {
|
|
3
|
-
constructor(rawRanges:
|
|
4
|
-
readonly ranges: (NumericValueRangeDefinition | NumericValueDiscrete)[];
|
|
5
|
-
includesValue(value: number): boolean;
|
|
6
|
-
get first(): number;
|
|
7
|
-
get legend(): string;
|
|
8
|
-
}
|
|
9
|
-
export declare class NumericValueDiscrete {
|
|
10
|
-
readonly value: number;
|
|
11
|
-
constructor(value: number);
|
|
12
|
-
includesValue(value: number): boolean;
|
|
13
|
-
get first(): number;
|
|
14
|
-
get legend(): string;
|
|
15
|
-
}
|
|
16
|
-
export declare class NumericValueRangeDefinition {
|
|
17
|
-
constructor(rawRange:
|
|
18
|
-
readonly minValue: number;
|
|
19
|
-
readonly maxValue: number;
|
|
20
|
-
readonly increment: number | undefined;
|
|
21
|
-
includesValue(value: number): boolean;
|
|
22
|
-
get first(): number;
|
|
23
|
-
get legend(): string;
|
|
24
|
-
}
|
|
1
|
+
import { DtoCodeRange } from "./CatalogueAPI.js";
|
|
2
|
+
export declare class NumericValuesSelection {
|
|
3
|
+
constructor(rawRanges: DtoCodeRange[]);
|
|
4
|
+
readonly ranges: (NumericValueRangeDefinition | NumericValueDiscrete)[];
|
|
5
|
+
includesValue(value: number): boolean;
|
|
6
|
+
get first(): number;
|
|
7
|
+
get legend(): string;
|
|
8
|
+
}
|
|
9
|
+
export declare class NumericValueDiscrete {
|
|
10
|
+
readonly value: number;
|
|
11
|
+
constructor(value: number);
|
|
12
|
+
includesValue(value: number): boolean;
|
|
13
|
+
get first(): number;
|
|
14
|
+
get legend(): string;
|
|
15
|
+
}
|
|
16
|
+
export declare class NumericValueRangeDefinition {
|
|
17
|
+
constructor(rawRange: DtoCodeRange);
|
|
18
|
+
readonly minValue: number;
|
|
19
|
+
readonly maxValue: number;
|
|
20
|
+
readonly increment: number | undefined;
|
|
21
|
+
includesValue(value: number): boolean;
|
|
22
|
+
get first(): number;
|
|
23
|
+
get legend(): string;
|
|
24
|
+
}
|
|
25
25
|
//# sourceMappingURL=utilitiesNumericValues.d.ts.map
|
|
@@ -1,109 +1,109 @@
|
|
|
1
|
-
/** Rounds the supplied value to 3 decimal points. */
|
|
2
|
-
function round(v) {
|
|
3
|
-
return Math.round(v * 1000) / 1000;
|
|
4
|
-
}
|
|
5
|
-
export class NumericValuesSelection {
|
|
6
|
-
constructor(rawRanges) {
|
|
7
|
-
if (rawRanges.length === 0) {
|
|
8
|
-
throw new Error("A numeric values selection must have at least one value");
|
|
9
|
-
}
|
|
10
|
-
this.ranges = rawRanges.map((rawRange) => {
|
|
11
|
-
const { minValue, maxValue } = rawRange;
|
|
12
|
-
if (minValue === maxValue) {
|
|
13
|
-
return new NumericValueDiscrete(minValue);
|
|
14
|
-
}
|
|
15
|
-
else {
|
|
16
|
-
return new NumericValueRangeDefinition(rawRange);
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
includesValue(value) {
|
|
21
|
-
return this.ranges.some((range) => range.includesValue(value));
|
|
22
|
-
}
|
|
23
|
-
get first() {
|
|
24
|
-
return this.ranges[0].first;
|
|
25
|
-
}
|
|
26
|
-
get legend() {
|
|
27
|
-
return this.ranges
|
|
28
|
-
.sort((l, r) => l.first - r.first)
|
|
29
|
-
.map((range) => range.legend)
|
|
30
|
-
.join(", ");
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
export class NumericValueDiscrete {
|
|
34
|
-
constructor(value) {
|
|
35
|
-
this.value = value;
|
|
36
|
-
}
|
|
37
|
-
includesValue(value) {
|
|
38
|
-
return value === this.value;
|
|
39
|
-
}
|
|
40
|
-
get first() {
|
|
41
|
-
return this.value;
|
|
42
|
-
}
|
|
43
|
-
get legend() {
|
|
44
|
-
return `${round(this.value)}`;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
export class NumericValueRangeDefinition {
|
|
48
|
-
constructor(rawRange) {
|
|
49
|
-
const { minValue, maxValue, increment } = rawRange;
|
|
50
|
-
this.minValue = minValue;
|
|
51
|
-
this.maxValue = maxValue;
|
|
52
|
-
this.increment = increment === 0 ? undefined : increment;
|
|
53
|
-
}
|
|
54
|
-
includesValue(value) {
|
|
55
|
-
const { minValue: start, maxValue: end, increment: step } = this;
|
|
56
|
-
if (value < start || end < value) {
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
// TODO: This comparison will often fail due to the fact that all the values used are
|
|
60
|
-
// base-2 (binary) floating point numbers based on base-10 (decimal) input strings.
|
|
61
|
-
//
|
|
62
|
-
// Such calculations are often not 100% accurate as is visible in JS by simply
|
|
63
|
-
// computing "0.1 + 0.2" which should equal about "0.30000000000000004" != "0.3".
|
|
64
|
-
//
|
|
65
|
-
// The easiest workaround is to define an static accuracy, say "6 decimals" and round
|
|
66
|
-
// everything when comparing. One could also use a scaled version of Number.EPSILON to
|
|
67
|
-
// dynamically match the precision to the precision of the input numbers.
|
|
68
|
-
//
|
|
69
|
-
// Both workarounds share the same problem however; an infinite number of numbers will be
|
|
70
|
-
// included in the range since an "infinite" number of values will map to the same rounded
|
|
71
|
-
// actual number.
|
|
72
|
-
//
|
|
73
|
-
// The proper fix is probably to use a fixed point mathematics, where we either define a
|
|
74
|
-
// maximum of say 6 decimals or the number of decimals vary on the number of decimals given
|
|
75
|
-
// in the JSON for each value.
|
|
76
|
-
//
|
|
77
|
-
// This should work given that the input in CatCreator is decimal (human created string) and
|
|
78
|
-
// both XML and JSON uses string based decimal numbers. One question mark remains however,
|
|
79
|
-
// and that is how the numbers are stored in CatCreator if you use a db3-file. If it is a
|
|
80
|
-
// string there as well, everything is dandy. Otherwise we might get problems with rounding
|
|
81
|
-
// or infinite decimals during the conversions to/from the db3-file.
|
|
82
|
-
return step === undefined || (value - start) % step === 0;
|
|
83
|
-
}
|
|
84
|
-
get first() {
|
|
85
|
-
return this.minValue;
|
|
86
|
-
}
|
|
87
|
-
get legend() {
|
|
88
|
-
const { minValue, maxValue, increment } = this;
|
|
89
|
-
if (increment === undefined) {
|
|
90
|
-
return `[${round(minValue)} ... ${round(maxValue)}]`;
|
|
91
|
-
}
|
|
92
|
-
const steps = 1 + Math.floor((maxValue - minValue) / increment);
|
|
93
|
-
let legend = `[${round(minValue)}`;
|
|
94
|
-
if (increment !== undefined && 3 <= steps) {
|
|
95
|
-
legend += `, ${round(minValue + increment)}`;
|
|
96
|
-
}
|
|
97
|
-
if (5 <= steps) {
|
|
98
|
-
legend += " ... ";
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
legend += ", ";
|
|
102
|
-
}
|
|
103
|
-
if (4 <= steps) {
|
|
104
|
-
legend += `${round(minValue + increment * (steps - 2))}, `;
|
|
105
|
-
}
|
|
106
|
-
legend += `${round(minValue + increment * (steps - 1))}]`;
|
|
107
|
-
return legend;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
1
|
+
/** Rounds the supplied value to 3 decimal points. */
|
|
2
|
+
function round(v) {
|
|
3
|
+
return Math.round(v * 1000) / 1000;
|
|
4
|
+
}
|
|
5
|
+
export class NumericValuesSelection {
|
|
6
|
+
constructor(rawRanges) {
|
|
7
|
+
if (rawRanges.length === 0) {
|
|
8
|
+
throw new Error("A numeric values selection must have at least one value");
|
|
9
|
+
}
|
|
10
|
+
this.ranges = rawRanges.map((rawRange) => {
|
|
11
|
+
const { minValue, maxValue } = rawRange;
|
|
12
|
+
if (minValue === maxValue) {
|
|
13
|
+
return new NumericValueDiscrete(minValue);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
return new NumericValueRangeDefinition(rawRange);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
includesValue(value) {
|
|
21
|
+
return this.ranges.some((range) => range.includesValue(value));
|
|
22
|
+
}
|
|
23
|
+
get first() {
|
|
24
|
+
return this.ranges[0].first;
|
|
25
|
+
}
|
|
26
|
+
get legend() {
|
|
27
|
+
return this.ranges
|
|
28
|
+
.sort((l, r) => l.first - r.first)
|
|
29
|
+
.map((range) => range.legend)
|
|
30
|
+
.join(", ");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export class NumericValueDiscrete {
|
|
34
|
+
constructor(value) {
|
|
35
|
+
this.value = value;
|
|
36
|
+
}
|
|
37
|
+
includesValue(value) {
|
|
38
|
+
return value === this.value;
|
|
39
|
+
}
|
|
40
|
+
get first() {
|
|
41
|
+
return this.value;
|
|
42
|
+
}
|
|
43
|
+
get legend() {
|
|
44
|
+
return `${round(this.value)}`;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export class NumericValueRangeDefinition {
|
|
48
|
+
constructor(rawRange) {
|
|
49
|
+
const { minValue, maxValue, increment } = rawRange;
|
|
50
|
+
this.minValue = minValue;
|
|
51
|
+
this.maxValue = maxValue;
|
|
52
|
+
this.increment = increment === 0 ? undefined : increment;
|
|
53
|
+
}
|
|
54
|
+
includesValue(value) {
|
|
55
|
+
const { minValue: start, maxValue: end, increment: step } = this;
|
|
56
|
+
if (value < start || end < value) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
// TODO: This comparison will often fail due to the fact that all the values used are
|
|
60
|
+
// base-2 (binary) floating point numbers based on base-10 (decimal) input strings.
|
|
61
|
+
//
|
|
62
|
+
// Such calculations are often not 100% accurate as is visible in JS by simply
|
|
63
|
+
// computing "0.1 + 0.2" which should equal about "0.30000000000000004" != "0.3".
|
|
64
|
+
//
|
|
65
|
+
// The easiest workaround is to define an static accuracy, say "6 decimals" and round
|
|
66
|
+
// everything when comparing. One could also use a scaled version of Number.EPSILON to
|
|
67
|
+
// dynamically match the precision to the precision of the input numbers.
|
|
68
|
+
//
|
|
69
|
+
// Both workarounds share the same problem however; an infinite number of numbers will be
|
|
70
|
+
// included in the range since an "infinite" number of values will map to the same rounded
|
|
71
|
+
// actual number.
|
|
72
|
+
//
|
|
73
|
+
// The proper fix is probably to use a fixed point mathematics, where we either define a
|
|
74
|
+
// maximum of say 6 decimals or the number of decimals vary on the number of decimals given
|
|
75
|
+
// in the JSON for each value.
|
|
76
|
+
//
|
|
77
|
+
// This should work given that the input in CatCreator is decimal (human created string) and
|
|
78
|
+
// both XML and JSON uses string based decimal numbers. One question mark remains however,
|
|
79
|
+
// and that is how the numbers are stored in CatCreator if you use a db3-file. If it is a
|
|
80
|
+
// string there as well, everything is dandy. Otherwise we might get problems with rounding
|
|
81
|
+
// or infinite decimals during the conversions to/from the db3-file.
|
|
82
|
+
return step === undefined || (value - start) % step === 0;
|
|
83
|
+
}
|
|
84
|
+
get first() {
|
|
85
|
+
return this.minValue;
|
|
86
|
+
}
|
|
87
|
+
get legend() {
|
|
88
|
+
const { minValue, maxValue, increment } = this;
|
|
89
|
+
if (increment === undefined) {
|
|
90
|
+
return `[${round(minValue)} ... ${round(maxValue)}]`;
|
|
91
|
+
}
|
|
92
|
+
const steps = 1 + Math.floor((maxValue - minValue) / increment);
|
|
93
|
+
let legend = `[${round(minValue)}`;
|
|
94
|
+
if (increment !== undefined && 3 <= steps) {
|
|
95
|
+
legend += `, ${round(minValue + increment)}`;
|
|
96
|
+
}
|
|
97
|
+
if (5 <= steps) {
|
|
98
|
+
legend += " ... ";
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
legend += ", ";
|
|
102
|
+
}
|
|
103
|
+
if (4 <= steps) {
|
|
104
|
+
legend += `${round(minValue + increment * (steps - 2))}, `;
|
|
105
|
+
}
|
|
106
|
+
legend += `${round(minValue + increment * (steps - 1))}]`;
|
|
107
|
+
return legend;
|
|
108
|
+
}
|
|
109
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@configura/web-api",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.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": "
|
|
26
|
+
"@configura/web-utilities": "2.0.0-alpha.1"
|
|
27
27
|
},
|
|
28
|
-
"gitHead": "
|
|
28
|
+
"gitHead": "f35367369c2e0189ed8181ae91040a149c729368"
|
|
29
29
|
}
|