@centreon/ui 23.10.18-MON-17793-create-graph-component-centreon-ui.4 → 23.10.18-MON-17793-create-graph-component-centreon-ui.6

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 (127) hide show
  1. package/package.json +13 -2
  2. package/src/@types/aria-attributes.d.ts +10 -0
  3. package/src/@types/data-attributes.d.ts +3 -0
  4. package/src/Dashboard/Dashboard.styles.ts +83 -0
  5. package/src/Dashboard/DashboardLayout.stories.tsx +106 -0
  6. package/src/Dashboard/Grid.tsx +70 -0
  7. package/src/Dashboard/Item.tsx +78 -0
  8. package/src/Dashboard/Layout.tsx +74 -0
  9. package/src/Dashboard/index.tsx +9 -0
  10. package/src/Dashboard/utils.ts +28 -0
  11. package/src/Form/{index.stories.tsx → Form.stories.tsx} +1 -2
  12. package/src/Form/Form.styles.ts +11 -0
  13. package/src/Form/{index.tsx → Form.tsx} +17 -10
  14. package/src/Form/FormButtons.tsx +1 -2
  15. package/src/Form/index.ts +1 -0
  16. package/src/Form/storiesData.tsx +1 -3
  17. package/src/Graph/BasicComponents/Axes/index.tsx +7 -3
  18. package/src/Graph/BasicComponents/Lines/RegularLines/index.tsx +1 -1
  19. package/src/Graph/BasicComponents/Lines/StackedLines/index.tsx +15 -15
  20. package/src/Graph/BasicComponents/Lines/Threshold/index.tsx +51 -0
  21. package/src/Graph/BasicComponents/Lines/Threshold/models.ts +7 -0
  22. package/src/Graph/BasicComponents/Lines/index.tsx +42 -43
  23. package/src/Graph/BasicComponents/Lines/models.ts +1 -0
  24. package/src/Graph/BasicComponents/Lines/useDataRegularLines.ts +38 -0
  25. package/src/Graph/BasicComponents/Lines/useDataStackLines.ts +58 -0
  26. package/src/Graph/BasicComponents/Lines/useDataThreshold.ts +80 -0
  27. package/src/Graph/BasicComponents/useFilterLines.ts +66 -0
  28. package/src/Graph/Graph.tsx +23 -9
  29. package/src/Graph/IntercatifsComponents/Annotations/Annotation/index.tsx +1 -1
  30. package/src/Graph/Legend/InteractiveValue.tsx +22 -0
  31. package/src/Graph/Legend/Legend.styles.ts +71 -0
  32. package/src/Graph/Legend/LegendContent.tsx +27 -0
  33. package/src/Graph/Legend/LegendHeader.tsx +45 -0
  34. package/src/Graph/Legend/Marker.tsx +43 -0
  35. package/src/Graph/Legend/index.tsx +134 -0
  36. package/src/Graph/Legend/models.ts +11 -0
  37. package/src/Graph/Legend/useInteractiveValues.ts +84 -0
  38. package/src/Graph/Legend/useLegend.ts +111 -0
  39. package/src/Graph/common/index.ts +4 -2
  40. package/src/Graph/graphAtoms.ts +5 -0
  41. package/src/Graph/helpers/doc.ts +3 -0
  42. package/src/Graph/helpers/index.ts +6 -2
  43. package/src/Graph/index.stories.tsx +44 -3
  44. package/src/Graph/index.tsx +1 -1
  45. package/src/Graph/mockedData/lastDay.json +1170 -1170
  46. package/src/Graph/mockedData/lastDayThreshold.json +2352 -0
  47. package/src/Graph/models.ts +1 -0
  48. package/src/Graph/translatedLabels.ts +3 -0
  49. package/src/Graph/useGraphData.ts +3 -19
  50. package/src/InputField/Select/Autocomplete/index.stories.tsx +1 -10
  51. package/src/TimePeriods/SelectedTimePeriod.tsx +2 -2
  52. package/src/TimePeriods/helpers/index.ts +2 -1
  53. package/src/TimePeriods/index.stories.tsx +7 -0
  54. package/src/TimePeriods/index.tsx +12 -10
  55. package/src/TimePeriods/models.ts +8 -12
  56. package/src/TimePeriods/timePeriodsAtoms.ts +37 -57
  57. package/src/TimePeriods/useAwesomeTimePeriod.ts +4 -3
  58. package/src/TimePeriods/useSortTimePeriods.ts +8 -1
  59. package/src/Typography/FluidTypography/index.stories.tsx +63 -0
  60. package/src/Typography/FluidTypography/index.tsx +51 -0
  61. package/src/Typography/FluidTypography/useFluidResizeObserver.ts +56 -0
  62. package/src/Typography/{index.stories.tsx → Typography.stories.tsx} +5 -5
  63. package/src/__image_snapshots__/storyshots-test-js-image-story-shots-dashboard-normal-1-snap.png +0 -0
  64. package/src/__image_snapshots__/storyshots-test-js-image-story-shots-dashboard-with-item-header-1-snap.png +0 -0
  65. package/src/__image_snapshots__/storyshots-test-js-image-story-shots-dashboard-with-many-panels-1-snap.png +0 -0
  66. package/src/__image_snapshots__/storyshots-test-js-image-story-shots-fluid-typography-basic-1-snap.png +0 -0
  67. package/src/__image_snapshots__/storyshots-test-js-image-story-shots-fluid-typography-with-20-px-height-1-snap.png +0 -0
  68. package/src/__image_snapshots__/storyshots-test-js-image-story-shots-fluid-typography-with-200-px-width-1-snap.png +0 -0
  69. package/src/__image_snapshots__/storyshots-test-js-image-story-shots-fluid-typography-with-heading-5-variant-1-snap.png +0 -0
  70. package/src/__image_snapshots__/storyshots-test-js-image-story-shots-fluid-typography-with-long-text-1-snap.png +0 -0
  71. package/src/api/useMutationQuery/index.ts +7 -3
  72. package/src/components/Button/Button.stories.tsx +34 -0
  73. package/src/components/Button/Button.styles.ts +30 -0
  74. package/src/components/Button/Button.tsx +75 -0
  75. package/src/components/Button/Icon/IconButton.stories.tsx +18 -0
  76. package/src/components/Button/Icon/IconButton.styles.ts +7 -0
  77. package/src/components/Button/Icon/IconButton.tsx +58 -0
  78. package/src/components/Button/Icon/index.tsx +1 -0
  79. package/src/components/Button/index.ts +2 -0
  80. package/src/components/DataTable/DataTable.stories.tsx +42 -0
  81. package/src/components/DataTable/DataTable.styles.ts +22 -0
  82. package/src/components/DataTable/DataTable.tsx +33 -0
  83. package/src/components/DataTable/EmptyState/DataTableEmptyState.stories.tsx +21 -0
  84. package/src/components/DataTable/EmptyState/DataTableEmptyState.styles.ts +26 -0
  85. package/src/components/DataTable/EmptyState/DataTableEmptyState.tsx +46 -0
  86. package/src/components/DataTable/Item/DataTableItem.stories.tsx +25 -0
  87. package/src/components/DataTable/Item/DataTableItem.styles.ts +36 -0
  88. package/src/components/DataTable/Item/DataTableItem.tsx +81 -0
  89. package/src/components/DataTable/Item/DataTableItemSkeleton.tsx +13 -0
  90. package/src/components/DataTable/index.ts +10 -0
  91. package/src/components/Form/Dashboard/Dashboard.resource.ts +4 -0
  92. package/src/components/Form/Dashboard/DashboardForm.stories.ts +39 -0
  93. package/src/components/Form/Dashboard/DashboardForm.styles.ts +19 -0
  94. package/src/components/Form/Dashboard/DashboardForm.tsx +100 -0
  95. package/src/components/Form/Dashboard/DashboardFormActions.tsx +56 -0
  96. package/src/components/Form/Dashboard/index.ts +2 -0
  97. package/src/components/Form/Dashboard/translatedLabels.ts +5 -0
  98. package/src/components/Form/Form.models.ts +1 -0
  99. package/src/components/Form/index.ts +2 -0
  100. package/src/components/Header/Header.stories.tsx +27 -0
  101. package/src/components/Header/Header.styles.ts +27 -0
  102. package/src/components/Header/Header.tsx +23 -0
  103. package/src/components/Header/index.ts +1 -0
  104. package/src/components/Icon/Icon.styles.ts +0 -0
  105. package/src/components/Icon/Icon.tsx +2 -0
  106. package/src/components/Icon/index.ts +0 -0
  107. package/src/components/Modal/Modal.stories.tsx +111 -0
  108. package/src/components/Modal/Modal.styles.ts +55 -0
  109. package/src/components/Modal/Modal.tsx +59 -0
  110. package/src/components/Modal/ModalActions.tsx +57 -0
  111. package/src/components/Modal/ModalBody.tsx +15 -0
  112. package/src/components/Modal/ModalHeader.tsx +21 -0
  113. package/src/components/Modal/index.ts +10 -0
  114. package/src/components/README.md +3 -0
  115. package/src/components/index.ts +5 -0
  116. package/src/index.ts +5 -1
  117. package/src/layout/TiledListingPage/TiledListingActions.tsx +15 -0
  118. package/src/layout/TiledListingPage/TiledListingContent.tsx +21 -0
  119. package/src/layout/TiledListingPage/TiledListingList.tsx +11 -0
  120. package/src/layout/TiledListingPage/TiledListingPage.styles.ts +16 -0
  121. package/src/layout/TiledListingPage/TiledListingPage.tsx +15 -0
  122. package/src/layout/TiledListingPage/index.ts +4 -0
  123. package/src/screens/dashboard/DashboardsOverview.stories.tsx +273 -0
  124. package/src/utils/useMemoComponent.ts +2 -0
  125. package/test/setupTests.js +86 -0
  126. package/test/testRenderer.tsx +56 -0
  127. /package/src/Typography/{index.tsx → story.utils.tsx} +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.4",
3
+ "version": "23.10.18-MON-17793-create-graph-component-centreon-ui.6",
4
4
  "description": "Centreon UI Components",
5
5
  "scripts": {
6
6
  "eslint": "eslint ./src --ext .js,.jsx,.ts,.tsx --max-warnings 0",
@@ -31,10 +31,17 @@
31
31
  },
32
32
  "homepage": "https://github.com/centreon/centreon#readme",
33
33
  "main": "src/index.ts",
34
+ "exports": {
35
+ ".": "./src/index.ts",
36
+ "./components": "./src/components/index.ts",
37
+ "./fonts/*": "./public/fonts/*",
38
+ "./test/testRenderer": "./test/testRenderer.tsx"
39
+ },
34
40
  "files": [
35
41
  "package.json",
36
42
  "src/*",
37
- "public/*"
43
+ "public/*",
44
+ "test/*"
38
45
  ],
39
46
  "devDependencies": {
40
47
  "@cypress/react": "^7.0.2",
@@ -58,6 +65,7 @@
58
65
  "@testing-library/react-hooks": "^8.0.1",
59
66
  "@types/jest": "^27.5.0",
60
67
  "@types/ramda": "^0.28.12",
68
+ "@types/react": "^18.0.26",
61
69
  "@vitejs/plugin-react": "^4.0.0",
62
70
  "@vitejs/plugin-react-swc": "^3.3.0",
63
71
  "axios-mock-adapter": "^1.21.4",
@@ -89,6 +97,8 @@
89
97
  "humanize-duration": "^3.27.3",
90
98
  "lexical": "0.8.0",
91
99
  "notistack": "^2.0.8",
100
+ "react-grid-layout": "^1.3.4",
101
+ "react-resizable": "^3.0.5",
92
102
  "react-transition-group": "^4.4.5",
93
103
  "ulog": "^2.0.0-beta.19"
94
104
  },
@@ -109,6 +119,7 @@
109
119
  "ramda": "0.x",
110
120
  "react-i18next": "12.x",
111
121
  "react-router-dom": "6.x",
122
+ "react-scale-text": "1.x",
112
123
  "resize-observer-polyfill": "1.x",
113
124
  "ts.data.json": "2.x",
114
125
  "tss-react": "4.x"
@@ -0,0 +1,10 @@
1
+ export interface AriaLabelingAttributes {
2
+ 'aria-describedby'?: string;
3
+ 'aria-details'?: string;
4
+ 'aria-label'?: string;
5
+ 'aria-labelledby'?: string;
6
+ }
7
+
8
+ export interface AriaValidationAttributes {
9
+ 'aria-errormessage'?: string;
10
+ }
@@ -0,0 +1,3 @@
1
+ export interface DataTestAttributes {
2
+ 'data-testid'?: string;
3
+ }
@@ -0,0 +1,83 @@
1
+ import { makeStyles } from 'tss-react/mui';
2
+
3
+ import { alpha } from '@mui/material';
4
+
5
+ export const useDashboardLayoutStyles = makeStyles()((theme) => ({
6
+ container: {
7
+ '& .react-grid-item': {
8
+ borderRadius: theme.shape.borderRadius,
9
+ transition: theme.transitions.create('all', {
10
+ delay: 0,
11
+ duration: 100,
12
+ easing: theme.transitions.easing.easeOut
13
+ })
14
+ },
15
+ '& .react-grid-item.react-draggable-dragging': {
16
+ boxShadow: theme.shadows[3]
17
+ },
18
+ '& .react-grid-item.react-grid-placeholder': {
19
+ backgroundColor: alpha(theme.palette.primary.main, 0.7)
20
+ },
21
+ '& .react-grid-item.resizing': {
22
+ boxShadow: theme.shadows[3]
23
+ },
24
+ '& .react-resizable-handle': {
25
+ backgroundColor: theme.palette.action.focus,
26
+ backgroundImage: 'none',
27
+ borderRadius: theme.shape.borderRadius,
28
+ display: 'block',
29
+ opacity: 0,
30
+ position: 'absolute'
31
+ },
32
+ '& .react-resizable-handle.react-resizable-handle-e': {
33
+ cursor: 'ew-resize',
34
+ height: `calc(100% - ${theme.spacing(3)})`,
35
+ marginTop: 0,
36
+ right: 0,
37
+ top: 0,
38
+ transform: 'rotate(0deg)',
39
+ width: theme.spacing(1)
40
+ },
41
+ '& .react-resizable-handle.react-resizable-handle-s': {
42
+ bottom: 0,
43
+ cursor: 'ns-resize',
44
+ height: theme.spacing(1),
45
+ left: 0,
46
+ marginLeft: 0,
47
+ transform: 'rotate(0deg)',
48
+ width: `calc(100% - ${theme.spacing(3)})`
49
+ },
50
+ '& .react-resizable-handle.react-resizable-handle-se': {
51
+ bottom: 0,
52
+ cursor: 'nwse-resize',
53
+ height: theme.spacing(2),
54
+ right: 0,
55
+ transform: 'rotate(0deg)',
56
+ width: theme.spacing(2)
57
+ },
58
+ '& .react-resizable-handle::after': {
59
+ content: 'none'
60
+ },
61
+ '& .react-resizable-handle:hover': {
62
+ opacity: 1
63
+ }
64
+ }
65
+ }));
66
+
67
+ export const useDashboardItemStyles = makeStyles()((theme) => ({
68
+ widgetContainer: {
69
+ height: '100%',
70
+ width: '100%'
71
+ },
72
+ widgetContent: {
73
+ height: '100%',
74
+ padding: theme.spacing(1, 2)
75
+ },
76
+ widgetHeader: {
77
+ '&:hover': {
78
+ backgroundColor: theme.palette.action.hover
79
+ },
80
+ cursor: 'move',
81
+ padding: theme.spacing(0.5, 2)
82
+ }
83
+ }));
@@ -0,0 +1,106 @@
1
+ import { ReactElement } from 'react';
2
+
3
+ import { ComponentMeta } from '@storybook/react';
4
+ import { Layout } from 'react-grid-layout';
5
+
6
+ import { Typography } from '@mui/material';
7
+
8
+ import FluidTypography from '../Typography/FluidTypography';
9
+
10
+ import { DashboardLayout } from '.';
11
+
12
+ interface CustomLayout extends Layout {
13
+ content: string;
14
+ shouldUseFluidTypography: boolean;
15
+ }
16
+
17
+ const dashboardLayout: Array<CustomLayout> = [
18
+ {
19
+ content: 'Hello world',
20
+ h: 4,
21
+ i: 'a',
22
+ shouldUseFluidTypography: false,
23
+ w: 6,
24
+ x: 0,
25
+ y: 0
26
+ },
27
+ {
28
+ content: 'This is a panel',
29
+ h: 3,
30
+ i: 'b',
31
+ minW: 2,
32
+ shouldUseFluidTypography: false,
33
+ w: 7,
34
+ x: 1,
35
+ y: 7
36
+ },
37
+ {
38
+ content: 'And the last panel with fluid typography',
39
+ h: 7,
40
+ i: 'c',
41
+ shouldUseFluidTypography: true,
42
+ w: 6,
43
+ x: 6,
44
+ y: 6
45
+ }
46
+ ];
47
+
48
+ const generateLayout = (maxElements: number): Array<CustomLayout> => {
49
+ return Array(maxElements)
50
+ .fill(0)
51
+ .map((_, i): CustomLayout => {
52
+ return {
53
+ content: `${i}`,
54
+ h: 3,
55
+ i: i.toString(),
56
+ shouldUseFluidTypography: false,
57
+ w: 3,
58
+ x: (i * 3) % 12,
59
+ y: Math.floor(i / 12)
60
+ };
61
+ });
62
+ };
63
+
64
+ interface DashboardTemplateProps {
65
+ header?: ReactElement;
66
+ layout?: Array<CustomLayout>;
67
+ }
68
+
69
+ const Header = (): ReactElement => (
70
+ <Typography variant="body2">The title</Typography>
71
+ );
72
+
73
+ const DashboardTemplate = ({
74
+ header,
75
+ layout = dashboardLayout
76
+ }: DashboardTemplateProps): ReactElement => (
77
+ <DashboardLayout.Layout<CustomLayout> layout={layout}>
78
+ {layout.map(({ i, content, shouldUseFluidTypography }) => (
79
+ <DashboardLayout.Item header={header} key={i}>
80
+ {shouldUseFluidTypography ? (
81
+ <FluidTypography text={content} />
82
+ ) : (
83
+ <Typography>{content}</Typography>
84
+ )}
85
+ </DashboardLayout.Item>
86
+ ))}
87
+ </DashboardLayout.Layout>
88
+ );
89
+
90
+ export default {
91
+ argTypes: {},
92
+ component: DashboardTemplate,
93
+ title: 'Dashboard'
94
+ } as ComponentMeta<typeof DashboardTemplate>;
95
+
96
+ export const normal = DashboardTemplate.bind({});
97
+
98
+ export const withManyPanels = DashboardTemplate.bind({});
99
+ withManyPanels.args = {
100
+ layout: generateLayout(1000)
101
+ };
102
+
103
+ export const withItemHeader = DashboardTemplate.bind({});
104
+ withItemHeader.args = {
105
+ header: <Header />
106
+ };
@@ -0,0 +1,70 @@
1
+ import { ReactElement, useMemo } from 'react';
2
+
3
+ import { Grid as VisxGrid } from '@visx/visx';
4
+ import { scaleLinear } from '@visx/scale';
5
+
6
+ import { useTheme } from '@mui/material';
7
+
8
+ import { useMemoComponent } from '../utils';
9
+
10
+ import { maxColumns, rowHeight } from './utils';
11
+
12
+ interface Props {
13
+ columns: number;
14
+ height: number;
15
+ width: number;
16
+ }
17
+
18
+ const Grid = ({ width, height, columns }: Props): ReactElement => {
19
+ const theme = useTheme();
20
+
21
+ const xScale = useMemo(
22
+ () =>
23
+ scaleLinear({
24
+ domain: [0, maxColumns],
25
+ range: [0, width]
26
+ }),
27
+ [width]
28
+ );
29
+
30
+ const numberOfRows = Math.floor(height / (rowHeight + 16));
31
+
32
+ const yScale = useMemo(
33
+ () =>
34
+ scaleLinear({
35
+ domain: [0, numberOfRows],
36
+ range: [0, height]
37
+ }),
38
+ [height]
39
+ );
40
+
41
+ const tick = maxColumns / columns;
42
+
43
+ const xTickValues = Array(columns)
44
+ .fill(0)
45
+ .map((_, index) => index * tick);
46
+
47
+ return useMemoComponent({
48
+ Component: (
49
+ <svg style={{ height, position: 'absolute', width }}>
50
+ <VisxGrid.GridColumns
51
+ height={height}
52
+ scale={xScale}
53
+ stroke={theme.palette.divider}
54
+ tickValues={xTickValues}
55
+ width={width}
56
+ />
57
+ <VisxGrid.GridRows
58
+ height={height}
59
+ scale={yScale}
60
+ stroke={theme.palette.divider}
61
+ top={-10}
62
+ width={width}
63
+ />
64
+ </svg>
65
+ ),
66
+ memoProps: [height, width, columns]
67
+ });
68
+ };
69
+
70
+ export default Grid;
@@ -0,0 +1,78 @@
1
+ import {
2
+ CSSProperties,
3
+ ForwardedRef,
4
+ forwardRef,
5
+ MouseEvent,
6
+ ReactElement
7
+ } from 'react';
8
+
9
+ import { isNil } from 'ramda';
10
+
11
+ import { Card } from '@mui/material';
12
+
13
+ import { useMemoComponent } from '../utils';
14
+
15
+ import { useDashboardItemStyles } from './Dashboard.styles';
16
+
17
+ interface DashboardItemProps {
18
+ children: ReactElement;
19
+ className?: string;
20
+ header?: ReactElement;
21
+ key: string;
22
+ onMouseDown?: (e: MouseEvent<HTMLDivElement>) => void;
23
+ onMouseUp?: (e: MouseEvent<HTMLDivElement>) => void;
24
+ onTouchEnd?: (e) => void;
25
+ style?: CSSProperties;
26
+ }
27
+
28
+ const Item = forwardRef(
29
+ (
30
+ {
31
+ children,
32
+ key,
33
+ style,
34
+ className,
35
+ header,
36
+ onMouseDown,
37
+ onMouseUp,
38
+ onTouchEnd
39
+ }: DashboardItemProps,
40
+ ref: ForwardedRef<HTMLDivElement>
41
+ ): ReactElement => {
42
+ const { classes } = useDashboardItemStyles();
43
+
44
+ const hasHeader = !isNil(header);
45
+
46
+ const listeners = {
47
+ onMouseDown,
48
+ onMouseUp,
49
+ onTouchEnd
50
+ };
51
+
52
+ const cardContainerListeners = !hasHeader ? listeners : {};
53
+
54
+ return useMemoComponent({
55
+ Component: (
56
+ <div
57
+ className={className}
58
+ key={key}
59
+ ref={ref}
60
+ style={style}
61
+ {...cardContainerListeners}
62
+ >
63
+ <Card className={classes.widgetContainer}>
64
+ {header && (
65
+ <div {...listeners} className={classes.widgetHeader}>
66
+ {header}
67
+ </div>
68
+ )}
69
+ <div className={classes.widgetContent}>{children}</div>
70
+ </Card>
71
+ </div>
72
+ ),
73
+ memoProps: [key, style, className, header]
74
+ });
75
+ }
76
+ );
77
+
78
+ export default Item;
@@ -0,0 +1,74 @@
1
+ import { ReactElement, useEffect, useState } from 'react';
2
+
3
+ import { Responsive } from '@visx/visx';
4
+ import GridLayout, { Layout, WidthProvider } from 'react-grid-layout';
5
+ import 'react-grid-layout/css/styles.css';
6
+
7
+ import { Responsive as ResponsiveHeight, useMemoComponent } from '..';
8
+
9
+ import { useDashboardLayoutStyles } from './Dashboard.styles';
10
+ import { getColumnsFromScreenSize, getLayout, rowHeight } from './utils';
11
+ import Grid from './Grid';
12
+
13
+ const ReactGridLayout = WidthProvider(GridLayout);
14
+
15
+ interface DashboardLayoutProps<T> {
16
+ changeLayout?: (newLayout: Array<Layout>) => void;
17
+ children: Array<ReactElement>;
18
+ displayGrid?: boolean;
19
+ layout: Array<T>;
20
+ }
21
+
22
+ const Layout = <T extends Layout>({
23
+ children,
24
+ changeLayout,
25
+ displayGrid,
26
+ layout
27
+ }: DashboardLayoutProps<T>): ReactElement => {
28
+ const { classes } = useDashboardLayoutStyles();
29
+
30
+ const [columns, setColumns] = useState(getColumnsFromScreenSize());
31
+
32
+ const resize = (): void => {
33
+ setColumns(getColumnsFromScreenSize());
34
+ };
35
+
36
+ useEffect(() => {
37
+ window.addEventListener('resize', resize);
38
+
39
+ return (): void => {
40
+ window.removeEventListener('resize', resize);
41
+ };
42
+ }, []);
43
+
44
+ return useMemoComponent({
45
+ Component: (
46
+ <ResponsiveHeight>
47
+ <Responsive.ParentSize>
48
+ {({ width, height }): ReactElement => (
49
+ <div className={classes.container}>
50
+ {displayGrid && (
51
+ <Grid columns={columns} height={height} width={width} />
52
+ )}
53
+ <ReactGridLayout
54
+ cols={columns}
55
+ containerPadding={[4, 0]}
56
+ layout={getLayout(layout)}
57
+ margin={[20, 20]}
58
+ resizeHandles={['s', 'e', 'se']}
59
+ rowHeight={rowHeight}
60
+ width={width}
61
+ onLayoutChange={changeLayout}
62
+ >
63
+ {children}
64
+ </ReactGridLayout>
65
+ </div>
66
+ )}
67
+ </Responsive.ParentSize>
68
+ </ResponsiveHeight>
69
+ ),
70
+ memoProps: [columns, layout, displayGrid]
71
+ });
72
+ };
73
+
74
+ export default Layout;
@@ -0,0 +1,9 @@
1
+ import Layout from './Layout';
2
+ import Item from './Item';
3
+
4
+ export * from './utils';
5
+
6
+ export const DashboardLayout = {
7
+ Item,
8
+ Layout
9
+ };
@@ -0,0 +1,28 @@
1
+ import { lt } from 'ramda';
2
+ import { Layout } from 'react-grid-layout';
3
+
4
+ export const maxColumns = 12;
5
+ const minColumns = 1;
6
+ const breakpoint = 768;
7
+
8
+ export const rowHeight = 64;
9
+
10
+ export const getIsSmallScreenSize = (): boolean =>
11
+ lt(window.innerWidth, breakpoint);
12
+
13
+ export const getColumnsFromScreenSize = (): number =>
14
+ getIsSmallScreenSize() ? minColumns : maxColumns;
15
+
16
+ export const getLayout = <T extends Layout>(layout: Array<T>): Array<T> => {
17
+ const isSmallScreenSize = getIsSmallScreenSize();
18
+ if (!isSmallScreenSize) {
19
+ return layout;
20
+ }
21
+
22
+ return layout
23
+ .sort((a, b) => a.x + a.y - (b.x + b.y))
24
+ .map((widget) => ({
25
+ ...widget,
26
+ w: 1
27
+ }));
28
+ };
@@ -8,8 +8,7 @@ import {
8
8
  basicFormValidationSchema,
9
9
  CustomButton
10
10
  } from './storiesData';
11
-
12
- import Form, { GroupDirection } from '.';
11
+ import { Form, GroupDirection } from './Form';
13
12
 
14
13
  export default { title: 'Form' };
15
14
 
@@ -0,0 +1,11 @@
1
+ import { makeStyles } from 'tss-react/mui';
2
+
3
+ const useStyles = makeStyles()((theme) => ({
4
+ form: {
5
+ display: 'flex',
6
+ flexDirection: 'column',
7
+ gap: theme.spacing(2)
8
+ }
9
+ }));
10
+
11
+ export { useStyles };
@@ -1,16 +1,22 @@
1
- import { Formik, FormikHelpers, FormikValues } from 'formik';
1
+ import {
2
+ Formik,
3
+ FormikHelpers,
4
+ FormikSharedConfig,
5
+ FormikValues
6
+ } from 'formik';
2
7
  import * as Yup from 'yup';
3
8
 
4
9
  import FormButtons from './FormButtons';
5
10
  import Inputs from './Inputs';
6
11
  import { Group, InputProps } from './Inputs/models';
12
+ import { useStyles } from './Form.styles';
7
13
 
8
14
  export enum GroupDirection {
9
15
  Horizontal = 'horizontal',
10
16
  Vertical = 'vertical'
11
17
  }
12
18
 
13
- interface Props<T> {
19
+ export type FormProps<T> = {
14
20
  Buttons?: React.ComponentType;
15
21
  groupDirection?: GroupDirection;
16
22
  groups?: Array<Group>;
@@ -21,7 +27,7 @@ interface Props<T> {
21
27
  submit: (values: T, bag: FormikHelpers<T>) => void | Promise<void>;
22
28
  validate?: (values: FormikValues) => void;
23
29
  validationSchema: Yup.SchemaOf<T>;
24
- }
30
+ } & Omit<FormikSharedConfig<T>, 'isInitialValid'>;
25
31
 
26
32
  const Form = <T extends object>({
27
33
  initialValues,
@@ -33,8 +39,11 @@ const Form = <T extends object>({
33
39
  Buttons = FormButtons,
34
40
  isLoading = false,
35
41
  isCollapsible = false,
36
- groupDirection = GroupDirection.Vertical
37
- }: Props<T>): JSX.Element => {
42
+ groupDirection = GroupDirection.Vertical,
43
+ ...formikSharedConfig
44
+ }: FormProps<T>): JSX.Element => {
45
+ const { classes } = useStyles();
46
+
38
47
  if (isLoading) {
39
48
  return (
40
49
  <Inputs
@@ -48,15 +57,13 @@ const Form = <T extends object>({
48
57
 
49
58
  return (
50
59
  <Formik<T>
51
- enableReinitialize
52
- validateOnBlur
53
- validateOnMount
54
60
  initialValues={initialValues}
55
61
  validate={validate}
56
62
  validationSchema={validationSchema}
57
63
  onSubmit={submit}
64
+ {...formikSharedConfig}
58
65
  >
59
- <div>
66
+ <div className={classes.form}>
60
67
  <Inputs
61
68
  groupDirection={groupDirection}
62
69
  groups={groups}
@@ -69,4 +76,4 @@ const Form = <T extends object>({
69
76
  );
70
77
  };
71
78
 
72
- export default Form;
79
+ export { Form };
@@ -23,8 +23,7 @@ const useStyles = makeStyles()((theme) => ({
23
23
  columnGap: theme.spacing(2),
24
24
  display: 'flex',
25
25
  flexDirection: 'row',
26
- justifyContent: 'flex-end',
27
- marginTop: theme.spacing(2)
26
+ justifyContent: 'flex-end'
28
27
  }
29
28
  }));
30
29
 
@@ -0,0 +1 @@
1
+ export * from './Form';
@@ -81,9 +81,7 @@ export const basicFormValidationSchema = Yup.object().shape({
81
81
  scopes: Yup.array().of(
82
82
  Yup.string().min(3, '3 characters min').required('Required')
83
83
  ),
84
- sports: Yup.array()
85
- .of(selectEntryValidationSchema.required('Required'))
86
- .min(2, 'Choose at least 2 sports')
84
+ sports: Yup.array().of(selectEntryValidationSchema.required('Required'))
87
85
  });
88
86
 
89
87
  const roleEntries: Array<SelectEntry> = [
@@ -1,11 +1,12 @@
1
1
  import { Axis } from '@visx/visx';
2
2
  import { ScaleLinear } from 'd3-scale';
3
+ import { isNil } from 'ramda';
3
4
 
4
5
  import { useLocaleDateTimeFormat } from '@centreon/ui';
5
6
 
6
- import { getUnits } from '../../timeSeries';
7
7
  import { getXAxisTickFormat } from '../../helpers';
8
8
  import { GraphInterval } from '../../models';
9
+ import { getUnits } from '../../timeSeries';
9
10
 
10
11
  import UnitLabel from './UnitLabel';
11
12
  import { Data } from './models';
@@ -35,7 +36,7 @@ const Axes = ({
35
36
 
36
37
  const { axisLeft, axisRight } = useAxisY({ data, graphHeight: height });
37
38
 
38
- const [firstUnit, secondUnit] = getUnits(lines);
39
+ const [firstUnit, secondUnit, thirdUnit] = getUnits(lines);
39
40
 
40
41
  const xTickCount = Math.ceil(width / 82);
41
42
 
@@ -45,6 +46,9 @@ const Axes = ({
45
46
  const formatAxisTick = (tick): string =>
46
47
  format({ date: new Date(tick), formatString: tickFormat });
47
48
 
49
+ const hasMoreThanTwoUnits = !isNil(thirdUnit);
50
+ const displayAxisRight = !isNil(secondUnit) && !hasMoreThanTwoUnits;
51
+
48
52
  return (
49
53
  <g>
50
54
  <Axis.AxisBottom
@@ -65,7 +69,7 @@ const Axes = ({
65
69
  tickLength={2}
66
70
  />
67
71
 
68
- {axisRight.display && (
72
+ {displayAxisRight && (
69
73
  <Axis.AxisRight
70
74
  left={width}
71
75
  numTicks={axisRight.numTicks}
@@ -37,7 +37,7 @@ const RegularLine = ({
37
37
  transparency,
38
38
  graphHeight
39
39
  }: Props): JSX.Element => {
40
- const isHighlighted = highlight ? 2 : 0.8;
40
+ const isHighlighted = highlight ? 2 : 1;
41
41
 
42
42
  const props = {
43
43
  curve: Curve.curveLinear,