@abgov/jsonforms-components 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc +12 -0
- package/.eslintrc.json +36 -0
- package/.releaserc.json +25 -0
- package/README.md +251 -0
- package/jest.config.ts +11 -0
- package/package.json +17 -0
- package/project.json +55 -0
- package/rollup.config.js +14 -0
- package/src/index.ts +166 -0
- package/src/lib/Additional/HelpContent.tsx +95 -0
- package/src/lib/Additional/index.ts +1 -0
- package/src/lib/Additional/styled-components.ts +27 -0
- package/src/lib/Cells/DateCell.tsx +10 -0
- package/src/lib/Cells/IntegerCell.tsx +10 -0
- package/src/lib/Cells/NumberCell.tsx +10 -0
- package/src/lib/Cells/TextCell.tsx +10 -0
- package/src/lib/Cells/TimeCell.tsx +10 -0
- package/src/lib/Cells/index.tsx +14 -0
- package/src/lib/Context/index.tsx +172 -0
- package/src/lib/Controls/FileUploader/ContextMenu.tsx +50 -0
- package/src/lib/Controls/FileUploader/FileUploaderControl.tsx +131 -0
- package/src/lib/Controls/FileUploader/FileUploaderTester.tsx +3 -0
- package/src/lib/Controls/FileUploader/index.tsx +2 -0
- package/src/lib/Controls/FileUploader/styled-components.tsx +10 -0
- package/src/lib/Controls/FormStepper/FormStepperControl.tsx +269 -0
- package/src/lib/Controls/FormStepper/FormStepperTester.tsx +22 -0
- package/src/lib/Controls/FormStepper/index.tsx +2 -0
- package/src/lib/Controls/FormStepper/styled-components.tsx +17 -0
- package/src/lib/Controls/Inputs/InputBaseControl.tsx +52 -0
- package/src/lib/Controls/Inputs/InputBooleanControl.tsx +67 -0
- package/src/lib/Controls/Inputs/InputBooleanRadioControl.tsx +74 -0
- package/src/lib/Controls/Inputs/InputDateControl.tsx +90 -0
- package/src/lib/Controls/Inputs/InputDateTimeControl.tsx +46 -0
- package/src/lib/Controls/Inputs/InputEnum.tsx +74 -0
- package/src/lib/Controls/Inputs/InputEnumAutoComplete.tsx +73 -0
- package/src/lib/Controls/Inputs/InputEnumRadios.tsx +43 -0
- package/src/lib/Controls/Inputs/InputIntegerControl.tsx +63 -0
- package/src/lib/Controls/Inputs/InputMultiLineTextControl.tsx +63 -0
- package/src/lib/Controls/Inputs/InputNumberControl.tsx +63 -0
- package/src/lib/Controls/Inputs/InputTextControl.tsx +62 -0
- package/src/lib/Controls/Inputs/InputTimeControl.tsx +46 -0
- package/src/lib/Controls/Inputs/index.tsx +13 -0
- package/src/lib/Controls/Inputs/inputControl.spec.ts +84 -0
- package/src/lib/Controls/Inputs/type.ts +3 -0
- package/src/lib/Controls/ObjectArray/DeleteDialog.tsx +49 -0
- package/src/lib/Controls/ObjectArray/ObjectArray.tsx +59 -0
- package/src/lib/Controls/ObjectArray/ObjectArrayToolBar.tsx +51 -0
- package/src/lib/Controls/ObjectArray/ObjectListControl.tsx +368 -0
- package/src/lib/Controls/ObjectArray/index.tsx +1 -0
- package/src/lib/Controls/ObjectArray/styled-components.tsx +13 -0
- package/src/lib/Controls/index.tsx +4 -0
- package/src/lib/ErrorHandling/GoAErrorControl.tsx +53 -0
- package/src/lib/ErrorHandling/MessageControl.tsx +19 -0
- package/src/lib/ErrorHandling/categorizationValidation.spec.ts +98 -0
- package/src/lib/ErrorHandling/controlValildation.spec.ts +57 -0
- package/src/lib/ErrorHandling/errorCheck.spec.ts +185 -0
- package/src/lib/ErrorHandling/errorCheck.tsx +86 -0
- package/src/lib/ErrorHandling/layoutValildation.spec.ts +47 -0
- package/src/lib/ErrorHandling/otherValildation.spec.ts +74 -0
- package/src/lib/ErrorHandling/schemaValidation.ts +115 -0
- package/src/lib/common/Grid.tsx +55 -0
- package/src/lib/jsonforms-components.module.scss +7 -0
- package/src/lib/jsonforms-components.spec.tsx +10 -0
- package/src/lib/jsonforms-components.tsx +14 -0
- package/src/lib/layouts/GroupControl.tsx +25 -0
- package/src/lib/layouts/HorizontalLayoutControl.tsx +30 -0
- package/src/lib/layouts/VerticalLayoutControl.tsx +28 -0
- package/src/lib/layouts/index.ts +3 -0
- package/src/lib/util/layout.tsx +68 -0
- package/src/lib/util/schemaUtils.ts +9 -0
- package/src/lib/util/stringUtils.ts +98 -0
- package/src/lib/util/style-component.ts +8 -0
- package/tsconfig.json +20 -0
- package/tsconfig.lib.json +19 -0
- package/tsconfig.spec.json +20 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import { ControlProps, isEnumControl, OwnPropsOfEnum, RankedTester, rankWith } from '@jsonforms/core';
|
|
3
|
+
import { TranslateProps, withJsonFormsEnumProps, withTranslateProps } from '@jsonforms/react';
|
|
4
|
+
import { WithInputProps } from './type';
|
|
5
|
+
import merge from 'lodash/merge';
|
|
6
|
+
import { GoAInputBaseControl } from './InputBaseControl';
|
|
7
|
+
import { WithOptionLabel } from '@jsonforms/material-renderers';
|
|
8
|
+
import { GoADropdown, GoADropdownItem } from '@abgov/react-components-new';
|
|
9
|
+
import { EnumCellProps, WithClassname } from '@jsonforms/core';
|
|
10
|
+
|
|
11
|
+
import { addDataByOptions, getData } from '../../Context';
|
|
12
|
+
import { checkFieldValidity } from '../../util/stringUtils';
|
|
13
|
+
|
|
14
|
+
type EnumSelectProp = EnumCellProps & WithClassname & TranslateProps & WithInputProps;
|
|
15
|
+
|
|
16
|
+
export const EnumSelect = (props: EnumSelectProp): JSX.Element => {
|
|
17
|
+
const { data, id, enabled, errors, schema, path, handleChange, options, config, label, uischema } = props;
|
|
18
|
+
const { required } = props as ControlProps;
|
|
19
|
+
|
|
20
|
+
let enumData: unknown[] = schema?.enum || [];
|
|
21
|
+
|
|
22
|
+
const appliedUiSchemaOptions = merge({}, config, props.uischema.options, options);
|
|
23
|
+
|
|
24
|
+
const dataKey = uischema?.options?.enumContext?.key;
|
|
25
|
+
|
|
26
|
+
const url = uischema?.options?.enumContext?.url;
|
|
27
|
+
const location = uischema?.options?.enumContext?.location;
|
|
28
|
+
const type = uischema?.options?.enumContext?.type;
|
|
29
|
+
const values = uischema?.options?.enumContext?.values;
|
|
30
|
+
|
|
31
|
+
const errorsFormInput = checkFieldValidity(props as ControlProps);
|
|
32
|
+
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (dataKey && url) {
|
|
35
|
+
addDataByOptions(dataKey, url, location, type, values);
|
|
36
|
+
}
|
|
37
|
+
}, [url, location, type, values, dataKey]);
|
|
38
|
+
|
|
39
|
+
if (dataKey && getData(dataKey)) {
|
|
40
|
+
const newData = getData(dataKey) as unknown[];
|
|
41
|
+
|
|
42
|
+
enumData = newData;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<GoADropdown
|
|
47
|
+
error={errorsFormInput.length > 0}
|
|
48
|
+
name={`${label}`}
|
|
49
|
+
value={data}
|
|
50
|
+
disabled={!enabled}
|
|
51
|
+
relative={true}
|
|
52
|
+
key={`${id}-jsonform-key`}
|
|
53
|
+
testId={`${id || label}-jsonform`}
|
|
54
|
+
{...appliedUiSchemaOptions}
|
|
55
|
+
onChange={(name, value) => {
|
|
56
|
+
handleChange(path, value);
|
|
57
|
+
}}
|
|
58
|
+
{...uischema?.options?.componentProps}
|
|
59
|
+
>
|
|
60
|
+
{enumData?.map((item) => {
|
|
61
|
+
return <GoADropdownItem key={`json-form-dropdown-${item}`} value={`${item}`} label={`${item}`} />;
|
|
62
|
+
})}
|
|
63
|
+
</GoADropdown>
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const numControl = (props: ControlProps & OwnPropsOfEnum & WithOptionLabel & TranslateProps) => {
|
|
68
|
+
return <GoAInputBaseControl {...props} input={EnumSelect} />;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const GoAEnumControlTester: RankedTester = rankWith(2, isEnumControl);
|
|
72
|
+
|
|
73
|
+
// HOC order can be reversed with https://github.com/eclipsesource/jsonforms/issues/1987
|
|
74
|
+
export const GoAEnumControl = withJsonFormsEnumProps(withTranslateProps(numControl), true);
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import { ControlProps, isEnumControl, and, optionIs, OwnPropsOfEnum, RankedTester, rankWith } from '@jsonforms/core';
|
|
3
|
+
import { TranslateProps, withJsonFormsEnumProps, withTranslateProps } from '@jsonforms/react';
|
|
4
|
+
import { WithInputProps } from './type';
|
|
5
|
+
import { GoAInputBaseControl } from './InputBaseControl';
|
|
6
|
+
import { WithOptionLabel } from '@jsonforms/material-renderers';
|
|
7
|
+
import { EnumCellProps, WithClassname } from '@jsonforms/core';
|
|
8
|
+
import TextField from '@mui/material/TextField';
|
|
9
|
+
import Autocomplete from '@mui/material/Autocomplete';
|
|
10
|
+
|
|
11
|
+
import { addDataByOptions, getData } from '../../Context';
|
|
12
|
+
|
|
13
|
+
type EnumSelectAutoCompleteProp = EnumCellProps & WithClassname & TranslateProps & WithInputProps;
|
|
14
|
+
|
|
15
|
+
export const EnumSelectAutoComplete = (props: EnumSelectAutoCompleteProp): JSX.Element => {
|
|
16
|
+
const { data, schema, path, handleChange, uischema } = props;
|
|
17
|
+
let enumData = schema?.enum || [];
|
|
18
|
+
|
|
19
|
+
const dataKey = uischema?.options?.enumContext?.key;
|
|
20
|
+
|
|
21
|
+
const url = uischema?.options?.enumContext?.url;
|
|
22
|
+
const location = uischema?.options?.enumContext?.location;
|
|
23
|
+
const type = uischema?.options?.enumContext?.type;
|
|
24
|
+
const values = uischema?.options?.enumContext?.values;
|
|
25
|
+
|
|
26
|
+
const defaultProps = {
|
|
27
|
+
options: enumData,
|
|
28
|
+
getOptionLabel: (option: Array<string>) => option,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const [inputValue, setInputValue] = React.useState('');
|
|
32
|
+
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (dataKey && url) {
|
|
35
|
+
addDataByOptions(dataKey, url, location, type, values);
|
|
36
|
+
}
|
|
37
|
+
}, [url, location, type, values, dataKey]);
|
|
38
|
+
|
|
39
|
+
if (dataKey && getData(dataKey)) {
|
|
40
|
+
const newData = getData(dataKey);
|
|
41
|
+
// eslint-disable-next-line
|
|
42
|
+
enumData = newData as any[];
|
|
43
|
+
defaultProps.options = enumData;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<Autocomplete
|
|
48
|
+
{...defaultProps}
|
|
49
|
+
id="autocomplete"
|
|
50
|
+
getOptionLabel={(option) => option}
|
|
51
|
+
isOptionEqualToValue={(option, value) => option.id === value.id}
|
|
52
|
+
value={data || null}
|
|
53
|
+
onChange={(name, value) => {
|
|
54
|
+
handleChange(path, value);
|
|
55
|
+
setInputValue(value);
|
|
56
|
+
}}
|
|
57
|
+
renderInput={(params) => {
|
|
58
|
+
return <TextField {...params} variant="outlined" size="small" placeholder={schema?.description} />;
|
|
59
|
+
}}
|
|
60
|
+
/>
|
|
61
|
+
);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const numControlAutoComplete = (props: ControlProps & OwnPropsOfEnum & WithOptionLabel & TranslateProps) => {
|
|
65
|
+
return <GoAInputBaseControl {...props} input={EnumSelectAutoComplete} />;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const GoAEnumControlAutoCompleteTester: RankedTester = rankWith(
|
|
69
|
+
3,
|
|
70
|
+
and(isEnumControl, optionIs('autocomplete', true))
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
export const GoAEnumAutoCompleteControl = withJsonFormsEnumProps(withTranslateProps(numControlAutoComplete), true);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ControlProps, isEnumControl, OwnPropsOfEnum, RankedTester, rankWith, optionIs, and } from '@jsonforms/core';
|
|
3
|
+
import { TranslateProps, withJsonFormsEnumProps, withTranslateProps } from '@jsonforms/react';
|
|
4
|
+
import { WithInputProps } from './type';
|
|
5
|
+
import merge from 'lodash/merge';
|
|
6
|
+
import { GoAInputBaseControl } from './InputBaseControl';
|
|
7
|
+
import { WithOptionLabel } from '@jsonforms/material-renderers';
|
|
8
|
+
import { GoARadioGroup, GoARadioItem } from '@abgov/react-components-new';
|
|
9
|
+
import { EnumCellProps, WithClassname } from '@jsonforms/core';
|
|
10
|
+
import { checkFieldValidity } from '../../util/stringUtils';
|
|
11
|
+
|
|
12
|
+
type RadioGroupProp = EnumCellProps & WithClassname & TranslateProps & WithInputProps;
|
|
13
|
+
|
|
14
|
+
export const RadioGroup = (props: RadioGroupProp): JSX.Element => {
|
|
15
|
+
const { data, className, id, enabled, schema, uischema, path, handleChange, options, config, label, t } = props;
|
|
16
|
+
const enumData = schema?.enum || [];
|
|
17
|
+
const appliedUiSchemaOptions = merge({}, config, props.uischema.options, uischema, options);
|
|
18
|
+
const errorsFormInput = checkFieldValidity(props as ControlProps);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<GoARadioGroup
|
|
22
|
+
error={errorsFormInput.length > 0}
|
|
23
|
+
name={`${options || appliedUiSchemaOptions.label}`}
|
|
24
|
+
testId={`${id || label}-jsonform-dropdown`}
|
|
25
|
+
value={data}
|
|
26
|
+
disabled={!enabled}
|
|
27
|
+
{...appliedUiSchemaOptions}
|
|
28
|
+
onChange={(name: string, value: string) => handleChange(path, value)}
|
|
29
|
+
{...uischema?.options?.componentProps}
|
|
30
|
+
>
|
|
31
|
+
{enumData.map((value) => {
|
|
32
|
+
return <GoARadioItem name={value} value={`${value}`} label={value} {...appliedUiSchemaOptions} />;
|
|
33
|
+
})}
|
|
34
|
+
</GoARadioGroup>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const EnumRadioControl = (props: ControlProps & OwnPropsOfEnum & WithOptionLabel & TranslateProps) => {
|
|
39
|
+
return <GoAInputBaseControl {...props} input={RadioGroup} />;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const GoAEnumRadioGroupControl = withJsonFormsEnumProps(withTranslateProps(EnumRadioControl), true);
|
|
43
|
+
export const GoARadioGroupControlTester: RankedTester = rankWith(20, and(isEnumControl, optionIs('format', 'radio')));
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { CellProps, WithClassname, ControlProps, isIntegerControl, RankedTester, rankWith } from '@jsonforms/core';
|
|
3
|
+
import { GoAInput, GoAInputNumber } from '@abgov/react-components-new';
|
|
4
|
+
import { WithInputProps } from './type';
|
|
5
|
+
import { withJsonFormsControlProps } from '@jsonforms/react';
|
|
6
|
+
import { GoAInputBaseControl } from './InputBaseControl';
|
|
7
|
+
import { checkFieldValidity, isValidDate } from '../../util/stringUtils';
|
|
8
|
+
type GoAInputIntegerProps = CellProps & WithClassname & WithInputProps;
|
|
9
|
+
|
|
10
|
+
export const GoAInputInteger = (props: GoAInputIntegerProps): JSX.Element => {
|
|
11
|
+
// eslint-disable-next-line
|
|
12
|
+
const { data, config, id, enabled, uischema, isValid, path, handleChange, schema, label } = props;
|
|
13
|
+
const appliedUiSchemaOptions = { ...config, ...uischema?.options };
|
|
14
|
+
const placeholder = appliedUiSchemaOptions?.placeholder || schema?.description || '';
|
|
15
|
+
const InputValue = data && data !== undefined ? data : '';
|
|
16
|
+
const clonedSchema = JSON.parse(JSON.stringify(schema));
|
|
17
|
+
const StepValue = clonedSchema.multipleOf ? clonedSchema.multipleOf : 0;
|
|
18
|
+
const MinValue = clonedSchema.minimum ? clonedSchema.minimum : '';
|
|
19
|
+
const MaxValue = clonedSchema.exclusiveMaximum ? clonedSchema.exclusiveMaximum : '';
|
|
20
|
+
const errorsFormInput = checkFieldValidity(props as ControlProps);
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<GoAInput
|
|
24
|
+
type="number"
|
|
25
|
+
error={errorsFormInput.length > 0}
|
|
26
|
+
width="100%"
|
|
27
|
+
disabled={!enabled}
|
|
28
|
+
value={InputValue}
|
|
29
|
+
step={StepValue}
|
|
30
|
+
min={MinValue}
|
|
31
|
+
max={MaxValue}
|
|
32
|
+
placeholder={placeholder}
|
|
33
|
+
name={appliedUiSchemaOptions?.name || `${id || label}-input`}
|
|
34
|
+
testId={appliedUiSchemaOptions?.testId || `${id}-input`}
|
|
35
|
+
onKeyPress={(name: string, value: string, key: string) => {
|
|
36
|
+
if (!(key === 'Tab' || key === 'Shift')) {
|
|
37
|
+
let newValue: string | number = '';
|
|
38
|
+
if (value !== '') {
|
|
39
|
+
newValue = +value;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
handleChange(path, newValue);
|
|
43
|
+
}
|
|
44
|
+
}}
|
|
45
|
+
onBlur={(name: string, value: string) => {
|
|
46
|
+
let newValue: string | number = '';
|
|
47
|
+
if (value !== '') {
|
|
48
|
+
newValue = +value;
|
|
49
|
+
}
|
|
50
|
+
handleChange(path, newValue);
|
|
51
|
+
}}
|
|
52
|
+
//Dont trigger the handleChange event on the onChange event as it will cause
|
|
53
|
+
//issue with the error message from displaying, use keyPress or the onBlur event instead
|
|
54
|
+
onChange={(name: string, value: string) => {}}
|
|
55
|
+
{...uischema?.options?.componentProps}
|
|
56
|
+
/>
|
|
57
|
+
);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const GoAIntegerControl = (props: ControlProps) => <GoAInputBaseControl {...props} input={GoAInputInteger} />;
|
|
61
|
+
|
|
62
|
+
export const GoAIntegerControlTester: RankedTester = rankWith(2, isIntegerControl);
|
|
63
|
+
export const GoAInputIntegerControl = withJsonFormsControlProps(GoAIntegerControl);
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
CellProps,
|
|
4
|
+
WithClassname,
|
|
5
|
+
ControlProps,
|
|
6
|
+
isStringControl,
|
|
7
|
+
RankedTester,
|
|
8
|
+
rankWith,
|
|
9
|
+
and,
|
|
10
|
+
optionIs,
|
|
11
|
+
} from '@jsonforms/core';
|
|
12
|
+
import { GoATextArea } from '@abgov/react-components-new';
|
|
13
|
+
import { WithInputProps } from './type';
|
|
14
|
+
import { withJsonFormsControlProps } from '@jsonforms/react';
|
|
15
|
+
import { GoAInputBaseControl } from './InputBaseControl';
|
|
16
|
+
import { checkFieldValidity } from '../../util/stringUtils';
|
|
17
|
+
type GoAInputTextProps = CellProps & WithClassname & WithInputProps;
|
|
18
|
+
|
|
19
|
+
export const MultiLineText = (props: GoAInputTextProps): JSX.Element => {
|
|
20
|
+
// eslint-disable-next-line
|
|
21
|
+
const { data, config, id, enabled, uischema, path, handleChange, schema, label } = props;
|
|
22
|
+
|
|
23
|
+
const appliedUiSchemaOptions = { ...config, ...uischema?.options };
|
|
24
|
+
const placeholder = appliedUiSchemaOptions?.placeholder || schema?.description || '';
|
|
25
|
+
const errorsFormInput = checkFieldValidity(props as ControlProps);
|
|
26
|
+
const autoCapitalize =
|
|
27
|
+
uischema?.options?.componentProps?.autoCapitalize === true || uischema?.options?.autoCapitalize === true;
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<GoATextArea
|
|
31
|
+
error={errorsFormInput.length > 0}
|
|
32
|
+
value={data}
|
|
33
|
+
disabled={!enabled}
|
|
34
|
+
placeholder={placeholder}
|
|
35
|
+
testId={appliedUiSchemaOptions?.testId || `${id}-input`}
|
|
36
|
+
name={`${label || path}-text-area`}
|
|
37
|
+
width={'100%'}
|
|
38
|
+
// Note: Paul Jan-09-2023. The latest ui-component come with the maxCount. We need to uncomment the following line when the component is updated
|
|
39
|
+
// maxCount={schema.maxLength || 256}
|
|
40
|
+
onKeyPress={(name: string, value: string, key: string) => {
|
|
41
|
+
if (!(key === 'Tab' || key === 'Shift')) {
|
|
42
|
+
if (autoCapitalize === true) {
|
|
43
|
+
handleChange(path, value.toUpperCase());
|
|
44
|
+
} else {
|
|
45
|
+
handleChange(path, value);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}}
|
|
49
|
+
// Dont use handleChange in the onChange event, use the keyPress or onBlur.
|
|
50
|
+
// If you use it onChange along with keyPress event it will cause a
|
|
51
|
+
// side effect that causes the validation to render when it shouldnt.
|
|
52
|
+
onChange={() => {}}
|
|
53
|
+
{...uischema?.options?.componentProps}
|
|
54
|
+
/>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const MultiLineTextControlInput = (props: ControlProps) => (
|
|
59
|
+
<GoAInputBaseControl {...props} input={MultiLineText} />
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
export const MultiLineTextControlTester: RankedTester = rankWith(3, and(isStringControl, optionIs('multi', true)));
|
|
63
|
+
export const MultiLineTextControl = withJsonFormsControlProps(MultiLineTextControlInput);
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { CellProps, WithClassname, ControlProps, isNumberControl, RankedTester, rankWith } from '@jsonforms/core';
|
|
3
|
+
import { GoAInput } from '@abgov/react-components-new';
|
|
4
|
+
import { WithInputProps } from './type';
|
|
5
|
+
import { withJsonFormsControlProps } from '@jsonforms/react';
|
|
6
|
+
import { GoAInputBaseControl } from './InputBaseControl';
|
|
7
|
+
import { checkFieldValidity } from '../../util/stringUtils';
|
|
8
|
+
type GoAInputNumberProps = CellProps & WithClassname & WithInputProps;
|
|
9
|
+
|
|
10
|
+
export const GoANumberInput = (props: GoAInputNumberProps): JSX.Element => {
|
|
11
|
+
// eslint-disable-next-line
|
|
12
|
+
const { data, config, id, enabled, uischema, isValid, path, handleChange, schema, label } = props;
|
|
13
|
+
|
|
14
|
+
const appliedUiSchemaOptions = { ...config, ...uischema?.options };
|
|
15
|
+
const placeholder = appliedUiSchemaOptions?.placeholder || schema?.description || '';
|
|
16
|
+
const InputValue = data && data !== undefined ? data : '';
|
|
17
|
+
const clonedSchema = JSON.parse(JSON.stringify(schema));
|
|
18
|
+
const StepValue = clonedSchema.multipleOf ? clonedSchema.multipleOf : 0.01;
|
|
19
|
+
const MinValue = clonedSchema.minimum ? clonedSchema.minimum : '';
|
|
20
|
+
const MaxValue = clonedSchema.exclusiveMaximum ? clonedSchema.exclusiveMaximum : '';
|
|
21
|
+
const errorsFormInput = checkFieldValidity(props as ControlProps);
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<GoAInput
|
|
25
|
+
type="number"
|
|
26
|
+
error={errorsFormInput.length > 0}
|
|
27
|
+
disabled={!enabled}
|
|
28
|
+
value={InputValue}
|
|
29
|
+
placeholder={placeholder}
|
|
30
|
+
step={StepValue}
|
|
31
|
+
min={MinValue}
|
|
32
|
+
max={MaxValue}
|
|
33
|
+
width="100%"
|
|
34
|
+
name={appliedUiSchemaOptions?.name || `${id || label}-input`}
|
|
35
|
+
testId={appliedUiSchemaOptions?.testId || `${id}-input`}
|
|
36
|
+
onKeyPress={(name: string, value: string, key: string) => {
|
|
37
|
+
if (!(key === 'Tab' || key === 'Shift')) {
|
|
38
|
+
let newValue: string | number = '';
|
|
39
|
+
if (value !== '') {
|
|
40
|
+
newValue = +value;
|
|
41
|
+
}
|
|
42
|
+
handleChange(path, newValue);
|
|
43
|
+
}
|
|
44
|
+
}}
|
|
45
|
+
onBlur={(name: string, value: string) => {
|
|
46
|
+
let newValue: string | number = '';
|
|
47
|
+
if (value !== '') {
|
|
48
|
+
newValue = +value;
|
|
49
|
+
}
|
|
50
|
+
handleChange(path, newValue);
|
|
51
|
+
}}
|
|
52
|
+
//Dont trigger the handleChange event on the onChange event as it will cause
|
|
53
|
+
//issue with the error message from displaying, use keyPress or the onBlur event instead
|
|
54
|
+
onChange={(name: string, value: string) => {}}
|
|
55
|
+
{...uischema?.options?.componentProps}
|
|
56
|
+
/>
|
|
57
|
+
);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const GoANumberControl = (props: ControlProps) => <GoAInputBaseControl {...props} input={GoANumberInput} />;
|
|
61
|
+
|
|
62
|
+
export const GoANumberControlTester: RankedTester = rankWith(2, isNumberControl);
|
|
63
|
+
export const GoAInputNumberControl = withJsonFormsControlProps(GoANumberControl);
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { CellProps, WithClassname, ControlProps, isStringControl, RankedTester, rankWith } from '@jsonforms/core';
|
|
3
|
+
import { withJsonFormsControlProps } from '@jsonforms/react';
|
|
4
|
+
import { GoAInput, GoAFormItem } from '@abgov/react-components-new';
|
|
5
|
+
import { WithInputProps } from './type';
|
|
6
|
+
import { GoAInputBaseControl } from './InputBaseControl';
|
|
7
|
+
import { checkFieldValidity, getLabelText } from '../../util/stringUtils';
|
|
8
|
+
|
|
9
|
+
type GoAInputTextProps = CellProps & WithClassname & WithInputProps;
|
|
10
|
+
|
|
11
|
+
export const GoAInputText = (props: GoAInputTextProps): JSX.Element => {
|
|
12
|
+
// eslint-disable-next-line
|
|
13
|
+
const { data, config, id, enabled, uischema, isValid, errors, path, handleChange, schema, label } = props;
|
|
14
|
+
|
|
15
|
+
const appliedUiSchemaOptions = { ...config, ...uischema?.options };
|
|
16
|
+
const placeholder = appliedUiSchemaOptions?.placeholder || schema?.description || '';
|
|
17
|
+
|
|
18
|
+
const errorsFormInput = checkFieldValidity(props as ControlProps);
|
|
19
|
+
|
|
20
|
+
const autoCapitalize =
|
|
21
|
+
uischema?.options?.componentProps?.autoCapitalize === true || uischema?.options?.autoCapitalize === true;
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<GoAInput
|
|
25
|
+
error={errorsFormInput.length > 0}
|
|
26
|
+
type={appliedUiSchemaOptions.format === 'password' ? 'password' : 'text'}
|
|
27
|
+
disabled={!enabled}
|
|
28
|
+
value={data}
|
|
29
|
+
width={'100%'}
|
|
30
|
+
placeholder={placeholder}
|
|
31
|
+
// maxLength={appliedUiSchemaOptions?.maxLength}
|
|
32
|
+
name={appliedUiSchemaOptions?.name || `${id || label}-input`}
|
|
33
|
+
testId={appliedUiSchemaOptions?.testId || `${id}-input`}
|
|
34
|
+
// Dont use handleChange in the onChange event, use the keyPress or onBlur.
|
|
35
|
+
// If you use it onChange along with keyPress event it will cause a
|
|
36
|
+
// side effect that causes the validation to render when it shouldnt.
|
|
37
|
+
onChange={(name: string, value: string) => {}}
|
|
38
|
+
onKeyPress={(name: string, value: string, key: string) => {
|
|
39
|
+
if (!(key === 'Tab' || key === 'Shift')) {
|
|
40
|
+
if (autoCapitalize === true) {
|
|
41
|
+
handleChange(path, value.toUpperCase());
|
|
42
|
+
} else {
|
|
43
|
+
handleChange(path, value);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}}
|
|
47
|
+
onBlur={(name: string, value: string) => {
|
|
48
|
+
if (autoCapitalize === true) {
|
|
49
|
+
handleChange(path, value.toUpperCase());
|
|
50
|
+
} else {
|
|
51
|
+
handleChange(path, value);
|
|
52
|
+
}
|
|
53
|
+
}}
|
|
54
|
+
{...uischema?.options?.componentProps}
|
|
55
|
+
/>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const GoATextControl = (props: ControlProps) => <GoAInputBaseControl {...props} input={GoAInputText} />;
|
|
60
|
+
|
|
61
|
+
export const GoATextControlTester: RankedTester = rankWith(1, isStringControl);
|
|
62
|
+
export const GoAInputTextControl = withJsonFormsControlProps(GoATextControl);
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { CellProps, WithClassname, ControlProps, isTimeControl, RankedTester, rankWith } from '@jsonforms/core';
|
|
3
|
+
import { GoAInputTime } from '@abgov/react-components-new';
|
|
4
|
+
import { WithInputProps } from './type';
|
|
5
|
+
import { withJsonFormsControlProps } from '@jsonforms/react';
|
|
6
|
+
import { GoAInputBaseControl } from './InputBaseControl';
|
|
7
|
+
import { checkFieldValidity, isValidDate } from '../../util/stringUtils';
|
|
8
|
+
type GoAInputTimeProps = CellProps & WithClassname & WithInputProps;
|
|
9
|
+
|
|
10
|
+
export const GoATimeInput = (props: GoAInputTimeProps): JSX.Element => {
|
|
11
|
+
// eslint-disable-next-line
|
|
12
|
+
const { data, config, id, enabled, uischema, isValid, path, handleChange, schema, label } = props;
|
|
13
|
+
const appliedUiSchemaOptions = { ...config, ...uischema?.options };
|
|
14
|
+
const placeholder = appliedUiSchemaOptions?.placeholder || schema?.description || '';
|
|
15
|
+
const errorsFormInput = checkFieldValidity(props as ControlProps);
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<GoAInputTime
|
|
19
|
+
error={errorsFormInput.length > 0}
|
|
20
|
+
name={appliedUiSchemaOptions?.name || `${id || label}-input`}
|
|
21
|
+
value={data}
|
|
22
|
+
step={1}
|
|
23
|
+
width="100%"
|
|
24
|
+
disabled={!enabled}
|
|
25
|
+
testId={appliedUiSchemaOptions?.testId || `${id}-input`}
|
|
26
|
+
onBlur={(name: string, value: string) => {
|
|
27
|
+
handleChange(path, value);
|
|
28
|
+
}}
|
|
29
|
+
// Dont use handleChange in the onChange event, use the keyPress or onBlur.
|
|
30
|
+
// If you use it onChange along with keyPress event it will cause a
|
|
31
|
+
// side effect that causes the validation to render when it shouldnt.
|
|
32
|
+
onChange={(name, value) => {}}
|
|
33
|
+
onKeyPress={(name: string, value: string, key: string) => {
|
|
34
|
+
if (!(key === 'Tab' || key === 'Shift')) {
|
|
35
|
+
handleChange(path, value);
|
|
36
|
+
}
|
|
37
|
+
}}
|
|
38
|
+
{...uischema?.options?.componentProps}
|
|
39
|
+
/>
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const GoATimeControl = (props: ControlProps) => <GoAInputBaseControl {...props} input={GoATimeInput} />;
|
|
44
|
+
|
|
45
|
+
export const GoATimeControlTester: RankedTester = rankWith(4, isTimeControl);
|
|
46
|
+
export const GoAInputTimeControl = withJsonFormsControlProps(GoATimeControl);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from './InputBaseControl';
|
|
2
|
+
export * from './InputTextControl';
|
|
3
|
+
export * from './InputMultiLineTextControl';
|
|
4
|
+
export * from './InputDateControl';
|
|
5
|
+
export * from './InputNumberControl';
|
|
6
|
+
export * from './InputIntegerControl';
|
|
7
|
+
export * from './InputDateTimeControl';
|
|
8
|
+
export * from './InputTimeControl';
|
|
9
|
+
export * from './InputEnum';
|
|
10
|
+
export * from './InputEnumAutoComplete';
|
|
11
|
+
export * from './InputEnumRadios';
|
|
12
|
+
export * from './InputBooleanControl';
|
|
13
|
+
export * from './InputBooleanRadioControl';
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render } from '@testing-library/react';
|
|
3
|
+
import '@testing-library/jest-dom';
|
|
4
|
+
import { GoADateInput, errMalformedDate } from './InputDateControl';
|
|
5
|
+
import { GoAInputDateProps } from './InputDateControl';
|
|
6
|
+
import { ControlElement } from '@jsonforms/core';
|
|
7
|
+
|
|
8
|
+
const theDate = {
|
|
9
|
+
theDate: '',
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const dateSchema = {
|
|
13
|
+
type: 'object',
|
|
14
|
+
properties: {
|
|
15
|
+
theDate: {
|
|
16
|
+
type: 'string',
|
|
17
|
+
format: 'date',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const uiSchema = (min: string, max: string): ControlElement => {
|
|
23
|
+
return {
|
|
24
|
+
type: 'Control',
|
|
25
|
+
scope: '#/properties/theDate',
|
|
26
|
+
label: 'Date control test',
|
|
27
|
+
options: {
|
|
28
|
+
componentProps: {
|
|
29
|
+
min: min,
|
|
30
|
+
max: max,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const staticProps: GoAInputDateProps = {
|
|
37
|
+
uischema: uiSchema('2023-02-01', '2025-02-01'),
|
|
38
|
+
schema: dateSchema,
|
|
39
|
+
rootSchema: dateSchema,
|
|
40
|
+
handleChange: () => {},
|
|
41
|
+
enabled: true,
|
|
42
|
+
label: 'Date control test',
|
|
43
|
+
id: 'My ID',
|
|
44
|
+
config: {},
|
|
45
|
+
path: '',
|
|
46
|
+
errors: '',
|
|
47
|
+
data: theDate.theDate,
|
|
48
|
+
visible: true,
|
|
49
|
+
isValid: true,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
describe('input control tests', () => {
|
|
53
|
+
describe('input date control tests', () => {
|
|
54
|
+
it('can render valid date', () => {
|
|
55
|
+
const props = { ...staticProps, uischema: uiSchema('2023-02-01', '2025-02-01') };
|
|
56
|
+
const component = render(GoADateInput(props));
|
|
57
|
+
expect(component.getByTestId('My ID-input')).toBeInTheDocument();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('can detect malformed max dates in schema', () => {
|
|
61
|
+
const props = { ...staticProps, uischema: uiSchema('2023-02-01', '2025a/02-01') };
|
|
62
|
+
const component = render(GoADateInput(props));
|
|
63
|
+
expect(component.getByText(errMalformedDate(props.uischema.scope, 'Max'))).toBeInTheDocument();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('can detect malformed min dates in schema', () => {
|
|
67
|
+
const props = { ...staticProps, uischema: uiSchema('2023b/02-01', '2025-02-01') };
|
|
68
|
+
const component = render(GoADateInput(props));
|
|
69
|
+
expect(component.getByText(errMalformedDate(props.uischema.scope, 'Min'))).toBeInTheDocument();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('will reformat non-standard min dates', () => {
|
|
73
|
+
const props = { ...staticProps, uischema: uiSchema('2023/02-01', '2025-02-01') };
|
|
74
|
+
const component = render(GoADateInput(props));
|
|
75
|
+
expect(component.getByTestId('My ID-input')).toBeInTheDocument();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('will reformat non-standard max', () => {
|
|
79
|
+
const props = { ...staticProps, uischema: uiSchema('2023-02-01', '2025/02-01') };
|
|
80
|
+
const component = render(GoADateInput(props));
|
|
81
|
+
expect(component.getByTestId('My ID-input')).toBeInTheDocument();
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { GoAButton, GoAModal, GoAButtonGroup } from '@abgov/react-components-new';
|
|
3
|
+
import { DeleteDialogContent } from './styled-components';
|
|
4
|
+
|
|
5
|
+
export interface DeleteDialogProps {
|
|
6
|
+
open: boolean;
|
|
7
|
+
onConfirm(): void;
|
|
8
|
+
onCancel(): void;
|
|
9
|
+
title: string;
|
|
10
|
+
message: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface WithDeleteDialogSupport {
|
|
14
|
+
openDeleteDialog(path: string, data: number): void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const DeleteDialog = React.memo(function DeleteDialog({
|
|
18
|
+
open,
|
|
19
|
+
onConfirm,
|
|
20
|
+
onCancel,
|
|
21
|
+
title,
|
|
22
|
+
message,
|
|
23
|
+
}: DeleteDialogProps) {
|
|
24
|
+
return (
|
|
25
|
+
<GoAModal open={open} key={1} testId="object-array-modal" heading={title}>
|
|
26
|
+
<DeleteDialogContent data-testid="object-array-modal-content">{message}</DeleteDialogContent>
|
|
27
|
+
<GoAButtonGroup alignment="end">
|
|
28
|
+
<GoAButton
|
|
29
|
+
type="secondary"
|
|
30
|
+
testId="object-array-modal-button"
|
|
31
|
+
onClick={() => {
|
|
32
|
+
onCancel();
|
|
33
|
+
}}
|
|
34
|
+
>
|
|
35
|
+
Cancel
|
|
36
|
+
</GoAButton>
|
|
37
|
+
<GoAButton
|
|
38
|
+
type="primary"
|
|
39
|
+
testId="object-array-confirm-button"
|
|
40
|
+
onClick={() => {
|
|
41
|
+
onConfirm();
|
|
42
|
+
}}
|
|
43
|
+
>
|
|
44
|
+
Delete
|
|
45
|
+
</GoAButton>
|
|
46
|
+
</GoAButtonGroup>
|
|
47
|
+
</GoAModal>
|
|
48
|
+
);
|
|
49
|
+
});
|