@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.
Files changed (59) hide show
  1. package/package.json +1 -1
  2. package/src/Form/Inputs/ConnectedAutocomplete.tsx +3 -1
  3. package/src/Form/Inputs/models.ts +1 -0
  4. package/src/Graph/Gauge/Gauge.stories.tsx +15 -2
  5. package/src/Graph/HeatMap/HeatMap.stories.tsx +105 -0
  6. package/src/Graph/HeatMap/HeatMap.styles.tsx +29 -0
  7. package/src/Graph/HeatMap/HeatMap.tsx +12 -0
  8. package/src/Graph/HeatMap/HeatMapData.json +137 -0
  9. package/src/Graph/HeatMap/ResponsiveHeatMap.tsx +98 -0
  10. package/src/Graph/HeatMap/index.ts +1 -0
  11. package/src/Graph/HeatMap/model.ts +33 -0
  12. package/src/Graph/LineChart/BasicComponents/Lines/RegularLines/index.tsx +1 -1
  13. package/src/Graph/LineChart/BasicComponents/useFilterLines.ts +2 -4
  14. package/src/Graph/LineChart/Legend/InteractiveValue.tsx +3 -3
  15. package/src/Graph/LineChart/Legend/Legend.styles.ts +78 -32
  16. package/src/Graph/LineChart/Legend/LegendContent.tsx +12 -6
  17. package/src/Graph/LineChart/Legend/LegendHeader.tsx +69 -21
  18. package/src/Graph/LineChart/Legend/index.tsx +51 -23
  19. package/src/Graph/LineChart/Legend/models.ts +5 -0
  20. package/src/Graph/LineChart/Legend/useLegend.ts +9 -10
  21. package/src/Graph/LineChart/LineChart.tsx +17 -3
  22. package/src/Graph/index.ts +1 -0
  23. package/src/InputField/Select/Autocomplete/Connected/Multi/index.test.tsx +1 -0
  24. package/src/InputField/Select/Autocomplete/Connected/index.test.tsx +1 -0
  25. package/src/InputField/Select/Autocomplete/Connected/index.tsx +3 -0
  26. package/src/InputField/Text/index.tsx +6 -1
  27. package/src/RichTextEditor/RichTextEditor.cypress.spec.tsx +100 -52
  28. package/src/RichTextEditor/RichTextEditor.tsx +9 -3
  29. package/src/RichTextEditor/plugins/ToolbarPlugin/AlignPicker.tsx +21 -20
  30. package/src/RichTextEditor/plugins/ToolbarPlugin/BlockButtons.tsx +35 -77
  31. package/src/RichTextEditor/plugins/ToolbarPlugin/FormatButtons.tsx +29 -83
  32. package/src/RichTextEditor/plugins/ToolbarPlugin/LinkButton.tsx +106 -0
  33. package/src/RichTextEditor/plugins/ToolbarPlugin/ListButton.tsx +155 -0
  34. package/src/RichTextEditor/plugins/ToolbarPlugin/MacrosButton.tsx +23 -39
  35. package/src/RichTextEditor/plugins/ToolbarPlugin/ToolbarPlugin.styles.ts +24 -14
  36. package/src/RichTextEditor/plugins/ToolbarPlugin/UndoRedoButtons.tsx +6 -0
  37. package/src/RichTextEditor/plugins/ToolbarPlugin/index.tsx +5 -10
  38. package/src/RichTextEditor/translatedLabels.ts +3 -0
  39. package/src/ThemeProvider/palettes.ts +4 -4
  40. package/src/Typography/EllipsisTypography.tsx +18 -0
  41. package/src/api/buildListingEndpoint/models.ts +2 -1
  42. package/src/api/customFetch.ts +12 -3
  43. package/src/api/useFetchQuery/index.ts +16 -5
  44. package/src/api/useGraphQuery/index.ts +4 -1
  45. package/src/api/useMutationQuery/index.ts +4 -1
  46. package/src/components/Header/PageHeader/PageHeader.styles.ts +28 -1
  47. package/src/components/Header/PageHeader/PageHeaderMessage.tsx +32 -0
  48. package/src/components/Header/PageHeader/index.ts +2 -0
  49. package/src/components/ItemComposition/Item.tsx +2 -2
  50. package/src/components/ItemComposition/ItemComposition.styles.ts +3 -0
  51. package/src/components/ItemComposition/ItemComposition.tsx +4 -2
  52. package/src/components/Menu/Button/MenuButton.tsx +4 -2
  53. package/src/components/Menu/MenuItem.tsx +5 -3
  54. package/src/components/Menu/MenuItems.tsx +4 -3
  55. package/src/components/Modal/Modal.styles.ts +4 -2
  56. package/src/index.ts +4 -0
  57. package/src/utils/useInfiniteScrollListing.ts +22 -7
  58. package/src/utils/useLocaleDateTimeFormat/index.ts +3 -0
  59. 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;
@@ -52,7 +52,8 @@ export type Operator =
52
52
  | '$lk'
53
53
  | '$nk'
54
54
  | '$in'
55
- | '$ni';
55
+ | '$ni'
56
+ | '$rg';
56
57
 
57
58
  export type ConditionValue = {
58
59
  [value in Operator]?: string | Array<string>;
@@ -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(endpoint, options)
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=[${definedMetrics.join(',')}]`;
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: 'flex-start',
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
- {!deleteButtonHidden && (
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
  };
@@ -22,5 +22,8 @@ export const useItemStyles = makeStyles()((theme) => ({
22
22
  display: 'flex',
23
23
  flexDirection: 'row',
24
24
  width: '100%'
25
+ },
26
+ visibilityHiden: {
27
+ visibility: 'hidden'
25
28
  }
26
29
  }));
@@ -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: 'sticky'
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
- decoder: JsonDecoder.Decoder<Listing<T>>;
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
- parameters: { limit, page: params?.page || page }
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;