@configura/web-api 2.0.0-alpha.9 → 2.1.0-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 (58) hide show
  1. package/.eslintrc.json +1 -14
  2. package/dist/CatalogueAPI.d.ts +103 -32
  3. package/dist/CatalogueAPI.js +62 -6
  4. package/dist/CfgProduct.d.ts +90 -14
  5. package/dist/CfgProduct.js +266 -56
  6. package/dist/CfgReferencePathHelper.d.ts +3 -3
  7. package/dist/index.d.ts +1 -1
  8. package/dist/index.js +1 -1
  9. package/dist/io/CfgHistoryManager.d.ts +33 -1
  10. package/dist/io/CfgHistoryManager.js +68 -6
  11. package/dist/io/CfgHistoryToProdConfConnector.d.ts +11 -10
  12. package/dist/io/CfgHistoryToProdConfConnector.js +32 -38
  13. package/dist/io/CfgIOManager.d.ts +5 -0
  14. package/dist/io/CfgIOManager.js +20 -1
  15. package/dist/io/CfgIOProdConfConnector.d.ts +17 -18
  16. package/dist/io/CfgIOProdConfConnector.js +52 -58
  17. package/dist/io/CfgIOWarningSupplier.d.ts +4 -0
  18. package/dist/io/CfgIOWarningSupplier.js +1 -0
  19. package/dist/io/CfgObservableStateToProdConfConnector.d.ts +4 -4
  20. package/dist/io/CfgObservableStateToProdConfConnector.js +3 -3
  21. package/dist/io/CfgWindowMessageManager.js +4 -0
  22. package/dist/io/CfgWindowMessageToProdConfConnector.d.ts +4 -4
  23. package/dist/io/CfgWindowMessageToProdConfConnector.js +3 -3
  24. package/dist/productConfiguration/CfgFeature.d.ts +12 -7
  25. package/dist/productConfiguration/CfgFeature.js +33 -14
  26. package/dist/productConfiguration/CfgOption.d.ts +16 -10
  27. package/dist/productConfiguration/CfgOption.js +46 -18
  28. package/dist/productConfiguration/CfgProductConfiguration.d.ts +27 -16
  29. package/dist/productConfiguration/CfgProductConfiguration.js +53 -29
  30. package/dist/productConfiguration/filters.d.ts +6 -4
  31. package/dist/productConfiguration/filters.js +94 -23
  32. package/dist/productConfiguration/productParamsGenerator.d.ts +3 -3
  33. package/dist/productConfiguration/utilitiesProductConfiguration.d.ts +1 -1
  34. package/dist/productConfiguration/utilitiesProductConfiguration.js +11 -4
  35. package/dist/productLoader.d.ts +3 -3
  36. package/dist/productLoader.js +1 -1
  37. package/dist/syncGroups/SyncGroupsHandler.d.ts +9 -2
  38. package/dist/syncGroups/SyncGroupsHandler.js +15 -4
  39. package/dist/syncGroups/SyncGroupsState.d.ts +5 -1
  40. package/dist/syncGroups/SyncGroupsState.js +44 -2
  41. package/dist/syncGroups/SyncGroupsTransaction.js +34 -21
  42. package/dist/tasks/TaskHandler.d.ts +2 -2
  43. package/dist/tasks/TaskHandler.js +2 -1
  44. package/dist/tests/testData/dummyProductForTest.d.ts +2 -2
  45. package/dist/tests/testData/testDataAdditionalProductInAdditionalProductInProductForTest.js +14 -9
  46. package/dist/tests/testData/testDataCachedGetProduct.js +2 -0
  47. package/dist/tests/testData/testDataCachedPostValidate.js +2 -0
  48. package/dist/tests/testData/testDataProductAggregatedPrice.js +3 -1
  49. package/dist/tests/testData/testDataUpcharge.js +2 -0
  50. package/dist/utilitiesCatalogueData.d.ts +14 -9
  51. package/dist/utilitiesCatalogueData.js +7 -0
  52. package/dist/utilitiesCataloguePermission.d.ts +4 -4
  53. package/dist/utilitiesConfiguration.d.ts +29 -0
  54. package/dist/utilitiesConfiguration.js +200 -0
  55. package/dist/utilitiesNumericValues.js +13 -8
  56. package/package.json +3 -3
  57. package/dist/ConfigurationConverter.d.ts +0 -5
  58. package/dist/ConfigurationConverter.js +0 -72
@@ -1,18 +1,18 @@
1
- import { DtoProductConfiguration } from "../CatalogueAPI.js";
1
+ import { DtoProductConf } from "../CatalogueAPI.js";
2
+ import { CfgProdConfParts } from "../utilitiesConfiguration.js";
2
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.
6
7
  * It will also make Stage listen for incoming product configuration update messages.
7
8
  * This can be used to communicate in and out of an iframe for example.
8
- * @param doValidate Run server side product validation for incoming
9
9
  * @param sendVersions What versions of the productConfiguration shall be sent? Multiple can be selected
10
10
  * @param includeExtendedDataInSend Only for version 2.0. Includes unit and groupCode.
11
11
  * @param includeProdParamsInSend Only for version 2.0. Includes product params, in both main and additional products.
12
12
  */
13
13
  export declare class CfgWindowMessageToProdConfConnector extends CfgIOProdConfConnector<CfgProdConfMessage> {
14
14
  private _sendVersions;
15
- constructor(manager: CfgWindowMessageManager, doValidate?: boolean, _sendVersions?: CfgProdConfMessageVersions, includeExtendedDataInSend?: boolean, includeProdParamsInSend?: boolean);
16
- protected makeSendData(conf: DtoProductConfiguration, initial: boolean): CfgProdConfMessage;
15
+ constructor(manager: CfgWindowMessageManager, _sendVersions?: CfgProdConfMessageVersions, includeInSend?: CfgProdConfParts);
16
+ protected makeSendData(conf: DtoProductConf, initial: boolean): CfgProdConfMessage;
17
17
  }
18
18
  //# sourceMappingURL=CfgWindowMessageToProdConfConnector.d.ts.map
@@ -1,16 +1,16 @@
1
+ import { CfgProdConfParts } from "../utilitiesConfiguration.js";
1
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.
5
6
  * This can be used to communicate in and out of an iframe for example.
6
- * @param doValidate Run server side product validation for incoming
7
7
  * @param sendVersions What versions of the productConfiguration shall be sent? Multiple can be selected
8
8
  * @param includeExtendedDataInSend Only for version 2.0. Includes unit and groupCode.
9
9
  * @param includeProdParamsInSend Only for version 2.0. Includes product params, in both main and additional products.
10
10
  */
11
11
  export class CfgWindowMessageToProdConfConnector extends CfgIOProdConfConnector {
12
- constructor(manager, doValidate = true, _sendVersions = CfgProdConfMessageVersions.V2dot0, includeExtendedDataInSend = false, includeProdParamsInSend = false) {
13
- super(manager, doValidate, includeExtendedDataInSend, includeProdParamsInSend);
12
+ constructor(manager, _sendVersions = CfgProdConfMessageVersions.V2dot0, includeInSend = CfgProdConfParts.NoExtra) {
13
+ super(manager, includeInSend);
14
14
  this._sendVersions = _sendVersions;
15
15
  }
16
16
  makeSendData(conf, initial) {
@@ -1,5 +1,5 @@
1
1
  import { LengthUnit, Observable, SingleArgCallback } from "@configura/web-utilities";
2
- import { DtoFeature, DtoFeatureConfiguration, DtoSelectedOption, DtoSyncGroup, DtoSyncGroupMethods } from "../CatalogueAPI.js";
2
+ import { DtoFeature, DtoFeatureConf, DtoNote, 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";
@@ -32,13 +32,13 @@ export declare type FeatureChangeNotification = {
32
32
  */
33
33
  export declare class _CfgFeatureInternal {
34
34
  readonly rawFeature: DtoFeature;
35
- private readonly allRawFeatures;
36
- readonly key: string;
35
+ private readonly rawFeatures;
36
+ private _key;
37
37
  readonly parent: _CfgProductConfigurationInternal | _CfgOptionInternal;
38
38
  readonly parentConfiguration: _CfgProductConfigurationInternal;
39
39
  readonly parentProduct: _CfgProductInternal;
40
40
  readonly rootProduct: _CfgProductInternal;
41
- constructor(rawFeature: DtoFeature, allRawFeatures: DtoFeature[], key: string, // Unique amongst siblings
41
+ constructor(rawFeature: DtoFeature, rawFeatures: DtoFeature[], _key: string, // Unique amongst siblings
42
42
  parent: _CfgProductConfigurationInternal | _CfgOptionInternal, parentConfiguration: _CfgProductConfigurationInternal, parentProduct: _CfgProductInternal, rootProduct: _CfgProductInternal);
43
43
  readonly selectionType: SelectionType;
44
44
  private _options;
@@ -48,10 +48,14 @@ export declare class _CfgFeatureInternal {
48
48
  readonly changeObservable: Observable<FeatureChangeNotification>;
49
49
  get code(): string;
50
50
  get groupCode(): string | undefined;
51
+ get key(): string;
52
+ set key(k: string);
53
+ get notes(): DtoNote[];
51
54
  get isUseNumericValue(): boolean;
52
55
  get numericValue(): number | undefined;
53
56
  setNumericValue: (val: number) => Promise<boolean>;
54
57
  get description(): string;
58
+ get omitOnOrder(): boolean;
55
59
  get syncGroup(): DtoSyncGroup | undefined;
56
60
  /**
57
61
  * @return one of the following, in order:
@@ -99,7 +103,7 @@ export declare class _CfgFeatureInternal {
99
103
  * as nonexisting children can not call their parent.
100
104
  */
101
105
  _childHasChanged: (childOption: _CfgOptionInternal, bubbleMode: ProductConfigurationBubbleMode, committed: boolean) => Promise<void>;
102
- getDtoConf: (includeExtendedData: boolean) => DtoFeatureConfiguration;
106
+ getDtoConf: (includeExtendedData: boolean) => DtoFeatureConf;
103
107
  setApiSelection: (apiOptionSelectionMap: {
104
108
  [index: string]: DtoSelectedOption;
105
109
  } | undefined) => Promise<boolean>;
@@ -124,11 +128,10 @@ export declare class _CfgFeatureInternal {
124
128
  * @throws Will throw if options have not yet been generated.
125
129
  */
126
130
  private _freshRefAllOptions;
127
- _freshRefDescendants(): void;
128
131
  }
129
132
  export declare class CfgFeature {
130
133
  readonly _internal: _CfgFeatureInternal;
131
- static make(rawFeature: DtoFeature, allRawFeatures: DtoFeature[], key: string, parent: _CfgProductConfigurationInternal | _CfgOptionInternal, parentConfiguration: _CfgProductConfigurationInternal, parentProduct: _CfgProductInternal, rootProduct: _CfgProductInternal): CfgFeature;
134
+ static make(rawFeature: DtoFeature, rawFeatures: DtoFeature[], key: string, parent: _CfgProductConfigurationInternal | _CfgOptionInternal, parentConfiguration: _CfgProductConfigurationInternal, parentProduct: _CfgProductInternal, rootProduct: _CfgProductInternal): CfgFeature;
132
135
  /**
133
136
  * Makes an object wrapping the passed object. This is not a clone method,
134
137
  * it is a method to make a new outer reference. Like a shallow copy.
@@ -148,6 +151,7 @@ export declare class CfgFeature {
148
151
  get key(): string;
149
152
  get code(): string;
150
153
  get groupCode(): string | undefined;
154
+ get notes(): DtoNote[];
151
155
  /**
152
156
  * If true the options in the feature is selected by both sending its code and numeric value
153
157
  * when selecting.
@@ -162,6 +166,7 @@ export declare class CfgFeature {
162
166
  setNumericValue: (val: number) => Promise<boolean>;
163
167
  get unit(): LengthUnit;
164
168
  get description(): string;
169
+ get omitOnOrder(): boolean;
165
170
  get hasUpcharge(): boolean | undefined;
166
171
  get selectedOptions(): CfgOption[];
167
172
  /** Are all ancestors up to the CfgProductConfiguration selected? */
@@ -62,11 +62,11 @@ function doFreshRefOption(options, optionInternal, committed, beforeNotify) {
62
62
  * should be used and interacted with.
63
63
  */
64
64
  export class _CfgFeatureInternal {
65
- constructor(rawFeature, allRawFeatures, key, // Unique amongst siblings
65
+ constructor(rawFeature, rawFeatures, _key, // Unique amongst siblings
66
66
  parent, parentConfiguration, parentProduct, rootProduct) {
67
67
  this.rawFeature = rawFeature;
68
- this.allRawFeatures = allRawFeatures;
69
- this.key = key;
68
+ this.rawFeatures = rawFeatures;
69
+ this._key = _key;
70
70
  this.parent = parent;
71
71
  this.parentConfiguration = parentConfiguration;
72
72
  this.parentProduct = parentProduct;
@@ -114,6 +114,7 @@ export class _CfgFeatureInternal {
114
114
  }
115
115
  yield this._notifyAllOfChange(bubbleMode, committed);
116
116
  });
117
+ // Keep in sync with stripExtendedDataFromDtoFeatureConf
117
118
  this.getDtoConf = (includeExtendedData) => {
118
119
  const result = {
119
120
  code: this.code,
@@ -128,6 +129,12 @@ export class _CfgFeatureInternal {
128
129
  }
129
130
  return result;
130
131
  };
132
+ // DtoFeatureConf is the newer more easily readable format for configuration. As
133
+ // the API:s are still using the older format (and will for the forseeable future) we need
134
+ // to support both formats. The new format can be converted to the old, but not the other
135
+ // way around. For that reason the get-method above uses the new format, and the set-method
136
+ // below the old format. As these functions are meant to only be used internally this should't
137
+ // cause too much confusion.
131
138
  this.setApiSelection = (apiOptionSelectionMap) => __awaiter(this, void 0, void 0, function* () {
132
139
  const selectionType = this.selectionType;
133
140
  const isGroup = selectionType === SelectionType.Group;
@@ -407,6 +414,16 @@ export class _CfgFeatureInternal {
407
414
  get groupCode() {
408
415
  return this.rawFeature.groupCode;
409
416
  }
417
+ get key() {
418
+ return this._key;
419
+ }
420
+ set key(k) {
421
+ this._key = k;
422
+ }
423
+ get notes() {
424
+ var _a;
425
+ return this.parentProduct.getNotes((_a = this.rawFeature.noteRefs) !== null && _a !== void 0 ? _a : []);
426
+ }
410
427
  get isUseNumericValue() {
411
428
  return this.rawFeature.numericOrder;
412
429
  }
@@ -430,6 +447,9 @@ export class _CfgFeatureInternal {
430
447
  get description() {
431
448
  return this.rawFeature.description;
432
449
  }
450
+ get omitOnOrder() {
451
+ return this.rawFeature.omitOnOrder === true;
452
+ }
433
453
  get syncGroup() {
434
454
  return this.rawFeature.syncGroup;
435
455
  }
@@ -512,7 +532,7 @@ export class _CfgFeatureInternal {
512
532
  const hasDuplicateDescription = someMatch(this.rawFeature.options, (l, r) => {
513
533
  return l.description.toLowerCase() === r.description.toLowerCase();
514
534
  });
515
- this._options = this.rawFeature.options.map((o) => CfgOption.make(o, this.allRawFeatures, hasDuplicateDescription, this, this.parentConfiguration, this.parentProduct, this.rootProduct));
535
+ this._options = this.rawFeature.options.map((o) => CfgOption.make(o, this.rawFeatures, hasDuplicateDescription, this, this.parentConfiguration, this.parentProduct, this.rootProduct));
516
536
  }
517
537
  return this._options;
518
538
  }
@@ -536,14 +556,6 @@ export class _CfgFeatureInternal {
536
556
  });
537
557
  }
538
558
  }
539
- _freshRefDescendants() {
540
- const options = this._options || [];
541
- for (let i = 0; i < options.length; i++) {
542
- const optionInternal = options[i]._internal;
543
- optionInternal._freshRefDescendants();
544
- options[i] = CfgOption._makeNewRefFrom(optionInternal);
545
- }
546
- }
547
559
  }
548
560
  export class CfgFeature {
549
561
  /**
@@ -571,8 +583,8 @@ export class CfgFeature {
571
583
  this.listenForChange = (l) => this._internal.changeObservable.listen(l);
572
584
  this.stopListenForChange = (l) => this._internal.changeObservable.stopListen(l);
573
585
  }
574
- static make(rawFeature, allRawFeatures, key, parent, parentConfiguration, parentProduct, rootProduct) {
575
- return new this(new _CfgFeatureInternal(rawFeature, allRawFeatures, key, parent, parentConfiguration, parentProduct, rootProduct));
586
+ static make(rawFeature, rawFeatures, key, parent, parentConfiguration, parentProduct, rootProduct) {
587
+ return new this(new _CfgFeatureInternal(rawFeature, rawFeatures, key, parent, parentConfiguration, parentProduct, rootProduct));
576
588
  }
577
589
  /**
578
590
  * Makes an object wrapping the passed object. This is not a clone method,
@@ -591,6 +603,7 @@ export class CfgFeature {
591
603
  get selectionType() {
592
604
  return this._internal.selectionType;
593
605
  }
606
+ // Unique amongst siblings. Can change. Only use for presentation layer i.e. React.
594
607
  get key() {
595
608
  return this._internal.key;
596
609
  }
@@ -600,6 +613,9 @@ export class CfgFeature {
600
613
  get groupCode() {
601
614
  return this._internal.groupCode;
602
615
  }
616
+ get notes() {
617
+ return this._internal.notes;
618
+ }
603
619
  /**
604
620
  * If true the options in the feature is selected by both sending its code and numeric value
605
621
  * when selecting.
@@ -617,6 +633,9 @@ export class CfgFeature {
617
633
  get description() {
618
634
  return this._internal.description;
619
635
  }
636
+ get omitOnOrder() {
637
+ return this._internal.omitOnOrder;
638
+ }
620
639
  get hasUpcharge() {
621
640
  return this._internal.hasUpcharge;
622
641
  }
@@ -1,5 +1,5 @@
1
1
  import { LengthUnit, Observable, SingleArgCallback } from "@configura/web-utilities";
2
- import { DtoFeature, DtoOption, DtoOptionConfiguration, DtoSelectedOption } from "../CatalogueAPI.js";
2
+ import { DtoFeature, DtoMiscFile, DtoNote, DtoOption, DtoOptionConf, 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";
@@ -60,20 +60,23 @@ export declare enum ProductConfigurationBubbleMode {
60
60
  */
61
61
  export declare class _CfgOptionInternal {
62
62
  readonly rawOption: DtoOption;
63
- private readonly allRawFeatures;
63
+ private readonly rawFeatures;
64
64
  readonly parent: _CfgFeatureInternal;
65
65
  readonly parentConfiguration: _CfgProductConfigurationInternal;
66
66
  readonly parentProduct: _CfgProductInternal;
67
67
  readonly rootProduct: _CfgProductInternal;
68
- constructor(rawOption: DtoOption, allRawFeatures: DtoFeature[], siblingHasDuplicateDescription: boolean, parent: _CfgFeatureInternal, parentConfiguration: _CfgProductConfigurationInternal, parentProduct: _CfgProductInternal, rootProduct: _CfgProductInternal);
68
+ constructor(rawOption: DtoOption, rawFeatures: DtoFeature[], siblingHasDuplicateDescription: boolean, parent: _CfgFeatureInternal, parentConfiguration: _CfgProductConfigurationInternal, parentProduct: _CfgProductInternal, rootProduct: _CfgProductInternal);
69
69
  private _features;
70
70
  private _mtrlApplications;
71
71
  readonly key: string;
72
+ private _upcharge;
72
73
  private _numericValue;
73
74
  readonly allowedNumericValues: NumericValuesSelection | undefined;
74
75
  isAllowedNumericValue(val: number): boolean;
75
76
  readonly changeObservable: Observable<OptionChangeNotification>;
76
77
  get code(): string;
78
+ get notes(): DtoNote[];
79
+ get miscFiles(): DtoMiscFile[];
77
80
  get isUseNumericValue(): boolean;
78
81
  get numericValue(): number | undefined;
79
82
  setNumericValue(val: number, doSelectOption: boolean): Promise<boolean>;
@@ -84,22 +87,22 @@ export declare class _CfgOptionInternal {
84
87
  get ancestorsSelected(): boolean;
85
88
  get mtrlApplications(): CfgMtrlApplication[];
86
89
  get thumbnail(): string | undefined;
87
- get upcharge(): number | undefined;
88
- get priceChangeAtSelectChange(): number | undefined;
90
+ private _calculateUpcharge;
91
+ get upcharge(): number;
92
+ get priceChangeAtSelectChange(): number;
89
93
  get features(): CfgFeature[];
90
94
  /** Called by child to tell its parent that it has changed. */
91
95
  _childHasChanged: (freshRef: CfgFeature, bubbleMode: ProductConfigurationBubbleMode, committed: boolean) => Promise<void>;
92
- getDtoConf: (includeExtendedData: boolean) => DtoOptionConfiguration;
96
+ getDtoConf: (includeExtendedData: boolean) => DtoOptionConf;
93
97
  setApiSelection: (apiOptionSelection: DtoSelectedOption | undefined) => Promise<boolean>;
94
98
  structureCompare: (other: _CfgOptionInternal, strictOrder?: boolean, descriptionMatch?: boolean) => boolean;
95
99
  tryMatchSelection: (other: CfgOption, descriptionMatch?: boolean) => Promise<boolean>;
96
100
  keyMatch: (other: _CfgOptionInternal, descriptionMatch?: boolean) => boolean;
97
101
  _getFeaturesWithCode: (code: string) => _CfgFeatureInternal[];
98
- _freshRefDescendants(): void;
99
102
  }
100
103
  export declare class CfgOption {
101
104
  readonly _internal: _CfgOptionInternal;
102
- static make(rawOption: DtoOption, allRawFeatures: DtoFeature[], siblingHasDuplicateDescription: boolean, parent: _CfgFeatureInternal, parentConfiguration: _CfgProductConfigurationInternal, parentProduct: _CfgProductInternal, rootProduct: _CfgProductInternal): CfgOption;
105
+ static make(rawOption: DtoOption, rawFeatures: DtoFeature[], siblingHasDuplicateDescription: boolean, parent: _CfgFeatureInternal, parentConfiguration: _CfgProductConfigurationInternal, parentProduct: _CfgProductInternal, rootProduct: _CfgProductInternal): CfgOption;
103
106
  /**
104
107
  * Makes an object wrapping the passed object. This is not a clone method,
105
108
  * it is a method to make a new outer reference. Like a shallow copy.
@@ -114,10 +117,13 @@ export declare class CfgOption {
114
117
  private constructor();
115
118
  isBackedBySame: (other: CfgOption) => boolean;
116
119
  get parentProduct(): CfgProduct;
120
+ get parent(): CfgFeature;
117
121
  get rootProduct(): CfgProduct;
118
122
  get rawOption(): DtoOption;
119
123
  get key(): string;
120
124
  get code(): string;
125
+ get notes(): DtoNote[];
126
+ get miscFiles(): DtoMiscFile[];
121
127
  get isUseNumericValue(): boolean;
122
128
  get numericValue(): number | undefined;
123
129
  setNumericValue: (val: number, doSelectOption: boolean) => Promise<boolean>;
@@ -143,8 +149,8 @@ export declare class CfgOption {
143
149
  */
144
150
  setSelected: (on: boolean) => Promise<boolean>;
145
151
  get thumbnail(): string | undefined;
146
- get upcharge(): number | undefined;
147
- get priceChangeAtSelectChange(): number | undefined;
152
+ get upcharge(): number;
153
+ get priceChangeAtSelectChange(): number;
148
154
  get features(): CfgFeature[];
149
155
  listenForChange: (l: SingleArgCallback<OptionChangeNotification>) => void;
150
156
  stopListenForChange: (l: SingleArgCallback<OptionChangeNotification>) => void;
@@ -80,9 +80,9 @@ function doesChildrenShareOptionsCode(features) {
80
80
  * the class that should be used and interacted with.
81
81
  */
82
82
  export class _CfgOptionInternal {
83
- constructor(rawOption, allRawFeatures, siblingHasDuplicateDescription, parent, parentConfiguration, parentProduct, rootProduct) {
83
+ constructor(rawOption, rawFeatures, siblingHasDuplicateDescription, parent, parentConfiguration, parentProduct, rootProduct) {
84
84
  this.rawOption = rawOption;
85
- this.allRawFeatures = allRawFeatures;
85
+ this.rawFeatures = rawFeatures;
86
86
  this.parent = parent;
87
87
  this.parentConfiguration = parentConfiguration;
88
88
  this.parentProduct = parentProduct;
@@ -132,7 +132,19 @@ export class _CfgOptionInternal {
132
132
  }
133
133
  return result;
134
134
  };
135
+ // DtoOptionConf is the newer more easily readable format for configuration. As
136
+ // the API:s are still using the older format (and will for the forseeable future) we need
137
+ // to support both formats. The new format can be converted to the old, but not the other
138
+ // way around. For that reason the get-method above uses the new format, and the set-method
139
+ // below the old format. As these functions are meant to only be used internally this should't
140
+ // cause too much confusion.
135
141
  this.setApiSelection = (apiOptionSelection) => __awaiter(this, void 0, void 0, function* () {
142
+ let change = false;
143
+ const upcharge = this._calculateUpcharge();
144
+ if (this._upcharge !== upcharge) {
145
+ change = true;
146
+ this._upcharge = upcharge;
147
+ }
136
148
  let features;
137
149
  if (apiOptionSelection === undefined) {
138
150
  features = this._features || []; // All already generated children
@@ -140,7 +152,10 @@ export class _CfgOptionInternal {
140
152
  else {
141
153
  features = this.features; // This will generate all children
142
154
  }
143
- return (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)))).some((b) => b)) {
156
+ change = true;
157
+ }
158
+ return change;
144
159
  });
145
160
  this.structureCompare = (other, strictOrder = true, descriptionMatch = false) => this.keyMatch(other, descriptionMatch) &&
146
161
  compareArrays(this.features, other.features, (l, r) => l._internal.structureCompare(r._internal, strictOrder, descriptionMatch), strictOrder);
@@ -174,6 +189,7 @@ export class _CfgOptionInternal {
174
189
  this.key =
175
190
  this.description +
176
191
  (this.description === "" || siblingHasDuplicateDescription ? this.code : "");
192
+ this._upcharge = this._calculateUpcharge();
177
193
  const rawRanges = rawOption.codeRanges;
178
194
  if (rawRanges === undefined || rawRanges.length === 0) {
179
195
  if (this.isUseNumericValue) {
@@ -200,6 +216,14 @@ export class _CfgOptionInternal {
200
216
  get code() {
201
217
  return this.rawOption.code;
202
218
  }
219
+ get notes() {
220
+ var _a;
221
+ return this.parentProduct.getNotes((_a = this.rawOption.noteRefs) !== null && _a !== void 0 ? _a : []);
222
+ }
223
+ get miscFiles() {
224
+ var _a;
225
+ return (_a = this.rawOption.miscFiles) !== null && _a !== void 0 ? _a : [];
226
+ }
203
227
  get isUseNumericValue() {
204
228
  return this.parent.isUseNumericValue;
205
229
  }
@@ -272,18 +296,21 @@ export class _CfgOptionInternal {
272
296
  get thumbnail() {
273
297
  return this.rawOption.material || getMtrlPreview(this.mtrlApplications);
274
298
  }
275
- get upcharge() {
299
+ _calculateUpcharge() {
276
300
  let upcharge = this.rawOption.upcharge || 0;
277
301
  const priceCodes = this.rawOption.priceCodes || [];
278
302
  const prices = this.rootProduct.prices;
279
303
  upcharge += recursivelyGetPriceCodeValue(priceCodes, prices) || 0;
280
304
  return upcharge;
281
305
  }
306
+ get upcharge() {
307
+ return this._upcharge;
308
+ }
282
309
  get priceChangeAtSelectChange() {
283
310
  if (!this.parent.hasUpcharge) {
284
- return undefined;
311
+ return 0;
285
312
  }
286
- const upcharge = this.upcharge || 0;
313
+ const upcharge = this._upcharge || 0;
287
314
  const isSelected = this.parent.isSelected(this);
288
315
  if (this.parent.selectionType === SelectionType.SelectMany) {
289
316
  return isSelected ? -upcharge : upcharge;
@@ -299,12 +326,12 @@ export class _CfgOptionInternal {
299
326
  }
300
327
  return upcharge - (selectedOptions[0].upcharge || 0);
301
328
  }
302
- return undefined;
329
+ return 0;
303
330
  }
304
331
  get features() {
305
332
  if (this._features === undefined) {
306
333
  const allRefs = this.rawOption.featureRefs || [];
307
- const features = syncCfgFeatures(allRefs, [], this.allRawFeatures, this, this.parentConfiguration, this.parentProduct, this.rootProduct);
334
+ const features = syncCfgFeatures(allRefs, [], this.rawFeatures, this, this.parentConfiguration, this.parentProduct, this.rootProduct);
308
335
  if (doesChildrenShareOptionsCode(features)) {
309
336
  throw new Error("Stage does not yet properly support Options that has multiple sub-features with overlapping option codes.");
310
337
  }
@@ -312,14 +339,6 @@ export class _CfgOptionInternal {
312
339
  }
313
340
  return this._features;
314
341
  }
315
- _freshRefDescendants() {
316
- const features = this._features || [];
317
- for (let i = 0; i < features.length; i++) {
318
- const featureInternal = features[i]._internal;
319
- featureInternal._freshRefDescendants();
320
- features[i] = CfgFeature._makeNewRefFrom(featureInternal);
321
- }
322
- }
323
342
  }
324
343
  export class CfgOption {
325
344
  /**
@@ -343,8 +362,8 @@ export class CfgOption {
343
362
  this.listenForChange = (l) => this._internal.changeObservable.listen(l);
344
363
  this.stopListenForChange = (l) => this._internal.changeObservable.stopListen(l);
345
364
  }
346
- static make(rawOption, allRawFeatures, siblingHasDuplicateDescription, parent, parentConfiguration, parentProduct, rootProduct) {
347
- return new this(new _CfgOptionInternal(rawOption, allRawFeatures, siblingHasDuplicateDescription, parent, parentConfiguration, parentProduct, rootProduct));
365
+ static make(rawOption, rawFeatures, siblingHasDuplicateDescription, parent, parentConfiguration, parentProduct, rootProduct) {
366
+ return new this(new _CfgOptionInternal(rawOption, rawFeatures, siblingHasDuplicateDescription, parent, parentConfiguration, parentProduct, rootProduct));
348
367
  }
349
368
  /**
350
369
  * Makes an object wrapping the passed object. This is not a clone method,
@@ -357,6 +376,9 @@ export class CfgOption {
357
376
  get parentProduct() {
358
377
  return CfgProduct._makeNewRefFrom(this._internal.parentProduct);
359
378
  }
379
+ get parent() {
380
+ return CfgFeature._makeNewRefFrom(this._internal.parent);
381
+ }
360
382
  get rootProduct() {
361
383
  return CfgProduct._makeNewRefFrom(this._internal.rootProduct);
362
384
  }
@@ -369,6 +391,12 @@ export class CfgOption {
369
391
  get code() {
370
392
  return this._internal.code;
371
393
  }
394
+ get notes() {
395
+ return this._internal.notes;
396
+ }
397
+ get miscFiles() {
398
+ return this._internal.miscFiles;
399
+ }
372
400
  get isUseNumericValue() {
373
401
  return this._internal.isUseNumericValue;
374
402
  }
@@ -1,5 +1,5 @@
1
1
  import { LengthUnit, LengthValue, Observable, SingleArgCallback } from "@configura/web-utilities";
2
- import { DtoFeature, DtoFeatureConfiguration, DtoFeatureRef, DtoSelectedOption } from "../CatalogueAPI.js";
2
+ import { DtoFeature, DtoFeatureConf, DtoFeatureRef, 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";
@@ -17,27 +17,29 @@ export declare type StretchMap = Map<string, {
17
17
  * modified. CfgProductConfiguration is the class that should be used and interacted with.
18
18
  */
19
19
  export declare class _CfgProductConfigurationInternal {
20
- readonly allRawFeatures: DtoFeature[];
21
20
  readonly parentProduct: _CfgProductInternal;
22
21
  readonly rootProduct: _CfgProductInternal;
23
- static _makeUninitialized(rootFeatureRefs: DtoFeatureRef[], allRawFeatures: DtoFeature[], // Flat packed. All the features that can appear anyplace in the selection tree.
22
+ private readonly _initialRootFeatureRefs;
23
+ static _makeUninitialized(rootFeatureRefs: DtoFeatureRef[], rawFeatures: DtoFeature[], // Flat packed. All the features that can currently appear anyplace in the selection tree.
24
24
  parentProduct: _CfgProductInternal, rootProduct: _CfgProductInternal): _CfgProductConfigurationInternal;
25
25
  private constructor();
26
26
  readonly key = "~";
27
27
  private _rootFeatureRefs;
28
+ readonly accumulatedRawFeatures: DtoFeature[];
28
29
  private _features;
29
30
  readonly stretchReferenceLengthsByMeasureParamCode: StretchMap;
30
31
  readonly changeObservable: Observable<ProductConfigurationChangeNotification>;
31
32
  get rootFeatureRefs(): DtoFeatureRef[];
32
33
  get features(): CfgFeature[];
33
34
  private _notifyAllOfChange;
34
- _freshRefDescendants(): void;
35
35
  /** Called by child to tell its parent that it has changed. */
36
36
  _childHasChanged: (freshRef: CfgFeature, bubbleMode: ProductConfigurationBubbleMode, committed: boolean) => Promise<void>;
37
- getDtoConf: (includeExtendedData: boolean) => DtoFeatureConfiguration[];
37
+ getDtoConf: (includeExtendedData: boolean) => DtoFeatureConf[];
38
+ getApiSelection: () => DtoSelectedOption[];
38
39
  /**
39
40
  * When used internally the notifications are taken care off by the caller, but if set from
40
41
  * outside we want notifications to bubble all the way to the root.
42
+ * This method will not cause validation calls. Data is assumed to already be validated.
41
43
  */
42
44
  setApiSelection: (selectedOptions: DtoSelectedOption[], bubbleToRoot: boolean) => Promise<boolean>;
43
45
  structureCompare: (other: _CfgProductConfigurationInternal, strictOrder: boolean, descriptionMatch: boolean) => boolean;
@@ -48,7 +50,22 @@ export declare class _CfgProductConfigurationInternal {
48
50
  tryMatchSelection: (other: _CfgProductConfigurationInternal, descriptionMatch: boolean | undefined, validate: boolean) => Promise<boolean>;
49
51
  /** Only selected features. */
50
52
  _getFeaturesWithCode: (code: string) => _CfgFeatureInternal[];
51
- populateFeatures: (rootFeatureRefs: DtoFeatureRef[]) => void;
53
+ /**
54
+ * Extends the list of loaded potentially used features. Will warn for but ignore duplicates.
55
+ * Returns true if a change happened.
56
+ */
57
+ addRawFeatures: (rawFeatures: DtoFeature[], warnForDuplicates: boolean) => boolean;
58
+ private _hasRootFeaturesChanged;
59
+ /**
60
+ * True if what root Features are used is not the same as at initial load.
61
+ * This means that functional selection has happened.
62
+ */
63
+ get hasRootFeaturesChanged(): boolean;
64
+ /**
65
+ * Populates _features based on the passed @param rootFeatureRefs .
66
+ * @return true if a change happened.
67
+ */
68
+ populateFeatures: (rootFeatureRefs: DtoFeatureRef[]) => boolean;
52
69
  setStretchReferenceLength: (measureParamCode: string, referenceLength: number | undefined, unit: LengthUnit) => Promise<boolean>;
53
70
  }
54
71
  export declare class CfgProductConfiguration {
@@ -58,7 +75,7 @@ export declare class CfgProductConfiguration {
58
75
  * CfgProductConfiguration, but is not properly initialized until the initDone-callback
59
76
  * has been called.
60
77
  */
61
- static make(initSuccess: (c: CfgProductConfiguration) => void, initFail: (error: Error) => void, rootFeatureRefs: DtoFeatureRef[], allRawFeatures: DtoFeature[], // Flat packed. All the features that can appear anyplace in the selection tree.
78
+ 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.
62
79
  apiSelection: DtoSelectedOption[], parentProduct: _CfgProductInternal, rootProduct: _CfgProductInternal): CfgProductConfiguration;
63
80
  /**
64
81
  * Makes an object wrapping the passed object. This is not a clone method, it is a method to
@@ -78,11 +95,11 @@ export declare class CfgProductConfiguration {
78
95
  get rootProduct(): CfgProduct;
79
96
  get key(): string;
80
97
  /**
81
- * Every (unprocessed) feature which might be used in this product. This is constant for a
82
- * product load. What features are actually used is controlled by rootFeatureRefs and what
98
+ * Every (unprocessed) feature that is currently loaded for this product. This can be extended
99
+ * by validation calls. What features are actually used is controlled by rootFeatureRefs and what
83
100
  * options are selected.
84
101
  */
85
- get allRawFeatures(): DtoFeature[];
102
+ get rawFeatures(): DtoFeature[];
86
103
  /** What features are used in the root of this. This can change with new validate calls. */
87
104
  get rootFeatureRefs(): DtoFeatureRef[];
88
105
  /** The root features at the root of the selection tree. */
@@ -94,12 +111,6 @@ export declare class CfgProductConfiguration {
94
111
  * This method will cause validation calls.
95
112
  */
96
113
  tryMatchSelection: (other: CfgProductConfiguration, descriptionMatch?: boolean) => Promise<boolean>;
97
- getApiSelection: () => DtoSelectedOption[];
98
- /**
99
- * This method does not propagate its selections.
100
- * This method will not cause validation calls. Data is assumed to already be validated.
101
- */
102
- setApiSelection: (selectedOptions: DtoSelectedOption[]) => Promise<boolean>;
103
114
  /**
104
115
  * Set how stretched a certain measure should be measureParamCode is the measure to be
105
116
  * stretched referenceLength is a value relative to the initial length of the measure. If the