@centreon/ui 25.10.29 → 25.10.30

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 (69) hide show
  1. package/package.json +3 -3
  2. package/public/mockServiceWorker.js +8 -31
  3. package/src/Dashboard/Item.tsx +142 -149
  4. package/src/Form/Inputs/ConnectedAutocomplete.tsx +2 -0
  5. package/src/Form/Inputs/Grid.tsx +2 -3
  6. package/src/Form/Inputs/models.ts +2 -0
  7. package/src/Form/Section/navigateToSection.ts +6 -6
  8. package/src/Graph/BarChart/BarChart.cypress.spec.tsx +55 -102
  9. package/src/Graph/BarChart/BarChart.stories.tsx +1 -51
  10. package/src/Graph/BarChart/BarChart.tsx +1 -1
  11. package/src/Graph/BarChart/BarGroup.tsx +32 -22
  12. package/src/Graph/BarChart/BarStack.tsx +26 -15
  13. package/src/Graph/BarChart/MemoizedGroup.tsx +18 -14
  14. package/src/Graph/BarChart/ResponsiveBarChart.tsx +6 -7
  15. package/src/Graph/BarChart/Tooltip/BarChartTooltip.tsx +2 -2
  16. package/src/Graph/Chart/BasicComponents/Lines/StackedLines/index.tsx +5 -4
  17. package/src/Graph/Chart/BasicComponents/Lines/StackedLines/useStackedLines.ts +45 -18
  18. package/src/Graph/Chart/BasicComponents/Lines/index.tsx +118 -124
  19. package/src/Graph/Chart/Chart.cypress.spec.tsx +6 -25
  20. package/src/Graph/Chart/Chart.stories.tsx +1 -43
  21. package/src/Graph/Chart/Chart.tsx +13 -9
  22. package/src/Graph/Chart/InteractiveComponents/GraphValueTooltip/useGraphValueTooltip.ts +4 -2
  23. package/src/Graph/Chart/Legend/index.tsx +2 -26
  24. package/src/Graph/Chart/index.tsx +45 -31
  25. package/src/Graph/Chart/models.ts +1 -6
  26. package/src/Graph/Chart/translatedLabels.ts +1 -0
  27. package/src/Graph/Chart/useChartData.ts +24 -3
  28. package/src/Graph/common/Axes/index.tsx +1 -1
  29. package/src/Graph/common/BaseChart/BaseChart.tsx +1 -6
  30. package/src/Graph/common/BaseChart/ChartSvgWrapper.tsx +23 -16
  31. package/src/Graph/common/Error/NoData.tsx +18 -0
  32. package/src/Graph/common/Grids/index.tsx +4 -4
  33. package/src/Graph/common/timeSeries/index.test.ts +4 -24
  34. package/src/Graph/common/timeSeries/index.ts +120 -184
  35. package/src/Graph/common/timeSeries/models.ts +1 -1
  36. package/src/Graph/common/utils.ts +4 -10
  37. package/src/Graph/index.ts +20 -20
  38. package/src/InputField/Select/Autocomplete/Connected/index.tsx +3 -3
  39. package/src/InputField/Select/Autocomplete/Multi/Listbox.tsx +11 -3
  40. package/src/InputField/Select/Autocomplete/Multi/Multi.tsx +3 -2
  41. package/src/InputField/Select/index.tsx +2 -1
  42. package/src/Listing/ActionBar/Pagination.tsx +2 -1
  43. package/src/Listing/ActionBar/index.tsx +113 -8
  44. package/src/Listing/index.tsx +19 -2
  45. package/src/Listing/translatedLabels.ts +4 -0
  46. package/src/Module/index.tsx +2 -8
  47. package/src/ThemeProvider/index.tsx +21 -30
  48. package/src/ThemeProvider/tailwindcss.css +12 -10
  49. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/PickersStartEndDate.tsx +8 -5
  50. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/models.ts +0 -1
  51. package/src/api/useGraphQuery/index.ts +7 -4
  52. package/src/components/Layout/PageLayout/PageLayout.tsx +3 -9
  53. package/src/components/Layout/PageLayout/PageLayoutActions.tsx +3 -5
  54. package/src/components/Layout/PageLayout/PageLayoutBody.tsx +3 -5
  55. package/src/components/Layout/PageLayout/PageLayoutHeader.tsx +3 -5
  56. package/src/components/Layout/PageLayout/PageQuickAccess.tsx +44 -25
  57. package/src/components/Layout/PageLayout/translatedLabels.ts +1 -0
  58. package/src/components/Menu/Button/MenuButton.styles.ts +27 -0
  59. package/src/components/Menu/Button/MenuButton.tsx +5 -6
  60. package/src/components/Menu/Menu.styles.ts +68 -0
  61. package/src/components/Menu/MenuDivider.tsx +5 -1
  62. package/src/components/Menu/MenuItem.tsx +5 -1
  63. package/src/components/Menu/MenuItems.tsx +4 -5
  64. package/src/components/Modal/Modal.styles.ts +2 -1
  65. package/src/components/Modal/ModalHeader.tsx +1 -5
  66. package/src/utils/useInfiniteScrollListing.ts +11 -7
  67. package/src/utils/useViewportIntersection.ts +3 -4
  68. package/src/Graph/mockedData/dataWithMissingPoint.json +0 -74
  69. package/src/Graph/mockedData/pingServiceWithStackedKeys.json +0 -205
@@ -2,31 +2,37 @@ import { useTranslation } from 'react-i18next';
2
2
 
3
3
  import AddIcon from '@mui/icons-material/Add';
4
4
  import ArrowBackIcon from '@mui/icons-material/ArrowBack';
5
+ import { CircularProgress } from '@mui/material';
5
6
 
6
7
  import { Button, Menu } from '../..';
7
8
 
9
+ import { labelLoading } from './translatedLabels';
10
+
8
11
  interface NamedEntity {
9
12
  id: number | string;
10
13
  name: string;
11
14
  }
12
15
 
13
16
  type Props = {
14
- create?: () => void;
17
+ create: () => void;
15
18
  elements: Array<NamedEntity>;
16
19
  goBack: () => void;
17
20
  isActive: (id: number | string) => boolean;
18
- isDisabled?: (id: number | string) => boolean;
21
+ isLoading?: boolean;
19
22
  labels: {
20
23
  create: string;
21
24
  goBack: string;
22
25
  };
26
+ // Observed at the bottom of the list to load the next page when it is reached
27
+ loadMoreRef?: (node: Element | null) => void;
23
28
  navigateToElement: (id: number | string) => () => void;
24
29
  };
25
30
 
26
31
  export const PageQuickAccess = ({
27
32
  elements,
28
33
  isActive,
29
- isDisabled,
34
+ isLoading,
35
+ loadMoreRef,
30
36
  navigateToElement,
31
37
  goBack,
32
38
  create,
@@ -38,27 +44,40 @@ export const PageQuickAccess = ({
38
44
  <Menu>
39
45
  <Menu.Button data-testid="quickaccess" />
40
46
  <Menu.Items>
41
- {elements?.map((element) => (
42
- <Menu.Item
43
- key={`${element.id}`}
44
- onClick={navigateToElement(element.id)}
45
- isActive={isActive(element.id)}
46
- isDisabled={isDisabled?.(element.id)}
47
- >
48
- {element.name}
49
- </Menu.Item>
50
- ))}
47
+ <div
48
+ className="max-h-[50vh] overflow-y-auto"
49
+ data-testid="quickaccess-elements"
50
+ >
51
+ {elements?.map((element) => (
52
+ <Menu.Item
53
+ key={`${element.id}`}
54
+ onClick={navigateToElement(element.id)}
55
+ {...(isActive(element.id) && {
56
+ isActive: true,
57
+ isDisabled: true
58
+ })}
59
+ >
60
+ {element.name}
61
+ </Menu.Item>
62
+ ))}
63
+ {loadMoreRef && <div className="h-px" ref={loadMoreRef} />}
64
+ {isLoading && (
65
+ <div className="flex justify-center py-2">
66
+ <CircularProgress aria-label={t(labelLoading)} size={20} />
67
+ </div>
68
+ )}
69
+ </div>
51
70
  <Menu.Divider key="divider" />
52
- <div className="px-2 pb-2 flex gap-4">
53
- <Button
54
- icon={<ArrowBackIcon />}
55
- iconVariant="start"
56
- variant="ghost"
57
- onClick={goBack}
58
- >
59
- {t(labels.goBack)}
60
- </Button>
61
- {create && (
71
+ <Menu.Item key="create">
72
+ <>
73
+ <Button
74
+ icon={<ArrowBackIcon />}
75
+ iconVariant="start"
76
+ variant="ghost"
77
+ onClick={goBack}
78
+ >
79
+ {t(labels.goBack)}
80
+ </Button>
62
81
  <Button
63
82
  icon={<AddIcon />}
64
83
  iconVariant="start"
@@ -67,8 +86,8 @@ export const PageQuickAccess = ({
67
86
  >
68
87
  {t(labels.create)}
69
88
  </Button>
70
- )}
71
- </div>
89
+ </>
90
+ </Menu.Item>
72
91
  </Menu.Items>
73
92
  </Menu>
74
93
  );
@@ -0,0 +1 @@
1
+ export const labelLoading = 'Loading...';
@@ -0,0 +1,27 @@
1
+ import { makeStyles } from 'tss-react/mui';
2
+
3
+ export const useStyles = makeStyles()((theme) => ({
4
+ buttonIcon: {
5
+ '[data-is-active="true"] &': {
6
+ transform: 'rotate(180deg)'
7
+ },
8
+
9
+ fontSize: '1.25rem',
10
+ transition: 'transform 0.15s ease-in-out'
11
+ },
12
+ menuButton: {
13
+ '&:hover:not(&[data-is-active="true"])': {
14
+ backgroundColor: theme.palette.menu.button.background.hover,
15
+ color: theme.palette.menu.button.color.hover
16
+ },
17
+ '&[data-is-active="true"]': {
18
+ backgroundColor: theme.palette.menu.button.background.active,
19
+ color: theme.palette.menu.button.color.active
20
+ },
21
+ backgroundColor: theme.palette.menu.button.background.default,
22
+ color: theme.palette.menu.button.color.default,
23
+ display: 'flex',
24
+ height: 'unset',
25
+ minWidth: 'unset'
26
+ }
27
+ }));
@@ -5,6 +5,7 @@ import {
5
5
  Menu as MenuIcon
6
6
  } from '@mui/icons-material';
7
7
 
8
+ import { useStyles } from './MenuButton.styles';
8
9
  import { AriaLabelingAttributes } from '../../../@types/aria-attributes';
9
10
  import { DataTestAttributes } from '../../../@types/data-attributes';
10
11
  import { Button, ButtonProps } from '../../Button';
@@ -31,6 +32,8 @@ const MenuButton = ({
31
32
  className,
32
33
  ...attr
33
34
  }: MenuButtonProps): ReactElement => {
35
+ const { cx, classes } = useStyles();
36
+
34
37
  const { isMenuOpen, setIsMenuOpen, setAnchorEl, onOpen } = useMenu();
35
38
 
36
39
  const onToggle = useCallback(
@@ -48,18 +51,14 @@ const MenuButton = ({
48
51
  <Button
49
52
  {...attr}
50
53
  aria-label={ariaLabel}
51
- className={`${isMenuOpen ? 'bg-primary-main/8 text-text-primary-main' : 'text-text-secondary'} ${className}`}
54
+ className={cx(classes.menuButton, className)}
52
55
  data-is-active={isMenuOpen}
53
56
  size={size}
54
57
  variant={variant}
55
58
  onClick={onToggle}
56
59
  >
57
60
  {children || <MenuIcon />}
58
- {hasArrow && (
59
- <ArrowDropDownIcon
60
- className={`transform-gpu transition-[rotate] ${isMenuOpen ? 'rotate-180' : 'rotate-0'}`}
61
- />
62
- )}
61
+ {hasArrow && <ArrowDropDownIcon className={classes.buttonIcon} />}
63
62
  </Button>
64
63
  );
65
64
  };
@@ -0,0 +1,68 @@
1
+ import { makeStyles } from 'tss-react/mui';
2
+
3
+ export const useStyles = makeStyles()((theme) => ({
4
+ menuDivider: {
5
+ '&, &.MuiDivider-root': {
6
+ borderColor: theme.palette.menu.divider.border
7
+ }
8
+ },
9
+ menuItem: {
10
+ '&, &.MuiMenuItem-root': {
11
+ '& > button': {
12
+ fontSize: '1rem',
13
+ justifyContent: 'flex-start'
14
+ },
15
+
16
+ '&:has(button)': {
17
+ '& > .MuiTouchRipple-root': {
18
+ display: 'none'
19
+ },
20
+ '&:hover:not(&[data-is-active="true"])': {
21
+ backgroundColor: 'unset'
22
+ },
23
+ padding: theme.spacing(0, 2)
24
+ },
25
+
26
+ '&:not(:has(button))': {
27
+ '&:hover:not(&[data-is-active="true"])': {
28
+ backgroundColor: theme.palette.menu.item.background.hover,
29
+ color: theme.palette.menu.item.color.hover
30
+ },
31
+ '&[data-is-active="true"], &.Mui-selected': {
32
+ '&[data-is-disabled="true"], &.Mui-disabled': {
33
+ opacity: 1
34
+ },
35
+ backgroundColor: theme.palette.menu.item.background.active,
36
+ color: theme.palette.menu.item.color.active,
37
+ opacity: 1
38
+ },
39
+ '&[data-is-disabled="true"], &.Mui-disabled': {
40
+ opacity: 0.5
41
+ },
42
+ backgroundColor: theme.palette.menu.item.background.default,
43
+ color: theme.palette.menu.item.color.default,
44
+ padding: theme.spacing(0.75, 2)
45
+ },
46
+
47
+ alignItems: 'center',
48
+ display: 'flex',
49
+ flexDirection: 'row',
50
+ fontSize: '1rem',
51
+ gap: theme.spacing(2),
52
+ justifyContent: 'space-between',
53
+ minHeight: 'unset'
54
+ }
55
+ },
56
+ menuItems: {
57
+ '& > .MuiPaper-root.MuiMenu-paper': {
58
+ backgroundColor: theme.palette.menu.background,
59
+ borderRadius: '4px',
60
+ boxShadow: theme.shadows[8],
61
+ minWidth: '240px',
62
+ transform: `translateY(${theme.spacing(0.5)}) !important`
63
+ },
64
+ '& ul, & ul.MuiMenu-list': {
65
+ padding: theme.spacing(1, 0)
66
+ }
67
+ }
68
+ }));
@@ -2,8 +2,12 @@ import { ReactElement } from 'react';
2
2
 
3
3
  import { Divider as MuiDivider } from '@mui/material';
4
4
 
5
+ import { useStyles } from './Menu.styles';
6
+
5
7
  const MenuDivider = (): ReactElement => {
6
- return <MuiDivider />;
8
+ const { classes } = useStyles();
9
+
10
+ return <MuiDivider className={classes.menuDivider} />;
7
11
  };
8
12
 
9
13
  export { MenuDivider };
@@ -2,6 +2,8 @@ import { ReactElement, ReactNode } from 'react';
2
2
 
3
3
  import { MenuItem as MuiMenuItem } from '@mui/material';
4
4
 
5
+ import { useStyles } from './Menu.styles';
6
+
5
7
  type MenuItemProps = {
6
8
  children?: ReactNode;
7
9
  className?: string;
@@ -17,9 +19,11 @@ const MenuItem = ({
17
19
  isDisabled = false,
18
20
  className
19
21
  }: MenuItemProps): ReactElement => {
22
+ const { cx, classes } = useStyles();
23
+
20
24
  return (
21
25
  <MuiMenuItem
22
- className={className}
26
+ className={cx(classes.menuItem, className)}
23
27
  data-is-active={isActive}
24
28
  data-is-disabled={isDisabled}
25
29
  disabled={isDisabled}
@@ -2,6 +2,7 @@ import { ReactElement, ReactNode } from 'react';
2
2
 
3
3
  import { Menu as MuiMenu } from '@mui/material';
4
4
 
5
+ import { useStyles } from './Menu.styles';
5
6
  import { useMenu } from './useMenu';
6
7
 
7
8
  type MenuItemsProps = {
@@ -9,6 +10,8 @@ type MenuItemsProps = {
9
10
  className?: string;
10
11
  };
11
12
  const MenuItems = ({ children, className }: MenuItemsProps): ReactElement => {
13
+ const { cx, classes } = useStyles();
14
+
12
15
  const { isMenuOpen, setIsMenuOpen, anchorEl, onClose } = useMenu();
13
16
 
14
17
  const onCloseMenu = (): void => {
@@ -19,11 +22,7 @@ const MenuItems = ({ children, className }: MenuItemsProps): ReactElement => {
19
22
  return (
20
23
  <MuiMenu
21
24
  anchorEl={anchorEl}
22
- className={className}
23
- classes={{
24
- paper:
25
- 'rounded-sm shadow-lg min-w-[240px] bg-background-paper border-1 border-divider'
26
- }}
25
+ className={cx(classes.menuItems, className)}
27
26
  open={isMenuOpen}
28
27
  variant="menu"
29
28
  onClick={onCloseMenu}
@@ -72,7 +72,8 @@ const useStyles = makeStyles<{
72
72
  opacity: 0.6
73
73
  },
74
74
  top: theme.spacing(1)
75
- }
75
+ },
76
+
76
77
  }));
77
78
 
78
79
  export { useStyles };
@@ -16,11 +16,7 @@ const ModalHeader = ({
16
16
  }: ModalHeaderProps & DialogTitleProps): ReactElement => {
17
17
  return (
18
18
  <div className={modalHeader}>
19
- <MuiDialogTitle
20
- className="p-0 font-bold text-2xl"
21
- color="primary"
22
- {...rest}
23
- >
19
+ <MuiDialogTitle className="p-0 font-bold text-2xl" color="primary" {...rest}>
24
20
  {children}
25
21
  </MuiDialogTitle>
26
22
  </div>
@@ -50,6 +50,15 @@ export const useInfiniteScrollListing = <T>({
50
50
 
51
51
  const [page, setPage] = useAtom(pageAtom);
52
52
 
53
+ // Shared by the active query and the next page prefetch, so that the
54
+ // prefetched page is reused instead of being requested again
55
+ const getQueryKey = (queryPage: number): Array<string | number> => [
56
+ queryKeyName,
57
+ queryPage,
58
+ JSON.stringify(parameters),
59
+ JSON.stringify(customQueryParameters)
60
+ ];
61
+
53
62
  const { data, isLoading, prefetchNextPage, fetchStatus } = useFetchQuery<
54
63
  Listing<T>
55
64
  >({
@@ -60,12 +69,7 @@ export const useInfiniteScrollListing = <T>({
60
69
  customQueryParameters,
61
70
  parameters: { limit, page: params?.page || page, ...parameters }
62
71
  }),
63
- getQueryKey: () => [
64
- queryKeyName,
65
- page,
66
- JSON.stringify(parameters),
67
- JSON.stringify(customQueryParameters)
68
- ],
72
+ getQueryKey: () => getQueryKey(page),
69
73
  isPaginated: true,
70
74
  queryOptions: {
71
75
  enabled,
@@ -111,7 +115,7 @@ export const useInfiniteScrollListing = <T>({
111
115
  }
112
116
 
113
117
  prefetchNextPage({
114
- getPrefetchQueryKey: (newPage) => ['dashboards', newPage],
118
+ getPrefetchQueryKey: getQueryKey,
115
119
  page
116
120
  });
117
121
  }, [data]);
@@ -18,10 +18,9 @@ export const useViewportIntersection = (
18
18
  observer.current.disconnect();
19
19
  }
20
20
 
21
- observer.current = new window.IntersectionObserver(
22
- ([newEntry]) => setEntry(newEntry),
23
- options
24
- );
21
+ observer.current = new window.IntersectionObserver(([newEntry]) => {
22
+ setEntry(newEntry);
23
+ }, options);
25
24
 
26
25
  if (element) {
27
26
  observer.current.observe(element);
@@ -1,74 +0,0 @@
1
- {
2
- "global": {},
3
- "metrics": [
4
- {
5
- "metric": "count",
6
- "metric_id": 1,
7
- "legend": "count",
8
- "displayAs": "bar",
9
- "ds_data": {
10
- "ds_stack": true,
11
- "ds_transparency": 0,
12
- "ds_filled": false,
13
- "ds_color_area": "#4269d0",
14
- "ds_color_line": "#4269d0"
15
- },
16
- "datasourceOptions": {
17
- "field": null,
18
- "group_by": null,
19
- "op": "count-doc",
20
- "query": "severity_text:\"Fatal\" OR severity_text:\"Error\"",
21
- "period": 3600
22
- },
23
- "data": [
24
- 217, 270, 293, 300, 303, 295, 298, 283, 299, 299, 297, 285, 270, 248,
25
- 274, 292, 284, 47
26
- ]
27
- },
28
- {
29
- "metric": "count",
30
- "metric_id": 2,
31
- "legend": "count",
32
- "displayAs": "bar",
33
- "ds_data": {
34
- "ds_stack": true,
35
- "ds_transparency": 0,
36
- "ds_filled": false,
37
- "ds_color_area": "#efb118",
38
- "ds_color_line": "#efb118"
39
- },
40
- "datasourceOptions": {
41
- "field": null,
42
- "group_by": null,
43
- "op": "count-doc",
44
- "query": "",
45
- "period": 3600
46
- },
47
- "data": [
48
- 32, 825, 939, 922, 918, 939, 943, 947, 946, 909, 931, 939, 883, 907,
49
- 928, 904, 923, 893, 139
50
- ]
51
- }
52
- ],
53
- "times": [
54
- "2025-10-04T16:19:30.000Z",
55
- "2025-10-04T16:20:00.000Z",
56
- "2025-10-04T16:20:30.000Z",
57
- "2025-10-04T16:21:00.000Z",
58
- "2025-10-04T16:21:30.000Z",
59
- "2025-10-04T16:22:00.000Z",
60
- "2025-10-04T16:22:30.000Z",
61
- "2025-10-04T16:23:00.000Z",
62
- "2025-10-04T16:23:30.000Z",
63
- "2025-10-04T16:24:00.000Z",
64
- "2025-10-04T16:24:30.000Z",
65
- "2025-10-04T16:25:00.000Z",
66
- "2025-10-04T16:25:30.000Z",
67
- "2025-10-04T16:26:00.000Z",
68
- "2025-10-04T16:26:30.000Z",
69
- "2025-10-04T16:27:00.000Z",
70
- "2025-10-04T16:27:30.000Z",
71
- "2025-10-04T16:28:00.000Z",
72
- "2025-10-04T16:28:30.000Z"
73
- ]
74
- }
@@ -1,205 +0,0 @@
1
- {
2
- "global": {
3
- "base": 1000,
4
- "title": "Ping service"
5
- },
6
- "metrics": [
7
- {
8
- "metric_id": 2,
9
- "metric": "Centreon-Server: pl",
10
- "metric_legend": "Centreon-Server: pl",
11
- "unit": "%",
12
- "min": 0.0,
13
- "max": 100.0,
14
- "ds_data": {
15
- "ds_color_line": "#F30B23",
16
- "ds_color_area": "#F30B23",
17
- "ds_filled": true,
18
- "ds_invert": false,
19
- "ds_legend": null,
20
- "ds_stack": false,
21
- "ds_order": 1,
22
- "ds_transparency": 80.0,
23
- "ds_color_line_mode": 0
24
- },
25
- "legend": "Centreon-Server: Packet Loss",
26
- "stack": 0,
27
- "warning_high_threshold": 20.0,
28
- "critical_high_threshold": 50.0,
29
- "warning_low_threshold": 0.0,
30
- "critical_low_threshold": 0.0,
31
- "ds_order": 1,
32
- "data": [
33
- 0.0,
34
- 0.0,
35
- 0.0,
36
- 0.0,
37
- 0.0,
38
- 0.0,
39
- 0.0,
40
- 0.0,
41
- 0.0,
42
- 10.0,
43
- 20.0,
44
- null,
45
- null
46
- ],
47
- "last_value": 0.0,
48
- "minimum_value": null,
49
- "maximum_value": 0.0,
50
- "average_value": 0.0
51
- },
52
- {
53
- "metric_id": 1,
54
- "metric": "Centreon-Server: rta",
55
- "metric_legend": "Centreon-Server: rta",
56
- "unit": "ms",
57
- "min": 0.0,
58
- "max": null,
59
- "ds_data": {
60
- "ds_color_line": "#29AFEE",
61
- "ds_color_area": "#29AFEE",
62
- "ds_filled": true,
63
- "ds_invert": false,
64
- "ds_legend": null,
65
- "ds_stack": true,
66
- "ds_order": 1,
67
- "ds_transparency": 80.0,
68
- "ds_color_line_mode": 0
69
- },
70
- "legend": "Centreon-Server: Round-Trip Average Time",
71
- "stack": 0,
72
- "warning_high_threshold": 200.0,
73
- "critical_high_threshold": 400.0,
74
- "warning_low_threshold": 0.0,
75
- "critical_low_threshold": 0.0,
76
- "ds_order": 1,
77
- "data": [
78
- 0.04508,
79
- 0.0242,
80
- 0.03592,
81
- 0.01304,
82
- 0.025,
83
- 0.02748,
84
- 0.05296,
85
- 0.01864,
86
- 0.02688,
87
- 0.03676,
88
- 0.03696,
89
- null,
90
- null
91
- ],
92
- "last_value": 0.04,
93
- "minimum_value": null,
94
- "maximum_value": null,
95
- "average_value": 0.03
96
- },
97
- {
98
- "metric_id": 3,
99
- "metric": "Centreon-Server: rtmax",
100
- "metric_legend": "Centreon-Server: rtmax",
101
- "unit": "ms",
102
- "min": null,
103
- "max": null,
104
- "ds_data": {
105
- "ds_color_line": "#525256",
106
- "ds_color_area": "#525256",
107
- "ds_filled": false,
108
- "ds_invert": false,
109
- "ds_legend": null,
110
- "ds_stack": true,
111
- "ds_stack_key": "test",
112
- "ds_order": 2,
113
- "ds_transparency": 80.0,
114
- "ds_color_line_mode": 0
115
- },
116
- "legend": "Centreon-Server: Round-Trip Maximum Time",
117
- "stack": 0,
118
- "warning_high_threshold": null,
119
- "critical_high_threshold": null,
120
- "warning_low_threshold": null,
121
- "critical_low_threshold": null,
122
- "ds_order": 2,
123
- "data": [
124
- 0.11372,
125
- 0.05604,
126
- 0.08556,
127
- 0.02548,
128
- 0.05352,
129
- 0.05336,
130
- 0.109,
131
- 0.04112,
132
- 0.05504,
133
- 0.06812,
134
- 0.08644,
135
- null,
136
- null
137
- ],
138
- "last_value": 0.09,
139
- "minimum_value": null,
140
- "maximum_value": 0.11,
141
- "average_value": null
142
- },
143
- {
144
- "metric_id": 4,
145
- "metric": "Centreon-Server: rtmin",
146
- "metric_legend": "Centreon-Server: rtmin",
147
- "unit": "ms",
148
- "min": null,
149
- "max": null,
150
- "ds_data": {
151
- "ds_color_line": "#191777",
152
- "ds_color_area": "#191777",
153
- "ds_filled": false,
154
- "ds_invert": false,
155
- "ds_legend": null,
156
- "ds_stack": true,
157
- "ds_stack_key": "test",
158
- "ds_order": 2,
159
- "ds_transparency": 80.0,
160
- "ds_color_line_mode": 0
161
- },
162
- "legend": "Centreon-Server: Round-Trip Minimum Time",
163
- "stack": 0,
164
- "warning_high_threshold": null,
165
- "critical_high_threshold": null,
166
- "warning_low_threshold": null,
167
- "critical_low_threshold": null,
168
- "ds_order": 2,
169
- "data": [
170
- 0.00984,
171
- 0.008,
172
- 0.00784,
173
- 0.00624,
174
- 0.00932,
175
- 0.01348,
176
- 0.01796,
177
- 0.0064,
178
- 0.01148,
179
- 0.01644,
180
- 0.01168,
181
- null,
182
- null
183
- ],
184
- "last_value": 0.01,
185
- "minimum_value": 0.01,
186
- "maximum_value": null,
187
- "average_value": null
188
- }
189
- ],
190
- "times": [
191
- "2024-06-19T10:50:00+02:00",
192
- "2024-06-19T10:55:00+02:00",
193
- "2024-06-19T11:00:00+02:00",
194
- "2024-06-19T11:05:00+02:00",
195
- "2024-06-19T11:10:00+02:00",
196
- "2024-06-19T11:15:00+02:00",
197
- "2024-06-19T11:20:00+02:00",
198
- "2024-06-19T11:25:00+02:00",
199
- "2024-06-19T11:30:00+02:00",
200
- "2024-06-19T11:35:00+02:00",
201
- "2024-06-19T11:40:00+02:00",
202
- "2024-06-19T11:45:00+02:00",
203
- "2024-06-19T11:50:00+02:00"
204
- ]
205
- }