@centreon/ui 24.10.12 → 24.10.13

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 (153) hide show
  1. package/package.json +3 -2
  2. package/public/mockServiceWorker.js +1 -1
  3. package/src/Button/Icon/index.tsx +3 -1
  4. package/src/Dashboard/Dashboard.styles.ts +3 -4
  5. package/src/Dashboard/DashboardLayout.stories.tsx +1 -1
  6. package/src/Dashboard/Grid.tsx +11 -17
  7. package/src/Dashboard/Layout.tsx +27 -56
  8. package/src/Dialog/UnsavedChanges/index.tsx +15 -13
  9. package/src/Dialog/UnsavedChanges/translatedLabels.ts +15 -13
  10. package/src/Form/Form.tsx +0 -1
  11. package/src/Form/Inputs/Autocomplete.tsx +1 -1
  12. package/src/Form/Inputs/ConnectedAutocomplete.tsx +5 -2
  13. package/src/Form/Inputs/Grid.tsx +7 -1
  14. package/src/Form/Inputs/Radio.tsx +1 -1
  15. package/src/Form/Inputs/Switch.tsx +1 -1
  16. package/src/Form/Inputs/Text.tsx +1 -1
  17. package/src/Form/Inputs/index.tsx +25 -24
  18. package/src/Form/Inputs/models.ts +2 -0
  19. package/src/Graph/BarChart/BarChart.cypress.spec.tsx +3 -3
  20. package/src/Graph/BarChart/BarChart.tsx +24 -31
  21. package/src/Graph/BarChart/BarGroup.tsx +32 -59
  22. package/src/Graph/BarChart/BarStack.tsx +64 -13
  23. package/src/Graph/BarChart/MemoizedGroup.tsx +123 -0
  24. package/src/Graph/BarChart/ResponsiveBarChart.tsx +21 -7
  25. package/src/Graph/BarStack/BarStack.cypress.spec.tsx +87 -9
  26. package/src/Graph/BarStack/BarStack.stories.tsx +13 -4
  27. package/src/Graph/BarStack/BarStack.styles.ts +57 -33
  28. package/src/Graph/BarStack/Graph.tsx +173 -0
  29. package/src/Graph/BarStack/GraphAndLegend.tsx +117 -0
  30. package/src/Graph/BarStack/ResponsiveBarStack.tsx +61 -168
  31. package/src/Graph/BarStack/constants.ts +5 -0
  32. package/src/Graph/BarStack/models.ts +0 -1
  33. package/src/Graph/BarStack/useGraphAndLegend.ts +84 -0
  34. package/src/Graph/BarStack/useResponsiveBarStack.ts +73 -97
  35. package/src/Graph/Chart/Chart.cypress.spec.tsx +14 -26
  36. package/src/Graph/Chart/Chart.stories.tsx +1 -1
  37. package/src/Graph/Chart/Chart.tsx +53 -37
  38. package/src/Graph/Chart/InteractiveComponents/AnchorPoint/GuidingLines.tsx +3 -3
  39. package/src/Graph/Chart/InteractiveComponents/AnchorPoint/useTickGraph.ts +19 -6
  40. package/src/Graph/Chart/Legend/Legend.styles.ts +25 -11
  41. package/src/Graph/Chart/Legend/index.tsx +6 -24
  42. package/src/Graph/Chart/index.tsx +34 -43
  43. package/src/Graph/Chart/models.ts +0 -1
  44. package/src/Graph/Chart/useChartData.ts +19 -1
  45. package/src/Graph/HeatMap/ResponsiveHeatMap.tsx +20 -2
  46. package/src/Graph/HeatMap/model.ts +6 -2
  47. package/src/Graph/Legend/Legend.styles.ts +10 -0
  48. package/src/Graph/Legend/Legend.tsx +6 -1
  49. package/src/Graph/SingleBar/ResponsiveSingleBar.tsx +9 -10
  50. package/src/Graph/SingleBar/ThresholdLine.tsx +6 -6
  51. package/src/Graph/Text/Text.styles.ts +2 -2
  52. package/src/Graph/Text/Text.tsx +23 -10
  53. package/src/Graph/Timeline/ResponsiveTimeline.tsx +152 -0
  54. package/src/Graph/Timeline/Timeline.cypress.spec.tsx +148 -0
  55. package/src/Graph/Timeline/Timeline.stories.tsx +91 -0
  56. package/src/Graph/Timeline/Timeline.tsx +28 -0
  57. package/src/Graph/Timeline/index.ts +1 -0
  58. package/src/Graph/Timeline/models.ts +20 -0
  59. package/src/Graph/Timeline/timeline.styles.ts +11 -0
  60. package/src/Graph/Timeline/translatedLabel.ts +6 -0
  61. package/src/Graph/Timeline/useTimeline.ts +90 -0
  62. package/src/Graph/Tree/Links.tsx +2 -2
  63. package/src/Graph/Tree/Tree.tsx +2 -2
  64. package/src/Graph/Tree/constants.ts +1 -1
  65. package/src/Graph/common/Axes/index.tsx +1 -1
  66. package/src/Graph/common/Axes/useAxisY.ts +8 -4
  67. package/src/Graph/common/BaseChart/BaseChart.tsx +3 -12
  68. package/src/Graph/common/BaseChart/ChartSvgWrapper.tsx +12 -4
  69. package/src/Graph/common/BaseChart/Header/index.tsx +3 -1
  70. package/src/Graph/common/BaseChart/useComputeBaseChartDimensions.ts +23 -11
  71. package/src/Graph/common/BaseChart/useComputeYAxisMaxCharacters.ts +92 -0
  72. package/src/Graph/common/models.ts +7 -8
  73. package/src/Graph/common/timeSeries/index.test.ts +1 -1
  74. package/src/Graph/common/timeSeries/index.ts +56 -29
  75. package/src/Graph/common/timeSeries/models.ts +2 -0
  76. package/src/Graph/common/utils.ts +51 -3
  77. package/src/Graph/index.ts +4 -1
  78. package/src/Graph/mockedData/lastDayWithNullValues.json +6 -6
  79. package/src/Graph/mockedData/pingServiceLinesBars.json +47 -47
  80. package/src/Icon/DowntimeIcon.tsx +8 -1
  81. package/src/Icon/FlappingIcon.tsx +22 -0
  82. package/src/Icon/index.ts +1 -0
  83. package/src/InputField/Select/Autocomplete/Connected/Multi/index.test.tsx +21 -1
  84. package/src/InputField/Select/Autocomplete/Connected/index.test.tsx +2 -2
  85. package/src/InputField/Select/Autocomplete/Connected/index.tsx +52 -15
  86. package/src/InputField/Select/Autocomplete/Multi/index.stories.tsx +19 -0
  87. package/src/InputField/Select/Autocomplete/Multi/index.tsx +8 -5
  88. package/src/InputField/Select/Autocomplete/index.tsx +79 -54
  89. package/src/InputField/Text/index.tsx +6 -4
  90. package/src/InputField/translatedLabels.ts +2 -0
  91. package/src/Listing/ActionBar/index.tsx +1 -1
  92. package/src/Listing/Listing.styles.ts +3 -3
  93. package/src/Listing/index.tsx +40 -37
  94. package/src/Listing/models.ts +0 -8
  95. package/src/Listing/useStyleTable.ts +58 -32
  96. package/src/MultiSelectEntries/index.tsx +2 -0
  97. package/src/PopoverMenu/index.tsx +2 -9
  98. package/src/SortableItems/index.tsx +0 -1
  99. package/src/ThemeProvider/index.tsx +1 -1
  100. package/src/ThemeProvider/palettes.ts +6 -0
  101. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/PickersStartEndDate.tsx +2 -3
  102. package/src/TimePeriods/DateTimePickerInput.tsx +3 -1
  103. package/src/api/buildListingEndpoint/getSearchQueryParameterValue.ts +7 -1
  104. package/src/api/buildListingEndpoint/models.ts +1 -0
  105. package/src/api/customFetch.ts +4 -1
  106. package/src/api/models.ts +9 -0
  107. package/src/api/useGraphQuery/index.ts +117 -20
  108. package/src/api/useGraphQuery/models.ts +1 -0
  109. package/src/api/useMutationQuery/index.ts +1 -1
  110. package/src/components/DataTable/DataTable.styles.ts +1 -1
  111. package/src/components/DataTable/EmptyState/DataTableEmptyState.styles.ts +2 -1
  112. package/src/components/DataTable/EmptyState/DataTableEmptyState.tsx +4 -1
  113. package/src/components/DataTable/Item/DataTableItem.styles.ts +28 -2
  114. package/src/components/DataTable/Item/DataTableItem.tsx +19 -4
  115. package/src/components/Form/FormActions.tsx +21 -12
  116. package/src/components/Layout/AreaIndicator.tsx +1 -1
  117. package/src/components/Layout/PageLayout/PageLayout.styles.ts +2 -7
  118. package/src/components/Layout/PageLayout/PageLayoutBody.tsx +0 -1
  119. package/src/components/Zoom/Zoom.tsx +9 -2
  120. package/src/components/Zoom/ZoomContent.tsx +143 -136
  121. package/src/components/Zoom/models.ts +18 -15
  122. package/src/components/Zoom/useMinimap.ts +5 -8
  123. package/src/components/Zoom/useZoom.ts +3 -3
  124. package/src/index.ts +2 -0
  125. package/src/utils/index.ts +1 -0
  126. package/src/utils/useLocale/index.ts +9 -0
  127. package/src/utils/useLocale/useLocale.cypress.spec.tsx +38 -0
  128. package/src/utils/useLocaleDateTimeFormat/index.ts +4 -2
  129. package/src/utils/usePluralizedTranslation.ts +2 -3
  130. package/src/Graph/common/timeSeries/index.test.ts-E +0 -622
  131. package/src/components/CrudPage/Actions/Actions.styles.ts +0 -16
  132. package/src/components/CrudPage/Actions/Actions.tsx +0 -24
  133. package/src/components/CrudPage/Actions/AddButton.tsx +0 -23
  134. package/src/components/CrudPage/Actions/Filters.tsx +0 -25
  135. package/src/components/CrudPage/Actions/Search.tsx +0 -31
  136. package/src/components/CrudPage/Actions/useSearch.tsx +0 -24
  137. package/src/components/CrudPage/Columns/Actions.tsx +0 -88
  138. package/src/components/CrudPage/CrudPage.cypress.spec.tsx +0 -559
  139. package/src/components/CrudPage/CrudPage.stories.tsx +0 -278
  140. package/src/components/CrudPage/CrudPageRoot.tsx +0 -142
  141. package/src/components/CrudPage/DeleteModal.tsx +0 -77
  142. package/src/components/CrudPage/Form/AddModal.tsx +0 -35
  143. package/src/components/CrudPage/Form/Buttons.tsx +0 -98
  144. package/src/components/CrudPage/Form/UpdateModal.tsx +0 -60
  145. package/src/components/CrudPage/Listing.tsx +0 -63
  146. package/src/components/CrudPage/atoms.ts +0 -30
  147. package/src/components/CrudPage/hooks/useDeleteItem.ts +0 -53
  148. package/src/components/CrudPage/hooks/useGetItem.ts +0 -36
  149. package/src/components/CrudPage/hooks/useGetItems.ts +0 -67
  150. package/src/components/CrudPage/hooks/useListingQueryKey.ts +0 -31
  151. package/src/components/CrudPage/index.tsx +0 -7
  152. package/src/components/CrudPage/models.ts +0 -118
  153. package/src/components/CrudPage/utils.ts +0 -4
@@ -16,6 +16,7 @@ export interface DataTableItemProps {
16
16
  hasActions?: boolean;
17
17
  hasCardAction?: boolean;
18
18
  onClick?: () => void;
19
+ thumbnail?: string | null;
19
20
  title: string;
20
21
  }
21
22
 
@@ -27,7 +28,8 @@ const DataTableItem = forwardRef(
27
28
  hasCardAction = false,
28
29
  hasActions = false,
29
30
  onClick,
30
- Actions
31
+ Actions,
32
+ thumbnail
31
33
  }: DataTableItemProps,
32
34
  ref
33
35
  ): ReactElement => {
@@ -46,15 +48,28 @@ const DataTableItem = forwardRef(
46
48
  variant="outlined"
47
49
  >
48
50
  <ActionArea aria-label="view" onClick={() => onClick?.()}>
49
- <MuiCardContent>
51
+ {thumbnail && (
52
+ <img
53
+ alt={`thumbnail-${title}-${description}`}
54
+ className={classes.thumbnail}
55
+ data-testId={`thumbnail-${title}-${description}`}
56
+ loading="lazy"
57
+ src={thumbnail}
58
+ />
59
+ )}
60
+ <MuiCardContent className={classes.cardContent}>
50
61
  <MuiTypography fontWeight={500} variant="h5">
51
62
  {title}
52
63
  </MuiTypography>
53
- {description && <MuiTypography>{description}</MuiTypography>}
64
+ {description && (
65
+ <MuiTypography className={classes.description}>
66
+ {description}
67
+ </MuiTypography>
68
+ )}
54
69
  </MuiCardContent>
55
70
  </ActionArea>
56
71
  {hasActions && (
57
- <MuiCardActions>
72
+ <MuiCardActions className={classes.cardActions}>
58
73
  <span />
59
74
  <span>{Actions}</span>
60
75
  </MuiCardActions>
@@ -12,6 +12,8 @@ export type FormActionsProps = {
12
12
  labels: FormActionsLabels;
13
13
  onCancel: () => void;
14
14
  variant: FormVariant;
15
+ isCancelButtonVisible?: boolean;
16
+ disableSubmit?: boolean;
15
17
  };
16
18
 
17
19
  export type FormActionsLabels = {
@@ -23,27 +25,34 @@ const FormActions = <TResource extends object>({
23
25
  labels,
24
26
  onCancel,
25
27
  variant,
26
- enableSubmitWhenNotDirty
28
+ enableSubmitWhenNotDirty,
29
+ isCancelButtonVisible = true,
30
+ disableSubmit = false
27
31
  }: FormActionsProps): ReactElement => {
28
32
  const { classes } = useStyles();
29
33
  const { isSubmitting, dirty, isValid, submitForm } =
30
34
  useFormikContext<TResource>();
31
35
 
32
36
  const isSubmitDisabled =
33
- isSubmitting || (!dirty && !enableSubmitWhenNotDirty) || !isValid;
37
+ disableSubmit ||
38
+ isSubmitting ||
39
+ (!dirty && !enableSubmitWhenNotDirty) ||
40
+ !isValid;
34
41
 
35
42
  return (
36
43
  <div className={classes.actions}>
37
- <Button
38
- aria-label={labels.cancel}
39
- data-testid="cancel"
40
- disabled={isSubmitting}
41
- size="medium"
42
- variant="secondary"
43
- onClick={() => onCancel?.()}
44
- >
45
- {labels.cancel}
46
- </Button>
44
+ {isCancelButtonVisible && (
45
+ <Button
46
+ aria-label={labels.cancel}
47
+ data-testid="cancel"
48
+ disabled={isSubmitting}
49
+ size="medium"
50
+ variant="secondary"
51
+ onClick={() => onCancel?.()}
52
+ >
53
+ {labels.cancel}
54
+ </Button>
55
+ )}
47
56
  <Button
48
57
  aria-label={labels.submit[variant]}
49
58
  data-testid="submit"
@@ -25,7 +25,7 @@ const AreaIndicator = ({
25
25
  data-depth={depth}
26
26
  style={{ height, width }}
27
27
  >
28
- {/* biome-ignore lint/a11y: */}
28
+ {/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
29
29
  <label>{name}</label>
30
30
  {children}
31
31
  </div>
@@ -2,10 +2,8 @@ import { makeStyles } from 'tss-react/mui';
2
2
 
3
3
  export const useStyles = makeStyles()((theme) => ({
4
4
  pageLayout: {
5
- height: '100%',
6
5
  display: 'grid',
7
- gridTemplateRows: 'auto 1fr',
8
- height: '100%',
6
+ gridTemplateRows: 'min-content',
9
7
  overflow: 'hidden'
10
8
  },
11
9
  pageLayoutActions: {
@@ -24,11 +22,8 @@ export const useStyles = makeStyles()((theme) => ({
24
22
  '&[data-has-background="true"]': {
25
23
  backgroundColor: theme.palette.layout.body.background
26
24
  },
27
- '&[data-has-actions="true"]': {
28
- gridTemplateRows: 'min-content auto',
29
- },
30
25
  display: 'grid',
31
- gridTemplateRows: 'auto',
26
+ gridTemplateRows: 'min-content',
32
27
  overflow: 'hidden',
33
28
  padding: theme.spacing(1.5, 3, 5)
34
29
  },
@@ -17,7 +17,6 @@ export const PageLayoutBody = ({
17
17
  <section
18
18
  className={classes.pageLayoutBody}
19
19
  data-has-background={hasBackground}
20
- data-has-actions={!!children?.length}
21
20
  id="page-body"
22
21
  >
23
22
  {children}
@@ -1,4 +1,6 @@
1
1
  import { Zoom as VisxZoom } from '@visx/zoom';
2
+ import { TransformMatrix } from '@visx/zoom/lib/types';
3
+ import { type MutableRefObject } from 'react';
2
4
 
3
5
  import { ParentSize } from '../..';
4
6
 
@@ -12,6 +14,8 @@ export interface ZoomProps {
12
14
  scaleMax?: number;
13
15
  scaleMin?: number;
14
16
  showMinimap?: boolean;
17
+ contentRef?: MutableRefObject<SVGGElement | null>;
18
+ transformMatrix?: TransformMatrix;
15
19
  }
16
20
 
17
21
  const initialTransform = {
@@ -29,14 +33,16 @@ const Zoom = ({
29
33
  scaleMax = 4,
30
34
  showMinimap = false,
31
35
  minimapPosition = 'top-left',
32
- id = 0
36
+ id = 0,
37
+ contentRef,
38
+ transformMatrix = initialTransform
33
39
  }: ZoomProps): JSX.Element => {
34
40
  return (
35
41
  <ParentSize>
36
42
  {({ width, height }) => (
37
43
  <VisxZoom<SVGSVGElement>
38
44
  height={height}
39
- initialTransformMatrix={initialTransform}
45
+ initialTransformMatrix={transformMatrix}
40
46
  scaleXMax={scaleMax}
41
47
  scaleXMin={scaleMin}
42
48
  scaleYMax={scaleMax}
@@ -51,6 +57,7 @@ const Zoom = ({
51
57
  showMinimap={showMinimap}
52
58
  width={width}
53
59
  zoom={zoom}
60
+ ref={contentRef}
54
61
  >
55
62
  {children}
56
63
  </ZoomContent>
@@ -1,7 +1,13 @@
1
- import { useEffect, useRef, useState } from 'react';
1
+ import {
2
+ type ForwardedRef,
3
+ MutableRefObject,
4
+ forwardRef,
5
+ useEffect,
6
+ useRef,
7
+ useState
8
+ } from 'react';
2
9
 
3
10
  import { RectClipPath } from '@visx/clip-path';
4
- import { ProvidedZoom } from '@visx/zoom/lib/types';
5
11
 
6
12
  import ZoomInIcon from '@mui/icons-material/Add';
7
13
  import ZoomOutIcon from '@mui/icons-material/Remove';
@@ -12,159 +18,160 @@ import { IconButton } from '../Button';
12
18
  import Minimap from './Minimap';
13
19
  import { useZoomStyles } from './Zoom.styles';
14
20
  import { minimapScale, radius } from './constants';
15
- import { ChildrenProps, MinimapPosition, ZoomState } from './models';
21
+ import {
22
+ type Dimension,
23
+ type MinimapPosition,
24
+ ZoomChildren,
25
+ type ZoomInterface
26
+ } from './models';
16
27
  import { useZoom } from './useZoom';
17
28
 
18
- export interface Props {
19
- children: ({ width, height, transformMatrix }: ChildrenProps) => JSX.Element;
20
- height: number;
29
+ export interface Props extends Dimension, ZoomInterface, ZoomChildren {
21
30
  id?: number | string;
22
31
  minimapPosition: MinimapPosition;
23
32
  showMinimap?: boolean;
24
- width: number;
25
- zoom: ProvidedZoom<SVGSVGElement> & ZoomState;
26
33
  }
27
34
 
28
- const ZoomContent = ({
29
- zoom,
30
- width,
31
- height,
32
- children,
33
- showMinimap,
34
- minimapPosition,
35
- id
36
- }: Props): JSX.Element => {
37
- const { classes } = useZoomStyles();
38
- const contentRef = useRef<SVGGElement | null>(null);
39
- const minimapSvgRef = useRef<SVGSVGElement | null>(null);
40
- const minimapContentRef = useRef<SVGSVGElement | null>(null);
41
- const [contentClientRect, setContentClientRect] = useState<{
42
- height: number;
43
- width: number;
44
- } | null>(null);
35
+ const ZoomContent = forwardRef(
36
+ (
37
+ { zoom, width, height, children, showMinimap, minimapPosition, id }: Props,
38
+ ref?: ForwardedRef<SVGGElement | null>
39
+ ): JSX.Element => {
40
+ const { classes } = useZoomStyles();
45
41
 
46
- const resizeObserver = new ResizeObserver(() => {
47
- const contentBoundingClientRect = (
48
- contentRef.current as SVGGElement
49
- ).getBoundingClientRect();
42
+ const fallbackRef = useRef<SVGGElement | null>(null);
43
+ const contentRef = (ref ||
44
+ fallbackRef) as MutableRefObject<SVGGElement | null>;
45
+ const minimapSvgRef = useRef<SVGSVGElement | null>(null);
46
+ const minimapContentRef = useRef<SVGSVGElement | null>(null);
47
+ const [contentClientRect, setContentClientRect] =
48
+ useState<Dimension | null>(null);
50
49
 
51
- setContentClientRect({
52
- height: contentBoundingClientRect.height,
53
- width: contentBoundingClientRect.width
50
+ const resizeObserver = new ResizeObserver(() => {
51
+ const contentBoundingClientRect = (
52
+ contentRef.current as SVGGElement
53
+ ).getBoundingClientRect();
54
+
55
+ setContentClientRect({
56
+ height: contentBoundingClientRect.height,
57
+ width: contentBoundingClientRect.width
58
+ });
54
59
  });
55
- });
56
60
 
57
- useEffect(() => {
58
- if (contentRef.current) {
59
- resizeObserver.disconnect();
60
- resizeObserver.observe(contentRef.current);
61
- }
61
+ useEffect(() => {
62
+ if (contentRef.current) {
63
+ resizeObserver.disconnect();
64
+ resizeObserver.observe(contentRef.current);
65
+ }
62
66
 
63
- return () => {
64
- resizeObserver.disconnect();
65
- };
66
- }, [contentRef.current]);
67
+ return () => {
68
+ resizeObserver.disconnect();
69
+ };
70
+ }, [contentRef.current]);
67
71
 
68
- const { move, dragEnd, dragStart, isDragging } = useZoom();
72
+ const { move, dragEnd, dragStart, isDragging } = useZoom();
69
73
 
70
- const diffBetweenContentAndSvg = minimapSvgRef.current &&
71
- minimapContentRef.current && {
72
- left:
73
- minimapContentRef.current.getBoundingClientRect().left -
74
- minimapSvgRef.current.getBoundingClientRect().left,
75
- top:
76
- minimapContentRef.current.getBoundingClientRect().top -
77
- minimapSvgRef.current.getBoundingClientRect().top
78
- };
74
+ const diffBetweenContentAndSvg = minimapSvgRef.current &&
75
+ minimapContentRef.current && {
76
+ left:
77
+ minimapContentRef.current.getBoundingClientRect().left -
78
+ minimapSvgRef.current.getBoundingClientRect().left,
79
+ top:
80
+ minimapContentRef.current.getBoundingClientRect().top -
81
+ minimapSvgRef.current.getBoundingClientRect().top
82
+ };
79
83
 
80
- return (
81
- <div style={{ position: 'relative' }}>
82
- <svg
83
- className={classes.svg}
84
- data-is-grabbing={isDragging}
85
- data-testid="zoom-container"
86
- height={height}
87
- width={width}
88
- onMouseDown={dragStart(zoom)}
89
- onMouseEnter={dragStart(zoom)}
90
- onMouseLeave={dragEnd}
91
- onMouseMove={move(zoom)}
92
- onMouseUp={dragEnd}
93
- onWheel={zoom.handleWheel}
94
- >
95
- <RectClipPath
96
- height={Math.max(contentClientRect?.height || 0, height)}
97
- id={`zoom-clip-${id}`}
98
- rx={radius}
99
- width={Math.max(contentClientRect?.width || 0, width)}
100
- />
101
- <g
102
- data-testid="zoom-content"
103
- ref={contentRef}
104
- transform={zoom.toString()}
84
+ return (
85
+ <div style={{ position: 'relative' }}>
86
+ <svg
87
+ className={classes.svg}
88
+ data-is-grabbing={isDragging}
89
+ data-testid="zoom-container"
90
+ height={height}
91
+ width={width}
92
+ onMouseDown={dragStart(zoom)}
93
+ onMouseEnter={dragStart(zoom)}
94
+ onMouseLeave={dragEnd}
95
+ onMouseMove={move(zoom)}
96
+ onMouseUp={dragEnd}
97
+ onWheel={zoom.handleWheel}
105
98
  >
106
- {children({
107
- contentClientRect,
108
- height,
109
- transformMatrix: zoom.transformMatrix,
110
- width
111
- })}
112
- </g>
113
- </svg>
114
- <div className={classes.actionsAndZoom} data-position={minimapPosition}>
115
- {showMinimap && contentClientRect && (
116
- <svg
117
- className={classes.minimapContainer}
118
- data-testid="minimap"
119
- height={height * minimapScale}
120
- ref={minimapSvgRef}
121
- width={width * minimapScale}
99
+ <RectClipPath
100
+ height={Math.max(contentClientRect?.height || 0, height)}
101
+ id={`zoom-clip-${id}`}
102
+ rx={radius}
103
+ width={Math.max(contentClientRect?.width || 0, width)}
104
+ />
105
+ <g
106
+ data-testid="zoom-content"
107
+ ref={contentRef}
108
+ transform={zoom.toString()}
122
109
  >
123
- <Minimap
124
- contentClientRect={contentClientRect}
125
- diffBetweenContentAndSvg={
126
- diffBetweenContentAndSvg || { left: 0, top: 0 }
127
- }
128
- height={height}
129
- id={id}
130
- isDraggingFromContainer={isDragging}
131
- width={width}
132
- zoom={zoom}
110
+ {children({
111
+ contentClientRect,
112
+ height,
113
+ transformMatrix: zoom.transformMatrix,
114
+ width,
115
+ zoom
116
+ })}
117
+ </g>
118
+ </svg>
119
+ <div className={classes.actionsAndZoom} data-position={minimapPosition}>
120
+ {showMinimap && contentClientRect && (
121
+ <svg
122
+ className={classes.minimapContainer}
123
+ data-testid="minimap"
124
+ height={height * minimapScale}
125
+ ref={minimapSvgRef}
126
+ width={width * minimapScale}
133
127
  >
134
- <g ref={minimapContentRef}>
135
- {children({
136
- contentClientRect,
137
- height,
138
- transformMatrix: zoom.transformMatrix,
139
- width
140
- })}
141
- </g>
142
- </Minimap>
143
- </svg>
144
- )}
145
- <div className={classes.actions}>
146
- <IconButton
147
- data-testid="zoom in"
148
- icon={<ZoomInIcon />}
149
- size="small"
150
- onClick={() => zoom.scale({ scaleX: 1.2, scaleY: 1.2 })}
151
- />
152
- <IconButton
153
- data-testid="zoom out"
154
- icon={<ZoomOutIcon />}
155
- size="small"
156
- onClick={() => zoom.scale({ scaleX: 0.8, scaleY: 0.8 })}
157
- />
158
- <IconButton
159
- data-testid="clear"
160
- icon={<ReplayIcon />}
161
- size="small"
162
- onClick={zoom.reset}
163
- />
128
+ <Minimap
129
+ contentClientRect={contentClientRect}
130
+ diffBetweenContentAndSvg={
131
+ diffBetweenContentAndSvg || { left: 0, top: 0 }
132
+ }
133
+ height={height}
134
+ id={id}
135
+ isDraggingFromContainer={isDragging}
136
+ width={width}
137
+ zoom={zoom}
138
+ >
139
+ <g ref={minimapContentRef}>
140
+ {children({
141
+ contentClientRect,
142
+ height,
143
+ transformMatrix: zoom.transformMatrix,
144
+ width,
145
+ zoom
146
+ })}
147
+ </g>
148
+ </Minimap>
149
+ </svg>
150
+ )}
151
+ <div className={classes.actions}>
152
+ <IconButton
153
+ data-testid="zoom in"
154
+ icon={<ZoomInIcon />}
155
+ size="small"
156
+ onClick={() => zoom.scale({ scaleX: 1.2, scaleY: 1.2 })}
157
+ />
158
+ <IconButton
159
+ data-testid="zoom out"
160
+ icon={<ZoomOutIcon />}
161
+ size="small"
162
+ onClick={() => zoom.scale({ scaleX: 0.8, scaleY: 0.8 })}
163
+ />
164
+ <IconButton
165
+ data-testid="clear"
166
+ icon={<ReplayIcon />}
167
+ size="small"
168
+ onClick={zoom.reset}
169
+ />
170
+ </div>
164
171
  </div>
165
172
  </div>
166
- </div>
167
- );
168
- };
173
+ );
174
+ }
175
+ );
169
176
 
170
177
  export default ZoomContent;
@@ -1,12 +1,12 @@
1
+ import { ProvidedZoom, TransformMatrix } from '@visx/zoom/lib/types';
2
+
1
3
  export interface ZoomState {
2
- transformMatrix: {
3
- scaleX: number;
4
- scaleY: number;
5
- skewX: number;
6
- skewY: number;
7
- translateX: number;
8
- translateY: number;
9
- };
4
+ transformMatrix: TransformMatrix;
5
+ }
6
+
7
+ export interface Dimension {
8
+ height: number;
9
+ width: number;
10
10
  }
11
11
 
12
12
  export type MinimapPosition =
@@ -15,11 +15,14 @@ export type MinimapPosition =
15
15
  | 'bottom-left'
16
16
  | 'bottom-right';
17
17
 
18
- export interface ChildrenProps extends ZoomState {
19
- contentClientRect: {
20
- height: number;
21
- width: number;
22
- } | null;
23
- height: number;
24
- width: number;
18
+ export interface ZoomInterface {
19
+ zoom: ProvidedZoom<SVGSVGElement> & ZoomState;
20
+ }
21
+
22
+ export interface ChildrenProps extends ZoomState, Dimension, ZoomInterface {
23
+ contentClientRect: Dimension | null;
24
+ }
25
+
26
+ export interface ZoomChildren {
27
+ children: (args: ChildrenProps) => JSX.Element;
25
28
  }
@@ -2,7 +2,7 @@ import { useCallback, useState } from 'react';
2
2
 
3
3
  import { Point } from '@visx/point';
4
4
  import { ProvidedZoom, Translate } from '@visx/zoom/lib/types';
5
- import { equals, gt, isNil, pick } from 'ramda';
5
+ import { equals, gt, pick } from 'ramda';
6
6
 
7
7
  import { ZoomState } from './models';
8
8
 
@@ -62,8 +62,8 @@ export const useMinimap = ({
62
62
  );
63
63
 
64
64
  const transformTo = useCallback(
65
- (e): void => {
66
- if (!isNil(e.nativeEvent.which) && !equals(e.nativeEvent.which, 1)) {
65
+ (e: MouseEvent): void => {
66
+ if (!equals(e.buttons, 1)) {
67
67
  return;
68
68
  }
69
69
  const { x, y } = getMatrixPoint(e);
@@ -76,11 +76,8 @@ export const useMinimap = ({
76
76
  [zoom.transformMatrix, scale]
77
77
  );
78
78
 
79
- const dragStart = (e): void => {
80
- if (
81
- (!isNil(e.nativeEvent.which) && !equals(e.nativeEvent.which, 1)) ||
82
- isDraggingFromContainer
83
- ) {
79
+ const dragStart = (e: MouseEvent): void => {
80
+ if (!equals(e.buttons, 1) || isDraggingFromContainer) {
84
81
  return;
85
82
  }
86
83
  setStartPoint(getMatrixPoint(e));
@@ -1,13 +1,13 @@
1
1
  import { useCallback, useState } from 'react';
2
2
 
3
3
  import { Point, ProvidedZoom, Translate } from '@visx/zoom/lib/types';
4
- import { equals, isNil } from 'ramda';
4
+ import { equals } from 'ramda';
5
5
 
6
6
  import { localPoint } from './localPoint';
7
7
  import { ZoomState } from './models';
8
8
 
9
- const isLeftMouseButtonClicked = (e): boolean =>
10
- !isNil(e.nativeEvent.which) && equals(e.nativeEvent.which, 1);
9
+ const isLeftMouseButtonClicked = (e: MouseEvent): boolean =>
10
+ equals(e.buttons, 1);
11
11
 
12
12
  interface UseZoomState {
13
13
  dragEnd: () => void;
package/src/index.ts CHANGED
@@ -71,6 +71,7 @@ export { default as StatusChip } from './StatusChip';
71
71
  export type { Props as StatusChipProps } from './StatusChip';
72
72
 
73
73
  export type { Listing as ListingModel } from './api/models';
74
+ export type { ListingMap as ListingMapModel } from './api/models';
74
75
 
75
76
  export { default as useCancelTokenSource } from './api/useCancelTokenSource';
76
77
  export { getData, patchData, postData, putData, deleteData } from './api';
@@ -131,6 +132,7 @@ export {
131
132
  default as useGraphQuery,
132
133
  resourceTypeQueryParameter
133
134
  } from './api/useGraphQuery';
135
+ export { WidgetResourceType as ResourceType } from './api/useGraphQuery/models';
134
136
  export { default as QueryProvider, client } from './api/QueryProvider';
135
137
  export {
136
138
  default as FileDropZone,
@@ -28,3 +28,4 @@ export * from '../Graph/Chart/InteractiveComponents/TimeShiftZones/useTimeShiftZ
28
28
  export * from '../TimePeriods/helpers';
29
29
  export { lastDayPeriod, type Parameters } from '../TimePeriods/models';
30
30
  export * from './useLocaleTimezoneDate/useLocaleTimezoneDate';
31
+ export * from './useLocale';
@@ -0,0 +1,9 @@
1
+ import { browserLocaleAtom, userAtom } from '@centreon/ui-context';
2
+ import { useAtomValue } from 'jotai';
3
+
4
+ export const useLocale = () => {
5
+ const user = useAtomValue(userAtom);
6
+ const browserLocale = useAtomValue(browserLocaleAtom);
7
+
8
+ return user.locale || browserLocale;
9
+ };
@@ -0,0 +1,38 @@
1
+ import { browserLocaleAtom, userAtom } from '@centreon/ui-context';
2
+ import { Provider, createStore } from 'jotai';
3
+ import { useLocale } from '.';
4
+
5
+ const TestComponent = () => {
6
+ const locale = useLocale();
7
+
8
+ return <p>{locale}</p>;
9
+ };
10
+
11
+ const initialize = ({ userLocale, browserLocale }) => {
12
+ const store = createStore();
13
+
14
+ store.set(userAtom, { locale: userLocale });
15
+ store.set(browserLocaleAtom, browserLocale);
16
+
17
+ cy.mount({
18
+ Component: (
19
+ <Provider store={store}>
20
+ <TestComponent />
21
+ </Provider>
22
+ )
23
+ });
24
+ };
25
+
26
+ describe('useLocale', () => {
27
+ it('displays the user locale when the corresponding atom is set', () => {
28
+ initialize({ userLocale: 'fi', browserLocale: 'en' });
29
+
30
+ cy.contains('fi').should('be.visible');
31
+ });
32
+
33
+ it('displays the browser locale when the user locale is not set', () => {
34
+ initialize({ browserLocale: 'de', userLocale: null });
35
+
36
+ cy.contains('de').should('be.visible');
37
+ });
38
+ });