@dartech/arsenal-ui 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.
Files changed (124) hide show
  1. package/.babelrc +12 -0
  2. package/.eslintrc.json +22 -0
  3. package/README.md +7 -0
  4. package/index.ts +3 -0
  5. package/jest.config.js +9 -0
  6. package/package.json +21 -0
  7. package/project.json +69 -0
  8. package/rollup.config.js +135 -0
  9. package/src/interfaces/common.ts +12 -0
  10. package/src/interfaces/definition.ts +143 -0
  11. package/src/interfaces/index.ts +3 -0
  12. package/src/interfaces/ui.ts +35 -0
  13. package/src/lib/Alert/Alert.tsx +108 -0
  14. package/src/lib/Alert/index.ts +1 -0
  15. package/src/lib/Definition/CreateDefinition/CreateDefinition.tsx +74 -0
  16. package/src/lib/Definition/CreateDefinition/index.ts +1 -0
  17. package/src/lib/Definition/DefinitionFiller/DefinitionFiller.tsx +85 -0
  18. package/src/lib/Definition/DefinitionFiller/WidgetDefinitionFiller.tsx +96 -0
  19. package/src/lib/Definition/DefinitionFiller/index.ts +2 -0
  20. package/src/lib/Definition/index.ts +2 -0
  21. package/src/lib/DemPropertyField/DemPropertyField.tsx +93 -0
  22. package/src/lib/DemPropertyField/DemPropertyView/DemPropertyView.tsx +44 -0
  23. package/src/lib/DemPropertyField/DemPropertyView/index.ts +1 -0
  24. package/src/lib/DemPropertyField/MultipleDemField/MultipleDemField.tsx +293 -0
  25. package/src/lib/DemPropertyField/MultipleDemField/index.tsx +1 -0
  26. package/src/lib/DemPropertyField/RestrictedValuesEditor.tsx +63 -0
  27. package/src/lib/DemPropertyField/SingleDemField/SingleDemField.tsx +156 -0
  28. package/src/lib/DemPropertyField/SingleDemField/index.ts +1 -0
  29. package/src/lib/DemPropertyField/index.ts +2 -0
  30. package/src/lib/DemPropertyField/styles.ts +50 -0
  31. package/src/lib/DemPropertyField/widgets/DemBooleanWidget.tsx +26 -0
  32. package/src/lib/DemPropertyField/widgets/DemDateTimeWidget.tsx +34 -0
  33. package/src/lib/DemPropertyField/widgets/DemDateWidget.tsx +33 -0
  34. package/src/lib/DemPropertyField/widgets/DemFieldWidget.tsx +67 -0
  35. package/src/lib/DemPropertyField/widgets/DemFloatWidget.tsx +49 -0
  36. package/src/lib/DemPropertyField/widgets/DemIntegerWidget.tsx +63 -0
  37. package/src/lib/DemPropertyField/widgets/DemJsonWidget.tsx +33 -0
  38. package/src/lib/DemPropertyField/widgets/DemStringWidget.tsx +35 -0
  39. package/src/lib/DemPropertyField/widgets/DemTimeWidget.tsx +46 -0
  40. package/src/lib/DemPropertyField/widgets/index.ts +1 -0
  41. package/src/lib/Forms/BackButton.tsx +45 -0
  42. package/src/lib/Forms/ControlAceEditor.tsx +103 -0
  43. package/src/lib/Forms/ControlAutocomplete.tsx +134 -0
  44. package/src/lib/Forms/ControlCheckbox.tsx +57 -0
  45. package/src/lib/Forms/ControlDebouncedInput.tsx +69 -0
  46. package/src/lib/Forms/ControlInput.tsx +102 -0
  47. package/src/lib/Forms/ControlNumberInput.tsx +144 -0
  48. package/src/lib/Forms/ControlRadioBtn.tsx +46 -0
  49. package/src/lib/Forms/ControlSelect.tsx +135 -0
  50. package/src/lib/Forms/CopyButton.tsx +49 -0
  51. package/src/lib/Forms/index.ts +10 -0
  52. package/src/lib/InfoItem/InfoItem.tsx +39 -0
  53. package/src/lib/InfoItem/index.ts +1 -0
  54. package/src/lib/InfoItem/styles.ts +17 -0
  55. package/src/lib/JsonPathPicker/JsonPathPicker.tsx +71 -0
  56. package/src/lib/JsonPathPicker/PropertyStep.tsx +74 -0
  57. package/src/lib/JsonPathPicker/index.ts +1 -0
  58. package/src/lib/JsonView/JsonView.tsx +43 -0
  59. package/src/lib/JsonView/index.ts +1 -0
  60. package/src/lib/Loader/Loader.tsx +41 -0
  61. package/src/lib/Loader/index.ts +1 -0
  62. package/src/lib/Modals/JsonModalView.tsx +52 -0
  63. package/src/lib/Modals/index.ts +1 -0
  64. package/src/lib/Property/PropertyValueField/BooleanValueField.tsx +41 -0
  65. package/src/lib/Property/PropertyValueField/DateTimeValueField.tsx +59 -0
  66. package/src/lib/Property/PropertyValueField/DateValueField.tsx +59 -0
  67. package/src/lib/Property/PropertyValueField/EntityValueField.tsx +33 -0
  68. package/src/lib/Property/PropertyValueField/JsonValueField.tsx +64 -0
  69. package/src/lib/Property/PropertyValueField/PropertyValue.tsx +97 -0
  70. package/src/lib/Property/PropertyValueField/PropertyValueField.tsx +86 -0
  71. package/src/lib/Property/PropertyValueField/StringValueField.tsx +21 -0
  72. package/src/lib/Property/PropertyValueField/TimeValueField.tsx +68 -0
  73. package/src/lib/Property/PropertyValueField/ValueComponent.tsx +63 -0
  74. package/src/lib/Property/PropertyValueField/index.ts +1 -0
  75. package/src/lib/Property/PropertyWidget/PropertyWidget.tsx +167 -0
  76. package/src/lib/Property/PropertyWidget/index.ts +1 -0
  77. package/src/lib/Property/UpsertProperty/CreatePropertiesList.tsx +131 -0
  78. package/src/lib/Property/UpsertProperty/CreatePropertyFormFields.tsx +147 -0
  79. package/src/lib/Property/UpsertProperty/CustomPropertyField.tsx +40 -0
  80. package/src/lib/Property/UpsertProperty/PropertyAdditionalFields/BigDecimalPropertyFields.tsx +41 -0
  81. package/src/lib/Property/UpsertProperty/PropertyAdditionalFields/DateAdditionalFields.tsx +27 -0
  82. package/src/lib/Property/UpsertProperty/PropertyAdditionalFields/EntityAdditionalFields.tsx +133 -0
  83. package/src/lib/Property/UpsertProperty/PropertyAdditionalFields/EntityReferencePropertyFields.tsx +46 -0
  84. package/src/lib/Property/UpsertProperty/PropertyAdditionalFields/PropertyAdditionalFields.tsx +52 -0
  85. package/src/lib/Property/UpsertProperty/PropertyAdditionalFields/StringPropertyFields.tsx +98 -0
  86. package/src/lib/Property/UpsertProperty/PropertyAdditionalFields/index.ts +1 -0
  87. package/src/lib/Property/UpsertProperty/index.ts +2 -0
  88. package/src/lib/Property/UpsertProperty/useCustomFields.ts +22 -0
  89. package/src/lib/Property/ViewPropertiesList/ViewPropertiesList.tsx +50 -0
  90. package/src/lib/Property/ViewPropertiesList/index.ts +1 -0
  91. package/src/lib/Property/ViewProperty/EntityPropertiesShortView.tsx +41 -0
  92. package/src/lib/Property/ViewProperty/EntityPropertiesView.tsx +48 -0
  93. package/src/lib/Property/ViewProperty/PropertyDataTable.tsx +139 -0
  94. package/src/lib/Property/ViewProperty/PropertyItem.tsx +46 -0
  95. package/src/lib/Property/ViewProperty/ViewProperty.tsx +52 -0
  96. package/src/lib/Property/ViewProperty/index.ts +1 -0
  97. package/src/lib/Property/index.ts +4 -0
  98. package/src/lib/Status/Status.tsx +15 -0
  99. package/src/lib/Status/index.ts +1 -0
  100. package/src/lib/Status/styles.ts +14 -0
  101. package/src/lib/Table/Table.tsx +116 -0
  102. package/src/lib/Table/TableColumnMenu.tsx +12 -0
  103. package/src/lib/Table/TablePagination.tsx +42 -0
  104. package/src/lib/Table/index.ts +1 -0
  105. package/src/lib/Table/styles.ts +59 -0
  106. package/src/lib/Table/usePagination.ts +15 -0
  107. package/src/lib/Table/useTableQueryPagination.ts +49 -0
  108. package/src/lib/Table/useTableQuerySorting.ts +52 -0
  109. package/src/lib/Tabs/RouteTabs.tsx +54 -0
  110. package/src/lib/Tabs/TabPanel.tsx +42 -0
  111. package/src/lib/Tabs/index.ts +2 -0
  112. package/src/lib/TemplateContent/ExpressionDecorator.tsx +7 -0
  113. package/src/lib/TemplateContent/TemplateContentEditor.tsx +144 -0
  114. package/src/lib/TemplateContent/index.ts +1 -0
  115. package/src/lib/index.ts +14 -0
  116. package/src/utils/common.ts +68 -0
  117. package/src/utils/dem.ts +78 -0
  118. package/src/utils/hooks.ts +41 -0
  119. package/src/utils/index.ts +5 -0
  120. package/src/utils/ui-utils.tsx +71 -0
  121. package/src/utils/validators.ts +130 -0
  122. package/tsconfig.json +24 -0
  123. package/tsconfig.lib.json +22 -0
  124. package/tsconfig.spec.json +19 -0
@@ -0,0 +1,59 @@
1
+ import TextField from '@mui/material/TextField';
2
+ import { DatePicker } from '@mui/x-date-pickers/DatePicker';
3
+
4
+ import { format as dateFnsFormat, isValid } from 'date-fns';
5
+ import { Controller, useFormContext } from 'react-hook-form';
6
+ import { DATE_DEFAULT_FORMAT } from '../../../interfaces';
7
+
8
+ type Props = {
9
+ name: string;
10
+ format: string;
11
+ label?: string;
12
+ required?: boolean;
13
+ };
14
+
15
+ const DateValueField = ({ name, label = '', required = false, format = DATE_DEFAULT_FORMAT }: Props) => {
16
+ const { control, setError, clearErrors } = useFormContext();
17
+
18
+ const onError = (err) => {
19
+ if (err) {
20
+ setError(name, { type: 'custom', message: 'Incorrect date format' });
21
+ } else {
22
+ clearErrors(name);
23
+ }
24
+ };
25
+
26
+ return (
27
+ <Controller
28
+ control={control}
29
+ name={name}
30
+ rules={{ required: required && 'Required field' }}
31
+ render={({ field: { ref, value, onChange }, fieldState: { error } }) => (
32
+ <DatePicker
33
+ clearable
34
+ mask=""
35
+ label={label}
36
+ inputRef={ref}
37
+ inputFormat={format}
38
+ value={value || null}
39
+ onError={onError}
40
+ onChange={(date) => {
41
+ onChange(isValid(date) ? dateFnsFormat(date, format) : date);
42
+ }}
43
+ renderInput={(props) => (
44
+ <TextField
45
+ {...props}
46
+ fullWidth
47
+ size="small"
48
+ variant="outlined"
49
+ error={!!error}
50
+ helperText={error?.message}
51
+ />
52
+ )}
53
+ />
54
+ )}
55
+ />
56
+ );
57
+ };
58
+
59
+ export default DateValueField;
@@ -0,0 +1,33 @@
1
+ import Step from '@material-ui/core/Step';
2
+ import StepContent from '@material-ui/core/StepContent';
3
+ import StepLabel from '@material-ui/core/StepLabel';
4
+ import Stepper from '@material-ui/core/Stepper';
5
+ import PropertyValue from './PropertyValue';
6
+
7
+ import { PropertiesArrayType } from '../../../interfaces';
8
+
9
+ type Props = {
10
+ label?: string;
11
+ name?: string;
12
+ properties: PropertiesArrayType;
13
+ };
14
+
15
+ const EntityValueField = ({ name, properties }: Props) => {
16
+ return properties && properties.length ? (
17
+ <Stepper nonLinear orientation="vertical">
18
+ {properties.map((property, index) => (
19
+ <Step expanded key={index}>
20
+ <StepLabel StepIconProps={{ icon: '', completed: false, active: true }}>
21
+ {property.name} - {property.key}
22
+ </StepLabel>
23
+ <StepContent>
24
+ <PropertyValue name={`${name}.${property.key}`} property={property} label={property.name} />
25
+ </StepContent>
26
+ </Step>
27
+ ))}
28
+ <Step />
29
+ </Stepper>
30
+ ) : null;
31
+ };
32
+
33
+ export default EntityValueField;
@@ -0,0 +1,64 @@
1
+ import AceEditor from 'react-ace';
2
+ import FormHelperText from '@material-ui/core/FormHelperText';
3
+ import Typography from '@material-ui/core/Typography';
4
+ import { Controller, useFormContext } from 'react-hook-form';
5
+
6
+ import 'ace-builds/src-noconflict/ace';
7
+ import 'ace-builds/src-noconflict/mode-json';
8
+
9
+ type Props = {
10
+ name: string;
11
+ label?: string;
12
+ required?: boolean;
13
+ };
14
+
15
+ const JsonValueField = ({ name, label, required = false }: Props) => {
16
+ const { control, setError, clearErrors } = useFormContext();
17
+
18
+ return (
19
+ <>
20
+ <Typography>{label}</Typography>
21
+ <Controller
22
+ control={control}
23
+ name={name}
24
+ rules={{
25
+ required: required && 'Required field',
26
+ }}
27
+ render={({ field: { value, onChange }, fieldState: { error } }) => (
28
+ <>
29
+ <AceEditor
30
+ value={value && typeof value !== 'string' ? JSON.stringify(value, null, 2) : value}
31
+ onChange={(value) => {
32
+ if (!value) {
33
+ onChange('');
34
+ return null;
35
+ }
36
+ try {
37
+ clearErrors(name);
38
+ const val = JSON.parse(value);
39
+ onChange(Array.isArray(val) ? '' : val);
40
+ } catch (e) {
41
+ setError(name, { message: 'Invalid JSON' });
42
+ onChange(value);
43
+ }
44
+ }}
45
+ mode="json"
46
+ width="100%"
47
+ height="200px"
48
+ fontSize="16"
49
+ setOptions={{
50
+ enableSnippets: false,
51
+ copyWithEmptySelection: true,
52
+ showLineNumbers: true,
53
+ tabSize: 2,
54
+ }}
55
+ />
56
+ {error && <FormHelperText error>{error.message}</FormHelperText>}
57
+ </>
58
+ )}
59
+ />
60
+ </>
61
+ );
62
+ };
63
+
64
+ export default JsonValueField;
@@ -0,0 +1,97 @@
1
+ import Box from '@material-ui/core/Box';
2
+ import Grid from '@material-ui/core/Grid';
3
+ import Button from '@material-ui/core/Button';
4
+ import Typography from '@material-ui/core/Typography';
5
+ import IconButton from '@material-ui/core/IconButton';
6
+ import CloseIcon from '@material-ui/icons/Close';
7
+ import ValueComponent, { ValueComponentProps } from './ValueComponent';
8
+
9
+ import { useCallback, useMemo } from 'react';
10
+ import { useFormContext, useWatch } from 'react-hook-form';
11
+
12
+ import { PropertyUnion } from '../../../interfaces';
13
+ import { removeArrayItem } from '../../../utils';
14
+
15
+ type Props = {
16
+ property: PropertyUnion;
17
+ name: string;
18
+ label?: string;
19
+ required?: boolean | 'byProperty';
20
+ };
21
+
22
+ const PropertyValue = ({ property, name, label, required = 'byProperty' }: Props) => {
23
+ const { control, setValue } = useFormContext();
24
+ const values = useWatch({ control, name });
25
+
26
+ const handleDeleteValue = useCallback(
27
+ (index) => {
28
+ setValue(name, removeArrayItem(values, index));
29
+ },
30
+ [name, values]
31
+ );
32
+
33
+ const handleAddValue = useCallback(() => {
34
+ if (values && Array.isArray(values)) {
35
+ setValue(`${name}.${values.length}`, null);
36
+ } else {
37
+ setValue(name, [null]);
38
+ }
39
+ }, [name, values]);
40
+
41
+ const valueComponentProps: ValueComponentProps = useMemo(
42
+ () => ({
43
+ control,
44
+ name,
45
+ label,
46
+ required: required === 'byProperty' ? property.isRequired : required,
47
+ propertyType: typeof property.propertyType === 'string' ? property.propertyType : property.propertyType['value'],
48
+ format: property['format'],
49
+ restrictedValues: property['restrictedValues'],
50
+ properties: property['properties'],
51
+ }),
52
+ [
53
+ name,
54
+ label,
55
+ required,
56
+ property.propertyType,
57
+ property['format'],
58
+ property['restrictedValues'],
59
+ property['properties'],
60
+ ]
61
+ );
62
+
63
+ return property.isMultiple ? (
64
+ <Grid item container spacing={2} direction="column">
65
+ <Grid item>
66
+ <Typography variant="h6">{label}</Typography>
67
+ </Grid>
68
+ {values && Array.isArray(values) ? (
69
+ <>
70
+ {values.map((_, index) => (
71
+ <Grid item key={index}>
72
+ <Box display="flex" alignItems="center">
73
+ <ValueComponent
74
+ {...valueComponentProps}
75
+ label={`${property.name} (${index})`}
76
+ name={`${name}.${index}`}
77
+ />
78
+ <IconButton size="small" onClick={() => handleDeleteValue(index)}>
79
+ <CloseIcon fontSize="small" />
80
+ </IconButton>
81
+ </Box>
82
+ </Grid>
83
+ ))}
84
+ </>
85
+ ) : null}
86
+ <Grid item>
87
+ <Button variant="contained" size="small" color="primary" onClick={handleAddValue}>
88
+ Add value
89
+ </Button>
90
+ </Grid>
91
+ </Grid>
92
+ ) : (
93
+ <ValueComponent {...valueComponentProps} />
94
+ );
95
+ };
96
+
97
+ export default PropertyValue;
@@ -0,0 +1,86 @@
1
+ import Box from '@material-ui/core/Box';
2
+ import Grid from '@material-ui/core/Grid';
3
+ import Button from '@material-ui/core/Button';
4
+ import Typography from '@material-ui/core/Typography';
5
+ import IconButton from '@material-ui/core/IconButton';
6
+ import CloseIcon from '@material-ui/icons/Close';
7
+ import ValueComponent, { ValueComponentProps } from './ValueComponent';
8
+
9
+ import { useCallback, useEffect, useMemo } from 'react';
10
+ import { useFormContext, useWatch } from 'react-hook-form';
11
+ import { removeArrayItem } from '../../../utils';
12
+
13
+ type Props = {
14
+ propertyFieldName: string;
15
+ name: string;
16
+ label?: string;
17
+ required?: boolean;
18
+ };
19
+
20
+ export const PropertyValueField = ({ propertyFieldName, name, label = '', required }: Props) => {
21
+ const { control, setValue } = useFormContext();
22
+
23
+ const propertyType = useWatch({ control, name: `${propertyFieldName}.propertyType` });
24
+ const isMultiple = useWatch({ control, name: `${propertyFieldName}.isMultiple` });
25
+ const format = useWatch({ control, name: `${propertyFieldName}.format` });
26
+ const restrictedValues = useWatch({ control, name: `${propertyFieldName}.restrictedValues` });
27
+ const properties = useWatch({ control, name: `${propertyFieldName}.properties` });
28
+ const values = useWatch({ control, name });
29
+
30
+ useEffect(() => {
31
+ if (isMultiple && !Array.isArray(values)) {
32
+ setValue(name, [values]);
33
+ } else if (!isMultiple && Array.isArray(values)) {
34
+ setValue(name, values[0]);
35
+ }
36
+ }, [isMultiple, values, name]);
37
+
38
+ const valueComponentProps: ValueComponentProps = useMemo(() => {
39
+ const typeValue = typeof propertyType === 'string' ? propertyType : propertyType.value;
40
+ return { control, name, label, required, format, restrictedValues, properties, propertyType: typeValue };
41
+ }, [propertyType, format, restrictedValues, name, label, required, properties]);
42
+
43
+ const handleDeleteValue = useCallback(
44
+ (index) => {
45
+ setValue(name, removeArrayItem(values, index));
46
+ },
47
+ [name, values]
48
+ );
49
+
50
+ const handleAddValue = useCallback(() => {
51
+ if (values && Array.isArray(values)) {
52
+ setValue(`${name}.${values.length}`, null);
53
+ } else {
54
+ setValue(name, [null]);
55
+ }
56
+ }, [name, values]);
57
+
58
+ return isMultiple ? (
59
+ values && Array.isArray(values) ? (
60
+ <Grid item container spacing={2} direction="column">
61
+ <Grid item>
62
+ <Typography variant="h6">{label}</Typography>
63
+ </Grid>
64
+ {values.map((_, index) => (
65
+ <Grid item key={index}>
66
+ <Box display="flex" alignItems="center">
67
+ <ValueComponent {...valueComponentProps} label="" name={`${name}.${index}`} />
68
+ <IconButton size="small" onClick={() => handleDeleteValue(index)}>
69
+ <CloseIcon fontSize="small" />
70
+ </IconButton>
71
+ </Box>
72
+ </Grid>
73
+ ))}
74
+ <Grid item>
75
+ <Button variant="contained" size="small" color="primary" onClick={handleAddValue}>
76
+ Add value
77
+ </Button>
78
+ </Grid>
79
+ </Grid>
80
+ ) : null
81
+ ) : (
82
+ <ValueComponent {...valueComponentProps} />
83
+ );
84
+ };
85
+
86
+ export default PropertyValueField;
@@ -0,0 +1,21 @@
1
+ import { useFormContext, useWatch } from 'react-hook-form';
2
+ import { ControlInput, ControlSelect } from '../../Forms';
3
+
4
+ type Props = {
5
+ name: string;
6
+ label?: string;
7
+ required?: boolean;
8
+ restrictedValues?: string[];
9
+ };
10
+
11
+ const StringValueField = ({ name, label, required = false, restrictedValues }: Props) => {
12
+ const { control } = useFormContext();
13
+
14
+ return Array.isArray(restrictedValues) && restrictedValues.length ? (
15
+ <ControlSelect required={required} control={control} name={name} label={label} options={restrictedValues} />
16
+ ) : (
17
+ <ControlInput required={required} control={control} name={name} label={label} />
18
+ );
19
+ };
20
+
21
+ export default StringValueField;
@@ -0,0 +1,68 @@
1
+ import TextField from '@mui/material/TextField';
2
+ import { TimePicker } from '@mui/x-date-pickers/TimePicker';
3
+
4
+ import { format as dateFnsFormat, isValid, parse } from 'date-fns';
5
+ import { useEffect, useState } from 'react';
6
+ import { useController, useFormContext } from 'react-hook-form';
7
+ import { TIME_DEFAULT_FORMAT } from '../../../interfaces';
8
+
9
+ type Props = {
10
+ name: string;
11
+ label?: string;
12
+ format?: string;
13
+ required?: boolean;
14
+ };
15
+
16
+ const TimeValueField = ({ name, label, format = TIME_DEFAULT_FORMAT, required = false }: Props) => {
17
+ const { control, setError, clearErrors } = useFormContext();
18
+ const {
19
+ field: { ref, onChange, value },
20
+ fieldState: { error },
21
+ } = useController({ control, name, rules: { required: required && 'Required field' } });
22
+
23
+ const [fieldValue, setFieldValue] = useState(null);
24
+
25
+ useEffect(() => {
26
+ if (value && format) {
27
+ let parsedValue = parse(value, format, new Date());
28
+
29
+ if (!isValid(parsedValue)) {
30
+ parsedValue = parse(value, 'HH:mm:ss.SSS', new Date());
31
+ }
32
+
33
+ setFieldValue(parsedValue);
34
+ }
35
+ }, [value, format]);
36
+
37
+ const handleChange = (date: Date) => {
38
+ setFieldValue(date);
39
+ onChange(isValid(date) ? dateFnsFormat(date, format) : date);
40
+ };
41
+
42
+ const onError = (err) => {
43
+ if (err) {
44
+ setError(name, { type: 'custom', message: 'Incorrect date format' });
45
+ } else {
46
+ clearErrors(name);
47
+ }
48
+ };
49
+
50
+ return (
51
+ <TimePicker
52
+ clearable
53
+ mask=""
54
+ inputRef={ref}
55
+ label={label}
56
+ ampm={false}
57
+ value={fieldValue}
58
+ inputFormat={format}
59
+ onError={onError}
60
+ onChange={handleChange}
61
+ renderInput={(props) => (
62
+ <TextField {...props} fullWidth size="small" variant="outlined" error={!!error} helperText={error?.message} />
63
+ )}
64
+ />
65
+ );
66
+ };
67
+
68
+ export default TimeValueField;
@@ -0,0 +1,63 @@
1
+ import { PropertiesArrayType, PropertyType } from '../../../interfaces';
2
+ import { Control } from 'react-hook-form';
3
+ import { DefinitionFiller } from '../../Definition';
4
+ import { ControlInput, ControlNumberInput } from '../../Forms';
5
+ import BooleanValueField from './BooleanValueField';
6
+ import DateTimeValueField from './DateTimeValueField';
7
+ import DateValueField from './DateValueField';
8
+ import JsonValueField from './JsonValueField';
9
+ import StringValueField from './StringValueField';
10
+ import TimeValueField from './TimeValueField';
11
+
12
+ export type ValueComponentProps = {
13
+ control: Control;
14
+ propertyType: PropertyType;
15
+ name: string;
16
+ label: string;
17
+ required: boolean;
18
+ format?: string;
19
+ restrictedValues?: string[];
20
+ properties?: PropertiesArrayType;
21
+ };
22
+
23
+ const ValueComponent = ({
24
+ propertyType,
25
+ control,
26
+ name,
27
+ label,
28
+ required,
29
+ format,
30
+ restrictedValues,
31
+ properties,
32
+ }: ValueComponentProps) => {
33
+ switch (propertyType) {
34
+ case PropertyType.BIG_DECIMAL:
35
+ case PropertyType.FLOAT:
36
+ case PropertyType.DOUBLE:
37
+ return <ControlNumberInput decimal control={control} name={name} label={label} required={required} />;
38
+ case PropertyType.INTEGER:
39
+ case PropertyType.BIG_INTEGER:
40
+ case PropertyType.LONG:
41
+ return <ControlNumberInput control={control} name={name} label={label} required={required} />;
42
+ case PropertyType.BOOLEAN:
43
+ return <BooleanValueField name={name} label={label} />;
44
+ case PropertyType.DATE:
45
+ return <DateValueField name={name} label={label} format={format} required={required} />;
46
+ case PropertyType.TIME:
47
+ return <TimeValueField name={name} label={label} format={format} required={required} />;
48
+ case PropertyType.DATE_TIME:
49
+ return <DateTimeValueField name={name} label={label} format={format} required={required} />;
50
+ case PropertyType.JSON:
51
+ return <JsonValueField name={name} label={label} required={required} />;
52
+ case PropertyType.STRING:
53
+ return <StringValueField name={name} label={label} required={required} restrictedValues={restrictedValues} />;
54
+ case PropertyType.ENTITY_REFERENCE:
55
+ return <ControlInput name={name} control={control} label={label} required={required} />;
56
+ case PropertyType.ENTITY:
57
+ return <DefinitionFiller dataFieldName={name} properties={properties} />;
58
+ default:
59
+ return null;
60
+ }
61
+ };
62
+
63
+ export default ValueComponent;
@@ -0,0 +1 @@
1
+ export * from './PropertyValueField';
@@ -0,0 +1,167 @@
1
+ import Box from '@material-ui/core/Box';
2
+ import Select from '@material-ui/core/Select';
3
+ import MenuItem from '@material-ui/core/MenuItem';
4
+ import FormControl from '@material-ui/core/FormControl';
5
+ import InputLabel from '@material-ui/core/InputLabel';
6
+ import Typography from '@material-ui/core/Typography';
7
+ import { ControlAceEditor, ControlInput } from '../../Forms';
8
+ import PropertyValue from '../PropertyValueField/PropertyValue';
9
+ import { WidgetDefinitionFiller } from '../../Definition';
10
+
11
+ import { useEffect, useMemo, useState } from 'react';
12
+ import { useController, useFormContext, useWatch } from 'react-hook-form';
13
+ import { getEntityStarterValue, isExpression } from '../../../utils';
14
+
15
+ import { PropertyType, PropertyUnion } from '../../../interfaces';
16
+
17
+ type Props = {
18
+ property: PropertyUnion;
19
+ nullable?: boolean;
20
+ name: string;
21
+ };
22
+
23
+ type InputType = 'expression' | 'widget' | 'null' | 'string';
24
+
25
+ const getInputTypes = (propertyType: PropertyType, nullable: boolean): { value: InputType; label: string }[] => {
26
+ const options: { value: InputType; label: string }[] = [
27
+ {
28
+ value: 'widget',
29
+ label: 'Widget',
30
+ },
31
+ {
32
+ value: 'expression',
33
+ label: 'Expression',
34
+ },
35
+ ];
36
+
37
+ if (nullable) {
38
+ options.push({
39
+ value: 'null',
40
+ label: 'NULL',
41
+ });
42
+ }
43
+
44
+ switch (propertyType) {
45
+ case PropertyType.STRING:
46
+ options[0].label = 'Text input';
47
+ break;
48
+ case PropertyType.INTEGER:
49
+ case PropertyType.BIG_INTEGER:
50
+ case PropertyType.BIG_DECIMAL:
51
+ case PropertyType.FLOAT:
52
+ case PropertyType.LONG:
53
+ case PropertyType.DOUBLE:
54
+ options[0].label = 'Number input';
55
+ break;
56
+ case PropertyType.BOOLEAN:
57
+ options[0].label = 'Checkbox';
58
+ break;
59
+ case PropertyType.ENTITY_REFERENCE:
60
+ options[0].label = 'Entity reference fields';
61
+ break;
62
+ case PropertyType.JSON:
63
+ options[0].label = 'JSON';
64
+ break;
65
+ case PropertyType.DATE:
66
+ options[0].label = 'Date';
67
+ options.push({ value: 'string', label: 'Text input' });
68
+ break;
69
+ case PropertyType.DATE_TIME:
70
+ options[0].label = 'Date time';
71
+ options.push({ value: 'string', label: 'Text input' });
72
+ break;
73
+ case PropertyType.TIME:
74
+ options[0].label = 'Time';
75
+ options.push({ value: 'string', label: 'Text input' });
76
+ break;
77
+ default:
78
+ break;
79
+ }
80
+
81
+ return options;
82
+ };
83
+
84
+ export const PropertyWidget = ({ property, name = '', nullable = false }: Props) => {
85
+ const { control, setValue } = useFormContext();
86
+ const {
87
+ fieldState: { error },
88
+ } = useController({ name });
89
+ const value = useWatch({ control, name });
90
+
91
+ const [inputType, setInputType] = useState<InputType>('widget');
92
+
93
+ const inputOptions = useMemo(
94
+ () => getInputTypes(property.propertyType, nullable && !property.isRequired),
95
+ [property, nullable]
96
+ );
97
+
98
+ const handleInputTypeChange = (event: React.ChangeEvent<{ value: InputType }>) => {
99
+ setInputType(event.target.value);
100
+ };
101
+
102
+ useEffect(() => {
103
+ if (value && !inputType) {
104
+ if (value === null && nullable && !property.isRequired) {
105
+ setInputType('null');
106
+ } else if (isExpression(inputType)) {
107
+ setInputType('expression');
108
+ } else {
109
+ setInputType('widget');
110
+ }
111
+ }
112
+ }, [value, inputType, property.isRequired, nullable]);
113
+
114
+ useEffect(() => {
115
+ if (!value && inputType === 'expression' && property.propertyType === PropertyType.ENTITY) {
116
+ setValue(name, JSON.stringify(getEntityStarterValue(property), null, 2));
117
+ }
118
+ }, [value, inputType, property.propertyType]);
119
+
120
+ return (
121
+ <>
122
+ {inputOptions.length ? (
123
+ <>
124
+ <Box mb={2}>
125
+ <FormControl fullWidth size="small" variant="outlined">
126
+ <InputLabel htmlFor="type-select">Input type</InputLabel>
127
+ <Select labelId="type-select" label="Input type" value={inputType} onChange={handleInputTypeChange}>
128
+ {inputOptions.map((option) => (
129
+ <MenuItem key={option.value} value={option.value}>
130
+ {option.label}
131
+ </MenuItem>
132
+ ))}
133
+ </Select>
134
+ </FormControl>
135
+ </Box>
136
+ {inputType ? (
137
+ <>
138
+ {inputType === 'widget' &&
139
+ (property.propertyType === PropertyType.ENTITY ? (
140
+ <WidgetDefinitionFiller dataFieldName={name} properties={property.properties} nullable={nullable} />
141
+ ) : (
142
+ <PropertyValue name={name} property={property} label={property.name} />
143
+ ))}
144
+ {inputType === 'expression' &&
145
+ (property.propertyType === PropertyType.ENTITY || property.propertyType === PropertyType.JSON ? (
146
+ <ControlAceEditor
147
+ required
148
+ mode="json"
149
+ fontSize={14}
150
+ validateJson={false}
151
+ control={control}
152
+ name={name}
153
+ />
154
+ ) : (
155
+ <ControlInput required name={name} control={control} label="Expression" />
156
+ ))}
157
+ {inputType === 'string' && <ControlInput required name={name} control={control} label={'Text input'} />}
158
+ </>
159
+ ) : null}
160
+ </>
161
+ ) : null}
162
+ {error && <Typography color="secondary">{error.message}</Typography>}
163
+ </>
164
+ );
165
+ };
166
+
167
+ export default PropertyWidget;
@@ -0,0 +1 @@
1
+ export * from './PropertyWidget';