@icure/form 3.0.37 → 3.0.39

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 (81) hide show
  1. package/.yarn/install-state.gz +0 -0
  2. package/components/common/field.d.ts +1 -0
  3. package/components/common/field.js +5 -0
  4. package/components/common/field.js.map +1 -1
  5. package/components/common/metadata-buttons-bar.js +4 -0
  6. package/components/common/metadata-buttons-bar.js.map +1 -1
  7. package/components/icure-button/index.js +4 -0
  8. package/components/icure-button/index.js.map +1 -1
  9. package/components/icure-button-group/index.js +4 -0
  10. package/components/icure-button-group/index.js.map +1 -1
  11. package/components/icure-date-picker/index.js +4 -0
  12. package/components/icure-date-picker/index.js.map +1 -1
  13. package/components/icure-dropdown-field/index.js +4 -0
  14. package/components/icure-dropdown-field/index.js.map +1 -1
  15. package/components/icure-form/fields/button-group/checkbox.d.ts +1 -0
  16. package/components/icure-form/fields/button-group/checkbox.js +39 -2
  17. package/components/icure-form/fields/button-group/checkbox.js.map +1 -1
  18. package/components/icure-form/fields/button-group/radio-button.d.ts +1 -0
  19. package/components/icure-form/fields/button-group/radio-button.js +39 -2
  20. package/components/icure-form/fields/button-group/radio-button.js.map +1 -1
  21. package/components/icure-form/fields/date-picker/date-picker.d.ts +1 -0
  22. package/components/icure-form/fields/date-picker/date-picker.js +54 -17
  23. package/components/icure-form/fields/date-picker/date-picker.js.map +1 -1
  24. package/components/icure-form/fields/date-picker/date-time-picker.d.ts +1 -0
  25. package/components/icure-form/fields/date-picker/date-time-picker.js +54 -17
  26. package/components/icure-form/fields/date-picker/date-time-picker.js.map +1 -1
  27. package/components/icure-form/fields/date-picker/time-picker.d.ts +1 -0
  28. package/components/icure-form/fields/date-picker/time-picker.js +54 -17
  29. package/components/icure-form/fields/date-picker/time-picker.js.map +1 -1
  30. package/components/icure-form/fields/dropdown/dropdown-field.d.ts +1 -0
  31. package/components/icure-form/fields/dropdown/dropdown-field.js +39 -2
  32. package/components/icure-form/fields/dropdown/dropdown-field.js.map +1 -1
  33. package/components/icure-form/fields/items-list-field/items-list-field.d.ts +1 -0
  34. package/components/icure-form/fields/items-list-field/items-list-field.js +55 -17
  35. package/components/icure-form/fields/items-list-field/items-list-field.js.map +1 -1
  36. package/components/icure-form/fields/measure-field/measure-field.d.ts +1 -0
  37. package/components/icure-form/fields/measure-field/measure-field.js +39 -2
  38. package/components/icure-form/fields/measure-field/measure-field.js.map +1 -1
  39. package/components/icure-form/fields/number-field/number-field.d.ts +1 -0
  40. package/components/icure-form/fields/number-field/number-field.js +55 -18
  41. package/components/icure-form/fields/number-field/number-field.js.map +1 -1
  42. package/components/icure-form/fields/text-field/text-field.d.ts +1 -0
  43. package/components/icure-form/fields/text-field/text-field.js +65 -28
  44. package/components/icure-form/fields/text-field/text-field.js.map +1 -1
  45. package/components/icure-form/fields/token-field/token-field.d.ts +1 -0
  46. package/components/icure-form/fields/token-field/token-field.js +55 -17
  47. package/components/icure-form/fields/token-field/token-field.js.map +1 -1
  48. package/components/icure-form/fields/utils/index.d.ts +1 -0
  49. package/components/icure-form/fields/utils/index.js +2 -0
  50. package/components/icure-form/fields/utils/index.js.map +1 -1
  51. package/components/icure-form/index.d.ts +1 -1
  52. package/components/icure-form/index.js +26 -5
  53. package/components/icure-form/index.js.map +1 -1
  54. package/components/icure-form/renderer/form/form-selection-button.js +4 -0
  55. package/components/icure-form/renderer/form/form-selection-button.js.map +1 -1
  56. package/components/icure-form/renderer/form/form.d.ts +7 -2
  57. package/components/icure-form/renderer/form/form.js +618 -454
  58. package/components/icure-form/renderer/form/form.js.map +1 -1
  59. package/components/icure-form/renderer/index.d.ts +1 -1
  60. package/components/icure-form/renderer/index.js.map +1 -1
  61. package/components/icure-label/index.js +4 -0
  62. package/components/icure-label/index.js.map +1 -1
  63. package/components/icure-text-field/index.js +11 -12
  64. package/components/icure-text-field/index.js.map +1 -1
  65. package/components/model/index.d.ts +15 -1
  66. package/components/model/index.js +13 -2
  67. package/components/model/index.js.map +1 -1
  68. package/generic/model.d.ts +6 -6
  69. package/generic/model.js.map +1 -1
  70. package/icure/form-values-container.d.ts +63 -42
  71. package/icure/form-values-container.js +180 -139
  72. package/icure/form-values-container.js.map +1 -1
  73. package/icure/icure-utils.js +30 -12
  74. package/icure/icure-utils.js.map +1 -1
  75. package/icure/model.d.ts +9 -2
  76. package/icure/model.js +7 -1
  77. package/icure/model.js.map +1 -1
  78. package/package.json +1 -1
  79. package/utils/code-utils.d.ts +3 -2
  80. package/utils/code-utils.js +5 -6
  81. package/utils/code-utils.js.map +1 -1
@@ -9,13 +9,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import { CodeStub, DecryptedContact, DecryptedService, DecryptedSubContact } from '@icure/cardinal-sdk';
11
11
  import { sortedBy } from '../utils/no-lodash';
12
+ import { CodeStubWithId } from './model';
12
13
  import { areCodesEqual, codeStubToCode, contentToPrimitiveType, isContentEqual, primitiveTypeToContent } from './icure-utils';
13
14
  import { parsePrimitive } from '../utils/primitive';
14
15
  import { anyDateToDate, dateToFuzzyDate } from '../utils/dates';
15
- import { v4 as uuidv4 } from 'uuid';
16
16
  import { normalizeCodes } from '../utils/code-utils';
17
- function notify(l, fvc) {
18
- l(fvc);
17
+ let bfvcIdGen = 0;
18
+ let cfvcIdGen = 0;
19
+ function notify(l, fvc, modifiedFields = [], context = undefined, id = undefined, recurse = false) {
20
+ console.log(`${id !== null && id !== void 0 ? id : 'cc'}: Notifying listener with context [>>> ${fvc['_id']}] -> ${context} <- ${modifiedFields.length ? `and modified fields ${modifiedFields.map((f) => f.label).join(', ')}` : ''}`);
21
+ l(fvc, modifiedFields, recurse);
19
22
  }
20
23
  /** This class is a bridge between the ICure API and the generic FormValuesContainer interface.
21
24
  * It wraps around a ContactFormValuesContainer and provides a series of services:
@@ -40,6 +43,21 @@ export class BridgedFormValuesContainer {
40
43
  toString() {
41
44
  return `Bridged(${this.contactFormValuesContainer.rootForm.formTemplateId}[${this.contactFormValuesContainer.rootForm.id}]) - ${this._id}`;
42
45
  }
46
+ options() {
47
+ return {
48
+ responsible: this.responsible,
49
+ contactFormValuesContainer: this.contactFormValuesContainer,
50
+ interpreter: this.interpreter,
51
+ contact: this.contact,
52
+ initialValuesProvider: this.initialValuesProvider,
53
+ dependentValuesProvider: this.dependentValuesProvider,
54
+ validatorsProvider: this.validatorsProvider,
55
+ language: this.language,
56
+ changeListeners: this.changeListeners,
57
+ interpreterContext: this.interpreterContext,
58
+ currentComputations: this.currentComputations,
59
+ };
60
+ }
43
61
  /**
44
62
  * Creates an instance of BridgedFormValuesContainer.
45
63
  * @param responsible The id of the data owner responsible for the creation of the values
@@ -52,36 +70,83 @@ export class BridgedFormValuesContainer {
52
70
  * @param language The language in which the values are displayed
53
71
  * @param changeListeners The listeners that will be notified when the values change
54
72
  * @param interpreterContext A map with keys that are the names of the variables and values that are the functions that return the values of the variables
73
+ * @param currentComputations A list of ongoing computations that should be observed and not recomputed when the form is created.
74
+ * @param modifiedFields A list of fields that have been modified and should be considered when computing the initial values
75
+ * @param stackLevel The stack level at which the BridgedFormValuesContainer is created, used to limit recursion induced by default values computations
76
+ * @param context A string that describes the context in which the BridgedFormValuesContainer is created, used for debugging purposes
55
77
  */
56
- constructor(responsible, contactFormValuesContainer, interpreter, contact, initialValuesProvider = () => [], dependentValuesProvider = () => [], validatorsProvider = () => [], language = 'en', changeListeners = [], interpreterContext = {}) {
57
- this.responsible = responsible;
58
- this.interpreter = interpreter;
59
- this.initialValuesProvider = initialValuesProvider;
60
- this.dependentValuesProvider = dependentValuesProvider;
61
- this.validatorsProvider = validatorsProvider;
62
- this.language = language;
63
- this.changeListeners = changeListeners;
64
- this.interpreterContext = interpreterContext;
65
- this._id = uuidv4();
66
- console.log(`Creating bridge FVC (${contactFormValuesContainer.rootForm.formTemplateId}) with ${contactFormValuesContainer.children.length} children [${this._id}]`);
78
+ constructor({ responsible, contactFormValuesContainer, interpreter, contact, initialValuesProvider, dependentValuesProvider, validatorsProvider, language, changeListeners, interpreterContext, currentComputations, modifiedFields, stackLevel = 0, context, }) {
79
+ this._id = `B-${(bfvcIdGen++).toString()}`;
80
+ this.initialValuesProvider = () => [];
81
+ this.dependentValuesProvider = () => [];
82
+ this.validatorsProvider = () => [];
83
+ this.language = 'en';
84
+ this.changeListeners = [];
85
+ this.interpreterContext = {};
86
+ this.currentComputations = {};
87
+ console.log(`${this._id}: Creating BridgedFormValuesContainer because ${context !== null && context !== void 0 ? context : 'no context provided'}`);
67
88
  //Before start to broadcast changes, we need to fill in the contactFormValuesContainer with the dependent values
68
89
  this.contactFormValuesContainer = contactFormValuesContainer;
69
- this.mutateAndNotify = (newContactFormValuesContainer) => __awaiter(this, void 0, void 0, function* () {
90
+ this.responsible = responsible;
91
+ this.interpreter = interpreter;
92
+ this.initialValuesProvider = initialValuesProvider !== null && initialValuesProvider !== void 0 ? initialValuesProvider : (() => []);
93
+ this.dependentValuesProvider = dependentValuesProvider !== null && dependentValuesProvider !== void 0 ? dependentValuesProvider : (() => []);
94
+ this.validatorsProvider = validatorsProvider !== null && validatorsProvider !== void 0 ? validatorsProvider : (() => []);
95
+ this.language = language !== null && language !== void 0 ? language : 'en';
96
+ this.changeListeners = changeListeners !== null && changeListeners !== void 0 ? changeListeners : [];
97
+ this.interpreterContext = interpreterContext !== null && interpreterContext !== void 0 ? interpreterContext : {};
98
+ this.contact = contact !== null && contact !== void 0 ? contact : contactFormValuesContainer.currentContact;
99
+ const isFormValueContainerObsolete = { current: false };
100
+ this.mutateAndNotify = (newContactFormValuesContainer_1, modifiedFields_1, ...args_1) => __awaiter(this, [newContactFormValuesContainer_1, modifiedFields_1, ...args_1], void 0, function* (newContactFormValuesContainer, modifiedFields, recurse = false) {
70
101
  newContactFormValuesContainer.unregisterChangeListener(this.mutateAndNotify);
71
- const newBridgedFormValueContainer = yield new BridgedFormValuesContainer(this.responsible, newContactFormValuesContainer, this.interpreter, this.contact === this.contactFormValuesContainer.currentContact ? newContactFormValuesContainer.currentContact : this.contact, this.initialValuesProvider, this.dependentValuesProvider, this.validatorsProvider, this.language, this.changeListeners, this.interpreterContext).init();
72
- this.changeListeners.forEach((l) => notify(l, newBridgedFormValueContainer));
102
+ const modifiedLabels = modifiedFields.map((f) => f.label);
103
+ const newBridgedFormValueContainer = new BridgedFormValuesContainer(Object.assign(Object.assign({}, this.options()), { contactFormValuesContainer: newContactFormValuesContainer, contact: this.contact === this.contactFormValuesContainer.currentContact ? newContactFormValuesContainer.currentContact : this.contact, currentComputations: Object.entries(this.currentComputations).reduce((acc, [label, { metadata, revisionsFilter, computation, status }]) => {
104
+ return modifiedLabels.includes(label)
105
+ ? Object.assign(Object.assign({}, acc), { [label]: { metadata, revisionsFilter, computation, status: 'resolved' } }) : Object.assign(Object.assign({}, acc), { [label]: { metadata, revisionsFilter, computation, status } });
106
+ }, {}), modifiedFields: modifiedFields, context: 'ContactFormValuesContainer change', stackLevel: recurse ? stackLevel + 1 : stackLevel }));
107
+ isFormValueContainerObsolete.current = true;
108
+ this.changeListeners.forEach((l) => notify(l, newBridgedFormValueContainer, modifiedFields, 'ContactFormValuesContainer change', this._id));
73
109
  return newBridgedFormValueContainer;
74
110
  });
75
111
  this.contactFormValuesContainer.registerChangeListener(this.mutateAndNotify);
76
- this.contact = contact !== null && contact !== void 0 ? contact : contactFormValuesContainer.currentContact;
77
- }
78
- init() {
79
- return __awaiter(this, void 0, void 0, function* () {
80
- if (this.contactFormValuesContainer.mustBeInitialised()) {
81
- yield this.computeInitialValues();
82
- }
83
- yield this.computeDependentValues();
84
- return this;
112
+ this.currentComputations =
113
+ (modifiedFields && !modifiedFields.length) || stackLevel > 1000
114
+ ? currentComputations !== null && currentComputations !== void 0 ? currentComputations : {}
115
+ : this.computeDependentValues(this.computeInitialValues(Object.fromEntries(Object.entries(currentComputations !== null && currentComputations !== void 0 ? currentComputations : {}).filter(([, c]) => c.status === 'pending')), modifiedFields), modifiedFields);
116
+ //console.log(`bFVC with uuid ${this.uuid} has the following initial computations`, Object.keys(this.currentComputations).join(', '))
117
+ Object.entries(this.currentComputations).forEach(([label, { metadata, revisionsFilter, computation: computationPromise, status }]) => {
118
+ computationPromise
119
+ .then((computationResult) => {
120
+ var _a;
121
+ if (isFormValueContainerObsolete.current) {
122
+ return;
123
+ }
124
+ //console.log(`Computed value for ${label} in ${this.uuid} with computation`, computation)
125
+ const newValue = this.convertRawValue(computationResult);
126
+ const currentValue = this.getValues(revisionsFilter);
127
+ if (newValue !== undefined || currentValue != undefined) {
128
+ const lng = (_a = this.language) !== null && _a !== void 0 ? _a : 'en';
129
+ if (newValue && !newValue.content[lng] && newValue.content['*']) {
130
+ newValue.content[lng] = newValue.content['*'];
131
+ }
132
+ if (newValue) {
133
+ delete newValue.content['*'];
134
+ }
135
+ console.log(`${this._id}: setValue for ${label}`);
136
+ if (this.setValue(label, lng, newValue, Object.keys(currentValue !== null && currentValue !== void 0 ? currentValue : {})[0], metadata, undefined, true)) {
137
+ console.log(`${this._id}: Obsolete because of update`);
138
+ }
139
+ else {
140
+ if (status === 'pending' && !isFormValueContainerObsolete.current) {
141
+ isFormValueContainerObsolete.current = true;
142
+ console.log(`${this._id}: Obsolete because of prune`);
143
+ const newBridgedFormValueContainer = new BridgedFormValuesContainer(Object.assign(Object.assign({}, this.options()), { currentComputations: Object.entries(this.currentComputations).reduce((acc, [cLabel, c]) => (cLabel !== label ? Object.assign(Object.assign({}, acc), { [cLabel]: c }) : Object.assign(Object.assign({}, acc), { [cLabel]: Object.assign(Object.assign({}, c), { status: 'resolved' }) })), {}), modifiedFields: [], context: 'Prune computed value' }));
144
+ this.changeListeners.forEach((l) => notify(l, newBridgedFormValueContainer, [], 'Prune computed value', this._id));
145
+ }
146
+ }
147
+ }
148
+ })
149
+ .catch(console.error); // Ignore errors in computations, they will be logged in the console
85
150
  });
86
151
  }
87
152
  getLabel() {
@@ -99,13 +164,6 @@ export class BridgedFormValuesContainer {
99
164
  unregisterChangeListener(listener) {
100
165
  this.changeListeners = this.changeListeners.filter((l) => l !== listener);
101
166
  }
102
- getDefaultValue(label) {
103
- return __awaiter(this, void 0, void 0, function* () {
104
- var _a;
105
- const formula = (_a = this.initialValuesProvider(this.contactFormValuesContainer.rootForm.descr, this.contactFormValuesContainer.rootForm.formTemplateId).find(({ metadata }) => metadata.label === label)) === null || _a === void 0 ? void 0 : _a.formula;
106
- return formula ? this.convertRawValue(yield this.compute(formula)) : undefined;
107
- });
108
- }
109
167
  getValues(revisionsFilter) {
110
168
  return Object.entries(this.contactFormValuesContainer.getValues((id, history) => revisionsFilter(id, history
111
169
  .filter(({ modified }) => !this.contact.created || !modified || modified <= this.contact.created)
@@ -189,92 +247,46 @@ export class BridgedFormValuesContainer {
189
247
  }
190
248
  return undefined;
191
249
  }
192
- //This method mutates the BridgedFormValuesContainer but can only be called from the constructor
193
- computeInitialValues() {
194
- return __awaiter(this, void 0, void 0, function* () {
195
- if (this.contactFormValuesContainer.rootForm.formTemplateId) {
196
- yield Promise.all(this.initialValuesProvider(this.contactFormValuesContainer.rootForm.descr, this.contactFormValuesContainer.rootForm.formTemplateId).map((_a) => __awaiter(this, [_a], void 0, function* ({ metadata, revisionsFilter, formula }) {
197
- var _b;
198
- try {
199
- const currentValue = this.getValues(revisionsFilter);
200
- if (!currentValue || !Object.keys(currentValue).length) {
201
- const newValue = this.convertRawValue((yield this.compute(formula)));
202
- if (newValue !== undefined) {
203
- const lng = (_b = this.language) !== null && _b !== void 0 ? _b : 'en';
204
- if (newValue && !newValue.content[lng] && newValue.content['*']) {
205
- newValue.content[lng] = newValue.content['*'];
206
- }
207
- if (newValue) {
208
- delete newValue.content['*'];
209
- }
210
- setValueOnContactFormValuesContainer(this.contactFormValuesContainer, metadata.label, lng, newValue, undefined, metadata, (fvc) => {
211
- const currentContact = this.contactFormValuesContainer.currentContact;
212
- this.contactFormValuesContainer = fvc;
213
- if (this.contact === currentContact) {
214
- this.contact = fvc.currentContact;
215
- }
216
- });
217
- }
218
- }
219
- }
220
- catch (e) {
221
- console.log(`Error while computing formula : ${formula}`, e);
222
- }
223
- })));
224
- }
225
- });
250
+ computeInitialValues(currentComputations, modifiedFields) {
251
+ return this.contactFormValuesContainer.rootForm.formTemplateId
252
+ ? this.initialValuesProvider(this.contactFormValuesContainer.rootForm.descr, this.contactFormValuesContainer.rootForm.formTemplateId, modifiedFields).reduce((acc, { metadata, revisionsFilter, formula }) => {
253
+ if (currentComputations[metadata.label] === undefined) {
254
+ const currentValue = this.getValues(revisionsFilter);
255
+ return !currentValue || !Object.keys(currentValue).length
256
+ ? Object.assign(Object.assign({}, acc), { [metadata.label]: { metadata, revisionsFilter, computation: this.compute(formula), status: 'pending' } }) : acc;
257
+ }
258
+ else {
259
+ return acc;
260
+ }
261
+ }, currentComputations)
262
+ : currentComputations;
226
263
  }
227
- //This method mutates the BridgedFormValuesContainer but can only be called from the constructor
228
- computeDependentValues() {
229
- return __awaiter(this, void 0, void 0, function* () {
230
- if (this.contactFormValuesContainer.rootForm.formTemplateId) {
231
- yield Promise.all(this.dependentValuesProvider(this.contactFormValuesContainer.rootForm.descr, this.contactFormValuesContainer.rootForm.formTemplateId).map((_a) => __awaiter(this, [_a], void 0, function* ({ metadata, revisionsFilter, formula }) {
232
- var _b;
233
- try {
234
- const currentValue = this.getValues(revisionsFilter);
235
- const newValue = this.convertRawValue((yield this.compute(formula)));
236
- if (newValue !== undefined || currentValue != undefined) {
237
- const lng = (_b = this.language) !== null && _b !== void 0 ? _b : 'en';
238
- if (newValue && !newValue.content[lng] && newValue.content['*']) {
239
- newValue.content[lng] = newValue.content['*'];
240
- }
241
- if (newValue) {
242
- delete newValue.content['*'];
243
- }
244
- const interceptor = (fvc) => {
245
- const currentContact = this.contactFormValuesContainer.currentContact;
246
- this.contactFormValuesContainer = fvc;
247
- if (this.contact === currentContact) {
248
- this.contact = fvc.currentContact;
249
- }
250
- };
251
- setValueOnContactFormValuesContainer(this.contactFormValuesContainer, metadata.label, lng, newValue, Object.keys(currentValue !== null && currentValue !== void 0 ? currentValue : {})[0], metadata, interceptor);
252
- }
253
- }
254
- catch (e) {
255
- console.log(`Error while computing formula : ${formula}`, e);
256
- }
257
- })));
258
- }
259
- });
264
+ computeDependentValues(currentComputations, modifiedFields) {
265
+ return this.contactFormValuesContainer.rootForm.formTemplateId
266
+ ? this.dependentValuesProvider(this.contactFormValuesContainer.rootForm.descr, this.contactFormValuesContainer.rootForm.formTemplateId, modifiedFields).reduce((acc, { metadata, revisionsFilter, formula }) => {
267
+ return currentComputations[metadata.label] === undefined
268
+ ? Object.assign(Object.assign({}, acc), { [metadata.label]: { metadata, revisionsFilter, computation: this.compute(formula), status: 'pending' } }) : acc;
269
+ }, currentComputations)
270
+ : currentComputations;
260
271
  }
261
- setValue(label, language, fv, id, metadata) {
262
- setValueOnContactFormValuesContainer(this.contactFormValuesContainer, label, language, fv, id, metadata);
272
+ setValue(label, language, fv, id, metadata, _, recurse = false) {
273
+ console.log(`${this._id}: setValue on ${this.contactFormValuesContainer._id}`);
274
+ return setValueOnContactFormValuesContainer(this.contactFormValuesContainer, label, language, fv, id, metadata, recurse);
263
275
  }
264
276
  setMetadata(meta, id) {
265
277
  var _a;
266
- this.contactFormValuesContainer.setMetadata({
278
+ return this.contactFormValuesContainer.setMetadata({
267
279
  label: meta.label,
268
280
  responsible: meta.owner,
269
281
  valueDate: meta.valueDate,
270
- tags: (_a = meta.tags) === null || _a === void 0 ? void 0 : _a.map((x) => new CodeStub(x)),
282
+ tags: (_a = meta.tags) === null || _a === void 0 ? void 0 : _a.map((x) => new CodeStubWithId(x)),
271
283
  }, id);
272
284
  }
273
285
  delete(serviceId) {
274
286
  this.contactFormValuesContainer.delete(serviceId);
275
287
  }
276
288
  getVersionedValuesForKey(key) {
277
- return this.getValues((id, history) => { var _a, _b, _c; return (((_b = (_a = history === null || history === void 0 ? void 0 : history[0]) === null || _a === void 0 ? void 0 : _a.value) === null || _b === void 0 ? void 0 : _b.label) && key === history[0].value.label ? [(_c = history === null || history === void 0 ? void 0 : history[0]) === null || _c === void 0 ? void 0 : _c.revision] : []); });
289
+ return this.getValues((_id, history) => { var _a, _b, _c; return (((_b = (_a = history === null || history === void 0 ? void 0 : history[0]) === null || _a === void 0 ? void 0 : _a.value) === null || _b === void 0 ? void 0 : _b.label) && key === history[0].value.label ? [(_c = history === null || history === void 0 ? void 0 : history[0]) === null || _c === void 0 ? void 0 : _c.revision] : []); });
278
290
  }
279
291
  compute(formula, sandbox) {
280
292
  return __awaiter(this, void 0, void 0, function* () {
@@ -299,6 +311,7 @@ export class BridgedFormValuesContainer {
299
311
  .join(', ');
300
312
  };
301
313
  const log = console.log;
314
+ // noinspection JSUnusedGlobalSymbols
302
315
  const native = {
303
316
  parseInt: parseInt,
304
317
  parseFloat: parseFloat,
@@ -337,8 +350,8 @@ export class BridgedFormValuesContainer {
337
350
  Promise,
338
351
  };
339
352
  const proxy = new Proxy({}, {
340
- has: (target, key) => { var _a; return !!native[key] || key === 'self' || !!this.interpreterContext[key] || Object.keys((_a = this.getVersionedValuesForKey(key)) !== null && _a !== void 0 ? _a : {}).length > 0; },
341
- get: (target, key) => {
353
+ has: (_target, key) => { var _a; return !!native[key] || key === 'self' || !!this.interpreterContext[key] || Object.keys((_a = this.getVersionedValuesForKey(key)) !== null && _a !== void 0 ? _a : {}).length > 0; },
354
+ get: (_target, key) => {
342
355
  if (key === 'undefined') {
343
356
  return undefined;
344
357
  }
@@ -352,9 +365,24 @@ export class BridgedFormValuesContainer {
352
365
  return (_a = this.interpreter) === null || _a === void 0 ? void 0 : _a.call(this, formula, sandbox !== null && sandbox !== void 0 ? sandbox : proxy);
353
366
  });
354
367
  }
368
+ isFieldBeingComputed(label) {
369
+ var _a;
370
+ return ((_a = this.currentComputations[label]) === null || _a === void 0 ? void 0 : _a.status) === 'pending';
371
+ }
355
372
  getChildren() {
356
373
  return __awaiter(this, void 0, void 0, function* () {
357
- const children = yield Promise.all((yield this.contactFormValuesContainer.getChildren()).map((fvc) => new BridgedFormValuesContainer(this.responsible, fvc, this.interpreter, this.contact, this.initialValuesProvider, this.dependentValuesProvider, this.validatorsProvider, this.language, [], this.interpreterContext).init()));
374
+ const children = yield Promise.all((yield this.contactFormValuesContainer.getChildren()).map((fvc) => new BridgedFormValuesContainer({
375
+ responsible: this.responsible,
376
+ contactFormValuesContainer: fvc,
377
+ interpreter: this.interpreter,
378
+ contact: this.contact,
379
+ initialValuesProvider: this.initialValuesProvider,
380
+ dependentValuesProvider: this.dependentValuesProvider,
381
+ validatorsProvider: this.validatorsProvider,
382
+ language: this.language,
383
+ interpreterContext: this.interpreterContext,
384
+ context: 'New child form',
385
+ })));
358
386
  console.log(`${children.length} children found in ${this.contactFormValuesContainer.rootForm.formTemplateId} initialised with `, this.initialValuesProvider);
359
387
  return children;
360
388
  });
@@ -372,7 +400,7 @@ export class BridgedFormValuesContainer {
372
400
  }
373
401
  }
374
402
  catch (e) {
375
- console.log(`Error while computing validation : ${validation}`, e);
403
+ console.warn(`Error while computing validation : ${validation}`, e);
376
404
  }
377
405
  return res;
378
406
  }), resPromise);
@@ -410,9 +438,6 @@ export class ContactFormValuesContainer {
410
438
  toString() {
411
439
  return `Contact(${this.rootForm.formTemplateId}[${this.rootForm.id}]) - ${this._id}`;
412
440
  }
413
- mustBeInitialised() {
414
- return !this._initialised;
415
- }
416
441
  /**
417
442
  * Returns a contact that combines the content of the contact in this form with the content of all contents stored in the children
418
443
  */
@@ -432,10 +457,9 @@ export class ContactFormValuesContainer {
432
457
  allForms() {
433
458
  return [this.rootForm].concat(this.children.flatMap((c) => c.allForms()));
434
459
  }
435
- constructor(rootForm, currentContact, contactsHistory, serviceFactory, children, formFactory, formRecycler, changeListeners = [], initialised = true) {
436
- this._id = uuidv4();
437
- this._initialised = false;
438
- console.log(`Creating contact FVC (${rootForm.formTemplateId}) with ${children.length} children [${this._id}]`);
460
+ constructor(rootForm, currentContact, contactsHistory, serviceFactory, children, formFactory, formRecycler, changeListeners = []) {
461
+ //console.log(`Creating contact FVC (${rootForm.formTemplateId}) with ${children.length} children [${this._id}]`)
462
+ this._id = `C-${(cfvcIdGen++).toString()}`;
439
463
  if (contactsHistory.includes(currentContact)) {
440
464
  throw new Error('Illegal argument, the history must not contain the currentContact');
441
465
  }
@@ -447,10 +471,9 @@ export class ContactFormValuesContainer {
447
471
  this.formFactory = formFactory;
448
472
  this.formRecycler = formRecycler;
449
473
  this.changeListeners = changeListeners;
450
- this._initialised = initialised;
451
474
  this.indexedServices = [this.currentContact].concat(this.contactsHistory).reduce((acc, ctc) => {
452
475
  var _a, _b, _c;
453
- const services = (_c = (_b = (_a = ctc.services) === null || _a === void 0 ? void 0 : _a.filter((s) => { var _a; return (_a = ctc.subContacts) === null || _a === void 0 ? void 0 : _a.some((sc) => { var _a; return sc.formId === this.rootForm.id && ((_a = sc.services) === null || _a === void 0 ? void 0 : _a.some((sss) => sss.serviceId === s.id)); }); })) === null || _b === void 0 ? void 0 : _b.reduce((acc, s) => {
476
+ return ((_c = (_b = (_a = ctc.services) === null || _a === void 0 ? void 0 : _a.filter((s) => { var _a; return (_a = ctc.subContacts) === null || _a === void 0 ? void 0 : _a.some((sc) => { var _a; return sc.formId === this.rootForm.id && ((_a = sc.services) === null || _a === void 0 ? void 0 : _a.some((sss) => sss.serviceId === s.id)); }); })) === null || _b === void 0 ? void 0 : _b.reduce((acc, s) => {
454
477
  var _a, _b;
455
478
  return s.id
456
479
  ? Object.assign(Object.assign({}, acc), { [s.id]: ((_a = acc[s.id]) !== null && _a !== void 0 ? _a : (acc[s.id] = [])).concat({
@@ -458,8 +481,7 @@ export class ContactFormValuesContainer {
458
481
  modified: ctc.created,
459
482
  value: s,
460
483
  }) }) : acc;
461
- }, acc)) !== null && _c !== void 0 ? _c : acc;
462
- return services;
484
+ }, acc)) !== null && _c !== void 0 ? _c : acc);
463
485
  }, {});
464
486
  this.synchronise();
465
487
  }
@@ -477,7 +499,7 @@ export class ContactFormValuesContainer {
477
499
  const newContactFormValuesContainer = new ContactFormValuesContainer(this.rootForm, this.currentContact, this.contactsHistory, this.serviceFactory, this.children.map((c) => {
478
500
  return c.rootForm.id === childFormValueContainer.rootForm.id ? newValue : c;
479
501
  }), this.formFactory, this.formRecycler);
480
- this.changeListeners.forEach((l) => notify(l, newContactFormValuesContainer));
502
+ this.changeListeners.forEach((l) => notify(l, newContactFormValuesContainer, [], `Child ${childFormValueContainer.rootForm.formTemplateId} changed`, this._id));
481
503
  },
482
504
  ];
483
505
  }
@@ -487,7 +509,7 @@ export class ContactFormValuesContainer {
487
509
  ? yield Promise.all((yield formChildrenProvider(rootForm.id)).map((f) => __awaiter(this, void 0, void 0, function* () {
488
510
  // eslint-disable-next-line max-len
489
511
  return yield ContactFormValuesContainer.fromFormsHierarchy(f, currentContact, contactsHistory, serviceFactory, formChildrenProvider, formFactory, formRecycler); })))
490
- : [], formFactory, formRecycler, changeListeners, false);
512
+ : [], formFactory, formRecycler, changeListeners);
491
513
  contactFormValuesContainer.children.forEach((childFVC) => contactFormValuesContainer.registerChildFormValuesContainer(childFVC));
492
514
  return contactFormValuesContainer;
493
515
  });
@@ -516,9 +538,6 @@ export class ContactFormValuesContainer {
516
538
  throw new Error('Validation not supported at contact level');
517
539
  });
518
540
  }
519
- getDefaultValue() {
520
- return Promise.resolve(undefined);
521
- }
522
541
  getValues(revisionsFilter) {
523
542
  return Object.entries(this.getServicesInHistory(revisionsFilter)).reduce((acc, [id, history]) => history.length
524
543
  ? Object.assign(Object.assign({}, acc), { [id]: [...history].sort((a, b) => ((b === null || b === void 0 ? void 0 : b.modified) || +new Date()) - ((a === null || a === void 0 ? void 0 : a.modified) || +new Date())) }) : acc, {});
@@ -541,7 +560,7 @@ export class ContactFormValuesContainer {
541
560
  label: (_c = s.label) !== null && _c !== void 0 ? _c : s.id,
542
561
  responsible: s.responsible,
543
562
  valueDate: s.valueDate,
544
- tags: s.tags,
563
+ tags: normalizeCodes(s.tags),
545
564
  },
546
565
  }) }) : acc;
547
566
  }, acc)) !== null && _b !== void 0 ? _b : acc;
@@ -563,19 +582,23 @@ export class ContactFormValuesContainer {
563
582
  meta.codes && (newService.codes = normalizeCodes(meta.codes));
564
583
  meta.tags && (newService.tags = normalizeCodes(meta.tags));
565
584
  const newFormValuesContainer = new ContactFormValuesContainer(this.rootForm, Object.assign(Object.assign({}, this.currentContact), { services: (_a = this.currentContact.services) === null || _a === void 0 ? void 0 : _a.map((s) => (s.id === service.id ? newService : s)) }), this.contactsHistory, this.serviceFactory, this.children, this.formFactory, this.formRecycler, this.changeListeners);
566
- this.changeListeners.forEach((l) => notify(l, newFormValuesContainer));
585
+ this.changeListeners.forEach((l) => notify(l, newFormValuesContainer, [meta], `Metadata change for service ${service.id}`, this._id));
586
+ return true;
587
+ }
588
+ else {
589
+ return false;
567
590
  }
568
591
  }
569
- setValue(label, language, value, id, metadata, changeListenersOverrider) {
592
+ setValue(label, language, value, id, metadata, changeListenersOverrider, recurse = false) {
570
593
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
571
594
  const service = (id && ((_b = (_a = this.getServicesInHistory((sid, history) => (sid === id ? history.map((x) => x.revision) : []))[id]) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.value)) || this.serviceFactory(label, id);
572
595
  if (!service.id) {
573
596
  throw new Error('Service id must be defined');
574
597
  }
575
- console.log('Setting value of service', service.id, 'with', value, 'and metadata', metadata);
576
598
  const newContent = (_c = value === null || value === void 0 ? void 0 : value.content) === null || _c === void 0 ? void 0 : _c[language];
577
599
  const newCodes = (value === null || value === void 0 ? void 0 : value.codes) ? normalizeCodes(value.codes) : [];
578
600
  if (!isContentEqual((_d = service.content) === null || _d === void 0 ? void 0 : _d[language], newContent) || (newCodes && !areCodesEqual(newCodes, (_e = service.codes) !== null && _e !== void 0 ? _e : []))) {
601
+ //console.log('Setting value of service', service.id, 'with', value, 'and metadata', metadata)
579
602
  const newService = new DecryptedService(Object.assign(Object.assign({}, service), { modified: Date.now() }));
580
603
  const newContents = newContent
581
604
  ? Object.assign(Object.assign({}, (service.content || {})), { [language]: newContent }) : Object.assign({}, (service.content || {}));
@@ -628,7 +651,22 @@ export class ContactFormValuesContainer {
628
651
  : [...((_v = this.currentContact.services) !== null && _v !== void 0 ? _v : []), newService] });
629
652
  }
630
653
  const newFormValuesContainer = new ContactFormValuesContainer(this.rootForm, newCurrentContact, this.contactsHistory.map((c) => (c === this.currentContact ? newCurrentContact : c)), this.serviceFactory, this.children, this.formFactory, this.formRecycler, this.changeListeners);
631
- changeListenersOverrider ? changeListenersOverrider(newFormValuesContainer) : this.changeListeners.forEach((l) => notify(l, newFormValuesContainer));
654
+ changeListenersOverrider
655
+ ? changeListenersOverrider(newFormValuesContainer)
656
+ : this.changeListeners.forEach((l) => {
657
+ var _a;
658
+ return notify(l, newFormValuesContainer, [
659
+ {
660
+ valueDate: newService.valueDate,
661
+ tags: normalizeCodes(newService.tags),
662
+ label: (_a = newService.label) !== null && _a !== void 0 ? _a : label,
663
+ },
664
+ ], `Set value of service ${service.id}}`, this._id, recurse);
665
+ });
666
+ return true;
667
+ }
668
+ else {
669
+ return false;
632
670
  }
633
671
  }
634
672
  delete(serviceId) {
@@ -638,7 +676,7 @@ export class ContactFormValuesContainer {
638
676
  const newFormValuesContainer = new ContactFormValuesContainer(this.rootForm, Object.assign(Object.assign({}, this.currentContact), { services: (_a = this.currentContact.services) === null || _a === void 0 ? void 0 : _a.map((s) => s.id === serviceId
639
677
  ? new DecryptedService(Object.assign(Object.assign({}, service), { endOfLife: Date.now() }))
640
678
  : s) }), this.contactsHistory, this.serviceFactory, this.children, this.formFactory, this.formRecycler, this.changeListeners);
641
- this.changeListeners.forEach((l) => notify(l, newFormValuesContainer));
679
+ this.changeListeners.forEach((l) => notify(l, newFormValuesContainer, [], `Delete service ${serviceId}`, this._id));
642
680
  }
643
681
  }
644
682
  compute() {
@@ -646,6 +684,9 @@ export class ContactFormValuesContainer {
646
684
  throw new Error('Compute not supported at contact level');
647
685
  });
648
686
  }
687
+ isFieldBeingComputed() {
688
+ return false;
689
+ }
649
690
  /** returns all services in history that match a selector
650
691
  *
651
692
  * @private
@@ -665,7 +706,7 @@ export class ContactFormValuesContainer {
665
706
  owner: s.responsible,
666
707
  valueDate: s.valueDate,
667
708
  codes: s.codes,
668
- tags: s.tags,
709
+ tags: normalizeCodes(s.tags),
669
710
  },
670
711
  });
671
712
  }));
@@ -679,10 +720,10 @@ export class ContactFormValuesContainer {
679
720
  if (!parentId)
680
721
  return;
681
722
  const newForm = yield this.formFactory(parentId, anchorId, templateId, label);
682
- const childFVC = new ContactFormValuesContainer(newForm, this.currentContact, this.contactsHistory, this.serviceFactory, [], this.formFactory, this.formRecycler, [], false);
723
+ const childFVC = new ContactFormValuesContainer(newForm, this.currentContact, this.contactsHistory, this.serviceFactory, [], this.formFactory, this.formRecycler, []);
683
724
  const newContactFormValuesContainer = new ContactFormValuesContainer(this.rootForm, this.currentContact, this.contactsHistory, this.serviceFactory, [...this.children, childFVC], this.formFactory, this.formRecycler, this.changeListeners);
684
725
  newContactFormValuesContainer.registerChildFormValuesContainer(childFVC);
685
- this.changeListeners.forEach((l) => notify(l, newContactFormValuesContainer));
726
+ this.changeListeners.forEach((l) => notify(l, newContactFormValuesContainer, [], `Add child form ${newForm.formTemplateId} to contact form ${this.rootForm.formTemplateId}`, this._id));
686
727
  });
687
728
  }
688
729
  getServiceInCurrentContact(id) {
@@ -693,14 +734,14 @@ export class ContactFormValuesContainer {
693
734
  removeChild(container) {
694
735
  return __awaiter(this, void 0, void 0, function* () {
695
736
  const newContactFormValuesContainer = new ContactFormValuesContainer(this.rootForm, this.currentContact, this.contactsHistory, this.serviceFactory, this.children.filter((c) => c.rootForm.id !== container.rootForm.id), this.formFactory, this.formRecycler, this.changeListeners);
696
- this.changeListeners.forEach((l) => notify(l, newContactFormValuesContainer));
737
+ this.changeListeners.forEach((l) => notify(l, newContactFormValuesContainer, [], `Remove child form ${container.rootForm.formTemplateId} from contact form ${this.rootForm.formTemplateId}`, this._id));
697
738
  });
698
739
  }
699
740
  }
700
- const setValueOnContactFormValuesContainer = (cfvc, label, language, fv, id, metadata, changeListenersOverrider) => {
741
+ const setValueOnContactFormValuesContainer = (cfvc, label, language, fv, id, metadata, recurse = false) => {
701
742
  var _a, _b, _c, _d;
702
743
  const value = fv === null || fv === void 0 ? void 0 : fv.content[language];
703
- cfvc.setValue(label, language, new DecryptedService({
744
+ return cfvc.setValue(label, language, new DecryptedService({
704
745
  id: id,
705
746
  codes: (_b = (_a = fv === null || fv === void 0 ? void 0 : fv.codes) === null || _a === void 0 ? void 0 : _a.map((x) => new CodeStub(x))) !== null && _b !== void 0 ? _b : [],
706
747
  content: value
@@ -713,8 +754,8 @@ const setValueOnContactFormValuesContainer = (cfvc, label, language, fv, id, met
713
754
  label: (_c = metadata === null || metadata === void 0 ? void 0 : metadata.label) !== null && _c !== void 0 ? _c : label,
714
755
  responsible: metadata === null || metadata === void 0 ? void 0 : metadata.owner,
715
756
  valueDate: metadata === null || metadata === void 0 ? void 0 : metadata.valueDate,
716
- tags: (_d = metadata === null || metadata === void 0 ? void 0 : metadata.tags) === null || _d === void 0 ? void 0 : _d.map((x) => new CodeStub(x)),
757
+ tags: normalizeCodes((_d = metadata === null || metadata === void 0 ? void 0 : metadata.tags) === null || _d === void 0 ? void 0 : _d.map((x) => new CodeStub(x))),
717
758
  }
718
- : undefined, changeListenersOverrider);
759
+ : undefined, undefined, recurse);
719
760
  };
720
761
  //# sourceMappingURL=form-values-container.js.map