@jsonforms/core 3.1.0-alpha.1 → 3.1.0-alpha.3
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 +436 -262
- package/lib/jsonforms-core.cjs.js.map +1 -1
- package/lib/jsonforms-core.esm.js +318 -201
- 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/lib/util/schema.d.ts +5 -0
- 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 +119 -75
- 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 +202 -148
- 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 +10 -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/reducers/core.ts
CHANGED
|
@@ -43,12 +43,15 @@ import {
|
|
|
43
43
|
UPDATE_DATA,
|
|
44
44
|
UPDATE_ERRORS,
|
|
45
45
|
UPDATE_CORE,
|
|
46
|
-
UpdateCoreAction
|
|
46
|
+
UpdateCoreAction,
|
|
47
47
|
} from '../actions';
|
|
48
|
-
import { createAjv, Reducer } from '../util';
|
|
48
|
+
import { createAjv, isOneOfEnumSchema, Reducer } from '../util';
|
|
49
49
|
import type { JsonSchema, UISchemaElement } from '../models';
|
|
50
50
|
|
|
51
|
-
export const validate = (
|
|
51
|
+
export const validate = (
|
|
52
|
+
validator: ValidateFunction | undefined,
|
|
53
|
+
data: any
|
|
54
|
+
): ErrorObject[] => {
|
|
52
55
|
if (validator === undefined) {
|
|
53
56
|
return [];
|
|
54
57
|
}
|
|
@@ -59,7 +62,10 @@ export const validate = (validator: ValidateFunction | undefined, data: any): Er
|
|
|
59
62
|
return validator.errors;
|
|
60
63
|
};
|
|
61
64
|
|
|
62
|
-
export type ValidationMode =
|
|
65
|
+
export type ValidationMode =
|
|
66
|
+
| 'ValidateAndShow'
|
|
67
|
+
| 'ValidateAndHide'
|
|
68
|
+
| 'NoValidation';
|
|
63
69
|
|
|
64
70
|
export interface JsonFormsCore {
|
|
65
71
|
data: any;
|
|
@@ -80,7 +86,7 @@ const initState: JsonFormsCore = {
|
|
|
80
86
|
validator: undefined,
|
|
81
87
|
ajv: undefined,
|
|
82
88
|
validationMode: 'ValidateAndShow',
|
|
83
|
-
additionalErrors: []
|
|
89
|
+
additionalErrors: [],
|
|
84
90
|
};
|
|
85
91
|
|
|
86
92
|
const reuseAjvForSchema = (ajv: Ajv, schema: JsonSchema): Ajv => {
|
|
@@ -90,14 +96,15 @@ const reuseAjvForSchema = (ajv: Ajv, schema: JsonSchema): Ajv => {
|
|
|
90
96
|
return ajv;
|
|
91
97
|
};
|
|
92
98
|
|
|
93
|
-
const getOrCreateAjv = (
|
|
99
|
+
const getOrCreateAjv = (
|
|
100
|
+
state: JsonFormsCore,
|
|
101
|
+
action?: InitAction | UpdateCoreAction
|
|
102
|
+
): Ajv => {
|
|
94
103
|
if (action) {
|
|
95
104
|
if (hasAjvOption(action.options)) {
|
|
96
105
|
// options object with ajv
|
|
97
106
|
return action.options.ajv;
|
|
98
|
-
} else if (
|
|
99
|
-
action.options !== undefined
|
|
100
|
-
) {
|
|
107
|
+
} else if (action.options !== undefined) {
|
|
101
108
|
// it is not an option object => should be ajv itself => check for compile function
|
|
102
109
|
if (isFunction(action.options.compile)) {
|
|
103
110
|
return action.options;
|
|
@@ -136,7 +143,9 @@ const hasValidationModeOption = (option: any): option is InitActionOptions => {
|
|
|
136
143
|
return false;
|
|
137
144
|
};
|
|
138
145
|
|
|
139
|
-
const hasAdditionalErrorsOption = (
|
|
146
|
+
const hasAdditionalErrorsOption = (
|
|
147
|
+
option: any
|
|
148
|
+
): option is InitActionOptions => {
|
|
140
149
|
if (option) {
|
|
141
150
|
return option.additionalErrors !== undefined;
|
|
142
151
|
}
|
|
@@ -153,7 +162,6 @@ const getAdditionalErrors = (
|
|
|
153
162
|
return state.additionalErrors;
|
|
154
163
|
};
|
|
155
164
|
|
|
156
|
-
// tslint:disable-next-line: cyclomatic-complexity
|
|
157
165
|
export const coreReducer: Reducer<JsonFormsCore, CoreActions> = (
|
|
158
166
|
state = initState,
|
|
159
167
|
action
|
|
@@ -163,7 +171,10 @@ export const coreReducer: Reducer<JsonFormsCore, CoreActions> = (
|
|
|
163
171
|
const thisAjv = getOrCreateAjv(state, action);
|
|
164
172
|
|
|
165
173
|
const validationMode = getValidationMode(state, action);
|
|
166
|
-
const v =
|
|
174
|
+
const v =
|
|
175
|
+
validationMode === 'NoValidation'
|
|
176
|
+
? undefined
|
|
177
|
+
: thisAjv.compile(action.schema);
|
|
167
178
|
const e = validate(v, action.data);
|
|
168
179
|
const additionalErrors = getAdditionalErrors(state, action);
|
|
169
180
|
|
|
@@ -208,7 +219,7 @@ export const coreReducer: Reducer<JsonFormsCore, CoreActions> = (
|
|
|
208
219
|
state.errors !== errors ||
|
|
209
220
|
state.validator !== validator ||
|
|
210
221
|
state.validationMode !== validationMode ||
|
|
211
|
-
state.additionalErrors !== additionalErrors
|
|
222
|
+
state.additionalErrors !== additionalErrors;
|
|
212
223
|
return stateChanged
|
|
213
224
|
? {
|
|
214
225
|
...state,
|
|
@@ -219,22 +230,26 @@ export const coreReducer: Reducer<JsonFormsCore, CoreActions> = (
|
|
|
219
230
|
errors: isEqual(errors, state.errors) ? state.errors : errors,
|
|
220
231
|
validator: validator,
|
|
221
232
|
validationMode: validationMode,
|
|
222
|
-
additionalErrors
|
|
233
|
+
additionalErrors,
|
|
223
234
|
}
|
|
224
235
|
: state;
|
|
225
236
|
}
|
|
226
237
|
case SET_AJV: {
|
|
227
238
|
const currentAjv = action.ajv;
|
|
228
|
-
const validator =
|
|
239
|
+
const validator =
|
|
240
|
+
state.validationMode === 'NoValidation'
|
|
241
|
+
? undefined
|
|
242
|
+
: currentAjv.compile(state.schema);
|
|
229
243
|
const errors = validate(validator, state.data);
|
|
230
244
|
return {
|
|
231
245
|
...state,
|
|
232
246
|
validator,
|
|
233
|
-
errors
|
|
247
|
+
errors,
|
|
234
248
|
};
|
|
235
249
|
}
|
|
236
250
|
case SET_SCHEMA: {
|
|
237
|
-
const needsNewValidator =
|
|
251
|
+
const needsNewValidator =
|
|
252
|
+
action.schema && state.ajv && state.validationMode !== 'NoValidation';
|
|
238
253
|
const v = needsNewValidator
|
|
239
254
|
? reuseAjvForSchema(state.ajv, action.schema).compile(action.schema)
|
|
240
255
|
: state.validator;
|
|
@@ -243,13 +258,13 @@ export const coreReducer: Reducer<JsonFormsCore, CoreActions> = (
|
|
|
243
258
|
...state,
|
|
244
259
|
validator: v,
|
|
245
260
|
schema: action.schema,
|
|
246
|
-
errors
|
|
261
|
+
errors,
|
|
247
262
|
};
|
|
248
263
|
}
|
|
249
264
|
case SET_UISCHEMA: {
|
|
250
265
|
return {
|
|
251
266
|
...state,
|
|
252
|
-
uischema: action.uischema
|
|
267
|
+
uischema: action.uischema,
|
|
253
268
|
};
|
|
254
269
|
}
|
|
255
270
|
case UPDATE_DATA: {
|
|
@@ -262,7 +277,7 @@ export const coreReducer: Reducer<JsonFormsCore, CoreActions> = (
|
|
|
262
277
|
return {
|
|
263
278
|
...state,
|
|
264
279
|
data: result,
|
|
265
|
-
errors
|
|
280
|
+
errors,
|
|
266
281
|
};
|
|
267
282
|
} else {
|
|
268
283
|
const oldData: any = get(state.data, action.path);
|
|
@@ -276,14 +291,14 @@ export const coreReducer: Reducer<JsonFormsCore, CoreActions> = (
|
|
|
276
291
|
return {
|
|
277
292
|
...state,
|
|
278
293
|
data: newState,
|
|
279
|
-
errors
|
|
294
|
+
errors,
|
|
280
295
|
};
|
|
281
296
|
}
|
|
282
297
|
}
|
|
283
298
|
case UPDATE_ERRORS: {
|
|
284
299
|
return {
|
|
285
300
|
...state,
|
|
286
|
-
errors: action.errors
|
|
301
|
+
errors: action.errors,
|
|
287
302
|
};
|
|
288
303
|
}
|
|
289
304
|
case SET_VALIDATION_MODE: {
|
|
@@ -295,22 +310,24 @@ export const coreReducer: Reducer<JsonFormsCore, CoreActions> = (
|
|
|
295
310
|
return {
|
|
296
311
|
...state,
|
|
297
312
|
errors,
|
|
298
|
-
validationMode: action.validationMode
|
|
313
|
+
validationMode: action.validationMode,
|
|
299
314
|
};
|
|
300
315
|
}
|
|
301
316
|
if (state.validationMode === 'NoValidation') {
|
|
302
|
-
const validator = reuseAjvForSchema(state.ajv, state.schema).compile(
|
|
317
|
+
const validator = reuseAjvForSchema(state.ajv, state.schema).compile(
|
|
318
|
+
state.schema
|
|
319
|
+
);
|
|
303
320
|
const errors = validate(validator, state.data);
|
|
304
321
|
return {
|
|
305
322
|
...state,
|
|
306
323
|
validator,
|
|
307
324
|
errors,
|
|
308
|
-
validationMode: action.validationMode
|
|
325
|
+
validationMode: action.validationMode,
|
|
309
326
|
};
|
|
310
327
|
}
|
|
311
328
|
return {
|
|
312
329
|
...state,
|
|
313
|
-
validationMode: action.validationMode
|
|
330
|
+
validationMode: action.validationMode,
|
|
314
331
|
};
|
|
315
332
|
}
|
|
316
333
|
default:
|
|
@@ -342,62 +359,72 @@ export const getControlPath = (error: ErrorObject) => {
|
|
|
342
359
|
return dataPath.replace(/\//g, '.').substr(1);
|
|
343
360
|
}
|
|
344
361
|
// dataPath was renamed to instancePath in AJV v8
|
|
345
|
-
|
|
362
|
+
let controlPath: string = error.instancePath;
|
|
346
363
|
|
|
347
364
|
// change '/' chars to '.'
|
|
348
365
|
controlPath = controlPath.replace(/\//g, '.');
|
|
349
|
-
|
|
366
|
+
|
|
350
367
|
const invalidProperty = getInvalidProperty(error);
|
|
351
368
|
if (invalidProperty !== undefined && !controlPath.endsWith(invalidProperty)) {
|
|
352
369
|
controlPath = `${controlPath}.${invalidProperty}`;
|
|
353
370
|
}
|
|
354
|
-
|
|
371
|
+
|
|
355
372
|
// remove '.' chars at the beginning of paths
|
|
356
373
|
controlPath = controlPath.replace(/^./, '');
|
|
357
374
|
return controlPath;
|
|
358
|
-
}
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
export const errorsAt =
|
|
378
|
+
(
|
|
379
|
+
instancePath: string,
|
|
380
|
+
schema: JsonSchema,
|
|
381
|
+
matchPath: (path: string) => boolean
|
|
382
|
+
) =>
|
|
383
|
+
(errors: ErrorObject[]): ErrorObject[] => {
|
|
384
|
+
// Get data paths of oneOf and anyOf errors to later determine whether an error occurred inside a subschema of oneOf or anyOf.
|
|
385
|
+
const combinatorPaths = filter(
|
|
386
|
+
errors,
|
|
387
|
+
(error) => error.keyword === 'oneOf' || error.keyword === 'anyOf'
|
|
388
|
+
).map((error) => getControlPath(error));
|
|
359
389
|
|
|
360
|
-
|
|
361
|
-
instancePath: string,
|
|
362
|
-
schema: JsonSchema,
|
|
363
|
-
matchPath: (path: string) => boolean
|
|
364
|
-
) => (errors: ErrorObject[]): ErrorObject[] => {
|
|
365
|
-
// Get data paths of oneOf and anyOf errors to later determine whether an error occurred inside a subschema of oneOf or anyOf.
|
|
366
|
-
const combinatorPaths = filter(
|
|
367
|
-
errors,
|
|
368
|
-
error => error.keyword === 'oneOf' || error.keyword === 'anyOf'
|
|
369
|
-
).map(error => getControlPath(error));
|
|
370
|
-
|
|
371
|
-
return filter(errors, error => {
|
|
390
|
+
return filter(errors, (error) => {
|
|
372
391
|
// Filter errors that match any keyword that we don't want to show in the UI
|
|
373
|
-
|
|
392
|
+
// but keep the errors for oneOf enums
|
|
393
|
+
if (
|
|
394
|
+
filteredErrorKeywords.indexOf(error.keyword) !== -1 &&
|
|
395
|
+
!isOneOfEnumSchema(error.parentSchema)
|
|
396
|
+
) {
|
|
374
397
|
return false;
|
|
375
398
|
}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
399
|
+
const controlPath = getControlPath(error);
|
|
400
|
+
let result = matchPath(controlPath);
|
|
401
|
+
// In anyOf and oneOf blocks with "primitive" (i.e. string, number etc.) or array subschemas,
|
|
402
|
+
// we want to make sure that errors are only shown for the correct subschema.
|
|
403
|
+
// Therefore, we compare the error's parent schema with the property's schema.
|
|
404
|
+
// In the primitive case the error's data path is the same for all subschemas:
|
|
405
|
+
// It directly points to the property defining the anyOf/oneOf.
|
|
406
|
+
// The same holds true for errors on the array level (e.g. min item amount).
|
|
407
|
+
// In contrast, this comparison must not be done for errors whose parent schema defines an object or a oneOf enum,
|
|
408
|
+
// because the parent schema can never match the property schema (e.g. for 'required' checks).
|
|
409
|
+
const parentSchema: JsonSchema | undefined = error.parentSchema;
|
|
410
|
+
if (
|
|
411
|
+
result &&
|
|
412
|
+
!isObjectSchema(parentSchema) &&
|
|
413
|
+
!isOneOfEnumSchema(parentSchema) &&
|
|
414
|
+
combinatorPaths.findIndex((p) => instancePath.startsWith(p)) !== -1
|
|
415
|
+
) {
|
|
416
|
+
result = result && isEqual(parentSchema, schema);
|
|
417
|
+
}
|
|
418
|
+
return result;
|
|
419
|
+
});
|
|
420
|
+
};
|
|
394
421
|
|
|
395
422
|
/**
|
|
396
423
|
* @returns true if the schema describes an object.
|
|
397
424
|
*/
|
|
398
425
|
const isObjectSchema = (schema?: JsonSchema): boolean => {
|
|
399
426
|
return schema?.type === 'object' || !!schema?.properties;
|
|
400
|
-
}
|
|
427
|
+
};
|
|
401
428
|
|
|
402
429
|
/**
|
|
403
430
|
* The error-type of an AJV error is defined by its `keyword` property.
|
|
@@ -410,19 +437,36 @@ const isObjectSchema = (schema?: JsonSchema): boolean => {
|
|
|
410
437
|
* - anyOf: Indicates that an anyOf definition itself is not valid because none of its subschemas matches.
|
|
411
438
|
* - oneOf: Indicates that an oneOf definition itself is not valid because not exactly one of its subschemas matches.
|
|
412
439
|
*/
|
|
413
|
-
const filteredErrorKeywords = [
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
440
|
+
const filteredErrorKeywords = [
|
|
441
|
+
'additionalProperties',
|
|
442
|
+
'allOf',
|
|
443
|
+
'anyOf',
|
|
444
|
+
'oneOf',
|
|
445
|
+
];
|
|
446
|
+
|
|
447
|
+
const getErrorsAt =
|
|
448
|
+
(
|
|
449
|
+
instancePath: string,
|
|
450
|
+
schema: JsonSchema,
|
|
451
|
+
matchPath: (path: string) => boolean
|
|
452
|
+
) =>
|
|
453
|
+
(state: JsonFormsCore): ErrorObject[] => {
|
|
454
|
+
const errors = state.errors ?? [];
|
|
455
|
+
const additionalErrors = state.additionalErrors ?? [];
|
|
456
|
+
return errorsAt(
|
|
457
|
+
instancePath,
|
|
458
|
+
schema,
|
|
459
|
+
matchPath
|
|
460
|
+
)(
|
|
461
|
+
state.validationMode === 'ValidateAndHide'
|
|
462
|
+
? additionalErrors
|
|
463
|
+
: [...errors, ...additionalErrors]
|
|
464
|
+
);
|
|
465
|
+
};
|
|
424
466
|
|
|
425
467
|
export const errorAt = (instancePath: string, schema: JsonSchema) =>
|
|
426
|
-
getErrorsAt(instancePath, schema, path => path === instancePath);
|
|
468
|
+
getErrorsAt(instancePath, schema, (path) => path === instancePath);
|
|
427
469
|
export const subErrorsAt = (instancePath: string, schema: JsonSchema) =>
|
|
428
|
-
getErrorsAt(instancePath, schema, path =>
|
|
470
|
+
getErrorsAt(instancePath, schema, (path) =>
|
|
471
|
+
path.startsWith(instancePath + '.')
|
|
472
|
+
);
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
ADD_DEFAULT_DATA,
|
|
28
28
|
RegisterDefaultDataAction,
|
|
29
29
|
REMOVE_DEFAULT_DATA,
|
|
30
|
-
UnregisterDefaultDataAction
|
|
30
|
+
UnregisterDefaultDataAction,
|
|
31
31
|
} from '../actions';
|
|
32
32
|
import type { Reducer } from '../util';
|
|
33
33
|
|
|
@@ -40,17 +40,17 @@ type ValidDefaultDataActions =
|
|
|
40
40
|
| RegisterDefaultDataAction
|
|
41
41
|
| UnregisterDefaultDataAction;
|
|
42
42
|
|
|
43
|
-
export const defaultDataReducer: Reducer<
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
) => {
|
|
43
|
+
export const defaultDataReducer: Reducer<
|
|
44
|
+
JsonFormsDefaultDataRegistryEntry[],
|
|
45
|
+
ValidDefaultDataActions
|
|
46
|
+
> = (state = [], action) => {
|
|
47
47
|
switch (action.type) {
|
|
48
48
|
case ADD_DEFAULT_DATA:
|
|
49
49
|
return state.concat([
|
|
50
|
-
{ schemaPath: action.schemaPath, data: action.data }
|
|
50
|
+
{ schemaPath: action.schemaPath, data: action.data },
|
|
51
51
|
]);
|
|
52
52
|
case REMOVE_DEFAULT_DATA:
|
|
53
|
-
return state.filter(t => t.schemaPath !== action.schemaPath);
|
|
53
|
+
return state.filter((t) => t.schemaPath !== action.schemaPath);
|
|
54
54
|
default:
|
|
55
55
|
return state;
|
|
56
56
|
}
|
package/src/reducers/i18n.ts
CHANGED
|
@@ -23,17 +23,29 @@
|
|
|
23
23
|
THE SOFTWARE.
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
-
import {
|
|
27
|
-
|
|
26
|
+
import {
|
|
27
|
+
defaultErrorTranslator,
|
|
28
|
+
defaultTranslator,
|
|
29
|
+
JsonFormsI18nState,
|
|
30
|
+
} from '../i18n';
|
|
31
|
+
import {
|
|
32
|
+
I18nActions,
|
|
33
|
+
SET_LOCALE,
|
|
34
|
+
SET_TRANSLATOR,
|
|
35
|
+
UPDATE_I18N,
|
|
36
|
+
} from '../actions';
|
|
28
37
|
import type { Reducer } from '../util';
|
|
29
38
|
|
|
30
39
|
export const defaultJsonFormsI18nState: Required<JsonFormsI18nState> = {
|
|
31
40
|
locale: 'en',
|
|
32
41
|
translate: defaultTranslator,
|
|
33
|
-
translateError: defaultErrorTranslator
|
|
42
|
+
translateError: defaultErrorTranslator,
|
|
34
43
|
};
|
|
35
44
|
|
|
36
|
-
export const i18nReducer: Reducer<JsonFormsI18nState, I18nActions> = (
|
|
45
|
+
export const i18nReducer: Reducer<JsonFormsI18nState, I18nActions> = (
|
|
46
|
+
state = defaultJsonFormsI18nState,
|
|
47
|
+
action
|
|
48
|
+
) => {
|
|
37
49
|
switch (action.type) {
|
|
38
50
|
case UPDATE_I18N: {
|
|
39
51
|
const locale = action.locale ?? defaultJsonFormsI18nState.locale;
|
|
@@ -51,7 +63,7 @@ export const i18nReducer: Reducer<JsonFormsI18nState, I18nActions> = (state = de
|
|
|
51
63
|
...state,
|
|
52
64
|
locale,
|
|
53
65
|
translate,
|
|
54
|
-
translateError
|
|
66
|
+
translateError,
|
|
55
67
|
};
|
|
56
68
|
}
|
|
57
69
|
return state;
|
|
@@ -60,12 +72,12 @@ export const i18nReducer: Reducer<JsonFormsI18nState, I18nActions> = (state = de
|
|
|
60
72
|
return {
|
|
61
73
|
...state,
|
|
62
74
|
translate: action.translator ?? defaultTranslator,
|
|
63
|
-
translateError: action.errorTranslator ?? defaultErrorTranslator
|
|
75
|
+
translateError: action.errorTranslator ?? defaultErrorTranslator,
|
|
64
76
|
};
|
|
65
77
|
case SET_LOCALE:
|
|
66
78
|
return {
|
|
67
79
|
...state,
|
|
68
|
-
locale: action.locale ?? navigator.languages[0]
|
|
80
|
+
locale: action.locale ?? navigator.languages[0],
|
|
69
81
|
};
|
|
70
82
|
default:
|
|
71
83
|
return state;
|
|
@@ -84,11 +96,11 @@ export const fetchTranslator = (state?: JsonFormsI18nState) => {
|
|
|
84
96
|
return defaultTranslator;
|
|
85
97
|
}
|
|
86
98
|
return state.translate;
|
|
87
|
-
}
|
|
99
|
+
};
|
|
88
100
|
|
|
89
101
|
export const fetchErrorTranslator = (state?: JsonFormsI18nState) => {
|
|
90
102
|
if (state === undefined) {
|
|
91
103
|
return defaultErrorTranslator;
|
|
92
104
|
}
|
|
93
105
|
return state.translateError;
|
|
94
|
-
}
|
|
106
|
+
};
|
package/src/reducers/reducers.ts
CHANGED
|
@@ -24,24 +24,13 @@
|
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
26
|
import type { ControlElement, UISchemaElement } from '../models';
|
|
27
|
-
import {
|
|
28
|
-
coreReducer,
|
|
29
|
-
errorAt,
|
|
30
|
-
subErrorsAt,
|
|
31
|
-
} from './core';
|
|
27
|
+
import { coreReducer, errorAt, subErrorsAt } from './core';
|
|
32
28
|
import { defaultDataReducer } from './default-data';
|
|
33
29
|
import { rendererReducer } from './renderers';
|
|
34
30
|
import type { JsonFormsState } from '../store';
|
|
35
31
|
import type { JsonFormsUISchemaRegistryEntry } from './uischemas';
|
|
36
|
-
import {
|
|
37
|
-
|
|
38
|
-
uischemaRegistryReducer,
|
|
39
|
-
} from './uischemas';
|
|
40
|
-
import {
|
|
41
|
-
fetchErrorTranslator,
|
|
42
|
-
fetchLocale,
|
|
43
|
-
i18nReducer,
|
|
44
|
-
} from './i18n';
|
|
32
|
+
import { findMatchingUISchema, uischemaRegistryReducer } from './uischemas';
|
|
33
|
+
import { fetchErrorTranslator, fetchLocale, i18nReducer } from './i18n';
|
|
45
34
|
|
|
46
35
|
import { Generate } from '../generators';
|
|
47
36
|
import type { JsonSchema } from '../models/jsonSchema';
|
|
@@ -84,7 +73,7 @@ export const findUISchema = (
|
|
|
84
73
|
if (typeof control.options.detail === 'string') {
|
|
85
74
|
if (control.options.detail.toUpperCase() === 'GENERATE') {
|
|
86
75
|
//use fallback generation function
|
|
87
|
-
if(typeof fallback ===
|
|
76
|
+
if (typeof fallback === 'function') {
|
|
88
77
|
return fallback();
|
|
89
78
|
}
|
|
90
79
|
// force generation of uischema
|
|
@@ -104,7 +93,7 @@ export const findUISchema = (
|
|
|
104
93
|
const uiSchema = findMatchingUISchema(uischemas)(schema, schemaPath, path);
|
|
105
94
|
if (uiSchema === undefined) {
|
|
106
95
|
//use fallback generation function
|
|
107
|
-
if(typeof fallback === 'function'){
|
|
96
|
+
if (typeof fallback === 'function') {
|
|
108
97
|
return fallback();
|
|
109
98
|
}
|
|
110
99
|
return Generate.uiSchema(schema, fallback, '#', rootSchema);
|
|
@@ -112,25 +101,26 @@ export const findUISchema = (
|
|
|
112
101
|
return uiSchema;
|
|
113
102
|
};
|
|
114
103
|
|
|
115
|
-
export const getErrorAt =
|
|
116
|
-
state: JsonFormsState
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
};
|
|
104
|
+
export const getErrorAt =
|
|
105
|
+
(instancePath: string, schema: JsonSchema) => (state: JsonFormsState) => {
|
|
106
|
+
return errorAt(instancePath, schema)(state.jsonforms.core);
|
|
107
|
+
};
|
|
120
108
|
|
|
121
|
-
export const getSubErrorsAt =
|
|
122
|
-
state: JsonFormsState
|
|
123
|
-
|
|
109
|
+
export const getSubErrorsAt =
|
|
110
|
+
(instancePath: string, schema: JsonSchema) => (state: JsonFormsState) =>
|
|
111
|
+
subErrorsAt(instancePath, schema)(state.jsonforms.core);
|
|
124
112
|
|
|
125
113
|
export const getConfig = (state: JsonFormsState) => state.jsonforms.config;
|
|
126
114
|
|
|
127
115
|
export const getLocale = (state: JsonFormsState) =>
|
|
128
116
|
fetchLocale(get(state, 'jsonforms.i18n'));
|
|
129
117
|
|
|
130
|
-
export const getTranslator =
|
|
131
|
-
|
|
132
|
-
): Translator =>
|
|
118
|
+
export const getTranslator =
|
|
119
|
+
() =>
|
|
120
|
+
(state: JsonFormsState): Translator =>
|
|
121
|
+
fetchTranslator(get(state, 'jsonforms.i18n'));
|
|
133
122
|
|
|
134
|
-
export const getErrorTranslator =
|
|
135
|
-
|
|
136
|
-
): ErrorTranslator =>
|
|
123
|
+
export const getErrorTranslator =
|
|
124
|
+
() =>
|
|
125
|
+
(state: JsonFormsState): ErrorTranslator =>
|
|
126
|
+
fetchErrorTranslator(get(state, 'jsonforms.i18n'));
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
ADD_RENDERER,
|
|
29
29
|
AddRendererAction,
|
|
30
30
|
REMOVE_RENDERER,
|
|
31
|
-
RemoveRendererAction
|
|
31
|
+
RemoveRendererAction,
|
|
32
32
|
} from '../actions';
|
|
33
33
|
import type { Reducer } from '../util';
|
|
34
34
|
|
|
@@ -39,17 +39,17 @@ export interface JsonFormsRendererRegistryEntry {
|
|
|
39
39
|
|
|
40
40
|
type ValidRendererReducerActions = AddRendererAction | RemoveRendererAction;
|
|
41
41
|
|
|
42
|
-
export const rendererReducer: Reducer<
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
) => {
|
|
42
|
+
export const rendererReducer: Reducer<
|
|
43
|
+
JsonFormsRendererRegistryEntry[],
|
|
44
|
+
ValidRendererReducerActions
|
|
45
|
+
> = (state = [], action) => {
|
|
46
46
|
switch (action.type) {
|
|
47
47
|
case ADD_RENDERER:
|
|
48
48
|
return state.concat([
|
|
49
|
-
{ tester: action.tester, renderer: action.renderer }
|
|
49
|
+
{ tester: action.tester, renderer: action.renderer },
|
|
50
50
|
]);
|
|
51
51
|
case REMOVE_RENDERER:
|
|
52
|
-
return state.filter(t => t.tester !== action.tester);
|
|
52
|
+
return state.filter((t) => t.tester !== action.tester);
|
|
53
53
|
default:
|
|
54
54
|
return state;
|
|
55
55
|
}
|
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
} from './core';
|
|
36
36
|
import {
|
|
37
37
|
extractDefaultData,
|
|
38
|
-
JsonFormsDefaultDataRegistryEntry
|
|
38
|
+
JsonFormsDefaultDataRegistryEntry,
|
|
39
39
|
} from './default-data';
|
|
40
40
|
import type { JsonFormsRendererRegistryEntry } from './renderers';
|
|
41
41
|
import type { JsonFormsCellRendererRegistryEntry } from './cells';
|
|
@@ -47,9 +47,8 @@ export const getSchema = (state: JsonFormsState): JsonSchema =>
|
|
|
47
47
|
extractSchema(get(state, 'jsonforms.core'));
|
|
48
48
|
export const getUiSchema = (state: JsonFormsState): UISchemaElement =>
|
|
49
49
|
extractUiSchema(get(state, 'jsonforms.core'));
|
|
50
|
-
export const getAjv = (
|
|
51
|
-
state
|
|
52
|
-
): Ajv => extractAjv(get(state, 'jsonforms.core'));
|
|
50
|
+
export const getAjv = (state: JsonFormsState): Ajv =>
|
|
51
|
+
extractAjv(get(state, 'jsonforms.core'));
|
|
53
52
|
export const getDefaultData = (
|
|
54
53
|
state: JsonFormsState
|
|
55
54
|
): JsonFormsDefaultDataRegistryEntry[] =>
|
|
@@ -62,4 +61,4 @@ export const getCells = (
|
|
|
62
61
|
): JsonFormsCellRendererRegistryEntry[] => get(state, 'jsonforms.cells');
|
|
63
62
|
export const getUISchemas = (
|
|
64
63
|
state: JsonFormsState
|
|
65
|
-
): JsonFormsUISchemaRegistryEntry[] => get(state, 'jsonforms.uischemas')
|
|
64
|
+
): JsonFormsUISchemaRegistryEntry[] => get(state, 'jsonforms.uischemas');
|
|
@@ -41,39 +41,40 @@ export interface JsonFormsUISchemaRegistryEntry {
|
|
|
41
41
|
uischema: UISchemaElement;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
export const uischemaRegistryReducer: Reducer<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
) => {
|
|
44
|
+
export const uischemaRegistryReducer: Reducer<
|
|
45
|
+
JsonFormsUISchemaRegistryEntry[],
|
|
46
|
+
UISchemaActions
|
|
47
|
+
> = (state = [], action) => {
|
|
48
48
|
switch (action.type) {
|
|
49
49
|
case ADD_UI_SCHEMA:
|
|
50
50
|
return state
|
|
51
51
|
.slice()
|
|
52
52
|
.concat({ tester: action.tester, uischema: action.uischema });
|
|
53
|
-
case REMOVE_UI_SCHEMA:
|
|
53
|
+
case REMOVE_UI_SCHEMA: {
|
|
54
54
|
const copy = state.slice();
|
|
55
|
-
remove(copy, entry => entry.tester === action.tester);
|
|
55
|
+
remove(copy, (entry) => entry.tester === action.tester);
|
|
56
56
|
return copy;
|
|
57
|
+
}
|
|
57
58
|
default:
|
|
58
59
|
return state;
|
|
59
60
|
}
|
|
60
61
|
};
|
|
61
62
|
|
|
62
|
-
export const findMatchingUISchema =
|
|
63
|
-
state: JsonFormsUISchemaRegistryEntry[]
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
): UISchemaElement => {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
};
|
|
63
|
+
export const findMatchingUISchema =
|
|
64
|
+
(state: JsonFormsUISchemaRegistryEntry[]) =>
|
|
65
|
+
(
|
|
66
|
+
jsonSchema: JsonSchema,
|
|
67
|
+
schemaPath: string,
|
|
68
|
+
path: string
|
|
69
|
+
): UISchemaElement => {
|
|
70
|
+
const match = maxBy(state, (entry) =>
|
|
71
|
+
entry.tester(jsonSchema, schemaPath, path)
|
|
72
|
+
);
|
|
73
|
+
if (
|
|
74
|
+
match !== undefined &&
|
|
75
|
+
match.tester(jsonSchema, schemaPath, path) !== NOT_APPLICABLE
|
|
76
|
+
) {
|
|
77
|
+
return match.uischema;
|
|
78
|
+
}
|
|
79
|
+
return undefined;
|
|
80
|
+
};
|