@configura/web-api 1.5.0-alpha.0 → 1.6.1-alpha.0

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.
Files changed (42) hide show
  1. package/dist/CatalogueAPI.d.ts +9 -2
  2. package/dist/CatalogueAPI.js +23 -0
  3. package/dist/CfgMeasure.d.ts +2 -2
  4. package/dist/CfgMeasure.js +1 -1
  5. package/dist/CfgProduct.d.ts +50 -4
  6. package/dist/CfgProduct.js +151 -17
  7. package/dist/index.d.ts +2 -0
  8. package/dist/index.js +2 -0
  9. package/dist/productConfiguration/CfgFeature.d.ts +19 -2
  10. package/dist/productConfiguration/CfgFeature.js +57 -6
  11. package/dist/productConfiguration/CfgOption.d.ts +12 -1
  12. package/dist/productConfiguration/CfgOption.js +29 -2
  13. package/dist/productConfiguration/CfgProductConfiguration.d.ts +4 -2
  14. package/dist/productConfiguration/CfgProductConfiguration.js +17 -0
  15. package/dist/productLoader.d.ts +1 -1
  16. package/dist/syncGroups/SyncGroupsApplier.d.ts +20 -0
  17. package/dist/syncGroups/SyncGroupsApplier.js +519 -0
  18. package/dist/syncGroups/SyncGroupsApplyMode.d.ts +15 -0
  19. package/dist/syncGroups/SyncGroupsApplyMode.js +15 -0
  20. package/dist/syncGroups/SyncGroupsHandler.d.ts +30 -0
  21. package/dist/syncGroups/SyncGroupsHandler.js +71 -0
  22. package/dist/syncGroups/SyncGroupsState.d.ts +20 -0
  23. package/dist/syncGroups/SyncGroupsState.js +61 -0
  24. package/dist/syncGroups/SyncGroupsTransaction.d.ts +50 -0
  25. package/dist/syncGroups/SyncGroupsTransaction.js +106 -0
  26. package/dist/tasks/TaskHandler.js +4 -3
  27. package/dist/tasks/formats.d.ts +1 -3
  28. package/dist/tasks/formats.js +3 -4
  29. package/dist/tests/testData/dummyProductForTest.d.ts +2 -2
  30. package/dist/tests/testData/dummyProductForTest.js +1 -1
  31. package/dist/tests/testData/testDataAdditionalProductInAdditionalProductInProductForTest.d.ts +3 -3
  32. package/dist/tests/testData/testDataAdditionalProductInAdditionalProductInProductForTest.js +27 -98
  33. package/dist/tests/testData/testDataCachedGetProduct.js +8 -19
  34. package/dist/tests/testData/testDataOptions.d.ts +13 -0
  35. package/dist/tests/testData/testDataOptions.js +60 -0
  36. package/dist/tests/testData/testDataProductAggregatedPrice.d.ts +3 -3
  37. package/dist/tests/testData/testDataProductAggregatedPrice.js +14 -25
  38. package/dist/tests/testData/testDataUpcharge.js +16 -48
  39. package/dist/utilitiesCatalogueData.d.ts +7 -1
  40. package/dist/utilitiesCatalogueData.js +102 -0
  41. package/dist/utilitiesNumericValues.d.ts +1 -1
  42. package/package.json +3 -3
@@ -11,6 +11,7 @@ import { compareArrays, convertLength, count, Observable, someMatch, toLengthUni
11
11
  import { CfgProduct } from "../CfgProduct.js";
12
12
  import { CfgMtrlApplication } from "../material/CfgMtrlApplication.js";
13
13
  import { CfgMtrlApplicationSource } from "../material/CfgMtrlApplicationSource.js";
14
+ import { wrapWithCache } from "../productLoader.js";
14
15
  import { CfgOption, ProductConfigurationBubbleMode } from "./CfgOption.js";
15
16
  import { _CfgProductConfigurationInternal } from "./CfgProductConfiguration.js";
16
17
  import { getMtrlPreview } from "./utilitiesProductConfiguration.js";
@@ -306,6 +307,15 @@ export class _CfgFeatureInternal {
306
307
  * Using a validate bubbleMode will cause validation calls to the server.
307
308
  */
308
309
  this.selectOption = (optionInternal, on, bubbleMode) => __awaiter(this, void 0, void 0, function* () {
310
+ if (bubbleMode ===
311
+ ProductConfigurationBubbleMode.ValidateAndBubbleSelectedAndApplySyncGroups) {
312
+ const product = this.rootProduct;
313
+ const syncGroupHandler = product.syncGroupHandler;
314
+ if (syncGroupHandler === undefined) {
315
+ throw new Error(`No sync group handler when bubble mode ${ProductConfigurationBubbleMode.ValidateAndBubbleSelectedAndApplySyncGroups}`);
316
+ }
317
+ return yield syncGroupHandler.selectOption(product, optionInternal.path, on, wrapWithCache(product._productLoaderRaw));
318
+ }
309
319
  if (!on) {
310
320
  if (this.selectionType === SelectionType.Group) {
311
321
  throw new Error(`Multiple features are always selected and are not user selectable. Feature key: "${this.key}".`);
@@ -357,11 +367,18 @@ export class _CfgFeatureInternal {
357
367
  if (isAllOptionsAffectedByAnySelection) {
358
368
  this._freshRefAllOptions();
359
369
  }
360
- // If this was a deselect action we shall not bubble selected, that is, we shall not
361
- // select the ancestors if this action was deselect.
362
- yield this._notifyAllOfChange(!on && bubbleMode === ProductConfigurationBubbleMode.ValidateAndBubbleSelected
363
- ? ProductConfigurationBubbleMode.Validate
364
- : bubbleMode);
370
+ let nextLevelBubbleMode = bubbleMode;
371
+ if (!on) {
372
+ // If this was a deselect action we shall not bubble selected, that is, we shall not
373
+ // select the ancestors if this action was deselect.
374
+ if (bubbleMode === ProductConfigurationBubbleMode.ValidateAndBubbleSelected) {
375
+ nextLevelBubbleMode = ProductConfigurationBubbleMode.Validate;
376
+ }
377
+ else if (bubbleMode === ProductConfigurationBubbleMode.BubbleSelected) {
378
+ nextLevelBubbleMode = ProductConfigurationBubbleMode.ToRoot;
379
+ }
380
+ }
381
+ yield this._notifyAllOfChange(nextLevelBubbleMode);
365
382
  return isActualChange;
366
383
  });
367
384
  this.isSelected = (option) => this.selectionType === SelectionType.Group ||
@@ -412,6 +429,9 @@ export class _CfgFeatureInternal {
412
429
  }
413
430
  return value;
414
431
  }
432
+ get syncGroup() {
433
+ return this.rawFeature.syncGroup;
434
+ }
415
435
  get description() {
416
436
  return this.rawFeature.description;
417
437
  }
@@ -450,12 +470,24 @@ export class _CfgFeatureInternal {
450
470
  get preview() {
451
471
  return getMtrlPreview(this._mtrlApplications);
452
472
  }
473
+ /**
474
+ * Please note that this relates to the visibility in the Configuration tree.
475
+ * It does not affect the visibility of anything in the 3D view at all.
476
+ */
453
477
  get visibleIfAdditionalProduct() {
454
478
  return this.rawFeature.hideIfAdditionalProduct !== true;
455
479
  }
480
+ /**
481
+ * Please note that this relates to the visibility in the Configuration tree.
482
+ * It does not affect the visibility of anything in the 3D view at all.
483
+ */
456
484
  get visibleIfMainProduct() {
457
485
  return this.rawFeature.hideIfMainProduct !== true;
458
486
  }
487
+ /**
488
+ * Please note that this relates to the visibility in the Configuration tree.
489
+ * It does not affect the visibility of anything in the 3D view at all.
490
+ */
459
491
  get visible() {
460
492
  return this.parentProduct.isAdditionalProduct
461
493
  ? this.visibleIfAdditionalProduct
@@ -470,6 +502,23 @@ export class _CfgFeatureInternal {
470
502
  }
471
503
  return this._options;
472
504
  }
505
+ get path() {
506
+ return [...this.parent.path, this.code];
507
+ }
508
+ getFromPath(path) {
509
+ path = path.slice();
510
+ const s = path.shift();
511
+ switch (s) {
512
+ case undefined:
513
+ return this;
514
+ default:
515
+ const option = this.options.find((o) => o.code === s);
516
+ if (option === undefined) {
517
+ throw new Error(`Option not found ${s}, ${path.join(", ")}`);
518
+ }
519
+ return option._internal.getFromPath(path);
520
+ }
521
+ }
473
522
  /**
474
523
  * Make fresh references to all options on this feature.
475
524
  * Also includes currently selected options.
@@ -519,7 +568,7 @@ export class CfgFeature {
519
568
  * Calling this will cause a validation call to the server.
520
569
  */
521
570
  this.selectOption = (option, on) => __awaiter(this, void 0, void 0, function* () {
522
- return yield this._internal.selectOption(option._internal, on, ProductConfigurationBubbleMode.ValidateAndBubbleSelected);
571
+ return yield this._internal.selectOption(option._internal, on, ProductConfigurationBubbleMode.ValidateAndBubbleSelectedAndApplySyncGroups);
523
572
  });
524
573
  this.isSelected = (option) => this._internal.isSelected(option._internal);
525
574
  this.listenForChange = (l) => this._internal.changeObservable.listen(l);
@@ -588,6 +637,8 @@ export class CfgFeature {
588
637
  return this._internal.options;
589
638
  }
590
639
  /**
640
+ * Please note that this relates to the visibility in the Configuration tree.
641
+ * It does not affect the visibility of anything in the 3D view at all.
591
642
  * Visibility is not inherited. If this is hidden the children
592
643
  * of this Feature might still be visible, depending on their settings.
593
644
  */
@@ -1,6 +1,6 @@
1
1
  import { LengthUnit, Observable, SingleArgCallback } from "@configura/web-utilities";
2
2
  import { Feature, Option, SelectedOption } from "../CatalogueAPI.js";
3
- import { CfgProduct, _CfgProductInternal } from "../CfgProduct.js";
3
+ import { CfgPath, CfgProduct, _CfgProductInternal } from "../CfgProduct.js";
4
4
  import { CfgMtrlApplication } from "../material/CfgMtrlApplication.js";
5
5
  import { NumericValuesSelection } from "../utilitiesNumericValues.js";
6
6
  import { CfgFeature, _CfgFeatureInternal } from "./CfgFeature.js";
@@ -9,6 +9,10 @@ export declare type OptionChangeNotification = {
9
9
  freshRef: CfgOption;
10
10
  };
11
11
  export declare enum ProductConfigurationBubbleMode {
12
+ /**
13
+ * If this is select it will turns on all ancestors all the way up.
14
+ */
15
+ BubbleSelected = "BubbleSelected",
12
16
  /**
13
17
  * Bubble to the closest CfgProduct, let it revalidate, then that will continue
14
18
  * the bubble after validate.
@@ -20,6 +24,11 @@ export declare enum ProductConfigurationBubbleMode {
20
24
  * So with this mode it is possible to select an option where its parents are not selected.
21
25
  */
22
26
  ValidateAndBubbleSelected = "ValidateAndBubbleSelected",
27
+ /**
28
+ * Like ValidateAndBubbleSelected, but SyncGroups are applied after
29
+ * ValidateAndBubbleSelected has been done
30
+ */
31
+ ValidateAndBubbleSelectedAndApplySyncGroups = "ValidateAndBubbleSelectedAndApplySyncGroups",
23
32
  /**
24
33
  * Stop bubbling
25
34
  * This mode supports internal functionality and is not expected to be used by integrators.
@@ -81,6 +90,8 @@ export declare class _CfgOptionInternal {
81
90
  _childHasChanged: (freshRef: CfgFeature, bubbleMode: ProductConfigurationBubbleMode) => Promise<void>;
82
91
  getApiSelection: () => SelectedOption;
83
92
  setApiSelection: (apiOptionSelection: SelectedOption | undefined) => Promise<boolean>;
93
+ get path(): CfgPath;
94
+ getFromPath(path: CfgPath): _CfgFeatureInternal | _CfgOptionInternal;
84
95
  structureCompare: (other: _CfgOptionInternal, strictOrder?: boolean, descriptionMatch?: boolean) => boolean;
85
96
  tryMatchSelection: (other: CfgOption, descriptionMatch?: boolean) => Promise<boolean>;
86
97
  keyMatch: (other: _CfgOptionInternal, descriptionMatch?: boolean) => boolean;
@@ -17,6 +17,10 @@ import { CfgFeature, SelectionType } from "./CfgFeature.js";
17
17
  import { getMtrlPreview, syncCfgFeatures } from "./utilitiesProductConfiguration.js";
18
18
  export var ProductConfigurationBubbleMode;
19
19
  (function (ProductConfigurationBubbleMode) {
20
+ /**
21
+ * If this is select it will turns on all ancestors all the way up.
22
+ */
23
+ ProductConfigurationBubbleMode["BubbleSelected"] = "BubbleSelected";
20
24
  /**
21
25
  * Bubble to the closest CfgProduct, let it revalidate, then that will continue
22
26
  * the bubble after validate.
@@ -28,6 +32,11 @@ export var ProductConfigurationBubbleMode;
28
32
  * So with this mode it is possible to select an option where its parents are not selected.
29
33
  */
30
34
  ProductConfigurationBubbleMode["ValidateAndBubbleSelected"] = "ValidateAndBubbleSelected";
35
+ /**
36
+ * Like ValidateAndBubbleSelected, but SyncGroups are applied after
37
+ * ValidateAndBubbleSelected has been done
38
+ */
39
+ ProductConfigurationBubbleMode["ValidateAndBubbleSelectedAndApplySyncGroups"] = "ValidateAndBubbleSelectedAndApplySyncGroups";
31
40
  /**
32
41
  * Stop bubbling
33
42
  * This mode supports internal functionality and is not expected to be used by integrators.
@@ -93,7 +102,8 @@ export class _CfgOptionInternal {
93
102
  features[i] = freshRef;
94
103
  // In CfgOption we let stop bubble slip through. This is because CfgOption is sort of
95
104
  // a semi level. Like Feature + Option together constitutes one level.
96
- if (bubbleMode === ProductConfigurationBubbleMode.ValidateAndBubbleSelected) {
105
+ if (bubbleMode === ProductConfigurationBubbleMode.ValidateAndBubbleSelected ||
106
+ bubbleMode === ProductConfigurationBubbleMode.BubbleSelected) {
97
107
  // selectOption takes care of the bubble
98
108
  yield this.parent.selectOption(this, true, bubbleMode);
99
109
  }
@@ -300,6 +310,23 @@ export class _CfgOptionInternal {
300
310
  }
301
311
  return this._features;
302
312
  }
313
+ get path() {
314
+ return [...this.parent.path, this.code];
315
+ }
316
+ getFromPath(path) {
317
+ path = path.slice();
318
+ const s = path.shift();
319
+ switch (s) {
320
+ case undefined:
321
+ return this;
322
+ default:
323
+ const feature = this.features.find((o) => o.code === s);
324
+ if (feature === undefined) {
325
+ throw new Error(`Feature not found ${s}, ${path.join(", ")}`);
326
+ }
327
+ return feature._internal.getFromPath(path);
328
+ }
329
+ }
303
330
  _freshRefDescendants() {
304
331
  const features = this._features || [];
305
332
  for (let i = 0; i < features.length; i++) {
@@ -326,7 +353,7 @@ export class CfgOption {
326
353
  * Calling this will cause a validation call to the server.
327
354
  */
328
355
  this.setSelected = (on) => __awaiter(this, void 0, void 0, function* () {
329
- return yield this._internal.parent.selectOption(this._internal, on, ProductConfigurationBubbleMode.ValidateAndBubbleSelected);
356
+ return yield this._internal.parent.selectOption(this._internal, on, ProductConfigurationBubbleMode.ValidateAndBubbleSelectedAndApplySyncGroups);
330
357
  });
331
358
  this.listenForChange = (l) => this._internal.changeObservable.listen(l);
332
359
  this.stopListenForChange = (l) => this._internal.changeObservable.stopListen(l);
@@ -1,8 +1,8 @@
1
1
  import { LengthUnit, Observable, SingleArgCallback } from "@configura/web-utilities";
2
2
  import { Feature, FeatureRef, SelectedOption } from "../CatalogueAPI.js";
3
- import { CfgProduct, _CfgProductInternal } from "../CfgProduct.js";
3
+ import { CfgPath, CfgProduct, _CfgProductInternal } from "../CfgProduct.js";
4
4
  import { CfgFeature, _CfgFeatureInternal } from "./CfgFeature.js";
5
- import { ProductConfigurationBubbleMode } from "./CfgOption.js";
5
+ import { ProductConfigurationBubbleMode, _CfgOptionInternal } from "./CfgOption.js";
6
6
  export declare type ProductConfigurationChangeNotification = {
7
7
  freshRef: CfgProductConfiguration;
8
8
  };
@@ -43,6 +43,8 @@ export declare class _CfgProductConfigurationInternal {
43
43
  * outside we want notifications to bubble all the way to the root.
44
44
  */
45
45
  setApiSelection: (selectedOptions: SelectedOption[], bubbleToRoot: boolean) => Promise<boolean>;
46
+ get path(): CfgPath;
47
+ getFromPath(path: CfgPath): _CfgProductConfigurationInternal | _CfgFeatureInternal | _CfgOptionInternal;
46
48
  structureCompare: (other: _CfgProductConfigurationInternal, strictOrder?: boolean, descriptionMatch?: boolean) => boolean;
47
49
  /**
48
50
  * When used internally the notifications are taken care off by the caller, but if set from
@@ -215,6 +215,23 @@ export class _CfgProductConfigurationInternal {
215
215
  features[i] = CfgFeature._makeNewRefFrom(featureInternal);
216
216
  }
217
217
  }
218
+ get path() {
219
+ return [...this.parentProduct.path, "c"];
220
+ }
221
+ getFromPath(path) {
222
+ path = path.slice();
223
+ const s = path.shift();
224
+ switch (s) {
225
+ case undefined:
226
+ return this;
227
+ default:
228
+ const feature = this.features.find((f) => f.code === s);
229
+ if (feature === undefined) {
230
+ throw new Error(`Feature not found ${s}, ${path.join(", ")}`);
231
+ }
232
+ return feature._internal.getFromPath(path);
233
+ }
234
+ }
218
235
  }
219
236
  export class CfgProductConfiguration {
220
237
  /**
@@ -1,4 +1,4 @@
1
- import { GetProductParams, PostValidateParams, ValidateRequest } from "./CatalogueAPI";
1
+ import { GetProductParams, PostValidateParams, ValidateRequest } from "./CatalogueAPI.js";
2
2
  import { CfgProductResponse, CfgValidateResponse } from "./utilitiesCatalogueData.js";
3
3
  export declare type GetProduct = (params: GetProductParams) => Promise<CfgProductResponse>;
4
4
  export declare type PostValidate = (params: PostValidateParams, body: ValidateRequest) => Promise<CfgValidateResponse>;
@@ -0,0 +1,20 @@
1
+ import { SyncGroup } from "../CatalogueAPI.js";
2
+ import { _CfgOptionInternal } from "../productConfiguration/CfgOption.js";
3
+ import { SyncCode } from "./SyncGroupsHandler.js";
4
+ import { SyncGroupsTransaction } from "./SyncGroupsTransaction.js";
5
+ export declare class SyncGroupsApplier {
6
+ /**
7
+ * At load of a new product this is used to move it into a synced state
8
+ */
9
+ static init(transaction: SyncGroupsTransaction): Promise<boolean>;
10
+ /**
11
+ * At an active select of an option this is the entry point
12
+ */
13
+ static selectOption(transaction: SyncGroupsTransaction, option: _CfgOptionInternal, on: boolean): Promise<boolean>;
14
+ /**
15
+ * @returns undefined if the @syncGroup is undefined, false if
16
+ * the @mustSupport is not fulfilled or the syncCode if all is ok
17
+ */
18
+ static getSyncCode(syncGroup: SyncGroup | undefined, mustSupport: "push" | "pull"): SyncCode | undefined | false;
19
+ }
20
+ //# sourceMappingURL=SyncGroupsApplier.d.ts.map