mirror of
https://github.com/openmhz/trunk-server.git
synced 2026-11-13 09:17:30 -05:00
better graphs - group modal fix - system list
This commit is contained in:
@@ -9,7 +9,7 @@ import { useSelector, useDispatch } from 'react-redux'
|
||||
import { setFilter, setDateFilter } from "../features/callPlayer/callPlayerSlice";
|
||||
|
||||
import { useGetStatsQuery,useGetTalkgroupsQuery } from '../features/api/apiSlice'
|
||||
import ActivityChart from "./ActivityChart";
|
||||
import ActivityChart from "./BetterActivityChart";
|
||||
import { selectSystem } from "../features/systems/systemsSlice";
|
||||
import {
|
||||
Container,
|
||||
|
||||
524
frontend/src/Call/BetterActivityChart.js
Normal file
524
frontend/src/Call/BetterActivityChart.js
Normal file
@@ -0,0 +1,524 @@
|
||||
import React, { useMemo, useCallback } from 'react';
|
||||
import { AreaClosed, Line, Bar } from '@visx/shape';
|
||||
import appleStock, { AppleStock } from '@visx/mock-data/lib/mocks/appleStock';
|
||||
import { curveMonotoneX } from '@visx/curve';
|
||||
import { GridRows, GridColumns } from '@visx/grid';
|
||||
import { scaleTime, scaleLinear } from '@visx/scale';
|
||||
import { withTooltip, Tooltip, TooltipWithBounds, defaultStyles } from '@visx/tooltip';
|
||||
import { useTooltip, useTooltipInPortal } from '@visx/tooltip';
|
||||
import { Loader } from "semantic-ui-react";
|
||||
import { WithTooltipProvidedProps } from '@visx/tooltip/lib/enhancers/withTooltip';
|
||||
import { localPoint } from '@visx/event';
|
||||
import { LinearGradient } from '@visx/gradient';
|
||||
import { max, extent, bisector } from 'd3-array';
|
||||
import { timeFormat } from 'd3-time-format';
|
||||
|
||||
const data = [
|
||||
0,
|
||||
3,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
6,
|
||||
5,
|
||||
2,
|
||||
7,
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
];
|
||||
|
||||
export const background = '#3b6978';
|
||||
export const background2 = '#204051';
|
||||
export const accentColor = '#edffea';
|
||||
export const accentColorDark = '#75daad';
|
||||
const tooltipStyles = {
|
||||
...defaultStyles,
|
||||
background,
|
||||
border: '1px solid white',
|
||||
color: 'white',
|
||||
};
|
||||
|
||||
// util
|
||||
const formatDate = timeFormat("%b %d, %H:%m");
|
||||
|
||||
// accessors
|
||||
const getDate = (d) => {
|
||||
return d.x;
|
||||
}
|
||||
const getCallActivity = (d) => {
|
||||
return d.y;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const ChartWithTooltip = () => {
|
||||
const props = {data};
|
||||
const {
|
||||
tooltipData,
|
||||
tooltipLeft,
|
||||
tooltipTop,
|
||||
tooltipOpen,
|
||||
showTooltip,
|
||||
hideTooltip,
|
||||
} = useTooltip();
|
||||
const width = 500;
|
||||
const height = 250;
|
||||
// If you don't want to use a Portal, simply replace `TooltipInPortal` below with
|
||||
// `Tooltip` or `TooltipWithBounds` and remove `containerRef`
|
||||
const { containerRef, TooltipInPortal } = useTooltipInPortal({
|
||||
// use TooltipWithBounds
|
||||
detectBounds: true,
|
||||
// when tooltip containers are scrolled, this will correctly update the Tooltip position
|
||||
scroll: true,
|
||||
})
|
||||
const bisectDate = bisector((d) => d.x).left;
|
||||
|
||||
const getMouseData = (event) => {
|
||||
const coords = localPoint(event.target.ownerSVGElement, event);
|
||||
const { x } = coords;
|
||||
|
||||
const x0 = dateScale.invert(x);
|
||||
const index = bisectDate(calls, x0, 1);
|
||||
const d0 = calls[index - 1];
|
||||
const d1 = calls[index];
|
||||
let d = d0;
|
||||
if (d1 && getDate(d1)) {
|
||||
d = x0.valueOf() - getDate(d0).valueOf() > getDate(d1).valueOf() - x0.valueOf() ? d1 : d0;
|
||||
}
|
||||
|
||||
return { data: d, coords }
|
||||
}
|
||||
const handleMouseClick = (event) => {
|
||||
const { data } = getMouseData(event);
|
||||
console.log(data);
|
||||
}
|
||||
const handleMouseOver = (event, datum) => {
|
||||
const { coords, data } = getMouseData(event);
|
||||
showTooltip({
|
||||
tooltipLeft: coords.x,
|
||||
tooltipTop: callActivityScale(getCallActivity(data)),
|
||||
tooltipData: data
|
||||
});
|
||||
};
|
||||
// bounds
|
||||
const margin = { top: 0, right: 0, bottom: 0, left: 0 };
|
||||
const innerWidth = width - margin.left - margin.right;
|
||||
const innerHeight = height - margin.top - margin.bottom;
|
||||
|
||||
const calls = useMemo(
|
||||
() => {
|
||||
let callTotals = [];
|
||||
const now = new Date();
|
||||
var MS_PER_MINUTE = 60000;
|
||||
|
||||
for (let j = 0; j < props.data.length; j++) {
|
||||
let spotsBack = props.data.length - j;
|
||||
let time = new Date(now - spotsBack * 15 * MS_PER_MINUTE);
|
||||
callTotals.push({ y: props.data[j], x: time });
|
||||
}
|
||||
return callTotals
|
||||
|
||||
|
||||
|
||||
|
||||
}, [props.data]
|
||||
);
|
||||
const dateScale = useMemo(
|
||||
() =>
|
||||
scaleTime({
|
||||
range: [margin.left, innerWidth + margin.left],
|
||||
domain: extent(calls, getDate),
|
||||
}),
|
||||
[innerWidth, margin.left],
|
||||
);
|
||||
|
||||
const callActivityScale = useMemo(
|
||||
() => {
|
||||
return scaleLinear({
|
||||
range: [innerHeight + margin.top, margin.top],
|
||||
domain: [0, (max(calls, getCallActivity) || 0)], // + innerHeight / 3],
|
||||
nice: true,
|
||||
})
|
||||
},
|
||||
[margin.top, innerHeight],
|
||||
);
|
||||
|
||||
return (
|
||||
// Set `ref={containerRef}` on the element corresponding to the coordinate system that
|
||||
// `left/top` (passed to `TooltipInPortal`) are relative to.
|
||||
<>
|
||||
<svg ref={containerRef} width={width} height={height}>
|
||||
<rect
|
||||
x={0}
|
||||
y={0}
|
||||
width={width}
|
||||
height={height}
|
||||
fill="url(#area-background-gradient)"
|
||||
rx={14}
|
||||
/>
|
||||
<LinearGradient id="area-background-gradient" from={background} to={background2} />
|
||||
<LinearGradient id="area-gradient" from={accentColor} to={accentColor} toOpacity={0.1} />
|
||||
<GridRows
|
||||
left={margin.left}
|
||||
scale={callActivityScale}
|
||||
width={innerWidth}
|
||||
strokeDasharray="1,3"
|
||||
stroke={accentColor}
|
||||
strokeOpacity={0}
|
||||
pointerEvents="none"
|
||||
/>
|
||||
<GridColumns
|
||||
top={margin.top}
|
||||
scale={dateScale}
|
||||
height={innerHeight}
|
||||
strokeDasharray="1,3"
|
||||
stroke={accentColor}
|
||||
strokeOpacity={0.2}
|
||||
pointerEvents="none"
|
||||
/>
|
||||
<AreaClosed
|
||||
data={calls}
|
||||
x={(d) => dateScale(getDate(d)) ?? 0}
|
||||
y={(d) => callActivityScale(getCallActivity(d)) ?? 0}
|
||||
yScale={callActivityScale}
|
||||
strokeWidth={1}
|
||||
stroke="url(#area-gradient)"
|
||||
fill="url(#area-gradient)"
|
||||
curve={curveMonotoneX}
|
||||
|
||||
/>
|
||||
<Bar
|
||||
x={margin.left}
|
||||
y={margin.top}
|
||||
width={innerWidth}
|
||||
height={innerHeight}
|
||||
fill="transparent"
|
||||
rx={14}
|
||||
onMouseMove={handleMouseOver}
|
||||
onMouseUp={handleMouseClick}
|
||||
onMouseOut={hideTooltip}
|
||||
/>
|
||||
{tooltipData && (
|
||||
<g>
|
||||
<Line
|
||||
from={{ x: tooltipLeft, y: margin.top }}
|
||||
to={{ x: tooltipLeft, y: innerHeight + margin.top }}
|
||||
stroke={accentColorDark}
|
||||
strokeWidth={2}
|
||||
pointerEvents="none"
|
||||
strokeDasharray="5,2"
|
||||
/>
|
||||
<circle
|
||||
cx={tooltipLeft}
|
||||
cy={tooltipTop + 1}
|
||||
r={4}
|
||||
fill="black"
|
||||
fillOpacity={0.1}
|
||||
stroke="black"
|
||||
strokeOpacity={0.1}
|
||||
strokeWidth={2}
|
||||
pointerEvents="none"
|
||||
/>
|
||||
<circle
|
||||
cx={tooltipLeft}
|
||||
cy={tooltipTop}
|
||||
r={4}
|
||||
fill={accentColorDark}
|
||||
stroke="white"
|
||||
strokeWidth={2}
|
||||
pointerEvents="none"
|
||||
/>
|
||||
</g>
|
||||
)}
|
||||
</svg>
|
||||
{tooltipOpen && (
|
||||
<div>
|
||||
<TooltipWithBounds
|
||||
key={Math.random()}
|
||||
top={tooltipTop - 12}
|
||||
left={tooltipLeft + 12}
|
||||
style={tooltipStyles}
|
||||
>
|
||||
{`$${getCallActivity(tooltipData)}`}
|
||||
</TooltipWithBounds>
|
||||
<Tooltip
|
||||
top={innerHeight + margin.top - 14}
|
||||
left={tooltipLeft}
|
||||
style={{
|
||||
...defaultStyles,
|
||||
minWidth: 72,
|
||||
textAlign: 'center',
|
||||
transform: 'translateX(-50%)',
|
||||
}}
|
||||
>
|
||||
{formatDate(getDate(tooltipData))}
|
||||
</Tooltip>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
};
|
||||
|
||||
export default ChartWithTooltip;
|
||||
/*
|
||||
export default withTooltip(({
|
||||
width = 250,
|
||||
height = 250,
|
||||
margin = { top: 0, right: 0, bottom: 0, left: 0 },
|
||||
showTooltip,
|
||||
hideTooltip,
|
||||
data,
|
||||
tooltipTop = 0,
|
||||
tooltipLeft = 0,
|
||||
}) => {
|
||||
//if (width < 10) return null;
|
||||
|
||||
// bounds
|
||||
const innerWidth = width - margin.left - margin.right;
|
||||
const innerHeight = height - margin.top - margin.bottom;
|
||||
const stock = buildData();
|
||||
const tooltipData = stock;
|
||||
// scales
|
||||
const dateScale = useMemo(
|
||||
() =>
|
||||
scaleTime({
|
||||
range: [margin.left, innerWidth + margin.left],
|
||||
domain: extent(stock, getDate),
|
||||
}),
|
||||
[innerWidth, margin.left],
|
||||
);
|
||||
const stockValueScale = useMemo(
|
||||
() =>
|
||||
scaleLinear({
|
||||
range: [innerHeight + margin.top, margin.top],
|
||||
domain: [0, (max(stock, getStockValue) || 0) + innerHeight / 3],
|
||||
nice: true,
|
||||
}),
|
||||
[margin.top, innerHeight],
|
||||
);
|
||||
|
||||
// tooltip handler
|
||||
const handleTooltip = useCallback(
|
||||
(event) => {
|
||||
const { x } = localPoint(event) || { x: 0 };
|
||||
const x0 = dateScale.invert(x);
|
||||
const index = bisectDate(stock, x0, 1);
|
||||
const d0 = stock[index - 1];
|
||||
const d1 = stock[index];
|
||||
let d = d0;
|
||||
if (d1 && getDate(d1)) {
|
||||
d = x0.valueOf() - getDate(d0).valueOf() > getDate(d1).valueOf() - x0.valueOf() ? d1 : d0;
|
||||
}
|
||||
showTooltip({
|
||||
tooltipData: d,
|
||||
tooltipLeft: x,
|
||||
tooltipTop: stockValueScale(getStockValue(d)),
|
||||
});
|
||||
},
|
||||
[showTooltip, stockValueScale, dateScale],
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<svg width={width} height={height}>
|
||||
<rect
|
||||
x={0}
|
||||
y={0}
|
||||
width={width}
|
||||
height={height}
|
||||
fill="url(#area-background-gradient)"
|
||||
rx={14}
|
||||
/>
|
||||
<LinearGradient id="area-background-gradient" from={background} to={background2} />
|
||||
<LinearGradient id="area-gradient" from={accentColor} to={accentColor} toOpacity={0.1} />
|
||||
<GridRows
|
||||
left={margin.left}
|
||||
scale={stockValueScale}
|
||||
width={innerWidth}
|
||||
strokeDasharray="1,3"
|
||||
stroke={accentColor}
|
||||
strokeOpacity={0}
|
||||
pointerEvents="none"
|
||||
/>
|
||||
<GridColumns
|
||||
top={margin.top}
|
||||
scale={dateScale}
|
||||
height={innerHeight}
|
||||
strokeDasharray="1,3"
|
||||
stroke={accentColor}
|
||||
strokeOpacity={0.2}
|
||||
pointerEvents="none"
|
||||
/>
|
||||
<AreaClosed
|
||||
data={stock}
|
||||
x={(d) => dateScale(getDate(d)) ?? 0}
|
||||
y={(d) => stockValueScale(getStockValue(d)) ?? 0}
|
||||
yScale={stockValueScale}
|
||||
strokeWidth={1}
|
||||
stroke="url(#area-gradient)"
|
||||
fill="url(#area-gradient)"
|
||||
curve={curveMonotoneX}
|
||||
/>
|
||||
<Bar
|
||||
x={margin.left}
|
||||
y={margin.top}
|
||||
width={innerWidth}
|
||||
height={innerHeight}
|
||||
fill="transparent"
|
||||
rx={14}
|
||||
onTouchStart={handleTooltip}
|
||||
onTouchMove={handleTooltip}
|
||||
onMouseMove={handleTooltip}
|
||||
onMouseLeave={() => hideTooltip()}
|
||||
/>
|
||||
|
||||
<g>
|
||||
<Line
|
||||
from={{ x: tooltipLeft, y: margin.top }}
|
||||
to={{ x: tooltipLeft, y: innerHeight + margin.top }}
|
||||
stroke={accentColorDark}
|
||||
strokeWidth={2}
|
||||
pointerEvents="none"
|
||||
strokeDasharray="5,2"
|
||||
/>
|
||||
<circle
|
||||
cx={tooltipLeft}
|
||||
cy={tooltipTop + 1}
|
||||
r={4}
|
||||
fill="black"
|
||||
fillOpacity={0.1}
|
||||
stroke="black"
|
||||
strokeOpacity={0.1}
|
||||
strokeWidth={2}
|
||||
pointerEvents="none"
|
||||
/>
|
||||
<circle
|
||||
cx={tooltipLeft}
|
||||
cy={tooltipTop}
|
||||
r={4}
|
||||
fill={accentColorDark}
|
||||
stroke="white"
|
||||
strokeWidth={2}
|
||||
pointerEvents="none"
|
||||
/>
|
||||
</g>
|
||||
|
||||
</svg>
|
||||
|
||||
<div>
|
||||
<TooltipWithBounds
|
||||
key={Math.random()}
|
||||
top={tooltipTop - 12}
|
||||
left={tooltipLeft + 12}
|
||||
style={tooltipStyles}
|
||||
>
|
||||
{getStockValue(tooltipData)}
|
||||
</TooltipWithBounds>
|
||||
<Tooltip
|
||||
top={innerHeight + margin.top - 14}
|
||||
left={tooltipLeft}
|
||||
style={{
|
||||
...defaultStyles,
|
||||
minWidth: 72,
|
||||
textAlign: 'center',
|
||||
transform: 'translateX(-50%)',
|
||||
}}
|
||||
>
|
||||
{formatDate(getDate(tooltipData))}
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
*/
|
||||
212
frontend/src/Call/Example.js
Normal file
212
frontend/src/Call/Example.js
Normal file
@@ -0,0 +1,212 @@
|
||||
import React, { useMemo, useCallback } from 'react';
|
||||
import { AreaClosed, Line, Bar } from '@visx/shape';
|
||||
import appleStock, { AppleStock } from '@visx/mock-data/lib/mocks/appleStock';
|
||||
import { curveMonotoneX } from '@visx/curve';
|
||||
import { GridRows, GridColumns } from '@visx/grid';
|
||||
import { scaleTime, scaleLinear } from '@visx/scale';
|
||||
import { withTooltip, Tooltip, TooltipWithBounds, defaultStyles } from '@visx/tooltip';
|
||||
import { WithTooltipProvidedProps } from '@visx/tooltip/lib/enhancers/withTooltip';
|
||||
import { localPoint } from '@visx/event';
|
||||
import { LinearGradient } from '@visx/gradient';
|
||||
import { max, extent, bisector } from 'd3-array';
|
||||
import { timeFormat } from 'd3-time-format';
|
||||
|
||||
type TooltipData = AppleStock;
|
||||
|
||||
const stock = appleStock.slice(800);
|
||||
export const background = '#3b6978';
|
||||
export const background2 = '#204051';
|
||||
export const accentColor = '#edffea';
|
||||
export const accentColorDark = '#75daad';
|
||||
const tooltipStyles = {
|
||||
...defaultStyles,
|
||||
background,
|
||||
border: '1px solid white',
|
||||
color: 'white',
|
||||
};
|
||||
|
||||
// util
|
||||
const formatDate = timeFormat("%b %d, '%y");
|
||||
|
||||
// accessors
|
||||
const getDate = (d: AppleStock) => new Date(d.date);
|
||||
const getStockValue = (d: AppleStock) => d.close;
|
||||
const bisectDate = bisector<AppleStock, Date>((d) => new Date(d.date)).left;
|
||||
|
||||
export type AreaProps = {
|
||||
width: number;
|
||||
height: number;
|
||||
margin?: { top: number; right: number; bottom: number; left: number };
|
||||
};
|
||||
|
||||
export default withTooltip<AreaProps, TooltipData>(
|
||||
({
|
||||
width,
|
||||
height,
|
||||
margin = { top: 0, right: 0, bottom: 0, left: 0 },
|
||||
showTooltip,
|
||||
hideTooltip,
|
||||
tooltipData,
|
||||
tooltipTop = 0,
|
||||
tooltipLeft = 0,
|
||||
}: AreaProps & WithTooltipProvidedProps<TooltipData>) => {
|
||||
if (width < 10) return null;
|
||||
|
||||
// bounds
|
||||
const innerWidth = width - margin.left - margin.right;
|
||||
const innerHeight = height - margin.top - margin.bottom;
|
||||
|
||||
// scales
|
||||
const dateScale = useMemo(
|
||||
() =>
|
||||
scaleTime({
|
||||
range: [margin.left, innerWidth + margin.left],
|
||||
domain: extent(stock, getDate) as [Date, Date],
|
||||
}),
|
||||
[innerWidth, margin.left],
|
||||
);
|
||||
const stockValueScale = useMemo(
|
||||
() =>
|
||||
scaleLinear({
|
||||
range: [innerHeight + margin.top, margin.top],
|
||||
domain: [0, (max(stock, getStockValue) || 0) + innerHeight / 3],
|
||||
nice: true,
|
||||
}),
|
||||
[margin.top, innerHeight],
|
||||
);
|
||||
|
||||
// tooltip handler
|
||||
const handleTooltip = useCallback(
|
||||
(event: React.TouchEvent<SVGRectElement> | React.MouseEvent<SVGRectElement>) => {
|
||||
const { x } = localPoint(event) || { x: 0 };
|
||||
const x0 = dateScale.invert(x);
|
||||
const index = bisectDate(stock, x0, 1);
|
||||
const d0 = stock[index - 1];
|
||||
const d1 = stock[index];
|
||||
let d = d0;
|
||||
if (d1 && getDate(d1)) {
|
||||
d = x0.valueOf() - getDate(d0).valueOf() > getDate(d1).valueOf() - x0.valueOf() ? d1 : d0;
|
||||
}
|
||||
showTooltip({
|
||||
tooltipData: d,
|
||||
tooltipLeft: x,
|
||||
tooltipTop: stockValueScale(getStockValue(d)),
|
||||
});
|
||||
},
|
||||
[showTooltip, stockValueScale, dateScale],
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<svg width={width} height={height}>
|
||||
<rect
|
||||
x={0}
|
||||
y={0}
|
||||
width={width}
|
||||
height={height}
|
||||
fill="url(#area-background-gradient)"
|
||||
rx={14}
|
||||
/>
|
||||
<LinearGradient id="area-background-gradient" from={background} to={background2} />
|
||||
<LinearGradient id="area-gradient" from={accentColor} to={accentColor} toOpacity={0.1} />
|
||||
<GridRows
|
||||
left={margin.left}
|
||||
scale={stockValueScale}
|
||||
width={innerWidth}
|
||||
strokeDasharray="1,3"
|
||||
stroke={accentColor}
|
||||
strokeOpacity={0}
|
||||
pointerEvents="none"
|
||||
/>
|
||||
<GridColumns
|
||||
top={margin.top}
|
||||
scale={dateScale}
|
||||
height={innerHeight}
|
||||
strokeDasharray="1,3"
|
||||
stroke={accentColor}
|
||||
strokeOpacity={0.2}
|
||||
pointerEvents="none"
|
||||
/>
|
||||
<AreaClosed<AppleStock>
|
||||
data={stock}
|
||||
x={(d) => dateScale(getDate(d)) ?? 0}
|
||||
y={(d) => stockValueScale(getStockValue(d)) ?? 0}
|
||||
yScale={stockValueScale}
|
||||
strokeWidth={1}
|
||||
stroke="url(#area-gradient)"
|
||||
fill="url(#area-gradient)"
|
||||
curve={curveMonotoneX}
|
||||
/>
|
||||
<Bar
|
||||
x={margin.left}
|
||||
y={margin.top}
|
||||
width={innerWidth}
|
||||
height={innerHeight}
|
||||
fill="transparent"
|
||||
rx={14}
|
||||
onTouchStart={handleTooltip}
|
||||
onTouchMove={handleTooltip}
|
||||
onMouseMove={handleTooltip}
|
||||
onMouseLeave={() => hideTooltip()}
|
||||
/>
|
||||
{tooltipData && (
|
||||
<g>
|
||||
<Line
|
||||
from={{ x: tooltipLeft, y: margin.top }}
|
||||
to={{ x: tooltipLeft, y: innerHeight + margin.top }}
|
||||
stroke={accentColorDark}
|
||||
strokeWidth={2}
|
||||
pointerEvents="none"
|
||||
strokeDasharray="5,2"
|
||||
/>
|
||||
<circle
|
||||
cx={tooltipLeft}
|
||||
cy={tooltipTop + 1}
|
||||
r={4}
|
||||
fill="black"
|
||||
fillOpacity={0.1}
|
||||
stroke="black"
|
||||
strokeOpacity={0.1}
|
||||
strokeWidth={2}
|
||||
pointerEvents="none"
|
||||
/>
|
||||
<circle
|
||||
cx={tooltipLeft}
|
||||
cy={tooltipTop}
|
||||
r={4}
|
||||
fill={accentColorDark}
|
||||
stroke="white"
|
||||
strokeWidth={2}
|
||||
pointerEvents="none"
|
||||
/>
|
||||
</g>
|
||||
)}
|
||||
</svg>
|
||||
{tooltipData && (
|
||||
<div>
|
||||
<TooltipWithBounds
|
||||
key={Math.random()}
|
||||
top={tooltipTop - 12}
|
||||
left={tooltipLeft + 12}
|
||||
style={tooltipStyles}
|
||||
>
|
||||
{`$${getStockValue(tooltipData)}`}
|
||||
</TooltipWithBounds>
|
||||
<Tooltip
|
||||
top={innerHeight + margin.top - 14}
|
||||
left={tooltipLeft}
|
||||
style={{
|
||||
...defaultStyles,
|
||||
minWidth: 72,
|
||||
textAlign: 'center',
|
||||
transform: 'translateX(-50%)',
|
||||
}}
|
||||
>
|
||||
{formatDate(getDate(tooltipData))}
|
||||
</Tooltip>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -19,6 +19,7 @@ import AboutComponent from "./About/AboutComponent"
|
||||
// Event
|
||||
import ListEvents from "./Event/ListEvents"
|
||||
import ViewEvent from "./Event/ViewEvent"
|
||||
import ActivityChart from './Call/BetterActivityChart';
|
||||
|
||||
|
||||
const App = () => {
|
||||
@@ -32,6 +33,7 @@ return (
|
||||
<Route exact path="/events" element={<ListEvents/>} />
|
||||
<Route exact path="/events/:id" element={<ViewEvent/>} />
|
||||
<Route exact path="/about" element={<AboutComponent/>} />
|
||||
<Route exact path="/test" element={<ActivityChart/>} />
|
||||
</Routes>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user