@icure/form 3.0.46 → 3.1.1
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/{@babel-runtime-npm-7.28.4-31bc1b0001-934b0a0460.zip → @babel-runtime-npm-7.28.6-f40c99aeef-42d8a868c2.zip} +0 -0
- package/.yarn/cache/@lit-labs-ssr-dom-shim-npm-1.5.1-3b3c832bd1-22c404c481.zip +0 -0
- package/.yarn/cache/@lit-reactive-element-npm-2.1.2-2c713bebce-e0ed931b9c.zip +0 -0
- package/.yarn/cache/{lit-element-npm-4.2.1-b5bc114ced-5925326176.zip → lit-element-npm-4.2.2-70d4af2233-554254b87c.zip} +0 -0
- package/.yarn/cache/lit-html-npm-3.3.2-4a3e00215f-7fe23502ca.zip +0 -0
- package/.yarn/cache/{lit-npm-3.3.1-8f683c51f1-fb88f1ff80.zip → lit-npm-3.3.2-7dea58471e-2136d4beac.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.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-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 +0 -8
- 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 +7 -5
- 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 +16 -16
- package/components/model/index.js +34 -30
- package/components/model/index.js.map +1 -1
- package/conversion/icure-convert.d.ts +3 -0
- package/conversion/icure-convert.js +161 -0
- package/conversion/icure-convert.js.map +1 -0
- package/generic/model.d.ts +11 -6
- package/generic/model.js.map +1 -1
- package/icure/form-values-container.d.ts +27 -21
- package/icure/form-values-container.js +318 -125
- package/icure/form-values-container.js.map +1 -1
- package/icure/icure-utils.js +47 -17
- package/icure/icure-utils.js.map +1 -1
- package/package.json +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/@lit-labs-ssr-dom-shim-npm-1.4.0-e5ef5fbeba-e267c25576.zip +0 -0
- package/.yarn/cache/@lit-reactive-element-npm-2.1.1-3875228c32-b9bbc9c089.zip +0 -0
- package/.yarn/cache/lit-html-npm-3.3.1-e3722d4f4a-de07c66945.zip +0 -0
- 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
- package/.yarn/cache/prosemirror-view-npm-1.41.4-cf361fd330-b663b8c6ce.zip +0 -0
|
@@ -12,10 +12,30 @@ import { sortedBy } from '../utils/no-lodash';
|
|
|
12
12
|
import { areCodesEqual, codeStubToCode, contentToPrimitiveType, isContentEqual, primitiveTypeToContent } from './icure-utils';
|
|
13
13
|
import { parsePrimitive } from '../utils/primitive';
|
|
14
14
|
import { anyDateToDate, dateToFuzzyDate } from '../utils/dates';
|
|
15
|
-
import { v4 as uuidv4 } from 'uuid';
|
|
16
15
|
import { normalizeCodes } from '../utils/code-utils';
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
let _ordinal = 0;
|
|
17
|
+
function notify(l, fvc, changedKeys, force = false) {
|
|
18
|
+
l(fvc, changedKeys, force);
|
|
19
|
+
}
|
|
20
|
+
function primitiveTypeToString(pt) {
|
|
21
|
+
switch (pt.type) {
|
|
22
|
+
case 'string':
|
|
23
|
+
return pt.value;
|
|
24
|
+
case 'number':
|
|
25
|
+
return pt.value.toString();
|
|
26
|
+
case 'boolean':
|
|
27
|
+
return pt.value.toString();
|
|
28
|
+
case 'measure':
|
|
29
|
+
return pt.value !== undefined ? `${pt.value}${pt.unit ? ' ' + pt.unit : ''}` : '';
|
|
30
|
+
case 'timestamp':
|
|
31
|
+
return new Date(pt.value).toISOString();
|
|
32
|
+
case 'datetime':
|
|
33
|
+
return pt.value.toString();
|
|
34
|
+
case 'compound':
|
|
35
|
+
return Object.entries(pt.value)
|
|
36
|
+
.map(([k, v]) => `${k}: ${primitiveTypeToString(v)}`)
|
|
37
|
+
.join(', ');
|
|
38
|
+
}
|
|
19
39
|
}
|
|
20
40
|
/** This class is a bridge between the ICure API and the generic FormValuesContainer interface.
|
|
21
41
|
* It wraps around a ContactFormValuesContainer and provides a series of services:
|
|
@@ -52,8 +72,9 @@ export class BridgedFormValuesContainer {
|
|
|
52
72
|
* @param language The language in which the values are displayed
|
|
53
73
|
* @param changeListeners The listeners that will be notified when the values change
|
|
54
74
|
* @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
|
|
75
|
+
* @param dependenciesCache
|
|
55
76
|
*/
|
|
56
|
-
constructor(responsible, contactFormValuesContainer, interpreter, contact, initialValuesProvider = () => [], dependentValuesProvider = () => [], validatorsProvider = () => [], language = 'en', changeListeners = [], interpreterContext = {}) {
|
|
77
|
+
constructor(responsible, contactFormValuesContainer, interpreter, contact, initialValuesProvider = () => [], dependentValuesProvider = () => [], validatorsProvider = () => [], language = 'en', changeListeners = [], interpreterContext = {}, dependenciesCache = {}) {
|
|
57
78
|
this.responsible = responsible;
|
|
58
79
|
this.interpreter = interpreter;
|
|
59
80
|
this.initialValuesProvider = initialValuesProvider;
|
|
@@ -62,25 +83,54 @@ export class BridgedFormValuesContainer {
|
|
|
62
83
|
this.language = language;
|
|
63
84
|
this.changeListeners = changeListeners;
|
|
64
85
|
this.interpreterContext = interpreterContext;
|
|
65
|
-
this.
|
|
66
|
-
|
|
86
|
+
this.dependenciesCache = dependenciesCache;
|
|
87
|
+
this._id = '';
|
|
88
|
+
this.dependentValuesComputationIteration = undefined;
|
|
67
89
|
//Before start to broadcast changes, we need to fill in the contactFormValuesContainer with the dependent values
|
|
68
90
|
this.contactFormValuesContainer = contactFormValuesContainer;
|
|
69
|
-
this.
|
|
91
|
+
this._id = `[${contactFormValuesContainer._id}]`;
|
|
92
|
+
console.log(`+ BFVC ${this._id} created`);
|
|
93
|
+
this.mutateAndNotify = (newContactFormValuesContainer, changedKeys, force = false) => {
|
|
94
|
+
if (this.changeListeners.length === 0) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (!force && this.contactFormValuesContainer === newContactFormValuesContainer) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
this.contactFormValuesContainer.unregisterChangeListener(this.mutateAndNotify);
|
|
70
101
|
newContactFormValuesContainer.unregisterChangeListener(this.mutateAndNotify);
|
|
71
|
-
const newBridgedFormValueContainer =
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
102
|
+
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);
|
|
103
|
+
const initPromise = newBridgedFormValueContainer.init(changedKeys, this.dependentValuesComputationIteration);
|
|
104
|
+
this.changeListeners.forEach((l) => notify(l, newBridgedFormValueContainer, changedKeys));
|
|
105
|
+
initPromise.catch((e) => {
|
|
106
|
+
console.log('Error while initializing new BridgedFormValuesContainer', e);
|
|
107
|
+
});
|
|
108
|
+
};
|
|
75
109
|
this.contactFormValuesContainer.registerChangeListener(this.mutateAndNotify);
|
|
76
110
|
this.contact = contact !== null && contact !== void 0 ? contact : contactFormValuesContainer.currentContact;
|
|
77
111
|
}
|
|
112
|
+
/* init can be called several times on the same instance but the initialisation will only be done once */
|
|
78
113
|
init() {
|
|
79
|
-
return __awaiter(this,
|
|
114
|
+
return __awaiter(this, arguments, void 0, function* (changedKeys = null, pendingComputationIteration) {
|
|
80
115
|
if (this.contactFormValuesContainer.mustBeInitialised()) {
|
|
81
116
|
yield this.computeInitialValues();
|
|
82
117
|
}
|
|
83
|
-
|
|
118
|
+
let changedKeysByInit = [];
|
|
119
|
+
if (pendingComputationIteration) {
|
|
120
|
+
const changes = yield pendingComputationIteration;
|
|
121
|
+
if (changes.length > 0) {
|
|
122
|
+
this.quietlyApplyChangesOnContactFormValueContainer(changes);
|
|
123
|
+
changedKeysByInit = yield this.computeDependentValues([...(changedKeys !== null && changedKeys !== void 0 ? changedKeys : []), ...changes.map(([, metadata]) => metadata.label)]);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
changedKeysByInit = yield this.computeDependentValues(changedKeys);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
changedKeysByInit = yield this.computeDependentValues(changedKeys);
|
|
131
|
+
}
|
|
132
|
+
//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
|
|
133
|
+
this.contactFormValuesContainer.changeListeners.forEach((l) => notify(l, this.contactFormValuesContainer, changedKeysByInit, changedKeysByInit.length > 0));
|
|
84
134
|
return this;
|
|
85
135
|
});
|
|
86
136
|
}
|
|
@@ -99,12 +149,10 @@ export class BridgedFormValuesContainer {
|
|
|
99
149
|
unregisterChangeListener(listener) {
|
|
100
150
|
this.changeListeners = this.changeListeners.filter((l) => l !== listener);
|
|
101
151
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
return formula ? this.convertRawValue(yield this.compute(formula)) : undefined;
|
|
107
|
-
});
|
|
152
|
+
getDefaultValueProvider(label) {
|
|
153
|
+
var _a;
|
|
154
|
+
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;
|
|
155
|
+
return formula ? () => __awaiter(this, void 0, void 0, function* () { return this.convertRawValue(yield this.compute(formula)); }) : undefined;
|
|
108
156
|
}
|
|
109
157
|
getValues(revisionsFilter) {
|
|
110
158
|
return Object.entries(this.contactFormValuesContainer.getValues((id, history) => revisionsFilter(id, history
|
|
@@ -198,7 +246,8 @@ export class BridgedFormValuesContainer {
|
|
|
198
246
|
try {
|
|
199
247
|
const currentValue = this.getValues(revisionsFilter);
|
|
200
248
|
if (!currentValue || !Object.keys(currentValue).length) {
|
|
201
|
-
const
|
|
249
|
+
const computedValue = (yield this.compute(formula)).value;
|
|
250
|
+
const newValue = computedValue ? this.convertRawValue(computedValue) : undefined;
|
|
202
251
|
if (newValue !== undefined) {
|
|
203
252
|
const lng = (_b = this.language) !== null && _b !== void 0 ? _b : 'en';
|
|
204
253
|
if (newValue && !newValue.content[lng] && newValue.content['*']) {
|
|
@@ -225,38 +274,80 @@ export class BridgedFormValuesContainer {
|
|
|
225
274
|
});
|
|
226
275
|
}
|
|
227
276
|
//This method mutates the BridgedFormValuesContainer but can only be called from the constructor
|
|
228
|
-
computeDependentValues() {
|
|
277
|
+
computeDependentValues(changedKeys) {
|
|
229
278
|
return __awaiter(this, void 0, void 0, function* () {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
279
|
+
const iterate = (changedKeys, iterationCount) => __awaiter(this, void 0, void 0, function* () {
|
|
280
|
+
if (this.contactFormValuesContainer.rootForm.formTemplateId) {
|
|
281
|
+
console.log(`% ${iterationCount}, keys: ${changedKeys ? changedKeys.join(', ') : 'all'}`);
|
|
282
|
+
return yield Promise.all(this.dependentValuesProvider(this.contactFormValuesContainer.rootForm.descr, this.contactFormValuesContainer.rootForm.formTemplateId).map((_a) => __awaiter(this, [_a], void 0, function* ({ metadata, revisionsFilter, formula }) {
|
|
283
|
+
var _b, _c;
|
|
284
|
+
try {
|
|
285
|
+
if (!changedKeys || !this.dependenciesCache[formula] || this.dependenciesCache[formula].some((d) => changedKeys.includes(d))) {
|
|
286
|
+
const currentValue = this.getValues(revisionsFilter);
|
|
287
|
+
try {
|
|
288
|
+
const computationResult = yield this.compute(formula);
|
|
289
|
+
this.dependenciesCache[formula] = [...((_b = this.dependenciesCache[formula]) !== null && _b !== void 0 ? _b : []), ...computationResult.dependencies].filter((d, idx, array) => array.indexOf(d) === idx);
|
|
290
|
+
const newValue = computationResult.value ? this.convertRawValue(computationResult.value) : undefined;
|
|
291
|
+
if (newValue !== undefined || (currentValue != undefined && Object.keys(currentValue).length > 0 && currentValue[Object.keys(currentValue)[0]][0].value)) {
|
|
292
|
+
const lng = (_c = this.language) !== null && _c !== void 0 ? _c : 'en';
|
|
293
|
+
if (newValue && !newValue.content[lng] && newValue.content['*']) {
|
|
294
|
+
newValue.content[lng] = newValue.content['*'];
|
|
295
|
+
}
|
|
296
|
+
if (newValue) {
|
|
297
|
+
delete newValue.content['*'];
|
|
298
|
+
}
|
|
299
|
+
return [Object.keys(currentValue !== null && currentValue !== void 0 ? currentValue : {})[0], metadata, lng, newValue];
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
catch (e) {
|
|
303
|
+
console.log(`Error while computing formula : ${formula}`, e);
|
|
249
304
|
}
|
|
250
|
-
}
|
|
251
|
-
setValueOnContactFormValuesContainer(this.contactFormValuesContainer, metadata.label, lng, newValue, Object.keys(currentValue !== null && currentValue !== void 0 ? currentValue : {})[0], metadata, interceptor);
|
|
305
|
+
}
|
|
252
306
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
307
|
+
catch (e) {
|
|
308
|
+
console.log(`Error while computing formula : ${formula}`, e);
|
|
309
|
+
}
|
|
310
|
+
return null;
|
|
311
|
+
}))).then((results) => results.filter((r) => !!r));
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
return [];
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
let latestKeys = changedKeys;
|
|
318
|
+
let iterationCount = 0;
|
|
319
|
+
const allChangedKeys = [];
|
|
320
|
+
while (true) {
|
|
321
|
+
if (latestKeys != null && latestKeys.length === 0) {
|
|
322
|
+
this.dependentValuesComputationIteration = undefined;
|
|
323
|
+
break;
|
|
324
|
+
}
|
|
325
|
+
const changes = yield (this.dependentValuesComputationIteration = iterate(latestKeys, iterationCount++));
|
|
326
|
+
latestKeys = this.quietlyApplyChangesOnContactFormValueContainer(changes);
|
|
327
|
+
allChangedKeys.push(...latestKeys);
|
|
328
|
+
}
|
|
329
|
+
return allChangedKeys;
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
quietlyApplyChangesOnContactFormValueContainer(changes) {
|
|
333
|
+
const allChangedKeys = [];
|
|
334
|
+
const interceptor = (fvc, changedKeys) => {
|
|
335
|
+
const currentContact = this.contactFormValuesContainer.currentContact;
|
|
336
|
+
this.contactFormValuesContainer = fvc;
|
|
337
|
+
if (this.contact === currentContact) {
|
|
338
|
+
this.contact = fvc.currentContact;
|
|
339
|
+
}
|
|
340
|
+
allChangedKeys.push(...(changedKeys !== null && changedKeys !== void 0 ? changedKeys : []));
|
|
341
|
+
};
|
|
342
|
+
changes.forEach(([id, metadata, language, newValue]) => {
|
|
343
|
+
try {
|
|
344
|
+
setValueOnContactFormValuesContainer(this.contactFormValuesContainer, metadata.label, language, newValue !== null && newValue !== void 0 ? newValue : undefined, id, metadata, interceptor);
|
|
345
|
+
}
|
|
346
|
+
catch (e) {
|
|
347
|
+
console.log(`Error while applying dependent value change for ${metadata.label} (${id})`, e);
|
|
258
348
|
}
|
|
259
349
|
});
|
|
350
|
+
return allChangedKeys;
|
|
260
351
|
}
|
|
261
352
|
setValue(label, language, fv, id, metadata) {
|
|
262
353
|
setValueOnContactFormValuesContainer(this.contactFormValuesContainer, label, language, fv, id, metadata);
|
|
@@ -276,9 +367,10 @@ export class BridgedFormValuesContainer {
|
|
|
276
367
|
getVersionedValuesForKey(key) {
|
|
277
368
|
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
369
|
}
|
|
279
|
-
compute(formula
|
|
370
|
+
compute(formula) {
|
|
280
371
|
return __awaiter(this, void 0, void 0, function* () {
|
|
281
372
|
var _a;
|
|
373
|
+
const dependencies = new Set();
|
|
282
374
|
// noinspection JSUnusedGlobalSymbols
|
|
283
375
|
const parseContent = (content, toString = false) => {
|
|
284
376
|
var _a, _b;
|
|
@@ -299,6 +391,7 @@ export class BridgedFormValuesContainer {
|
|
|
299
391
|
.join(', ');
|
|
300
392
|
};
|
|
301
393
|
const log = console.log;
|
|
394
|
+
// noinspection JSUnusedGlobalSymbols
|
|
302
395
|
const native = {
|
|
303
396
|
parseInt: parseInt,
|
|
304
397
|
parseFloat: parseFloat,
|
|
@@ -346,42 +439,40 @@ export class BridgedFormValuesContainer {
|
|
|
346
439
|
if (!!nativeValue) {
|
|
347
440
|
return nativeValue;
|
|
348
441
|
}
|
|
349
|
-
|
|
442
|
+
if (key === 'self') {
|
|
443
|
+
return proxy;
|
|
444
|
+
}
|
|
445
|
+
else {
|
|
446
|
+
dependencies.add(key.toString());
|
|
447
|
+
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; });
|
|
448
|
+
}
|
|
350
449
|
},
|
|
351
450
|
});
|
|
352
|
-
return (_a = this.interpreter) === null || _a === void 0 ? void 0 : _a.call(this, formula,
|
|
451
|
+
return { value: yield ((_a = this.interpreter) === null || _a === void 0 ? void 0 : _a.call(this, formula, proxy)), dependencies: Array.from(dependencies) };
|
|
353
452
|
});
|
|
354
453
|
}
|
|
355
454
|
getChildren() {
|
|
356
455
|
return __awaiter(this, void 0, void 0, function* () {
|
|
357
|
-
|
|
358
|
-
console.log(`${children.length} children found in ${this.contactFormValuesContainer.rootForm.formTemplateId} initialised with `, this.initialValuesProvider);
|
|
359
|
-
return children;
|
|
456
|
+
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()));
|
|
360
457
|
});
|
|
361
458
|
}
|
|
362
459
|
getValidationErrors() {
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
}), Promise.resolve([]));
|
|
380
|
-
}
|
|
381
|
-
else {
|
|
382
|
-
return [];
|
|
383
|
-
}
|
|
384
|
-
});
|
|
460
|
+
if (this.contactFormValuesContainer.rootForm.formTemplateId) {
|
|
461
|
+
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 }) {
|
|
462
|
+
try {
|
|
463
|
+
if (!(yield this.compute(validation))) {
|
|
464
|
+
return [metadata, message];
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
catch (e) {
|
|
468
|
+
console.log(`Error while computing validation : ${validation}`, e);
|
|
469
|
+
}
|
|
470
|
+
return null;
|
|
471
|
+
})));
|
|
472
|
+
}
|
|
473
|
+
else {
|
|
474
|
+
return [];
|
|
475
|
+
}
|
|
385
476
|
}
|
|
386
477
|
addChild(anchorId, templateId, label) {
|
|
387
478
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -432,17 +523,20 @@ export class ContactFormValuesContainer {
|
|
|
432
523
|
allForms() {
|
|
433
524
|
return [this.rootForm].concat(this.children.flatMap((c) => c.allForms()));
|
|
434
525
|
}
|
|
435
|
-
constructor(rootForm, currentContact, contactsHistory, serviceFactory, children, formFactory, formRecycler, changeListeners = [], initialised = true) {
|
|
436
|
-
|
|
526
|
+
constructor(rootForm, currentContact, contactsHistory, serviceFactory, children, formFactory, formRecycler, changeListeners = [], anchorId, initialised = true) {
|
|
527
|
+
var _a;
|
|
528
|
+
this._id = '';
|
|
437
529
|
this._initialised = false;
|
|
438
|
-
|
|
530
|
+
this.rootForm = rootForm;
|
|
531
|
+
this._id = `${((_a = rootForm.formTemplateId) !== null && _a !== void 0 ? _a : '').substring(0, 4)}.${++_ordinal}`;
|
|
532
|
+
console.log(`+ CFVC: ${this._id} with children { ${children.map((c) => c._id).join(', ')} }`);
|
|
439
533
|
if (contactsHistory.includes(currentContact)) {
|
|
440
534
|
throw new Error('Illegal argument, the history must not contain the currentContact');
|
|
441
535
|
}
|
|
442
|
-
this.rootForm = rootForm;
|
|
443
536
|
this.currentContact = currentContact;
|
|
444
537
|
this.contactsHistory = sortedBy(contactsHistory, 'created', 'desc');
|
|
445
538
|
this.children = children;
|
|
539
|
+
this.anchorId = anchorId;
|
|
446
540
|
this.serviceFactory = serviceFactory;
|
|
447
541
|
this.formFactory = formFactory;
|
|
448
542
|
this.formRecycler = formRecycler;
|
|
@@ -450,7 +544,7 @@ export class ContactFormValuesContainer {
|
|
|
450
544
|
this._initialised = initialised;
|
|
451
545
|
this.indexedServices = [this.currentContact].concat(this.contactsHistory).reduce((acc, ctc) => {
|
|
452
546
|
var _a, _b, _c;
|
|
453
|
-
|
|
547
|
+
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
548
|
var _a, _b;
|
|
455
549
|
return s.id
|
|
456
550
|
? Object.assign(Object.assign({}, acc), { [s.id]: ((_a = acc[s.id]) !== null && _a !== void 0 ? _a : (acc[s.id] = [])).concat({
|
|
@@ -458,26 +552,29 @@ export class ContactFormValuesContainer {
|
|
|
458
552
|
modified: ctc.created,
|
|
459
553
|
value: s,
|
|
460
554
|
}) }) : acc;
|
|
461
|
-
}, acc)) !== null && _c !== void 0 ? _c : acc;
|
|
462
|
-
return services;
|
|
555
|
+
}, acc)) !== null && _c !== void 0 ? _c : acc);
|
|
463
556
|
}, {});
|
|
464
557
|
this.synchronise();
|
|
465
558
|
}
|
|
466
559
|
synchronise() {
|
|
467
560
|
this.children.forEach((childFVC) => {
|
|
468
|
-
|
|
561
|
+
var _a;
|
|
562
|
+
this.registerChildFormValuesContainer(childFVC.synchronise(), (_a = childFVC.anchorId) !== null && _a !== void 0 ? _a : '');
|
|
469
563
|
});
|
|
470
564
|
return this;
|
|
471
565
|
}
|
|
472
566
|
//Make sure that when a child is changed, a new version of this is created with the updated child
|
|
473
|
-
registerChildFormValuesContainer(childFormValueContainer) {
|
|
567
|
+
registerChildFormValuesContainer(childFormValueContainer, anchorId) {
|
|
474
568
|
childFormValueContainer.changeListeners = [
|
|
475
|
-
(newValue) => {
|
|
569
|
+
(newValue, changedKeys, force) => {
|
|
570
|
+
if ((changedKeys === null || changedKeys === void 0 ? void 0 : changedKeys.length) === 0 && !force) {
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
476
573
|
console.log(`Child ${newValue._id} ${childFormValueContainer.rootForm.formTemplateId} changed, updating parent ${this._id} ${this.rootForm.formTemplateId}`);
|
|
477
574
|
const newContactFormValuesContainer = new ContactFormValuesContainer(this.rootForm, this.currentContact, this.contactsHistory, this.serviceFactory, this.children.map((c) => {
|
|
478
575
|
return c.rootForm.id === childFormValueContainer.rootForm.id ? newValue : c;
|
|
479
|
-
}), this.formFactory, this.formRecycler);
|
|
480
|
-
this.changeListeners.forEach((l) => notify(l, newContactFormValuesContainer));
|
|
576
|
+
}), this.formFactory, this.formRecycler, [], this.anchorId, true);
|
|
577
|
+
this.changeListeners.forEach((l) => notify(l, newContactFormValuesContainer, null));
|
|
481
578
|
},
|
|
482
579
|
];
|
|
483
580
|
}
|
|
@@ -487,8 +584,8 @@ export class ContactFormValuesContainer {
|
|
|
487
584
|
? yield Promise.all((yield formChildrenProvider(rootForm.id)).map((f) => __awaiter(this, void 0, void 0, function* () {
|
|
488
585
|
// eslint-disable-next-line max-len
|
|
489
586
|
return yield ContactFormValuesContainer.fromFormsHierarchy(f, currentContact, contactsHistory, serviceFactory, formChildrenProvider, formFactory, formRecycler); })))
|
|
490
|
-
: [], formFactory, formRecycler, changeListeners, false);
|
|
491
|
-
contactFormValuesContainer.children.forEach((childFVC) => contactFormValuesContainer.registerChildFormValuesContainer(childFVC));
|
|
587
|
+
: [], formFactory, formRecycler, changeListeners, rootForm.descr, false);
|
|
588
|
+
contactFormValuesContainer.children.forEach((childFVC) => { var _a; return contactFormValuesContainer.registerChildFormValuesContainer(childFVC, (_a = childFVC.anchorId) !== null && _a !== void 0 ? _a : 'all'); });
|
|
492
589
|
return contactFormValuesContainer;
|
|
493
590
|
});
|
|
494
591
|
}
|
|
@@ -512,12 +609,10 @@ export class ContactFormValuesContainer {
|
|
|
512
609
|
});
|
|
513
610
|
}
|
|
514
611
|
getValidationErrors() {
|
|
515
|
-
|
|
516
|
-
throw new Error('Validation not supported at contact level');
|
|
517
|
-
});
|
|
612
|
+
throw new Error('Validation not supported at contact level');
|
|
518
613
|
}
|
|
519
|
-
|
|
520
|
-
return
|
|
614
|
+
getDefaultValueProvider() {
|
|
615
|
+
return undefined;
|
|
521
616
|
}
|
|
522
617
|
getValues(revisionsFilter) {
|
|
523
618
|
return Object.entries(this.getServicesInHistory(revisionsFilter)).reduce((acc, [id, history]) => history.length
|
|
@@ -562,20 +657,20 @@ export class ContactFormValuesContainer {
|
|
|
562
657
|
meta.valueDate && (newService.valueDate = meta.valueDate);
|
|
563
658
|
meta.codes && (newService.codes = normalizeCodes(meta.codes));
|
|
564
659
|
meta.tags && (newService.tags = normalizeCodes(meta.tags));
|
|
565
|
-
const newFormValuesContainer = new ContactFormValuesContainer(this.rootForm, new DecryptedContact(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));
|
|
660
|
+
const newFormValuesContainer = new ContactFormValuesContainer(this.rootForm, new DecryptedContact(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);
|
|
661
|
+
this.changeListeners.forEach((l) => notify(l, newFormValuesContainer, [meta.label]));
|
|
567
662
|
}
|
|
568
663
|
}
|
|
569
664
|
setValue(label, language, value, id, metadata, changeListenersOverrider) {
|
|
570
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
|
|
665
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
|
|
571
666
|
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
667
|
if (!service.id) {
|
|
573
668
|
throw new Error('Service id must be defined');
|
|
574
669
|
}
|
|
575
|
-
console.log(
|
|
576
|
-
const newContent = (
|
|
670
|
+
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(contentToPrimitiveType(k, c))}`)} and md`, metadata);
|
|
671
|
+
const newContent = (_d = value === null || value === void 0 ? void 0 : value.content) === null || _d === void 0 ? void 0 : _d[language];
|
|
577
672
|
const newCodes = (value === null || value === void 0 ? void 0 : value.codes) ? normalizeCodes(value.codes) : [];
|
|
578
|
-
if (!isContentEqual((
|
|
673
|
+
if (!isContentEqual((_e = service.content) === null || _e === void 0 ? void 0 : _e[language], newContent) || (newCodes && !areCodesEqual(newCodes, (_f = service.codes) !== null && _f !== void 0 ? _f : []))) {
|
|
579
674
|
const newService = new DecryptedService(Object.assign(Object.assign({}, service), { modified: Date.now() }));
|
|
580
675
|
const newContents = newContent
|
|
581
676
|
? Object.assign(Object.assign({}, (service.content || {})), { [language]: newContent }) : Object.assign({}, (service.content || {}));
|
|
@@ -584,8 +679,8 @@ export class ContactFormValuesContainer {
|
|
|
584
679
|
}
|
|
585
680
|
let newCurrentContact;
|
|
586
681
|
if (!Object.entries(newContents).filter(([, cnt]) => cnt !== undefined).length) {
|
|
587
|
-
newCurrentContact = new DecryptedContact(Object.assign(Object.assign({}, this.currentContact), { subContacts: ((
|
|
588
|
-
? ((
|
|
682
|
+
newCurrentContact = new DecryptedContact(Object.assign(Object.assign({}, this.currentContact), { subContacts: ((_g = this.currentContact.subContacts) !== null && _g !== void 0 ? _g : []).some((sc) => sc.formId === this.rootForm.id)
|
|
683
|
+
? ((_h = this.currentContact.subContacts) !== null && _h !== void 0 ? _h : []).map((sc) => {
|
|
589
684
|
var _a;
|
|
590
685
|
if (sc.formId === this.rootForm.id) {
|
|
591
686
|
return new DecryptedSubContact(Object.assign(Object.assign({}, sc), { services: ((_a = sc.services) !== null && _a !== void 0 ? _a : []).filter((s) => s.serviceId !== service.id).concat([new ServiceLink({ serviceId: service.id })]) }));
|
|
@@ -594,24 +689,24 @@ export class ContactFormValuesContainer {
|
|
|
594
689
|
return sc;
|
|
595
690
|
}
|
|
596
691
|
})
|
|
597
|
-
: ((
|
|
692
|
+
: ((_j = this.currentContact.subContacts) !== null && _j !== void 0 ? _j : []).concat(new DecryptedSubContact({
|
|
598
693
|
formId: this.rootForm.id,
|
|
599
694
|
services: [new ServiceLink({ serviceId: service.id })],
|
|
600
|
-
})), services: ((
|
|
601
|
-
? ((
|
|
602
|
-
: [...((
|
|
695
|
+
})), services: ((_k = this.currentContact.services) !== null && _k !== void 0 ? _k : []).some((s) => s.id === service.id)
|
|
696
|
+
? ((_l = this.currentContact.services) !== null && _l !== void 0 ? _l : []).filter((s) => s.id !== service.id)
|
|
697
|
+
: [...((_m = this.currentContact.services) !== null && _m !== void 0 ? _m : [])] }));
|
|
603
698
|
}
|
|
604
699
|
else {
|
|
605
700
|
newService.content = newContents;
|
|
606
701
|
newService.codes = newCodes;
|
|
607
702
|
if (metadata) {
|
|
608
|
-
newService.responsible = (
|
|
609
|
-
newService.valueDate = (
|
|
703
|
+
newService.responsible = (_o = metadata.responsible) !== null && _o !== void 0 ? _o : newService.responsible;
|
|
704
|
+
newService.valueDate = (_p = metadata.valueDate) !== null && _p !== void 0 ? _p : newService.valueDate;
|
|
610
705
|
newService.tags = metadata.tags ? normalizeCodes(metadata.tags) : newService.tags;
|
|
611
|
-
newService.label = (
|
|
706
|
+
newService.label = (_q = metadata.label) !== null && _q !== void 0 ? _q : newService.label;
|
|
612
707
|
}
|
|
613
|
-
newCurrentContact = new DecryptedContact(Object.assign(Object.assign({}, this.currentContact), { subContacts: ((
|
|
614
|
-
? ((
|
|
708
|
+
newCurrentContact = new DecryptedContact(Object.assign(Object.assign({}, this.currentContact), { subContacts: ((_r = this.currentContact.subContacts) !== null && _r !== void 0 ? _r : []).some((sc) => sc.formId === this.rootForm.id)
|
|
709
|
+
? ((_s = this.currentContact.subContacts) !== null && _s !== void 0 ? _s : []).map((sc) => {
|
|
615
710
|
var _a;
|
|
616
711
|
if (sc.formId === this.rootForm.id) {
|
|
617
712
|
return new DecryptedSubContact(Object.assign(Object.assign({}, sc), { services: ((_a = sc.services) !== null && _a !== void 0 ? _a : []).filter((s) => s.serviceId !== service.id).concat([new ServiceLink({ serviceId: service.id })]) }));
|
|
@@ -620,15 +715,15 @@ export class ContactFormValuesContainer {
|
|
|
620
715
|
return sc;
|
|
621
716
|
}
|
|
622
717
|
})
|
|
623
|
-
: ((
|
|
718
|
+
: ((_t = this.currentContact.subContacts) !== null && _t !== void 0 ? _t : []).concat(new DecryptedSubContact({
|
|
624
719
|
formId: this.rootForm.id,
|
|
625
720
|
services: [new ServiceLink({ serviceId: service.id })],
|
|
626
|
-
})), services: ((
|
|
627
|
-
? ((
|
|
628
|
-
: [...((
|
|
721
|
+
})), services: ((_u = this.currentContact.services) !== null && _u !== void 0 ? _u : []).some((s) => s.id === service.id)
|
|
722
|
+
? ((_v = this.currentContact.services) !== null && _v !== void 0 ? _v : []).map((s) => (s.id === service.id ? newService : s))
|
|
723
|
+
: [...((_w = this.currentContact.services) !== null && _w !== void 0 ? _w : []), newService] }));
|
|
629
724
|
}
|
|
630
|
-
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));
|
|
725
|
+
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);
|
|
726
|
+
changeListenersOverrider ? changeListenersOverrider(newFormValuesContainer, [label]) : this.changeListeners.forEach((l) => notify(l, newFormValuesContainer, [label]));
|
|
632
727
|
}
|
|
633
728
|
}
|
|
634
729
|
delete(serviceId) {
|
|
@@ -637,10 +732,35 @@ export class ContactFormValuesContainer {
|
|
|
637
732
|
if (service) {
|
|
638
733
|
const newFormValuesContainer = new ContactFormValuesContainer(this.rootForm, new DecryptedContact(Object.assign(Object.assign({}, this.currentContact), { services: (_a = this.currentContact.services) === null || _a === void 0 ? void 0 : _a.map((s) => s.id === serviceId
|
|
639
734
|
? new DecryptedService(Object.assign(Object.assign({}, service), { endOfLife: Date.now() }))
|
|
640
|
-
: s) })), this.contactsHistory, this.serviceFactory, this.children, this.formFactory, this.formRecycler, this.changeListeners);
|
|
641
|
-
this.changeListeners.forEach((l) => notify(l, newFormValuesContainer));
|
|
735
|
+
: s) })), this.contactsHistory, this.serviceFactory, this.children, this.formFactory, this.formRecycler, this.changeListeners, this.anchorId, true);
|
|
736
|
+
this.changeListeners.forEach((l) => { var _a; return notify(l, newFormValuesContainer, [(_a = service.label) !== null && _a !== void 0 ? _a : service.id] /* only the label is going to propagate the changes for the formulas */); });
|
|
642
737
|
}
|
|
643
738
|
}
|
|
739
|
+
toMarkdownTable() {
|
|
740
|
+
var _a, _b, _c;
|
|
741
|
+
const tableRows = [];
|
|
742
|
+
for (const [, versions] of Object.entries(this.indexedServices)) {
|
|
743
|
+
if (!versions.length)
|
|
744
|
+
continue;
|
|
745
|
+
const service = versions[0].value;
|
|
746
|
+
const label = (_b = (_a = service.label) !== null && _a !== void 0 ? _a : service.id) !== null && _b !== void 0 ? _b : '';
|
|
747
|
+
const modifiedStr = service.modified ? new Date(service.modified).toISOString() : '';
|
|
748
|
+
const contentParts = [];
|
|
749
|
+
for (const [lng, cnt] of Object.entries((_c = service.content) !== null && _c !== void 0 ? _c : {})) {
|
|
750
|
+
const primitive = contentToPrimitiveType(lng, cnt);
|
|
751
|
+
if (primitive) {
|
|
752
|
+
contentParts.push(primitiveTypeToString(primitive));
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
tableRows.push([label, modifiedStr, contentParts.join(', ')]);
|
|
756
|
+
}
|
|
757
|
+
const headers = ['Label', 'Modified', 'Content'];
|
|
758
|
+
const colWidths = headers.map((h, i) => Math.max(h.length, ...tableRows.map((r) => r[i].length)));
|
|
759
|
+
const pad = (s, w) => s + ' '.repeat(w - s.length);
|
|
760
|
+
const formatRow = (cells) => '| ' + cells.map((c, i) => pad(c, colWidths[i])).join(' | ') + ' |';
|
|
761
|
+
const separator = '|' + colWidths.map((w) => '-'.repeat(w + 2)).join('|') + '|';
|
|
762
|
+
return [formatRow(headers), separator, ...tableRows.map(formatRow)].join('\n');
|
|
763
|
+
}
|
|
644
764
|
compute() {
|
|
645
765
|
return __awaiter(this, void 0, void 0, function* () {
|
|
646
766
|
throw new Error('Compute not supported at contact level');
|
|
@@ -679,10 +799,12 @@ export class ContactFormValuesContainer {
|
|
|
679
799
|
if (!parentId)
|
|
680
800
|
return;
|
|
681
801
|
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);
|
|
683
|
-
const newContactFormValuesContainer = new ContactFormValuesContainer(this.rootForm, this.currentContact, this.contactsHistory, this.serviceFactory, [...this.children, childFVC], this.formFactory, this.formRecycler, this.changeListeners);
|
|
684
|
-
newContactFormValuesContainer.registerChildFormValuesContainer(childFVC);
|
|
685
|
-
this.changeListeners.forEach((l) =>
|
|
802
|
+
const childFVC = new ContactFormValuesContainer(newForm, this.currentContact, this.contactsHistory, this.serviceFactory, [], this.formFactory, this.formRecycler, [], anchorId, false);
|
|
803
|
+
const newContactFormValuesContainer = new ContactFormValuesContainer(this.rootForm, this.currentContact, this.contactsHistory, this.serviceFactory, [...this.children, childFVC], this.formFactory, this.formRecycler, this.changeListeners, this.anchorId, true);
|
|
804
|
+
newContactFormValuesContainer.registerChildFormValuesContainer(childFVC, anchorId);
|
|
805
|
+
this.changeListeners.forEach((l) => {
|
|
806
|
+
notify(l, newContactFormValuesContainer, null);
|
|
807
|
+
});
|
|
686
808
|
});
|
|
687
809
|
}
|
|
688
810
|
getServiceInCurrentContact(id) {
|
|
@@ -692,13 +814,84 @@ export class ContactFormValuesContainer {
|
|
|
692
814
|
}
|
|
693
815
|
removeChild(container) {
|
|
694
816
|
return __awaiter(this, void 0, void 0, function* () {
|
|
695
|
-
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));
|
|
817
|
+
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);
|
|
818
|
+
this.changeListeners.forEach((l) => { var _a; return notify(l, newContactFormValuesContainer, [`subForms_${(_a = container.anchorId) !== null && _a !== void 0 ? _a : 'all'}`]); });
|
|
697
819
|
});
|
|
698
820
|
}
|
|
699
821
|
}
|
|
822
|
+
// Runtime validation for FieldValue — guards against mistyped data coming from
|
|
823
|
+
// external callers (formulas, SDK bridges, etc.) where the TypeScript types may
|
|
824
|
+
// not match the actual runtime values.
|
|
825
|
+
const validatePrimitiveType = (pt, path) => {
|
|
826
|
+
const v = pt.value;
|
|
827
|
+
switch (pt.type) {
|
|
828
|
+
case 'string':
|
|
829
|
+
if (typeof v !== 'string') {
|
|
830
|
+
throw new Error(`${path}: expected string value, got ${typeof v}`);
|
|
831
|
+
}
|
|
832
|
+
break;
|
|
833
|
+
case 'number':
|
|
834
|
+
if (typeof v !== 'number') {
|
|
835
|
+
throw new Error(`${path}: expected number value, got ${typeof v}`);
|
|
836
|
+
}
|
|
837
|
+
break;
|
|
838
|
+
case 'boolean':
|
|
839
|
+
if (typeof v !== 'boolean') {
|
|
840
|
+
throw new Error(`${path}: expected boolean value, got ${typeof v}`);
|
|
841
|
+
}
|
|
842
|
+
break;
|
|
843
|
+
case 'timestamp':
|
|
844
|
+
if (typeof v !== 'number') {
|
|
845
|
+
throw new Error(`${path}: expected number value for timestamp, got ${typeof v}`);
|
|
846
|
+
}
|
|
847
|
+
break;
|
|
848
|
+
case 'datetime':
|
|
849
|
+
if (typeof v !== 'number') {
|
|
850
|
+
throw new Error(`${path}: expected number value for datetime, got ${typeof v}`);
|
|
851
|
+
}
|
|
852
|
+
break;
|
|
853
|
+
case 'measure': {
|
|
854
|
+
const m = pt;
|
|
855
|
+
if (m.value !== undefined && typeof m.value !== 'number') {
|
|
856
|
+
throw new Error(`${path}: expected number or undefined value for measure, got ${typeof m.value}`);
|
|
857
|
+
}
|
|
858
|
+
if (m.unit !== undefined && typeof m.unit !== 'string') {
|
|
859
|
+
throw new Error(`${path}: expected string or undefined unit for measure, got ${typeof m.unit}`);
|
|
860
|
+
}
|
|
861
|
+
break;
|
|
862
|
+
}
|
|
863
|
+
case 'compound':
|
|
864
|
+
if (typeof v !== 'object' || v === null || Array.isArray(v)) {
|
|
865
|
+
throw new Error(`${path}: expected object value for compound, got ${Array.isArray(v) ? 'array' : typeof v}`);
|
|
866
|
+
}
|
|
867
|
+
for (const [key, subValue] of Object.entries(v)) {
|
|
868
|
+
validatePrimitiveType(subValue, `${path}.compound[${key}]`);
|
|
869
|
+
}
|
|
870
|
+
break;
|
|
871
|
+
default:
|
|
872
|
+
throw new Error(`${path}: unknown PrimitiveType type: ${pt.type}`);
|
|
873
|
+
}
|
|
874
|
+
};
|
|
875
|
+
const validateCode = (code, path) => {
|
|
876
|
+
const id = code.id;
|
|
877
|
+
if (!id || typeof id !== 'string') {
|
|
878
|
+
throw new Error(`${path}: code must have a non-empty string id, got ${JSON.stringify(id)}`);
|
|
879
|
+
}
|
|
880
|
+
};
|
|
881
|
+
const validateFieldValue = (fv, language, label) => {
|
|
882
|
+
const pt = fv.content[language];
|
|
883
|
+
if (pt) {
|
|
884
|
+
validatePrimitiveType(pt, `FieldValue[${label}].content[${language}]`);
|
|
885
|
+
}
|
|
886
|
+
if (fv.codes) {
|
|
887
|
+
fv.codes.forEach((code, i) => validateCode(code, `FieldValue[${label}].codes[${i}]`));
|
|
888
|
+
}
|
|
889
|
+
};
|
|
700
890
|
const setValueOnContactFormValuesContainer = (cfvc, label, language, fv, id, metadata, changeListenersOverrider) => {
|
|
701
891
|
var _a, _b, _c, _d;
|
|
892
|
+
if (fv) {
|
|
893
|
+
validateFieldValue(fv, language, label);
|
|
894
|
+
}
|
|
702
895
|
const value = fv === null || fv === void 0 ? void 0 : fv.content[language];
|
|
703
896
|
cfvc.setValue(label, language, new DecryptedService({
|
|
704
897
|
id: id,
|