@icure/form 1.1.26 → 2.0.2

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 (46) hide show
  1. package/.yarn/install-state.gz +0 -0
  2. package/components/common/metadata-buttons-bar.js +66 -15
  3. package/components/common/metadata-buttons-bar.js.map +1 -1
  4. package/components/icure-button/index.js +66 -15
  5. package/components/icure-button/index.js.map +1 -1
  6. package/components/icure-button-group/index.js +66 -15
  7. package/components/icure-button-group/index.js.map +1 -1
  8. package/components/icure-date-picker/index.js +70 -18
  9. package/components/icure-date-picker/index.js.map +1 -1
  10. package/components/icure-dropdown-field/index.js +66 -15
  11. package/components/icure-dropdown-field/index.js.map +1 -1
  12. package/components/icure-form/index.js +66 -15
  13. package/components/icure-form/index.js.map +1 -1
  14. package/components/icure-form/renderer/form/form-selection-button.d.ts +6 -1
  15. package/components/icure-form/renderer/form/form-selection-button.js +1126 -58
  16. package/components/icure-form/renderer/form/form-selection-button.js.map +1 -1
  17. package/components/icure-form/renderer/form/form.js +22 -19
  18. package/components/icure-form/renderer/form/form.js.map +1 -1
  19. package/components/icure-label/index.js +66 -15
  20. package/components/icure-label/index.js.map +1 -1
  21. package/components/icure-text-field/index.js +66 -15
  22. package/components/icure-text-field/index.js.map +1 -1
  23. package/components/model/index.d.ts +7 -1
  24. package/components/model/index.js +47 -3
  25. package/components/model/index.js.map +1 -1
  26. package/components/themes/default/index.js +2 -0
  27. package/components/themes/default/index.js.map +1 -1
  28. package/components/themes/icure-blue/index.js +2 -0
  29. package/components/themes/icure-blue/index.js.map +1 -1
  30. package/components/themes/kendo/index.js +2 -0
  31. package/components/themes/kendo/index.js.map +1 -1
  32. package/generic/model.d.ts +6 -5
  33. package/generic/model.js.map +1 -1
  34. package/icure/form-values-container.d.ts +31 -17
  35. package/icure/form-values-container.js +134 -75
  36. package/icure/form-values-container.js.map +1 -1
  37. package/package.json +1 -1
  38. package/utils/code-utils.d.ts +2 -0
  39. package/utils/code-utils.js +4 -1
  40. package/utils/code-utils.js.map +1 -1
  41. package/utils/fields-values-provider.d.ts +4 -9
  42. package/utils/fields-values-provider.js +6 -15
  43. package/utils/fields-values-provider.js.map +1 -1
  44. package/utils/form-value-container.d.ts +1 -1
  45. package/utils/form-value-container.js +25 -36
  46. package/utils/form-value-container.js.map +1 -1
@@ -1,5 +1,5 @@
1
1
  import { Contact, Form as ICureForm, Service } from '@icure/api';
2
- import { FormValuesContainer, FormValuesContainerMutation, ID, Version, VersionedData } from '../generic';
2
+ import { FormValuesContainer, Version, VersionedData } from '../generic';
3
3
  import { ServiceMetadata } from './model';
4
4
  import { FieldMetadata, FieldValue, Validator } from '../components/model';
5
5
  /** This class is a bridge between the ICure API and the generic FormValuesContainer interface.
@@ -24,14 +24,16 @@ import { FieldMetadata, FieldValue, Validator } from '../components/model';
24
24
  export declare class BridgedFormValuesContainer implements FormValuesContainer<FieldValue, FieldMetadata> {
25
25
  private responsible;
26
26
  private interpreter?;
27
+ private initialValuesProvider;
27
28
  private dependentValuesProvider;
28
29
  private validatorsProvider;
29
30
  private language;
30
31
  private changeListeners;
31
32
  private contact;
32
33
  private contactFormValuesContainer;
33
- private _children;
34
- get children(): BridgedFormValuesContainer[];
34
+ private _id;
35
+ private mutateAndNotify;
36
+ toString(): string;
35
37
  /**
36
38
  * Creates an instance of BridgedFormValuesContainer.
37
39
  * @param responsible The id of the data owner responsible for the creation of the values
@@ -42,12 +44,18 @@ export declare class BridgedFormValuesContainer implements FormValuesContainer<F
42
44
  * @param validatorsProvider A function that provides the validators for a given anchorId and templateId
43
45
  * @param language The language in which the values are displayed
44
46
  * @param changeListeners The listeners that will be notified when the values change
47
+ * @param initialValuesProvider A lambda that provides the initial values of the form
45
48
  */
46
49
  constructor(responsible: string, contactFormValuesContainer: ContactFormValuesContainer, interpreter?: (<T, S extends {
47
50
  [key: string]: unknown;
48
51
  [key: symbol]: unknown;
49
- }>(formula: string, sandbox: S) => T | undefined) | undefined, contact?: Contact, dependentValuesProvider?: (anchorId: string | undefined, templateId: string) => {
52
+ }>(formula: string, sandbox: S) => T | undefined) | undefined, contact?: Contact, initialValuesProvider?: (anchorId?: string, templateId?: string) => {
53
+ metadata: FieldMetadata;
54
+ revisionsFilter: (id: string, history: Version<FieldMetadata>[]) => (string | null)[];
55
+ formula: string;
56
+ }[], dependentValuesProvider?: (anchorId: string | undefined, templateId: string | undefined) => {
50
57
  metadata: FieldMetadata;
58
+ revisionsFilter: (id: string, history: Version<FieldMetadata>[]) => (string | null)[];
51
59
  formula: string;
52
60
  }[], validatorsProvider?: (anchorId: string | undefined, templateId: string) => {
53
61
  metadata: FieldMetadata;
@@ -60,19 +68,20 @@ export declare class BridgedFormValuesContainer implements FormValuesContainer<F
60
68
  unregisterChangeListener(listener: (newValue: BridgedFormValuesContainer) => void): void;
61
69
  getValues(revisionsFilter: (id: string, history: Version<FieldMetadata>[]) => (string | null)[]): VersionedData<FieldValue>;
62
70
  getMetadata(id: string, revisions: (string | null)[]): VersionedData<FieldMetadata>;
63
- private mutateAndNotify;
71
+ private computeInitialValues;
64
72
  private computeDependentValues;
65
- setValue(label: string, language: string, fv?: FieldValue, id?: string, metadata?: FieldMetadata): FormValuesContainerMutation<FieldValue, FieldMetadata, BridgedFormValuesContainer, ID>;
66
- setMetadata(meta: FieldMetadata, id?: string | undefined): FormValuesContainerMutation<FieldValue, FieldMetadata, BridgedFormValuesContainer, ID>;
67
- delete(serviceId: string): FormValuesContainerMutation<FieldValue, FieldMetadata, BridgedFormValuesContainer, void>;
73
+ setValue(label: string, language: string, fv?: FieldValue, id?: string, metadata?: FieldMetadata): void;
74
+ setMetadata(meta: FieldMetadata, id?: string | undefined): void;
75
+ delete(serviceId: string): void;
68
76
  private getVersionedValuesForKey;
69
77
  compute<T, S extends {
70
78
  [key: string | symbol]: unknown;
71
79
  }>(formula: string, sandbox?: S): T | undefined;
72
80
  getChildren(): FormValuesContainer<FieldValue, FieldMetadata>[];
73
81
  getValidationErrors(): [FieldMetadata, string][];
74
- addChild(anchorId: string, templateId: string, label: string): Promise<FormValuesContainerMutation<FieldValue, FieldMetadata, BridgedFormValuesContainer, BridgedFormValuesContainer>>;
75
- removeChild(container: BridgedFormValuesContainer): Promise<FormValuesContainerMutation<FieldValue, FieldMetadata, BridgedFormValuesContainer, void>>;
82
+ addChild(anchorId: string, templateId: string, label: string): Promise<void>;
83
+ removeChild(container: BridgedFormValuesContainer): Promise<void>;
84
+ synchronise(): this;
76
85
  }
77
86
  /**
78
87
  * This class is a form values container that uses a hierarchy of forms as a data source. The actual values are extracted from the services of the contacts.
@@ -90,8 +99,13 @@ export declare class ContactFormValuesContainer implements FormValuesContainer<S
90
99
  serviceFactory: (label: string, serviceId?: string) => Service;
91
100
  formFactory: (anchorId: string, formTemplateId: string, label: string) => Promise<ICureForm>;
92
101
  changeListeners: ((newValue: ContactFormValuesContainer) => void)[];
93
- constructor(rootForm: ICureForm, currentContact: Contact, contactsHistory: Contact[], serviceFactory: (label: string, serviceId?: string) => Service, children: ContactFormValuesContainer[], formFactory: (anchorId: string, formTemplateId: string, label: string) => Promise<ICureForm>, changeListeners?: ((newValue: ContactFormValuesContainer) => void)[]);
94
- registerChildFormValuesContainer(childFVC: ContactFormValuesContainer): void;
102
+ private _id;
103
+ private _initialised;
104
+ toString(): string;
105
+ mustBeInitialised(): boolean;
106
+ constructor(rootForm: ICureForm, currentContact: Contact, contactsHistory: Contact[], serviceFactory: (label: string, serviceId?: string) => Service, children: ContactFormValuesContainer[], formFactory: (anchorId: string, formTemplateId: string, label: string) => Promise<ICureForm>, changeListeners?: ((newValue: ContactFormValuesContainer) => void)[], initialised?: boolean);
107
+ synchronise(): this;
108
+ registerChildFormValuesContainer(childFormValueContainer: ContactFormValuesContainer): void;
95
109
  static fromFormsHierarchy(rootForm: ICureForm, currentContact: Contact, contactsHistory: Contact[], serviceFactory: (label: string, serviceId?: string) => Service, formChildrenProvider: (parentId: string) => Promise<ICureForm[]>, formFactory: (anchorId: string, formTemplateId: string, label: string) => Promise<ICureForm>, changeListeners?: ((newValue: ContactFormValuesContainer) => void)[]): Promise<ContactFormValuesContainer>;
96
110
  getLabel(): string;
97
111
  getFormId(): string | undefined;
@@ -101,9 +115,9 @@ export declare class ContactFormValuesContainer implements FormValuesContainer<S
101
115
  getValidationErrors(): [FieldMetadata, string][];
102
116
  getValues(revisionsFilter: (id: string, history: Version<ServiceMetadata>[]) => (string | null)[]): VersionedData<Service>;
103
117
  getMetadata(id: string, revisions: (string | null)[]): VersionedData<ServiceMetadata>;
104
- setMetadata(meta: ServiceMetadata, id?: string): FormValuesContainerMutation<Service, ServiceMetadata, ContactFormValuesContainer, ID>;
105
- setValue(label: string, language: string, value?: Service, id?: string, metadata?: ServiceMetadata): FormValuesContainerMutation<Service, ServiceMetadata, ContactFormValuesContainer, ID>;
106
- delete(serviceId: string): FormValuesContainerMutation<Service, ServiceMetadata, ContactFormValuesContainer, void>;
118
+ setMetadata(meta: ServiceMetadata, id?: string): void;
119
+ setValue(label: string, language: string, value?: Service, id?: string, metadata?: ServiceMetadata, changeListenersOverrider?: (fvc: ContactFormValuesContainer) => void): void;
120
+ delete(serviceId: string): void;
107
121
  compute<T>(): T | undefined;
108
122
  /** returns all services in history that match a selector
109
123
  *
@@ -111,7 +125,7 @@ export declare class ContactFormValuesContainer implements FormValuesContainer<S
111
125
  * @param revisionsFilter
112
126
  */
113
127
  private getServicesInHistory;
114
- addChild(anchorId: string, templateId: string, label: string): Promise<FormValuesContainerMutation<Service, ServiceMetadata, ContactFormValuesContainer, ContactFormValuesContainer>>;
128
+ addChild(anchorId: string, templateId: string, label: string): Promise<void>;
115
129
  private getServiceInCurrentContact;
116
- removeChild(container: ContactFormValuesContainer): Promise<FormValuesContainerMutation<Service, ServiceMetadata, ContactFormValuesContainer, void>>;
130
+ removeChild(container: ContactFormValuesContainer): Promise<void>;
117
131
  }
@@ -15,6 +15,12 @@ const no_lodash_1 = require("../utils/no-lodash");
15
15
  const icure_utils_1 = require("./icure-utils");
16
16
  const primitive_1 = require("../utils/primitive");
17
17
  const dates_1 = require("../utils/dates");
18
+ const uuid_1 = require("uuid");
19
+ const code_utils_1 = require("../utils/code-utils");
20
+ function notify(l, fvc) {
21
+ //console.log('Notifying', l, fvc.toString())
22
+ l(fvc);
23
+ }
18
24
  /** This class is a bridge between the ICure API and the generic FormValuesContainer interface.
19
25
  * It wraps around a ContactFormValuesContainer and provides a series of services:
20
26
  * - It computes dependent values when the form is created
@@ -35,11 +41,8 @@ const dates_1 = require("../utils/dates");
35
41
  * This class is fairly generic and can be used as an inspiration or subclassed for other bridges
36
42
  */
37
43
  class BridgedFormValuesContainer {
38
- get children() {
39
- var _a;
40
- return ((_a = this._children) !== null && _a !== void 0 ? _a : (this._children = this.contactFormValuesContainer
41
- .getChildren()
42
- .map((fvc) => new BridgedFormValuesContainer(this.responsible, fvc, this.interpreter, this.contact, this.dependentValuesProvider, this.validatorsProvider, this.language, this.changeListeners))));
44
+ toString() {
45
+ return `Bridged(${this.contactFormValuesContainer.rootForm.formTemplateId}[${this.contactFormValuesContainer.rootForm.id}]) - ${this._id}`;
43
46
  }
44
47
  /**
45
48
  * Creates an instance of BridgedFormValuesContainer.
@@ -51,17 +54,31 @@ class BridgedFormValuesContainer {
51
54
  * @param validatorsProvider A function that provides the validators for a given anchorId and templateId
52
55
  * @param language The language in which the values are displayed
53
56
  * @param changeListeners The listeners that will be notified when the values change
57
+ * @param initialValuesProvider A lambda that provides the initial values of the form
54
58
  */
55
- constructor(responsible, contactFormValuesContainer, interpreter, contact, dependentValuesProvider = () => [], validatorsProvider = () => [], language = 'en', changeListeners = []) {
59
+ constructor(responsible, contactFormValuesContainer, interpreter, contact, initialValuesProvider = () => [], dependentValuesProvider = () => [], validatorsProvider = () => [], language = 'en', changeListeners = []) {
56
60
  this.responsible = responsible;
57
61
  this.interpreter = interpreter;
62
+ this.initialValuesProvider = initialValuesProvider;
58
63
  this.dependentValuesProvider = dependentValuesProvider;
59
64
  this.validatorsProvider = validatorsProvider;
60
65
  this.language = language;
61
66
  this.changeListeners = changeListeners;
67
+ this._id = (0, uuid_1.v4)();
68
+ console.log(`Creating bridge FVC (${contactFormValuesContainer.rootForm.formTemplateId}) with ${contactFormValuesContainer.children.length} children [${this._id}]`);
62
69
  //Before start to broadcast changes, we need to fill in the contactFormValuesContainer with the dependent values
63
70
  this.contactFormValuesContainer = contactFormValuesContainer;
71
+ this.mutateAndNotify = (newContactFormValuesContainer) => {
72
+ newContactFormValuesContainer.unregisterChangeListener(this.mutateAndNotify);
73
+ const newBridgedFormValueContainer = 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);
74
+ this.changeListeners.forEach((l) => notify(l, newBridgedFormValueContainer));
75
+ return newBridgedFormValueContainer;
76
+ };
77
+ this.contactFormValuesContainer.registerChangeListener(this.mutateAndNotify);
64
78
  this.contact = contact !== null && contact !== void 0 ? contact : contactFormValuesContainer.currentContact;
79
+ if (this.contactFormValuesContainer.mustBeInitialised()) {
80
+ this.computeInitialValues();
81
+ }
65
82
  this.computeDependentValues();
66
83
  }
67
84
  getLabel() {
@@ -127,18 +144,46 @@ class BridgedFormValuesContainer {
127
144
  },
128
145
  })) })), {});
129
146
  }
130
- mutateAndNotify(newContactFormValuesContainer) {
131
- const newBridgedFormValueContainer = new BridgedFormValuesContainer(this.responsible, newContactFormValuesContainer, this.interpreter, this.contact === this.contactFormValuesContainer.currentContact ? newContactFormValuesContainer.currentContact : this.contact, this.dependentValuesProvider, this.validatorsProvider, this.language, this.changeListeners);
132
- this.changeListeners.forEach((l) => l(newBridgedFormValueContainer));
133
- return newBridgedFormValueContainer;
147
+ //This method mutates the BridgedFormValuesContainer but can only be called from the constructor
148
+ computeInitialValues() {
149
+ if (this.contactFormValuesContainer.rootForm.formTemplateId) {
150
+ this.initialValuesProvider(this.contactFormValuesContainer.rootForm.descr, this.contactFormValuesContainer.rootForm.formTemplateId).forEach(({ metadata, revisionsFilter, formula }) => {
151
+ var _a;
152
+ try {
153
+ const currentValue = this.getValues(revisionsFilter);
154
+ if (!currentValue || !Object.keys(currentValue).length) {
155
+ const newValue = this.compute(formula);
156
+ if (newValue !== undefined) {
157
+ const lng = (_a = this.language) !== null && _a !== void 0 ? _a : 'en';
158
+ if (newValue && !newValue.content[lng] && newValue.content['*']) {
159
+ newValue.content[lng] = newValue.content['*'];
160
+ }
161
+ if (newValue) {
162
+ delete newValue.content['*'];
163
+ }
164
+ setValueOnContactFormValuesContainer(this.contactFormValuesContainer, metadata.label, lng, newValue, undefined, metadata, (fvc) => {
165
+ const currentContact = this.contactFormValuesContainer.currentContact;
166
+ this.contactFormValuesContainer = fvc;
167
+ if (this.contact === currentContact) {
168
+ this.contact = fvc.currentContact;
169
+ }
170
+ });
171
+ }
172
+ }
173
+ }
174
+ catch (e) {
175
+ console.log(`Error while computing formula : ${formula}`, e);
176
+ }
177
+ });
178
+ }
134
179
  }
135
180
  //This method mutates the BridgedFormValuesContainer but can only be called from the constructor
136
181
  computeDependentValues() {
137
182
  if (this.contactFormValuesContainer.rootForm.formTemplateId) {
138
- this.dependentValuesProvider(this.contactFormValuesContainer.rootForm.descr, this.contactFormValuesContainer.rootForm.formTemplateId).forEach(({ metadata, formula }) => {
183
+ this.dependentValuesProvider(this.contactFormValuesContainer.rootForm.descr, this.contactFormValuesContainer.rootForm.formTemplateId).forEach(({ metadata, revisionsFilter, formula }) => {
139
184
  var _a;
140
185
  try {
141
- const currentValue = this.getVersionedValuesForKey(metadata.label);
186
+ const currentValue = this.getValues(revisionsFilter);
142
187
  const newValue = this.compute(formula);
143
188
  if (newValue !== undefined || currentValue != undefined) {
144
189
  const lng = (_a = this.language) !== null && _a !== void 0 ? _a : 'en';
@@ -148,11 +193,13 @@ class BridgedFormValuesContainer {
148
193
  if (newValue) {
149
194
  delete newValue.content['*'];
150
195
  }
151
- const currentContact = this.contactFormValuesContainer.currentContact;
152
- this.contactFormValuesContainer = setValueOnContactFormValuesContainer(this.contactFormValuesContainer, metadata.label, lng, newValue, Object.keys(currentValue !== null && currentValue !== void 0 ? currentValue : {})[0], metadata).formValuesContainer;
153
- if (this.contact === currentContact) {
154
- this.contact = this.contactFormValuesContainer.currentContact;
155
- }
196
+ setValueOnContactFormValuesContainer(this.contactFormValuesContainer, metadata.label, lng, newValue, Object.keys(currentValue !== null && currentValue !== void 0 ? currentValue : {})[0], metadata, (fvc) => {
197
+ const currentContact = this.contactFormValuesContainer.currentContact;
198
+ this.contactFormValuesContainer = fvc;
199
+ if (this.contact === currentContact) {
200
+ this.contact = fvc.currentContact;
201
+ }
202
+ });
156
203
  }
157
204
  }
158
205
  catch (e) {
@@ -162,21 +209,18 @@ class BridgedFormValuesContainer {
162
209
  }
163
210
  }
164
211
  setValue(label, language, fv, id, metadata) {
165
- const mutation = setValueOnContactFormValuesContainer(this.contactFormValuesContainer, label, language, fv, id, metadata);
166
- return { result: mutation.result, formValuesContainer: this.mutateAndNotify(mutation.formValuesContainer) };
212
+ setValueOnContactFormValuesContainer(this.contactFormValuesContainer, label, language, fv, id, metadata);
167
213
  }
168
214
  setMetadata(meta, id) {
169
- const mutation = this.contactFormValuesContainer.setMetadata({
215
+ this.contactFormValuesContainer.setMetadata({
170
216
  label: meta.label,
171
217
  responsible: meta.owner,
172
218
  valueDate: meta.valueDate,
173
219
  tags: meta.tags,
174
220
  }, id);
175
- return { result: mutation.result, formValuesContainer: this.mutateAndNotify(mutation.formValuesContainer) };
176
221
  }
177
222
  delete(serviceId) {
178
- const mutation = this.contactFormValuesContainer.delete(serviceId);
179
- return { result: undefined, formValuesContainer: this.mutateAndNotify(mutation.formValuesContainer) };
223
+ this.contactFormValuesContainer.delete(serviceId);
180
224
  }
181
225
  getVersionedValuesForKey(key) {
182
226
  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] : []); });
@@ -229,7 +273,11 @@ class BridgedFormValuesContainer {
229
273
  return (_a = this.interpreter) === null || _a === void 0 ? void 0 : _a.call(this, formula, sandbox !== null && sandbox !== void 0 ? sandbox : proxy);
230
274
  }
231
275
  getChildren() {
232
- return this.contactFormValuesContainer.getChildren().map((fvc) => new BridgedFormValuesContainer(this.responsible, fvc, this.interpreter, this.contact));
276
+ const children = this.contactFormValuesContainer
277
+ .getChildren()
278
+ .map((fvc) => new BridgedFormValuesContainer(this.responsible, fvc, this.interpreter, this.contact, this.initialValuesProvider, this.dependentValuesProvider, this.validatorsProvider, this.language, []));
279
+ console.log(`${children.length} children found in ${this.contactFormValuesContainer.rootForm.formTemplateId} initialised with `, this.initialValuesProvider);
280
+ return children;
233
281
  }
234
282
  getValidationErrors() {
235
283
  if (this.contactFormValuesContainer.rootForm.formTemplateId) {
@@ -251,21 +299,18 @@ class BridgedFormValuesContainer {
251
299
  }
252
300
  addChild(anchorId, templateId, label) {
253
301
  return __awaiter(this, void 0, void 0, function* () {
254
- const mutation = yield this.contactFormValuesContainer.addChild(anchorId, templateId, label);
255
- const newBridgedFormValueContainer = this.mutateAndNotify(mutation.formValuesContainer);
256
- const newChild = newBridgedFormValueContainer.children.find((c) => c.contactFormValuesContainer === mutation.result);
257
- if (!newChild) {
258
- throw new Error('Illegal state, the new child must be found');
259
- }
260
- return { result: newChild, formValuesContainer: newBridgedFormValueContainer };
302
+ yield this.contactFormValuesContainer.addChild(anchorId, templateId, label);
261
303
  });
262
304
  }
263
305
  removeChild(container) {
264
306
  return __awaiter(this, void 0, void 0, function* () {
265
- const mutation = yield this.contactFormValuesContainer.removeChild(container.contactFormValuesContainer);
266
- return { result: undefined, formValuesContainer: this.mutateAndNotify(mutation.formValuesContainer) };
307
+ yield this.contactFormValuesContainer.removeChild(container.contactFormValuesContainer);
267
308
  });
268
309
  }
310
+ synchronise() {
311
+ this.contactFormValuesContainer.synchronise();
312
+ return this;
313
+ }
269
314
  }
270
315
  exports.BridgedFormValuesContainer = BridgedFormValuesContainer;
271
316
  /**
@@ -277,7 +322,16 @@ exports.BridgedFormValuesContainer = BridgedFormValuesContainer;
277
322
  * The `serviceFactory` and `formFactory` are used to create new services and add sub-forms.
278
323
  */
279
324
  class ContactFormValuesContainer {
280
- constructor(rootForm, currentContact, contactsHistory, serviceFactory, children, formFactory, changeListeners = []) {
325
+ toString() {
326
+ return `Contact(${this.rootForm.formTemplateId}[${this.rootForm.id}]) - ${this._id}`;
327
+ }
328
+ mustBeInitialised() {
329
+ return !this._initialised;
330
+ }
331
+ constructor(rootForm, currentContact, contactsHistory, serviceFactory, children, formFactory, changeListeners = [], initialised = true) {
332
+ this._id = (0, uuid_1.v4)();
333
+ this._initialised = false;
334
+ console.log(`Creating contact FVC (${rootForm.formTemplateId}) with ${children.length} children [${this._id}]`);
281
335
  if (contactsHistory.includes(currentContact)) {
282
336
  throw new Error('Illegal argument, the history must not contain the currentContact');
283
337
  }
@@ -288,12 +342,26 @@ class ContactFormValuesContainer {
288
342
  this.serviceFactory = serviceFactory;
289
343
  this.formFactory = formFactory;
290
344
  this.changeListeners = changeListeners;
345
+ this._initialised = initialised;
346
+ this.synchronise();
291
347
  }
292
- registerChildFormValuesContainer(childFVC) {
293
- childFVC.registerChangeListener((newValue) => {
294
- const newContactFormValuesContainer = new ContactFormValuesContainer(this.rootForm, this.currentContact, this.contactsHistory, this.serviceFactory, this.children.map((c) => (c === childFVC ? newValue : c)), this.formFactory, this.changeListeners);
295
- this.changeListeners.forEach((l) => l(newContactFormValuesContainer));
348
+ synchronise() {
349
+ this.children.forEach((childFVC) => {
350
+ this.registerChildFormValuesContainer(childFVC.synchronise());
296
351
  });
352
+ return this;
353
+ }
354
+ //Make sure that when a child is changed, a new version of this is created with the updated child
355
+ registerChildFormValuesContainer(childFormValueContainer) {
356
+ childFormValueContainer.changeListeners = [
357
+ (newValue) => {
358
+ console.log(`Child ${newValue._id} ${childFormValueContainer.rootForm.formTemplateId} changed, updating parent ${this._id} ${this.rootForm.formTemplateId}`);
359
+ const newContactFormValuesContainer = new ContactFormValuesContainer(this.rootForm, this.currentContact, this.contactsHistory, this.serviceFactory, this.children.map((c) => {
360
+ return c.rootForm.id === childFormValueContainer.rootForm.id ? newValue : c;
361
+ }), this.formFactory);
362
+ this.changeListeners.forEach((l) => notify(l, newContactFormValuesContainer));
363
+ },
364
+ ];
297
365
  }
298
366
  static fromFormsHierarchy(rootForm_1, currentContact_1, contactsHistory_1, serviceFactory_1, formChildrenProvider_1, formFactory_1) {
299
367
  return __awaiter(this, arguments, void 0, function* (rootForm, currentContact, contactsHistory, serviceFactory, formChildrenProvider, formFactory, changeListeners = []) {
@@ -301,7 +369,7 @@ class ContactFormValuesContainer {
301
369
  ? yield Promise.all((yield formChildrenProvider(rootForm.id)).map((f) => __awaiter(this, void 0, void 0, function* () {
302
370
  // eslint-disable-next-line max-len
303
371
  return yield ContactFormValuesContainer.fromFormsHierarchy(f, currentContact, contactsHistory, serviceFactory, formChildrenProvider, formFactory); })))
304
- : [], formFactory, changeListeners);
372
+ : [], formFactory, changeListeners, false);
305
373
  contactFormValuesContainer.children.forEach((childFVC) => contactFormValuesContainer.registerChildFormValuesContainer(childFVC));
306
374
  return contactFormValuesContainer;
307
375
  });
@@ -367,24 +435,22 @@ class ContactFormValuesContainer {
367
435
  const newService = new api_1.Service(Object.assign(Object.assign({}, service), { modified: Date.now() }));
368
436
  meta.responsible && (newService.responsible = meta.responsible);
369
437
  meta.valueDate && (newService.valueDate = meta.valueDate);
370
- meta.codes && (newService.codes = meta.codes);
371
- meta.tags && (newService.tags = meta.tags);
438
+ meta.codes && (newService.codes = (0, code_utils_1.normalizeCodes)(meta.codes));
439
+ meta.tags && (newService.tags = (0, code_utils_1.normalizeCodes)(meta.tags));
372
440
  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.changeListeners);
373
- this.changeListeners.forEach((l) => l(newFormValuesContainer));
374
- return { result: service.id, formValuesContainer: newFormValuesContainer };
441
+ this.changeListeners.forEach((l) => notify(l, newFormValuesContainer));
375
442
  }
376
- return { result: service.id, formValuesContainer: this };
377
443
  }
378
- setValue(label, language, value, id, metadata) {
379
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
444
+ setValue(label, language, value, id, metadata, changeListenersOverrider) {
445
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
380
446
  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);
381
447
  if (!service.id) {
382
448
  throw new Error('Service id must be defined');
383
449
  }
384
450
  console.log('Setting value of service', service.id, 'with', value, 'and metadata', metadata);
385
451
  const newContent = (_c = value === null || value === void 0 ? void 0 : value.content) === null || _c === void 0 ? void 0 : _c[language];
386
- const newCodes = (_d = value === null || value === void 0 ? void 0 : value.codes) !== null && _d !== void 0 ? _d : [];
387
- if (!(0, icure_utils_1.isContentEqual)((_e = service.content) === null || _e === void 0 ? void 0 : _e[language], newContent) || (newCodes && !(0, icure_utils_1.areCodesEqual)(newCodes, (_f = service.codes) !== null && _f !== void 0 ? _f : []))) {
452
+ const newCodes = (value === null || value === void 0 ? void 0 : value.codes) ? (0, code_utils_1.normalizeCodes)(value.codes) : [];
453
+ if (!(0, icure_utils_1.isContentEqual)((_d = service.content) === null || _d === void 0 ? void 0 : _d[language], newContent) || (newCodes && !(0, icure_utils_1.areCodesEqual)(newCodes, (_e = service.codes) !== null && _e !== void 0 ? _e : []))) {
388
454
  const newService = new api_1.Service(Object.assign(Object.assign({}, service), { modified: Date.now() }));
389
455
  const newContents = newContent ? Object.assign(Object.assign({}, (service.content || {})), { [language]: newContent }) : Object.assign({}, (service.content || {}));
390
456
  if (!newContent) {
@@ -392,38 +458,34 @@ class ContactFormValuesContainer {
392
458
  }
393
459
  let newCurrentContact;
394
460
  if (!Object.entries(newContents).filter(([, cnt]) => cnt !== undefined).length) {
395
- newCurrentContact = Object.assign(Object.assign({}, this.currentContact), { services: ((_g = this.currentContact.services) !== null && _g !== void 0 ? _g : []).some((s) => s.id === service.id)
396
- ? ((_h = this.currentContact.services) !== null && _h !== void 0 ? _h : []).filter((s) => s.id !== service.id)
397
- : [...((_j = this.currentContact.services) !== null && _j !== void 0 ? _j : [])] });
461
+ newCurrentContact = Object.assign(Object.assign({}, this.currentContact), { services: ((_f = this.currentContact.services) !== null && _f !== void 0 ? _f : []).some((s) => s.id === service.id)
462
+ ? ((_g = this.currentContact.services) !== null && _g !== void 0 ? _g : []).filter((s) => s.id !== service.id)
463
+ : [...((_h = this.currentContact.services) !== null && _h !== void 0 ? _h : [])] });
398
464
  }
399
465
  else {
400
466
  newService.content = newContents;
401
467
  newService.codes = newCodes;
402
468
  if (metadata) {
403
- newService.responsible = (_k = metadata.responsible) !== null && _k !== void 0 ? _k : newService.responsible;
404
- newService.valueDate = (_l = metadata.valueDate) !== null && _l !== void 0 ? _l : newService.valueDate;
405
- newService.tags = (_m = metadata.tags) !== null && _m !== void 0 ? _m : newService.tags;
406
- newService.label = (_o = metadata.label) !== null && _o !== void 0 ? _o : newService.label;
469
+ newService.responsible = (_j = metadata.responsible) !== null && _j !== void 0 ? _j : newService.responsible;
470
+ newService.valueDate = (_k = metadata.valueDate) !== null && _k !== void 0 ? _k : newService.valueDate;
471
+ newService.tags = metadata.tags ? (0, code_utils_1.normalizeCodes)(metadata.tags) : newService.tags;
472
+ newService.label = (_l = metadata.label) !== null && _l !== void 0 ? _l : newService.label;
407
473
  }
408
- newCurrentContact = Object.assign(Object.assign({}, this.currentContact), { services: ((_p = this.currentContact.services) !== null && _p !== void 0 ? _p : []).some((s) => s.id === service.id)
409
- ? ((_q = this.currentContact.services) !== null && _q !== void 0 ? _q : []).map((s) => (s.id === service.id ? newService : s))
410
- : [...((_r = this.currentContact.services) !== null && _r !== void 0 ? _r : []), newService] });
474
+ newCurrentContact = Object.assign(Object.assign({}, this.currentContact), { services: ((_m = this.currentContact.services) !== null && _m !== void 0 ? _m : []).some((s) => s.id === service.id)
475
+ ? ((_o = this.currentContact.services) !== null && _o !== void 0 ? _o : []).map((s) => (s.id === service.id ? newService : s))
476
+ : [...((_p = this.currentContact.services) !== null && _p !== void 0 ? _p : []), newService] });
411
477
  }
412
478
  const newFormValuesContainer = new ContactFormValuesContainer(this.rootForm, newCurrentContact, this.contactsHistory.map((c) => (c === this.currentContact ? newCurrentContact : c)), this.serviceFactory, this.children, this.formFactory, this.changeListeners);
413
- this.changeListeners.forEach((l) => l(newFormValuesContainer));
414
- return { result: service.id, formValuesContainer: newFormValuesContainer };
479
+ changeListenersOverrider ? changeListenersOverrider(newFormValuesContainer) : this.changeListeners.forEach((l) => notify(l, newFormValuesContainer));
415
480
  }
416
- return { result: service.id, formValuesContainer: this };
417
481
  }
418
482
  delete(serviceId) {
419
483
  var _a;
420
484
  const service = this.getServiceInCurrentContact(serviceId);
421
485
  if (service) {
422
486
  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 ? new api_1.Service(Object.assign(Object.assign({}, service), { endOfLife: Date.now() })) : s)) }), this.contactsHistory, this.serviceFactory, this.children, this.formFactory, this.changeListeners);
423
- this.changeListeners.forEach((l) => l(newFormValuesContainer));
424
- return { result: undefined, formValuesContainer: newFormValuesContainer };
487
+ this.changeListeners.forEach((l) => notify(l, newFormValuesContainer));
425
488
  }
426
- return { result: undefined, formValuesContainer: this };
427
489
  }
428
490
  compute() {
429
491
  throw new Error('Compute not supported at contact level');
@@ -463,11 +525,10 @@ class ContactFormValuesContainer {
463
525
  addChild(anchorId, templateId, label) {
464
526
  return __awaiter(this, void 0, void 0, function* () {
465
527
  const newForm = yield this.formFactory(anchorId, templateId, label);
466
- const childFVC = new ContactFormValuesContainer(newForm, this.currentContact, this.contactsHistory, this.serviceFactory, [], this.formFactory);
467
- const newContactFormValuesContainer = new ContactFormValuesContainer(this.rootForm, this.currentContact, this.contactsHistory, this.serviceFactory, [...this.children, childFVC], this.formFactory);
528
+ const childFVC = new ContactFormValuesContainer(newForm, this.currentContact, this.contactsHistory, this.serviceFactory, [], this.formFactory, [], false);
529
+ const newContactFormValuesContainer = new ContactFormValuesContainer(this.rootForm, this.currentContact, this.contactsHistory, this.serviceFactory, [...this.children, childFVC], this.formFactory, this.changeListeners);
468
530
  newContactFormValuesContainer.registerChildFormValuesContainer(childFVC);
469
- this.changeListeners.forEach((l) => l(newContactFormValuesContainer));
470
- return { result: childFVC, formValuesContainer: newContactFormValuesContainer };
531
+ this.changeListeners.forEach((l) => notify(l, newContactFormValuesContainer));
471
532
  });
472
533
  }
473
534
  getServiceInCurrentContact(id) {
@@ -477,17 +538,16 @@ class ContactFormValuesContainer {
477
538
  }
478
539
  removeChild(container) {
479
540
  return __awaiter(this, void 0, void 0, function* () {
480
- const newContactFormValuesContainer = new ContactFormValuesContainer(this.rootForm, this.currentContact, this.contactsHistory, this.serviceFactory, this.children.filter((c) => c !== container), this.formFactory);
481
- this.changeListeners.forEach((l) => l(newContactFormValuesContainer));
482
- return { result: undefined, formValuesContainer: newContactFormValuesContainer };
541
+ 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.changeListeners);
542
+ this.changeListeners.forEach((l) => notify(l, newContactFormValuesContainer));
483
543
  });
484
544
  }
485
545
  }
486
546
  exports.ContactFormValuesContainer = ContactFormValuesContainer;
487
- const setValueOnContactFormValuesContainer = (cfvc, label, language, fv, id, metadata) => {
547
+ const setValueOnContactFormValuesContainer = (cfvc, label, language, fv, id, metadata, changeListenersOverrider) => {
488
548
  var _a, _b;
489
549
  const value = fv === null || fv === void 0 ? void 0 : fv.content[language];
490
- const mutation = cfvc.setValue(label, language, {
550
+ cfvc.setValue(label, language, {
491
551
  id: id,
492
552
  codes: (_a = fv === null || fv === void 0 ? void 0 : fv.codes) !== null && _a !== void 0 ? _a : [],
493
553
  content: value
@@ -502,7 +562,6 @@ const setValueOnContactFormValuesContainer = (cfvc, label, language, fv, id, met
502
562
  valueDate: metadata === null || metadata === void 0 ? void 0 : metadata.valueDate,
503
563
  tags: metadata === null || metadata === void 0 ? void 0 : metadata.tags,
504
564
  }
505
- : undefined);
506
- return mutation;
565
+ : undefined, changeListenersOverrider);
507
566
  };
508
567
  //# sourceMappingURL=form-values-container.js.map