@centreon/ui 23.10.18-MON-17793-create-graph-component-centreon-ui.22 → 23.10.18-MON-17793-create-graph-component-centreon-ui.23
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/Graph/BasicComponents/Axes/index.tsx +2 -2
- package/src/Graph/BasicComponents/Axes/useAxisY.ts +5 -5
- package/src/Graph/BasicComponents/Lines/RegularLines/index.tsx +2 -2
- package/src/Graph/BasicComponents/Lines/StackedLines/index.tsx +2 -16
- package/src/Graph/BasicComponents/Lines/index.tsx +14 -13
- package/src/Graph/BasicComponents/useFilterLines.ts +4 -2
- package/src/Graph/Graph.tsx +18 -4
- package/src/Graph/Header/index.tsx +4 -2
- package/src/Graph/InteractiveComponents/AnchorPoint/AnchorPoint.styles.ts +52 -0
- package/src/Graph/InteractiveComponents/AnchorPoint/GuidingLines.tsx +8 -2
- package/src/Graph/InteractiveComponents/AnchorPoint/RegularAnchorPoint.tsx +1 -1
- package/src/Graph/InteractiveComponents/AnchorPoint/StackedAnchorPoint.tsx +16 -10
- package/src/Graph/InteractiveComponents/AnchorPoint/TooltipAnchorPoint.tsx +68 -0
- package/src/Graph/InteractiveComponents/AnchorPoint/models.ts +24 -1
- package/src/Graph/InteractiveComponents/AnchorPoint/useTickGraph.ts +44 -7
- package/src/Graph/InteractiveComponents/AnchorPoint/useTooltipAnchorPoint.ts +107 -0
- package/src/Graph/InteractiveComponents/TimeShiftZones/TimeShiftIcon.tsx +6 -2
- package/src/Graph/InteractiveComponents/TimeShiftZones/index.tsx +1 -0
- package/src/Graph/InteractiveComponents/Tooltip/useGraphTooltip.ts +4 -14
- package/src/Graph/Legend/useLegend.ts +5 -2
- package/src/Graph/helpers/doc.ts +29 -4
- package/src/Graph/helpers/index.ts +12 -2
- package/src/Graph/index.stories.tsx +1 -1
- package/src/Graph/mockedData/lastDay.json +1282 -614
- package/src/Graph/models.ts +14 -1
- package/src/Graph/useGraphData.ts +2 -2
- package/src/utils/useIntersectionObserver.ts +4 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@centreon/ui",
|
|
3
|
-
"version": "23.10.18-MON-17793-create-graph-component-centreon-ui.
|
|
3
|
+
"version": "23.10.18-MON-17793-create-graph-component-centreon-ui.23",
|
|
4
4
|
"description": "Centreon UI Components",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"eslint": "eslint ./src --ext .js,.jsx,.ts,.tsx --max-warnings 0",
|
|
@@ -61,7 +61,7 @@ const Axes = ({
|
|
|
61
61
|
{axisLeft.displayUnit && <UnitLabel unit={firstUnit} x={-4} />}
|
|
62
62
|
|
|
63
63
|
<Axis.AxisLeft
|
|
64
|
-
numTicks={axisLeft
|
|
64
|
+
numTicks={axisLeft?.numTicks}
|
|
65
65
|
orientation="left"
|
|
66
66
|
scale={leftScale}
|
|
67
67
|
tickFormat={axisLeft.tickFormat}
|
|
@@ -72,7 +72,7 @@ const Axes = ({
|
|
|
72
72
|
{displayAxisRight && (
|
|
73
73
|
<Axis.AxisRight
|
|
74
74
|
left={width}
|
|
75
|
-
numTicks={axisRight
|
|
75
|
+
numTicks={axisRight?.numTicks}
|
|
76
76
|
orientation="right"
|
|
77
77
|
scale={rightScale}
|
|
78
78
|
tickFormat={axisRight.tickFormat}
|
|
@@ -10,8 +10,8 @@ import { Data, LabelProps } from './models';
|
|
|
10
10
|
|
|
11
11
|
interface AxisYData {
|
|
12
12
|
displayUnit: boolean;
|
|
13
|
-
numTicks
|
|
14
|
-
tickFormat:
|
|
13
|
+
numTicks?: number;
|
|
14
|
+
tickFormat: (value: unknown) => string;
|
|
15
15
|
tickLabelProps: Axis.TickLabelProps<unknown>;
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -25,8 +25,8 @@ interface AxisY {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
interface Props {
|
|
28
|
-
data: Data
|
|
29
|
-
graphHeight
|
|
28
|
+
data: Omit<Data, 'timeSeries'>;
|
|
29
|
+
graphHeight?: number;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
const useAxisY = ({ data, graphHeight }: Props): AxisY => {
|
|
@@ -35,7 +35,7 @@ const useAxisY = ({ data, graphHeight }: Props): AxisY => {
|
|
|
35
35
|
const { lines } = data;
|
|
36
36
|
const [firstUnit, secondUnit, thirdUnit] = getUnits(lines);
|
|
37
37
|
|
|
38
|
-
const numTicks = Math.ceil(graphHeight / 30);
|
|
38
|
+
const numTicks = graphHeight && Math.ceil(graphHeight / 30);
|
|
39
39
|
|
|
40
40
|
const hasMoreThanTwoUnits = !isNil(thirdUnit);
|
|
41
41
|
const hasTwoUnits = !isNil(secondUnit) && !hasMoreThanTwoUnits;
|
|
@@ -37,13 +37,13 @@ const RegularLine = ({
|
|
|
37
37
|
transparency,
|
|
38
38
|
graphHeight
|
|
39
39
|
}: Props): JSX.Element => {
|
|
40
|
-
const isHighlighted = highlight ?
|
|
40
|
+
const isHighlighted = highlight ? 3 : 1;
|
|
41
41
|
|
|
42
42
|
const props = {
|
|
43
43
|
curve: Curve.curveLinear,
|
|
44
44
|
data: timeSeries,
|
|
45
45
|
defined: (value): boolean => !isNil(value[metric]),
|
|
46
|
-
opacity: !highlight ?
|
|
46
|
+
opacity: !highlight ? 1 : 3,
|
|
47
47
|
stroke: lineColor,
|
|
48
48
|
strokeWidth: isHighlighted,
|
|
49
49
|
unit,
|
|
@@ -4,15 +4,12 @@ import { all, isNil, map, not, nth, path, pipe, prop } from 'ramda';
|
|
|
4
4
|
|
|
5
5
|
import StackedAnchorPoint from '../../../InteractiveComponents/AnchorPoint/StackedAnchorPoint';
|
|
6
6
|
import { StackValue } from '../../../InteractiveComponents/AnchorPoint/models';
|
|
7
|
-
import useTickGraph from '../../../InteractiveComponents/AnchorPoint/useTickGraph';
|
|
8
7
|
import { getFillColor } from '../../../common';
|
|
9
8
|
import { getTime } from '../../../timeSeries';
|
|
10
9
|
import { Line, TimeValue } from '../../../timeSeries/models';
|
|
11
10
|
|
|
12
11
|
interface Props {
|
|
13
12
|
displayAnchor: boolean;
|
|
14
|
-
graphHeight: number;
|
|
15
|
-
graphWidth: number;
|
|
16
13
|
lines: Array<Line>;
|
|
17
14
|
timeSeries: Array<TimeValue>;
|
|
18
15
|
xScale: ScaleTime<number, number>;
|
|
@@ -24,15 +21,8 @@ const StackLines = ({
|
|
|
24
21
|
lines,
|
|
25
22
|
yScale,
|
|
26
23
|
xScale,
|
|
27
|
-
displayAnchor
|
|
28
|
-
graphHeight,
|
|
29
|
-
graphWidth
|
|
24
|
+
displayAnchor
|
|
30
25
|
}: Props): JSX.Element => {
|
|
31
|
-
const { timeTick, positionX, positionY } = useTickGraph({
|
|
32
|
-
timeSeries,
|
|
33
|
-
xScale
|
|
34
|
-
});
|
|
35
|
-
|
|
36
26
|
return (
|
|
37
27
|
<Shape.AreaStack
|
|
38
28
|
curve={Curve.curveLinear}
|
|
@@ -60,13 +50,9 @@ const StackLines = ({
|
|
|
60
50
|
{displayAnchor && (
|
|
61
51
|
<StackedAnchorPoint
|
|
62
52
|
areaColor={areaColor}
|
|
63
|
-
graphHeight={graphHeight}
|
|
64
|
-
graphWidth={graphWidth}
|
|
65
53
|
lineColor={lineColor}
|
|
66
|
-
positionX={positionX}
|
|
67
|
-
positionY={positionY}
|
|
68
54
|
stackValues={stack as unknown as Array<StackValue>}
|
|
69
|
-
|
|
55
|
+
timeSeries={timeSeries}
|
|
70
56
|
transparency={transparency}
|
|
71
57
|
xScale={xScale}
|
|
72
58
|
yScale={yScale}
|
|
@@ -6,7 +6,7 @@ import { isNil } from 'ramda';
|
|
|
6
6
|
import GuidingLines from '../../InteractiveComponents/AnchorPoint/GuidingLines';
|
|
7
7
|
import RegularAnchorPoint from '../../InteractiveComponents/AnchorPoint/RegularAnchorPoint';
|
|
8
8
|
import { displayArea } from '../../helpers/index';
|
|
9
|
-
import { GlobalAreaLines } from '../../models';
|
|
9
|
+
import { DisplayAnchor, GlobalAreaLines } from '../../models';
|
|
10
10
|
import { getStackedYScale, getUnits, getYScale } from '../../timeSeries';
|
|
11
11
|
import { Line, TimeValue } from '../../timeSeries/models';
|
|
12
12
|
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
} from './Threshold/models';
|
|
22
22
|
|
|
23
23
|
interface Props extends GlobalAreaLines {
|
|
24
|
-
displayAnchor
|
|
24
|
+
displayAnchor?: DisplayAnchor;
|
|
25
25
|
displayedLines: Array<Line>;
|
|
26
26
|
graphSvgRef: MutableRefObject<SVGSVGElement | null>;
|
|
27
27
|
height: number;
|
|
@@ -65,8 +65,9 @@ const Lines = ({
|
|
|
65
65
|
rightScale
|
|
66
66
|
});
|
|
67
67
|
|
|
68
|
+
const displayGuidingLines = displayAnchor?.displayGuidingLines ?? true;
|
|
68
69
|
const commonStackedLinesProps = {
|
|
69
|
-
displayAnchor,
|
|
70
|
+
displayAnchor: displayGuidingLines,
|
|
70
71
|
graphHeight: height,
|
|
71
72
|
graphSvgRef,
|
|
72
73
|
graphWidth: width,
|
|
@@ -76,6 +77,15 @@ const Lines = ({
|
|
|
76
77
|
|
|
77
78
|
return (
|
|
78
79
|
<g>
|
|
80
|
+
{displayGuidingLines && (
|
|
81
|
+
<GuidingLines
|
|
82
|
+
graphHeight={height}
|
|
83
|
+
graphWidth={width}
|
|
84
|
+
timeSeries={timeSeries}
|
|
85
|
+
xScale={xScale}
|
|
86
|
+
/>
|
|
87
|
+
)}
|
|
88
|
+
|
|
79
89
|
{(areaStackedLines?.display ?? true) && (
|
|
80
90
|
<>
|
|
81
91
|
{displayArea(stackedLinesData.lines) && (
|
|
@@ -108,15 +118,6 @@ const Lines = ({
|
|
|
108
118
|
/>
|
|
109
119
|
)}
|
|
110
120
|
|
|
111
|
-
{displayAnchor && (
|
|
112
|
-
<GuidingLines
|
|
113
|
-
graphHeight={height}
|
|
114
|
-
graphWidth={width}
|
|
115
|
-
timeSeries={timeSeries}
|
|
116
|
-
xScale={xScale}
|
|
117
|
-
/>
|
|
118
|
-
)}
|
|
119
|
-
|
|
120
121
|
{displayAreaRegularLines
|
|
121
122
|
? regularLines.map(
|
|
122
123
|
({
|
|
@@ -143,7 +144,7 @@ const Lines = ({
|
|
|
143
144
|
|
|
144
145
|
return (
|
|
145
146
|
<g key={metric}>
|
|
146
|
-
{
|
|
147
|
+
{displayGuidingLines && (
|
|
147
148
|
<RegularAnchorPoint
|
|
148
149
|
areaColor={areaColor}
|
|
149
150
|
lineColor={lineColor}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useEffect } from 'react';
|
|
2
2
|
|
|
3
3
|
import { useAtom } from 'jotai';
|
|
4
|
-
import { equals, propEq, reject } from 'ramda';
|
|
4
|
+
import { compose, equals, prop, propEq, reject, sortBy, toLower } from 'ramda';
|
|
5
5
|
|
|
6
6
|
import { linesGraphAtom } from '../graphAtoms';
|
|
7
7
|
import { Line } from '../timeSeries/models';
|
|
@@ -49,7 +49,9 @@ const useFilterLines = ({
|
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
const sortedLines = sortBy(compose(toLower, prop('name')), filteredLines);
|
|
53
|
+
|
|
54
|
+
setLinesGraph(sortedLines);
|
|
53
55
|
}, [lines, displayThreshold]);
|
|
54
56
|
|
|
55
57
|
return { displayedLines, newLines: linesGraph ?? lines };
|
package/src/Graph/Graph.tsx
CHANGED
|
@@ -8,11 +8,13 @@ import { ClickAwayListener, Skeleton } from '@mui/material';
|
|
|
8
8
|
import Axes from './BasicComponents/Axes';
|
|
9
9
|
import Grids from './BasicComponents/Grids';
|
|
10
10
|
import Lines from './BasicComponents/Lines';
|
|
11
|
+
import { canDisplayThreshold } from './BasicComponents/Lines/Threshold/models';
|
|
11
12
|
import LoadingProgress from './BasicComponents/LoadingProgress';
|
|
12
13
|
import useFilterLines from './BasicComponents/useFilterLines';
|
|
13
14
|
import { useStyles } from './Graph.styles';
|
|
14
15
|
import Header from './Header';
|
|
15
16
|
import InteractionWithGraph from './InteractiveComponents';
|
|
17
|
+
import TooltipAnchorPoint from './InteractiveComponents/AnchorPoint/TooltipAnchorPoint';
|
|
16
18
|
import GraphTooltip from './InteractiveComponents/Tooltip';
|
|
17
19
|
import useGraphTooltip from './InteractiveComponents/Tooltip/useGraphTooltip';
|
|
18
20
|
import Legend from './Legend';
|
|
@@ -26,7 +28,6 @@ import {
|
|
|
26
28
|
} from './models';
|
|
27
29
|
import { getLeftScale, getRightScale, getXScale } from './timeSeries';
|
|
28
30
|
import { useIntersection } from './useGraphIntersection';
|
|
29
|
-
import { canDisplayThreshold } from './BasicComponents/Lines/Threshold/models';
|
|
30
31
|
|
|
31
32
|
interface Props extends GraphProps {
|
|
32
33
|
graphData: Data;
|
|
@@ -42,7 +43,7 @@ const Graph = ({
|
|
|
42
43
|
width,
|
|
43
44
|
shapeLines,
|
|
44
45
|
axis,
|
|
45
|
-
displayAnchor
|
|
46
|
+
displayAnchor,
|
|
46
47
|
loading,
|
|
47
48
|
zoomPreview,
|
|
48
49
|
graphInterval,
|
|
@@ -119,7 +120,7 @@ const Graph = ({
|
|
|
119
120
|
return (
|
|
120
121
|
<>
|
|
121
122
|
<Header
|
|
122
|
-
displayTimeTick={displayAnchor}
|
|
123
|
+
displayTimeTick={displayAnchor?.displayGuidingLines ?? true}
|
|
123
124
|
header={header}
|
|
124
125
|
timeSeries={timeSeries}
|
|
125
126
|
title={title}
|
|
@@ -185,10 +186,23 @@ const Graph = ({
|
|
|
185
186
|
{displayTooltip && (
|
|
186
187
|
<GraphTooltip {...tooltip} {...graphTooltipData} />
|
|
187
188
|
)}
|
|
189
|
+
{(displayAnchor?.displayTooltipsGuidingLines ?? true) && (
|
|
190
|
+
<TooltipAnchorPoint
|
|
191
|
+
baseAxis={baseAxis}
|
|
192
|
+
graphHeight={graphHeight}
|
|
193
|
+
graphWidth={graphWidth}
|
|
194
|
+
leftScale={leftScale}
|
|
195
|
+
lines={displayedLines}
|
|
196
|
+
rightScale={rightScale}
|
|
197
|
+
timeSeries={timeSeries}
|
|
198
|
+
xScale={xScale}
|
|
199
|
+
/>
|
|
200
|
+
)}
|
|
201
|
+
|
|
188
202
|
{displayLegend && (
|
|
189
203
|
<Legend
|
|
190
204
|
base={baseAxis}
|
|
191
|
-
displayAnchor={displayAnchor}
|
|
205
|
+
displayAnchor={displayAnchor?.displayGuidingLines ?? true}
|
|
192
206
|
lines={newLines}
|
|
193
207
|
renderExtraComponent={legend?.renderExtraComponent}
|
|
194
208
|
timeSeries={timeSeries}
|
|
@@ -28,12 +28,14 @@ const Header = ({
|
|
|
28
28
|
const { classes } = useStyles();
|
|
29
29
|
const { toDateTime } = useLocaleDateTimeFormat();
|
|
30
30
|
|
|
31
|
-
const {
|
|
31
|
+
const { tickAxisBottom } = useTickGraph({
|
|
32
32
|
timeSeries,
|
|
33
33
|
xScale
|
|
34
34
|
});
|
|
35
35
|
const time =
|
|
36
|
-
displayTimeTick && !isNil(
|
|
36
|
+
displayTimeTick && !isNil(tickAxisBottom)
|
|
37
|
+
? toDateTime(tickAxisBottom)
|
|
38
|
+
: null;
|
|
37
39
|
|
|
38
40
|
const displayTitle = header?.displayTitle ?? true;
|
|
39
41
|
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { makeStyles } from 'tss-react/mui';
|
|
2
|
+
|
|
3
|
+
interface StylesProps {
|
|
4
|
+
tooltipLeftAxisX?: number;
|
|
5
|
+
tooltipLeftAxisYLeft?: number;
|
|
6
|
+
tooltipLeftAxisYRight?: number;
|
|
7
|
+
tooltipTopAxisX?: number;
|
|
8
|
+
tooltipTopAxisYLeft?: number;
|
|
9
|
+
tooltipTopAxisYRight?: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const useStyles = makeStyles<StylesProps>()(
|
|
13
|
+
(
|
|
14
|
+
theme,
|
|
15
|
+
{
|
|
16
|
+
tooltipLeftAxisX,
|
|
17
|
+
tooltipTopAxisX,
|
|
18
|
+
tooltipLeftAxisYLeft,
|
|
19
|
+
tooltipTopAxisYLeft,
|
|
20
|
+
tooltipLeftAxisYRight,
|
|
21
|
+
tooltipTopAxisYRight
|
|
22
|
+
}
|
|
23
|
+
) => ({
|
|
24
|
+
tooltipAxisBottom: {
|
|
25
|
+
backgroundColor: theme.palette.background.listingHeader,
|
|
26
|
+
color: theme.palette.common.white,
|
|
27
|
+
left: tooltipLeftAxisX ?? 0,
|
|
28
|
+
minWidth: theme.spacing(5.5),
|
|
29
|
+
position: 'absolute',
|
|
30
|
+
textAlign: 'center',
|
|
31
|
+
top: tooltipTopAxisX ?? 0
|
|
32
|
+
},
|
|
33
|
+
tooltipAxisLeftY: {
|
|
34
|
+
backgroundColor: theme.palette.background.listingHeader,
|
|
35
|
+
color: theme.palette.common.white,
|
|
36
|
+
left: tooltipLeftAxisYLeft ?? 0,
|
|
37
|
+
minWidth: theme.spacing(3),
|
|
38
|
+
position: 'absolute',
|
|
39
|
+
textAlign: 'center',
|
|
40
|
+
top: tooltipTopAxisYLeft ?? 0
|
|
41
|
+
},
|
|
42
|
+
tooltipLeftAxisRightY: {
|
|
43
|
+
backgroundColor: theme.palette.background.listingHeader,
|
|
44
|
+
color: theme.palette.common.white,
|
|
45
|
+
left: tooltipLeftAxisYRight ?? 0,
|
|
46
|
+
minWidth: theme.spacing(3),
|
|
47
|
+
position: 'absolute',
|
|
48
|
+
textAlign: 'center',
|
|
49
|
+
top: tooltipTopAxisYRight ?? 0
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
);
|
|
@@ -2,26 +2,31 @@ import { Shape } from '@visx/visx';
|
|
|
2
2
|
|
|
3
3
|
import { grey } from '@mui/material/colors';
|
|
4
4
|
|
|
5
|
-
import useTickGraph from './useTickGraph';
|
|
6
5
|
import { GuidingLines } from './models';
|
|
6
|
+
import useTickGraph from './useTickGraph';
|
|
7
7
|
|
|
8
8
|
const GuidingLines = ({
|
|
9
9
|
timeSeries,
|
|
10
10
|
xScale,
|
|
11
11
|
graphHeight,
|
|
12
12
|
graphWidth
|
|
13
|
-
}: GuidingLines): JSX.Element => {
|
|
13
|
+
}: GuidingLines): JSX.Element | null => {
|
|
14
14
|
const { positionX, positionY } = useTickGraph({
|
|
15
15
|
timeSeries,
|
|
16
16
|
xScale
|
|
17
17
|
});
|
|
18
|
+
if (!positionX || !positionY) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
18
21
|
|
|
19
22
|
return (
|
|
20
23
|
<>
|
|
21
24
|
<Shape.Line
|
|
25
|
+
fill="dotted"
|
|
22
26
|
from={{ x: positionX, y: 0 }}
|
|
23
27
|
pointerEvents="none"
|
|
24
28
|
stroke={grey[400]}
|
|
29
|
+
strokeDasharray="5,2"
|
|
25
30
|
strokeWidth={1}
|
|
26
31
|
to={{ x: positionX, y: graphHeight }}
|
|
27
32
|
/>
|
|
@@ -29,6 +34,7 @@ const GuidingLines = ({
|
|
|
29
34
|
from={{ x: 0, y: positionY }}
|
|
30
35
|
pointerEvents="none"
|
|
31
36
|
stroke={grey[400]}
|
|
37
|
+
strokeDasharray="5,2"
|
|
32
38
|
strokeWidth={1}
|
|
33
39
|
to={{ x: graphWidth, y: positionY }}
|
|
34
40
|
/>
|
|
@@ -2,24 +2,27 @@ import { ScaleLinear, ScaleTime } from 'd3-scale';
|
|
|
2
2
|
import { isNil, map, pipe } from 'ramda';
|
|
3
3
|
|
|
4
4
|
import { bisectDate } from '../../timeSeries';
|
|
5
|
+
import { TimeValue } from '../../timeSeries/models';
|
|
5
6
|
|
|
6
7
|
import { StackValue } from './models';
|
|
8
|
+
import useTickGraph from './useTickGraph';
|
|
7
9
|
|
|
8
10
|
import AnchorPoint from '.';
|
|
9
11
|
|
|
10
12
|
interface Props {
|
|
11
13
|
areaColor: string;
|
|
12
|
-
graphHeight: number;
|
|
13
|
-
graphWidth: number;
|
|
14
14
|
lineColor: string;
|
|
15
|
-
positionX?: number;
|
|
16
|
-
positionY?: number;
|
|
17
15
|
stackValues: Array<StackValue>;
|
|
18
|
-
|
|
16
|
+
timeSeries: Array<TimeValue>;
|
|
19
17
|
transparency: number;
|
|
20
18
|
xScale: ScaleTime<number, number>;
|
|
21
19
|
yScale: ScaleLinear<number, number>;
|
|
22
20
|
}
|
|
21
|
+
interface GetYAnchorPoint {
|
|
22
|
+
stackValues: Array<StackValue>;
|
|
23
|
+
timeTick: Date | null;
|
|
24
|
+
yScale: ScaleTime<number, number>;
|
|
25
|
+
}
|
|
23
26
|
|
|
24
27
|
const getStackedDates = (stackValues: Array<StackValue>): Array<Date> => {
|
|
25
28
|
const toTimeTick = (stackValue: StackValue): string =>
|
|
@@ -34,7 +37,7 @@ const getYAnchorPoint = ({
|
|
|
34
37
|
timeTick,
|
|
35
38
|
stackValues,
|
|
36
39
|
yScale
|
|
37
|
-
}:
|
|
40
|
+
}: GetYAnchorPoint): number => {
|
|
38
41
|
const index = bisectDate(getStackedDates(stackValues), timeTick);
|
|
39
42
|
const timeValue = stackValues[index];
|
|
40
43
|
|
|
@@ -45,12 +48,16 @@ const StackedAnchorPoint = ({
|
|
|
45
48
|
xScale,
|
|
46
49
|
yScale,
|
|
47
50
|
stackValues,
|
|
48
|
-
|
|
51
|
+
timeSeries,
|
|
49
52
|
areaColor,
|
|
50
53
|
transparency,
|
|
51
|
-
lineColor
|
|
52
|
-
...rest
|
|
54
|
+
lineColor
|
|
53
55
|
}: Props): JSX.Element | null => {
|
|
56
|
+
const { tickAxisBottom: timeTick } = useTickGraph({
|
|
57
|
+
timeSeries,
|
|
58
|
+
xScale
|
|
59
|
+
});
|
|
60
|
+
|
|
54
61
|
if (isNil(timeTick)) {
|
|
55
62
|
return null;
|
|
56
63
|
}
|
|
@@ -73,7 +80,6 @@ const StackedAnchorPoint = ({
|
|
|
73
80
|
transparency={transparency}
|
|
74
81
|
x={xAnchorPoint}
|
|
75
82
|
y={yAnchorPoint}
|
|
76
|
-
{...rest}
|
|
77
83
|
/>
|
|
78
84
|
);
|
|
79
85
|
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import Paper from '@mui/material/Paper';
|
|
2
|
+
import { Typography } from '@mui/material';
|
|
3
|
+
|
|
4
|
+
import useTooltipAnchorPoint from './useTooltipAnchorPoint';
|
|
5
|
+
import { useStyles } from './AnchorPoint.styles';
|
|
6
|
+
import { TooltipAnchorModel } from './models';
|
|
7
|
+
|
|
8
|
+
const TooltipAnchorPoint = ({
|
|
9
|
+
timeSeries,
|
|
10
|
+
xScale,
|
|
11
|
+
graphHeight,
|
|
12
|
+
leftScale,
|
|
13
|
+
rightScale,
|
|
14
|
+
graphWidth,
|
|
15
|
+
lines,
|
|
16
|
+
baseAxis
|
|
17
|
+
}: TooltipAnchorModel): JSX.Element => {
|
|
18
|
+
const {
|
|
19
|
+
tooltipDataAxisX,
|
|
20
|
+
tooltipDataAxisYLeft,
|
|
21
|
+
tooltipLeftAxisX,
|
|
22
|
+
tooltipLeftAxisYLeft,
|
|
23
|
+
tooltipTopAxisX,
|
|
24
|
+
tooltipTopAxisYLeft,
|
|
25
|
+
tooltipDataAxisYRight,
|
|
26
|
+
tooltipTopAxisYRight,
|
|
27
|
+
tooltipLeftAxisYRight
|
|
28
|
+
} = useTooltipAnchorPoint({
|
|
29
|
+
baseAxis,
|
|
30
|
+
graphHeight,
|
|
31
|
+
graphWidth,
|
|
32
|
+
leftScale,
|
|
33
|
+
lines,
|
|
34
|
+
rightScale,
|
|
35
|
+
timeSeries,
|
|
36
|
+
xScale
|
|
37
|
+
});
|
|
38
|
+
const { classes } = useStyles({
|
|
39
|
+
tooltipLeftAxisX,
|
|
40
|
+
tooltipLeftAxisYLeft,
|
|
41
|
+
tooltipLeftAxisYRight,
|
|
42
|
+
tooltipTopAxisX,
|
|
43
|
+
tooltipTopAxisYLeft,
|
|
44
|
+
tooltipTopAxisYRight
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<>
|
|
49
|
+
{tooltipDataAxisYLeft && (
|
|
50
|
+
<Paper className={classes.tooltipAxisLeftY}>
|
|
51
|
+
<Typography variant="caption">{tooltipDataAxisYLeft}</Typography>
|
|
52
|
+
</Paper>
|
|
53
|
+
)}
|
|
54
|
+
{tooltipDataAxisX && (
|
|
55
|
+
<Paper className={classes.tooltipAxisBottom}>
|
|
56
|
+
<Typography variant="caption">{tooltipDataAxisX}</Typography>
|
|
57
|
+
</Paper>
|
|
58
|
+
)}
|
|
59
|
+
{tooltipDataAxisYRight && (
|
|
60
|
+
<Paper className={classes.tooltipLeftAxisRightY}>
|
|
61
|
+
<Typography variant="caption">{tooltipDataAxisYRight}</Typography>
|
|
62
|
+
</Paper>
|
|
63
|
+
)}
|
|
64
|
+
</>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export default TooltipAnchorPoint;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ScaleLinear, ScaleTime } from 'd3-scale';
|
|
2
2
|
|
|
3
|
-
import { TimeValue } from '../../timeSeries/models';
|
|
3
|
+
import { Line, TimeValue } from '../../timeSeries/models';
|
|
4
4
|
|
|
5
5
|
interface AnchorPoint {
|
|
6
6
|
areaColor: string;
|
|
@@ -37,3 +37,26 @@ export interface GetYAnchorPoint {
|
|
|
37
37
|
timeTick: Date;
|
|
38
38
|
yScale: ScaleLinear<number, number>;
|
|
39
39
|
}
|
|
40
|
+
|
|
41
|
+
export interface UseTooltipAnchorPointResult {
|
|
42
|
+
tooltipDataAxisX?: string | null;
|
|
43
|
+
tooltipDataAxisYLeft?: number | null;
|
|
44
|
+
tooltipDataAxisYRight?: number | null;
|
|
45
|
+
tooltipLeftAxisX?: number;
|
|
46
|
+
tooltipLeftAxisYLeft?: number;
|
|
47
|
+
tooltipLeftAxisYRight?: number;
|
|
48
|
+
tooltipTopAxisX?: number;
|
|
49
|
+
tooltipTopAxisYLeft?: number;
|
|
50
|
+
tooltipTopAxisYRight?: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface TooltipAnchorModel {
|
|
54
|
+
baseAxis: number;
|
|
55
|
+
graphHeight: number;
|
|
56
|
+
graphWidth?: number;
|
|
57
|
+
leftScale?: ScaleLinear<number, number>;
|
|
58
|
+
lines: Array<Line>;
|
|
59
|
+
rightScale?: ScaleLinear<number, number>;
|
|
60
|
+
timeSeries: Array<TimeValue>;
|
|
61
|
+
xScale: ScaleLinear<number, number>;
|
|
62
|
+
}
|
|
@@ -4,24 +4,43 @@ import { ScaleLinear } from 'd3-scale';
|
|
|
4
4
|
import { useAtomValue } from 'jotai';
|
|
5
5
|
import { isEmpty, isNil, not } from 'ramda';
|
|
6
6
|
|
|
7
|
+
import useAxisY from '../../BasicComponents/Axes/useAxisY';
|
|
7
8
|
import { margin } from '../../common';
|
|
8
9
|
import { getMetrics, getTimeValue } from '../../timeSeries';
|
|
9
|
-
import { TimeValue } from '../../timeSeries/models';
|
|
10
|
+
import { Line, TimeValue } from '../../timeSeries/models';
|
|
10
11
|
import { mousePositionAtom, timeValueAtom } from '../interactionWithGraphAtoms';
|
|
11
12
|
|
|
12
13
|
interface AnchorPointResult {
|
|
13
14
|
positionX?: number;
|
|
14
15
|
positionY?: number;
|
|
15
|
-
|
|
16
|
+
tickAxisBottom: Date | null;
|
|
17
|
+
tickAxisLeft: string | null;
|
|
18
|
+
tickAxisRight: string | null;
|
|
16
19
|
}
|
|
17
20
|
|
|
18
21
|
interface Props {
|
|
22
|
+
baseAxis?: number;
|
|
23
|
+
leftScale?: ScaleLinear<number, number>;
|
|
24
|
+
lines?: Array<Line>;
|
|
25
|
+
rightScale?: ScaleLinear<number, number>;
|
|
19
26
|
timeSeries: Array<TimeValue>;
|
|
20
27
|
xScale: ScaleLinear<number, number>;
|
|
21
28
|
}
|
|
22
29
|
|
|
23
|
-
const useTickGraph = ({
|
|
24
|
-
|
|
30
|
+
const useTickGraph = ({
|
|
31
|
+
timeSeries,
|
|
32
|
+
xScale,
|
|
33
|
+
leftScale,
|
|
34
|
+
rightScale,
|
|
35
|
+
lines = [],
|
|
36
|
+
baseAxis = 1000
|
|
37
|
+
}: Props): AnchorPointResult => {
|
|
38
|
+
const [tickAxisBottom, setTickAxisBottom] = useState<Date | null>(null);
|
|
39
|
+
const [tickAxisLeft, setTickAxisLeft] = useState<string | null>(null);
|
|
40
|
+
const [tickAxisRight, setTickAxisRight] = useState<string | null>(null);
|
|
41
|
+
|
|
42
|
+
const { axisRight, axisLeft } = useAxisY({ data: { baseAxis, lines } });
|
|
43
|
+
|
|
25
44
|
const mousePosition = useAtomValue(mousePositionAtom);
|
|
26
45
|
const timeValueData = useAtomValue(timeValueAtom);
|
|
27
46
|
|
|
@@ -34,7 +53,9 @@ const useTickGraph = ({ timeSeries, xScale }: Props): AnchorPointResult => {
|
|
|
34
53
|
|
|
35
54
|
useEffect(() => {
|
|
36
55
|
if (!mousePosition) {
|
|
37
|
-
|
|
56
|
+
setTickAxisBottom(null);
|
|
57
|
+
setTickAxisLeft(null);
|
|
58
|
+
setTickAxisRight(null);
|
|
38
59
|
|
|
39
60
|
return;
|
|
40
61
|
}
|
|
@@ -45,13 +66,29 @@ const useTickGraph = ({ timeSeries, xScale }: Props): AnchorPointResult => {
|
|
|
45
66
|
? new Date(mousePositionTimeTick)
|
|
46
67
|
: null;
|
|
47
68
|
|
|
48
|
-
|
|
69
|
+
setTickAxisBottom(timeTickValue);
|
|
70
|
+
|
|
71
|
+
const valueTickAxisLeft = leftScale?.invert(positionY);
|
|
72
|
+
const formattedTickAxisLeft = axisLeft?.tickFormat?.(valueTickAxisLeft);
|
|
73
|
+
|
|
74
|
+
setTickAxisLeft(formattedTickAxisLeft);
|
|
75
|
+
|
|
76
|
+
if (!axisRight.display) {
|
|
77
|
+
setTickAxisRight(null);
|
|
78
|
+
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const valueTickAxisRight = rightScale?.invert(positionY);
|
|
82
|
+
const formattedTickAxisRight = axisRight?.tickFormat?.(valueTickAxisRight);
|
|
83
|
+
setTickAxisRight(formattedTickAxisRight);
|
|
49
84
|
}, [mousePosition]);
|
|
50
85
|
|
|
51
86
|
return {
|
|
52
87
|
positionX,
|
|
53
88
|
positionY,
|
|
54
|
-
|
|
89
|
+
tickAxisBottom,
|
|
90
|
+
tickAxisLeft,
|
|
91
|
+
tickAxisRight
|
|
55
92
|
};
|
|
56
93
|
};
|
|
57
94
|
export default useTickGraph;
|