@jsonforms/core 3.1.0-alpha.1 → 3.1.0-alpha.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.
- package/README.md +3 -3
- package/lib/actions/actions.d.ts +21 -21
- package/lib/i18n/arrayTranslations.d.ts +24 -0
- package/lib/i18n/i18nUtil.d.ts +3 -0
- package/lib/i18n/index.d.ts +1 -0
- package/lib/jsonforms-core.cjs.js +427 -258
- package/lib/jsonforms-core.cjs.js.map +1 -1
- package/lib/jsonforms-core.esm.js +313 -200
- package/lib/jsonforms-core.esm.js.map +1 -1
- package/lib/util/cell.d.ts +0 -1
- package/lib/util/renderer.d.ts +6 -2
- package/package.json +11 -4
- package/src/Helpers.ts +1 -1
- package/src/actions/actions.ts +52 -55
- package/src/configDefault.ts +1 -1
- package/src/generators/Generate.ts +3 -1
- package/src/generators/schema.ts +29 -25
- package/src/generators/uischema.ts +7 -6
- package/src/i18n/arrayTranslations.ts +54 -0
- package/src/i18n/i18nTypes.ts +10 -6
- package/src/i18n/i18nUtil.ts +64 -14
- package/src/i18n/index.ts +1 -0
- package/src/models/draft4.ts +33 -33
- package/src/models/uischema.ts +17 -6
- package/src/reducers/cells.ts +8 -7
- package/src/reducers/core.ts +112 -73
- package/src/reducers/default-data.ts +7 -7
- package/src/reducers/i18n.ts +21 -9
- package/src/reducers/reducers.ts +20 -30
- package/src/reducers/renderers.ts +7 -7
- package/src/reducers/selectors.ts +4 -5
- package/src/reducers/uischemas.ts +25 -24
- package/src/store.ts +1 -1
- package/src/testers/testers.ts +199 -146
- package/src/util/cell.ts +24 -26
- package/src/util/combinators.ts +5 -3
- package/src/util/label.ts +1 -1
- package/src/util/path.ts +11 -7
- package/src/util/renderer.ts +118 -67
- package/src/util/resolvers.ts +15 -13
- package/src/util/runtime.ts +2 -2
- package/src/util/schema.ts +1 -1
- package/src/util/type.ts +5 -3
- package/src/util/uischema.ts +9 -9
- package/src/util/util.ts +52 -52
- package/src/util/validator.ts +1 -1
package/src/testers/testers.ts
CHANGED
|
@@ -35,7 +35,7 @@ import type {
|
|
|
35
35
|
Categorization,
|
|
36
36
|
ControlElement,
|
|
37
37
|
JsonSchema,
|
|
38
|
-
UISchemaElement
|
|
38
|
+
UISchemaElement,
|
|
39
39
|
} from '../models';
|
|
40
40
|
import { deriveTypes, hasType, resolveSchema } from '../util';
|
|
41
41
|
|
|
@@ -49,7 +49,11 @@ export const NOT_APPLICABLE = -1;
|
|
|
49
49
|
* A tester is a function that receives an UI schema and a JSON schema and returns a boolean.
|
|
50
50
|
* The rootSchema is handed over as context. Can be used to resolve references.
|
|
51
51
|
*/
|
|
52
|
-
export type Tester = (
|
|
52
|
+
export type Tester = (
|
|
53
|
+
uischema: UISchemaElement,
|
|
54
|
+
schema: JsonSchema,
|
|
55
|
+
context: TesterContext
|
|
56
|
+
) => boolean;
|
|
53
57
|
|
|
54
58
|
/**
|
|
55
59
|
* A ranked tester associates a tester with a number.
|
|
@@ -83,50 +87,70 @@ export const isControl = (uischema: any): uischema is ControlElement =>
|
|
|
83
87
|
* @param {(JsonSchema) => boolean} predicate the predicate that should be
|
|
84
88
|
* applied to the resolved sub-schema
|
|
85
89
|
*/
|
|
86
|
-
export const schemaMatches =
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
90
|
+
export const schemaMatches =
|
|
91
|
+
(
|
|
92
|
+
predicate: (schema: JsonSchema, rootSchema: JsonSchema) => boolean
|
|
93
|
+
): Tester =>
|
|
94
|
+
(
|
|
95
|
+
uischema: UISchemaElement,
|
|
96
|
+
schema: JsonSchema,
|
|
97
|
+
context: TesterContext
|
|
98
|
+
): boolean => {
|
|
99
|
+
if (isEmpty(uischema) || !isControl(uischema)) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
if (isEmpty(schema)) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
const schemaPath = uischema.scope;
|
|
106
|
+
if (isEmpty(schemaPath)) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
let currentDataSchema = schema;
|
|
110
|
+
if (hasType(schema, 'object')) {
|
|
111
|
+
currentDataSchema = resolveSchema(
|
|
112
|
+
schema,
|
|
113
|
+
schemaPath,
|
|
114
|
+
context?.rootSchema
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
if (currentDataSchema === undefined) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
109
120
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
121
|
+
return predicate(currentDataSchema, context?.rootSchema);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export const schemaSubPathMatches =
|
|
125
|
+
(
|
|
126
|
+
subPath: string,
|
|
127
|
+
predicate: (schema: JsonSchema, rootSchema: JsonSchema) => boolean
|
|
128
|
+
): Tester =>
|
|
129
|
+
(
|
|
130
|
+
uischema: UISchemaElement,
|
|
131
|
+
schema: JsonSchema,
|
|
132
|
+
context: TesterContext
|
|
133
|
+
): boolean => {
|
|
134
|
+
if (isEmpty(uischema) || !isControl(uischema)) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
const schemaPath = uischema.scope;
|
|
138
|
+
let currentDataSchema: JsonSchema = schema;
|
|
139
|
+
if (hasType(schema, 'object')) {
|
|
140
|
+
currentDataSchema = resolveSchema(
|
|
141
|
+
schema,
|
|
142
|
+
schemaPath,
|
|
143
|
+
context?.rootSchema
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
currentDataSchema = get(currentDataSchema, subPath);
|
|
123
147
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
148
|
+
if (currentDataSchema === undefined) {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
127
151
|
|
|
128
|
-
|
|
129
|
-
};
|
|
152
|
+
return predicate(currentDataSchema, context?.rootSchema);
|
|
153
|
+
};
|
|
130
154
|
|
|
131
155
|
/**
|
|
132
156
|
* Only applicable for Controls.
|
|
@@ -138,7 +162,7 @@ export const schemaSubPathMatches = (
|
|
|
138
162
|
* @param {string} expectedType the expected type of the resolved sub-schema
|
|
139
163
|
*/
|
|
140
164
|
export const schemaTypeIs = (expectedType: string): Tester =>
|
|
141
|
-
schemaMatches(schema => !isEmpty(schema) && hasType(schema, expectedType));
|
|
165
|
+
schemaMatches((schema) => !isEmpty(schema) && hasType(schema, expectedType));
|
|
142
166
|
|
|
143
167
|
/**
|
|
144
168
|
* Only applicable for Controls.
|
|
@@ -151,7 +175,7 @@ export const schemaTypeIs = (expectedType: string): Tester =>
|
|
|
151
175
|
*/
|
|
152
176
|
export const formatIs = (expectedFormat: string): Tester =>
|
|
153
177
|
schemaMatches(
|
|
154
|
-
schema =>
|
|
178
|
+
(schema) =>
|
|
155
179
|
!isEmpty(schema) &&
|
|
156
180
|
schema.format === expectedFormat &&
|
|
157
181
|
hasType(schema, 'string')
|
|
@@ -162,9 +186,10 @@ export const formatIs = (expectedFormat: string): Tester =>
|
|
|
162
186
|
*
|
|
163
187
|
* @param {string} expected the expected UI schema type
|
|
164
188
|
*/
|
|
165
|
-
export const uiTypeIs =
|
|
166
|
-
|
|
167
|
-
): boolean =>
|
|
189
|
+
export const uiTypeIs =
|
|
190
|
+
(expected: string): Tester =>
|
|
191
|
+
(uischema: UISchemaElement): boolean =>
|
|
192
|
+
!isEmpty(uischema) && uischema.type === expected;
|
|
168
193
|
|
|
169
194
|
/**
|
|
170
195
|
* Checks whether the given UI schema has an option with the given
|
|
@@ -174,16 +199,16 @@ export const uiTypeIs = (expected: string): Tester => (
|
|
|
174
199
|
* @param {string} optionName the name of the option to check
|
|
175
200
|
* @param {any} optionValue the expected value of the option
|
|
176
201
|
*/
|
|
177
|
-
export const optionIs =
|
|
178
|
-
|
|
179
|
-
): boolean => {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
202
|
+
export const optionIs =
|
|
203
|
+
(optionName: string, optionValue: any): Tester =>
|
|
204
|
+
(uischema: UISchemaElement): boolean => {
|
|
205
|
+
if (isEmpty(uischema)) {
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
183
208
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
};
|
|
209
|
+
const options = uischema.options;
|
|
210
|
+
return !isEmpty(options) && options[optionName] === optionValue;
|
|
211
|
+
};
|
|
187
212
|
|
|
188
213
|
/**
|
|
189
214
|
* Only applicable for Controls.
|
|
@@ -192,15 +217,15 @@ export const optionIs = (optionName: string, optionValue: any): Tester => (
|
|
|
192
217
|
*
|
|
193
218
|
* @param {string} expected the expected ending of the reference
|
|
194
219
|
*/
|
|
195
|
-
export const scopeEndsWith =
|
|
196
|
-
|
|
197
|
-
): boolean => {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
220
|
+
export const scopeEndsWith =
|
|
221
|
+
(expected: string): Tester =>
|
|
222
|
+
(uischema: UISchemaElement): boolean => {
|
|
223
|
+
if (isEmpty(expected) || !isControl(uischema)) {
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
201
226
|
|
|
202
|
-
|
|
203
|
-
};
|
|
227
|
+
return endsWith(uischema.scope, expected);
|
|
228
|
+
};
|
|
204
229
|
|
|
205
230
|
/**
|
|
206
231
|
* Only applicable for Controls.
|
|
@@ -209,38 +234,42 @@ export const scopeEndsWith = (expected: string): Tester => (
|
|
|
209
234
|
*
|
|
210
235
|
* @param {string} expected the expected ending of the reference
|
|
211
236
|
*/
|
|
212
|
-
export const scopeEndIs =
|
|
213
|
-
|
|
214
|
-
): boolean => {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
237
|
+
export const scopeEndIs =
|
|
238
|
+
(expected: string): Tester =>
|
|
239
|
+
(uischema: UISchemaElement): boolean => {
|
|
240
|
+
if (isEmpty(expected) || !isControl(uischema)) {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
const schemaPath = uischema.scope;
|
|
219
244
|
|
|
220
|
-
|
|
221
|
-
};
|
|
245
|
+
return !isEmpty(schemaPath) && last(schemaPath.split('/')) === expected;
|
|
246
|
+
};
|
|
222
247
|
|
|
223
248
|
/**
|
|
224
249
|
* A tester that allow composing other testers by && them.
|
|
225
250
|
*
|
|
226
251
|
* @param {Array<Tester>} testers the testers to be composed
|
|
227
252
|
*/
|
|
228
|
-
export const and =
|
|
229
|
-
|
|
230
|
-
schema: JsonSchema,
|
|
231
|
-
|
|
232
|
-
|
|
253
|
+
export const and =
|
|
254
|
+
(...testers: Tester[]): Tester =>
|
|
255
|
+
(uischema: UISchemaElement, schema: JsonSchema, context: TesterContext) =>
|
|
256
|
+
testers.reduce(
|
|
257
|
+
(acc, tester) => acc && tester(uischema, schema, context),
|
|
258
|
+
true
|
|
259
|
+
);
|
|
233
260
|
|
|
234
261
|
/**
|
|
235
262
|
* A tester that allow composing other testers by || them.
|
|
236
263
|
*
|
|
237
264
|
* @param {Array<Tester>} testers the testers to be composed
|
|
238
265
|
*/
|
|
239
|
-
export const or =
|
|
240
|
-
|
|
241
|
-
schema: JsonSchema,
|
|
242
|
-
|
|
243
|
-
|
|
266
|
+
export const or =
|
|
267
|
+
(...testers: Tester[]): Tester =>
|
|
268
|
+
(uischema: UISchemaElement, schema: JsonSchema, context: TesterContext) =>
|
|
269
|
+
testers.reduce(
|
|
270
|
+
(acc, tester) => acc || tester(uischema, schema, context),
|
|
271
|
+
false
|
|
272
|
+
);
|
|
244
273
|
/**
|
|
245
274
|
* Create a ranked tester that will associate a number with a given tester, if the
|
|
246
275
|
* latter returns true.
|
|
@@ -248,30 +277,34 @@ export const or = (...testers: Tester[]): Tester => (
|
|
|
248
277
|
* @param {number} rank the rank to be returned in case the tester returns true
|
|
249
278
|
* @param {Tester} tester a tester
|
|
250
279
|
*/
|
|
251
|
-
export const rankWith =
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
};
|
|
280
|
+
export const rankWith =
|
|
281
|
+
(rank: number, tester: Tester) =>
|
|
282
|
+
(
|
|
283
|
+
uischema: UISchemaElement,
|
|
284
|
+
schema: JsonSchema,
|
|
285
|
+
context: TesterContext
|
|
286
|
+
): number => {
|
|
287
|
+
if (tester(uischema, schema, context)) {
|
|
288
|
+
return rank;
|
|
289
|
+
}
|
|
262
290
|
|
|
263
|
-
export const withIncreasedRank = (by: number, rankedTester: RankedTester) => (
|
|
264
|
-
uischema: UISchemaElement,
|
|
265
|
-
schema: JsonSchema,
|
|
266
|
-
context: TesterContext
|
|
267
|
-
): number => {
|
|
268
|
-
const rank = rankedTester(uischema, schema, context);
|
|
269
|
-
if (rank === NOT_APPLICABLE) {
|
|
270
291
|
return NOT_APPLICABLE;
|
|
271
|
-
}
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
export const withIncreasedRank =
|
|
295
|
+
(by: number, rankedTester: RankedTester) =>
|
|
296
|
+
(
|
|
297
|
+
uischema: UISchemaElement,
|
|
298
|
+
schema: JsonSchema,
|
|
299
|
+
context: TesterContext
|
|
300
|
+
): number => {
|
|
301
|
+
const rank = rankedTester(uischema, schema, context);
|
|
302
|
+
if (rank === NOT_APPLICABLE) {
|
|
303
|
+
return NOT_APPLICABLE;
|
|
304
|
+
}
|
|
272
305
|
|
|
273
|
-
|
|
274
|
-
};
|
|
306
|
+
return rank + by;
|
|
307
|
+
};
|
|
275
308
|
|
|
276
309
|
/**
|
|
277
310
|
* Default tester for boolean.
|
|
@@ -287,17 +320,17 @@ export const isObjectControl = and(uiTypeIs('Control'), schemaTypeIs('object'));
|
|
|
287
320
|
|
|
288
321
|
export const isAllOfControl = and(
|
|
289
322
|
uiTypeIs('Control'),
|
|
290
|
-
schemaMatches(schema => schema.hasOwnProperty('allOf'))
|
|
323
|
+
schemaMatches((schema) => schema.hasOwnProperty('allOf'))
|
|
291
324
|
);
|
|
292
325
|
|
|
293
326
|
export const isAnyOfControl = and(
|
|
294
327
|
uiTypeIs('Control'),
|
|
295
|
-
schemaMatches(schema => schema.hasOwnProperty('anyOf'))
|
|
328
|
+
schemaMatches((schema) => schema.hasOwnProperty('anyOf'))
|
|
296
329
|
);
|
|
297
330
|
|
|
298
331
|
export const isOneOfControl = and(
|
|
299
332
|
uiTypeIs('Control'),
|
|
300
|
-
schemaMatches(schema => schema.hasOwnProperty('oneOf'))
|
|
333
|
+
schemaMatches((schema) => schema.hasOwnProperty('oneOf'))
|
|
301
334
|
);
|
|
302
335
|
|
|
303
336
|
/**
|
|
@@ -308,8 +341,8 @@ export const isOneOfControl = and(
|
|
|
308
341
|
export const isEnumControl = and(
|
|
309
342
|
uiTypeIs('Control'),
|
|
310
343
|
or(
|
|
311
|
-
schemaMatches(schema => schema.hasOwnProperty('enum')),
|
|
312
|
-
schemaMatches(schema => schema.hasOwnProperty('const'))
|
|
344
|
+
schemaMatches((schema) => schema.hasOwnProperty('enum')),
|
|
345
|
+
schemaMatches((schema) => schema.hasOwnProperty('const'))
|
|
313
346
|
)
|
|
314
347
|
);
|
|
315
348
|
|
|
@@ -320,9 +353,10 @@ export const isEnumControl = and(
|
|
|
320
353
|
*/
|
|
321
354
|
export const isOneOfEnumControl = and(
|
|
322
355
|
uiTypeIs('Control'),
|
|
323
|
-
schemaMatches(
|
|
324
|
-
schema
|
|
325
|
-
|
|
356
|
+
schemaMatches(
|
|
357
|
+
(schema) =>
|
|
358
|
+
schema.hasOwnProperty('oneOf') &&
|
|
359
|
+
(schema.oneOf as JsonSchema[]).every((s) => s.const !== undefined)
|
|
326
360
|
)
|
|
327
361
|
);
|
|
328
362
|
|
|
@@ -396,11 +430,15 @@ export const isDateTimeControl = and(
|
|
|
396
430
|
*/
|
|
397
431
|
export const isObjectArray = and(
|
|
398
432
|
schemaMatches(
|
|
399
|
-
(schema, rootSchema) =>
|
|
433
|
+
(schema, rootSchema) =>
|
|
434
|
+
hasType(schema, 'array') &&
|
|
435
|
+
!Array.isArray(resolveSchema(schema, 'items', rootSchema)) // we don't care about tuples
|
|
400
436
|
),
|
|
401
437
|
schemaSubPathMatches('items', (schema, rootSchema) => {
|
|
402
|
-
const resolvedSchema = schema.$ref
|
|
403
|
-
|
|
438
|
+
const resolvedSchema = schema.$ref
|
|
439
|
+
? resolveSchema(rootSchema, schema.$ref, rootSchema)
|
|
440
|
+
: schema;
|
|
441
|
+
return hasType(resolvedSchema, 'object');
|
|
404
442
|
})
|
|
405
443
|
);
|
|
406
444
|
|
|
@@ -417,7 +455,11 @@ const traverse = (
|
|
|
417
455
|
rootSchema: JsonSchema
|
|
418
456
|
): boolean => {
|
|
419
457
|
if (isArray(any)) {
|
|
420
|
-
return reduce(
|
|
458
|
+
return reduce(
|
|
459
|
+
any,
|
|
460
|
+
(acc, el) => acc || traverse(el, pred, rootSchema),
|
|
461
|
+
false
|
|
462
|
+
);
|
|
421
463
|
}
|
|
422
464
|
|
|
423
465
|
if (pred(any)) {
|
|
@@ -454,32 +496,43 @@ export const isObjectArrayWithNesting = (
|
|
|
454
496
|
return false;
|
|
455
497
|
}
|
|
456
498
|
const schemaPath = (uischema as ControlElement).scope;
|
|
457
|
-
const resolvedSchema = resolveSchema(
|
|
499
|
+
const resolvedSchema = resolveSchema(
|
|
500
|
+
schema,
|
|
501
|
+
schemaPath,
|
|
502
|
+
context?.rootSchema ?? schema
|
|
503
|
+
);
|
|
458
504
|
let objectDepth = 0;
|
|
459
505
|
if (resolvedSchema !== undefined && resolvedSchema.items !== undefined) {
|
|
460
506
|
// check if nested arrays
|
|
461
507
|
if (
|
|
462
|
-
traverse(
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
if (hasType(val, 'object')) {
|
|
473
|
-
objectDepth++;
|
|
474
|
-
if (objectDepth === 2) {
|
|
508
|
+
traverse(
|
|
509
|
+
resolvedSchema.items,
|
|
510
|
+
(val) => {
|
|
511
|
+
if (val === schema) {
|
|
512
|
+
return false;
|
|
513
|
+
}
|
|
514
|
+
if (val.$ref !== undefined) {
|
|
515
|
+
return false;
|
|
516
|
+
}
|
|
517
|
+
if (val.anyOf || val.allOf) {
|
|
475
518
|
return true;
|
|
476
519
|
}
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
520
|
+
if (val.oneOf && !isOneOfEnumControl(uischema, val, context)) {
|
|
521
|
+
return true;
|
|
522
|
+
}
|
|
523
|
+
if (hasType(val, 'object')) {
|
|
524
|
+
objectDepth++;
|
|
525
|
+
if (objectDepth === 2) {
|
|
526
|
+
return true;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
if (hasType(val, 'array')) {
|
|
530
|
+
return true;
|
|
531
|
+
}
|
|
532
|
+
return false;
|
|
533
|
+
},
|
|
534
|
+
context?.rootSchema
|
|
535
|
+
)
|
|
483
536
|
) {
|
|
484
537
|
return true;
|
|
485
538
|
}
|
|
@@ -516,7 +569,9 @@ export const isPrimitiveArrayControl = and(
|
|
|
516
569
|
!Array.isArray(resolveSchema(schema, 'items', rootSchema)) // we don't care about tuples
|
|
517
570
|
),
|
|
518
571
|
schemaSubPathMatches('items', (schema, rootSchema) => {
|
|
519
|
-
const resolvedSchema = schema.$ref
|
|
572
|
+
const resolvedSchema = schema.$ref
|
|
573
|
+
? resolveSchema(rootSchema, schema.$ref, rootSchema)
|
|
574
|
+
: schema;
|
|
520
575
|
const types = deriveTypes(resolvedSchema);
|
|
521
576
|
return (
|
|
522
577
|
types.length === 1 &&
|
|
@@ -535,7 +590,7 @@ export const isRangeControl = and(
|
|
|
535
590
|
uiTypeIs('Control'),
|
|
536
591
|
or(schemaTypeIs('number'), schemaTypeIs('integer')),
|
|
537
592
|
schemaMatches(
|
|
538
|
-
schema =>
|
|
593
|
+
(schema) =>
|
|
539
594
|
schema.hasOwnProperty('maximum') &&
|
|
540
595
|
schema.hasOwnProperty('minimum') &&
|
|
541
596
|
schema.hasOwnProperty('default')
|
|
@@ -567,7 +622,7 @@ export const hasCategory = (categorization: Categorization): boolean => {
|
|
|
567
622
|
}
|
|
568
623
|
// all children of the categorization have to be categories
|
|
569
624
|
return categorization.elements
|
|
570
|
-
.map(elem =>
|
|
625
|
+
.map((elem) =>
|
|
571
626
|
isCategorization(elem) ? hasCategory(elem) : isCategory(elem)
|
|
572
627
|
)
|
|
573
628
|
.reduce((prev, curr) => prev && curr, true);
|
|
@@ -576,9 +631,7 @@ export const hasCategory = (categorization: Categorization): boolean => {
|
|
|
576
631
|
export const categorizationHasCategory = (uischema: UISchemaElement) =>
|
|
577
632
|
hasCategory(uischema as Categorization);
|
|
578
633
|
|
|
579
|
-
export const not =
|
|
580
|
-
|
|
581
|
-
schema: JsonSchema,
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
) => !tester(uischema, schema, context);
|
|
634
|
+
export const not =
|
|
635
|
+
(tester: Tester): Tester =>
|
|
636
|
+
(uischema: UISchemaElement, schema: JsonSchema, context: TesterContext) =>
|
|
637
|
+
!tester(uischema, schema, context);
|
package/src/util/cell.ts
CHANGED
|
@@ -24,9 +24,8 @@
|
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
26
|
import isEmpty from 'lodash/isEmpty';
|
|
27
|
-
import union from 'lodash/union';
|
|
28
|
-
import type { JsonFormsCellRendererRegistryEntry } from '../reducers';
|
|
29
27
|
import {
|
|
28
|
+
getErrorTranslator,
|
|
30
29
|
getAjv,
|
|
31
30
|
getConfig,
|
|
32
31
|
getData,
|
|
@@ -34,15 +33,10 @@ import {
|
|
|
34
33
|
getSchema,
|
|
35
34
|
getTranslator,
|
|
36
35
|
} from '../reducers';
|
|
36
|
+
import type { JsonFormsCellRendererRegistryEntry } from '../reducers';
|
|
37
37
|
import type { AnyAction, Dispatch } from './type';
|
|
38
|
-
import {
|
|
39
|
-
|
|
40
|
-
Resolve,
|
|
41
|
-
} from './util';
|
|
42
|
-
import {
|
|
43
|
-
isInherentlyEnabled,
|
|
44
|
-
isVisible,
|
|
45
|
-
} from './runtime';
|
|
38
|
+
import { Resolve } from './util';
|
|
39
|
+
import { isInherentlyEnabled, isVisible } from './runtime';
|
|
46
40
|
import {
|
|
47
41
|
DispatchPropsOfControl,
|
|
48
42
|
EnumOption,
|
|
@@ -53,11 +47,9 @@ import {
|
|
|
53
47
|
OwnPropsOfEnum,
|
|
54
48
|
StatePropsOfScopedRenderer,
|
|
55
49
|
} from './renderer';
|
|
50
|
+
import { getCombinedErrorMessage, getI18nKeyPrefix } from '../i18n';
|
|
56
51
|
import type { JsonFormsState } from '../store';
|
|
57
52
|
import type { JsonSchema } from '../models';
|
|
58
|
-
import { getI18nKeyPrefix } from '../i18n';
|
|
59
|
-
|
|
60
|
-
export type { JsonFormsCellRendererRegistryEntry };
|
|
61
53
|
|
|
62
54
|
export interface OwnPropsOfCell extends OwnPropsOfControl {
|
|
63
55
|
data?: any;
|
|
@@ -126,7 +118,7 @@ export const mapStateToCellProps = (
|
|
|
126
118
|
|
|
127
119
|
/* When determining the enabled state of cells we take a shortcut: At the
|
|
128
120
|
* moment it's only possible to configure enablement and disablement at the
|
|
129
|
-
* control level. Therefore the renderer using the cell, for example a
|
|
121
|
+
* control level. Therefore the renderer using the cell, for example a
|
|
130
122
|
* table renderer, determines whether a cell is enabled and should hand
|
|
131
123
|
* over the prop themselves. If that prop was given, we prefer it over
|
|
132
124
|
* anything else to save evaluation effort (except for the global readonly
|
|
@@ -148,8 +140,15 @@ export const mapStateToCellProps = (
|
|
|
148
140
|
);
|
|
149
141
|
}
|
|
150
142
|
|
|
151
|
-
const
|
|
152
|
-
|
|
143
|
+
const t = getTranslator()(state);
|
|
144
|
+
const te = getErrorTranslator()(state);
|
|
145
|
+
const errors = getCombinedErrorMessage(
|
|
146
|
+
getErrorAt(path, schema)(state),
|
|
147
|
+
te,
|
|
148
|
+
t,
|
|
149
|
+
schema,
|
|
150
|
+
uischema,
|
|
151
|
+
path
|
|
153
152
|
);
|
|
154
153
|
const isValid = isEmpty(errors);
|
|
155
154
|
|
|
@@ -166,7 +165,7 @@ export const mapStateToCellProps = (
|
|
|
166
165
|
config: getConfig(state),
|
|
167
166
|
rootSchema,
|
|
168
167
|
renderers,
|
|
169
|
-
cells
|
|
168
|
+
cells,
|
|
170
169
|
};
|
|
171
170
|
};
|
|
172
171
|
|
|
@@ -175,11 +174,11 @@ export const mapStateToDispatchCellProps = (
|
|
|
175
174
|
ownProps: OwnPropsOfCell
|
|
176
175
|
): DispatchCellStateProps => {
|
|
177
176
|
const props: StatePropsOfCell = mapStateToCellProps(state, ownProps);
|
|
178
|
-
const { renderers, cells, ...otherOwnProps } = ownProps;
|
|
177
|
+
const { renderers: _renderers, cells, ...otherOwnProps } = ownProps;
|
|
179
178
|
return {
|
|
180
179
|
...props,
|
|
181
180
|
...otherOwnProps,
|
|
182
|
-
cells: cells || state.jsonforms.cells || []
|
|
181
|
+
cells: cells || state.jsonforms.cells || [],
|
|
183
182
|
};
|
|
184
183
|
};
|
|
185
184
|
|
|
@@ -198,7 +197,7 @@ export const defaultMapStateToEnumCellProps = (
|
|
|
198
197
|
const props: StatePropsOfCell = mapStateToCellProps(state, ownProps);
|
|
199
198
|
const options: EnumOption[] =
|
|
200
199
|
ownProps.options ||
|
|
201
|
-
props.schema.enum?.map(e =>
|
|
200
|
+
props.schema.enum?.map((e) =>
|
|
202
201
|
enumToEnumOptionMapper(
|
|
203
202
|
e,
|
|
204
203
|
getTranslator()(state),
|
|
@@ -210,11 +209,11 @@ export const defaultMapStateToEnumCellProps = (
|
|
|
210
209
|
props.schema.const,
|
|
211
210
|
getTranslator()(state),
|
|
212
211
|
getI18nKeyPrefix(props.schema, props.uischema, props.path)
|
|
213
|
-
)
|
|
212
|
+
),
|
|
214
213
|
]);
|
|
215
214
|
return {
|
|
216
215
|
...props,
|
|
217
|
-
options
|
|
216
|
+
options,
|
|
218
217
|
};
|
|
219
218
|
};
|
|
220
219
|
|
|
@@ -231,7 +230,7 @@ export const mapStateToOneOfEnumCellProps = (
|
|
|
231
230
|
const props: StatePropsOfCell = mapStateToCellProps(state, ownProps);
|
|
232
231
|
const options: EnumOption[] =
|
|
233
232
|
ownProps.options ||
|
|
234
|
-
(props.schema.oneOf as JsonSchema[])?.map(oneOfSubSchema =>
|
|
233
|
+
(props.schema.oneOf as JsonSchema[])?.map((oneOfSubSchema) =>
|
|
235
234
|
oneOfToEnumOptionMapper(
|
|
236
235
|
oneOfSubSchema,
|
|
237
236
|
getTranslator()(state),
|
|
@@ -240,11 +239,10 @@ export const mapStateToOneOfEnumCellProps = (
|
|
|
240
239
|
);
|
|
241
240
|
return {
|
|
242
241
|
...props,
|
|
243
|
-
options
|
|
242
|
+
options,
|
|
244
243
|
};
|
|
245
244
|
};
|
|
246
245
|
|
|
247
|
-
|
|
248
246
|
/**
|
|
249
247
|
* Synonym for mapDispatchToControlProps.
|
|
250
248
|
*
|
|
@@ -264,6 +262,6 @@ export const defaultMapDispatchToControlProps =
|
|
|
264
262
|
const { handleChange } = mapDispatchToCellProps(dispatch);
|
|
265
263
|
|
|
266
264
|
return {
|
|
267
|
-
handleChange: ownProps.handleChange || handleChange
|
|
265
|
+
handleChange: ownProps.handleChange || handleChange,
|
|
268
266
|
};
|
|
269
267
|
};
|
package/src/util/combinators.ts
CHANGED
|
@@ -56,7 +56,9 @@ export const createCombinatorRenderInfos = (
|
|
|
56
56
|
uischemas: JsonFormsUISchemaRegistryEntry[]
|
|
57
57
|
): CombinatorSubSchemaRenderInfo[] =>
|
|
58
58
|
combinatorSubSchemas.map((subSchema, subSchemaIndex) => {
|
|
59
|
-
const schema = subSchema.$ref
|
|
59
|
+
const schema = subSchema.$ref
|
|
60
|
+
? Resolve.schema(rootSchema, subSchema.$ref, rootSchema)
|
|
61
|
+
: subSchema;
|
|
60
62
|
return {
|
|
61
63
|
schema,
|
|
62
64
|
uischema: findUISchema(
|
|
@@ -68,6 +70,6 @@ export const createCombinatorRenderInfos = (
|
|
|
68
70
|
control,
|
|
69
71
|
rootSchema
|
|
70
72
|
),
|
|
71
|
-
label: createLabel(subSchema, subSchemaIndex, keyword)
|
|
72
|
-
}
|
|
73
|
+
label: createLabel(subSchema, subSchemaIndex, keyword),
|
|
74
|
+
};
|
|
73
75
|
});
|
package/src/util/label.ts
CHANGED