@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/i18n/i18nUtil.ts
CHANGED
|
@@ -3,6 +3,10 @@ import { isInternationalized, Labelable, UISchemaElement } from '../models';
|
|
|
3
3
|
import { getControlPath } from '../reducers';
|
|
4
4
|
import { formatErrorMessage } from '../util';
|
|
5
5
|
import type { i18nJsonSchema, ErrorTranslator, Translator } from './i18nTypes';
|
|
6
|
+
import {
|
|
7
|
+
ArrayDefaultTranslation,
|
|
8
|
+
ArrayTranslations,
|
|
9
|
+
} from './arrayTranslations';
|
|
6
10
|
|
|
7
11
|
export const getI18nKeyPrefixBySchema = (
|
|
8
12
|
schema: i18nJsonSchema | undefined,
|
|
@@ -22,7 +26,7 @@ export const transformPathToI18nPrefix = (path: string): string => {
|
|
|
22
26
|
return (
|
|
23
27
|
path
|
|
24
28
|
?.split('.')
|
|
25
|
-
.filter(segment => !/^\d+$/.test(segment))
|
|
29
|
+
.filter((segment) => !/^\d+$/.test(segment))
|
|
26
30
|
.join('.') || 'root'
|
|
27
31
|
);
|
|
28
32
|
};
|
|
@@ -47,7 +51,17 @@ export const getI18nKey = (
|
|
|
47
51
|
return `${getI18nKeyPrefix(schema, uischema, path)}.${key}`;
|
|
48
52
|
};
|
|
49
53
|
|
|
50
|
-
export const
|
|
54
|
+
export const addI18nKeyToPrefix = (
|
|
55
|
+
i18nKeyPrefix: string,
|
|
56
|
+
key: string
|
|
57
|
+
): string => {
|
|
58
|
+
return `${i18nKeyPrefix}.${key}`;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const defaultTranslator: Translator = (
|
|
62
|
+
_id: string,
|
|
63
|
+
defaultMessage: string | undefined
|
|
64
|
+
) => defaultMessage;
|
|
51
65
|
|
|
52
66
|
export const defaultErrorTranslator: ErrorTranslator = (error, t, uischema) => {
|
|
53
67
|
// check whether there is a special keyword message
|
|
@@ -57,13 +71,15 @@ export const defaultErrorTranslator: ErrorTranslator = (error, t, uischema) => {
|
|
|
57
71
|
getControlPath(error),
|
|
58
72
|
`error.${error.keyword}`
|
|
59
73
|
);
|
|
60
|
-
const specializedKeywordMessage = t(i18nKey, undefined, { error }
|
|
74
|
+
const specializedKeywordMessage = t(i18nKey, undefined, { error });
|
|
61
75
|
if (specializedKeywordMessage !== undefined) {
|
|
62
76
|
return specializedKeywordMessage;
|
|
63
77
|
}
|
|
64
78
|
|
|
65
79
|
// check whether there is a generic keyword message
|
|
66
|
-
const genericKeywordMessage = t(`error.${error.keyword}`, undefined, {
|
|
80
|
+
const genericKeywordMessage = t(`error.${error.keyword}`, undefined, {
|
|
81
|
+
error,
|
|
82
|
+
});
|
|
67
83
|
if (genericKeywordMessage !== undefined) {
|
|
68
84
|
return genericKeywordMessage;
|
|
69
85
|
}
|
|
@@ -75,7 +91,10 @@ export const defaultErrorTranslator: ErrorTranslator = (error, t, uischema) => {
|
|
|
75
91
|
}
|
|
76
92
|
|
|
77
93
|
// rewrite required property messages (if they were not customized) as we place them next to the respective input
|
|
78
|
-
if (
|
|
94
|
+
if (
|
|
95
|
+
error.keyword === 'required' &&
|
|
96
|
+
error.message?.startsWith('must have required property')
|
|
97
|
+
) {
|
|
79
98
|
return t('is a required property', 'is a required property', { error });
|
|
80
99
|
}
|
|
81
100
|
|
|
@@ -97,29 +116,60 @@ export const getCombinedErrorMessage = (
|
|
|
97
116
|
if (errors.length > 0 && t) {
|
|
98
117
|
// check whether there is a special message which overwrites all others
|
|
99
118
|
const customErrorKey = getI18nKey(schema, uischema, path, 'error.custom');
|
|
100
|
-
const specializedErrorMessage = t(customErrorKey, undefined, {
|
|
119
|
+
const specializedErrorMessage = t(customErrorKey, undefined, {
|
|
120
|
+
schema,
|
|
121
|
+
uischema,
|
|
122
|
+
path,
|
|
123
|
+
errors,
|
|
124
|
+
});
|
|
101
125
|
if (specializedErrorMessage !== undefined) {
|
|
102
126
|
return specializedErrorMessage;
|
|
103
127
|
}
|
|
104
128
|
}
|
|
105
|
-
return formatErrorMessage(
|
|
106
|
-
errors.map(error => et(error, t, uischema))
|
|
107
|
-
);
|
|
129
|
+
return formatErrorMessage(errors.map((error) => et(error, t, uischema)));
|
|
108
130
|
};
|
|
109
131
|
|
|
110
132
|
/**
|
|
111
133
|
* This can be used to internationalize the label of the given Labelable (e.g. UI Schema elements).
|
|
112
134
|
* This should not be used for controls as there we have additional context in the form of the JSON Schema available.
|
|
113
135
|
*/
|
|
114
|
-
export const deriveLabelForUISchemaElement = (
|
|
136
|
+
export const deriveLabelForUISchemaElement = (
|
|
137
|
+
uischema: Labelable<boolean>,
|
|
138
|
+
t: Translator
|
|
139
|
+
): string | undefined => {
|
|
115
140
|
if (uischema.label === false) {
|
|
116
141
|
return undefined;
|
|
117
142
|
}
|
|
118
|
-
if (
|
|
143
|
+
if (
|
|
144
|
+
(uischema.label === undefined ||
|
|
145
|
+
uischema.label === null ||
|
|
146
|
+
uischema.label === true) &&
|
|
147
|
+
!isInternationalized(uischema)
|
|
148
|
+
) {
|
|
119
149
|
return undefined;
|
|
120
150
|
}
|
|
121
|
-
const stringifiedLabel =
|
|
151
|
+
const stringifiedLabel =
|
|
152
|
+
typeof uischema.label === 'string'
|
|
153
|
+
? uischema.label
|
|
154
|
+
: JSON.stringify(uischema.label);
|
|
122
155
|
const i18nKeyPrefix = getI18nKeyPrefixBySchema(undefined, uischema);
|
|
123
|
-
const i18nKey =
|
|
156
|
+
const i18nKey =
|
|
157
|
+
typeof i18nKeyPrefix === 'string'
|
|
158
|
+
? `${i18nKeyPrefix}.label`
|
|
159
|
+
: stringifiedLabel;
|
|
124
160
|
return t(i18nKey, stringifiedLabel, { uischema: uischema });
|
|
125
|
-
}
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
export const getArrayTranslations = (
|
|
164
|
+
t: Translator,
|
|
165
|
+
defaultTranslations: ArrayDefaultTranslation[],
|
|
166
|
+
i18nKeyPrefix: string,
|
|
167
|
+
label: string
|
|
168
|
+
): ArrayTranslations => {
|
|
169
|
+
const translations: ArrayTranslations = {};
|
|
170
|
+
defaultTranslations.forEach((controlElement) => {
|
|
171
|
+
const key = addI18nKeyToPrefix(i18nKeyPrefix, controlElement.key);
|
|
172
|
+
translations[controlElement.key] = t(key, controlElement.default(label));
|
|
173
|
+
});
|
|
174
|
+
return translations;
|
|
175
|
+
};
|
package/src/i18n/index.ts
CHANGED
package/src/models/draft4.ts
CHANGED
|
@@ -31,14 +31,14 @@ export const Draft4 = {
|
|
|
31
31
|
schemaArray: {
|
|
32
32
|
type: 'array',
|
|
33
33
|
minItems: 1,
|
|
34
|
-
items: { $ref: '#' }
|
|
34
|
+
items: { $ref: '#' },
|
|
35
35
|
},
|
|
36
36
|
positiveInteger: {
|
|
37
37
|
type: 'integer',
|
|
38
|
-
minimum: 0
|
|
38
|
+
minimum: 0,
|
|
39
39
|
},
|
|
40
40
|
positiveIntegerDefault0: {
|
|
41
|
-
allOf: [{ $ref: '#/definitions/positiveInteger' }, { default: 0 }]
|
|
41
|
+
allOf: [{ $ref: '#/definitions/positiveInteger' }, { default: 0 }],
|
|
42
42
|
},
|
|
43
43
|
simpleTypes: {
|
|
44
44
|
enum: [
|
|
@@ -48,104 +48,104 @@ export const Draft4 = {
|
|
|
48
48
|
'null',
|
|
49
49
|
'number',
|
|
50
50
|
'object',
|
|
51
|
-
'string'
|
|
52
|
-
]
|
|
51
|
+
'string',
|
|
52
|
+
],
|
|
53
53
|
},
|
|
54
54
|
stringArray: {
|
|
55
55
|
type: 'array',
|
|
56
56
|
items: { type: 'string' },
|
|
57
57
|
minItems: 1,
|
|
58
|
-
uniqueItems: true
|
|
59
|
-
}
|
|
58
|
+
uniqueItems: true,
|
|
59
|
+
},
|
|
60
60
|
},
|
|
61
61
|
type: 'object',
|
|
62
62
|
properties: {
|
|
63
63
|
id: {
|
|
64
64
|
type: 'string',
|
|
65
|
-
format: 'uri'
|
|
65
|
+
format: 'uri',
|
|
66
66
|
},
|
|
67
67
|
$schema: {
|
|
68
68
|
type: 'string',
|
|
69
|
-
format: 'uri'
|
|
69
|
+
format: 'uri',
|
|
70
70
|
},
|
|
71
71
|
title: {
|
|
72
|
-
type: 'string'
|
|
72
|
+
type: 'string',
|
|
73
73
|
},
|
|
74
74
|
description: {
|
|
75
|
-
type: 'string'
|
|
75
|
+
type: 'string',
|
|
76
76
|
},
|
|
77
77
|
default: {},
|
|
78
78
|
multipleOf: {
|
|
79
79
|
type: 'number',
|
|
80
80
|
minimum: 0,
|
|
81
|
-
exclusiveMinimum: true
|
|
81
|
+
exclusiveMinimum: true,
|
|
82
82
|
},
|
|
83
83
|
maximum: {
|
|
84
|
-
type: 'number'
|
|
84
|
+
type: 'number',
|
|
85
85
|
},
|
|
86
86
|
exclusiveMaximum: {
|
|
87
87
|
type: 'boolean',
|
|
88
|
-
default: false
|
|
88
|
+
default: false,
|
|
89
89
|
},
|
|
90
90
|
minimum: {
|
|
91
|
-
type: 'number'
|
|
91
|
+
type: 'number',
|
|
92
92
|
},
|
|
93
93
|
exclusiveMinimum: {
|
|
94
94
|
type: 'boolean',
|
|
95
|
-
default: false
|
|
95
|
+
default: false,
|
|
96
96
|
},
|
|
97
97
|
maxLength: { $ref: '#/definitions/positiveInteger' },
|
|
98
98
|
minLength: { $ref: '#/definitions/positiveIntegerDefault0' },
|
|
99
99
|
pattern: {
|
|
100
100
|
type: 'string',
|
|
101
|
-
format: 'regex'
|
|
101
|
+
format: 'regex',
|
|
102
102
|
},
|
|
103
103
|
additionalItems: {
|
|
104
104
|
anyOf: [{ type: 'boolean' }, { $ref: '#' }],
|
|
105
|
-
default: {}
|
|
105
|
+
default: {},
|
|
106
106
|
},
|
|
107
107
|
items: {
|
|
108
108
|
anyOf: [{ $ref: '#' }, { $ref: '#/definitions/schemaArray' }],
|
|
109
|
-
default: {}
|
|
109
|
+
default: {},
|
|
110
110
|
},
|
|
111
111
|
maxItems: { $ref: '#/definitions/positiveInteger' },
|
|
112
112
|
minItems: { $ref: '#/definitions/positiveIntegerDefault0' },
|
|
113
113
|
uniqueItems: {
|
|
114
114
|
type: 'boolean',
|
|
115
|
-
default: false
|
|
115
|
+
default: false,
|
|
116
116
|
},
|
|
117
117
|
maxProperties: { $ref: '#/definitions/positiveInteger' },
|
|
118
118
|
minProperties: { $ref: '#/definitions/positiveIntegerDefault0' },
|
|
119
119
|
required: { $ref: '#/definitions/stringArray' },
|
|
120
120
|
additionalProperties: {
|
|
121
121
|
anyOf: [{ type: 'boolean' }, { $ref: '#' }],
|
|
122
|
-
default: {}
|
|
122
|
+
default: {},
|
|
123
123
|
},
|
|
124
124
|
definitions: {
|
|
125
125
|
type: 'object',
|
|
126
126
|
additionalProperties: { $ref: '#' },
|
|
127
|
-
default: {}
|
|
127
|
+
default: {},
|
|
128
128
|
},
|
|
129
129
|
properties: {
|
|
130
130
|
type: 'object',
|
|
131
131
|
additionalProperties: { $ref: '#' },
|
|
132
|
-
default: {}
|
|
132
|
+
default: {},
|
|
133
133
|
},
|
|
134
134
|
patternProperties: {
|
|
135
135
|
type: 'object',
|
|
136
136
|
additionalProperties: { $ref: '#' },
|
|
137
|
-
default: {}
|
|
137
|
+
default: {},
|
|
138
138
|
},
|
|
139
139
|
dependencies: {
|
|
140
140
|
type: 'object',
|
|
141
141
|
additionalProperties: {
|
|
142
|
-
anyOf: [{ $ref: '#' }, { $ref: '#/definitions/stringArray' }]
|
|
143
|
-
}
|
|
142
|
+
anyOf: [{ $ref: '#' }, { $ref: '#/definitions/stringArray' }],
|
|
143
|
+
},
|
|
144
144
|
},
|
|
145
145
|
enum: {
|
|
146
146
|
type: 'array',
|
|
147
147
|
minItems: 1,
|
|
148
|
-
uniqueItems: true
|
|
148
|
+
uniqueItems: true,
|
|
149
149
|
},
|
|
150
150
|
type: {
|
|
151
151
|
anyOf: [
|
|
@@ -154,18 +154,18 @@ export const Draft4 = {
|
|
|
154
154
|
type: 'array',
|
|
155
155
|
items: { $ref: '#/definitions/simpleTypes' },
|
|
156
156
|
minItems: 1,
|
|
157
|
-
uniqueItems: true
|
|
158
|
-
}
|
|
159
|
-
]
|
|
157
|
+
uniqueItems: true,
|
|
158
|
+
},
|
|
159
|
+
],
|
|
160
160
|
},
|
|
161
161
|
allOf: { $ref: '#/definitions/schemaArray' },
|
|
162
162
|
anyOf: { $ref: '#/definitions/schemaArray' },
|
|
163
163
|
oneOf: { $ref: '#/definitions/schemaArray' },
|
|
164
|
-
not: { $ref: '#' }
|
|
164
|
+
not: { $ref: '#' },
|
|
165
165
|
},
|
|
166
166
|
dependencies: {
|
|
167
167
|
exclusiveMaximum: ['maximum'],
|
|
168
|
-
exclusiveMinimum: ['minimum']
|
|
168
|
+
exclusiveMinimum: ['minimum'],
|
|
169
169
|
},
|
|
170
|
-
default: {}
|
|
170
|
+
default: {},
|
|
171
171
|
};
|
package/src/models/uischema.ts
CHANGED
|
@@ -54,7 +54,7 @@ export interface Labelable<T = string> {
|
|
|
54
54
|
/**
|
|
55
55
|
* Label for UI schema element.
|
|
56
56
|
*/
|
|
57
|
-
label?: string|T;
|
|
57
|
+
label?: string | T;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
/**
|
|
@@ -108,7 +108,7 @@ export enum RuleEffect {
|
|
|
108
108
|
/**
|
|
109
109
|
* Effect that disables the associated element.
|
|
110
110
|
*/
|
|
111
|
-
DISABLE = 'DISABLE'
|
|
111
|
+
DISABLE = 'DISABLE',
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
/**
|
|
@@ -240,7 +240,11 @@ export interface LabelElement extends UISchemaElement, Internationalizable {
|
|
|
240
240
|
* A control element. The scope property of the control determines
|
|
241
241
|
* to which part of the schema the control should be bound.
|
|
242
242
|
*/
|
|
243
|
-
export interface ControlElement
|
|
243
|
+
export interface ControlElement
|
|
244
|
+
extends UISchemaElement,
|
|
245
|
+
Scoped,
|
|
246
|
+
Labelable<string | boolean | LabelDescription>,
|
|
247
|
+
Internationalizable {
|
|
244
248
|
type: 'Control';
|
|
245
249
|
}
|
|
246
250
|
|
|
@@ -256,7 +260,10 @@ export interface Category extends Layout, Labeled, Internationalizable {
|
|
|
256
260
|
* A child element may either be itself a Categorization or a Category, hence
|
|
257
261
|
* the categorization element can be used to represent recursive structures like trees.
|
|
258
262
|
*/
|
|
259
|
-
export interface Categorization
|
|
263
|
+
export interface Categorization
|
|
264
|
+
extends UISchemaElement,
|
|
265
|
+
Labeled,
|
|
266
|
+
Internationalizable {
|
|
260
267
|
type: 'Categorization';
|
|
261
268
|
/**
|
|
262
269
|
* The child elements of this categorization which are either of type
|
|
@@ -265,8 +272,12 @@ export interface Categorization extends UISchemaElement, Labeled, Internationali
|
|
|
265
272
|
elements: (Category | Categorization)[];
|
|
266
273
|
}
|
|
267
274
|
|
|
268
|
-
export const isInternationalized = (
|
|
269
|
-
|
|
275
|
+
export const isInternationalized = (
|
|
276
|
+
element: unknown
|
|
277
|
+
): element is Required<Internationalizable> =>
|
|
278
|
+
typeof element === 'object' &&
|
|
279
|
+
element !== null &&
|
|
280
|
+
typeof (element as Internationalizable).i18n === 'string';
|
|
270
281
|
|
|
271
282
|
export const isGroup = (layout: Layout): layout is GroupLayout =>
|
|
272
283
|
layout.type === 'Group';
|
package/src/reducers/cells.ts
CHANGED
|
@@ -28,28 +28,29 @@ import {
|
|
|
28
28
|
ADD_CELL,
|
|
29
29
|
AddCellRendererAction,
|
|
30
30
|
REMOVE_CELL,
|
|
31
|
-
RemoveCellRendererAction
|
|
31
|
+
RemoveCellRendererAction,
|
|
32
32
|
} from '../actions';
|
|
33
33
|
import type { Reducer } from '../util';
|
|
34
34
|
|
|
35
35
|
type ValidCellReducerActions = AddCellRendererAction | RemoveCellRendererAction;
|
|
36
36
|
|
|
37
|
-
export type JsonFormsCellRendererRegistryState =
|
|
37
|
+
export type JsonFormsCellRendererRegistryState =
|
|
38
|
+
JsonFormsCellRendererRegistryEntry[];
|
|
38
39
|
|
|
39
40
|
export interface JsonFormsCellRendererRegistryEntry {
|
|
40
41
|
tester: RankedTester;
|
|
41
42
|
cell: any;
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
export const cellReducer: Reducer<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
) => {
|
|
45
|
+
export const cellReducer: Reducer<
|
|
46
|
+
JsonFormsCellRendererRegistryState,
|
|
47
|
+
ValidCellReducerActions
|
|
48
|
+
> = (state = [], { type, tester, cell }) => {
|
|
48
49
|
switch (type) {
|
|
49
50
|
case ADD_CELL:
|
|
50
51
|
return state.concat([{ tester, cell }]);
|
|
51
52
|
case REMOVE_CELL:
|
|
52
|
-
return state.filter(t => t.tester !== tester);
|
|
53
|
+
return state.filter((t) => t.tester !== tester);
|
|
53
54
|
default:
|
|
54
55
|
return state;
|
|
55
56
|
}
|