@centreon/ui 23.10.18-MON-17793-create-graph-component-centreon-ui.13 → 23.10.18-MON-17793-create-graph-component-centreon-ui.14
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/package.json +1 -1
- package/src/Checkbox/Checkbox.tsx +107 -0
- package/src/Checkbox/CheckboxGroup/index.stories.tsx +41 -0
- package/src/Checkbox/CheckboxGroup/index.tsx +66 -0
- package/src/Checkbox/index.stories.tsx +39 -0
- package/src/Checkbox/index.tsx +2 -0
- package/src/Form/CollapsibleGroup.tsx +11 -5
- package/src/Form/Form.stories.tsx +1 -1
- package/src/Form/Form.tsx +24 -9
- package/src/Form/Inputs/Checkbox.tsx +57 -0
- package/src/Form/Inputs/CheckboxGroup.tsx +76 -0
- package/src/Form/Inputs/Grid.tsx +4 -2
- package/src/Form/Inputs/index.tsx +29 -7
- package/src/Form/Inputs/models.ts +13 -1
- package/src/Form/storiesData.tsx +45 -0
- package/src/Graph/BasicComponents/Lines/StackedLines/index.tsx +36 -20
- package/src/Graph/BasicComponents/Lines/index.tsx +101 -82
- package/src/Graph/Graph.tsx +24 -129
- package/src/Graph/Header/index.tsx +35 -23
- package/src/Graph/{IntercatifsComponents → InteractiveComponents}/AnchorPoint/RegularAnchorPoint.tsx +14 -13
- package/src/Graph/{IntercatifsComponents → InteractiveComponents}/AnchorPoint/StackedAnchorPoint.tsx +8 -19
- package/src/Graph/InteractiveComponents/AnchorPoint/useTickGraph.ts +57 -0
- package/src/Graph/{IntercatifsComponents → InteractiveComponents}/Annotations/useAnnotation.ts +6 -12
- package/src/Graph/{IntercatifsComponents → InteractiveComponents}/ZoomPreview/index.tsx +1 -3
- package/src/Graph/{IntercatifsComponents → InteractiveComponents}/ZoomPreview/models.ts +0 -3
- package/src/Graph/{IntercatifsComponents → InteractiveComponents}/ZoomPreview/useZoomPreview.ts +7 -13
- package/src/Graph/{IntercatifsComponents → InteractiveComponents}/index.tsx +44 -13
- package/src/Graph/{IntercatifsComponents → InteractiveComponents}/interactionWithGraphAtoms.ts +0 -1
- package/src/Graph/Legend/index.tsx +16 -2
- package/src/Graph/Legend/useInteractiveValues.ts +10 -8
- package/src/Graph/graphAtoms.ts +1 -0
- package/src/Graph/helpers/doc.ts +2 -2
- package/src/Graph/index.stories.tsx +1 -1
- package/src/Graph/index.tsx +3 -3
- package/src/Graph/mockedData/annotationData.json +182 -45
- package/src/Graph/mockedData/lastDay.json +1179 -1179
- package/src/Graph/mockedData/lastDayAreaStack.json +3106 -0
- package/src/Graph/mockedData/lastDayForward.json +751 -751
- package/src/Graph/mockedData/lastWeek.json +2045 -2045
- package/src/Graph/mockedData/zoomPreview.json +591 -199
- package/src/Graph/models.ts +4 -13
- package/src/Panel/index.tsx +6 -4
- package/src/RichTextEditor/ContentEditable.tsx +27 -7
- package/src/RichTextEditor/RichTextEditor.tsx +86 -45
- package/src/ThemeProvider/index.tsx +4 -1
- package/src/ThemeProvider/palettes.ts +7 -0
- package/src/index.ts +2 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/panelSize.ts +15 -0
- package/src/Graph/BasicComponents/Lines/RegularLines/useDataRegularLines.ts +0 -37
- package/src/Graph/BasicComponents/Lines/StackedLines/useDataStackLines.ts +0 -57
- package/src/Graph/IntercatifsComponents/AnchorPoint/useAnchorPoint.ts +0 -107
- /package/src/Graph/{IntercatifsComponents → InteractiveComponents}/AnchorPoint/index.tsx +0 -0
- /package/src/Graph/{IntercatifsComponents → InteractiveComponents}/AnchorPoint/models.ts +0 -0
- /package/src/Graph/{IntercatifsComponents → InteractiveComponents}/Annotations/Annotation/Area.tsx +0 -0
- /package/src/Graph/{IntercatifsComponents → InteractiveComponents}/Annotations/Annotation/Line.tsx +0 -0
- /package/src/Graph/{IntercatifsComponents → InteractiveComponents}/Annotations/Annotation/index.tsx +0 -0
- /package/src/Graph/{IntercatifsComponents → InteractiveComponents}/Annotations/Area/Downtime.tsx +0 -0
- /package/src/Graph/{IntercatifsComponents → InteractiveComponents}/Annotations/EventAnnotations.tsx +0 -0
- /package/src/Graph/{IntercatifsComponents → InteractiveComponents}/Annotations/Line/Acknowledgement.tsx +0 -0
- /package/src/Graph/{IntercatifsComponents → InteractiveComponents}/Annotations/Line/Comments.tsx +0 -0
- /package/src/Graph/{IntercatifsComponents → InteractiveComponents}/Annotations/annotationsAtoms.ts +0 -0
- /package/src/Graph/{IntercatifsComponents → InteractiveComponents}/Annotations/index.tsx +0 -0
- /package/src/Graph/{IntercatifsComponents → InteractiveComponents}/Annotations/models.ts +0 -0
- /package/src/Graph/{IntercatifsComponents → InteractiveComponents}/Bar.tsx +0 -0
- /package/src/Graph/{IntercatifsComponents → InteractiveComponents}/TimeShiftZones/TimeShiftIcon.tsx +0 -0
- /package/src/Graph/{IntercatifsComponents → InteractiveComponents}/TimeShiftZones/TimeShiftZone.tsx +0 -0
- /package/src/Graph/{IntercatifsComponents → InteractiveComponents}/TimeShiftZones/index.tsx +0 -0
- /package/src/Graph/{IntercatifsComponents → InteractiveComponents}/TimeShiftZones/models.ts +0 -0
- /package/src/Graph/{IntercatifsComponents → InteractiveComponents}/TimeShiftZones/useTimeShiftZones.ts +0 -0
- /package/src/Graph/{IntercatifsComponents → InteractiveComponents}/Tooltip/index.tsx +0 -0
- /package/src/Graph/{IntercatifsComponents → InteractiveComponents}/Tooltip/models.ts +0 -0
- /package/src/Graph/{IntercatifsComponents → InteractiveComponents}/Tooltip/useGraphTooltip.ts +0 -0
- /package/src/Graph/{IntercatifsComponents → InteractiveComponents}/ZoomPreview/zoomPreviewAtoms.ts +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@centreon/ui",
|
|
3
|
-
"version": "23.10.18-MON-17793-create-graph-component-centreon-ui.
|
|
3
|
+
"version": "23.10.18-MON-17793-create-graph-component-centreon-ui.14",
|
|
4
4
|
"description": "Centreon UI Components",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"eslint": "eslint ./src --ext .js,.jsx,.ts,.tsx --max-warnings 0",
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { makeStyles } from 'tss-react/mui';
|
|
2
|
+
import { T, always, cond, equals } from 'ramda';
|
|
3
|
+
|
|
4
|
+
import { SvgIconComponent } from '@mui/icons-material';
|
|
5
|
+
import {
|
|
6
|
+
FormControlLabel,
|
|
7
|
+
Checkbox as MuiCheckbox,
|
|
8
|
+
Box,
|
|
9
|
+
Typography
|
|
10
|
+
} from '@mui/material';
|
|
11
|
+
|
|
12
|
+
export type LabelPlacement = 'bottom' | 'top' | 'end' | 'start' | undefined;
|
|
13
|
+
|
|
14
|
+
interface StyleProps {
|
|
15
|
+
disabled: boolean;
|
|
16
|
+
hasIcon: boolean;
|
|
17
|
+
labelPlacement: LabelPlacement;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const getLabelSpacing = (labelPlacement, theme): string => {
|
|
21
|
+
return cond([
|
|
22
|
+
[equals('top'), always(theme.spacing(0, 0, 0.5))],
|
|
23
|
+
[equals('end'), always(theme.spacing(0, 0, 0, 0.5))],
|
|
24
|
+
[T, always(0)]
|
|
25
|
+
])(labelPlacement);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const useStyles = makeStyles<StyleProps>()(
|
|
29
|
+
(theme, { disabled, hasIcon, labelPlacement }) => ({
|
|
30
|
+
container: hasIcon
|
|
31
|
+
? {
|
|
32
|
+
alignItems: 'center',
|
|
33
|
+
display: 'flex',
|
|
34
|
+
flexDirection: 'column',
|
|
35
|
+
justifyContent: 'space-between',
|
|
36
|
+
minHeight: theme.spacing(11)
|
|
37
|
+
}
|
|
38
|
+
: {},
|
|
39
|
+
icon: {
|
|
40
|
+
fontSize: theme.spacing(10)
|
|
41
|
+
},
|
|
42
|
+
label: {
|
|
43
|
+
color: disabled
|
|
44
|
+
? theme.palette.action.disabled
|
|
45
|
+
: theme.palette.text.secondary,
|
|
46
|
+
fontSize: theme.typography.body1.fontSize,
|
|
47
|
+
fontWeight: equals(labelPlacement, 'top')
|
|
48
|
+
? theme.typography.fontWeightBold
|
|
49
|
+
: theme.typography.fontWeightMedium,
|
|
50
|
+
padding: getLabelSpacing(labelPlacement, theme)
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
interface Props {
|
|
56
|
+
Icon?: SvgIconComponent;
|
|
57
|
+
checked: boolean;
|
|
58
|
+
className?: string;
|
|
59
|
+
dataTestId?: string;
|
|
60
|
+
disabled?: boolean;
|
|
61
|
+
label: string;
|
|
62
|
+
labelPlacement?: LabelPlacement;
|
|
63
|
+
onChange?: (e) => void;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const Checkbox = ({
|
|
67
|
+
Icon,
|
|
68
|
+
checked,
|
|
69
|
+
label,
|
|
70
|
+
onChange,
|
|
71
|
+
className,
|
|
72
|
+
disabled = false,
|
|
73
|
+
labelPlacement = 'end',
|
|
74
|
+
dataTestId
|
|
75
|
+
}: Props): JSX.Element => {
|
|
76
|
+
const { classes, cx } = useStyles({
|
|
77
|
+
disabled,
|
|
78
|
+
hasIcon: !!Icon,
|
|
79
|
+
labelPlacement
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<Box className={cx(classes.container, className)}>
|
|
84
|
+
{Icon && <Icon className={classes.icon} />}
|
|
85
|
+
<FormControlLabel
|
|
86
|
+
control={
|
|
87
|
+
<MuiCheckbox
|
|
88
|
+
checked={checked}
|
|
89
|
+
color="primary"
|
|
90
|
+
disabled={disabled}
|
|
91
|
+
id={label}
|
|
92
|
+
size="small"
|
|
93
|
+
sx={{ padding: 0 }}
|
|
94
|
+
onChange={onChange}
|
|
95
|
+
/>
|
|
96
|
+
}
|
|
97
|
+
data-testid={dataTestId || ''}
|
|
98
|
+
key={label}
|
|
99
|
+
label={<Typography className={classes.label}>{label}</Typography>}
|
|
100
|
+
labelPlacement={labelPlacement}
|
|
101
|
+
sx={{ margin: 0, padding: 0 }}
|
|
102
|
+
/>
|
|
103
|
+
</Box>
|
|
104
|
+
);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export default Checkbox;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ComponentMeta, ComponentStory } from '@storybook/react';
|
|
2
|
+
|
|
3
|
+
import CheckboxGroup from '.';
|
|
4
|
+
|
|
5
|
+
const options = ['ok', 'warning', 'critical', 'unknown'];
|
|
6
|
+
|
|
7
|
+
const values = ['ok', 'critical'];
|
|
8
|
+
|
|
9
|
+
export default {
|
|
10
|
+
argTypes: {},
|
|
11
|
+
component: CheckboxGroup,
|
|
12
|
+
title: 'Checkbox/Multi'
|
|
13
|
+
} as ComponentMeta<typeof CheckboxGroup>;
|
|
14
|
+
|
|
15
|
+
const Template: ComponentStory<typeof CheckboxGroup> = (args) => (
|
|
16
|
+
<CheckboxGroup {...args} />
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
export const Playground = Template.bind({});
|
|
20
|
+
|
|
21
|
+
Playground.args = {
|
|
22
|
+
options,
|
|
23
|
+
values
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const Horizontal = Template.bind({});
|
|
27
|
+
|
|
28
|
+
Horizontal.args = {
|
|
29
|
+
direction: 'horizontal',
|
|
30
|
+
options,
|
|
31
|
+
values
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const LabelOnTop = Template.bind({});
|
|
35
|
+
|
|
36
|
+
LabelOnTop.args = {
|
|
37
|
+
direction: 'horizontal',
|
|
38
|
+
labelPlacement: 'top',
|
|
39
|
+
options,
|
|
40
|
+
values
|
|
41
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { equals, includes } from 'ramda';
|
|
2
|
+
import { makeStyles } from 'tss-react/mui';
|
|
3
|
+
|
|
4
|
+
import { FormGroup } from '@mui/material';
|
|
5
|
+
|
|
6
|
+
import Checkbox, { LabelPlacement } from '../Checkbox';
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
dataTestId?: string;
|
|
10
|
+
direction?: 'horizontal' | 'vertical';
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
labelPlacement?: LabelPlacement;
|
|
13
|
+
onChange?: (e) => void;
|
|
14
|
+
options: Array<string>;
|
|
15
|
+
values: Array<string>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const useStyles = makeStyles()((theme) => ({
|
|
19
|
+
checkbox: {
|
|
20
|
+
display: 'flex',
|
|
21
|
+
justifyContent: 'center',
|
|
22
|
+
minWidth: theme.spacing(10)
|
|
23
|
+
},
|
|
24
|
+
container: {
|
|
25
|
+
display: 'flex',
|
|
26
|
+
gap: 1
|
|
27
|
+
}
|
|
28
|
+
}));
|
|
29
|
+
|
|
30
|
+
const CheckboxGroup = ({
|
|
31
|
+
options,
|
|
32
|
+
values,
|
|
33
|
+
direction = 'vertical',
|
|
34
|
+
onChange,
|
|
35
|
+
labelPlacement = 'end',
|
|
36
|
+
disabled = false,
|
|
37
|
+
dataTestId
|
|
38
|
+
}: Props): JSX.Element => {
|
|
39
|
+
const { classes } = useStyles();
|
|
40
|
+
|
|
41
|
+
const row = !equals(direction, 'vertical');
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<FormGroup
|
|
45
|
+
className={classes.container}
|
|
46
|
+
data-testid={dataTestId || ''}
|
|
47
|
+
row={row}
|
|
48
|
+
>
|
|
49
|
+
{options.map((value) => {
|
|
50
|
+
return (
|
|
51
|
+
<Checkbox
|
|
52
|
+
checked={includes(value, values)}
|
|
53
|
+
className={classes.checkbox}
|
|
54
|
+
disabled={disabled}
|
|
55
|
+
key={value}
|
|
56
|
+
label={value}
|
|
57
|
+
labelPlacement={labelPlacement}
|
|
58
|
+
onChange={onChange}
|
|
59
|
+
/>
|
|
60
|
+
);
|
|
61
|
+
})}
|
|
62
|
+
</FormGroup>
|
|
63
|
+
);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export default CheckboxGroup;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ComponentMeta, ComponentStory } from '@storybook/react';
|
|
2
|
+
|
|
3
|
+
import MailIcon from '@mui/icons-material/MailOutline';
|
|
4
|
+
|
|
5
|
+
import Checkbox from './Checkbox';
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
argTypes: {},
|
|
9
|
+
component: Checkbox,
|
|
10
|
+
title: 'Checkbox/Single'
|
|
11
|
+
} as ComponentMeta<typeof Checkbox>;
|
|
12
|
+
|
|
13
|
+
const Template: ComponentStory<typeof Checkbox> = (args) => (
|
|
14
|
+
<Checkbox {...args} />
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
export const Playground = Template.bind({});
|
|
18
|
+
|
|
19
|
+
Playground.args = {
|
|
20
|
+
checked: true,
|
|
21
|
+
label: 'Up'
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const WithIcon = Template.bind({});
|
|
25
|
+
|
|
26
|
+
WithIcon.args = {
|
|
27
|
+
Icon: MailIcon,
|
|
28
|
+
checked: true,
|
|
29
|
+
label: 'Mail',
|
|
30
|
+
labelPlacement: 'end'
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const LabelOnTop = Template.bind({});
|
|
34
|
+
|
|
35
|
+
LabelOnTop.args = {
|
|
36
|
+
checked: true,
|
|
37
|
+
label: 'Down',
|
|
38
|
+
labelPlacement: 'top'
|
|
39
|
+
};
|
|
@@ -18,6 +18,7 @@ import { Group } from './Inputs/models';
|
|
|
18
18
|
|
|
19
19
|
interface Props {
|
|
20
20
|
children: React.ReactNode;
|
|
21
|
+
className?: string;
|
|
21
22
|
defaultIsOpen?: boolean;
|
|
22
23
|
group?: Group;
|
|
23
24
|
hasGroupTitle: boolean;
|
|
@@ -50,9 +51,10 @@ const CollapsibleGroup = ({
|
|
|
50
51
|
isCollapsible,
|
|
51
52
|
group,
|
|
52
53
|
hasGroupTitle,
|
|
53
|
-
defaultIsOpen = false
|
|
54
|
+
defaultIsOpen = false,
|
|
55
|
+
className
|
|
54
56
|
}: Props): JSX.Element => {
|
|
55
|
-
const { classes } = useStyles();
|
|
57
|
+
const { classes, cx } = useStyles();
|
|
56
58
|
const { t } = useTranslation();
|
|
57
59
|
|
|
58
60
|
const [isOpen, setIsOpen] = useState(isCollapsible && defaultIsOpen);
|
|
@@ -61,6 +63,8 @@ const CollapsibleGroup = ({
|
|
|
61
63
|
setIsOpen((currentIsOpen) => !currentIsOpen);
|
|
62
64
|
};
|
|
63
65
|
|
|
66
|
+
const containerClassName = className || '';
|
|
67
|
+
|
|
64
68
|
const CollapseIcon = isOpen ? ExpandMore : ChevronRightIcon;
|
|
65
69
|
const ContainerComponent = useCallback(
|
|
66
70
|
({
|
|
@@ -72,13 +76,13 @@ const CollapsibleGroup = ({
|
|
|
72
76
|
disableGutters
|
|
73
77
|
disableRipple
|
|
74
78
|
aria-label={group?.name}
|
|
75
|
-
className={classes.groupTitleContainer}
|
|
79
|
+
className={cx(classes.groupTitleContainer, containerClassName)}
|
|
76
80
|
onClick={toggle}
|
|
77
81
|
>
|
|
78
82
|
{containerComponentChildren}
|
|
79
83
|
</ListItemButton>
|
|
80
84
|
) : (
|
|
81
|
-
<Box className={classes.groupTitleContainer}>
|
|
85
|
+
<Box className={cx(classes.groupTitleContainer, containerClassName)}>
|
|
82
86
|
{containerComponentChildren}
|
|
83
87
|
</Box>
|
|
84
88
|
),
|
|
@@ -91,7 +95,9 @@ const CollapsibleGroup = ({
|
|
|
91
95
|
<ContainerComponent>
|
|
92
96
|
{isCollapsible && <CollapseIcon />}
|
|
93
97
|
<div className={classes.groupTitleIcon}>
|
|
94
|
-
<Typography variant="h5">
|
|
98
|
+
<Typography className="groupText" variant="h5">
|
|
99
|
+
{t(group?.name as string)}
|
|
100
|
+
</Typography>
|
|
95
101
|
{group?.EndIcon && (
|
|
96
102
|
<Tooltip
|
|
97
103
|
classes={{
|
|
@@ -71,7 +71,7 @@ export const basicFormWithHorizontalGroups = (): JSX.Element => (
|
|
|
71
71
|
<Form<BasicForm>
|
|
72
72
|
{...mandatoryProps}
|
|
73
73
|
groupDirection={GroupDirection.Horizontal}
|
|
74
|
-
groups={basicFormGroups}
|
|
74
|
+
groups={basicFormGroups.filter((group) => group.order !== 3)}
|
|
75
75
|
/>
|
|
76
76
|
</Paper>
|
|
77
77
|
);
|
package/src/Form/Form.tsx
CHANGED
|
@@ -18,8 +18,12 @@ export enum GroupDirection {
|
|
|
18
18
|
|
|
19
19
|
export type FormProps<T> = {
|
|
20
20
|
Buttons?: React.ComponentType;
|
|
21
|
+
areGroupsOpen?: boolean;
|
|
22
|
+
children?: JSX.Element;
|
|
23
|
+
className?: string;
|
|
21
24
|
groupDirection?: GroupDirection;
|
|
22
25
|
groups?: Array<Group>;
|
|
26
|
+
groupsClassName?: string;
|
|
23
27
|
initialValues: T;
|
|
24
28
|
inputs: Array<InputProps>;
|
|
25
29
|
isCollapsible?: boolean;
|
|
@@ -30,6 +34,10 @@ export type FormProps<T> = {
|
|
|
30
34
|
} & Omit<FormikSharedConfig<T>, 'isInitialValid'>;
|
|
31
35
|
|
|
32
36
|
const Form = <T extends object>({
|
|
37
|
+
children,
|
|
38
|
+
className,
|
|
39
|
+
groupsClassName,
|
|
40
|
+
areGroupsOpen,
|
|
33
41
|
initialValues,
|
|
34
42
|
validate,
|
|
35
43
|
validationSchema,
|
|
@@ -42,13 +50,15 @@ const Form = <T extends object>({
|
|
|
42
50
|
groupDirection = GroupDirection.Vertical,
|
|
43
51
|
...formikSharedConfig
|
|
44
52
|
}: FormProps<T>): JSX.Element => {
|
|
45
|
-
const { classes } = useStyles();
|
|
53
|
+
const { cx, classes } = useStyles();
|
|
46
54
|
|
|
47
55
|
if (isLoading) {
|
|
48
56
|
return (
|
|
49
57
|
<Inputs
|
|
50
58
|
isLoading
|
|
59
|
+
areGroupsOpen={areGroupsOpen}
|
|
51
60
|
groups={groups}
|
|
61
|
+
groupsClassName={groupsClassName}
|
|
52
62
|
inputs={inputs}
|
|
53
63
|
isCollapsible={isCollapsible}
|
|
54
64
|
/>
|
|
@@ -63,14 +73,19 @@ const Form = <T extends object>({
|
|
|
63
73
|
onSubmit={submit}
|
|
64
74
|
{...formikSharedConfig}
|
|
65
75
|
>
|
|
66
|
-
<div
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
76
|
+
<div>
|
|
77
|
+
{children}
|
|
78
|
+
<div className={cx(className, classes.form)}>
|
|
79
|
+
<Inputs
|
|
80
|
+
areGroupsOpen={areGroupsOpen}
|
|
81
|
+
groupDirection={groupDirection}
|
|
82
|
+
groups={groups}
|
|
83
|
+
groupsClassName={groupsClassName}
|
|
84
|
+
inputs={inputs}
|
|
85
|
+
isCollapsible={isCollapsible}
|
|
86
|
+
/>
|
|
87
|
+
<Buttons />
|
|
88
|
+
</div>
|
|
74
89
|
</div>
|
|
75
90
|
</Formik>
|
|
76
91
|
);
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { ChangeEvent } from 'react';
|
|
2
|
+
|
|
3
|
+
import { FormikValues, useFormikContext } from 'formik';
|
|
4
|
+
import { path, split } from 'ramda';
|
|
5
|
+
|
|
6
|
+
import { Box } from '@mui/material';
|
|
7
|
+
|
|
8
|
+
import { Checkbox as CheckboxComponent } from '../../Checkbox';
|
|
9
|
+
import { useMemoComponent } from '../..';
|
|
10
|
+
|
|
11
|
+
import { InputPropsWithoutGroup } from './models';
|
|
12
|
+
|
|
13
|
+
const Checkbox = ({
|
|
14
|
+
checkbox,
|
|
15
|
+
fieldName,
|
|
16
|
+
getDisabled,
|
|
17
|
+
hideInput,
|
|
18
|
+
dataTestId
|
|
19
|
+
}: InputPropsWithoutGroup): JSX.Element => {
|
|
20
|
+
const { values, setFieldValue } = useFormikContext<FormikValues>();
|
|
21
|
+
|
|
22
|
+
const fieldNamePath = split('.', fieldName);
|
|
23
|
+
|
|
24
|
+
const value = path(fieldNamePath, values);
|
|
25
|
+
|
|
26
|
+
const disabled = getDisabled?.(values) || false;
|
|
27
|
+
const hideCheckbox = hideInput?.(values) || false;
|
|
28
|
+
|
|
29
|
+
const handleChange = (event: ChangeEvent<HTMLInputElement>): void => {
|
|
30
|
+
const newValue = {
|
|
31
|
+
...value,
|
|
32
|
+
checked: event.target.checked,
|
|
33
|
+
label: event.target.id
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
setFieldValue(fieldName, newValue);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
return useMemoComponent({
|
|
40
|
+
Component: hideCheckbox ? (
|
|
41
|
+
<Box />
|
|
42
|
+
) : (
|
|
43
|
+
<CheckboxComponent
|
|
44
|
+
Icon={value?.Icon}
|
|
45
|
+
checked={value?.checked}
|
|
46
|
+
dataTestId={dataTestId || ''}
|
|
47
|
+
disabled={disabled}
|
|
48
|
+
label={value?.label}
|
|
49
|
+
labelPlacement={checkbox?.labelPlacement || 'end'}
|
|
50
|
+
onChange={handleChange}
|
|
51
|
+
/>
|
|
52
|
+
),
|
|
53
|
+
memoProps: [value, disabled, hideCheckbox]
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export default Checkbox;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { ChangeEvent, useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
import { FormikValues, useFormikContext } from 'formik';
|
|
4
|
+
import { equals, includes, path, split } from 'ramda';
|
|
5
|
+
|
|
6
|
+
import { Box, Typography } from '@mui/material';
|
|
7
|
+
|
|
8
|
+
import { CheckboxGroup as CheckboxGroupComponent } from '../../Checkbox';
|
|
9
|
+
import { useMemoComponent } from '../..';
|
|
10
|
+
|
|
11
|
+
import { InputPropsWithoutGroup } from './models';
|
|
12
|
+
|
|
13
|
+
const CheckboxGroup = ({
|
|
14
|
+
checkbox,
|
|
15
|
+
fieldName,
|
|
16
|
+
additionalLabel,
|
|
17
|
+
getDisabled,
|
|
18
|
+
hideInput,
|
|
19
|
+
dataTestId
|
|
20
|
+
}: InputPropsWithoutGroup): JSX.Element => {
|
|
21
|
+
const { values, setFieldValue } = useFormikContext<FormikValues>();
|
|
22
|
+
|
|
23
|
+
const fieldNamePath = split('.', fieldName);
|
|
24
|
+
|
|
25
|
+
const value = path(fieldNamePath, values);
|
|
26
|
+
|
|
27
|
+
const disabled = getDisabled?.(values) || false;
|
|
28
|
+
const hideCheckbox = hideInput?.(values) || false;
|
|
29
|
+
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
if (!disabled && !hideCheckbox) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const resetedValue = value?.map((element) => ({
|
|
35
|
+
...element,
|
|
36
|
+
checked: false
|
|
37
|
+
}));
|
|
38
|
+
setFieldValue(fieldName, resetedValue);
|
|
39
|
+
}, [disabled, hideCheckbox]);
|
|
40
|
+
|
|
41
|
+
const handleChange = (event: ChangeEvent<HTMLInputElement>): void => {
|
|
42
|
+
const label = event.target.id;
|
|
43
|
+
if (!includes(label, value)) {
|
|
44
|
+
setFieldValue(fieldName, [...value, label]);
|
|
45
|
+
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
setFieldValue(
|
|
50
|
+
fieldName,
|
|
51
|
+
value?.filter((elm) => !equals(elm, label))
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
return useMemoComponent({
|
|
56
|
+
Component: hideCheckbox ? (
|
|
57
|
+
<Box />
|
|
58
|
+
) : (
|
|
59
|
+
<Box>
|
|
60
|
+
{additionalLabel && <Typography>{additionalLabel}</Typography>}
|
|
61
|
+
<CheckboxGroupComponent
|
|
62
|
+
dataTestId={dataTestId || ''}
|
|
63
|
+
direction={checkbox?.direction}
|
|
64
|
+
disabled={disabled}
|
|
65
|
+
labelPlacement={checkbox?.labelPlacement || 'end'}
|
|
66
|
+
options={checkbox?.options as Array<string>}
|
|
67
|
+
values={value}
|
|
68
|
+
onChange={handleChange}
|
|
69
|
+
/>
|
|
70
|
+
</Box>
|
|
71
|
+
),
|
|
72
|
+
memoProps: [value, disabled, hideCheckbox]
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export default CheckboxGroup;
|
package/src/Form/Inputs/Grid.tsx
CHANGED
|
@@ -23,14 +23,16 @@ const useStyles = makeStyles<StylesProps>()(
|
|
|
23
23
|
);
|
|
24
24
|
|
|
25
25
|
const Grid = ({ grid }: InputPropsWithoutGroup): JSX.Element => {
|
|
26
|
-
const { classes } = useStyles({
|
|
26
|
+
const { classes, cx } = useStyles({
|
|
27
27
|
alignItems: grid?.alignItems,
|
|
28
28
|
columns: grid?.columns.length,
|
|
29
29
|
gridTemplateColumns: grid?.gridTemplateColumns
|
|
30
30
|
});
|
|
31
31
|
|
|
32
|
+
const className = grid?.className || '';
|
|
33
|
+
|
|
32
34
|
return (
|
|
33
|
-
<div className={classes.gridFields}>
|
|
35
|
+
<div className={cx(classes.gridFields, className)}>
|
|
34
36
|
{grid?.columns.map((field) => {
|
|
35
37
|
const Input = getInput(field.type);
|
|
36
38
|
|
|
@@ -18,6 +18,8 @@ import TextInput from './Text';
|
|
|
18
18
|
import ConnectedAutocomplete from './ConnectedAutocomplete';
|
|
19
19
|
import FieldsTable from './FieldsTable/FieldsTable';
|
|
20
20
|
import Grid from './Grid';
|
|
21
|
+
import CheckboxGroup from './CheckboxGroup';
|
|
22
|
+
import Checkbox from './Checkbox';
|
|
21
23
|
import Custom from './Custom';
|
|
22
24
|
import LoadingSkeleton from './LoadingSkeleton';
|
|
23
25
|
|
|
@@ -61,7 +63,15 @@ export const getInput = R.cond<
|
|
|
61
63
|
R.always(FieldsTable)
|
|
62
64
|
],
|
|
63
65
|
[R.equals(InputType.Grid) as (b: InputType) => boolean, R.always(Grid)],
|
|
64
|
-
[R.equals(InputType.Custom) as (b: InputType) => boolean, R.always(Custom)]
|
|
66
|
+
[R.equals(InputType.Custom) as (b: InputType) => boolean, R.always(Custom)],
|
|
67
|
+
[
|
|
68
|
+
R.equals(InputType.Checkbox) as (b: InputType) => boolean,
|
|
69
|
+
R.always(Checkbox)
|
|
70
|
+
],
|
|
71
|
+
[
|
|
72
|
+
R.equals(InputType.CheckboxGroup) as (b: InputType) => boolean,
|
|
73
|
+
R.always(CheckboxGroup)
|
|
74
|
+
]
|
|
65
75
|
]);
|
|
66
76
|
|
|
67
77
|
interface StylesProps {
|
|
@@ -89,7 +99,9 @@ const useStyles = makeStyles<StylesProps>()((theme, { groupDirection }) => ({
|
|
|
89
99
|
? 'row'
|
|
90
100
|
: 'column'
|
|
91
101
|
},
|
|
92
|
-
inputWrapper: {
|
|
102
|
+
inputWrapper: {
|
|
103
|
+
width: '100%'
|
|
104
|
+
},
|
|
93
105
|
inputs: {
|
|
94
106
|
display: 'flex',
|
|
95
107
|
flexDirection: 'column',
|
|
@@ -99,8 +111,10 @@ const useStyles = makeStyles<StylesProps>()((theme, { groupDirection }) => ({
|
|
|
99
111
|
}));
|
|
100
112
|
|
|
101
113
|
interface Props {
|
|
114
|
+
areGroupsOpen?: boolean;
|
|
102
115
|
groupDirection?: GroupDirection;
|
|
103
116
|
groups?: Array<Group>;
|
|
117
|
+
groupsClassName?: string;
|
|
104
118
|
inputs: Array<InputProps>;
|
|
105
119
|
isCollapsible: boolean;
|
|
106
120
|
isLoading?: boolean;
|
|
@@ -111,9 +125,11 @@ const Inputs = ({
|
|
|
111
125
|
groups = [],
|
|
112
126
|
isLoading = false,
|
|
113
127
|
isCollapsible,
|
|
114
|
-
groupDirection
|
|
128
|
+
groupDirection,
|
|
129
|
+
groupsClassName,
|
|
130
|
+
areGroupsOpen
|
|
115
131
|
}: Props): JSX.Element => {
|
|
116
|
-
const { classes } = useStyles({ groupDirection });
|
|
132
|
+
const { classes, cx } = useStyles({ groupDirection });
|
|
117
133
|
const { t } = useTranslation();
|
|
118
134
|
const formikContext = useFormikContext<FormikValues>();
|
|
119
135
|
|
|
@@ -178,12 +194,13 @@ const Inputs = ({
|
|
|
178
194
|
? R.find(R.propEq('name', groupName), groups)
|
|
179
195
|
: ({} as Group);
|
|
180
196
|
|
|
181
|
-
const isFirstElement = R.equals(index, 0);
|
|
197
|
+
const isFirstElement = areGroupsOpen || R.equals(index, 0);
|
|
182
198
|
|
|
183
199
|
return (
|
|
184
200
|
<Fragment key={groupName}>
|
|
185
201
|
<div>
|
|
186
202
|
<CollapsibleGroup
|
|
203
|
+
className={groupsClassName}
|
|
187
204
|
defaultIsOpen={isFirstElement}
|
|
188
205
|
group={groupProps}
|
|
189
206
|
hasGroupTitle={hasGroupTitle}
|
|
@@ -209,13 +226,18 @@ const Inputs = ({
|
|
|
209
226
|
>
|
|
210
227
|
{inputProps.additionalLabel && (
|
|
211
228
|
<Typography
|
|
212
|
-
className={
|
|
229
|
+
className={cx(
|
|
230
|
+
classes.additionalLabel,
|
|
231
|
+
inputProps?.additionalLabelClassName
|
|
232
|
+
)}
|
|
213
233
|
variant="body1"
|
|
214
234
|
>
|
|
215
235
|
{t(inputProps.additionalLabel)}
|
|
216
236
|
</Typography>
|
|
217
237
|
)}
|
|
218
|
-
<
|
|
238
|
+
<div className={inputProps?.inputClassName || ''}>
|
|
239
|
+
<Input {...inputProps} />
|
|
240
|
+
</div>
|
|
219
241
|
</div>
|
|
220
242
|
);
|
|
221
243
|
})}
|