@centreon/ui 24.6.0 → 24.6.2
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/Dashboard/Item.tsx +25 -8
- package/src/Dashboard/Layout.tsx +15 -1
- package/src/Dashboard/atoms.ts +3 -0
- package/src/Graph/BarStack/BarStack.cypress.spec.tsx +1 -1
- package/src/Graph/BarStack/BarStack.stories.tsx +15 -0
- package/src/Graph/BarStack/BarStack.styles.ts +5 -1
- package/src/Graph/BarStack/ResponsiveBarStack.tsx +18 -15
- package/src/Graph/BarStack/useResponsiveBarStack.ts +4 -8
- package/src/Graph/Gauge/AnimatedPie.tsx +3 -1
- package/src/Graph/Gauge/Gauge.stories.tsx +10 -2
- package/src/Graph/Gauge/PieData.tsx +9 -4
- package/src/Graph/Gauge/ResponsiveGauge.tsx +55 -69
- package/src/Graph/Gauge/Thresholds.tsx +5 -3
- package/src/Graph/Gauge/utils.ts +4 -0
- package/src/Graph/HeatMap/HeatMap.tsx +3 -1
- package/src/Graph/HeatMap/ResponsiveHeatMap.tsx +12 -4
- package/src/Graph/LineChart/Header/index.tsx +2 -2
- package/src/Graph/LineChart/InteractiveComponents/AnchorPoint/useTickGraph.ts +1 -1
- package/src/Graph/LineChart/InteractiveComponents/GraphValueTooltip/useGraphValueTooltip.ts +5 -3
- package/src/Graph/LineChart/Legend/Legend.styles.ts +10 -3
- package/src/Graph/LineChart/Legend/LegendHeader.tsx +3 -1
- package/src/Graph/LineChart/Legend/index.tsx +19 -3
- package/src/Graph/LineChart/LineChart.styles.ts +4 -47
- package/src/Graph/LineChart/LineChart.tsx +132 -211
- package/src/Graph/LineChart/index.stories.tsx +3 -1
- package/src/Graph/LineChart/models.ts +1 -5
- package/src/Graph/PieChart/PieChart.cypress.spec.tsx +1 -1
- package/src/Graph/PieChart/PieChart.stories.tsx +14 -0
- package/src/Graph/PieChart/ResponsivePie.tsx +15 -9
- package/src/Graph/PieChart/useResponsivePie.ts +0 -3
- package/src/Graph/SingleBar/ResponsiveSingleBar.tsx +65 -68
- package/src/Graph/SingleBar/SingleBar.stories.tsx +28 -0
- package/src/Graph/SingleBar/ThresholdLine.tsx +14 -18
- package/src/Graph/SingleBar/Thresholds.tsx +9 -1
- package/src/Graph/Text/Text.stories.tsx +32 -0
- package/src/Graph/Text/Text.styles.ts +0 -1
- package/src/Graph/Text/Text.tsx +11 -7
- package/src/Graph/{LineChart/BasicComponents → common}/Axes/UnitLabel.tsx +1 -1
- package/src/Graph/{LineChart/BasicComponents → common}/Axes/index.tsx +8 -7
- package/src/Graph/{LineChart/BasicComponents → common}/Axes/models.ts +2 -2
- package/src/Graph/{LineChart/BasicComponents → common}/Axes/useAxisY.ts +2 -2
- package/src/Graph/common/BaseChart/BaseChart.tsx +114 -0
- package/src/Graph/common/BaseChart/ChartSvgWrapper.tsx +75 -0
- package/src/Graph/common/BaseChart/useBaseChartStyles.ts +38 -0
- package/src/Graph/common/BaseChart/useComputeBaseChartDimensions.ts +61 -0
- package/src/Graph/{LineChart/BasicComponents → common}/Grids/index.tsx +1 -1
- package/src/Graph/common/useTooltipStyles.ts +17 -0
- package/src/Graph/common/utils.ts +6 -0
- package/src/Typography/FluidTypography/index.tsx +5 -3
package/package.json
CHANGED
package/src/Dashboard/Item.tsx
CHANGED
|
@@ -4,10 +4,12 @@ import {
|
|
|
4
4
|
forwardRef,
|
|
5
5
|
MouseEvent,
|
|
6
6
|
ReactElement,
|
|
7
|
-
useEffect
|
|
7
|
+
useEffect,
|
|
8
|
+
useMemo
|
|
8
9
|
} from 'react';
|
|
9
10
|
|
|
10
|
-
import { isNil, prop } from 'ramda';
|
|
11
|
+
import { equals, isNil, prop } from 'ramda';
|
|
12
|
+
import { useAtomValue } from 'jotai';
|
|
11
13
|
|
|
12
14
|
import { Card, useTheme } from '@mui/material';
|
|
13
15
|
|
|
@@ -15,6 +17,7 @@ import { useMemoComponent, useViewportIntersection } from '../utils';
|
|
|
15
17
|
import LoadingSkeleton from '../LoadingSkeleton';
|
|
16
18
|
|
|
17
19
|
import { useDashboardItemStyles } from './Dashboard.styles';
|
|
20
|
+
import { isResizingItemAtom } from './atoms';
|
|
18
21
|
|
|
19
22
|
interface DashboardItemProps {
|
|
20
23
|
additionalMemoProps?: Array<unknown>;
|
|
@@ -55,6 +58,18 @@ const Item = forwardRef<HTMLDivElement, DashboardItemProps>(
|
|
|
55
58
|
const { classes, cx } = useDashboardItemStyles({ hasHeader });
|
|
56
59
|
const theme = useTheme();
|
|
57
60
|
|
|
61
|
+
const isResizingItem = useAtomValue(isResizingItemAtom);
|
|
62
|
+
|
|
63
|
+
const isResizing = useMemo(
|
|
64
|
+
() => equals(id, isResizingItem),
|
|
65
|
+
[isResizingItem, id]
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
const sanitizedReactGridLayoutClassName = useMemo(
|
|
69
|
+
() => (isResizing ? className : className?.replace(' resizing ', '')),
|
|
70
|
+
[className, isResizing]
|
|
71
|
+
);
|
|
72
|
+
|
|
58
73
|
const listeners = {
|
|
59
74
|
onMouseDown,
|
|
60
75
|
onMouseUp,
|
|
@@ -75,7 +90,7 @@ const Item = forwardRef<HTMLDivElement, DashboardItemProps>(
|
|
|
75
90
|
Component: (
|
|
76
91
|
<div
|
|
77
92
|
{...cardContainerListeners}
|
|
78
|
-
className={
|
|
93
|
+
className={sanitizedReactGridLayoutClassName}
|
|
79
94
|
ref={ref}
|
|
80
95
|
style={{
|
|
81
96
|
...style,
|
|
@@ -88,11 +103,13 @@ const Item = forwardRef<HTMLDivElement, DashboardItemProps>(
|
|
|
88
103
|
>
|
|
89
104
|
{header && (
|
|
90
105
|
<div className={classes.widgetHeader} data-canMove={canMove}>
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
106
|
+
{canMove && (
|
|
107
|
+
<div
|
|
108
|
+
{...listeners}
|
|
109
|
+
className={classes.widgetHeaderDraggable}
|
|
110
|
+
data-testid={`${id}_move_panel`}
|
|
111
|
+
/>
|
|
112
|
+
)}
|
|
96
113
|
{header}
|
|
97
114
|
</div>
|
|
98
115
|
)}
|
package/src/Dashboard/Layout.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react';
|
|
1
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
2
2
|
|
|
3
|
+
import { useSetAtom } from 'jotai';
|
|
3
4
|
import GridLayout, { Layout, WidthProvider } from 'react-grid-layout';
|
|
4
5
|
import 'react-grid-layout/css/styles.css';
|
|
5
6
|
|
|
@@ -12,6 +13,7 @@ import {
|
|
|
12
13
|
import { useDashboardLayoutStyles } from './Dashboard.styles';
|
|
13
14
|
import { getColumnsFromScreenSize, getLayout, rowHeight } from './utils';
|
|
14
15
|
import Grid from './Grid';
|
|
16
|
+
import { isResizingItemAtom } from './atoms';
|
|
15
17
|
|
|
16
18
|
const ReactGridLayout = WidthProvider(GridLayout);
|
|
17
19
|
|
|
@@ -36,10 +38,20 @@ const DashboardLayout = <T extends Layout>({
|
|
|
36
38
|
|
|
37
39
|
const [columns, setColumns] = useState(getColumnsFromScreenSize());
|
|
38
40
|
|
|
41
|
+
const setIsResizingItem = useSetAtom(isResizingItemAtom);
|
|
42
|
+
|
|
39
43
|
const resize = (): void => {
|
|
40
44
|
setColumns(getColumnsFromScreenSize());
|
|
41
45
|
};
|
|
42
46
|
|
|
47
|
+
const startResize = useCallback((_, __, newItem: T) => {
|
|
48
|
+
setIsResizingItem(newItem.i);
|
|
49
|
+
}, []);
|
|
50
|
+
|
|
51
|
+
const stopResize = useCallback(() => {
|
|
52
|
+
setIsResizingItem(null);
|
|
53
|
+
}, []);
|
|
54
|
+
|
|
43
55
|
useEffect(() => {
|
|
44
56
|
window.addEventListener('resize', resize);
|
|
45
57
|
|
|
@@ -66,6 +78,8 @@ const DashboardLayout = <T extends Layout>({
|
|
|
66
78
|
rowHeight={rowHeight}
|
|
67
79
|
width={width}
|
|
68
80
|
onLayoutChange={changeLayout}
|
|
81
|
+
onResizeStart={startResize}
|
|
82
|
+
onResizeStop={stopResize}
|
|
69
83
|
>
|
|
70
84
|
{children}
|
|
71
85
|
</ReactGridLayout>
|
|
@@ -55,7 +55,7 @@ describe('Bar stack', () => {
|
|
|
55
55
|
it('adjusts size based on the provided width and height', () => {
|
|
56
56
|
initialize({ displayLegend: false, height: '300px', width: '300px' });
|
|
57
57
|
|
|
58
|
-
cy.findByTestId('barStack').should('have.css', 'height', '
|
|
58
|
+
cy.findByTestId('barStack').should('have.css', 'height', '270px');
|
|
59
59
|
|
|
60
60
|
cy.makeSnapshot();
|
|
61
61
|
});
|
|
@@ -50,6 +50,10 @@ const Template = (args): JSX.Element => {
|
|
|
50
50
|
return <ResponsiveBarStack height={300} width={500} {...args} />;
|
|
51
51
|
};
|
|
52
52
|
|
|
53
|
+
const SmallTemplate = (args): JSX.Element => {
|
|
54
|
+
return <ResponsiveBarStack height={120} width={120} {...args} />;
|
|
55
|
+
};
|
|
56
|
+
|
|
53
57
|
export const Vertical: Story = {
|
|
54
58
|
args: { data, title: 'hosts' },
|
|
55
59
|
render: Template
|
|
@@ -123,3 +127,14 @@ export const HorizontalWithoutLegend: Story = {
|
|
|
123
127
|
},
|
|
124
128
|
render: Template
|
|
125
129
|
};
|
|
130
|
+
|
|
131
|
+
export const SmallDisplay: Story = {
|
|
132
|
+
args: {
|
|
133
|
+
TooltipContent,
|
|
134
|
+
data,
|
|
135
|
+
displayValues: true,
|
|
136
|
+
title: 'hosts',
|
|
137
|
+
variant: 'horizontal'
|
|
138
|
+
},
|
|
139
|
+
render: SmallTemplate
|
|
140
|
+
};
|
|
@@ -13,12 +13,16 @@ export const useBarStackStyles = makeStyles()((theme) => ({
|
|
|
13
13
|
gap: theme.spacing(1.5),
|
|
14
14
|
justifyContent: 'center'
|
|
15
15
|
},
|
|
16
|
+
smallTitle: {
|
|
17
|
+
fontSize: theme.typography.body1.fontSize
|
|
18
|
+
},
|
|
16
19
|
svgContainer: {
|
|
17
20
|
alignItems: 'center',
|
|
18
21
|
backgroundColor: theme.palette.background.panelGroups,
|
|
19
22
|
borderRadius: theme.spacing(1.25),
|
|
20
23
|
display: 'flex',
|
|
21
|
-
justifyContent: 'center'
|
|
24
|
+
justifyContent: 'center',
|
|
25
|
+
padding: theme.spacing(1)
|
|
22
26
|
},
|
|
23
27
|
svgWrapper: {
|
|
24
28
|
alignItems: 'center',
|
|
@@ -5,7 +5,7 @@ import { Group } from '@visx/group';
|
|
|
5
5
|
import numeral from 'numeral';
|
|
6
6
|
import { Text } from '@visx/text';
|
|
7
7
|
import { useTranslation } from 'react-i18next';
|
|
8
|
-
import { equals } from 'ramda';
|
|
8
|
+
import { equals, lt } from 'ramda';
|
|
9
9
|
|
|
10
10
|
import { Tooltip } from '../../components';
|
|
11
11
|
import { LegendProps } from '../Legend/models';
|
|
@@ -36,7 +36,7 @@ const ResponsiveBarStack = ({
|
|
|
36
36
|
legendDirection = 'column'
|
|
37
37
|
}: BarStackProps & { height: number; width: number }): JSX.Element => {
|
|
38
38
|
const { t } = useTranslation();
|
|
39
|
-
const { classes } = useBarStackStyles();
|
|
39
|
+
const { classes, cx } = useBarStackStyles();
|
|
40
40
|
|
|
41
41
|
const titleRef = useRef(null);
|
|
42
42
|
const legendRef = useRef(null);
|
|
@@ -50,7 +50,6 @@ const ResponsiveBarStack = ({
|
|
|
50
50
|
total,
|
|
51
51
|
xScale,
|
|
52
52
|
yScale,
|
|
53
|
-
svgWrapperWidth,
|
|
54
53
|
svgContainerSize,
|
|
55
54
|
isVerticalBar
|
|
56
55
|
} = useResponsiveBarStack({
|
|
@@ -68,24 +67,28 @@ const ResponsiveBarStack = ({
|
|
|
68
67
|
? BarStackVertical
|
|
69
68
|
: BarStackHorizontal;
|
|
70
69
|
|
|
70
|
+
const isSmallHeight = isVerticalBar ? lt(height, 190) : lt(height, 100);
|
|
71
|
+
const isSmallWidth = isVerticalBar ? lt(width, 80) : lt(width, 350);
|
|
72
|
+
const mustDisplayLegend = isSmallWidth ? false : displayLegend;
|
|
73
|
+
|
|
71
74
|
return (
|
|
72
|
-
<div className={classes.container} style={{
|
|
73
|
-
<div
|
|
74
|
-
className={classes.svgWrapper}
|
|
75
|
-
style={{
|
|
76
|
-
minHeight: height,
|
|
77
|
-
width: svgWrapperWidth
|
|
78
|
-
}}
|
|
79
|
-
>
|
|
75
|
+
<div className={classes.container} style={{ width }}>
|
|
76
|
+
<div className={classes.svgWrapper}>
|
|
80
77
|
{title && (
|
|
81
|
-
<div
|
|
78
|
+
<div
|
|
79
|
+
className={cx(classes.title, isSmallHeight && classes.smallTitle)}
|
|
80
|
+
data-testid="Title"
|
|
81
|
+
ref={titleRef}
|
|
82
|
+
>
|
|
82
83
|
{`${numeral(total).format('0a').toUpperCase()} `} {t(title)}
|
|
83
84
|
</div>
|
|
84
85
|
)}
|
|
85
86
|
<div
|
|
86
87
|
className={classes.svgContainer}
|
|
87
88
|
data-testid="barStack"
|
|
88
|
-
style={
|
|
89
|
+
style={{
|
|
90
|
+
width: svgContainerSize.width
|
|
91
|
+
}}
|
|
89
92
|
>
|
|
90
93
|
<svg
|
|
91
94
|
data-variant={variant}
|
|
@@ -155,7 +158,7 @@ const ResponsiveBarStack = ({
|
|
|
155
158
|
isVerticalBar ? bar.height - 1 : bar.height
|
|
156
159
|
}
|
|
157
160
|
key={`bar-stack-${barStack.index}-${bar.index}`}
|
|
158
|
-
ry={
|
|
161
|
+
ry={4}
|
|
159
162
|
width={isVerticalBar ? bar.width : bar.width - 1}
|
|
160
163
|
x={bar.x}
|
|
161
164
|
y={bar.y}
|
|
@@ -190,7 +193,7 @@ const ResponsiveBarStack = ({
|
|
|
190
193
|
</svg>
|
|
191
194
|
</div>
|
|
192
195
|
</div>
|
|
193
|
-
{
|
|
196
|
+
{mustDisplayLegend && (
|
|
194
197
|
<div data-testid="Legend" ref={legendRef}>
|
|
195
198
|
<Legend
|
|
196
199
|
data={data}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { scaleBand, scaleLinear, scaleOrdinal } from '@visx/scale';
|
|
2
|
-
import { equals, pluck } from 'ramda';
|
|
2
|
+
import { equals, gt, pluck } from 'ramda';
|
|
3
3
|
|
|
4
4
|
import { getValueByUnit } from '../common/utils';
|
|
5
5
|
import { LegendScale } from '../Legend/models';
|
|
@@ -29,7 +29,6 @@ interface useBarStackState {
|
|
|
29
29
|
keys: Array<string>;
|
|
30
30
|
legendScale: LegendScale;
|
|
31
31
|
svgContainerSize: Size;
|
|
32
|
-
svgWrapperWidth: number;
|
|
33
32
|
total: number;
|
|
34
33
|
xScale;
|
|
35
34
|
yScale;
|
|
@@ -53,17 +52,15 @@ const useResponsiveBarStack = ({
|
|
|
53
52
|
const horizontalGap = widthOfLegend > 0 ? 12 : 0;
|
|
54
53
|
const verticalGap = heightOfTitle > 0 ? 8 : 0;
|
|
55
54
|
|
|
56
|
-
const svgWrapperWidth = isVerticalBar
|
|
57
|
-
? size + 36
|
|
58
|
-
: width - widthOfLegend - horizontalGap;
|
|
59
|
-
|
|
60
55
|
const svgContainerSize = {
|
|
61
56
|
height: isVerticalBar ? height - heightOfTitle - verticalGap : size,
|
|
62
57
|
width: isVerticalBar ? size : width - widthOfLegend - horizontalGap
|
|
63
58
|
};
|
|
64
59
|
|
|
65
60
|
const barSize = {
|
|
66
|
-
height: svgContainerSize.height - 16
|
|
61
|
+
height: gt(height / 2, svgContainerSize.height - 16)
|
|
62
|
+
? svgContainerSize.height - 16
|
|
63
|
+
: svgContainerSize.height - 46,
|
|
67
64
|
width: svgContainerSize.width - 16
|
|
68
65
|
};
|
|
69
66
|
|
|
@@ -121,7 +118,6 @@ const useResponsiveBarStack = ({
|
|
|
121
118
|
keys,
|
|
122
119
|
legendScale,
|
|
123
120
|
svgContainerSize,
|
|
124
|
-
svgWrapperWidth,
|
|
125
121
|
total,
|
|
126
122
|
xScale,
|
|
127
123
|
yScale
|
|
@@ -85,7 +85,9 @@ const AnimatedPie = <Datum,>({
|
|
|
85
85
|
'label',
|
|
86
86
|
thresholds[thresholdType as 'warning' | 'critical']
|
|
87
87
|
).map((label) => (
|
|
88
|
-
<Typography key={label}>
|
|
88
|
+
<Typography key={label} variant="body2">
|
|
89
|
+
{label}
|
|
90
|
+
</Typography>
|
|
89
91
|
))}
|
|
90
92
|
</div>
|
|
91
93
|
),
|
|
@@ -12,8 +12,16 @@ export default meta;
|
|
|
12
12
|
type Story = StoryObj<typeof Gauge>;
|
|
13
13
|
|
|
14
14
|
const Template = (props): JSX.Element => (
|
|
15
|
-
<div style={{
|
|
16
|
-
<
|
|
15
|
+
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
|
16
|
+
<div style={{ height: '500px', width: '500px' }}>
|
|
17
|
+
<Gauge {...props} />
|
|
18
|
+
</div>
|
|
19
|
+
<div style={{ height: '100px', width: '120px' }}>
|
|
20
|
+
<Gauge {...props} />
|
|
21
|
+
</div>
|
|
22
|
+
<div style={{ height: '300px', width: '200px' }}>
|
|
23
|
+
<Gauge {...props} />
|
|
24
|
+
</div>
|
|
17
25
|
</div>
|
|
18
26
|
);
|
|
19
27
|
|
|
@@ -9,6 +9,7 @@ import { getColorFromDataAndTresholds } from '../common/utils';
|
|
|
9
9
|
import { thresholdThickness } from './Thresholds';
|
|
10
10
|
import AnimatedPie from './AnimatedPie';
|
|
11
11
|
import { GaugeProps } from './models';
|
|
12
|
+
import { angles } from './utils';
|
|
12
13
|
|
|
13
14
|
const dataThickness = 45;
|
|
14
15
|
|
|
@@ -37,15 +38,19 @@ const PieData = ({
|
|
|
37
38
|
range: [pieColor, 'transparent']
|
|
38
39
|
});
|
|
39
40
|
|
|
41
|
+
const dataThicknessFactor = radius / dataThickness / 3;
|
|
42
|
+
const thresholdThicknessFactor = radius / thresholdThickness / 15;
|
|
43
|
+
|
|
40
44
|
return (
|
|
41
45
|
<Pie
|
|
46
|
+
{...angles}
|
|
42
47
|
data={pieData}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
innerRadius={radius - dataThickness * dataThicknessFactor}
|
|
49
|
+
outerRadius={
|
|
50
|
+
radius - thresholdThickness * thresholdThicknessFactor * 1.25
|
|
51
|
+
}
|
|
46
52
|
pieSortValues={() => -1}
|
|
47
53
|
pieValue={identity}
|
|
48
|
-
startAngle={Math.PI / 2}
|
|
49
54
|
>
|
|
50
55
|
{(pie) => (
|
|
51
56
|
<AnimatedPie<number>
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { useRef } from 'react';
|
|
2
2
|
|
|
3
3
|
import { Group } from '@visx/group';
|
|
4
|
-
import { flatten, head, pluck } from 'ramda';
|
|
5
4
|
import { Tooltip } from '@visx/visx';
|
|
5
|
+
import { flatten, head, pluck } from 'ramda';
|
|
6
6
|
|
|
7
|
-
import { Box,
|
|
7
|
+
import { Box, useTheme } from '@mui/material';
|
|
8
8
|
|
|
9
9
|
import { Metric } from '../common/timeSeries/models';
|
|
10
10
|
import { formatMetricValueWithUnit } from '../common/timeSeries';
|
|
11
11
|
import { getColorFromDataAndTresholds } from '../common/utils';
|
|
12
12
|
import { margins } from '../common/margins';
|
|
13
|
+
import { Tooltip as MuiTooltip } from '../../components/Tooltip';
|
|
14
|
+
import { useTooltipStyles } from '../common/useTooltipStyles';
|
|
13
15
|
|
|
14
16
|
import Thresholds from './Thresholds';
|
|
15
17
|
import PieData from './PieData';
|
|
@@ -22,11 +24,6 @@ interface Props extends Pick<GaugeProps, 'thresholds' | 'baseColor'> {
|
|
|
22
24
|
width: number;
|
|
23
25
|
}
|
|
24
26
|
|
|
25
|
-
const baseStyles = {
|
|
26
|
-
...Tooltip.defaultStyles,
|
|
27
|
-
textAlign: 'center'
|
|
28
|
-
};
|
|
29
|
-
|
|
30
27
|
const ResponsiveGauge = ({
|
|
31
28
|
width,
|
|
32
29
|
height,
|
|
@@ -35,24 +32,21 @@ const ResponsiveGauge = ({
|
|
|
35
32
|
displayAsRaw,
|
|
36
33
|
baseColor
|
|
37
34
|
}: Props): JSX.Element => {
|
|
35
|
+
const { classes } = useTooltipStyles();
|
|
38
36
|
const svgRef = useRef<SVGSVGElement>(null);
|
|
39
37
|
|
|
40
38
|
const theme = useTheme();
|
|
41
39
|
|
|
42
|
-
const {
|
|
43
|
-
|
|
44
|
-
hideTooltip,
|
|
45
|
-
tooltipOpen,
|
|
46
|
-
tooltipLeft,
|
|
47
|
-
tooltipTop,
|
|
48
|
-
tooltipData
|
|
49
|
-
} = Tooltip.useTooltip();
|
|
40
|
+
const { showTooltip, hideTooltip, tooltipOpen, tooltipData } =
|
|
41
|
+
Tooltip.useTooltip();
|
|
50
42
|
|
|
51
43
|
const innerWidth = width - margins.left - margins.right;
|
|
52
44
|
const innerHeight = height - margins.top - margins.bottom;
|
|
53
45
|
const centerY = innerHeight / 2;
|
|
54
46
|
const centerX = innerWidth / 2;
|
|
55
|
-
const
|
|
47
|
+
const baseSize = Math.min(width, height);
|
|
48
|
+
const heightOverWidthRatio = height / width;
|
|
49
|
+
const radius = baseSize / (heightOverWidthRatio > 0.9 ? 2 : 1.8);
|
|
56
50
|
const thresholdValues = thresholds.enabled
|
|
57
51
|
? flatten([
|
|
58
52
|
pluck('value', thresholds.warning),
|
|
@@ -72,11 +66,6 @@ const ResponsiveGauge = ({
|
|
|
72
66
|
thresholds
|
|
73
67
|
});
|
|
74
68
|
|
|
75
|
-
const svgTop = svgRef.current?.getBoundingClientRect().top || 0;
|
|
76
|
-
const svgLeft = svgRef.current?.getBoundingClientRect().left || 0;
|
|
77
|
-
|
|
78
|
-
const isSmallWidget = height < 240;
|
|
79
|
-
|
|
80
69
|
const gaugeValue = formatMetricValueWithUnit({
|
|
81
70
|
base: 1000,
|
|
82
71
|
isRaw: displayAsRaw,
|
|
@@ -93,54 +82,51 @@ const ResponsiveGauge = ({
|
|
|
93
82
|
width: '100%'
|
|
94
83
|
}}
|
|
95
84
|
>
|
|
96
|
-
<
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
{tooltipData}
|
|
142
|
-
</Tooltip.Tooltip>
|
|
143
|
-
</Fade>
|
|
85
|
+
<MuiTooltip
|
|
86
|
+
classes={{
|
|
87
|
+
tooltip: classes.tooltip
|
|
88
|
+
}}
|
|
89
|
+
label={tooltipData}
|
|
90
|
+
open={thresholds.enabled && tooltipOpen}
|
|
91
|
+
placement="top"
|
|
92
|
+
>
|
|
93
|
+
<svg height={height} ref={svgRef} width={width}>
|
|
94
|
+
<Group
|
|
95
|
+
left={centerX + margins.left}
|
|
96
|
+
top={centerY + margins.top + baseSize / 8}
|
|
97
|
+
>
|
|
98
|
+
<Thresholds
|
|
99
|
+
adaptedMaxValue={adaptedMaxValue}
|
|
100
|
+
hideTooltip={hideTooltip}
|
|
101
|
+
metric={metric}
|
|
102
|
+
radius={radius}
|
|
103
|
+
showTooltip={showTooltip}
|
|
104
|
+
thresholds={thresholds}
|
|
105
|
+
/>
|
|
106
|
+
<PieData
|
|
107
|
+
adaptedMaxValue={adaptedMaxValue}
|
|
108
|
+
baseColor={baseColor}
|
|
109
|
+
metric={metric}
|
|
110
|
+
radius={radius}
|
|
111
|
+
thresholds={thresholds}
|
|
112
|
+
/>
|
|
113
|
+
<text
|
|
114
|
+
dominantBaseline="middle"
|
|
115
|
+
style={{
|
|
116
|
+
fill: pieColor,
|
|
117
|
+
...theme.typography.h3,
|
|
118
|
+
fontSize:
|
|
119
|
+
Math.min(width, height) / (gaugeValue?.length || 1) + 3
|
|
120
|
+
}}
|
|
121
|
+
textAnchor="middle"
|
|
122
|
+
x="0%"
|
|
123
|
+
y="0%"
|
|
124
|
+
>
|
|
125
|
+
{gaugeValue}
|
|
126
|
+
</text>
|
|
127
|
+
</Group>
|
|
128
|
+
</svg>
|
|
129
|
+
</MuiTooltip>
|
|
144
130
|
</Box>
|
|
145
131
|
);
|
|
146
132
|
};
|
|
@@ -6,6 +6,7 @@ import { useTheme } from '@mui/material';
|
|
|
6
6
|
|
|
7
7
|
import AnimatedPie from './AnimatedPie';
|
|
8
8
|
import { GaugeProps } from './models';
|
|
9
|
+
import { angles } from './utils';
|
|
9
10
|
|
|
10
11
|
export const thresholdThickness = 12;
|
|
11
12
|
|
|
@@ -83,18 +84,19 @@ const Thresholds = ({
|
|
|
83
84
|
}
|
|
84
85
|
];
|
|
85
86
|
|
|
87
|
+
const thresholdThicknessFactor = radius / thresholdThickness / 15;
|
|
88
|
+
|
|
86
89
|
return (
|
|
87
90
|
<>
|
|
88
91
|
{arcs.map(({ thresholdArc, thresholdScaleOrdinal }) => (
|
|
89
92
|
<Pie
|
|
93
|
+
{...angles}
|
|
90
94
|
data={thresholdArc}
|
|
91
|
-
|
|
92
|
-
innerRadius={radius - thresholdThickness}
|
|
95
|
+
innerRadius={radius - thresholdThickness * thresholdThicknessFactor}
|
|
93
96
|
key={`arc-${thresholdArc[0].name}`}
|
|
94
97
|
outerRadius={radius}
|
|
95
98
|
pieSortValues={() => -1}
|
|
96
99
|
pieValue={(d) => d.value}
|
|
97
|
-
startAngle={Math.PI / 2}
|
|
98
100
|
>
|
|
99
101
|
{(pie) => (
|
|
100
102
|
<AnimatedPie<{ name: string; value: number }>
|
|
@@ -5,7 +5,9 @@ import { HeatMapProps } from './model';
|
|
|
5
5
|
|
|
6
6
|
const HeatMap = <TData,>(props: HeatMapProps<TData>): JSX.Element => (
|
|
7
7
|
<ParentSize>
|
|
8
|
-
{({ width }) =>
|
|
8
|
+
{({ width, height }) => (
|
|
9
|
+
<ResponsiveHeatMap<TData> {...props} height={height} width={width} />
|
|
10
|
+
)}
|
|
9
11
|
</ParentSize>
|
|
10
12
|
);
|
|
11
13
|
|
|
@@ -21,8 +21,12 @@ const ResponsiveHeatMap = <TData,>({
|
|
|
21
21
|
arrowClassName,
|
|
22
22
|
tooltipContent,
|
|
23
23
|
tileSizeFixed,
|
|
24
|
-
displayTooltipCondition = T
|
|
25
|
-
|
|
24
|
+
displayTooltipCondition = T,
|
|
25
|
+
height
|
|
26
|
+
}: HeatMapProps<TData> & {
|
|
27
|
+
height: number;
|
|
28
|
+
width: number;
|
|
29
|
+
}): JSX.Element | null => {
|
|
26
30
|
const { classes, cx } = useHeatMapStyles();
|
|
27
31
|
|
|
28
32
|
const tileSize = useMemo(() => {
|
|
@@ -40,7 +44,11 @@ const ResponsiveHeatMap = <TData,>({
|
|
|
40
44
|
const theoricalTotalTilesWidth =
|
|
41
45
|
tilesLength * tileWidth + (tilesLength - 1) * gap;
|
|
42
46
|
|
|
43
|
-
if (
|
|
47
|
+
if (
|
|
48
|
+
(lt(height, maxTileSize) ||
|
|
49
|
+
(lt(width, 680) && gt(maxTotalTilesWidth, width))) &&
|
|
50
|
+
!tileSizeFixed
|
|
51
|
+
) {
|
|
44
52
|
return smallestTileSize;
|
|
45
53
|
}
|
|
46
54
|
|
|
@@ -49,7 +57,7 @@ const ResponsiveHeatMap = <TData,>({
|
|
|
49
57
|
}
|
|
50
58
|
|
|
51
59
|
return tileSizeFixed ? maxTileSize : tileWidth;
|
|
52
|
-
}, [width, tiles]);
|
|
60
|
+
}, [width, tiles, height]);
|
|
53
61
|
|
|
54
62
|
const isSmallestSize = equals(tileSize, smallestTileSize);
|
|
55
63
|
|
|
@@ -2,7 +2,7 @@ import Typography from '@mui/material/Typography';
|
|
|
2
2
|
|
|
3
3
|
import { useMemoComponent } from '@centreon/ui';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { useLineChartStyles } from '../LineChart.styles';
|
|
6
6
|
import { LineChartHeader } from '../models';
|
|
7
7
|
|
|
8
8
|
interface Props {
|
|
@@ -11,7 +11,7 @@ interface Props {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
const Header = ({ title, header }: Props): JSX.Element => {
|
|
14
|
-
const { classes } =
|
|
14
|
+
const { classes } = useLineChartStyles();
|
|
15
15
|
|
|
16
16
|
const displayTitle = header?.displayTitle ?? true;
|
|
17
17
|
|
|
@@ -3,7 +3,7 @@ import { useEffect, useState } from 'react';
|
|
|
3
3
|
import { ScaleLinear } from 'd3-scale';
|
|
4
4
|
import { useAtomValue } from 'jotai';
|
|
5
5
|
|
|
6
|
-
import useAxisY from '
|
|
6
|
+
import useAxisY from '../../../common/Axes/useAxisY';
|
|
7
7
|
import { margin } from '../../common';
|
|
8
8
|
import { getTimeValue } from '../../../common/timeSeries';
|
|
9
9
|
import { Line, TimeValue } from '../../../common/timeSeries/models';
|