recharts#Tooltip TypeScript Examples
The following examples show how to use
recharts#Tooltip.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: SimpleLineChart.tsx From react-tutorials with MIT License | 7 votes |
SimpleLineChart = (props: ISimpleLineChartProps) => {
return (
<>
<LineChart
width={500}
height={300}
data={props.data}
margin={{
top: 5,
right: 30,
left: 20,
bottom: 5,
}}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis
height={60}
dataKey="date"
// @ts-ignore
tick={<CustomizedAxisTick />}
/>
<YAxis
// @ts-ignore
tick={<CustomizedYAxisTick />}
/>
<Tooltip />
<Line type="monotone" dataKey="value" stroke="#8884d8" dot={<EmptyDot />} />
</LineChart>
</>
)
}
Example #2
Source File: ProcessedTasksChart.tsx From asynqmon with MIT License | 6 votes |
function ProcessedTasksChart(props: Props) {
const theme = useTheme<Theme>();
return (
<ResponsiveContainer>
<BarChart data={props.data} maxBarSize={120}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="queue" stroke={theme.palette.text.secondary} />
<YAxis stroke={theme.palette.text.secondary} />
<Tooltip />
<Legend />
<Bar
dataKey="succeeded"
stackId="a"
fill={theme.palette.success.light}
/>
<Bar dataKey="failed" stackId="a" fill={theme.palette.error.light} />
</BarChart>
</ResponsiveContainer>
);
}
Example #3
Source File: ScatterChart.tsx From opensaas with MIT License | 6 votes |
ScatterChart: React.FC<ScatterChartProps> = (props: ScatterChartProps) => {
const { data, width, height, showGrid, strokeColor, fillColor, scatterName } = props;
return (
<ResponsiveContainer>
<RechartsScatterChart width={width} height={height}>
{showGrid ? <CartesianGrid strokeDasharray='3 3' /> : null}
<XAxis type='number' dataKey='x' name={data?.xname} tickLine={false} />
<YAxis type='number' dataKey='y' name={data?.yname} tickLine={false} />
<Tooltip />
<Legend
verticalAlign='top'
content={<CustomizedLegend strokeColor={strokeColor} fillColor={fillColor} scatterName={scatterName} />}
/>
<Scatter
name={scatterName}
data={data.lineChartData}
shape={<CustomizedDot strokeColor={strokeColor} fillColor={fillColor} r={6} cx={10} cy={10} />}
/>
</RechartsScatterChart>
</ResponsiveContainer>
);
}
Example #4
Source File: Debug.tsx From watchparty with MIT License | 6 votes |
Debug = () => {
const [data, setData] = useState([]);
// eslint-disable-next-line
useEffect(
(async () => {
const response = await fetch(timeSeriesUrl);
const json = await response.json();
json.reverse();
setData(json);
}) as any,
[setData]
);
const keys = Object.keys(data.slice(-1)[0] ?? {});
return (
<>
{keys.map((key) => (
<LineChart
width={1400}
height={400}
data={data}
margin={{
top: 5,
left: 20,
bottom: 5,
}}
>
<CartesianGrid />
<XAxis dataKey="time" />
<YAxis />
<Tooltip />
<Legend />
<Line type="monotone" dataKey={key} stroke="#8884d8" />
</LineChart>
))}
</>
);
}
Example #5
Source File: TrafficChart.tsx From web-show with Apache License 2.0 | 6 votes |
TrafficChart: React.FC<IProps> = props => {
const { data } = props;
return (
<ResponsiveContainer>
<ComposedChart
barGap="2%"
width={600}
height={400}
margin={{
top: 10,
right: 30,
left: 20,
bottom: 20
}}
data={data}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis
tickLine={false}
dataKey="time"
domain = {['auto', 'auto']}
tickFormatter = {(unixTime) => moment(unixTime).format('HH:mm:ss Do')}
type = 'number'
/>
<YAxis label={{ value: 'Latency', position: 'insideLeft', angle: -90 }} unit={"ms"}/>
<Tooltip labelFormatter={t => new Date(t).toLocaleString()} />
<Legend />
<Line type="monotone" dataKey="latency" stroke="#8884d8" />
</ComposedChart>
</ResponsiveContainer>
);
}
Example #6
Source File: BuildTimeline.tsx From backstage with Apache License 2.0 | 6 votes |
BuildTimeline = ({
targets,
height,
width,
}: BuildTimelineProps) => {
const theme = useTheme();
if (!targets.length) return <p>No Targets</p>;
const data = getTimelineData(targets);
return (
<ResponsiveContainer
height={height}
width={width}
minHeight={EMPTY_HEIGHT + targets.length * 5}
>
<BarChart layout="vertical" data={data} maxBarSize={10} barGap={0}>
<CartesianGrid strokeDasharray="2 2" />
<XAxis type="number" domain={[0, 'dataMax']} />
<YAxis type="category" dataKey="name" padding={{ top: 0, bottom: 0 }} />
<Tooltip content={<TargetToolTip />} />
<Legend />
<Bar
dataKey="buildTime"
fill={theme.palette.grey[400]}
minPointSize={1}
/>
<Bar dataKey="compileTime" fill={theme.palette.primary.main} />
</BarChart>
</ResponsiveContainer>
);
}
Example #7
Source File: Line.tsx From your_spotify with GNU General Public License v3.0 | 6 votes |
export default function Line<
D extends { x: number; y: number; dateWithPrecision: DateWithPrecision },
>({ data, xFormat, yFormat, tooltipLabelFormatter, tooltipValueFormatter }: LineProps<D>) {
const internTooltipLabelFormatter = useRawTooltipLabelFormatter(tooltipLabelFormatter);
const internTooltipValueFormatter = useRawTooltipValueFormatter(tooltipValueFormatter);
return (
<ResponsiveContainer width="100%" height="100%">
<LineChart data={data}>
<RLine
connectNulls
type="monotone"
dataKey="y"
fill="var(--primary)"
stroke="var(--primary)"
strokeWidth={2}
dot={false}
/>
<XAxis
name="X"
domain={['dataMin', 'dataMax']}
dataKey="x"
tickFormatter={xFormat}
style={{ fontWeight: 'bold' }}
/>
<YAxis domain={['dataMin', 'dataMax']} tickFormatter={yFormat} />
<Tooltip
wrapperStyle={{ zIndex: 10 }}
contentStyle={{ backgroundColor: 'var(--background)' }}
labelStyle={{ color: 'var(--text-on-light)' }}
labelFormatter={internTooltipLabelFormatter}
formatter={internTooltipValueFormatter}
/>
</LineChart>
</ResponsiveContainer>
);
}
Example #8
Source File: index.tsx From Demae with MIT License | 6 votes |
OrderChart = () => {
return (
<LineChart
width={500}
height={300}
data={data}
margin={{
top: 5, right: 30, left: 20, bottom: 5,
}}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="name" />
<YAxis />
<Tooltip />
<Legend />
<Line type="monotone" dataKey="pv" stroke="#8884d8" activeDot={{ r: 8 }} />
<Line type="monotone" dataKey="uv" stroke="#82ca9d" />
</LineChart>
);
}
Example #9
Source File: DailyIncidents.tsx From backstage-plugin-opsgenie with MIT License | 6 votes |
Graph = ({context}: {context: Context}) => {
const analyticsApi = useApi(analyticsApiRef);
const dataPoints = analyticsApi.incidentsByDay(context);
return (
<div id="daily-incidents" style={{ width: '100%', height: 300, paddingTop: '1.2rem', paddingRight: '1.2rem' }}>
<ResponsiveContainer>
<ScatterChart data={dataPoints}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="day" name="Day" />
<YAxis dataKey="total" name="Total" />
<Tooltip content={<FilterZeroTooltip />} />
<Scatter name="day" data={dataPoints} fill="#8884d8" />
</ScatterChart>
</ResponsiveContainer>
</div>
);
}
Example #10
Source File: index.tsx From vvs-ui with GNU General Public License v3.0 | 5 votes |
Chart = ({ data, setHoverValue, setHoverDate }: LineChartProps) => {
const { theme } = useTheme()
if (!data || data.length === 0) {
return <BarChartLoader />
}
return (
<ResponsiveContainer width="100%" height="100%">
<BarChart
data={data}
margin={{
top: 5,
right: 15,
left: 0,
bottom: 5,
}}
onMouseLeave={() => {
setHoverDate(undefined)
setHoverValue(undefined)
}}
>
<XAxis
dataKey="time"
axisLine={false}
tickLine={false}
tickFormatter={(time) => format(time, 'dd')}
minTickGap={10}
/>
<YAxis
dataKey="value"
tickCount={6}
scale="linear"
axisLine={false}
tickLine={false}
color={theme.colors.textSubtle}
fontSize="12px"
tickFormatter={(val) => `$${formatAmount(val)}`}
orientation="right"
tick={{ dx: 10, fill: theme.colors.textSubtle }}
/>
<Tooltip
cursor={{ fill: theme.colors.backgroundDisabled }}
contentStyle={{ display: 'none' }}
formatter={(tooltipValue, name, props) => (
<HoverUpdater payload={props.payload} setHoverValue={setHoverValue} setHoverDate={setHoverDate} />
)}
/>
<Bar
dataKey="value"
fill={theme.colors.primary}
shape={(props) => (
<CustomBar height={props.height} width={props.width} x={props.x} y={props.y} fill={theme.colors.primary} />
)}
/>
</BarChart>
</ResponsiveContainer>
)
}
Example #11
Source File: QueueMetricsChart.tsx From asynqmon with MIT License | 5 votes |
function QueueMetricsChart(props: Props) {
const theme = useTheme();
const data = toChartData(props.data);
const keys = props.data.map((x) => x.metric.queue);
return (
<ResponsiveContainer height={260}>
<LineChart data={data}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis
minTickGap={10}
dataKey="timestamp"
domain={[props.startTime, props.endTime]}
tickFormatter={(timestamp: number) =>
new Date(timestamp * 1000).toLocaleTimeString()
}
type="number"
scale="time"
stroke={theme.palette.text.secondary}
/>
<YAxis
tickFormatter={props.yAxisTickFormatter}
stroke={theme.palette.text.secondary}
/>
<Tooltip
labelFormatter={(timestamp: number) => {
return new Date(timestamp * 1000).toLocaleTimeString();
}}
/>
<Legend />
{keys.map((key, idx) => (
<Line
key={key}
type="monotone"
dataKey={key}
stroke={lineColors[idx % lineColors.length]}
dot={false}
/>
))}
</LineChart>
</ResponsiveContainer>
);
}
Example #12
Source File: StakeGraph.tsx From mStable-apps with GNU Lesser General Public License v3.0 | 5 votes |
StakeGraph: FC = () => {
const { data: tokenData } = useStakedTokenQuery()
const weightedTimestamp = tokenData?.stakedToken?.accounts?.[0]?.balance?.weightedTimestamp
const data = generateData(weightedTimestamp)
const ticks = removeDuplicatesBy(x => x.multiplier, data).map(v => v.week)
return (
<Container>
<ResponsiveContainer width="100%" aspect={1.75}>
<AreaChart data={data}>
<defs>
<linearGradient id="area" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor={Color.blue} stopOpacity={0.5} />
<stop offset="95%" stopColor={Color.blue} stopOpacity={0} />
</linearGradient>
</defs>
<XAxis dataKey="week" tickFormatter={w => `${w / WEEK}`} axisLine={false} padding={{ left: 16 }} tickLine={false} ticks={ticks} />
<YAxis
domain={['dataMin', 'dataMax']}
tickCount={4}
tickFormatter={m => `${m}x`}
axisLine={false}
padding={{ bottom: 16 }}
tickLine={false}
width={32}
/>
<Tooltip
cursor
labelFormatter={week => `+${(week as number) / WEEK} weeks`}
formatter={multiplier => multiplier}
separator=""
contentStyle={{
fontSize: '14px',
padding: '8px',
background: 'rgba(255, 255, 255, 0.8)',
textAlign: 'right',
border: 'none',
borderRadius: '4px',
color: Color.black,
}}
wrapperStyle={{
top: 0,
left: 0,
}}
/>
<Area type="stepAfter" name={`multiplier: `} dataKey="multiplier" stroke={Color.blue} strokeWidth={2} fill="url(#area)" />
</AreaChart>
</ResponsiveContainer>
</Container>
)
}
Example #13
Source File: stats.tsx From config-generator with MIT License | 5 votes |
public render() {
const { stats, onRefresh, range } = this.props;
const { strokeWidth } = this.state;
return (
<ResponsiveContainer width="100%" maxHeight={500} aspect={4.0 / 3.0}>
<LineChart
data={stats}
margin={{
top: 25,
right: 30,
left: 20,
bottom: 100,
}}
>
<CartesianGrid strokeDasharray="1 4" />
<XAxis
dataKey="timeStamp"
tick={this.renderCustomAxisTick}
interval={0}
ticks={stats.map((s: any) => s.timeStamp)}
type="number"
domain={['dataMin', 'dataMax']}
/>
<YAxis />
<Tooltip
itemStyle={{ textTransform: 'capitalize' }}
labelFormatter={value =>
range === 'day'
? moment(value).format('DD/MM/YYYY HH:mm:ss')
: moment(value).format('DD/MM/YYYY')
}
labelStyle={{ fontWeight: 'bold', marginBottom: '10px' }}
/>
<Legend
verticalAlign="top"
iconType="circle"
formatter={(value, entry, index) => value.toUpperCase()}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
/>
<Line
type="monotone"
dataKey="all"
connectNulls={true}
stroke="#4F4F4F"
activeDot={{ r: 8 }}
strokeWidth={strokeWidth.all}
/>
<Line
type="monotone"
dataKey="allowed"
stroke="#71ADFE"
connectNulls={true}
activeDot={{ r: 8 }}
strokeWidth={strokeWidth.allowed}
/>
<Line
type="monotone"
connectNulls={true}
dataKey="blocked"
stroke="#EB5757"
activeDot={{ r: 8 }}
strokeWidth={strokeWidth.blocked}
/>
</LineChart>
</ResponsiveContainer>
);
}
Example #14
Source File: StatisticsChart.tsx From jitsu with MIT License | 5 votes |
StatisticsChart: React.FC<Props> = ({
data,
granularity,
dataToDisplay = ["success", "skip", "errors"],
legendLabels = {},
}) => {
const [state, dispatch] = useReducer(reducer, initialState)
const handleClickOnLegend = (data: any) => {
const clickedDataType = data["value"] as DataType
dispatch({ type: clickedDataType })
}
return (
<ResponsiveContainer width="100%" minHeight={225} minWidth={300}>
<LineChart
className={styles.chart}
data={data.map(point => ({
...point,
date: granularity == "hour" ? point.date.format("HH:mm") : point.date.format("DD MMM"),
}))}
>
<XAxis dataKey="date" tick={<CustomizedXAxisTick />} stroke="#394e5a" />
<YAxis tick={<CustomizedYAxisTick />} stroke="#394e5a" />
<CartesianGrid strokeDasharray="3 3" stroke="#394e5a" />
<Legend onClick={handleClickOnLegend} formatter={value => legendLabels[value] ?? value} />
<Tooltip
wrapperStyle={{
backgroundColor: "#22313a",
border: "1px solid #394e5a",
}}
itemStyle={{ color: "#9bbcd1" }}
labelStyle={{ color: "#dcf3ff" }}
formatter={value => new Intl.NumberFormat("en").format(value)}
/>
{dataToDisplay.includes("total") && (
<Line dataKey="total" stroke={"rgb(135, 138, 252)"} hide={state.hide_total_data} {...commonLineProps} />
)}
{dataToDisplay.includes("success") && (
<Line dataKey="success" stroke={"#2cc56f"} hide={state.hide_success_data} {...commonLineProps} />
)}
{dataToDisplay.includes("skip") && (
<Line dataKey="skip" stroke={"#ffc021"} hide={state.hide_skip_data} {...commonLineProps} />
)}
{dataToDisplay.includes("errors") && (
<Line dataKey="errors" stroke={"#e53935"} hide={state.hide_errors_data} {...commonLineProps} />
)}
</LineChart>
</ResponsiveContainer>
)
}
Example #15
Source File: Chart.tsx From kubenav with MIT License | 5 votes |
Chart: React.FunctionComponent<IChartProps> = ({ aggregations }: IChartProps) => {
const context = useContext<IContext>(AppContext);
const formatTime = (time: number): string => {
const d = new Date(time);
return `${('0' + (d.getMonth() + 1)).slice(-2)}/${('0' + d.getDate()).slice(-2)} ${('0' + d.getHours()).slice(
-2,
)}:${('0' + d.getMinutes()).slice(-2)}`;
};
return (
<IonRow style={{ height: '200px', width: '100%' }}>
<IonCol style={{ padding: '0px' }}>
<ResponsiveContainer>
<BarChart data={aggregations?.logcount?.buckets}>
<XAxis
dataKey="key"
scale="time"
type="number"
domain={['dataMin', 'dataMax']}
tickFormatter={formatTime}
/>
{!isPlatform('hybrid') ? (
<Tooltip
cursor={{ stroke: '#949494', strokeWidth: 2 }}
contentStyle={
isDarkMode(context.settings.theme)
? isPlatform('ios')
? { backgroundColor: '1c1c1c', borderColor: '#949494' }
: { backgroundColor: '#1A1B1E', borderColor: '#949494' }
: { backgroundColor: '#ffffff', borderColor: '#949494' }
}
formatter={(value) => {
return [value, 'Count'];
}}
labelFormatter={formatTime}
/>
) : null}
<Bar dataKey="doc_count" stroke="#326ce5" fill="#326ce5" />
</BarChart>
</ResponsiveContainer>
</IonCol>
</IonRow>
);
}
Example #16
Source File: OrderChart.tsx From ra-enterprise-demo with MIT License | 5 votes |
OrderChart: FC<{ orders?: Order[] }> = ({ orders }) => {
const translate = useTranslate();
if (!orders) return null;
return (
<Card>
<CardHeader title={translate('pos.dashboard.month_history')} />
<CardContent>
<div style={{ width: '100%', height: 300 }}>
<ResponsiveContainer>
<AreaChart data={getRevenuePerDay(orders)}>
<defs>
<linearGradient
id="colorUv"
x1="0"
y1="0"
x2="0"
y2="1"
>
<stop
offset="5%"
stopColor="#8884d8"
stopOpacity={0.8}
/>
<stop
offset="95%"
stopColor="#8884d8"
stopOpacity={0}
/>
</linearGradient>
</defs>
<XAxis
dataKey="date"
name="Date"
type="number"
scale="time"
domain={[
addDays(aMonthAgo, 1).getTime(),
new Date().getTime(),
]}
tickFormatter={dateFormatter}
/>
<YAxis dataKey="total" name="Revenue" unit="€" />
<CartesianGrid strokeDasharray="3 3" />
<Tooltip
cursor={{ strokeDasharray: '3 3' }}
formatter={(value): string =>
new Intl.NumberFormat(undefined, {
style: 'currency',
currency: 'USD',
}).format(value as any)
}
labelFormatter={(label: any): string =>
dateFormatter(label)
}
/>
<Area
type="monotone"
dataKey="total"
stroke="#8884d8"
strokeWidth={2}
fill="url(#colorUv)"
/>
</AreaChart>
</ResponsiveContainer>
</div>
</CardContent>
</Card>
);
}
Example #17
Source File: ClaimGraph.tsx From mStable-apps with GNU Lesser General Public License v3.0 | 5 votes |
ClaimGraph: FC = () => {
const rewardsEarned = useRewardsEarned()
const data = useMemo<DataType[]>(() => {
return [
{
mta: 0,
ordering: 0,
},
{
mta: rewardsEarned?.rewards ?? 0,
ordering: 1,
},
]
}, [rewardsEarned])
return (
<Container>
<ResponsiveContainer width="100%" aspect={1.75}>
<AreaChart data={data}>
<defs>
<linearGradient id="area" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor={Color.blue} stopOpacity={0.5} />
<stop offset="95%" stopColor={Color.blue} stopOpacity={0} />
</linearGradient>
</defs>
<XAxis
dataKey="ordering"
tickFormatter={ordering => (ordering === 0 ? 'Last claim' : 'Now')}
axisLine={false}
padding={{ left: 16 }}
tickLine={false}
/>
<YAxis tickCount={2} tickFormatter={m => `${m}`} axisLine={false} padding={{ bottom: 16 }} tickLine={false} width={32} />
<Tooltip
cursor
label=""
labelFormatter={w => (w === 0 ? 'Last claim' : 'Available to claim')}
formatter={mta => `${(mta as number).toFixed(2)} MTA`}
separator=""
contentStyle={{
fontSize: '14px',
padding: '8px',
background: 'rgba(255, 255, 255, 0.8)',
textAlign: 'right',
border: 'none',
borderRadius: '4px',
color: Color.black,
}}
wrapperStyle={{
top: 0,
left: 0,
}}
/>
<Area type="monotone" name={'Earned: '} dataKey="mta" stroke={Color.blue} strokeWidth={2} fill="url(#area)" />
</AreaChart>
</ResponsiveContainer>
</Container>
)
}
Example #18
Source File: index.tsx From glide-frontend with GNU General Public License v3.0 | 5 votes |
Chart = ({ data, setHoverValue, setHoverDate }: LineChartProps) => {
const { theme } = useTheme()
if (!data || data.length === 0) {
return <BarChartLoader />
}
return (
<ResponsiveContainer width="100%" height="100%">
<BarChart
data={data}
margin={{
top: 5,
right: 15,
left: 0,
bottom: 5,
}}
onMouseLeave={() => {
setHoverDate(undefined)
setHoverValue(undefined)
}}
>
<XAxis
dataKey="time"
axisLine={false}
tickLine={false}
tickFormatter={(time) => format(time, 'dd')}
minTickGap={10}
/>
<YAxis
dataKey="value"
tickCount={6}
scale="linear"
axisLine={false}
tickLine={false}
color={theme.colors.textSubtle}
fontSize="12px"
tickFormatter={(val) => `$${formatAmount(val)}`}
orientation="right"
tick={{ dx: 10, fill: theme.colors.textSubtle }}
/>
<Tooltip
cursor={{ fill: theme.colors.backgroundDisabled }}
contentStyle={{ display: 'none' }}
formatter={(tooltipValue, name, props) => (
<HoverUpdater payload={props.payload} setHoverValue={setHoverValue} setHoverDate={setHoverDate} />
)}
/>
<Bar
dataKey="value"
fill={theme.colors.primary}
shape={(props) => (
<CustomBar height={props.height} width={props.width} x={props.x} y={props.y} fill={theme.colors.primary} />
)}
/>
</BarChart>
</ResponsiveContainer>
)
}
Example #19
Source File: index.tsx From Lux-Viewer-2021 with Apache License 2.0 | 5 votes |
Graph = ({ data, ylabel, xlabel }: GraphProps) => {
const renderColorfulLegendText = (value: string, entry: any) => {
const { color } = entry;
return <span style={{ color: '#f9efe2' }}>{value}</span>;
};
return (
<div className="Graph">
<ResponsiveContainer width={'100%'} height={220}>
<LineChart
// width={200}
onClick={() => {}}
// height={150}
data={data}
margin={{ top: 15, right: 20, left: 0, bottom: 15 }}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="name">
<Label
value={xlabel}
offset={-15}
position="insideBottom"
fill="#f9efe2"
/>
</XAxis>
<YAxis
label={{
value: ylabel,
angle: -90,
position: 'insideLeft',
fill: '#f9efe2',
color: 'f9efe2',
}}
></YAxis>
<Tooltip labelStyle={{ color: '#323D34' }} />
{/* <Legend
verticalAlign="top"
height={36}
formatter={renderColorfulLegendText}
/> */}
<Line
type="monotone"
dataKey="team0"
name="Team 0"
dot={false}
strokeWidth={2}
isAnimationActive={false}
stroke={TEAM_A_COLOR_STR}
/>
<Line
type="monotone"
dataKey="team1"
name="Team 1"
dot={false}
strokeWidth={2}
isAnimationActive={false}
stroke={TEAM_B_COLOR_STR}
/>
</LineChart>
</ResponsiveContainer>
</div>
);
}
Example #20
Source File: StackedBar.tsx From your_spotify with GNU General Public License v3.0 | 5 votes |
export default function Bar({
data,
xFormat,
yFormat,
tooltipLabelFormatter,
tooltipValueFormatter,
tooltipItemSorter,
customXTick,
}: StackedBarProps) {
const realFormatter = useMemo(() => {
if (tooltipValueFormatter) {
return (...args: any[]) => [tooltipValueFormatter(...args), null];
}
return undefined;
}, [tooltipValueFormatter]);
const allKeys = useMemo(
() =>
data.reduce<Set<string>>((acc, curr) => {
Object.keys(curr)
.filter((key) => key !== 'x')
.forEach((key) => acc.add(key));
return acc;
}, new Set()),
[data],
);
return (
<ResponsiveContainer width="100%" height="100%">
<BarChart data={data}>
<XAxis
dataKey="x"
tickFormatter={xFormat}
tick={customXTick}
style={{ fontWeight: 'bold' }}
/>
<YAxis tickFormatter={yFormat} width={40} />
{Array.from(allKeys).map((k, index) => (
<RBar key={k} stackId="only" dataKey={k} fill={getColor(index)} />
))}
<Tooltip
wrapperStyle={{ zIndex: 10 }}
contentStyle={{ backgroundColor: 'var(--background)' }}
labelStyle={{ color: 'var(--text-on-light)' }}
labelFormatter={tooltipLabelFormatter}
formatter={realFormatter}
itemSorter={tooltipItemSorter}
/>
</BarChart>
</ResponsiveContainer>
);
}
Example #21
Source File: SimplePriceChart.tsx From index-ui with MIT License | 4 votes |
MarketDataChart: React.FC<SimplePriceChartProps> = ({
title,
showTooltip,
icon,
data,
hourlyData,
onMouseMove = () => {},
onMouseLeave = () => {},
setChartRange = () => {},
}) => {
const theme = useTheme()
const formatFloats = (n: number) => parseFloat(numeral(n).format('0.00a'))
const formatToolTip = (chartData: any) => {
if (!chartData) return ['--', 'No Data Available']
const {
payload: { x, y },
} = chartData
let timeString = new Date(x).toLocaleDateString()
if (durationSelector === Durations.DAILY) {
timeString = new Date(x).toLocaleTimeString([], {
hour: 'numeric',
minute: 'numeric',
})
}
return [timeString, '$' + formatFloats(y)]
}
const [durationSelector, setDurationSelector] = useState<number>(
Durations.MONTHLY
)
const [price, setPrice] = useState(data)
useEffect(() => {
setTimeout(() => {
const hourlyDataInterval = 24
if (durationSelector === Durations.DAILY) {
setPrice(
hourlyData?.slice(
-PriceChartRangeOption.DAILY_PRICE_RANGE * hourlyDataInterval
)
) //last day, hourly
} else if (durationSelector === Durations.WEEKLY) {
setPrice(
hourlyData?.slice(
-PriceChartRangeOption.WEEKLY_PRICE_RANGE * hourlyDataInterval
)
) //last 7 days, hourly
} else if (durationSelector === Durations.MONTHLY) {
setPrice(
hourlyData?.slice(
-PriceChartRangeOption.MONTHLY_PRICE_RANGE * hourlyDataInterval
)
) //last 30 days, hourly
} else if (durationSelector === Durations.QUARTERLY) {
setPrice(
hourlyData?.slice(
-PriceChartRangeOption.QUARTERLY_PRICE_RANGE * hourlyDataInterval
)
) //last 90 days, hourly
} else if (durationSelector === Durations.YEARLY) {
setPrice(data?.slice(-PriceChartRangeOption.YEARLY_PRICE_RANGE)) //last year, daily
}
}, 0)
}, [durationSelector, data, hourlyData])
const handleDailyButton = () => {
setDurationSelector(Durations.DAILY)
setChartRange(PriceChartRangeOption.DAILY_PRICE_RANGE)
}
const handleWeeklyButton = () => {
setDurationSelector(Durations.WEEKLY)
setChartRange(PriceChartRangeOption.WEEKLY_PRICE_RANGE)
}
const handleMonthlyButton = () => {
setDurationSelector(Durations.MONTHLY)
setChartRange(PriceChartRangeOption.MONTHLY_PRICE_RANGE)
}
const handleQuarterlyButton = () => {
setDurationSelector(Durations.QUARTERLY)
setChartRange(PriceChartRangeOption.QUARTERLY_PRICE_RANGE)
}
const handleYearlyButton = () => {
setDurationSelector(Durations.YEARLY)
setChartRange(PriceChartRangeOption.YEARLY_PRICE_RANGE)
}
const renderTooltip = (props: any) => {
if (!showTooltip) return null
const tooltipData = props.payload?.[0]
const [label, value] = formatToolTip(tooltipData)
return <FancyValue icon={icon} label={label} value={value} />
}
const tickFormatter = (val: any) => {
if (val <= minY) return 'Min: $' + formatFloats(val)
return 'Max: $' + formatFloats(val)
}
const minY = Math.min(...(price || []).map<number>(({ y }) => y))
const maxY = Math.max(...(price || []).map<number>(({ y }) => y))
const minimumYAxisLabel = minY - 5 > 0 ? minY - 5 : 0
return (
<Container size='lg'>
{title && <ChartTitle>{title}</ChartTitle>}
<ChartContainer>
<LineChart
data={price}
onMouseMove={onMouseMove}
onMouseLeave={onMouseLeave}
>
<Line
type='monotone'
dataKey='y'
dot={false}
stroke={'url(#gradient)'}
strokeWidth={2}
animationEasing='ease'
animationDuration={800}
/>
<YAxis
stroke={theme.colors.grey[500]}
tickFormatter={tickFormatter}
axisLine={false}
tickLine={false}
mirror={true}
ticks={[minimumYAxisLabel + 0.001, maxY + 5.001]}
domain={[minY - 15, maxY + 5]}
orientation='right'
width={100}
dy={7}
dx={1}
/>
<Tooltip
content={renderTooltip}
wrapperStyle={{ backgroundColor: theme.baseColor }}
cursor={{ stroke: theme.colors.primary.light, strokeWidth: 2 }}
/>
<defs>
<linearGradient id='gradient' gradientTransform='rotate(90)'>
<stop offset='5%' stopColor='#8150E6' />
<stop offset='95%' stopColor='#E825A3' />
</linearGradient>
</defs>
</LineChart>
</ChartContainer>
<DurationWrapper>
<ButtonWrapper data-cy='date-range-selector'>
<Button
full
size={'sm'}
text='1D'
variant={
durationSelector === Durations.DAILY ? 'default' : 'secondary'
}
onClick={handleDailyButton}
/>
<Spacer size={'sm'} />
<Button
full
size={'sm'}
text='1W'
variant={
durationSelector === Durations.WEEKLY ? 'default' : 'secondary'
}
onClick={handleWeeklyButton}
/>
<Spacer size={'sm'} />
<Button
full
size={'sm'}
text='1M'
variant={
durationSelector === Durations.MONTHLY ? 'default' : 'secondary'
}
onClick={handleMonthlyButton}
/>
<Spacer size={'sm'} />
<Button
full
size={'sm'}
text='3M'
variant={
durationSelector === Durations.QUARTERLY ? 'default' : 'secondary'
}
onClick={handleQuarterlyButton}
/>
<Spacer size={'sm'} />
<Button
full
size={'sm'}
text='1Y'
variant={
durationSelector === Durations.YEARLY ? 'default' : 'secondary'
}
onClick={handleYearlyButton}
/>
</ButtonWrapper>
</DurationWrapper>
</Container>
)
}
Example #22
Source File: Profile.tsx From avalon.ist with MIT License | 4 votes |
render() {
const { initialHeight } = this;
const {
myname,
style: { themeLight },
} = this.props.match.params;
const theme = themeLight ? 'light' : 'dark';
const data: any[] = [];
// const { avatarStyle } = this.props.match.params.style;
const {
username,
nationality,
bio,
gameRating,
gameHistory,
games,
gameStats,
gameShots,
avatars,
showSpy,
redirect,
} = this.state;
for (const k in gameStats) {
const stat = gameStats[k];
data.push({
name: k.charAt(0).toUpperCase() + k.slice(1),
wins: stat[0],
total: stat[1],
Winrate: stat[1] === 0 ? 0 : Percent(stat[0] / stat[1]),
color: SPY_ROLES.has(k) ? '#ff6384' : '#36a2eb',
});
}
const country = countries.find((c) => c.text === nationality);
const totalWon = games[0];
const totalLost = games[1] - totalWon;
const winRate = games[1] > 0 ? Percent(totalWon / games[1]) : 0;
const shotRate = gameShots[1] > 0 ? Percent(gameShots[0] / gameShots[1]) : 0;
let countryFlag = <img alt={'UN'} src={UN_FLAG} />;
if (country && country.value != 'UN') {
if (country.value == 'LGBT') {
countryFlag = <img alt={'Stonewall'} src={STONEWALL_FLAG} />;
} else {
countryFlag = <Flag code={country.value} />;
}
}
return redirect ? (
<Redirect to="/profile-not-found" />
) : (
<div id="Background-2" className={`full ${theme}`}>
<Navbar username="" key={'Navbar'} />
<AvalonScrollbars>
<div id="Profile" style={{ minHeight: `${initialHeight}px` }}>
<div className="row">
<div id="user">
<img
src={showSpy ? avatars.spy : avatars.res}
alt={'Avatar'}
onMouseOver={this.onHover}
onMouseLeave={this.onStopHover}
/>
<div className="user-tag">
{countryFlag}
<p>
<b>{username}</b>
<br />
{nationality}
</p>
</div>
</div>
<div id="bio" className="bubble">
<AvalonScrollbars>
<ReactMarkdown
className="markdown"
allowedTypes={[
'text',
'paragraph',
'emphasis',
'strong',
'thematicBreak',
'blockquote',
'list',
'listItem',
'heading',
]}
>
{bio}
</ReactMarkdown>
</AvalonScrollbars>
</div>
</div>
<div className="row">
<div id="stats">
<h1>STATISTICS</h1>
<table>
<tbody>
<tr>
<th>Statistic</th>
<th>Value</th>
</tr>
<tr>
<td>Total Games Played</td>
<td>{games[1]}</td>
</tr>
<tr>
<td>Total Games Won</td>
<td>{totalWon}</td>
</tr>
<tr>
<td>Total Games Lost</td>
<td>{totalLost}</td>
</tr>
<tr>
<td>Total Win Rate</td>
<td>{winRate}%</td>
</tr>
<tr>
<td>Shot Accuracy</td>
<td>{shotRate}%</td>
</tr>
<tr>
<td>Rating</td>
<td>{gameRating}</td>
</tr>
</tbody>
</table>
</div>
<div id="graph">
<ResponsiveContainer width={'100%'} height={300}>
<BarChart
layout="vertical"
margin={{
top: 20,
right: 20,
bottom: 20,
left: 20,
}}
data={data}
>
<CartesianGrid strokeDasharray="1 1" />
<XAxis type="number" domain={[0, 100]} />
<YAxis type="category" width={100} dataKey="name" />
<Tooltip content={<CustomTooltip />} />
<Bar dataKey="Winrate" fill="#8884d8">
{data.map((entry, index) => (
<Cell key={`cell-${index}`} fill={entry.color} />
))}
</Bar>
</BarChart>
</ResponsiveContainer>
</div>
</div>
<div className="row">
<div id="history">
<h1>GAME HISTORY</h1>
<table>
<tbody>
<tr>
<th>Game</th>
<th>Role</th>
<th>Size</th>
<th>Winner</th>
<th>Date</th>
</tr>
{gameHistory
.slice(-10)
.reverse()
.map((g: any, i) => {
const date = new Date(g.date);
const month = ('00' + (date.getUTCMonth() + 1)).slice(-2);
const day = ('00' + date.getUTCDate()).slice(-2);
const year = date.getUTCFullYear();
return (
<tr key={'Game' + g.id}>
<td>
<Link to={'/game/' + g.id}>#{g.code}</Link>
</td>
<td>{g.role}</td>
<td>{g.size}</td>
<td>{g.winner ? 'Resistance' : 'Spy'}</td>
<td>
{year}-{month}-{day}
</td>
</tr>
);
})}
</tbody>
</table>
</div>
</div>
</div>
</AvalonScrollbars>
{myname === username ? (
<button
className="button-b edit-your-profile-with-this"
type="button"
onClick={this.onFormToggle}
>
<p>Edit Profile</p>
</button>
) : null}
{this.state.showForm ? (
<EditProfile
onExit={this.onFormToggle}
text="Submit"
nationality={nationality}
bio={bio}
title="EDIT YOUR PROFILE"
onSelect={this.onEdit}
/>
) : null}
</div>
);
}
Example #23
Source File: index.tsx From korona-info with MIT License | 4 votes |
Index: NextPage<{ groupedCoronaData: GroupedData, hospitalised: HospitalData[] }> = ({
groupedCoronaData, hospitalised
}: {
groupedCoronaData: GroupedData;
hospitalised: HospitalData[];
}) => {
const [selectedHealthCareDistrict, selectHealthCareDistrict] = useState<
string
>('all');
const confirmed = groupedCoronaData[selectedHealthCareDistrict].confirmed;
const deaths = groupedCoronaData[selectedHealthCareDistrict].deaths;
const recovered = groupedCoronaData[selectedHealthCareDistrict].recovered;
const allConfirmed = groupedCoronaData.all.confirmed;
const toast = useToast()
const latestInfection = confirmed.length
? format(
utcToZonedTime(
new Date(confirmed[confirmed.length - 1].date),
timeZone
),
'dd.MM.yyyy - HH:mm',
{ timeZone }
)
: null;
const latestInfectionDistrict =
confirmed[confirmed.length - 1]?.healthCareDistrict;
const latestDeath = deaths.length
? format(
utcToZonedTime(new Date(deaths[deaths.length - 1].date), timeZone),
'd.M.yyyy'
)
: null;
const latestDeathDistrict = deaths.length
? deaths[deaths.length - 1].area
: null;
const latestRecoveredDistrict = recovered.length
? recovered[recovered.length - 1].healthCareDistrict
: null;
const latestRecovered = recovered.length
? format(
utcToZonedTime(
new Date(recovered[recovered.length - 1].date),
timeZone
),
'd.M.yyyy'
)
: null;
const infectionsToday = getInfectionsToday(confirmed);
const [cumulativeChartScale, setCumulativeChartScale] = useState<
'linear' | 'log'
>('linear');
const [forecastChartScale, setForecaseChartScale] = useState<
'linear' | 'log'
>('linear');
// Map data to show development of infections
const {
infectionDevelopmentData,
infectionDevelopmentData30Days
} = groupedCoronaData[selectedHealthCareDistrict].timeSeries;
const maxValues =
infectionDevelopmentData30Days[infectionDevelopmentData30Days.length - 1];
const dataMaxValue = Math.max(
maxValues?.deaths ?? 0,
maxValues?.infections ?? 0,
maxValues?.infections ?? 0
);
const {
infectionsByDistrict,
infectionsByDistrictPercentage,
areas
} = getTnfectionsByDistrict(allConfirmed);
const { infectionsBySourceCountry } = getInfectionsBySourceCountry(confirmed);
const networkGraphData = getNetworkGraphData(confirmed);
const { t } = useContext(UserContext);
const humanizeHealthcareDistrict = (district: string) => {
if (district === 'all') {
return t('All healthcare districts');
} else if (district === 'unknown') {
return t('unknown');
} else {
return district;
}
};
const reversedConfirmed = confirmed
// @ts-ignore
.map((i, index) => ({
index: index + 1,
...i,
healthCareDistrict: humanizeHealthcareDistrict(i.healthCareDistrict)
}))
.reverse();
const humanizedHealthCareDistrict = humanizeHealthcareDistrict(
selectedHealthCareDistrict
);
useEffect(() => {
if (typeof window !== undefined) {
toast({
position: 'bottom',
title: 'Datan lähteenä nyt THL',
description: 'HS:n datan lähde on vaihtunut THL:ään. THL:n tiedotussyklistä johtuen tiedot päivittyvät aiempaa harvemmin. Myös vanhemmissa tapauksissa voi olla päivämääräkohtaisia eroja, johtuen muuttuneesta raportointitavasta.',
status: "info",
isClosable: true,
duration: 14000,
});
}
}, [])
return (
<>
<Head>
<title>
{t('finland corona status')} - {t('cases')} : {confirmed.length || 0}{' '}
- {t('recovered')}: {recovered.length || 0} - {t('deaths')}:{' '}
{deaths.length || 0}
</title>
<meta
name="description"
content={`Suomen koronavirus-tartuntatilanne – tartunnat: ${confirmed.length ||
0} - parantuneet: ${recovered.length ||
0} - menehtyneet: ${deaths.length || 0}`}
/>
<meta property="og:title" content={t('finland corona status')} />
<meta
property="og:description"
content={`Tartuntoja tällä hetkellä: ${confirmed.length ||
0} - parantuneet: ${recovered.length ||
0} - menehtyneet: ${deaths.length || 0}`}
/>
<meta
property="og:site_name"
content="Suomen koronavirus-tartuntatilanne"
/>
<meta property="og:locale" content="fi_FI" />
<meta property="og:type" content="website" />
<meta property="og:image" content="/images/corona-virus.png" />
<meta property="og:image:width" content="1920" />
<meta property="og:image:height" content="1928" />
<meta property="og:url" content="https://korona.kans.io" />
</Head>
<Layout>
<Flex
alignItems="center"
flexDirection="column"
flex="1"
width={'100%'}
maxWidth="1440px"
margin="auto"
>
<Header />
<Flex
flexWrap="wrap"
flexDirection="row"
justifyContent="left"
alignItems="stretch"
flex="1"
width={'100%'}
>
<Box width={['100%', '100%', 1 / 3, 1 / 3]} p={3}>
<Select
value={selectedHealthCareDistrict ?? undefined}
onChange={event => selectHealthCareDistrict(event.target.value)}
>
<option key={'all'} value={'all'}>
{t('All healthcare districts')}
</option>
{healtCareDistricts.map(healthcareDistrict => (
<option
key={healthcareDistrict.name}
value={healthcareDistrict.name}
>
{healthcareDistrict.name}
</option>
))}
))}
</Select>
</Box>
</Flex>
<Flex
flexWrap="wrap"
flexDirection="row"
justifyContent="center"
alignItems="stretch"
flex="1"
width={'100%'}
>
<Box width={['100%', '100%', 1 / 2, 1 / 2]} p={3}>
<Block
title={t('cases') + ` (${humanizedHealthCareDistrict})`}
textAlign="center"
extraInfo={`${t('New cases today')} ${infectionsToday} ${t(
'person'
)}`}
footer={`${t(
'latest case'
)} ${latestInfection} (${humanizeHealthcareDistrict(
latestInfectionDistrict
)})`}
>
<StatBlock
count={confirmed.length}
helpText={`${t('New cases today')}: ${infectionsToday} ${t(
'person'
)}`}
/>
</Block>
</Box>
<Box width={['100%', '100%', 1 / 2, 1 / 2]} p={3}>
<Block
title={t('deaths') + ` (${humanizedHealthCareDistrict})`}
footer={
latestDeath
? `${t(
'last death'
)} ${latestDeath} (${humanizeHealthcareDistrict(
latestDeathDistrict!
)})`
: t('no death')
}
>
<StatBlock count={deaths.length || 0} />
</Block>
</Box>
{/* <Box width={['100%', '100%', 1 / 3, 1 / 3]} p={3}>
<Block
title={t('recovered') + ` (${humanizedHealthCareDistrict})`}
footer={
`${latestRecovered
? `${t(
'latest recovery'
)} ${latestRecovered} (${humanizeHealthcareDistrict(latestRecoveredDistrict!)}).`
: ' '} ${t('recoveredNotice')}`}
>
<StatBlock count={recovered.length || 0} />
</Block>
</Box> */}
<Box width={['100%']} p={3}>
<Block
title={
t('accumulated change') + ` (${humanizedHealthCareDistrict})`
}
footer={t('cases recovered and death in past 30 days')}
>
<ButtonGroup
spacing={0}
alignSelf="center"
display="flex"
justifyContent="center"
marginTop="-15px"
>
<Button
size="xs"
fontFamily="Space Grotesk Regular"
px={3}
letterSpacing="1px"
borderRadius="4px 0px 0px 4px"
borderWidth="0px"
isActive={cumulativeChartScale === 'linear'}
onClick={() => setCumulativeChartScale('linear')}
>
{t('linear')}
</Button>
<Button
size="xs"
fontFamily="Space Grotesk Regular"
px={3}
letterSpacing="1px"
borderRadius="0px 4px 4px 0px"
borderWidth="0px"
isActive={cumulativeChartScale === 'log'}
onClick={() => setCumulativeChartScale('log')}
>
{t('logarithmic')}
</Button>
</ButtonGroup>
<ResponsiveContainer width={'100%'} height={380}>
<ComposedChart
data={
cumulativeChartScale === 'log'
? infectionDevelopmentData30Days.map(zerosToNulls)
: infectionDevelopmentData30Days
}
margin={{ top: 20, right: 30, left: 0, bottom: 30 }}
>
<defs>
<linearGradient
id="colorInfection"
x1="0"
y1="0"
x2="0"
y2="1"
>
<stop
offset="5%"
stopColor={colors[8]}
stopOpacity={0.6}
/>
<stop
offset="95%"
stopColor={colors[8]}
stopOpacity={0}
/>
</linearGradient>
<linearGradient
id="colorRecovered"
x1="0"
y1="0"
x2="0"
y2="1"
>
<stop
offset="5%"
stopColor={colors[7]}
stopOpacity={0.6}
/>
<stop
offset="95%"
stopColor={colors[7]}
stopOpacity={0}
/>
</linearGradient>
<linearGradient
id="colorDeaths"
x1="0"
y1="0"
x2="0"
y2="1"
>
<stop
offset="5%"
stopColor={colors[0]}
stopOpacity={0.6}
/>
<stop
offset="95%"
stopColor={colors[0]}
stopOpacity={0}
/>
</linearGradient>
</defs>
<XAxis
tickFormatter={d => format(new Date(d), 'd.M.')}
tick={<CustomizedAxisTick isDate />}
dataKey="date"
domain={['dataMin', 'dataMax']}
type="number"
scale="time"
/>
<YAxis
scale={cumulativeChartScale}
dataKey="infections"
domain={[
cumulativeChartScale === 'log' ? 1 : 0,
dataMaxValue + 10
]}
unit={' ' + t('person')}
tick={{ fontSize: 12 }}
name={t('cases')}
/>
<CartesianGrid opacity={0.2} />
<Tooltip
labelFormatter={v => format(new Date(v), 'dd.MM.yyyy')}
/>
<Bar
isAnimationActive={false}
fill={colors[1]}
opacity={0.4}
dataKey="infectionsDaily"
name={t('cases of the day')}
unit={' ' + t('person')}
/>
<Area
isAnimationActive={false}
type="monotone"
unit={' ' + t('person')}
name={t('total cases')}
dataKey="infections"
stroke={colors[8]}
fillOpacity={1}
fill="url(#colorInfection)"
/>
{/* <Area
isAnimationActive={false}
type="monotone"
unit={' ' + t('person')}
name={t('total recovered')}
dataKey="recovered"
stroke={colors[7]}
fillOpacity={1}
fill="url(#colorRecovered)"
/> */}
<Area
isAnimationActive={false}
type="monotone"
unit={' ' + t('person')}
name={t('total deaths')}
dataKey="deaths"
stroke={colors[0]}
fillOpacity={1}
fill="url(#colorDeaths)"
/>
<Legend wrapperStyle={{ bottom: '10px' }} />
</ComposedChart>
</ResponsiveContainer>
</Block>
</Box>
{/*
<Box width={['100%']} p={3}>
<Block title="Tartuntojen kumulatiivinen ennustemalli" footer={`Tartuntojen kehityksen ennustemalli 60 päivää. Laskee ennustetun eksponentiaalisen kasvun käyttämällä aiemmin luotuja tietoja. Käytetty <a style="color: #319795;" href="https://github.com/mljs/regression-exponential" target="_blank">exponential-regression</a> kirjastoa.`}>
<ButtonGroup spacing={0} alignSelf="center" display="flex" justifyContent="center" marginTop="-15px">
<Button size="xs" fontFamily="Space Grotesk Regular" px={3} letterSpacing="1px" borderRadius="4px 0px 0px 4px" borderWidth="0px" isActive={forecastChartScale === 'linear'} onClick={() => setForecaseChartScale('linear')}>
Lineaarinen
</Button>
<Button size="xs" fontFamily="Space Grotesk Regular" px={3} letterSpacing="1px" borderRadius="0px 4px 4px 0px" borderWidth="0px" isActive={forecastChartScale === 'log'} onClick={() => setForecaseChartScale('log')}>
Logaritminen
</Button>
</ButtonGroup>
<ResponsiveContainer width={'100%'} height={350}>
<AreaChart
data={prediction60Days}
margin={{ top: 20, right: 30, left: 0, bottom: 20 }}
>
<defs>
<linearGradient id="colorInfection" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor={colors[8]} stopOpacity={0.6} />
<stop offset="95%" stopColor={colors[8]} stopOpacity={0} />
</linearGradient>
</defs>
<XAxis tickFormatter={d => format(new Date(d), 'd.M.')} tick={<CustomizedAxisTick isDate />} dataKey="date" domain={['dataMin', 'dataMax']} type="number" scale="time" />
<YAxis scale={forecastChartScale} dataKey="infections" domain={['auto', 'auto']} unit={' ' + t('person') } tick={{ fontSize: 12 }} name="Tartunnat" />
<CartesianGrid opacity={0.2} />
<ReferenceLine
x={today}
stroke="rgba(0,0,0,.5)"
// @ts-ignore
label={{ position: 'top', value: 'Nyt', fill: 'rgba(0,0,0,0.5)', fontSize: 12 }}
strokeDasharray="3 3" />
<Tooltip labelFormatter={v => format(new Date(v), 'dd.MM.yyyy')} />
<Area type="monotone" name="Ennuste" unit={' ' + t('person') } dataKey="infections" stroke={colors[8]} fillOpacity={1} fill="url(#colorInfection)" />
</AreaChart>
</ResponsiveContainer>
</Block>
</Box>
*/}
<Box width={['100%', '100%', '100%', '100%', 1 / 2]} p={3}>
<Block
title={t('Cases by district')}
footer={t('Helsinki metropolitan area is shown as HUS')}
>
<ResponsiveContainer width={'100%'} height={350}>
<BarChart
data={infectionsByDistrict}
margin={{
top: 20,
right: 30,
left: 0,
bottom: 85
}}
>
<XAxis
interval={0}
dataKey="name"
tick={<CustomizedAxisTick />}
/>
<YAxis
yAxisId="left"
unit={' ' + t('person')}
dataKey="infections"
tick={{ fontSize: 12 }}
/>
<Tooltip />
<Bar
isAnimationActive={false}
dataKey="infections"
name={t('cases')}
unit={' ' + t('person')}
yAxisId="left"
>
{areas.map((area, index) => (
<Cell key={area} fill={colors[index % colors.length]} />
))}
<LabelList
dataKey="infections"
position="top"
formatter={e => e}
/>
</Bar>
</BarChart>
</ResponsiveContainer>
</Block>
</Box>
<Box width={['100%', '100%', '100%', '100%', 1 / 2]} p={3}>
<Block
title={t('infectionsPerDisrictAndSize')}
footer={t('infectionsPerDisrictAndSize')}
>
<ResponsiveContainer width={'100%'} height={350}>
<BarChart
data={infectionsByDistrictPercentage}
margin={{
top: 20,
right: 30,
left: 0,
bottom: 85
}}
>
<XAxis
interval={0}
dataKey="name"
tick={<CustomizedAxisTick />}
/>
<YAxis
unit=" %"
dataKey="perDistrict"
tick={{ fontSize: 12 }}
/>
<Tooltip />
<Bar isAnimationActive={false} dataKey="perDistrict" name="%-osuus väestöstä" unit=" %">
{areas.map((area, index) => (
<Cell key={area} fill={colors[index % colors.length]} />
))}
<LabelList
dataKey="perDistict"
position="top"
formatter={e => e}
/>
</Bar>
</BarChart>
</ResponsiveContainer>
</Block>
</Box>
<Box width={['100%', '100%', '100%', '100%', 1 / 2]} p={3}>
<Block
title={t('log') + ` (${humanizedHealthCareDistrict})`}
footer={t('logFooter')}
>
<Table
height={500}
data={reversedConfirmed}
columns={useMemo(() => infectionColumns, [])}
/>
</Block>
</Box>
<BubbleChart data={groupedCoronaData} />
{/* <Box width={['100%', '100%', '100%', '100%', 1 / 2]} p={3}>
<Block
title={
t('infectionNetwork') + ` (${humanizedHealthCareDistrict})`
}
footer={t('infectionNetworkFooter')}
>
<NetworkGraph data={networkGraphData} />
</Block>
</Box> */}
<Box width={['100%']} p={3}>
<Block
title={
t('hospitalizedData') + ` (${t('All healthcare districts')})`
}
>
<ResponsiveContainer width={'100%'} height={350}>
<BarChart
data={hospitalised.slice(Math.max(hospitalised.length - 30, 0))}
margin={{
top: 20,
right: 30,
left: 0,
bottom: 85
}}
>
<XAxis
interval={0}
dataKey="dateString"
tick={<CustomizedAxisTick />}
padding={{ left: 50, right: 50 }}
/>
<YAxis
unit={' ' + t('person')}
dataKey="totalHospitalised"
tick={{ fontSize: 12 }}
/>
<Tooltip />
<Bar
isAnimationActive={false}
stackId="a"
dataKey="inIcu"
name={t("inIcu")}
unit={' ' + t('person')}
fill="#F3858D"
/>
<Bar
isAnimationActive={false}
stackId="a"
dataKey="inWard"
name={t("inWard")}
unit={' ' + t('person')}
fill="#2FAB8E"
/>
<Bar
isAnimationActive={false}
stackId="a"
dataKey="totalHospitalised"
opacity={0}
name={t("inHospital")}
unit={' ' + t('person')}
fill="rgba(0,0,0,1)"
strokeWidth={0}
legendType="none"
/>
<Legend wrapperStyle={{ bottom: '15px' }} />
</BarChart>
</ResponsiveContainer>
</Block>
</Box>
</Flex>
<Copyright />
</Flex>
</Layout>
</>
);
}
Example #24
Source File: BalanceHistoryGraph.tsx From abrechnung with GNU Affero General Public License v3.0 | 4 votes |
export default function BalanceHistoryGraph({ group, accountID }) {
const theme: Theme = useTheme();
const balanceHistory = useRecoilValue(accountBalanceHistory({ groupID: group.id, accountID: accountID }));
const history = useHistory();
const transactionMap = useRecoilValue(transactionByIDMap(group.id));
const accountMap = useRecoilValue(accountByIDMap(group.id));
const onClick = (evt) => {
if (evt.activePayload.length > 0) {
const payload = evt.activePayload[0].payload;
if (payload.changeOrigin.type === "clearing") {
history.push(`/groups/${group.id}/accounts/${payload.changeOrigin.id}`);
} else {
history.push(`/groups/${group.id}/transactions/${payload.changeOrigin.id}`);
}
}
};
const renderTooltip = ({ payload, label, active }) => {
if (!active) {
return null;
}
const changeOrigin = payload[0].payload.changeOrigin;
const icon =
changeOrigin.type === "clearing" ? (
<ClearingAccountIcon color="primary" fontSize="small" />
) : transactionMap[changeOrigin.id].type === "purchase" ? (
<PurchaseIcon color="primary" sx={{ fontSize: theme.typography.fontSize }} />
) : (
<TransferIcon color="primary" fontSize="small" />
);
return (
<Box
sx={{
backgroundColor: theme.palette.background.paper,
borderColor: theme.palette.divider,
borderRadius: theme.shape.borderRadius,
borderWidth: "1px",
borderStyle: "solid",
padding: 2,
}}
>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<Typography variant="body1" component="span">
{DateTime.fromSeconds(payload[0].payload.date).toISODate()} {icon}
</Typography>
<Typography
component="span"
sx={{ color: (theme) => balanceColor(payload[0].value, theme), ml: 2 }}
>
{payload[0].value} {group.currency_symbol}
</Typography>
</div>
<Divider />
{payload[0].payload.changeOrigin.type === "clearing" ? (
<Typography variant="body1">{accountMap[payload[0].payload.changeOrigin.id].name}</Typography>
) : (
<Typography variant="body1">
{transactionMap[payload[0].payload.changeOrigin.id].description}
</Typography>
)}
</Box>
);
};
return (
<ResponsiveContainer width="100%" height={300}>
<LineChart
width={730}
height={250}
onClick={onClick}
data={balanceHistory}
margin={{
top: 5,
right: 30,
left: 20,
bottom: 5,
}}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis
dataKey="date"
stroke={theme.palette.text.primary}
type="number"
tickFormatter={(unixTime) => DateTime.fromSeconds(unixTime).toISODate()}
domain={["dataMin", "dataMax"]}
/>
<YAxis
tickFormatter={(value) => value.toFixed(2)}
type="number"
unit={group.currency_symbol}
stroke={theme.palette.text.primary}
/>
<Tooltip content={renderTooltip} />
<Legend />
<Line type="stepAfter" dataKey="balance" />
</LineChart>
</ResponsiveContainer>
);
}
Example #25
Source File: LiquidityChart.tsx From mStable-apps with GNU Lesser General Public License v3.0 | 4 votes |
Chart: FC<{
aggregateMetrics: {
type: string
enabled: boolean
label: string
color: string
}[]
}> = ({ aggregateMetrics }) => {
const poolAddress = useSelectedFeederPoolAddress()
const data = useTotalLiquidity(poolAddress)
const dateFilter = useDateFilter()
const { metrics } = useMetricsState()
return (
<RechartsContainer>
{data.length < 2 && <NoData>No data yet</NoData>}
<ResponsiveContainer aspect={2} debounce={1} width="99%">
<AreaChart margin={{ top: 40, right: 0, bottom: 0, left: 0 }} barCategoryGap={1} data={data.length > 1 ? data : []}>
<defs>
{aggregateMetrics.map(({ type, color }) => (
<linearGradient id={type} key={type} x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor={color} stopOpacity={0.5} />
<stop offset="95%" stopColor={color} stopOpacity={0} />
</linearGradient>
))}
</defs>
<XAxis
dataKey="timestamp"
axisLine={false}
xAxisId={0}
height={0}
tick={false}
tickFormatter={timestamp => (timestamp ? format(timestamp * 1000, periodFormatMapping[dateFilter.period]) : '')}
/>
<YAxis
type="number"
orientation="left"
tickFormatter={toK}
axisLine={false}
interval="preserveEnd"
yAxisId={0}
tick={false}
width={0}
/>
<Tooltip
cursor
labelFormatter={timestamp => format((timestamp as number) * 1000, 'yyyy-MM-dd HH:mm')}
formatter={toK as never}
separator=""
contentStyle={{
fontSize: '14px',
padding: '8px',
background: 'rgba(255, 255, 255, 0.8)',
textAlign: 'right',
border: 'none',
borderRadius: '4px',
color: Color.black,
}}
wrapperStyle={{
top: 0,
left: 0,
}}
/>
{metrics.map(({ color, type, label, enabled }) => (
<Area
animationDuration={100}
key={type}
type="monotone"
hide={!enabled}
dataKey={type}
name={`${label} `}
opacity={1}
dot={false}
yAxisId={0}
stroke={color}
strokeWidth={2}
fill={`url(#${type})`}
/>
))}
</AreaChart>
</ResponsiveContainer>
</RechartsContainer>
)
}
Example #26
Source File: Balances.tsx From abrechnung with GNU Affero General Public License v3.0 | 4 votes |
export default function Balances({ group }) {
const theme: Theme = useTheme();
const isSmallScreen = useMediaQuery(theme.breakpoints.down("sm"));
const history = useHistory();
const personalAccounts = useRecoilValue(personalAccountsSeenByUser(group.id));
const clearingAccounts = useRecoilValue(clearingAccountsSeenByUser(group.id));
const balances = useRecoilValue(accountBalances(group.id));
const [selectedTab, setSelectedTab] = useState("1");
const colorGreen = theme.palette.mode === "light" ? theme.palette.success.light : theme.palette.success.dark;
const colorRed = theme.palette.mode === "light" ? theme.palette.error.light : theme.palette.error.dark;
const colorGreenInverted = theme.palette.mode === "dark" ? theme.palette.success.light : theme.palette.success.dark;
const colorRedInverted = theme.palette.mode === "dark" ? theme.palette.error.light : theme.palette.error.dark;
useTitle(`${group.name} - Balances`);
const chartData = personalAccounts.map((account) => {
return {
name: account.name,
balance: balances[account.id].balance,
totalPaid: balances[account.id].totalPaid,
totalConsumed: balances[account.id].totalConsumed,
id: account.id,
};
});
const unbalancedClearingAccounts = clearingAccounts
.filter((account) => balances[account.id].balance !== 0)
.map((account) => {
return {
name: account.name,
id: account.id,
balance: balances[account.id].balance,
};
});
const chartHeight = Object.keys(balances).length * 30 + 100;
// TODO determine the rendered width of the account names and take the maximum
const yaxiswidth = isSmallScreen
? Math.max(Math.max(...personalAccounts.map((account) => account.name.length)), 20)
: Math.max(...personalAccounts.map((account) => account.name.length)) * 7 + 5;
const handleBarClick = (data, event) => {
const id = data.activePayload[0].payload.id;
history.push(`/groups/${group.id}/accounts/${id}`);
};
return (
<MobilePaper>
<TabContext value={selectedTab}>
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
<TabList onChange={(event, idx) => setSelectedTab(idx)} centered>
<Tab label="Chart" value="1" />
<Tab label="Table" value="2" />
</TabList>
</Box>
<TabPanel value="1" sx={{ padding: { xs: 1, md: 2 } }}>
{personalAccounts.length === 0 && <Alert severity="info">No Accounts</Alert>}
{unbalancedClearingAccounts.length !== 0 && (
<Alert severity="info">
<AlertTitle>Some Clearing Accounts have remaining balances.</AlertTitle>
{unbalancedClearingAccounts.map((account) => (
<Typography variant="body2" key={account.id} component="span">
<>{account.name}:</>
<Typography
variant="body2"
component="span"
sx={{ color: account.balance < 0 ? colorRedInverted : colorGreenInverted }}
>
{account.balance.toFixed(2)} {group.currency_symbol}{" "}
</Typography>
</Typography>
))}
</Alert>
)}
{isSmallScreen ? (
<List>
{personalAccounts.map((account) => (
<>
<ListItemLink key={account.id} to={`/groups/${group.id}/accounts/${account.id}`}>
<ListItemText primary={account.name} />
<Typography
align="right"
variant="body2"
sx={{
color:
balances[account.id].balance < 0
? colorRedInverted
: colorGreenInverted,
}}
>
{balances[account.id].balance.toFixed(2)} {group.currency_symbol}
</Typography>
</ListItemLink>
<Divider key={account.id * 2} component="li" />
</>
))}
</List>
) : (
<div className="area-chart-wrapper" style={{ width: "100%", height: `${chartHeight}px` }}>
<ResponsiveContainer>
<BarChart
data={chartData}
margin={{
top: 20,
right: 20,
bottom: 20,
left: 20,
}}
layout="vertical"
onClick={handleBarClick}
>
<XAxis
stroke={theme.palette.text.primary}
type="number"
unit={group.currency_symbol}
/>
<YAxis
dataKey="name"
stroke={theme.palette.text.primary}
type="category"
width={yaxiswidth}
/>
<Tooltip
formatter={(label) =>
parseFloat(label).toFixed(2) + ` ${group.currency_symbol}`
}
labelStyle={{
color: theme.palette.text.primary,
}}
itemStyle={{
color: theme.palette.text.primary,
}}
contentStyle={{
backgroundColor: theme.palette.background.paper,
borderColor: theme.palette.divider,
borderRadius: theme.shape.borderRadius,
}}
/>
<Bar dataKey="balance">
{chartData.map((entry, index) => {
return (
<Cell
key={`cell-${index}`}
fill={entry["balance"] >= 0 ? colorGreen : colorRed}
/>
);
})}
<LabelList
dataKey={(entry) =>
`${entry["balance"].toFixed(2)}${group.currency_symbol}`
}
position="insideLeft"
fill={theme.palette.text.primary}
/>
</Bar>
</BarChart>
</ResponsiveContainer>
</div>
)}
</TabPanel>
<TabPanel value="2" sx={{ padding: { xs: 1, md: 2 } }}>
<BalanceTable group={group} />
</TabPanel>
</TabContext>
</MobilePaper>
);
}
Example #27
Source File: ArtistListeningRepartition.tsx From your_spotify with GNU General Public License v3.0 | 4 votes |
export default function ArtistListeningRepartition({ className }: ArtistListeningRepartitionProps) {
const { interval } = useSelector(selectRawIntervalDetail);
const results = useAPI(api.mostListenedArtist, interval.start, interval.end, interval.timesplit);
const resultsWithCount = useMemo(
() =>
results?.map((res) => ({
_id: res._id,
artists: res.artists.reduce<Record<string, number>>((acc, curr, idx) => {
acc[curr.id] = res.counts[idx];
return acc;
}, {}),
})),
[results],
);
const allArtists = useMemo(() => {
const all: Record<string, Artist> = {};
results?.forEach((res) => {
res.artists.forEach((art) => {
if (!(art.id in all)) {
all[art.id] = art;
}
});
});
return all;
}, [results]);
const data = useMemo(() => {
if (!resultsWithCount) {
return [];
}
const d = resultsWithCount.map((curr, idx) => {
const obj: { x: number; _id: DateId } & any = {
x: idx,
_id: curr._id as DateId,
};
const total = Object.values(curr.artists).reduce((acc, count) => acc + count, 0);
Object.values(allArtists).forEach((art) => {
obj[art.id] = (curr.artists[art.id] ?? 0) / total;
});
return obj;
}, []);
return buildXYDataObjSpread(d, Object.keys(allArtists), interval.start, interval.end, false);
}, [allArtists, interval, resultsWithCount]);
const tooltipLabelFormatter = useRawTooltipLabelFormatter(formatXAxisDateTooltip, false);
const tooltipValueFormatter = useCallback(
(value: number, label: string) => {
if (value === 0) {
return [<span />];
}
return [`${allArtists[label].name}: ${Math.floor(value * 1000) / 10}%`];
},
[allArtists],
);
const tooltipSorter = useCallback((a: any) => {
return -a.payload[a.dataKey];
}, []);
const formatX = useFormatXAxis(data);
if (!results) {
return <LoadingImplementedChart title="Artist listening distribution" className={className} />;
}
return (
<ChartCard title="Artist listening distribution" className={className}>
<ResponsiveContainer width="100%" height="100%">
<AreaChart data={data}>
<XAxis dataKey="x" tickFormatter={formatX} style={{ fontWeight: 'bold' }} />
<YAxis domain={[0, 1]} tickFormatter={formatYAxis} />
<Tooltip
formatter={tooltipValueFormatter}
labelFormatter={tooltipLabelFormatter}
wrapperStyle={{ zIndex: 1000 }}
contentStyle={{ background: 'var(--background)' }}
itemSorter={tooltipSorter}
/>
{Object.values(allArtists).map((art, idx) => (
<Area
type="monotone"
dataKey={art.id}
key={art.id}
stackId={-1}
stroke={getColor(idx)}
fill={getColor(idx)}
/>
))}
</AreaChart>
</ResponsiveContainer>
</ChartCard>
);
}
Example #28
Source File: LinearGraphWidget.tsx From console with GNU Affero General Public License v3.0 | 4 votes |
LinearGraphWidget = ({
classes,
title,
timeStart,
timeEnd,
propLoading,
panelItem,
apiPrefix,
hideYAxis = false,
areaWidget = false,
yAxisFormatter = (item: string) => item,
xAxisFormatter = (item: string) => item,
zoomActivated = false,
}: ILinearGraphWidget) => {
const dispatch = useDispatch();
const [loading, setLoading] = useState<boolean>(true);
const [data, setData] = useState<object[]>([]);
const [dataMax, setDataMax] = useState<number>(0);
const [result, setResult] = useState<IDashboardPanel | null>(null);
useEffect(() => {
if (propLoading) {
setLoading(true);
}
}, [propLoading]);
useEffect(() => {
if (loading) {
let stepCalc = 0;
if (timeStart !== null && timeEnd !== null) {
const secondsInPeriod = timeEnd.unix() - timeStart.unix();
const periods = Math.floor(secondsInPeriod / 60);
stepCalc = periods < 1 ? 15 : periods;
}
api
.invoke(
"GET",
`/api/v1/${apiPrefix}/info/widgets/${
panelItem.id
}/?step=${stepCalc}&${
timeStart !== null ? `&start=${timeStart.unix()}` : ""
}${timeStart !== null && timeEnd !== null ? "&" : ""}${
timeEnd !== null ? `end=${timeEnd.unix()}` : ""
}`
)
.then((res: any) => {
const widgetsWithValue = widgetDetailsToPanel(res, panelItem);
setData(widgetsWithValue.data);
setResult(widgetsWithValue);
setLoading(false);
let maxVal = 0;
for (const dp of widgetsWithValue.data) {
for (const key in dp) {
if (key === "name") {
continue;
}
let val = parseInt(dp[key]);
if (isNaN(val)) {
val = 0;
}
if (maxVal < val) {
maxVal = val;
}
}
}
setDataMax(maxVal);
})
.catch((err: ErrorResponseHandler) => {
dispatch(setErrorSnackMessage(err));
setLoading(false);
});
}
}, [loading, panelItem, timeEnd, timeStart, dispatch, apiPrefix]);
let intervalCount = Math.floor(data.length / 5);
const linearConfiguration = result
? (result?.widgetConfiguration as ILinearGraphConfiguration[])
: [];
const CustomizedDot = (prop: any) => {
const { cx, cy, index } = prop;
if (index % 3 !== 0) {
return null;
}
return <circle cx={cx} cy={cy} r={3} strokeWidth={0} fill="#07264A" />;
};
const theme = useTheme();
const biggerThanMd = useMediaQuery(theme.breakpoints.up("md"));
return (
<Box className={zoomActivated ? "" : classes.singleValueContainer}>
{!zoomActivated && (
<div className={classes.titleContainer}>
{title} <ExpandGraphLink panelItem={panelItem} />
</div>
)}
<Box
sx={
zoomActivated
? { flexDirection: "column" }
: {
height: "100%",
display: "grid",
gridTemplateColumns: {
md: "1fr 1fr",
sm: "1fr",
},
}
}
style={areaWidget ? { gridTemplateColumns: "1fr" } : {}}
>
{loading && <Loader className={classes.loadingAlign} />}
{!loading && (
<React.Fragment>
<div
className={
zoomActivated ? classes.zoomChartCont : classes.chartCont
}
>
<ResponsiveContainer width="99%">
<AreaChart
data={data}
margin={{
top: 5,
right: 20,
left: hideYAxis ? 20 : 5,
bottom: 0,
}}
>
{areaWidget && (
<defs>
<linearGradient id="colorUv" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor="#2781B0" stopOpacity={1} />
<stop
offset="100%"
stopColor="#ffffff"
stopOpacity={0}
/>
<stop
offset="95%"
stopColor="#ffffff"
stopOpacity={0.8}
/>
</linearGradient>
</defs>
)}
<CartesianGrid
strokeDasharray={areaWidget ? "2 2" : "5 5"}
strokeWidth={1}
strokeOpacity={1}
stroke={"#eee0e0"}
vertical={!areaWidget}
/>
<XAxis
dataKey="name"
tickFormatter={(value: any) => xAxisFormatter(value)}
interval={intervalCount}
tick={{
fontSize: "68%",
fontWeight: "normal",
color: "#404143",
}}
tickCount={10}
stroke={"#082045"}
/>
<YAxis
type={"number"}
domain={[0, dataMax * 1.1]}
hide={hideYAxis}
tickFormatter={(value: any) => yAxisFormatter(value)}
tick={{
fontSize: "68%",
fontWeight: "normal",
color: "#404143",
}}
stroke={"#082045"}
/>
{linearConfiguration.map((section, index) => {
return (
<Area
key={`area-${section.dataKey}-${index.toString()}`}
type="monotone"
dataKey={section.dataKey}
isAnimationActive={false}
stroke={!areaWidget ? section.lineColor : "#D7E5F8"}
fill={areaWidget ? "url(#colorUv)" : section.fillColor}
fillOpacity={areaWidget ? 0.65 : 0}
strokeWidth={!areaWidget ? 3 : 0}
strokeLinecap={"round"}
dot={areaWidget ? <CustomizedDot /> : false}
/>
);
})}
<Tooltip
content={
<LineChartTooltip
linearConfiguration={linearConfiguration}
yAxisFormatter={yAxisFormatter}
/>
}
wrapperStyle={{
zIndex: 5000,
}}
/>
</AreaChart>
</ResponsiveContainer>
</div>
{!areaWidget && (
<Fragment>
{zoomActivated && (
<Fragment>
<strong>Series</strong>
<br />
<br />
</Fragment>
)}
{biggerThanMd && (
<div className={classes.legendChart}>
{linearConfiguration.map((section, index) => {
return (
<div
className={classes.singleLegendContainer}
key={`legend-${section.keyLabel}-${index.toString()}`}
>
<div
className={classes.colorContainer}
style={{ backgroundColor: section.lineColor }}
/>
<div className={classes.legendLabel}>
{section.keyLabel}
</div>
</div>
);
})}
</div>
)}
</Fragment>
)}
</React.Fragment>
)}
</Box>
</Box>
);
}
Example #29
Source File: stage-chart.tsx From backstage with Apache License 2.0 | 4 votes |
export function StageChart(props: StageChartProps) {
const { stage, ...chartOptions } = props;
const {
chartTypes,
defaultCollapsed = 0,
defaultHidden = 0,
zeroYAxis = false,
} = chartOptions;
const { zoomFilterValues } = useZoom();
const { zoomProps, getZoomArea } = useZoomArea();
const ticks = useMemo(
() => pickElements(stage.values, 8).map(val => val.__epoch),
[stage.values],
);
const domainY = useMemo(
() => [zeroYAxis ? 0 : 'auto', 'auto'] as YAxisProps['domain'],
[zeroYAxis],
);
const statuses = useMemo(
() => statusTypes.filter(status => stage.statusSet.has(status)),
[stage.statusSet],
);
const legendPayload = useMemo(
(): LegendProps['payload'] =>
statuses.map(status => ({
value: capitalize(status),
type: 'line',
id: status,
color: statusColorMap[status],
})),
[statuses],
);
const subStages = useMemo(
() =>
new Map<string, ChartableStage>(
[...stage.stages.entries()].filter(
([_name, subStage]) => subStage.combinedAnalysis.max > defaultHidden,
),
),
[stage.stages, defaultHidden],
);
const zoomFilteredValues = useMemo(
() => zoomFilterValues(stage.values),
[stage.values, zoomFilterValues],
);
return stage.combinedAnalysis.max < defaultHidden ? null : (
<Accordion
defaultExpanded={stage.combinedAnalysis.max > defaultCollapsed}
TransitionProps={transitionProps}
>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
<Typography>
{stage.name} (med {formatDuration(stage.combinedAnalysis.med)}, avg{' '}
{formatDuration(stage.combinedAnalysis.avg)})
</Typography>
</AccordionSummary>
<AccordionDetails>
{stage.values.length === 0 ? (
<Alert severity="info">No data</Alert>
) : (
<Grid container direction="column">
<Grid item style={noUserSelect}>
<ResponsiveContainer width="100%" height={140}>
<ComposedChart data={zoomFilteredValues} {...zoomProps}>
<defs>
<linearGradient id="colorDur" x1="0" y1="0" x2="0" y2="1">
{fireColors.map(([percent, color]) => (
<stop
key={percent}
offset={percent}
stopColor={color}
stopOpacity={0.8}
/>
))}
</linearGradient>
</defs>
{statuses.length > 1 && <Legend payload={legendPayload} />}
<CartesianGrid strokeDasharray="3 3" />
<XAxis
dataKey="__epoch"
type="category"
ticks={ticks}
tickFormatter={tickFormatterX}
/>
<YAxis
yAxisId={1}
tickFormatter={tickFormatterY}
type="number"
tickCount={5}
name="Duration"
domain={domainY}
/>
<YAxis
yAxisId={2}
orientation="right"
type="number"
tickCount={5}
name="Count"
/>
<Tooltip
formatter={tooltipValueFormatter}
labelFormatter={labelFormatter}
/>
{statuses.reverse().map(status => (
<Fragment key={status}>
{!chartTypes[status].includes('duration') ? null : (
<>
<Area
isAnimationActive={false}
yAxisId={1}
type="monotone"
dataKey={status}
stackId={status}
stroke={
statuses.length > 1
? statusColorMap[status]
: colorStroke
}
fillOpacity={statuses.length > 1 ? 0.5 : 1}
fill={
statuses.length > 1
? statusColorMap[status]
: 'url(#colorDur)'
}
connectNulls
/>
<Line
isAnimationActive={false}
yAxisId={1}
type="monotone"
dataKey={`${status} avg`}
stroke={
statuses.length > 1
? statusColorMap[status]
: colorStrokeAvg
}
opacity={0.8}
strokeWidth={2}
dot={false}
connectNulls
/>
</>
)}
{!chartTypes[status].includes('count') ? null : (
<Bar
isAnimationActive={false}
yAxisId={2}
type="monotone"
dataKey={`${status} count`}
stackId="1"
stroke={statusColorMap[status] ?? ''}
fillOpacity={0.5}
fill={statusColorMap[status] ?? ''}
/>
)}
</Fragment>
))}
{getZoomArea({ yAxisId: 1 })}
</ComposedChart>
</ResponsiveContainer>
</Grid>
{subStages.size === 0 ? null : (
<Grid item>
<Accordion
defaultExpanded={false}
TransitionProps={transitionProps}
>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
<Typography>Sub stages ({subStages.size})</Typography>
</AccordionSummary>
<AccordionDetails>
<div style={fullWidth}>
{[...subStages.values()].map(subStage => (
<StageChart
key={subStage.name}
{...chartOptions}
stage={subStage}
/>
))}
</div>
</AccordionDetails>
</Accordion>
</Grid>
)}
</Grid>
)}
</AccordionDetails>
</Accordion>
);
}