@configura/web-api 1.3.0-alpha.0 → 1.3.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -201
- package/README.md +1 -1
- package/dist/CatalogueAPI.d.ts +448 -448
- package/dist/CatalogueAPI.js +206 -206
- package/dist/CfgProduct.d.ts +116 -116
- package/dist/CfgProduct.js +588 -588
- package/dist/index.d.ts +15 -15
- package/dist/index.js +15 -15
- package/dist/material/CfgMaterialMapping.d.ts +7 -7
- package/dist/material/CfgMaterialMapping.js +176 -176
- 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 +134 -80
- package/dist/productConfiguration/CfgFeature.js +483 -451
- package/dist/productConfiguration/CfgOption.d.ts +112 -64
- package/dist/productConfiguration/CfgOption.js +293 -263
- package/dist/productConfiguration/CfgProductConfiguration.d.ts +50 -50
- package/dist/productConfiguration/CfgProductConfiguration.js +198 -198
- package/dist/productConfiguration/filters.d.ts +7 -7
- package/dist/productConfiguration/filters.js +29 -29
- package/dist/productConfiguration/productParamsGenerator.d.ts +15 -15
- package/dist/productConfiguration/productParamsGenerator.js +51 -51
- package/dist/productConfiguration/utilitiesProductConfiguration.d.ts +9 -9
- package/dist/productConfiguration/utilitiesProductConfiguration.js +61 -61
- package/dist/productLoader.d.ts +11 -11
- package/dist/productLoader.js +41 -41
- package/dist/tests/testData/collectorForTest.d.ts +73 -73
- package/dist/tests/testData/collectorForTest.js +195 -195
- package/dist/tests/testData/dummyProductForTest.d.ts +4 -4
- package/dist/tests/testData/dummyProductForTest.js +35 -35
- package/dist/tests/testData/testDataAdditionalProductInAdditionalProductInProductForTest.d.ts +32 -32
- package/dist/tests/testData/testDataAdditionalProductInAdditionalProductInProductForTest.js +368 -368
- package/dist/tests/testData/testDataCachedGetProduct.d.ts +5 -5
- package/dist/tests/testData/testDataCachedGetProduct.js +199 -199
- package/dist/tests/testData/testDataCachedPostValidate.d.ts +7 -7
- package/dist/tests/testData/testDataCachedPostValidate.js +189 -189
- package/dist/tests/testData/testDataNoAdditionalProductNoPropagateForTest.d.ts +3 -3
- package/dist/tests/testData/testDataNoAdditionalProductNoPropagateForTest.js +1117 -1117
- package/dist/tests/testData/testDataProductAggregatedPrice.d.ts +28 -28
- package/dist/tests/testData/testDataProductAggregatedPrice.js +205 -205
- package/dist/tests/testData/testDataUpcharge.d.ts +29 -29
- package/dist/tests/testData/testDataUpcharge.js +159 -159
- package/dist/utilitiesCatalogueData.d.ts +20 -18
- package/dist/utilitiesCatalogueData.js +64 -56
- package/dist/utilitiesCataloguePermission.d.ts +39 -39
- package/dist/utilitiesCataloguePermission.js +84 -84
- package/package.json +3 -3
|
@@ -1,263 +1,293 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
import { compareArrays, count, Observable } from "@configura/web-utilities";
|
|
11
|
-
import { CfgProduct } from "../CfgProduct.js";
|
|
12
|
-
import { CfgMtrlApplication } from "../material/CfgMtrlApplication.js";
|
|
13
|
-
import { CfgMtrlApplicationSource } from "../material/CfgMtrlApplicationSource.js";
|
|
14
|
-
import { recursivelyGetPriceCodeValue } from "../utilitiesCatalogueData.js";
|
|
15
|
-
import { CfgFeature, SelectionType } from "./CfgFeature.js";
|
|
16
|
-
import { getMtrlPreview, syncCfgFeatures } from "./utilitiesProductConfiguration.js";
|
|
17
|
-
export var ProductConfigurationBubbleMode;
|
|
18
|
-
(function (ProductConfigurationBubbleMode) {
|
|
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
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
this.
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
}
|
|
249
|
-
get
|
|
250
|
-
return this._internal.
|
|
251
|
-
}
|
|
252
|
-
get
|
|
253
|
-
return this._internal.
|
|
254
|
-
}
|
|
255
|
-
get
|
|
256
|
-
return this._internal.
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { compareArrays, count, Observable } from "@configura/web-utilities";
|
|
11
|
+
import { CfgProduct } from "../CfgProduct.js";
|
|
12
|
+
import { CfgMtrlApplication } from "../material/CfgMtrlApplication.js";
|
|
13
|
+
import { CfgMtrlApplicationSource } from "../material/CfgMtrlApplicationSource.js";
|
|
14
|
+
import { recursivelyGetPriceCodeValue } from "../utilitiesCatalogueData.js";
|
|
15
|
+
import { CfgFeature, SelectionType } from "./CfgFeature.js";
|
|
16
|
+
import { getMtrlPreview, syncCfgFeatures } from "./utilitiesProductConfiguration.js";
|
|
17
|
+
export var ProductConfigurationBubbleMode;
|
|
18
|
+
(function (ProductConfigurationBubbleMode) {
|
|
19
|
+
/**
|
|
20
|
+
* Bubble to the closest CfgProduct, let it revalidate, then that will continue
|
|
21
|
+
* the bubble after validate. Turns on all ancestors all the way up.
|
|
22
|
+
*/
|
|
23
|
+
ProductConfigurationBubbleMode["Validate"] = "Validate";
|
|
24
|
+
/**
|
|
25
|
+
* Bubble to the closest CfgProduct, let it revalidate, then that will continue
|
|
26
|
+
* the bubble after validate. If this is select it will turns on all ancestors all the way up.
|
|
27
|
+
* So with this mode it is possible to select an option where its parents are not selected.
|
|
28
|
+
*/
|
|
29
|
+
ProductConfigurationBubbleMode["ValidateAndBubbleSelected"] = "ValidateAndBubbleSelected";
|
|
30
|
+
/**
|
|
31
|
+
* Stop bubbling
|
|
32
|
+
* This mode supports internal functionality and is not expected to be used by integrators.
|
|
33
|
+
*/
|
|
34
|
+
ProductConfigurationBubbleMode["Stop"] = "Stop";
|
|
35
|
+
/**
|
|
36
|
+
* Bubble to the next level up the tree. In features-options the next level is considered
|
|
37
|
+
* the next feature, so option levels are skipped over. The node we call from notifies its
|
|
38
|
+
* parent, and the parent switches out the reference to the node. Then bubbling stops.
|
|
39
|
+
* This mode supports internal functionality and is not expected to be used by integrators.
|
|
40
|
+
*/
|
|
41
|
+
ProductConfigurationBubbleMode["OneLevel"] = "OneLevel";
|
|
42
|
+
/**
|
|
43
|
+
* Bubble to the closest CfgProduct without doing any validation
|
|
44
|
+
* This mode supports internal functionality and is not expected to be used by integrators.
|
|
45
|
+
*/
|
|
46
|
+
ProductConfigurationBubbleMode["ToParentProduct"] = "ToParentProduct";
|
|
47
|
+
/**
|
|
48
|
+
* Bubble to the root CfgProduct
|
|
49
|
+
* This mode supports internal functionality and is not expected to be used by integrators.
|
|
50
|
+
*/
|
|
51
|
+
ProductConfigurationBubbleMode["ToRoot"] = "ToRoot";
|
|
52
|
+
})(ProductConfigurationBubbleMode || (ProductConfigurationBubbleMode = {}));
|
|
53
|
+
/**
|
|
54
|
+
* This class is meant to only be used through CfgOption. It should
|
|
55
|
+
* never be instantiated on its own. Normally the internal state of this class
|
|
56
|
+
* should never be directly modified. CfgOption is the class that
|
|
57
|
+
* should be used and interacted with.
|
|
58
|
+
*/
|
|
59
|
+
export class _CfgOptionInternal {
|
|
60
|
+
constructor(rawOption, parent, allRawFeatures, siblingHasDuplicateDescription, parentProduct, rootProduct) {
|
|
61
|
+
this.rawOption = rawOption;
|
|
62
|
+
this.parent = parent;
|
|
63
|
+
this.allRawFeatures = allRawFeatures;
|
|
64
|
+
this.parentProduct = parentProduct;
|
|
65
|
+
this.rootProduct = rootProduct;
|
|
66
|
+
this.changeObservable = new Observable();
|
|
67
|
+
/** Called by child to tell its parent that it has changed. */
|
|
68
|
+
this._childHasChanged = (freshRef, bubbleMode) => __awaiter(this, void 0, void 0, function* () {
|
|
69
|
+
const features = this._features;
|
|
70
|
+
if (features === undefined) {
|
|
71
|
+
throw Error("Child says it changed, but no children has actually been generated");
|
|
72
|
+
}
|
|
73
|
+
const i = features.findIndex((a) => a.isBackedBySame(freshRef));
|
|
74
|
+
if (i === -1) {
|
|
75
|
+
throw Error("Child feature not found");
|
|
76
|
+
}
|
|
77
|
+
features[i] = freshRef;
|
|
78
|
+
// In CfgOption we let stop bubble slip through. This is because CfgOption is sort of
|
|
79
|
+
// a semi level. Like Feature + Option together constitutes one level.
|
|
80
|
+
let change = false;
|
|
81
|
+
if (bubbleMode === ProductConfigurationBubbleMode.ValidateAndBubbleSelected) {
|
|
82
|
+
// If there is a change selectOption will take care of the bubble
|
|
83
|
+
change = yield this.parent.selectOption(this, true, bubbleMode);
|
|
84
|
+
}
|
|
85
|
+
if (!change) {
|
|
86
|
+
// There was no change, or we did not try validate, so the normal childHasChanged
|
|
87
|
+
// takes over.
|
|
88
|
+
yield this.parent._childHasChanged(this, bubbleMode);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
this.getApiSelection = () => {
|
|
92
|
+
const { features, code } = this;
|
|
93
|
+
const selectionTrees = features.map((f) => f._internal.getApiSelection());
|
|
94
|
+
const mergedSelectionTree = {};
|
|
95
|
+
let anyItems = false;
|
|
96
|
+
for (const selectionTree of selectionTrees) {
|
|
97
|
+
if (selectionTree === undefined) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
for (const key of Object.keys(selectionTree)) {
|
|
101
|
+
if (mergedSelectionTree[key] !== undefined) {
|
|
102
|
+
console.warn(`The key (${key}) is already used in the selection tree. Option key: "${this.key}".`);
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
mergedSelectionTree[key] = selectionTree[key];
|
|
106
|
+
anyItems = true;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const selectedOption = {
|
|
110
|
+
code: code,
|
|
111
|
+
};
|
|
112
|
+
if (anyItems) {
|
|
113
|
+
selectedOption.next = mergedSelectionTree;
|
|
114
|
+
}
|
|
115
|
+
return selectedOption;
|
|
116
|
+
};
|
|
117
|
+
this.setApiSelection = (apiOptionSelection) => __awaiter(this, void 0, void 0, function* () {
|
|
118
|
+
let features;
|
|
119
|
+
if (apiOptionSelection === undefined) {
|
|
120
|
+
features = this._features || []; // All already generated children
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
features = this.features; // This will generate all children
|
|
124
|
+
}
|
|
125
|
+
return (yield Promise.all(features.map((f) => f._internal.setApiSelection(apiOptionSelection ? apiOptionSelection.next : undefined)))).some((b) => b);
|
|
126
|
+
});
|
|
127
|
+
this.structureCompare = (other, strictOrder = true, descriptionMatch = false) => this.keyMatch(other, descriptionMatch) &&
|
|
128
|
+
compareArrays(this.features, other.features, (l, r) => l._internal.structureCompare(r._internal, strictOrder, descriptionMatch), strictOrder);
|
|
129
|
+
this.tryMatchSelection = (other, descriptionMatch = false) => __awaiter(this, void 0, void 0, function* () {
|
|
130
|
+
return (yield Promise.all(other.features.map((otherF) => (() => __awaiter(this, void 0, void 0, function* () {
|
|
131
|
+
if (1 <
|
|
132
|
+
count(other.features, (item) => item._internal.keyMatch(otherF._internal, descriptionMatch))) {
|
|
133
|
+
console.warn("tryMatchSelection will ignore items with same key");
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
const toSetFeatures = this.features.filter((f) => f._internal.keyMatch(otherF._internal, descriptionMatch));
|
|
137
|
+
if (1 < toSetFeatures.length) {
|
|
138
|
+
console.warn("tryMatchSelection will ignore items with same key");
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
if (toSetFeatures.length === 0) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
return yield toSetFeatures[0]._internal.tryMatchSelection(otherF._internal, descriptionMatch);
|
|
145
|
+
}))()))).some((b) => b);
|
|
146
|
+
});
|
|
147
|
+
this.keyMatch = (other, descriptionMatch = false) => descriptionMatch
|
|
148
|
+
? this.description.toLowerCase() === other.description.toLowerCase()
|
|
149
|
+
: this.code === other.code;
|
|
150
|
+
this._getFeaturesWithCode = (code) => this.features.reduce((agg, feature) => {
|
|
151
|
+
agg.push(...feature._internal._getFeaturesWithCode(code));
|
|
152
|
+
return agg;
|
|
153
|
+
}, []);
|
|
154
|
+
// Description based key helps when switching between
|
|
155
|
+
// products with similar feature-options tree and trying
|
|
156
|
+
// to retain made selections
|
|
157
|
+
this.key =
|
|
158
|
+
this.description +
|
|
159
|
+
(this.description === "" || siblingHasDuplicateDescription ? this.code : "");
|
|
160
|
+
}
|
|
161
|
+
get code() {
|
|
162
|
+
return this.rawOption.code;
|
|
163
|
+
}
|
|
164
|
+
get description() {
|
|
165
|
+
return this.rawOption.description;
|
|
166
|
+
}
|
|
167
|
+
get selected() {
|
|
168
|
+
return this.parent.isSelected(this);
|
|
169
|
+
}
|
|
170
|
+
get ancestorsSelected() {
|
|
171
|
+
return this.selected && this.parent.ancestorsSelected;
|
|
172
|
+
}
|
|
173
|
+
get mtrlApplications() {
|
|
174
|
+
if (this._mtrlApplications === undefined) {
|
|
175
|
+
this._mtrlApplications = (this.rawOption.mtrlApplications || []).map((m) => CfgMtrlApplication.fromMtrlLikeApplication(CfgMtrlApplicationSource.Option, m));
|
|
176
|
+
}
|
|
177
|
+
return this._mtrlApplications;
|
|
178
|
+
}
|
|
179
|
+
get thumbnail() {
|
|
180
|
+
return this.rawOption.material || getMtrlPreview(this.mtrlApplications);
|
|
181
|
+
}
|
|
182
|
+
get upcharge() {
|
|
183
|
+
let upcharge = this.rawOption.upcharge || 0;
|
|
184
|
+
const priceCodes = this.rawOption.priceCodes || [];
|
|
185
|
+
const prices = this.rootProduct.prices;
|
|
186
|
+
upcharge += recursivelyGetPriceCodeValue(priceCodes, prices) || 0;
|
|
187
|
+
return upcharge;
|
|
188
|
+
}
|
|
189
|
+
get priceChangeAtSelectChange() {
|
|
190
|
+
if (!this.parent.hasUpcharge) {
|
|
191
|
+
return undefined;
|
|
192
|
+
}
|
|
193
|
+
const upcharge = this.upcharge || 0;
|
|
194
|
+
const isSelected = this.parent.isSelected(this);
|
|
195
|
+
if (this.parent.selectionType === SelectionType.SelectMany) {
|
|
196
|
+
return isSelected ? -upcharge : upcharge;
|
|
197
|
+
}
|
|
198
|
+
if (this.parent.selectionType === SelectionType.SelectOne) {
|
|
199
|
+
if (isSelected) {
|
|
200
|
+
return 0;
|
|
201
|
+
}
|
|
202
|
+
const selectedOptions = this.parent.selectedOptions;
|
|
203
|
+
if (1 < selectedOptions.length) {
|
|
204
|
+
throw new Error(`More than one selected in select one. Option key: "${this.key}"`);
|
|
205
|
+
}
|
|
206
|
+
if (selectedOptions.length === 0) {
|
|
207
|
+
return upcharge;
|
|
208
|
+
}
|
|
209
|
+
return upcharge - (selectedOptions[0].upcharge || 0);
|
|
210
|
+
}
|
|
211
|
+
return undefined;
|
|
212
|
+
}
|
|
213
|
+
get features() {
|
|
214
|
+
if (this._features === undefined) {
|
|
215
|
+
const allRefs = this.rawOption.featureRefs || [];
|
|
216
|
+
this._features = syncCfgFeatures(allRefs, [], this.allRawFeatures, this, this.parentProduct, this.rootProduct);
|
|
217
|
+
}
|
|
218
|
+
return this._features;
|
|
219
|
+
}
|
|
220
|
+
_freshRefDescendants() {
|
|
221
|
+
const features = this._features || [];
|
|
222
|
+
for (let i = 0; i < features.length; i++) {
|
|
223
|
+
const featureInternal = features[i]._internal;
|
|
224
|
+
featureInternal._freshRefDescendants();
|
|
225
|
+
features[i] = CfgFeature._makeNewRefFrom(featureInternal);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
export class CfgOption {
|
|
230
|
+
/**
|
|
231
|
+
* Private constructor and make-method because make new ref requires the constructor to
|
|
232
|
+
* take an internal and we don't want those who instantiate CfgOption to have to be aware
|
|
233
|
+
* of the internal.
|
|
234
|
+
*/
|
|
235
|
+
constructor(_internal) {
|
|
236
|
+
this._internal = _internal;
|
|
237
|
+
this.isBackedBySame = (other) => this._internal === other._internal;
|
|
238
|
+
/*
|
|
239
|
+
* Selects this Option.
|
|
240
|
+
* Only Options belonging to Features that are "select many" can be deselected.
|
|
241
|
+
* Calling this will cause a validation call to the server.
|
|
242
|
+
*/
|
|
243
|
+
this.setSelected = (on) => __awaiter(this, void 0, void 0, function* () {
|
|
244
|
+
return yield this._internal.parent.selectOption(this._internal, on, ProductConfigurationBubbleMode.ValidateAndBubbleSelected);
|
|
245
|
+
});
|
|
246
|
+
this.listenForChange = (l) => this._internal.changeObservable.listen(l);
|
|
247
|
+
this.stopListenForChange = (l) => this._internal.changeObservable.stopListen(l);
|
|
248
|
+
}
|
|
249
|
+
get parentProduct() {
|
|
250
|
+
return CfgProduct._makeNewRefFrom(this._internal.parentProduct);
|
|
251
|
+
}
|
|
252
|
+
get rootProduct() {
|
|
253
|
+
return CfgProduct._makeNewRefFrom(this._internal.rootProduct);
|
|
254
|
+
}
|
|
255
|
+
get rawOption() {
|
|
256
|
+
return this._internal.rawOption;
|
|
257
|
+
}
|
|
258
|
+
get key() {
|
|
259
|
+
return this._internal.key;
|
|
260
|
+
}
|
|
261
|
+
get code() {
|
|
262
|
+
return this._internal.code;
|
|
263
|
+
}
|
|
264
|
+
get description() {
|
|
265
|
+
return this._internal.description;
|
|
266
|
+
}
|
|
267
|
+
get selected() {
|
|
268
|
+
return this._internal.selected;
|
|
269
|
+
}
|
|
270
|
+
/** Are all ancestors up to the CfgProductConfiguration selected? Includes self. */
|
|
271
|
+
get ancestorsSelected() {
|
|
272
|
+
return this._internal.ancestorsSelected;
|
|
273
|
+
}
|
|
274
|
+
get thumbnail() {
|
|
275
|
+
return this._internal.thumbnail;
|
|
276
|
+
}
|
|
277
|
+
get upcharge() {
|
|
278
|
+
return this._internal.upcharge;
|
|
279
|
+
}
|
|
280
|
+
get priceChangeAtSelectChange() {
|
|
281
|
+
return this._internal.priceChangeAtSelectChange;
|
|
282
|
+
}
|
|
283
|
+
get features() {
|
|
284
|
+
return this._internal.features;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
CfgOption.make = (rawOption, parent, allRawFeatures, siblingHasDuplicateDescription, parentProduct, rootProduct) => new CfgOption(new _CfgOptionInternal(rawOption, parent, allRawFeatures, siblingHasDuplicateDescription, parentProduct, rootProduct));
|
|
288
|
+
/**
|
|
289
|
+
* Makes an object wrapping the passed object. This is not a clone method,
|
|
290
|
+
* it is a method to make a new outer reference. Like a shallow copy.
|
|
291
|
+
* We use this to help frameworks that are build around using equals to detect change.
|
|
292
|
+
*/
|
|
293
|
+
CfgOption._makeNewRefFrom = (internal) => new CfgOption(internal);
|