@icure/form 2.1.2 → 2.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.yarn/cache/{libphonenumber-js-npm-1.12.34-cd35ce8e26-e4bb10ba42.zip → libphonenumber-js-npm-1.12.38-a5180a8a02-2a2eeb122d.zip} +0 -0
- package/.yarn/cache/{lodash-npm-4.17.21-6382451519-eb835a2e51.zip → lodash-npm-4.17.23-50bdb1c01a-7daad39758.zip} +0 -0
- package/.yarn/cache/{markdown-it-npm-14.1.0-e337d75bfe-07296b45eb.zip → markdown-it-npm-14.1.1-45c173274d-d6d55865c6.zip} +0 -0
- package/.yarn/cache/prosemirror-markdown-npm-1.13.4-1a47b172bd-3306b4eca0.zip +0 -0
- package/.yarn/cache/prosemirror-transform-npm-1.11.0-fa260ad6f3-71989931b8.zip +0 -0
- package/.yarn/cache/{prosemirror-view-npm-1.41.5-39b37df338-ee47e9091a.zip → prosemirror-view-npm-1.41.6-a9d2feed27-68f6a8bd66.zip} +0 -0
- package/.yarn/install-state.gz +0 -0
- package/components/common/field.d.ts +14 -2
- package/components/common/field.js +95 -2
- package/components/common/field.js.map +1 -1
- package/components/common/utils.js +11 -1
- package/components/common/utils.js.map +1 -1
- package/components/icure-button-group/index.js +1 -1
- package/components/icure-button-group/index.js.map +1 -1
- package/components/icure-form/fields/button-group/checkbox.js +3 -4
- package/components/icure-form/fields/button-group/checkbox.js.map +1 -1
- package/components/icure-form/fields/button-group/radio-button.js +3 -4
- package/components/icure-form/fields/button-group/radio-button.js.map +1 -1
- package/components/icure-form/fields/date-picker/date-picker.js +3 -4
- package/components/icure-form/fields/date-picker/date-picker.js.map +1 -1
- package/components/icure-form/fields/date-picker/date-time-picker.js +3 -4
- package/components/icure-form/fields/date-picker/date-time-picker.js.map +1 -1
- package/components/icure-form/fields/date-picker/time-picker.js +3 -4
- package/components/icure-form/fields/date-picker/time-picker.js.map +1 -1
- package/components/icure-form/fields/dropdown/dropdown-field.js +3 -4
- package/components/icure-form/fields/dropdown/dropdown-field.js.map +1 -1
- package/components/icure-form/fields/measure-field/measure-field.js +3 -4
- package/components/icure-form/fields/measure-field/measure-field.js.map +1 -1
- package/components/icure-form/fields/number-field/number-field.js +3 -4
- package/components/icure-form/fields/number-field/number-field.js.map +1 -1
- package/components/icure-form/fields/text-field/text-field.js +3 -4
- package/components/icure-form/fields/text-field/text-field.js.map +1 -1
- package/components/icure-form/fields/utils/index.d.ts +0 -5
- package/components/icure-form/fields/utils/index.js +1 -12
- package/components/icure-form/fields/utils/index.js.map +1 -1
- package/components/icure-form/index.js +14 -10
- package/components/icure-form/index.js.map +1 -1
- package/components/icure-form/renderer/form/form.js +10 -8
- package/components/icure-form/renderer/form/form.js.map +1 -1
- package/components/icure-text-field/index.js +0 -2
- package/components/icure-text-field/index.js.map +1 -1
- package/components/icure-text-field/schema/measure-schema.js +0 -1
- package/components/icure-text-field/schema/measure-schema.js.map +1 -1
- package/components/model/index.d.ts +17 -17
- package/components/model/index.js +34 -30
- package/components/model/index.js.map +1 -1
- package/generic/model.d.ts +11 -6
- package/generic/model.js.map +1 -1
- package/icure/form-values-container.d.ts +33 -21
- package/icure/form-values-container.js +325 -154
- package/icure/form-values-container.js.map +1 -1
- package/icure/icure-utils.js +48 -18
- package/icure/icure-utils.js.map +1 -1
- package/package.json +1 -1
- package/utils/code-utils.js +2 -2
- package/utils/code-utils.js.map +1 -1
- package/utils/fields-values-provider.d.ts +1 -1
- package/utils/fields-values-provider.js +6 -4
- package/utils/fields-values-provider.js.map +1 -1
- package/.yarn/cache/prosemirror-markdown-npm-1.13.2-6e2f179fd8-ce9fcb3b13.zip +0 -0
- package/.yarn/cache/prosemirror-transform-npm-1.10.5-5b3b4f5f61-6f5921e53a.zip +0 -0
|
@@ -15,10 +15,30 @@ 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
18
|
const code_utils_1 = require("../utils/code-utils");
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
let _ordinal = 0;
|
|
20
|
+
function notify(l, fvc, changedKeys, force = false) {
|
|
21
|
+
l(fvc, changedKeys, force);
|
|
22
|
+
}
|
|
23
|
+
function primitiveTypeToString(pt) {
|
|
24
|
+
switch (pt.type) {
|
|
25
|
+
case 'string':
|
|
26
|
+
return pt.value;
|
|
27
|
+
case 'number':
|
|
28
|
+
return pt.value.toString();
|
|
29
|
+
case 'boolean':
|
|
30
|
+
return pt.value.toString();
|
|
31
|
+
case 'measure':
|
|
32
|
+
return pt.value !== undefined ? `${pt.value}${pt.unit ? ' ' + pt.unit : ''}` : '';
|
|
33
|
+
case 'timestamp':
|
|
34
|
+
return new Date(pt.value).toISOString();
|
|
35
|
+
case 'datetime':
|
|
36
|
+
return pt.value.toString();
|
|
37
|
+
case 'compound':
|
|
38
|
+
return Object.entries(pt.value)
|
|
39
|
+
.map(([k, v]) => `${k}: ${primitiveTypeToString(v)}`)
|
|
40
|
+
.join(', ');
|
|
41
|
+
}
|
|
22
42
|
}
|
|
23
43
|
/** This class is a bridge between the ICure API and the generic FormValuesContainer interface.
|
|
24
44
|
* It wraps around a ContactFormValuesContainer and provides a series of services:
|
|
@@ -55,8 +75,9 @@ class BridgedFormValuesContainer {
|
|
|
55
75
|
* @param language The language in which the values are displayed
|
|
56
76
|
* @param changeListeners The listeners that will be notified when the values change
|
|
57
77
|
* @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
|
|
78
|
+
* @param dependenciesCache
|
|
58
79
|
*/
|
|
59
|
-
constructor(responsible, contactFormValuesContainer, interpreter, contact, initialValuesProvider = () => [], dependentValuesProvider = () => [], validatorsProvider = () => [], language = 'en', changeListeners = [], interpreterContext = {}) {
|
|
80
|
+
constructor(responsible, contactFormValuesContainer, interpreter, contact, initialValuesProvider = () => [], dependentValuesProvider = () => [], validatorsProvider = () => [], language = 'en', changeListeners = [], interpreterContext = {}, dependenciesCache = {}) {
|
|
60
81
|
this.responsible = responsible;
|
|
61
82
|
this.interpreter = interpreter;
|
|
62
83
|
this.initialValuesProvider = initialValuesProvider;
|
|
@@ -65,25 +86,59 @@ class BridgedFormValuesContainer {
|
|
|
65
86
|
this.language = language;
|
|
66
87
|
this.changeListeners = changeListeners;
|
|
67
88
|
this.interpreterContext = interpreterContext;
|
|
68
|
-
this.
|
|
69
|
-
|
|
89
|
+
this.dependenciesCache = dependenciesCache;
|
|
90
|
+
this._id = '';
|
|
91
|
+
this.dependentValuesComputationIteration = undefined;
|
|
70
92
|
//Before start to broadcast changes, we need to fill in the contactFormValuesContainer with the dependent values
|
|
71
93
|
this.contactFormValuesContainer = contactFormValuesContainer;
|
|
72
|
-
this.
|
|
94
|
+
this._id = `[${contactFormValuesContainer._id}]`;
|
|
95
|
+
console.log(`+ BFVC ${this._id} created`);
|
|
96
|
+
this.mutateAndNotify = (newContactFormValuesContainer, changedKeys, force = false) => {
|
|
97
|
+
if (this.changeListeners.length === 0) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (!force && this.contactFormValuesContainer === newContactFormValuesContainer) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
this.contactFormValuesContainer.unregisterChangeListener(this.mutateAndNotify);
|
|
73
104
|
newContactFormValuesContainer.unregisterChangeListener(this.mutateAndNotify);
|
|
74
|
-
const newBridgedFormValueContainer =
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
105
|
+
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, this.interpreterContext, this.dependenciesCache);
|
|
106
|
+
console.log(`- init started ${newBridgedFormValueContainer._id} with changed keys: ${changedKeys ? changedKeys.join(', ') : 'all'}`);
|
|
107
|
+
const initPromise = newBridgedFormValueContainer.init(changedKeys, this.dependentValuesComputationIteration);
|
|
108
|
+
this.changeListeners.forEach((l) => notify(l, newBridgedFormValueContainer, changedKeys));
|
|
109
|
+
initPromise
|
|
110
|
+
.catch((e) => {
|
|
111
|
+
console.log('Error while initializing new BridgedFormValuesContainer', e);
|
|
112
|
+
})
|
|
113
|
+
.finally(() => {
|
|
114
|
+
console.log(`- init finished ${newBridgedFormValueContainer._id}`);
|
|
115
|
+
});
|
|
116
|
+
};
|
|
78
117
|
this.contactFormValuesContainer.registerChangeListener(this.mutateAndNotify);
|
|
79
118
|
this.contact = contact !== null && contact !== void 0 ? contact : contactFormValuesContainer.currentContact;
|
|
80
119
|
}
|
|
120
|
+
/* init can be called several times on the same instance but the initialisation will only be done once */
|
|
81
121
|
init() {
|
|
82
|
-
return __awaiter(this,
|
|
83
|
-
|
|
84
|
-
|
|
122
|
+
return __awaiter(this, arguments, void 0, function* (changedKeys = null, pendingComputationIteration) {
|
|
123
|
+
let changedKeysByInit = [];
|
|
124
|
+
if (pendingComputationIteration) {
|
|
125
|
+
const changes = yield pendingComputationIteration;
|
|
126
|
+
if (changes.length > 0) {
|
|
127
|
+
this.quietlyApplyChangesOnContactFormValueContainer(changes);
|
|
128
|
+
changedKeysByInit = yield this.computeDependentValues([...(changedKeys !== null && changedKeys !== void 0 ? changedKeys : []), ...changes.map(({ metadata }) => metadata.label)], this.contactFormValuesContainer.mustBeInitialised());
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
changedKeysByInit = yield this.computeDependentValues(changedKeys, this.contactFormValuesContainer.mustBeInitialised());
|
|
132
|
+
}
|
|
85
133
|
}
|
|
86
|
-
|
|
134
|
+
else {
|
|
135
|
+
console.log('Start compute');
|
|
136
|
+
changedKeysByInit = yield this.computeDependentValues(changedKeys, this.contactFormValuesContainer.mustBeInitialised());
|
|
137
|
+
console.log('Finish compute');
|
|
138
|
+
}
|
|
139
|
+
//After all the silent updates, we need a last one that causes a new BridgedFormValuesContainer to be created and broadcasted to the listeners, so that they get the final values with all the dependencies computed
|
|
140
|
+
console.log('Launch refresh');
|
|
141
|
+
this.contactFormValuesContainer.changeListeners.forEach((l) => notify(l, this.contactFormValuesContainer, changedKeysByInit, changedKeysByInit.length > 0));
|
|
87
142
|
return this;
|
|
88
143
|
});
|
|
89
144
|
}
|
|
@@ -102,12 +157,10 @@ class BridgedFormValuesContainer {
|
|
|
102
157
|
unregisterChangeListener(listener) {
|
|
103
158
|
this.changeListeners = this.changeListeners.filter((l) => l !== listener);
|
|
104
159
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
return formula ? this.convertRawValue(yield this.compute(formula)) : undefined;
|
|
110
|
-
});
|
|
160
|
+
getDefaultValueProvider(label) {
|
|
161
|
+
var _a;
|
|
162
|
+
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;
|
|
163
|
+
return formula ? () => __awaiter(this, void 0, void 0, function* () { return this.convertRawValue(yield this.compute(formula)); }) : undefined;
|
|
111
164
|
}
|
|
112
165
|
getValues(revisionsFilter) {
|
|
113
166
|
return Object.entries(this.contactFormValuesContainer.getValues((id, history) => revisionsFilter(id, history
|
|
@@ -193,73 +246,89 @@ class BridgedFormValuesContainer {
|
|
|
193
246
|
return undefined;
|
|
194
247
|
}
|
|
195
248
|
//This method mutates the BridgedFormValuesContainer but can only be called from the constructor
|
|
196
|
-
computeInitialValues
|
|
249
|
+
computeDependentValues(changedKeys, computeInitialValues) {
|
|
197
250
|
return __awaiter(this, void 0, void 0, function* () {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
251
|
+
const initialValues = (computeInitialValues ? this.initialValuesProvider(this.contactFormValuesContainer.rootForm.descr, this.contactFormValuesContainer.rootForm.formTemplateId) : []).filter(({ revisionsFilter }) => {
|
|
252
|
+
const currentValue = this.getValues(revisionsFilter);
|
|
253
|
+
return !currentValue || !Object.keys(currentValue).length;
|
|
254
|
+
});
|
|
255
|
+
const dependentValues = this.dependentValuesProvider(this.contactFormValuesContainer.rootForm.descr, this.contactFormValuesContainer.rootForm.formTemplateId);
|
|
256
|
+
const iterate = (changedKeys, iterationCount) => __awaiter(this, void 0, void 0, function* () {
|
|
257
|
+
if (this.contactFormValuesContainer.rootForm.formTemplateId) {
|
|
258
|
+
console.log(`% ${iterationCount}, keys: ${changedKeys ? changedKeys.join(', ') : 'all'}`);
|
|
259
|
+
return yield Promise.all(dependentValues.concat(initialValues).map((_a) => __awaiter(this, [_a], void 0, function* ({ metadata, revisionsFilter, formula }) {
|
|
260
|
+
var _b, _c;
|
|
261
|
+
try {
|
|
262
|
+
if (!changedKeys || !this.dependenciesCache[formula] || this.dependenciesCache[formula].some((d) => changedKeys.includes(d))) {
|
|
263
|
+
const currentValue = this.getValues(revisionsFilter);
|
|
264
|
+
try {
|
|
265
|
+
const computationResult = yield this.compute(formula);
|
|
266
|
+
this.dependenciesCache[formula] = [...((_b = this.dependenciesCache[formula]) !== null && _b !== void 0 ? _b : []), ...computationResult.dependencies].filter((d, idx, array) => array.indexOf(d) === idx);
|
|
267
|
+
const newValue = computationResult.value ? this.convertRawValue(computationResult.value) : undefined;
|
|
268
|
+
if (newValue !== undefined || (currentValue != undefined && Object.keys(currentValue).length > 0 && currentValue[Object.keys(currentValue)[0]][0].value)) {
|
|
269
|
+
const lng = (_c = this.language) !== null && _c !== void 0 ? _c : 'en';
|
|
270
|
+
if (newValue && !newValue.content[lng] && newValue.content['*']) {
|
|
271
|
+
newValue.content[lng] = newValue.content['*'];
|
|
272
|
+
}
|
|
273
|
+
if (newValue) {
|
|
274
|
+
delete newValue.content['*'];
|
|
275
|
+
}
|
|
276
|
+
return { serviceId: Object.keys(currentValue !== null && currentValue !== void 0 ? currentValue : {})[0], metadata, language: lng, value: newValue };
|
|
277
|
+
}
|
|
209
278
|
}
|
|
210
|
-
|
|
211
|
-
|
|
279
|
+
catch (e) {
|
|
280
|
+
console.log(`Error while computing formula : ${formula}`, e);
|
|
212
281
|
}
|
|
213
|
-
setValueOnContactFormValuesContainer(this.contactFormValuesContainer, metadata.label, lng, newValue, undefined, metadata, (fvc) => {
|
|
214
|
-
const currentContact = this.contactFormValuesContainer.currentContact;
|
|
215
|
-
this.contactFormValuesContainer = fvc;
|
|
216
|
-
if (this.contact === currentContact) {
|
|
217
|
-
this.contact = fvc.currentContact;
|
|
218
|
-
}
|
|
219
|
-
});
|
|
220
282
|
}
|
|
221
283
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
284
|
+
catch (e) {
|
|
285
|
+
console.log(`Error while computing formula : ${formula}`, e);
|
|
286
|
+
}
|
|
287
|
+
return null;
|
|
288
|
+
}))).then((results) => {
|
|
289
|
+
return results.filter((r) => !!r);
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
return [];
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
let latestKeys = changedKeys;
|
|
297
|
+
const iterationCount = 0;
|
|
298
|
+
const allChangedKeys = [];
|
|
299
|
+
while (true) {
|
|
300
|
+
if (latestKeys != null && latestKeys.length === 0) {
|
|
301
|
+
this.dependentValuesComputationIteration = undefined;
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
const changesPromise = iterate(latestKeys, iterationCount);
|
|
305
|
+
this.dependentValuesComputationIteration = changesPromise;
|
|
306
|
+
const changesResult = yield changesPromise;
|
|
307
|
+
latestKeys = this.quietlyApplyChangesOnContactFormValueContainer(changesResult);
|
|
308
|
+
allChangedKeys.push(...latestKeys);
|
|
227
309
|
}
|
|
310
|
+
return allChangedKeys;
|
|
228
311
|
});
|
|
229
312
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
247
|
-
const interceptor = (fvc) => {
|
|
248
|
-
const currentContact = this.contactFormValuesContainer.currentContact;
|
|
249
|
-
this.contactFormValuesContainer = fvc;
|
|
250
|
-
if (this.contact === currentContact) {
|
|
251
|
-
this.contact = fvc.currentContact;
|
|
252
|
-
}
|
|
253
|
-
};
|
|
254
|
-
setValueOnContactFormValuesContainer(this.contactFormValuesContainer, metadata.label, lng, newValue, Object.keys(currentValue !== null && currentValue !== void 0 ? currentValue : {})[0], metadata, interceptor);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
catch (e) {
|
|
258
|
-
console.log(`Error while computing formula : ${formula}`, e);
|
|
259
|
-
}
|
|
260
|
-
})));
|
|
313
|
+
quietlyApplyChangesOnContactFormValueContainer(changes) {
|
|
314
|
+
const allChangedKeys = [];
|
|
315
|
+
const interceptor = (fvc, changedKeys) => {
|
|
316
|
+
const currentContact = this.contactFormValuesContainer.currentContact;
|
|
317
|
+
this.contactFormValuesContainer = fvc;
|
|
318
|
+
if (this.contact === currentContact) {
|
|
319
|
+
this.contact = fvc.currentContact;
|
|
320
|
+
}
|
|
321
|
+
allChangedKeys.push(...(changedKeys !== null && changedKeys !== void 0 ? changedKeys : []));
|
|
322
|
+
};
|
|
323
|
+
changes.forEach(({ serviceId, metadata, language, value }) => {
|
|
324
|
+
try {
|
|
325
|
+
setValueOnContactFormValuesContainer(this.contactFormValuesContainer, metadata.label, language, value !== null && value !== void 0 ? value : undefined, serviceId, metadata, interceptor);
|
|
326
|
+
}
|
|
327
|
+
catch (e) {
|
|
328
|
+
console.log(`Error while applying dependent value change for ${metadata.label} (${serviceId})`, e);
|
|
261
329
|
}
|
|
262
330
|
});
|
|
331
|
+
return allChangedKeys;
|
|
263
332
|
}
|
|
264
333
|
setValue(label, language, fv, id, metadata) {
|
|
265
334
|
setValueOnContactFormValuesContainer(this.contactFormValuesContainer, label, language, fv, id, metadata);
|
|
@@ -278,9 +347,10 @@ class BridgedFormValuesContainer {
|
|
|
278
347
|
getVersionedValuesForKey(key) {
|
|
279
348
|
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] : []); });
|
|
280
349
|
}
|
|
281
|
-
compute(formula
|
|
350
|
+
compute(formula) {
|
|
282
351
|
return __awaiter(this, void 0, void 0, function* () {
|
|
283
352
|
var _a;
|
|
353
|
+
const dependencies = new Set();
|
|
284
354
|
// noinspection JSUnusedGlobalSymbols
|
|
285
355
|
const parseContent = (content, toString = false) => {
|
|
286
356
|
var _a, _b;
|
|
@@ -301,6 +371,7 @@ class BridgedFormValuesContainer {
|
|
|
301
371
|
.join(', ');
|
|
302
372
|
};
|
|
303
373
|
const log = console.log;
|
|
374
|
+
// noinspection JSUnusedGlobalSymbols
|
|
304
375
|
const native = {
|
|
305
376
|
parseInt: parseInt,
|
|
306
377
|
parseFloat: parseFloat,
|
|
@@ -348,42 +419,40 @@ class BridgedFormValuesContainer {
|
|
|
348
419
|
if (!!nativeValue) {
|
|
349
420
|
return nativeValue;
|
|
350
421
|
}
|
|
351
|
-
|
|
422
|
+
if (key === 'self') {
|
|
423
|
+
return proxy;
|
|
424
|
+
}
|
|
425
|
+
else {
|
|
426
|
+
dependencies.add(key.toString());
|
|
427
|
+
return this.interpreterContext[key] ? this.interpreterContext[key]() : Object.values(this.getVersionedValuesForKey(key)).map((v) => { var _a; return (_a = v[0]) === null || _a === void 0 ? void 0 : _a.value; });
|
|
428
|
+
}
|
|
352
429
|
},
|
|
353
430
|
});
|
|
354
|
-
return (_a = this.interpreter) === null || _a === void 0 ? void 0 : _a.call(this, formula,
|
|
431
|
+
return { value: yield ((_a = this.interpreter) === null || _a === void 0 ? void 0 : _a.call(this, formula, proxy)), dependencies: Array.from(dependencies) };
|
|
355
432
|
});
|
|
356
433
|
}
|
|
357
434
|
getChildren() {
|
|
358
435
|
return __awaiter(this, void 0, void 0, function* () {
|
|
359
|
-
|
|
360
|
-
console.log(`${children.length} children found in ${this.contactFormValuesContainer.rootForm.formTemplateId} initialised with `, this.initialValuesProvider);
|
|
361
|
-
return children;
|
|
436
|
+
return 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()));
|
|
362
437
|
});
|
|
363
438
|
}
|
|
364
439
|
getValidationErrors() {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
}), Promise.resolve([]));
|
|
382
|
-
}
|
|
383
|
-
else {
|
|
384
|
-
return [];
|
|
385
|
-
}
|
|
386
|
-
});
|
|
440
|
+
if (this.contactFormValuesContainer.rootForm.formTemplateId) {
|
|
441
|
+
return this.validatorsProvider(this.contactFormValuesContainer.rootForm.descr, this.contactFormValuesContainer.rootForm.formTemplateId).flatMap(({ metadata, validators }) => validators.map((_a) => __awaiter(this, [_a], void 0, function* ({ validation, message }) {
|
|
442
|
+
try {
|
|
443
|
+
if (!(yield this.compute(validation))) {
|
|
444
|
+
return [metadata, message];
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
catch (e) {
|
|
448
|
+
console.log(`Error while computing validation : ${validation}`, e);
|
|
449
|
+
}
|
|
450
|
+
return null;
|
|
451
|
+
})));
|
|
452
|
+
}
|
|
453
|
+
else {
|
|
454
|
+
return [];
|
|
455
|
+
}
|
|
387
456
|
}
|
|
388
457
|
addChild(anchorId, templateId, label) {
|
|
389
458
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -433,17 +502,20 @@ class ContactFormValuesContainer {
|
|
|
433
502
|
allForms() {
|
|
434
503
|
return [this.rootForm].concat(this.children.flatMap((c) => c.allForms()));
|
|
435
504
|
}
|
|
436
|
-
constructor(rootForm, currentContact, contactsHistory, serviceFactory, children, formFactory, formRecycler, changeListeners = [], initialised = true) {
|
|
437
|
-
|
|
505
|
+
constructor(rootForm, currentContact, contactsHistory, serviceFactory, children, formFactory, formRecycler, changeListeners = [], anchorId, initialised = true) {
|
|
506
|
+
var _a;
|
|
507
|
+
this._id = '';
|
|
438
508
|
this._initialised = false;
|
|
439
|
-
|
|
509
|
+
this.rootForm = rootForm;
|
|
510
|
+
this._id = `${((_a = rootForm.formTemplateId) !== null && _a !== void 0 ? _a : '').substring(0, 4)}.${++_ordinal}`;
|
|
511
|
+
console.log(`+ CFVC: ${this._id} with children { ${children.map((c) => c._id).join(', ')} }`);
|
|
440
512
|
if (contactsHistory.includes(currentContact)) {
|
|
441
513
|
throw new Error('Illegal argument, the history must not contain the currentContact');
|
|
442
514
|
}
|
|
443
|
-
this.rootForm = rootForm;
|
|
444
515
|
this.currentContact = currentContact;
|
|
445
516
|
this.contactsHistory = (0, no_lodash_1.sortedBy)(contactsHistory, 'created', 'desc');
|
|
446
517
|
this.children = children;
|
|
518
|
+
this.anchorId = anchorId;
|
|
447
519
|
this.serviceFactory = serviceFactory;
|
|
448
520
|
this.formFactory = formFactory;
|
|
449
521
|
this.formRecycler = formRecycler;
|
|
@@ -451,7 +523,7 @@ class ContactFormValuesContainer {
|
|
|
451
523
|
this._initialised = initialised;
|
|
452
524
|
this.indexedServices = [this.currentContact].concat(this.contactsHistory).reduce((acc, ctc) => {
|
|
453
525
|
var _a, _b, _c;
|
|
454
|
-
|
|
526
|
+
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) => {
|
|
455
527
|
var _a, _b;
|
|
456
528
|
return s.id
|
|
457
529
|
? Object.assign(Object.assign({}, acc), { [s.id]: ((_a = acc[s.id]) !== null && _a !== void 0 ? _a : (acc[s.id] = [])).concat({
|
|
@@ -459,26 +531,29 @@ class ContactFormValuesContainer {
|
|
|
459
531
|
modified: ctc.created,
|
|
460
532
|
value: s,
|
|
461
533
|
}) }) : acc;
|
|
462
|
-
}, acc)) !== null && _c !== void 0 ? _c : acc;
|
|
463
|
-
return services;
|
|
534
|
+
}, acc)) !== null && _c !== void 0 ? _c : acc);
|
|
464
535
|
}, {});
|
|
465
536
|
this.synchronise();
|
|
466
537
|
}
|
|
467
538
|
synchronise() {
|
|
468
539
|
this.children.forEach((childFVC) => {
|
|
469
|
-
|
|
540
|
+
var _a;
|
|
541
|
+
this.registerChildFormValuesContainer(childFVC.synchronise(), (_a = childFVC.anchorId) !== null && _a !== void 0 ? _a : '');
|
|
470
542
|
});
|
|
471
543
|
return this;
|
|
472
544
|
}
|
|
473
545
|
//Make sure that when a child is changed, a new version of this is created with the updated child
|
|
474
|
-
registerChildFormValuesContainer(childFormValueContainer) {
|
|
546
|
+
registerChildFormValuesContainer(childFormValueContainer, anchorId) {
|
|
475
547
|
childFormValueContainer.changeListeners = [
|
|
476
|
-
(newValue) => {
|
|
548
|
+
(newValue, changedKeys, force) => {
|
|
549
|
+
if ((changedKeys === null || changedKeys === void 0 ? void 0 : changedKeys.length) === 0 && !force) {
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
477
552
|
console.log(`Child ${newValue._id} ${childFormValueContainer.rootForm.formTemplateId} changed, updating parent ${this._id} ${this.rootForm.formTemplateId}`);
|
|
478
553
|
const newContactFormValuesContainer = new ContactFormValuesContainer(this.rootForm, this.currentContact, this.contactsHistory, this.serviceFactory, this.children.map((c) => {
|
|
479
554
|
return c.rootForm.id === childFormValueContainer.rootForm.id ? newValue : c;
|
|
480
|
-
}), this.formFactory, this.formRecycler);
|
|
481
|
-
this.changeListeners.forEach((l) => notify(l, newContactFormValuesContainer));
|
|
555
|
+
}), this.formFactory, this.formRecycler, [], this.anchorId, true);
|
|
556
|
+
this.changeListeners.forEach((l) => notify(l, newContactFormValuesContainer, null));
|
|
482
557
|
},
|
|
483
558
|
];
|
|
484
559
|
}
|
|
@@ -488,8 +563,8 @@ class ContactFormValuesContainer {
|
|
|
488
563
|
? yield Promise.all((yield formChildrenProvider(rootForm.id)).map((f) => __awaiter(this, void 0, void 0, function* () {
|
|
489
564
|
// eslint-disable-next-line max-len
|
|
490
565
|
return yield ContactFormValuesContainer.fromFormsHierarchy(f, currentContact, contactsHistory, serviceFactory, formChildrenProvider, formFactory, formRecycler); })))
|
|
491
|
-
: [], formFactory, formRecycler, changeListeners, false);
|
|
492
|
-
contactFormValuesContainer.children.forEach((childFVC) => contactFormValuesContainer.registerChildFormValuesContainer(childFVC));
|
|
566
|
+
: [], formFactory, formRecycler, changeListeners, rootForm.descr, false);
|
|
567
|
+
contactFormValuesContainer.children.forEach((childFVC) => { var _a; return contactFormValuesContainer.registerChildFormValuesContainer(childFVC, (_a = childFVC.anchorId) !== null && _a !== void 0 ? _a : 'all'); });
|
|
493
568
|
return contactFormValuesContainer;
|
|
494
569
|
});
|
|
495
570
|
}
|
|
@@ -513,12 +588,10 @@ class ContactFormValuesContainer {
|
|
|
513
588
|
});
|
|
514
589
|
}
|
|
515
590
|
getValidationErrors() {
|
|
516
|
-
|
|
517
|
-
throw new Error('Validation not supported at contact level');
|
|
518
|
-
});
|
|
591
|
+
throw new Error('Validation not supported at contact level');
|
|
519
592
|
}
|
|
520
|
-
|
|
521
|
-
return
|
|
593
|
+
getDefaultValueProvider() {
|
|
594
|
+
return undefined;
|
|
522
595
|
}
|
|
523
596
|
getValues(revisionsFilter) {
|
|
524
597
|
return Object.entries(this.getServicesInHistory(revisionsFilter)).reduce((acc, [id, history]) => history.length
|
|
@@ -563,20 +636,20 @@ class ContactFormValuesContainer {
|
|
|
563
636
|
meta.valueDate && (newService.valueDate = meta.valueDate);
|
|
564
637
|
meta.codes && (newService.codes = (0, code_utils_1.normalizeCodes)(meta.codes));
|
|
565
638
|
meta.tags && (newService.tags = (0, code_utils_1.normalizeCodes)(meta.tags));
|
|
566
|
-
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);
|
|
567
|
-
this.changeListeners.forEach((l) => notify(l, newFormValuesContainer));
|
|
639
|
+
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, this.anchorId, true);
|
|
640
|
+
this.changeListeners.forEach((l) => notify(l, newFormValuesContainer, [meta.label]));
|
|
568
641
|
}
|
|
569
642
|
}
|
|
570
643
|
setValue(label, language, value, id, metadata, changeListenersOverrider) {
|
|
571
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
|
|
644
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
|
|
572
645
|
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);
|
|
573
646
|
if (!service.id) {
|
|
574
647
|
throw new Error('Service id must be defined');
|
|
575
648
|
}
|
|
576
|
-
console.log(
|
|
577
|
-
const newContent = (
|
|
649
|
+
console.log(`Setting value of service ${service.label} [${service.id}] to ${Object.entries((_c = value === null || value === void 0 ? void 0 : value.content) !== null && _c !== void 0 ? _c : {}).map(([k, c]) => `${k}: ${JSON.stringify((0, icure_utils_1.contentToPrimitiveType)(k, c))}`)} and md`, metadata);
|
|
650
|
+
const newContent = (_d = value === null || value === void 0 ? void 0 : value.content) === null || _d === void 0 ? void 0 : _d[language];
|
|
578
651
|
const newCodes = (value === null || value === void 0 ? void 0 : value.codes) ? (0, code_utils_1.normalizeCodes)(value.codes) : [];
|
|
579
|
-
if (!(0, icure_utils_1.isContentEqual)((
|
|
652
|
+
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 : []))) {
|
|
580
653
|
const newService = new api_1.Service(Object.assign(Object.assign({}, service), { modified: Date.now() }));
|
|
581
654
|
const newContents = newContent
|
|
582
655
|
? Object.assign(Object.assign({}, (service.content || {})), { [language]: newContent }) : Object.assign({}, (service.content || {}));
|
|
@@ -585,8 +658,8 @@ class ContactFormValuesContainer {
|
|
|
585
658
|
}
|
|
586
659
|
let newCurrentContact;
|
|
587
660
|
if (!Object.entries(newContents).filter(([, cnt]) => cnt !== undefined).length) {
|
|
588
|
-
newCurrentContact = Object.assign(Object.assign({}, this.currentContact), { subContacts: ((
|
|
589
|
-
? ((
|
|
661
|
+
newCurrentContact = Object.assign(Object.assign({}, this.currentContact), { subContacts: ((_g = this.currentContact.subContacts) !== null && _g !== void 0 ? _g : []).some((sc) => sc.formId === this.rootForm.id)
|
|
662
|
+
? ((_h = this.currentContact.subContacts) !== null && _h !== void 0 ? _h : []).map((sc) => {
|
|
590
663
|
var _a;
|
|
591
664
|
if (sc.formId === this.rootForm.id) {
|
|
592
665
|
return Object.assign(Object.assign({}, sc), { services: ((_a = sc.services) !== null && _a !== void 0 ? _a : []).filter((s) => s.serviceId !== service.id).concat([{ serviceId: service.id }]) });
|
|
@@ -595,21 +668,21 @@ class ContactFormValuesContainer {
|
|
|
595
668
|
return sc;
|
|
596
669
|
}
|
|
597
670
|
})
|
|
598
|
-
: ((
|
|
599
|
-
? ((
|
|
600
|
-
: [...((
|
|
671
|
+
: ((_j = this.currentContact.subContacts) !== null && _j !== void 0 ? _j : []).concat({ formId: this.rootForm.id, services: [{ serviceId: service.id }] }), services: ((_k = this.currentContact.services) !== null && _k !== void 0 ? _k : []).some((s) => s.id === service.id)
|
|
672
|
+
? ((_l = this.currentContact.services) !== null && _l !== void 0 ? _l : []).filter((s) => s.id !== service.id)
|
|
673
|
+
: [...((_m = this.currentContact.services) !== null && _m !== void 0 ? _m : [])] });
|
|
601
674
|
}
|
|
602
675
|
else {
|
|
603
676
|
newService.content = newContents;
|
|
604
677
|
newService.codes = newCodes;
|
|
605
678
|
if (metadata) {
|
|
606
|
-
newService.responsible = (
|
|
607
|
-
newService.valueDate = (
|
|
679
|
+
newService.responsible = (_o = metadata.responsible) !== null && _o !== void 0 ? _o : newService.responsible;
|
|
680
|
+
newService.valueDate = (_p = metadata.valueDate) !== null && _p !== void 0 ? _p : newService.valueDate;
|
|
608
681
|
newService.tags = metadata.tags ? (0, code_utils_1.normalizeCodes)(metadata.tags) : newService.tags;
|
|
609
|
-
newService.label = (
|
|
682
|
+
newService.label = (_q = metadata.label) !== null && _q !== void 0 ? _q : newService.label;
|
|
610
683
|
}
|
|
611
|
-
newCurrentContact = Object.assign(Object.assign({}, this.currentContact), { subContacts: ((
|
|
612
|
-
? ((
|
|
684
|
+
newCurrentContact = Object.assign(Object.assign({}, this.currentContact), { subContacts: ((_r = this.currentContact.subContacts) !== null && _r !== void 0 ? _r : []).some((sc) => sc.formId === this.rootForm.id)
|
|
685
|
+
? ((_s = this.currentContact.subContacts) !== null && _s !== void 0 ? _s : []).map((sc) => {
|
|
613
686
|
var _a;
|
|
614
687
|
if (sc.formId === this.rootForm.id) {
|
|
615
688
|
return Object.assign(Object.assign({}, sc), { services: ((_a = sc.services) !== null && _a !== void 0 ? _a : []).filter((s) => s.serviceId !== service.id).concat([{ serviceId: service.id }]) });
|
|
@@ -618,12 +691,12 @@ class ContactFormValuesContainer {
|
|
|
618
691
|
return sc;
|
|
619
692
|
}
|
|
620
693
|
})
|
|
621
|
-
: ((
|
|
622
|
-
? ((
|
|
623
|
-
: [...((
|
|
694
|
+
: ((_t = this.currentContact.subContacts) !== null && _t !== void 0 ? _t : []).concat({ formId: this.rootForm.id, services: [{ serviceId: service.id }] }), services: ((_u = this.currentContact.services) !== null && _u !== void 0 ? _u : []).some((s) => s.id === service.id)
|
|
695
|
+
? ((_v = this.currentContact.services) !== null && _v !== void 0 ? _v : []).map((s) => (s.id === service.id ? newService : s))
|
|
696
|
+
: [...((_w = this.currentContact.services) !== null && _w !== void 0 ? _w : []), newService] });
|
|
624
697
|
}
|
|
625
|
-
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);
|
|
626
|
-
changeListenersOverrider ? changeListenersOverrider(newFormValuesContainer) : this.changeListeners.forEach((l) => notify(l, newFormValuesContainer));
|
|
698
|
+
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, this.anchorId, true);
|
|
699
|
+
changeListenersOverrider ? changeListenersOverrider(newFormValuesContainer, [label]) : this.changeListeners.forEach((l) => notify(l, newFormValuesContainer, [label]));
|
|
627
700
|
}
|
|
628
701
|
}
|
|
629
702
|
delete(serviceId) {
|
|
@@ -632,10 +705,35 @@ class ContactFormValuesContainer {
|
|
|
632
705
|
if (service) {
|
|
633
706
|
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
|
|
634
707
|
? new api_1.Service(Object.assign(Object.assign({}, service), { endOfLife: Date.now() }))
|
|
635
|
-
: s) }), this.contactsHistory, this.serviceFactory, this.children, this.formFactory, this.formRecycler, this.changeListeners);
|
|
636
|
-
this.changeListeners.forEach((l) => notify(l, newFormValuesContainer));
|
|
708
|
+
: s) }), this.contactsHistory, this.serviceFactory, this.children, this.formFactory, this.formRecycler, this.changeListeners, this.anchorId, true);
|
|
709
|
+
this.changeListeners.forEach((l) => { var _a, _b; return notify(l, newFormValuesContainer, [(_b = (_a = service.label) !== null && _a !== void 0 ? _a : service.id) !== null && _b !== void 0 ? _b : ''] /* only the label is going to propagate the changes for the formulas */); });
|
|
637
710
|
}
|
|
638
711
|
}
|
|
712
|
+
toMarkdownTable() {
|
|
713
|
+
var _a, _b, _c;
|
|
714
|
+
const tableRows = [];
|
|
715
|
+
for (const [, versions] of Object.entries(this.indexedServices)) {
|
|
716
|
+
if (!versions.length)
|
|
717
|
+
continue;
|
|
718
|
+
const service = versions[0].value;
|
|
719
|
+
const label = (_b = (_a = service.label) !== null && _a !== void 0 ? _a : service.id) !== null && _b !== void 0 ? _b : '';
|
|
720
|
+
const modifiedStr = service.modified ? new Date(service.modified).toISOString() : '';
|
|
721
|
+
const contentParts = [];
|
|
722
|
+
for (const [lng, cnt] of Object.entries((_c = service.content) !== null && _c !== void 0 ? _c : {})) {
|
|
723
|
+
const primitive = (0, icure_utils_1.contentToPrimitiveType)(lng, cnt);
|
|
724
|
+
if (primitive) {
|
|
725
|
+
contentParts.push(primitiveTypeToString(primitive));
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
tableRows.push([label, modifiedStr, contentParts.join(', ')]);
|
|
729
|
+
}
|
|
730
|
+
const headers = ['Label', 'Modified', 'Content'];
|
|
731
|
+
const colWidths = headers.map((h, i) => Math.max(h.length, ...tableRows.map((r) => r[i].length)));
|
|
732
|
+
const pad = (s, w) => s + ' '.repeat(w - s.length);
|
|
733
|
+
const formatRow = (cells) => '| ' + cells.map((c, i) => pad(c, colWidths[i])).join(' | ') + ' |';
|
|
734
|
+
const separator = '|' + colWidths.map((w) => '-'.repeat(w + 2)).join('|') + '|';
|
|
735
|
+
return [formatRow(headers), separator, ...tableRows.map(formatRow)].join('\n');
|
|
736
|
+
}
|
|
639
737
|
compute() {
|
|
640
738
|
return __awaiter(this, void 0, void 0, function* () {
|
|
641
739
|
throw new Error('Compute not supported at contact level');
|
|
@@ -674,10 +772,12 @@ class ContactFormValuesContainer {
|
|
|
674
772
|
if (!parentId)
|
|
675
773
|
return;
|
|
676
774
|
const newForm = yield this.formFactory(parentId, anchorId, templateId, label);
|
|
677
|
-
const childFVC = new ContactFormValuesContainer(newForm, this.currentContact, this.contactsHistory, this.serviceFactory, [], this.formFactory, this.formRecycler, [], false);
|
|
678
|
-
const newContactFormValuesContainer = new ContactFormValuesContainer(this.rootForm, this.currentContact, this.contactsHistory, this.serviceFactory, [...this.children, childFVC], this.formFactory, this.formRecycler, this.changeListeners);
|
|
679
|
-
newContactFormValuesContainer.registerChildFormValuesContainer(childFVC);
|
|
680
|
-
this.changeListeners.forEach((l) =>
|
|
775
|
+
const childFVC = new ContactFormValuesContainer(newForm, this.currentContact, this.contactsHistory, this.serviceFactory, [], this.formFactory, this.formRecycler, [], anchorId, false);
|
|
776
|
+
const newContactFormValuesContainer = new ContactFormValuesContainer(this.rootForm, this.currentContact, this.contactsHistory, this.serviceFactory, [...this.children, childFVC], this.formFactory, this.formRecycler, this.changeListeners, this.anchorId, true);
|
|
777
|
+
newContactFormValuesContainer.registerChildFormValuesContainer(childFVC, anchorId);
|
|
778
|
+
this.changeListeners.forEach((l) => {
|
|
779
|
+
notify(l, newContactFormValuesContainer, null);
|
|
780
|
+
});
|
|
681
781
|
});
|
|
682
782
|
}
|
|
683
783
|
getServiceInCurrentContact(id) {
|
|
@@ -687,14 +787,85 @@ class ContactFormValuesContainer {
|
|
|
687
787
|
}
|
|
688
788
|
removeChild(container) {
|
|
689
789
|
return __awaiter(this, void 0, void 0, function* () {
|
|
690
|
-
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);
|
|
691
|
-
this.changeListeners.forEach((l) => notify(l, newContactFormValuesContainer));
|
|
790
|
+
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, this.anchorId, true);
|
|
791
|
+
this.changeListeners.forEach((l) => { var _a; return notify(l, newContactFormValuesContainer, [`subForms_${(_a = container.anchorId) !== null && _a !== void 0 ? _a : 'all'}`]); });
|
|
692
792
|
});
|
|
693
793
|
}
|
|
694
794
|
}
|
|
695
795
|
exports.ContactFormValuesContainer = ContactFormValuesContainer;
|
|
796
|
+
// Runtime validation for FieldValue — guards against mistyped data coming from
|
|
797
|
+
// external callers (formulas, SDK bridges, etc.) where the TypeScript types may
|
|
798
|
+
// not match the actual runtime values.
|
|
799
|
+
const validatePrimitiveType = (pt, path) => {
|
|
800
|
+
const v = pt.value;
|
|
801
|
+
switch (pt.type) {
|
|
802
|
+
case 'string':
|
|
803
|
+
if (typeof v !== 'string') {
|
|
804
|
+
throw new Error(`${path}: expected string value, got ${typeof v}`);
|
|
805
|
+
}
|
|
806
|
+
break;
|
|
807
|
+
case 'number':
|
|
808
|
+
if (typeof v !== 'number') {
|
|
809
|
+
throw new Error(`${path}: expected number value, got ${typeof v}`);
|
|
810
|
+
}
|
|
811
|
+
break;
|
|
812
|
+
case 'boolean':
|
|
813
|
+
if (typeof v !== 'boolean') {
|
|
814
|
+
throw new Error(`${path}: expected boolean value, got ${typeof v}`);
|
|
815
|
+
}
|
|
816
|
+
break;
|
|
817
|
+
case 'timestamp':
|
|
818
|
+
if (typeof v !== 'number') {
|
|
819
|
+
throw new Error(`${path}: expected number value for timestamp, got ${typeof v}`);
|
|
820
|
+
}
|
|
821
|
+
break;
|
|
822
|
+
case 'datetime':
|
|
823
|
+
if (typeof v !== 'number') {
|
|
824
|
+
throw new Error(`${path}: expected number value for datetime, got ${typeof v}`);
|
|
825
|
+
}
|
|
826
|
+
break;
|
|
827
|
+
case 'measure': {
|
|
828
|
+
const m = pt;
|
|
829
|
+
if (m.value !== undefined && typeof m.value !== 'number') {
|
|
830
|
+
throw new Error(`${path}: expected number or undefined value for measure, got ${typeof m.value}`);
|
|
831
|
+
}
|
|
832
|
+
if (m.unit !== undefined && typeof m.unit !== 'string') {
|
|
833
|
+
throw new Error(`${path}: expected string or undefined unit for measure, got ${typeof m.unit}`);
|
|
834
|
+
}
|
|
835
|
+
break;
|
|
836
|
+
}
|
|
837
|
+
case 'compound':
|
|
838
|
+
if (typeof v !== 'object' || v === null || Array.isArray(v)) {
|
|
839
|
+
throw new Error(`${path}: expected object value for compound, got ${Array.isArray(v) ? 'array' : typeof v}`);
|
|
840
|
+
}
|
|
841
|
+
for (const [key, subValue] of Object.entries(v)) {
|
|
842
|
+
validatePrimitiveType(subValue, `${path}.compound[${key}]`);
|
|
843
|
+
}
|
|
844
|
+
break;
|
|
845
|
+
default:
|
|
846
|
+
throw new Error(`${path}: unknown PrimitiveType type: ${pt.type}`);
|
|
847
|
+
}
|
|
848
|
+
};
|
|
849
|
+
const validateCode = (code, path) => {
|
|
850
|
+
const id = code.id;
|
|
851
|
+
if (!id || typeof id !== 'string') {
|
|
852
|
+
throw new Error(`${path}: code must have a non-empty string id, got ${JSON.stringify(id)}`);
|
|
853
|
+
}
|
|
854
|
+
};
|
|
855
|
+
const validateFieldValue = (fv, language, label) => {
|
|
856
|
+
const pt = fv.content[language];
|
|
857
|
+
if (pt) {
|
|
858
|
+
validatePrimitiveType(pt, `FieldValue[${label}].content[${language}]`);
|
|
859
|
+
}
|
|
860
|
+
if (fv.codes) {
|
|
861
|
+
fv.codes.forEach((code, i) => validateCode(code, `FieldValue[${label}].codes[${i}]`));
|
|
862
|
+
}
|
|
863
|
+
};
|
|
696
864
|
const setValueOnContactFormValuesContainer = (cfvc, label, language, fv, id, metadata, changeListenersOverrider) => {
|
|
697
865
|
var _a, _b;
|
|
866
|
+
if (fv) {
|
|
867
|
+
validateFieldValue(fv, language, label);
|
|
868
|
+
}
|
|
698
869
|
const value = fv === null || fv === void 0 ? void 0 : fv.content[language];
|
|
699
870
|
cfvc.setValue(label, language, {
|
|
700
871
|
id: id,
|