@centreon/ui 23.10.1-sync-dev-23-10-x-develop-oss.0 → 23.10.1-sync-release-33038.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/Form/Inputs/ConnectedAutocomplete.tsx +3 -1
- package/src/Form/Inputs/models.ts +1 -0
- package/src/Graph/Gauge/Gauge.stories.tsx +15 -2
- package/src/Graph/HeatMap/HeatMap.stories.tsx +105 -0
- package/src/Graph/HeatMap/HeatMap.styles.tsx +29 -0
- package/src/Graph/HeatMap/HeatMap.tsx +12 -0
- package/src/Graph/HeatMap/HeatMapData.json +137 -0
- package/src/Graph/HeatMap/ResponsiveHeatMap.tsx +98 -0
- package/src/Graph/HeatMap/index.ts +1 -0
- package/src/Graph/HeatMap/model.ts +33 -0
- package/src/Graph/LineChart/BasicComponents/Lines/RegularLines/index.tsx +1 -1
- package/src/Graph/LineChart/BasicComponents/useFilterLines.ts +2 -4
- package/src/Graph/LineChart/Legend/InteractiveValue.tsx +3 -3
- package/src/Graph/LineChart/Legend/Legend.styles.ts +78 -32
- package/src/Graph/LineChart/Legend/LegendContent.tsx +12 -6
- package/src/Graph/LineChart/Legend/LegendHeader.tsx +69 -21
- package/src/Graph/LineChart/Legend/index.tsx +51 -23
- package/src/Graph/LineChart/Legend/models.ts +5 -0
- package/src/Graph/LineChart/Legend/useLegend.ts +9 -10
- package/src/Graph/LineChart/LineChart.tsx +17 -3
- package/src/Graph/index.ts +1 -0
- package/src/InputField/Select/Autocomplete/Connected/Multi/index.test.tsx +1 -0
- package/src/InputField/Select/Autocomplete/Connected/index.test.tsx +1 -0
- package/src/InputField/Select/Autocomplete/Connected/index.tsx +3 -0
- package/src/InputField/Text/index.tsx +6 -1
- package/src/RichTextEditor/RichTextEditor.cypress.spec.tsx +100 -52
- package/src/RichTextEditor/RichTextEditor.tsx +9 -3
- package/src/RichTextEditor/plugins/ToolbarPlugin/AlignPicker.tsx +21 -20
- package/src/RichTextEditor/plugins/ToolbarPlugin/BlockButtons.tsx +35 -77
- package/src/RichTextEditor/plugins/ToolbarPlugin/FormatButtons.tsx +29 -83
- package/src/RichTextEditor/plugins/ToolbarPlugin/LinkButton.tsx +106 -0
- package/src/RichTextEditor/plugins/ToolbarPlugin/ListButton.tsx +155 -0
- package/src/RichTextEditor/plugins/ToolbarPlugin/MacrosButton.tsx +23 -39
- package/src/RichTextEditor/plugins/ToolbarPlugin/ToolbarPlugin.styles.ts +24 -14
- package/src/RichTextEditor/plugins/ToolbarPlugin/UndoRedoButtons.tsx +6 -0
- package/src/RichTextEditor/plugins/ToolbarPlugin/index.tsx +5 -10
- package/src/RichTextEditor/translatedLabels.ts +3 -0
- package/src/ThemeProvider/palettes.ts +4 -4
- package/src/Typography/EllipsisTypography.tsx +18 -0
- package/src/api/buildListingEndpoint/models.ts +2 -1
- package/src/api/customFetch.ts +12 -3
- package/src/api/useFetchQuery/index.ts +16 -5
- package/src/api/useGraphQuery/index.ts +4 -1
- package/src/api/useMutationQuery/index.ts +4 -1
- package/src/components/Header/PageHeader/PageHeader.styles.ts +28 -1
- package/src/components/Header/PageHeader/PageHeaderMessage.tsx +32 -0
- package/src/components/Header/PageHeader/index.ts +2 -0
- package/src/components/ItemComposition/Item.tsx +2 -2
- package/src/components/ItemComposition/ItemComposition.styles.ts +3 -0
- package/src/components/ItemComposition/ItemComposition.tsx +4 -2
- package/src/components/Menu/Button/MenuButton.tsx +4 -2
- package/src/components/Menu/MenuItem.tsx +5 -3
- package/src/components/Menu/MenuItems.tsx +4 -3
- package/src/components/Modal/Modal.styles.ts +4 -2
- package/src/index.ts +4 -0
- package/src/utils/useInfiniteScrollListing.ts +22 -7
- package/src/utils/useLocaleDateTimeFormat/index.ts +3 -0
- package/src/Graph/LineChart/Legend/Marker.tsx +0 -43
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Box, Typography, TypographyProps } from '@mui/material';
|
|
2
|
+
|
|
3
|
+
const EllipsisTypography = (props: TypographyProps): JSX.Element => {
|
|
4
|
+
return (
|
|
5
|
+
<Box sx={{ width: '100%' }}>
|
|
6
|
+
<Typography
|
|
7
|
+
sx={{
|
|
8
|
+
overflow: 'hidden',
|
|
9
|
+
textOverflow: 'ellipsis',
|
|
10
|
+
whiteSpace: 'nowrap'
|
|
11
|
+
}}
|
|
12
|
+
{...props}
|
|
13
|
+
/>
|
|
14
|
+
</Box>
|
|
15
|
+
);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default EllipsisTypography;
|
package/src/api/customFetch.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { equals } from 'ramda';
|
|
1
|
+
import { equals, isNil, startsWith } from 'ramda';
|
|
2
2
|
import { JsonDecoder } from 'ts.data.json';
|
|
3
3
|
|
|
4
4
|
import { Method } from './useMutationQuery';
|
|
@@ -22,6 +22,7 @@ export interface CatchErrorProps {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
interface CustomFetchProps<T> {
|
|
25
|
+
baseEndpoint?: string;
|
|
25
26
|
catchError?: (props: CatchErrorProps) => void;
|
|
26
27
|
decoder?: JsonDecoder.Decoder<T>;
|
|
27
28
|
defaultFailureMessage?: string;
|
|
@@ -42,10 +43,18 @@ export const customFetch = <T>({
|
|
|
42
43
|
defaultFailureMessage = 'Something went wrong',
|
|
43
44
|
isMutation = false,
|
|
44
45
|
payload,
|
|
45
|
-
method = 'GET'
|
|
46
|
+
method = 'GET',
|
|
47
|
+
baseEndpoint = './api/latest'
|
|
46
48
|
}: CustomFetchProps<T>): Promise<T | ResponseError> => {
|
|
47
49
|
const defaultOptions = { headers, method, signal };
|
|
48
50
|
|
|
51
|
+
const formattedEndpoint =
|
|
52
|
+
!isNil(baseEndpoint) &&
|
|
53
|
+
!startsWith(baseEndpoint, endpoint) &&
|
|
54
|
+
!startsWith('./api/internal.php', endpoint)
|
|
55
|
+
? `${baseEndpoint}${endpoint}`
|
|
56
|
+
: endpoint;
|
|
57
|
+
|
|
49
58
|
const options = isMutation
|
|
50
59
|
? {
|
|
51
60
|
...defaultOptions,
|
|
@@ -53,7 +62,7 @@ export const customFetch = <T>({
|
|
|
53
62
|
}
|
|
54
63
|
: defaultOptions;
|
|
55
64
|
|
|
56
|
-
return fetch(
|
|
65
|
+
return fetch(formattedEndpoint, options)
|
|
57
66
|
.then((response) => {
|
|
58
67
|
if (equals(response.status, 204)) {
|
|
59
68
|
return {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useMemo } from 'react';
|
|
1
|
+
import { useEffect, useMemo, useRef } from 'react';
|
|
2
2
|
|
|
3
3
|
import 'ulog';
|
|
4
4
|
import {
|
|
@@ -10,13 +10,14 @@ import {
|
|
|
10
10
|
} from '@tanstack/react-query';
|
|
11
11
|
import { JsonDecoder } from 'ts.data.json';
|
|
12
12
|
import anylogger from 'anylogger';
|
|
13
|
-
import { has, includes, not, omit } from 'ramda';
|
|
13
|
+
import { has, includes, isNil, not, omit } from 'ramda';
|
|
14
14
|
|
|
15
15
|
import { CatchErrorProps, customFetch, ResponseError } from '../customFetch';
|
|
16
16
|
import useSnackbar from '../../Snackbar/useSnackbar';
|
|
17
17
|
import { useDeepCompare } from '../../utils';
|
|
18
18
|
|
|
19
19
|
export interface UseFetchQueryProps<T> {
|
|
20
|
+
baseEndpoint?: string;
|
|
20
21
|
catchError?: (props: CatchErrorProps) => void;
|
|
21
22
|
decoder?: JsonDecoder.Decoder<T>;
|
|
22
23
|
defaultFailureMessage?: string;
|
|
@@ -54,14 +55,18 @@ const useFetchQuery = <T extends object>({
|
|
|
54
55
|
fetchHeaders,
|
|
55
56
|
isPaginated,
|
|
56
57
|
queryOptions,
|
|
57
|
-
httpCodesBypassErrorSnackbar = []
|
|
58
|
+
httpCodesBypassErrorSnackbar = [],
|
|
59
|
+
baseEndpoint
|
|
58
60
|
}: UseFetchQueryProps<T>): UseFetchQueryState<T> => {
|
|
61
|
+
const dataRef = useRef<T | undefined>(undefined);
|
|
62
|
+
|
|
59
63
|
const { showErrorMessage } = useSnackbar();
|
|
60
64
|
|
|
61
65
|
const queryData = useQuery<T | ResponseError, Error>(
|
|
62
66
|
getQueryKey(),
|
|
63
67
|
({ signal }): Promise<T | ResponseError> =>
|
|
64
68
|
customFetch<T>({
|
|
69
|
+
baseEndpoint,
|
|
65
70
|
catchError,
|
|
66
71
|
decoder,
|
|
67
72
|
defaultFailureMessage,
|
|
@@ -96,6 +101,7 @@ const useFetchQuery = <T extends object>({
|
|
|
96
101
|
queryKey,
|
|
97
102
|
({ signal }): Promise<T | ResponseError> =>
|
|
98
103
|
customFetch<T>({
|
|
104
|
+
baseEndpoint,
|
|
99
105
|
catchError,
|
|
100
106
|
decoder,
|
|
101
107
|
defaultFailureMessage,
|
|
@@ -137,6 +143,7 @@ const useFetchQuery = <T extends object>({
|
|
|
137
143
|
getQueryKey(),
|
|
138
144
|
({ signal }): Promise<T | ResponseError> =>
|
|
139
145
|
customFetch<T>({
|
|
146
|
+
baseEndpoint,
|
|
140
147
|
catchError,
|
|
141
148
|
decoder,
|
|
142
149
|
defaultFailureMessage,
|
|
@@ -153,6 +160,10 @@ const useFetchQuery = <T extends object>({
|
|
|
153
160
|
[queryData.data]
|
|
154
161
|
);
|
|
155
162
|
|
|
163
|
+
if (!isNil(data)) {
|
|
164
|
+
dataRef.current = data;
|
|
165
|
+
}
|
|
166
|
+
|
|
156
167
|
const errorData = queryData.data as ResponseError | undefined;
|
|
157
168
|
|
|
158
169
|
useEffect(() => {
|
|
@@ -166,8 +177,8 @@ const useFetchQuery = <T extends object>({
|
|
|
166
177
|
}, useDeepCompare([queryData.data]));
|
|
167
178
|
|
|
168
179
|
return {
|
|
169
|
-
...omit(['data'], queryData),
|
|
170
|
-
data,
|
|
180
|
+
...omit(['data', 'error'], queryData),
|
|
181
|
+
data: dataRef.current,
|
|
171
182
|
error: errorData?.isError ? omit(['isError'], errorData) : null,
|
|
172
183
|
fetchQuery,
|
|
173
184
|
prefetchNextPage,
|
|
@@ -92,6 +92,9 @@ const useGraphQuery = ({
|
|
|
92
92
|
: getStartEndFromTimePeriod(timePeriodToUse as number);
|
|
93
93
|
|
|
94
94
|
const definedMetrics = metrics.filter((metric) => metric);
|
|
95
|
+
const formattedDefinedMetrics = definedMetrics.map((metric) =>
|
|
96
|
+
encodeURIComponent(metric)
|
|
97
|
+
);
|
|
95
98
|
|
|
96
99
|
const {
|
|
97
100
|
data: graphData,
|
|
@@ -115,7 +118,7 @@ const useGraphQuery = ({
|
|
|
115
118
|
|
|
116
119
|
return `${endpoint}&start=${startAndEnd.start}&end=${
|
|
117
120
|
startAndEnd.end
|
|
118
|
-
}&metric_names=[${
|
|
121
|
+
}&metric_names=[${formattedDefinedMetrics.join(',')}]`;
|
|
119
122
|
},
|
|
120
123
|
getQueryKey: () => [
|
|
121
124
|
'graph',
|
|
@@ -23,6 +23,7 @@ export enum Method {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export type UseMutationQueryProps<T, TMeta> = {
|
|
26
|
+
baseEndpoint?: string;
|
|
26
27
|
catchError?: (props: CatchErrorProps) => void;
|
|
27
28
|
decoder?: JsonDecoder.Decoder<T>;
|
|
28
29
|
defaultFailureMessage?: string;
|
|
@@ -49,7 +50,8 @@ const useMutationQuery = <T extends object, TMeta>({
|
|
|
49
50
|
method,
|
|
50
51
|
onMutate,
|
|
51
52
|
onError,
|
|
52
|
-
onSuccess
|
|
53
|
+
onSuccess,
|
|
54
|
+
baseEndpoint
|
|
53
55
|
}: UseMutationQueryProps<T, TMeta>): UseMutationQueryState<T> => {
|
|
54
56
|
const { showErrorMessage } = useSnackbar();
|
|
55
57
|
|
|
@@ -62,6 +64,7 @@ const useMutationQuery = <T extends object, TMeta>({
|
|
|
62
64
|
const { _meta, ...payload } = _payload || {};
|
|
63
65
|
|
|
64
66
|
return customFetch<T>({
|
|
67
|
+
baseEndpoint,
|
|
65
68
|
catchError,
|
|
66
69
|
decoder,
|
|
67
70
|
defaultFailureMessage,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { makeStyles } from 'tss-react/mui';
|
|
2
2
|
|
|
3
|
+
import { alpha } from '@mui/system';
|
|
4
|
+
|
|
3
5
|
const useStyles = makeStyles()((theme) => ({
|
|
4
6
|
header: {
|
|
5
7
|
alignItems: 'flex-start',
|
|
@@ -22,7 +24,7 @@ const useStyles = makeStyles()((theme) => ({
|
|
|
22
24
|
padding: theme.spacing(0, 0, 1.5, 0)
|
|
23
25
|
},
|
|
24
26
|
pageHeader: {
|
|
25
|
-
alignItems: '
|
|
27
|
+
alignItems: 'center',
|
|
26
28
|
borderBottom: `1px solid ${theme.palette.header.page.border}`,
|
|
27
29
|
display: 'flex',
|
|
28
30
|
gap: theme.spacing(4),
|
|
@@ -53,6 +55,31 @@ const useStyles = makeStyles()((theme) => ({
|
|
|
53
55
|
position: 'relative',
|
|
54
56
|
transform: `translateY(-${theme.spacing(0.25)})`
|
|
55
57
|
},
|
|
58
|
+
pageHeaderMessage: {
|
|
59
|
+
alignItems: 'center',
|
|
60
|
+
color: theme.palette.warning.main,
|
|
61
|
+
display: 'flex',
|
|
62
|
+
gap: theme.spacing(1)
|
|
63
|
+
},
|
|
64
|
+
pageHeaderMessageIcon: {
|
|
65
|
+
alignItems: 'center',
|
|
66
|
+
background: theme.palette.warning.main,
|
|
67
|
+
borderRadius: '50%',
|
|
68
|
+
color: theme.palette.common.white,
|
|
69
|
+
display: 'flex',
|
|
70
|
+
height: theme.spacing(2.5),
|
|
71
|
+
justifyContent: 'center',
|
|
72
|
+
width: theme.spacing(2.5)
|
|
73
|
+
},
|
|
74
|
+
pageHeaderMessageIconWrapper: {
|
|
75
|
+
alignItems: 'center',
|
|
76
|
+
backgroundColor: alpha(theme.palette.warning.main, 0.7),
|
|
77
|
+
borderRadius: '50%',
|
|
78
|
+
display: 'flex',
|
|
79
|
+
height: theme.spacing(3.5),
|
|
80
|
+
justifyContent: 'center',
|
|
81
|
+
width: theme.spacing(3.5)
|
|
82
|
+
},
|
|
56
83
|
pageHeaderTitle: {
|
|
57
84
|
'& > *': {
|
|
58
85
|
display: 'grid'
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ReactElement } from 'react';
|
|
2
|
+
|
|
3
|
+
import { Box, Typography } from '@mui/material';
|
|
4
|
+
|
|
5
|
+
import { useStyles } from './PageHeader.styles';
|
|
6
|
+
|
|
7
|
+
type PageHeaderMessageProps = {
|
|
8
|
+
message: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const PageHeaderMessage = ({
|
|
12
|
+
message
|
|
13
|
+
}: PageHeaderMessageProps): ReactElement => {
|
|
14
|
+
const { classes } = useStyles();
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<Box className={classes.pageHeaderMessage}>
|
|
18
|
+
{message && (
|
|
19
|
+
<>
|
|
20
|
+
<Box className={classes.pageHeaderMessageIconWrapper}>
|
|
21
|
+
<Box className={classes.pageHeaderMessageIcon}>!</Box>
|
|
22
|
+
</Box>
|
|
23
|
+
<Typography aria-label="page header message" variant="h6">
|
|
24
|
+
{message}
|
|
25
|
+
</Typography>
|
|
26
|
+
</>
|
|
27
|
+
)}
|
|
28
|
+
</Box>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export { PageHeaderMessage };
|
|
@@ -3,10 +3,12 @@ import { PageHeaderMain } from './PageHeaderMain';
|
|
|
3
3
|
import { PageHeaderMenu } from './PageHeaderMenu';
|
|
4
4
|
import { PageHeaderTitle } from './PageHeaderTitle';
|
|
5
5
|
import { PageHeaderActions } from './PageHeaderActions';
|
|
6
|
+
import { PageHeaderMessage } from './PageHeaderMessage';
|
|
6
7
|
|
|
7
8
|
export const PageHeader = Object.assign(PageHeaderRoot, {
|
|
8
9
|
Actions: PageHeaderActions,
|
|
9
10
|
Main: PageHeaderMain,
|
|
10
11
|
Menu: PageHeaderMenu,
|
|
12
|
+
Message: PageHeaderMessage,
|
|
11
13
|
Title: PageHeaderTitle
|
|
12
14
|
});
|
|
@@ -26,7 +26,7 @@ export const Item = ({
|
|
|
26
26
|
return (
|
|
27
27
|
<div className={classes.itemContainer}>
|
|
28
28
|
<div className={cx(classes.itemContent, className)}>{children}</div>
|
|
29
|
-
{
|
|
29
|
+
<div className={cx({ [classes.visibilityHiden]: deleteButtonHidden })}>
|
|
30
30
|
<IconButton
|
|
31
31
|
aria-label={labelDelete}
|
|
32
32
|
data-testid={labelDelete}
|
|
@@ -35,7 +35,7 @@ export const Item = ({
|
|
|
35
35
|
variant="ghost"
|
|
36
36
|
onClick={onDeleteItem}
|
|
37
37
|
/>
|
|
38
|
-
|
|
38
|
+
</div>
|
|
39
39
|
</div>
|
|
40
40
|
);
|
|
41
41
|
};
|
|
@@ -7,6 +7,7 @@ import { Button } from '..';
|
|
|
7
7
|
import { useItemCompositionStyles } from './ItemComposition.styles';
|
|
8
8
|
|
|
9
9
|
type Props = {
|
|
10
|
+
IconAdd?;
|
|
10
11
|
addButtonHidden?: boolean;
|
|
11
12
|
addbuttonDisabled?: boolean;
|
|
12
13
|
children: Array<ReactElement>;
|
|
@@ -19,7 +20,8 @@ export const ItemComposition = ({
|
|
|
19
20
|
children,
|
|
20
21
|
labelAdd,
|
|
21
22
|
addbuttonDisabled,
|
|
22
|
-
addButtonHidden
|
|
23
|
+
addButtonHidden,
|
|
24
|
+
IconAdd
|
|
23
25
|
}: Props): JSX.Element => {
|
|
24
26
|
const { classes } = useItemCompositionStyles();
|
|
25
27
|
|
|
@@ -31,7 +33,7 @@ export const ItemComposition = ({
|
|
|
31
33
|
aria-label={labelAdd}
|
|
32
34
|
data-testid={labelAdd}
|
|
33
35
|
disabled={addbuttonDisabled}
|
|
34
|
-
icon={<AddIcon />}
|
|
36
|
+
icon={IconAdd || <AddIcon />}
|
|
35
37
|
iconVariant="start"
|
|
36
38
|
size="small"
|
|
37
39
|
variant="ghost"
|
|
@@ -15,6 +15,7 @@ import { useStyles } from './MenuButton.styles';
|
|
|
15
15
|
type MenuButtonProps = {
|
|
16
16
|
ariaLabel?: string;
|
|
17
17
|
children?: ReactNode;
|
|
18
|
+
className?: string;
|
|
18
19
|
hasArrow?: boolean;
|
|
19
20
|
isOpen?: boolean;
|
|
20
21
|
onClick?: (args: { isOpen: boolean }) => void;
|
|
@@ -29,9 +30,10 @@ const MenuButton = ({
|
|
|
29
30
|
size = 'small',
|
|
30
31
|
variant = 'ghost',
|
|
31
32
|
ariaLabel,
|
|
33
|
+
className,
|
|
32
34
|
...attr
|
|
33
35
|
}: MenuButtonProps): ReactElement => {
|
|
34
|
-
const { classes } = useStyles();
|
|
36
|
+
const { cx, classes } = useStyles();
|
|
35
37
|
|
|
36
38
|
const { isMenuOpen, setIsMenuOpen, setAnchorEl, onOpen } = useMenu();
|
|
37
39
|
|
|
@@ -50,7 +52,7 @@ const MenuButton = ({
|
|
|
50
52
|
<Button
|
|
51
53
|
{...attr}
|
|
52
54
|
aria-label={ariaLabel}
|
|
53
|
-
className={classes.menuButton}
|
|
55
|
+
className={cx(classes.menuButton, className)}
|
|
54
56
|
data-is-active={isMenuOpen}
|
|
55
57
|
size={size}
|
|
56
58
|
variant={variant}
|
|
@@ -6,6 +6,7 @@ import { useStyles } from './Menu.styles';
|
|
|
6
6
|
|
|
7
7
|
type MenuItemProps = {
|
|
8
8
|
children?: ReactNode;
|
|
9
|
+
className?: string;
|
|
9
10
|
isActive?: boolean;
|
|
10
11
|
isDisabled?: boolean;
|
|
11
12
|
onClick?: () => void;
|
|
@@ -15,13 +16,14 @@ const MenuItem = ({
|
|
|
15
16
|
children,
|
|
16
17
|
onClick,
|
|
17
18
|
isActive = false,
|
|
18
|
-
isDisabled = false
|
|
19
|
+
isDisabled = false,
|
|
20
|
+
className
|
|
19
21
|
}: MenuItemProps): ReactElement => {
|
|
20
|
-
const { classes } = useStyles();
|
|
22
|
+
const { cx, classes } = useStyles();
|
|
21
23
|
|
|
22
24
|
return (
|
|
23
25
|
<MuiMenuItem
|
|
24
|
-
className={classes.menuItem}
|
|
26
|
+
className={cx(classes.menuItem, className)}
|
|
25
27
|
data-is-active={isActive}
|
|
26
28
|
data-is-disabled={isDisabled}
|
|
27
29
|
disabled={isDisabled}
|
|
@@ -7,9 +7,10 @@ import { useMenu } from './useMenu';
|
|
|
7
7
|
|
|
8
8
|
type MenuItemsProps = {
|
|
9
9
|
children?: ReactNode | Array<ReactNode>;
|
|
10
|
+
className?: string;
|
|
10
11
|
};
|
|
11
|
-
const MenuItems = ({ children }: MenuItemsProps): ReactElement => {
|
|
12
|
-
const { classes } = useStyles();
|
|
12
|
+
const MenuItems = ({ children, className }: MenuItemsProps): ReactElement => {
|
|
13
|
+
const { cx, classes } = useStyles();
|
|
13
14
|
|
|
14
15
|
const { isMenuOpen, setIsMenuOpen, anchorEl, onClose } = useMenu();
|
|
15
16
|
|
|
@@ -21,7 +22,7 @@ const MenuItems = ({ children }: MenuItemsProps): ReactElement => {
|
|
|
21
22
|
return (
|
|
22
23
|
<MuiMenu
|
|
23
24
|
anchorEl={anchorEl}
|
|
24
|
-
className={classes.menuItems}
|
|
25
|
+
className={cx(classes.menuItems, className)}
|
|
25
26
|
open={isMenuOpen}
|
|
26
27
|
variant="menu"
|
|
27
28
|
onClick={onCloseMenu}
|
|
@@ -24,9 +24,9 @@ const useStyles = makeStyles<{
|
|
|
24
24
|
},
|
|
25
25
|
'&[data-size="fullscreen"] .MuiDialog-paper': {
|
|
26
26
|
bottom: props?.bottom ?? 0,
|
|
27
|
+
height: 'calc(100vh - 90px)',
|
|
27
28
|
left: props?.left ?? 0,
|
|
28
29
|
margin: 0,
|
|
29
|
-
maxHeight: 'unset',
|
|
30
30
|
maxWidth: 'unset',
|
|
31
31
|
position: 'absolute',
|
|
32
32
|
right: props?.right ?? 0,
|
|
@@ -50,11 +50,13 @@ const useStyles = makeStyles<{
|
|
|
50
50
|
},
|
|
51
51
|
modalActions: {
|
|
52
52
|
bottom: 0,
|
|
53
|
+
bottom: theme.spacing(2),
|
|
53
54
|
display: 'flex',
|
|
54
55
|
flexDirection: 'row',
|
|
55
56
|
gap: theme.spacing(2),
|
|
56
57
|
justifyContent: 'flex-end',
|
|
57
|
-
position: '
|
|
58
|
+
position: 'fixed',
|
|
59
|
+
right: theme.spacing(2)
|
|
58
60
|
},
|
|
59
61
|
modalBody: {
|
|
60
62
|
'& > p': {
|
package/src/index.ts
CHANGED
|
@@ -154,6 +154,7 @@ export type { ResponseError, CatchErrorProps } from './api/customFetch';
|
|
|
154
154
|
|
|
155
155
|
export * from './utils';
|
|
156
156
|
export { default as FluidTypography } from './Typography/FluidTypography';
|
|
157
|
+
export { default as EllipsisTypography } from './Typography/EllipsisTypography';
|
|
157
158
|
export * from './Dashboard';
|
|
158
159
|
export * from './Graph';
|
|
159
160
|
export type { LineChartData } from './Graph/common/models';
|
|
@@ -162,3 +163,6 @@ export * from './Graph/common/timeSeries';
|
|
|
162
163
|
export { default as TimePeriods } from './TimePeriods';
|
|
163
164
|
export { default as SimpleCustomTimePeriod } from './TimePeriods/CustomTimePeriod/SimpleCustomTimePeriod';
|
|
164
165
|
export * from './ParentSize';
|
|
166
|
+
|
|
167
|
+
export { default as TablePagination } from './Listing/ActionBar/Pagination';
|
|
168
|
+
export { default as PaginationActions } from './Listing/ActionBar/PaginationActions';
|
|
@@ -5,33 +5,42 @@ import { PrimitiveAtom, useAtom } from 'jotai';
|
|
|
5
5
|
import { JsonDecoder } from 'ts.data.json';
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
|
+
QueryParameter,
|
|
8
9
|
buildListingEndpoint,
|
|
9
10
|
useFetchQuery,
|
|
10
11
|
useIntersectionObserver
|
|
11
12
|
} from '@centreon/ui';
|
|
12
13
|
|
|
13
14
|
import type { Listing } from '../api/models';
|
|
14
|
-
|
|
15
|
-
const limit = 100;
|
|
15
|
+
import { Parameters } from '../api/buildListingEndpoint/models';
|
|
16
16
|
|
|
17
17
|
interface UseInfiniteScrollListing<T> {
|
|
18
18
|
elementRef: (node) => void;
|
|
19
19
|
elements: Array<T>;
|
|
20
20
|
isLoading: boolean;
|
|
21
|
+
total?: number;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
interface UseInfiniteScrollListingProps<T> {
|
|
24
|
-
|
|
25
|
+
customQueryParameters?: Array<QueryParameter>;
|
|
26
|
+
decoder?: JsonDecoder.Decoder<Listing<T>>;
|
|
25
27
|
endpoint: string;
|
|
28
|
+
limit?: number;
|
|
26
29
|
pageAtom: PrimitiveAtom<number>;
|
|
30
|
+
parameters?: Parameters;
|
|
27
31
|
queryKeyName: string;
|
|
32
|
+
suspense?: boolean;
|
|
28
33
|
}
|
|
29
34
|
|
|
30
35
|
export const useInfiniteScrollListing = <T>({
|
|
31
36
|
queryKeyName,
|
|
32
37
|
endpoint,
|
|
33
38
|
decoder,
|
|
34
|
-
pageAtom
|
|
39
|
+
pageAtom,
|
|
40
|
+
suspense = true,
|
|
41
|
+
parameters,
|
|
42
|
+
customQueryParameters,
|
|
43
|
+
limit = 100
|
|
35
44
|
}: UseInfiniteScrollListingProps<T>): UseInfiniteScrollListing<T> => {
|
|
36
45
|
const [maxPage, setMaxPage] = useState(1);
|
|
37
46
|
|
|
@@ -46,14 +55,15 @@ export const useInfiniteScrollListing = <T>({
|
|
|
46
55
|
getEndpoint: (params) =>
|
|
47
56
|
buildListingEndpoint({
|
|
48
57
|
baseEndpoint: endpoint,
|
|
49
|
-
|
|
58
|
+
customQueryParameters,
|
|
59
|
+
parameters: { limit, page: params?.page || page, ...parameters }
|
|
50
60
|
}),
|
|
51
61
|
getQueryKey: () => [queryKeyName, page],
|
|
52
62
|
isPaginated: true,
|
|
53
63
|
queryOptions: {
|
|
54
64
|
refetchOnMount: false,
|
|
55
65
|
refetchOnWindowFocus: false,
|
|
56
|
-
suspense: equals(page, 1)
|
|
66
|
+
suspense: suspense && equals(page, 1)
|
|
57
67
|
}
|
|
58
68
|
});
|
|
59
69
|
|
|
@@ -98,9 +108,14 @@ export const useInfiniteScrollListing = <T>({
|
|
|
98
108
|
});
|
|
99
109
|
}, [data]);
|
|
100
110
|
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
return () => setPage(1);
|
|
113
|
+
}, []);
|
|
114
|
+
|
|
101
115
|
return {
|
|
102
116
|
elementRef,
|
|
103
117
|
elements: elements.current || [],
|
|
104
|
-
isLoading
|
|
118
|
+
isLoading,
|
|
119
|
+
total: data?.meta.total
|
|
105
120
|
};
|
|
106
121
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import dayjs from 'dayjs';
|
|
2
2
|
import humanizeDuration from 'humanize-duration';
|
|
3
3
|
import { useAtomValue } from 'jotai';
|
|
4
|
+
import localizedFormat from 'dayjs/plugin/localizedFormat';
|
|
4
5
|
|
|
5
6
|
import { userAtom } from '@centreon/ui-context';
|
|
6
7
|
|
|
@@ -20,6 +21,8 @@ export interface LocaleDateTimeFormat {
|
|
|
20
21
|
toTime: (date: Date | string) => string;
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
dayjs.extend(localizedFormat);
|
|
25
|
+
|
|
23
26
|
const dateFormat = 'L';
|
|
24
27
|
const timeFormat = 'LT';
|
|
25
28
|
const dateTimeFormat = `${dateFormat} ${timeFormat}`;
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { equals } from 'ramda';
|
|
2
|
-
import { makeStyles } from 'tss-react/mui';
|
|
3
|
-
|
|
4
|
-
export enum LegendMarkerVariant {
|
|
5
|
-
'dot',
|
|
6
|
-
'bar'
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
interface StylesProps {
|
|
10
|
-
color?: string;
|
|
11
|
-
variant: LegendMarkerVariant;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const useStyles = makeStyles<StylesProps>()((theme, { color, variant }) => ({
|
|
15
|
-
disabled: {
|
|
16
|
-
color: theme.palette.text.disabled
|
|
17
|
-
},
|
|
18
|
-
icon: {
|
|
19
|
-
backgroundColor: color,
|
|
20
|
-
borderRadius: equals(LegendMarkerVariant.dot, variant) ? '50%' : 0,
|
|
21
|
-
height: equals(LegendMarkerVariant.dot, variant) ? 9 : '100%',
|
|
22
|
-
marginRight: theme.spacing(0.5),
|
|
23
|
-
width: 9
|
|
24
|
-
}
|
|
25
|
-
}));
|
|
26
|
-
|
|
27
|
-
interface Props {
|
|
28
|
-
color: string;
|
|
29
|
-
disabled?: boolean;
|
|
30
|
-
variant?: LegendMarkerVariant;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const LegendMarker = ({
|
|
34
|
-
disabled,
|
|
35
|
-
color,
|
|
36
|
-
variant = LegendMarkerVariant.bar
|
|
37
|
-
}: Props): JSX.Element => {
|
|
38
|
-
const { classes, cx } = useStyles({ color, variant });
|
|
39
|
-
|
|
40
|
-
return <div className={cx(classes.icon, { [classes.disabled]: disabled })} />;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
export default LegendMarker;
|