@jsonforms/core 3.0.0-beta.5 → 3.0.0-rc.0
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/docs/assets/js/search.json +1 -1
- package/docs/globals.html +206 -101
- package/docs/index.html +21 -3
- package/docs/interfaces/arraycontrolprops.html +21 -21
- package/docs/interfaces/arraylayoutprops.html +21 -21
- package/docs/interfaces/categorization.html +1 -1
- package/docs/interfaces/category.html +1 -1
- package/docs/interfaces/cellprops.html +12 -12
- package/docs/interfaces/combinatorrendererprops.html +18 -18
- package/docs/interfaces/controlelement.html +2 -2
- package/docs/interfaces/controlprops.html +16 -16
- package/docs/interfaces/controlstate.html +2 -2
- package/docs/interfaces/controlwithdetailprops.html +17 -17
- package/docs/interfaces/dispatchcellprops.html +10 -10
- package/docs/interfaces/dispatchcellstateprops.html +10 -10
- package/docs/interfaces/dispatchpropsofarraycontrol.html +4 -4
- package/docs/interfaces/dispatchpropsofcontrol.html +1 -1
- package/docs/interfaces/dispatchpropsofmultienumcontrol.html +2 -2
- package/docs/interfaces/enumcellprops.html +13 -13
- package/docs/interfaces/enumoption.html +2 -2
- package/docs/interfaces/grouplayout.html +2 -2
- package/docs/interfaces/internationalizable.html +3 -0
- package/docs/interfaces/jsonformsprops.html +24 -9
- package/docs/interfaces/{lableable.html → labelable.html} +7 -7
- package/docs/interfaces/labeled.html +2 -2
- package/docs/interfaces/labelelement.html +18 -0
- package/docs/interfaces/labelprops.html +339 -0
- package/docs/interfaces/layoutprops.html +25 -10
- package/docs/interfaces/ownpropsofcell.html +9 -9
- package/docs/interfaces/ownpropsofcontrol.html +9 -9
- package/docs/interfaces/ownpropsofenum.html +1 -1
- package/docs/interfaces/ownpropsofenumcell.html +10 -10
- package/docs/interfaces/ownpropsofjsonformsrenderer.html +8 -8
- package/docs/interfaces/ownpropsoflabel.html +286 -0
- package/docs/interfaces/ownpropsoflayout.html +9 -9
- package/docs/interfaces/ownpropsofmasterlistitem.html +6 -6
- package/docs/interfaces/ownpropsofrenderer.html +11 -8
- package/docs/interfaces/rendererprops.html +9 -9
- package/docs/interfaces/statepropsofarraycontrol.html +17 -17
- package/docs/interfaces/statepropsofarraylayout.html +17 -17
- package/docs/interfaces/statepropsofcell.html +11 -11
- package/docs/interfaces/statepropsofcombinator.html +17 -17
- package/docs/interfaces/statepropsofcontrol.html +15 -15
- package/docs/interfaces/statepropsofcontrolwithdetail.html +16 -16
- package/docs/interfaces/statepropsofenumcell.html +12 -12
- package/docs/interfaces/statepropsofjsonformsrenderer.html +23 -9
- package/docs/interfaces/statepropsoflabel.html +343 -0
- package/docs/interfaces/statepropsoflayout.html +24 -10
- package/docs/interfaces/statepropsofmasteritem.html +7 -7
- package/docs/interfaces/statepropsofrenderer.html +12 -9
- package/docs/interfaces/statepropsofscopedrenderer.html +12 -12
- package/docs/interfaces/testercontext.html +184 -0
- package/docs/interfaces/withclassname.html +1 -1
- package/lib/i18n/i18nUtil.d.ts +9 -4
- package/lib/jsonforms-core.cjs.js +61 -32
- package/lib/jsonforms-core.cjs.js.map +1 -1
- package/lib/jsonforms-core.esm.js +59 -33
- package/lib/jsonforms-core.esm.js.map +1 -1
- package/lib/models/uischema.d.ts +7 -7
- package/lib/reducers/i18n.d.ts +1 -1
- package/lib/testers/testers.d.ts +15 -6
- package/lib/util/renderer.d.ts +18 -1
- package/package.json +2 -2
- package/src/i18n/i18nUtil.ts +24 -7
- package/src/models/uischema.ts +8 -8
- package/src/reducers/i18n.ts +1 -1
- package/src/testers/testers.ts +33 -23
- package/src/util/renderer.ts +52 -25
- package/stats.html +1 -1
- package/test/testers.test.ts +40 -23
- package/test/util/renderer.test.ts +105 -7
package/lib/models/uischema.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export interface Scoped extends Scopable {
|
|
|
22
22
|
/**
|
|
23
23
|
* Interface for describing an UI schema element that may be labeled.
|
|
24
24
|
*/
|
|
25
|
-
export interface
|
|
25
|
+
export interface Labelable<T = string> {
|
|
26
26
|
/**
|
|
27
27
|
* Label for UI schema element.
|
|
28
28
|
*/
|
|
@@ -31,7 +31,7 @@ export interface Lableable<T = string> {
|
|
|
31
31
|
/**
|
|
32
32
|
* Interface for describing an UI schema element that is labeled.
|
|
33
33
|
*/
|
|
34
|
-
export interface Labeled<T = string> extends
|
|
34
|
+
export interface Labeled<T = string> extends Labelable<T> {
|
|
35
35
|
label: string | T;
|
|
36
36
|
}
|
|
37
37
|
export interface Internationalizable {
|
|
@@ -157,7 +157,7 @@ export interface HorizontalLayout extends Layout {
|
|
|
157
157
|
* A group resembles a vertical layout, but additionally might have a label.
|
|
158
158
|
* This layout is useful when grouping different elements by a certain criteria.
|
|
159
159
|
*/
|
|
160
|
-
export interface GroupLayout extends Layout,
|
|
160
|
+
export interface GroupLayout extends Layout, Labelable {
|
|
161
161
|
type: 'Group';
|
|
162
162
|
}
|
|
163
163
|
/**
|
|
@@ -176,7 +176,7 @@ export interface LabelDescription {
|
|
|
176
176
|
/**
|
|
177
177
|
* A label element.
|
|
178
178
|
*/
|
|
179
|
-
export interface LabelElement extends UISchemaElement {
|
|
179
|
+
export interface LabelElement extends UISchemaElement, Internationalizable {
|
|
180
180
|
type: 'Label';
|
|
181
181
|
/**
|
|
182
182
|
* The text of label.
|
|
@@ -187,7 +187,7 @@ export interface LabelElement extends UISchemaElement {
|
|
|
187
187
|
* A control element. The scope property of the control determines
|
|
188
188
|
* to which part of the schema the control should be bound.
|
|
189
189
|
*/
|
|
190
|
-
export interface ControlElement extends UISchemaElement, Scoped,
|
|
190
|
+
export interface ControlElement extends UISchemaElement, Scoped, Labelable<string | boolean | LabelDescription>, Internationalizable {
|
|
191
191
|
type: 'Control';
|
|
192
192
|
}
|
|
193
193
|
/**
|
|
@@ -214,5 +214,5 @@ export declare const isGroup: (layout: Layout) => layout is GroupLayout;
|
|
|
214
214
|
export declare const isLayout: (uischema: UISchemaElement) => uischema is Layout;
|
|
215
215
|
export declare const isScopable: (obj: unknown) => obj is Scopable;
|
|
216
216
|
export declare const isScoped: (obj: unknown) => obj is Scoped;
|
|
217
|
-
export declare const isLabelable: (obj: unknown) => obj is
|
|
218
|
-
export declare const isLabeled: (obj: unknown) => obj is Labeled<
|
|
217
|
+
export declare const isLabelable: (obj: unknown) => obj is Labelable<string>;
|
|
218
|
+
export declare const isLabeled: <T = never>(obj: unknown) => obj is Labeled<T>;
|
package/lib/reducers/i18n.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { JsonFormsI18nState } from '../i18n';
|
|
2
2
|
import { I18nActions } from '../actions';
|
|
3
3
|
import { Reducer } from '../util';
|
|
4
|
-
export declare const defaultJsonFormsI18nState: JsonFormsI18nState
|
|
4
|
+
export declare const defaultJsonFormsI18nState: Required<JsonFormsI18nState>;
|
|
5
5
|
export declare const i18nReducer: Reducer<JsonFormsI18nState, I18nActions>;
|
|
6
6
|
export declare const fetchLocale: (state?: JsonFormsI18nState) => string;
|
|
7
7
|
export declare const fetchTranslator: (state?: JsonFormsI18nState) => import("../i18n").Translator;
|
package/lib/testers/testers.d.ts
CHANGED
|
@@ -9,11 +9,20 @@ export declare const NOT_APPLICABLE = -1;
|
|
|
9
9
|
* A tester is a function that receives an UI schema and a JSON schema and returns a boolean.
|
|
10
10
|
* The rootSchema is handed over as context. Can be used to resolve references.
|
|
11
11
|
*/
|
|
12
|
-
export declare type Tester = (uischema: UISchemaElement, schema: JsonSchema,
|
|
12
|
+
export declare type Tester = (uischema: UISchemaElement, schema: JsonSchema, context: TesterContext) => boolean;
|
|
13
13
|
/**
|
|
14
14
|
* A ranked tester associates a tester with a number.
|
|
15
15
|
*/
|
|
16
|
-
export declare type RankedTester = (uischema: UISchemaElement, schema: JsonSchema,
|
|
16
|
+
export declare type RankedTester = (uischema: UISchemaElement, schema: JsonSchema, context: TesterContext) => number;
|
|
17
|
+
/**
|
|
18
|
+
* Additional context given to a tester in addition to UISchema and JsonSchema.
|
|
19
|
+
*/
|
|
20
|
+
export interface TesterContext {
|
|
21
|
+
/** The root JsonSchema of the form. Can be used to resolve references. */
|
|
22
|
+
rootSchema: JsonSchema;
|
|
23
|
+
/** The form wide configuration object given to JsonForms. */
|
|
24
|
+
config: any;
|
|
25
|
+
}
|
|
17
26
|
export declare const isControl: (uischema: any) => uischema is ControlElement;
|
|
18
27
|
/**
|
|
19
28
|
* Only applicable for Controls.
|
|
@@ -97,8 +106,8 @@ export declare const or: (...testers: Tester[]) => Tester;
|
|
|
97
106
|
* @param {number} rank the rank to be returned in case the tester returns true
|
|
98
107
|
* @param {Tester} tester a tester
|
|
99
108
|
*/
|
|
100
|
-
export declare const rankWith: (rank: number, tester: Tester) => (uischema: UISchemaElement, schema: JsonSchema,
|
|
101
|
-
export declare const withIncreasedRank: (by: number, rankedTester: RankedTester) => (uischema: UISchemaElement, schema: JsonSchema,
|
|
109
|
+
export declare const rankWith: (rank: number, tester: Tester) => (uischema: UISchemaElement, schema: JsonSchema, context: TesterContext) => number;
|
|
110
|
+
export declare const withIncreasedRank: (by: number, rankedTester: RankedTester) => (uischema: UISchemaElement, schema: JsonSchema, context: TesterContext) => number;
|
|
102
111
|
/**
|
|
103
112
|
* Default tester for boolean.
|
|
104
113
|
* @type {RankedTester}
|
|
@@ -173,7 +182,7 @@ export declare const isObjectArray: Tester;
|
|
|
173
182
|
* @type {Tester}
|
|
174
183
|
*/
|
|
175
184
|
export declare const isObjectArrayControl: Tester;
|
|
176
|
-
export declare const isObjectArrayWithNesting: (uischema: UISchemaElement, schema: JsonSchema,
|
|
185
|
+
export declare const isObjectArrayWithNesting: (uischema: UISchemaElement, schema: JsonSchema, context: TesterContext) => boolean;
|
|
177
186
|
/**
|
|
178
187
|
* Synonym for isObjectArrayControl
|
|
179
188
|
*/
|
|
@@ -193,7 +202,7 @@ export declare const isPrimitiveArrayControl: Tester;
|
|
|
193
202
|
export declare const isRangeControl: Tester;
|
|
194
203
|
/**
|
|
195
204
|
* Tests whether the given UI schema is of type Control, if the schema
|
|
196
|
-
* is of type
|
|
205
|
+
* is of type integer and has option format
|
|
197
206
|
* @type {Tester}
|
|
198
207
|
*/
|
|
199
208
|
export declare const isNumberFormatControl: Tester;
|
package/lib/util/renderer.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ControlElement, JsonSchema, UISchemaElement } from '../models';
|
|
1
|
+
import { ControlElement, JsonSchema, LabelElement, UISchemaElement } from '../models';
|
|
2
2
|
import { JsonFormsCellRendererRegistryEntry, JsonFormsRendererRegistryEntry } from '../reducers';
|
|
3
3
|
import { JsonFormsUISchemaRegistryEntry } from '../reducers';
|
|
4
4
|
import { RankedTester } from '../testers';
|
|
@@ -82,6 +82,9 @@ export interface OwnPropsOfControl extends OwnPropsOfRenderer {
|
|
|
82
82
|
id?: string;
|
|
83
83
|
uischema?: ControlElement;
|
|
84
84
|
}
|
|
85
|
+
export interface OwnPropsOfLabel extends OwnPropsOfRenderer {
|
|
86
|
+
uischema?: LabelElement;
|
|
87
|
+
}
|
|
85
88
|
export interface OwnPropsOfEnum {
|
|
86
89
|
options?: EnumOption[];
|
|
87
90
|
}
|
|
@@ -202,6 +205,7 @@ export interface StatePropsOfLayout extends StatePropsOfRenderer {
|
|
|
202
205
|
* Direction for the layout to flow
|
|
203
206
|
*/
|
|
204
207
|
direction: 'row' | 'column';
|
|
208
|
+
label?: string;
|
|
205
209
|
}
|
|
206
210
|
export interface LayoutProps extends StatePropsOfLayout {
|
|
207
211
|
}
|
|
@@ -348,6 +352,7 @@ export interface OwnPropsOfJsonFormsRenderer extends OwnPropsOfRenderer {
|
|
|
348
352
|
}
|
|
349
353
|
export interface StatePropsOfJsonFormsRenderer extends OwnPropsOfJsonFormsRenderer {
|
|
350
354
|
rootSchema: JsonSchema;
|
|
355
|
+
config: any;
|
|
351
356
|
}
|
|
352
357
|
export interface JsonFormsProps extends StatePropsOfJsonFormsRenderer {
|
|
353
358
|
}
|
|
@@ -396,3 +401,15 @@ export declare const mapStateToArrayLayoutProps: (state: JsonFormsState, ownProp
|
|
|
396
401
|
*/
|
|
397
402
|
export interface ArrayLayoutProps extends StatePropsOfArrayLayout, DispatchPropsOfArrayControl {
|
|
398
403
|
}
|
|
404
|
+
export interface StatePropsOfLabel extends StatePropsOfRenderer {
|
|
405
|
+
text?: string;
|
|
406
|
+
}
|
|
407
|
+
export interface LabelProps extends StatePropsOfLabel {
|
|
408
|
+
}
|
|
409
|
+
export declare const mapStateToLabelProps: (state: JsonFormsState, props: OwnPropsOfLabel) => {
|
|
410
|
+
text: string;
|
|
411
|
+
visible: boolean;
|
|
412
|
+
config: any;
|
|
413
|
+
renderers: JsonFormsRendererRegistryEntry[];
|
|
414
|
+
cells: JsonFormsCellRendererRegistryEntry[];
|
|
415
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsonforms/core",
|
|
3
|
-
"version": "3.0.0-
|
|
3
|
+
"version": "3.0.0-rc.0",
|
|
4
4
|
"description": "Core module of JSON Forms",
|
|
5
5
|
"repository": "https://github.com/eclipsesource/jsonforms",
|
|
6
6
|
"bugs": "https://github.com/eclipsesource/jsonforms/issues",
|
|
@@ -88,5 +88,5 @@
|
|
|
88
88
|
"typedoc": "^0.19.2",
|
|
89
89
|
"typescript": "4.2.3"
|
|
90
90
|
},
|
|
91
|
-
"gitHead": "
|
|
91
|
+
"gitHead": "5ef030e8b3f91bcdc3e6b8d232a0b191bf1195ce"
|
|
92
92
|
}
|
package/src/i18n/i18nUtil.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { ErrorObject } from 'ajv';
|
|
2
|
-
import { isInternationalized, UISchemaElement } from '../models';
|
|
2
|
+
import { isInternationalized, Labelable, UISchemaElement } from '../models';
|
|
3
3
|
import { getControlPath } from '../reducers';
|
|
4
4
|
import { formatErrorMessage } from '../util';
|
|
5
5
|
import { i18nJsonSchema, ErrorTranslator, Translator } from './i18nTypes';
|
|
6
6
|
|
|
7
7
|
export const getI18nKeyPrefixBySchema = (
|
|
8
8
|
schema: i18nJsonSchema | undefined,
|
|
9
|
-
uischema:
|
|
9
|
+
uischema: unknown | undefined
|
|
10
10
|
): string | undefined => {
|
|
11
11
|
if (isInternationalized(uischema)) {
|
|
12
12
|
return uischema.i18n;
|
|
@@ -18,7 +18,7 @@ export const getI18nKeyPrefixBySchema = (
|
|
|
18
18
|
* Transforms a given path to a prefix which can be used for i18n keys.
|
|
19
19
|
* Returns 'root' for empty paths and removes array indices
|
|
20
20
|
*/
|
|
21
|
-
export const transformPathToI18nPrefix = (path: string) => {
|
|
21
|
+
export const transformPathToI18nPrefix = (path: string): string => {
|
|
22
22
|
return (
|
|
23
23
|
path
|
|
24
24
|
?.split('.')
|
|
@@ -29,9 +29,9 @@ export const transformPathToI18nPrefix = (path: string) => {
|
|
|
29
29
|
|
|
30
30
|
export const getI18nKeyPrefix = (
|
|
31
31
|
schema: i18nJsonSchema | undefined,
|
|
32
|
-
uischema:
|
|
32
|
+
uischema: unknown | undefined,
|
|
33
33
|
path: string | undefined
|
|
34
|
-
): string
|
|
34
|
+
): string => {
|
|
35
35
|
return (
|
|
36
36
|
getI18nKeyPrefixBySchema(schema, uischema) ??
|
|
37
37
|
transformPathToI18nPrefix(path)
|
|
@@ -40,10 +40,10 @@ export const getI18nKeyPrefix = (
|
|
|
40
40
|
|
|
41
41
|
export const getI18nKey = (
|
|
42
42
|
schema: i18nJsonSchema | undefined,
|
|
43
|
-
uischema:
|
|
43
|
+
uischema: unknown | undefined,
|
|
44
44
|
path: string | undefined,
|
|
45
45
|
key: string
|
|
46
|
-
): string
|
|
46
|
+
): string => {
|
|
47
47
|
return `${getI18nKeyPrefix(schema, uischema, path)}.${key}`;
|
|
48
48
|
};
|
|
49
49
|
|
|
@@ -106,3 +106,20 @@ export const getCombinedErrorMessage = (
|
|
|
106
106
|
errors.map(error => et(error, t, uischema))
|
|
107
107
|
);
|
|
108
108
|
};
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* This can be used to internationalize the label of the given Labelable (e.g. UI Schema elements).
|
|
112
|
+
* This should not be used for controls as there we have additional context in the form of the JSON Schema available.
|
|
113
|
+
*/
|
|
114
|
+
export const deriveLabelForUISchemaElement = (uischema: Labelable<boolean>, t: Translator): string | undefined => {
|
|
115
|
+
if (uischema.label === false) {
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
if ((uischema.label === undefined || uischema.label === null || uischema.label === true) && !isInternationalized(uischema)) {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
const stringifiedLabel = typeof uischema.label === 'string' ? uischema.label : JSON.stringify(uischema.label);
|
|
122
|
+
const i18nKeyPrefix = getI18nKeyPrefixBySchema(undefined, uischema);
|
|
123
|
+
const i18nKey = typeof i18nKeyPrefix === 'string' ? `${i18nKeyPrefix}.label` : stringifiedLabel;
|
|
124
|
+
return t(i18nKey, stringifiedLabel, { uischema: uischema });
|
|
125
|
+
}
|
package/src/models/uischema.ts
CHANGED
|
@@ -50,7 +50,7 @@ export interface Scoped extends Scopable {
|
|
|
50
50
|
/**
|
|
51
51
|
* Interface for describing an UI schema element that may be labeled.
|
|
52
52
|
*/
|
|
53
|
-
export interface
|
|
53
|
+
export interface Labelable<T = string> {
|
|
54
54
|
/**
|
|
55
55
|
* Label for UI schema element.
|
|
56
56
|
*/
|
|
@@ -60,7 +60,7 @@ export interface Lableable<T = string> {
|
|
|
60
60
|
/**
|
|
61
61
|
* Interface for describing an UI schema element that is labeled.
|
|
62
62
|
*/
|
|
63
|
-
export interface Labeled<T = string> extends
|
|
63
|
+
export interface Labeled<T = string> extends Labelable<T> {
|
|
64
64
|
label: string | T;
|
|
65
65
|
}
|
|
66
66
|
|
|
@@ -207,7 +207,7 @@ export interface HorizontalLayout extends Layout {
|
|
|
207
207
|
* A group resembles a vertical layout, but additionally might have a label.
|
|
208
208
|
* This layout is useful when grouping different elements by a certain criteria.
|
|
209
209
|
*/
|
|
210
|
-
export interface GroupLayout extends Layout,
|
|
210
|
+
export interface GroupLayout extends Layout, Labelable {
|
|
211
211
|
type: 'Group';
|
|
212
212
|
}
|
|
213
213
|
|
|
@@ -228,7 +228,7 @@ export interface LabelDescription {
|
|
|
228
228
|
/**
|
|
229
229
|
* A label element.
|
|
230
230
|
*/
|
|
231
|
-
export interface LabelElement extends UISchemaElement {
|
|
231
|
+
export interface LabelElement extends UISchemaElement, Internationalizable {
|
|
232
232
|
type: 'Label';
|
|
233
233
|
/**
|
|
234
234
|
* The text of label.
|
|
@@ -240,7 +240,7 @@ export interface LabelElement extends UISchemaElement {
|
|
|
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 extends UISchemaElement, Scoped,
|
|
243
|
+
export interface ControlElement extends UISchemaElement, Scoped, Labelable<string | boolean | LabelDescription>, Internationalizable {
|
|
244
244
|
type: 'Control';
|
|
245
245
|
}
|
|
246
246
|
|
|
@@ -280,8 +280,8 @@ export const isScopable = (obj: unknown): obj is Scopable =>
|
|
|
280
280
|
export const isScoped = (obj: unknown): obj is Scoped =>
|
|
281
281
|
isScopable(obj) && typeof obj.scope === 'string';
|
|
282
282
|
|
|
283
|
-
export const isLabelable = (obj: unknown): obj is
|
|
283
|
+
export const isLabelable = (obj: unknown): obj is Labelable =>
|
|
284
284
|
obj && typeof obj === 'object';
|
|
285
285
|
|
|
286
|
-
export const isLabeled = (obj: unknown): obj is Labeled =>
|
|
287
|
-
isLabelable(obj) && ['string', '
|
|
286
|
+
export const isLabeled = <T = never>(obj: unknown): obj is Labeled<T> =>
|
|
287
|
+
isLabelable(obj) && ['string', 'boolean'].includes(typeof obj.label);
|
package/src/reducers/i18n.ts
CHANGED
|
@@ -27,7 +27,7 @@ import { defaultErrorTranslator, defaultTranslator, JsonFormsI18nState } from '.
|
|
|
27
27
|
import { I18nActions, SET_LOCALE, SET_TRANSLATOR, UPDATE_I18N } from '../actions';
|
|
28
28
|
import { Reducer } from '../util';
|
|
29
29
|
|
|
30
|
-
export const defaultJsonFormsI18nState: JsonFormsI18nState = {
|
|
30
|
+
export const defaultJsonFormsI18nState: Required<JsonFormsI18nState> = {
|
|
31
31
|
locale: 'en',
|
|
32
32
|
translate: defaultTranslator,
|
|
33
33
|
translateError: defaultErrorTranslator
|
package/src/testers/testers.ts
CHANGED
|
@@ -49,7 +49,7 @@ 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 = (uischema: UISchemaElement, schema: JsonSchema,
|
|
52
|
+
export type Tester = (uischema: UISchemaElement, schema: JsonSchema, context: TesterContext) => boolean;
|
|
53
53
|
|
|
54
54
|
/**
|
|
55
55
|
* A ranked tester associates a tester with a number.
|
|
@@ -57,9 +57,19 @@ export type Tester = (uischema: UISchemaElement, schema: JsonSchema, rootSchema:
|
|
|
57
57
|
export type RankedTester = (
|
|
58
58
|
uischema: UISchemaElement,
|
|
59
59
|
schema: JsonSchema,
|
|
60
|
-
|
|
60
|
+
context: TesterContext
|
|
61
61
|
) => number;
|
|
62
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Additional context given to a tester in addition to UISchema and JsonSchema.
|
|
65
|
+
*/
|
|
66
|
+
export interface TesterContext {
|
|
67
|
+
/** The root JsonSchema of the form. Can be used to resolve references. */
|
|
68
|
+
rootSchema: JsonSchema;
|
|
69
|
+
/** The form wide configuration object given to JsonForms. */
|
|
70
|
+
config: any;
|
|
71
|
+
}
|
|
72
|
+
|
|
63
73
|
export const isControl = (uischema: any): uischema is ControlElement =>
|
|
64
74
|
!isEmpty(uischema) && uischema.scope !== undefined;
|
|
65
75
|
|
|
@@ -75,7 +85,7 @@ export const isControl = (uischema: any): uischema is ControlElement =>
|
|
|
75
85
|
*/
|
|
76
86
|
export const schemaMatches = (
|
|
77
87
|
predicate: (schema: JsonSchema, rootSchema: JsonSchema) => boolean
|
|
78
|
-
): Tester => (uischema: UISchemaElement, schema: JsonSchema,
|
|
88
|
+
): Tester => (uischema: UISchemaElement, schema: JsonSchema, context: TesterContext): boolean => {
|
|
79
89
|
if (isEmpty(uischema) || !isControl(uischema)) {
|
|
80
90
|
return false;
|
|
81
91
|
}
|
|
@@ -88,26 +98,26 @@ export const schemaMatches = (
|
|
|
88
98
|
}
|
|
89
99
|
let currentDataSchema = schema;
|
|
90
100
|
if (hasType(schema, 'object')) {
|
|
91
|
-
currentDataSchema = resolveSchema(schema, schemaPath, rootSchema);
|
|
101
|
+
currentDataSchema = resolveSchema(schema, schemaPath, context?.rootSchema);
|
|
92
102
|
}
|
|
93
103
|
if (currentDataSchema === undefined) {
|
|
94
104
|
return false;
|
|
95
105
|
}
|
|
96
106
|
|
|
97
|
-
return predicate(currentDataSchema, rootSchema);
|
|
107
|
+
return predicate(currentDataSchema, context?.rootSchema);
|
|
98
108
|
};
|
|
99
109
|
|
|
100
110
|
export const schemaSubPathMatches = (
|
|
101
111
|
subPath: string,
|
|
102
112
|
predicate: (schema: JsonSchema, rootSchema: JsonSchema) => boolean
|
|
103
|
-
): Tester => (uischema: UISchemaElement, schema: JsonSchema,
|
|
113
|
+
): Tester => (uischema: UISchemaElement, schema: JsonSchema, context: TesterContext): boolean => {
|
|
104
114
|
if (isEmpty(uischema) || !isControl(uischema)) {
|
|
105
115
|
return false;
|
|
106
116
|
}
|
|
107
117
|
const schemaPath = uischema.scope;
|
|
108
118
|
let currentDataSchema: JsonSchema = schema;
|
|
109
119
|
if (hasType(schema, 'object')) {
|
|
110
|
-
currentDataSchema = resolveSchema(schema, schemaPath, rootSchema);
|
|
120
|
+
currentDataSchema = resolveSchema(schema, schemaPath, context?.rootSchema);
|
|
111
121
|
}
|
|
112
122
|
currentDataSchema = get(currentDataSchema, subPath);
|
|
113
123
|
|
|
@@ -115,7 +125,7 @@ export const schemaSubPathMatches = (
|
|
|
115
125
|
return false;
|
|
116
126
|
}
|
|
117
127
|
|
|
118
|
-
return predicate(currentDataSchema, rootSchema);
|
|
128
|
+
return predicate(currentDataSchema, context?.rootSchema);
|
|
119
129
|
};
|
|
120
130
|
|
|
121
131
|
/**
|
|
@@ -218,8 +228,8 @@ export const scopeEndIs = (expected: string): Tester => (
|
|
|
218
228
|
export const and = (...testers: Tester[]): Tester => (
|
|
219
229
|
uischema: UISchemaElement,
|
|
220
230
|
schema: JsonSchema,
|
|
221
|
-
|
|
222
|
-
) => testers.reduce((acc, tester) => acc && tester(uischema, schema,
|
|
231
|
+
context: TesterContext
|
|
232
|
+
) => testers.reduce((acc, tester) => acc && tester(uischema, schema, context), true);
|
|
223
233
|
|
|
224
234
|
/**
|
|
225
235
|
* A tester that allow composing other testers by || them.
|
|
@@ -229,8 +239,8 @@ export const and = (...testers: Tester[]): Tester => (
|
|
|
229
239
|
export const or = (...testers: Tester[]): Tester => (
|
|
230
240
|
uischema: UISchemaElement,
|
|
231
241
|
schema: JsonSchema,
|
|
232
|
-
|
|
233
|
-
) => testers.reduce((acc, tester) => acc || tester(uischema, schema,
|
|
242
|
+
context: TesterContext
|
|
243
|
+
) => testers.reduce((acc, tester) => acc || tester(uischema, schema, context), false);
|
|
234
244
|
/**
|
|
235
245
|
* Create a ranked tester that will associate a number with a given tester, if the
|
|
236
246
|
* latter returns true.
|
|
@@ -241,9 +251,9 @@ export const or = (...testers: Tester[]): Tester => (
|
|
|
241
251
|
export const rankWith = (rank: number, tester: Tester) => (
|
|
242
252
|
uischema: UISchemaElement,
|
|
243
253
|
schema: JsonSchema,
|
|
244
|
-
|
|
254
|
+
context: TesterContext
|
|
245
255
|
): number => {
|
|
246
|
-
if (tester(uischema, schema,
|
|
256
|
+
if (tester(uischema, schema, context)) {
|
|
247
257
|
return rank;
|
|
248
258
|
}
|
|
249
259
|
|
|
@@ -253,9 +263,9 @@ export const rankWith = (rank: number, tester: Tester) => (
|
|
|
253
263
|
export const withIncreasedRank = (by: number, rankedTester: RankedTester) => (
|
|
254
264
|
uischema: UISchemaElement,
|
|
255
265
|
schema: JsonSchema,
|
|
256
|
-
|
|
266
|
+
context: TesterContext
|
|
257
267
|
): number => {
|
|
258
|
-
const rank = rankedTester(uischema, schema,
|
|
268
|
+
const rank = rankedTester(uischema, schema, context);
|
|
259
269
|
if (rank === NOT_APPLICABLE) {
|
|
260
270
|
return NOT_APPLICABLE;
|
|
261
271
|
}
|
|
@@ -438,13 +448,13 @@ const traverse = (
|
|
|
438
448
|
export const isObjectArrayWithNesting = (
|
|
439
449
|
uischema: UISchemaElement,
|
|
440
450
|
schema: JsonSchema,
|
|
441
|
-
|
|
451
|
+
context: TesterContext
|
|
442
452
|
): boolean => {
|
|
443
|
-
if (!uiTypeIs('Control')(uischema, schema,
|
|
453
|
+
if (!uiTypeIs('Control')(uischema, schema, context)) {
|
|
444
454
|
return false;
|
|
445
455
|
}
|
|
446
456
|
const schemaPath = (uischema as ControlElement).scope;
|
|
447
|
-
const resolvedSchema = resolveSchema(schema, schemaPath, rootSchema ?? schema);
|
|
457
|
+
const resolvedSchema = resolveSchema(schema, schemaPath, context?.rootSchema ?? schema);
|
|
448
458
|
let objectDepth = 0;
|
|
449
459
|
if (resolvedSchema !== undefined && resolvedSchema.items !== undefined) {
|
|
450
460
|
// check if nested arrays
|
|
@@ -466,7 +476,7 @@ export const isObjectArrayWithNesting = (
|
|
|
466
476
|
return true;
|
|
467
477
|
}
|
|
468
478
|
return false;
|
|
469
|
-
}, rootSchema)
|
|
479
|
+
}, context?.rootSchema)
|
|
470
480
|
) {
|
|
471
481
|
return true;
|
|
472
482
|
}
|
|
@@ -532,7 +542,7 @@ export const isRangeControl = and(
|
|
|
532
542
|
|
|
533
543
|
/**
|
|
534
544
|
* Tests whether the given UI schema is of type Control, if the schema
|
|
535
|
-
* is of type
|
|
545
|
+
* is of type integer and has option format
|
|
536
546
|
* @type {Tester}
|
|
537
547
|
*/
|
|
538
548
|
export const isNumberFormatControl = and(
|
|
@@ -566,6 +576,6 @@ export const categorizationHasCategory = (uischema: UISchemaElement) =>
|
|
|
566
576
|
export const not = (tester: Tester): Tester => (
|
|
567
577
|
uischema: UISchemaElement,
|
|
568
578
|
schema: JsonSchema,
|
|
569
|
-
|
|
579
|
+
context: TesterContext
|
|
570
580
|
|
|
571
|
-
) => !tester(uischema, schema,
|
|
581
|
+
) => !tester(uischema, schema, context);
|
package/src/util/renderer.ts
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
26
|
import get from 'lodash/get';
|
|
27
|
-
import { ControlElement, JsonSchema, UISchemaElement } from '../models';
|
|
27
|
+
import { ControlElement, isLabelable, JsonSchema, LabelElement, UISchemaElement } from '../models';
|
|
28
28
|
import find from 'lodash/find';
|
|
29
29
|
import {
|
|
30
30
|
getUISchemas,
|
|
@@ -32,7 +32,6 @@ import {
|
|
|
32
32
|
JsonFormsRendererRegistryEntry,
|
|
33
33
|
} from '../reducers';
|
|
34
34
|
import {
|
|
35
|
-
findUISchema,
|
|
36
35
|
getAjv,
|
|
37
36
|
getCells,
|
|
38
37
|
getConfig,
|
|
@@ -57,7 +56,7 @@ import { composePaths, composeWithUi } from './path';
|
|
|
57
56
|
import { CoreActions, update } from '../actions';
|
|
58
57
|
import { ErrorObject } from 'ajv';
|
|
59
58
|
import { JsonFormsState } from '../store';
|
|
60
|
-
import { getCombinedErrorMessage, getI18nKey, getI18nKeyPrefix, Translator } from '../i18n';
|
|
59
|
+
import { deriveLabelForUISchemaElement, getCombinedErrorMessage, getI18nKey, getI18nKeyPrefix, getI18nKeyPrefixBySchema, Translator } from '../i18n';
|
|
61
60
|
|
|
62
61
|
const isRequired = (
|
|
63
62
|
schema: JsonSchema,
|
|
@@ -255,6 +254,10 @@ export interface OwnPropsOfControl extends OwnPropsOfRenderer {
|
|
|
255
254
|
uischema?: ControlElement;
|
|
256
255
|
}
|
|
257
256
|
|
|
257
|
+
export interface OwnPropsOfLabel extends OwnPropsOfRenderer {
|
|
258
|
+
uischema?: LabelElement;
|
|
259
|
+
}
|
|
260
|
+
|
|
258
261
|
export interface OwnPropsOfEnum {
|
|
259
262
|
options?: EnumOption[];
|
|
260
263
|
}
|
|
@@ -398,6 +401,7 @@ export interface StatePropsOfLayout extends StatePropsOfRenderer {
|
|
|
398
401
|
* Direction for the layout to flow
|
|
399
402
|
*/
|
|
400
403
|
direction: 'row' | 'column';
|
|
404
|
+
label?: string;
|
|
401
405
|
}
|
|
402
406
|
|
|
403
407
|
export interface LayoutProps extends StatePropsOfLayout {}
|
|
@@ -857,6 +861,10 @@ export const mapStateToLayoutProps = (
|
|
|
857
861
|
config
|
|
858
862
|
);
|
|
859
863
|
|
|
864
|
+
// some layouts have labels which might need to be translated
|
|
865
|
+
const t = getTranslator()(state);
|
|
866
|
+
const label = isLabelable(uischema) ? deriveLabelForUISchemaElement(uischema, t) : undefined;
|
|
867
|
+
|
|
860
868
|
return {
|
|
861
869
|
...layoutDefaultProps,
|
|
862
870
|
renderers: ownProps.renderers || getRenderers(state),
|
|
@@ -868,7 +876,8 @@ export const mapStateToLayoutProps = (
|
|
|
868
876
|
uischema: ownProps.uischema,
|
|
869
877
|
schema: ownProps.schema,
|
|
870
878
|
direction: ownProps.direction ?? getDirection(uischema),
|
|
871
|
-
config
|
|
879
|
+
config,
|
|
880
|
+
label
|
|
872
881
|
};
|
|
873
882
|
};
|
|
874
883
|
|
|
@@ -879,6 +888,7 @@ export interface OwnPropsOfJsonFormsRenderer extends OwnPropsOfRenderer {}
|
|
|
879
888
|
export interface StatePropsOfJsonFormsRenderer
|
|
880
889
|
extends OwnPropsOfJsonFormsRenderer {
|
|
881
890
|
rootSchema: JsonSchema;
|
|
891
|
+
config: any;
|
|
882
892
|
}
|
|
883
893
|
|
|
884
894
|
export interface JsonFormsProps extends StatePropsOfJsonFormsRenderer {}
|
|
@@ -887,30 +897,15 @@ export const mapStateToJsonFormsRendererProps = (
|
|
|
887
897
|
state: JsonFormsState,
|
|
888
898
|
ownProps: OwnPropsOfJsonFormsRenderer
|
|
889
899
|
): StatePropsOfJsonFormsRenderer => {
|
|
890
|
-
let uischema = ownProps.uischema;
|
|
891
|
-
if (uischema === undefined) {
|
|
892
|
-
if (ownProps.schema) {
|
|
893
|
-
uischema = findUISchema(
|
|
894
|
-
state.jsonforms.uischemas,
|
|
895
|
-
ownProps.schema,
|
|
896
|
-
undefined,
|
|
897
|
-
ownProps.path,
|
|
898
|
-
undefined,
|
|
899
|
-
undefined,
|
|
900
|
-
state.jsonforms.core.schema
|
|
901
|
-
);
|
|
902
|
-
} else {
|
|
903
|
-
uischema = getUiSchema(state);
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
|
|
907
900
|
return {
|
|
908
|
-
renderers: ownProps.renderers || get(state.jsonforms, 'renderers')
|
|
909
|
-
cells: ownProps.cells || get(state.jsonforms, 'cells')
|
|
901
|
+
renderers: ownProps.renderers || get(state.jsonforms, 'renderers'),
|
|
902
|
+
cells: ownProps.cells || get(state.jsonforms, 'cells'),
|
|
910
903
|
schema: ownProps.schema || getSchema(state),
|
|
911
904
|
rootSchema: getSchema(state),
|
|
912
|
-
uischema: uischema,
|
|
913
|
-
path: ownProps.path
|
|
905
|
+
uischema: ownProps.uischema || getUiSchema(state),
|
|
906
|
+
path: ownProps.path,
|
|
907
|
+
enabled: ownProps.enabled,
|
|
908
|
+
config: getConfig(state)
|
|
914
909
|
};
|
|
915
910
|
};
|
|
916
911
|
|
|
@@ -1064,3 +1059,35 @@ export const mapStateToArrayLayoutProps = (
|
|
|
1064
1059
|
export interface ArrayLayoutProps
|
|
1065
1060
|
extends StatePropsOfArrayLayout,
|
|
1066
1061
|
DispatchPropsOfArrayControl {}
|
|
1062
|
+
|
|
1063
|
+
export interface StatePropsOfLabel extends StatePropsOfRenderer {
|
|
1064
|
+
text?: string;
|
|
1065
|
+
}
|
|
1066
|
+
export interface LabelProps extends StatePropsOfLabel{
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
export const mapStateToLabelProps = (
|
|
1070
|
+
state: JsonFormsState,
|
|
1071
|
+
props: OwnPropsOfLabel
|
|
1072
|
+
) => {
|
|
1073
|
+
const { uischema } = props;
|
|
1074
|
+
|
|
1075
|
+
const visible: boolean =
|
|
1076
|
+
props.visible === undefined || hasShowRule(uischema)
|
|
1077
|
+
? isVisible(props.uischema, getData(state), props.path, getAjv(state))
|
|
1078
|
+
: props.visible;
|
|
1079
|
+
|
|
1080
|
+
const text = uischema.text;
|
|
1081
|
+
const t = getTranslator()(state);
|
|
1082
|
+
const i18nKeyPrefix = getI18nKeyPrefixBySchema(undefined, uischema);
|
|
1083
|
+
const i18nKey = i18nKeyPrefix ? `${i18nKeyPrefix}.text` : text ?? '';
|
|
1084
|
+
const i18nText = t(i18nKey, text, { uischema });
|
|
1085
|
+
|
|
1086
|
+
return {
|
|
1087
|
+
text: i18nText,
|
|
1088
|
+
visible,
|
|
1089
|
+
config: getConfig(state),
|
|
1090
|
+
renderers: props.renderers || getRenderers(state),
|
|
1091
|
+
cells: props.cells || getCells(state),
|
|
1092
|
+
}
|
|
1093
|
+
}
|