recharts#Line TypeScript Examples
The following examples show how to use
recharts#Line.
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: 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 #3
Source File: PeriodByResponderGraph.tsx From backstage-plugin-opsgenie with MIT License | 6 votes |
PeriodByResponderGraph = ({data}: {data: IncidentsByResponders}) => {
return (
<ResponsiveContainer>
<ComposedChart data={data.dataPoints}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="period" />
<YAxis />
{data.responders.map(responder => (
<Bar dataKey={responder} fill={colorForString(responder)} stackId="a" barSize={30} key={responder} />
))}
<Line type="monotone" dataKey="total" name="Total" stroke="#ff7300" />
<Tooltip content={<FilterZeroTooltip />} />
<Legend />
</ComposedChart>
</ResponsiveContainer>
);
}
Example #4
Source File: WeeklyIncidents.tsx From backstage-plugin-opsgenie with MIT License | 6 votes |
Graph = ({context}: {context: Context}) => {
const analyticsApi = useApi(analyticsApiRef);
const dataPoints = analyticsApi.incidentsByWeekAndHours(context);
return (
<div id="weekly-incidents" style={{ width: '100%', height: 300, paddingTop: '1.2rem', paddingRight: '1.2rem' }}>
<ResponsiveContainer>
<ComposedChart
data={dataPoints}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="week" />
<YAxis />
<Bar dataKey="businessHours" fill="#82ca9d" name="Business hours" stackId="a" barSize={30} />
<Bar dataKey="onCallHours" fill="#8884d8" name="On-call hours" stackId="a" barSize={30} />
<Line type="monotone" dataKey="total" name="Total" stroke="#ff7300" />
<Tooltip content={<FilterZeroTooltip />} />
<Legend />
</ComposedChart>
</ResponsiveContainer>
</div>
);
}
Example #5
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 #6
Source File: DailyStatsChart.tsx From asynqmon with MIT License | 6 votes |
export default function DailyStatsChart(props: Props) {
const data = makeChartData(props.data, props.numDays);
const theme = useTheme<Theme>();
return (
<ResponsiveContainer>
<LineChart data={data}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis
dataKey="date"
minTickGap={10}
stroke={theme.palette.text.secondary}
/>
<YAxis stroke={theme.palette.text.secondary} />
<Tooltip />
<Legend />
<Line
type="monotone"
dataKey="succeeded"
stroke={theme.palette.success.main}
/>
<Line
type="monotone"
dataKey="failed"
stroke={theme.palette.error.main}
/>
</LineChart>
</ResponsiveContainer>
);
}
Example #7
Source File: ChartCard.tsx From genshin-optimizer with MIT License | 6 votes |
function Chart({ displayData, plotNode, valueNode, showMin }: {
displayData: Point[],
plotNode: NumNode,
valueNode: NumNode,
showMin: boolean
}) {
const plotBaseUnit = KeyMap.unit(plotNode.info?.key)
const valueUnit = KeyMap.unit(valueNode.info?.key)
return <ResponsiveContainer width="100%" height={600}>
<ComposedChart data={displayData}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="x" scale="linear" unit={plotBaseUnit} domain={["auto", "auto"]} tick={{ fill: 'white' }} type="number" tickFormatter={n => n > 10000 ? n.toFixed() : n.toFixed(1)} />
<YAxis name="DMG" domain={["auto", "auto"]} unit={valueUnit} allowDecimals={false} tick={{ fill: 'white' }} type="number" />
<ZAxis dataKey="y" range={[3, 25]} />
<Legend />
<Scatter name="Optimization Target" dataKey="y" fill="#8884d8" line lineType="fitting" isAnimationActive={false} />
{showMin && <Line name="Minimum Stat Requirement Threshold" dataKey="min" stroke="#ff7300" type="stepBefore" connectNulls strokeWidth={2} isAnimationActive={false} />}
</ComposedChart>
</ResponsiveContainer>
}
Example #8
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 #9
Source File: LineChart.tsx From opensaas with MIT License | 6 votes |
LineChart: React.FC<LineChartProps> = (props) => {
const { width, height, data, xAxis, line, showGrid, colors } = props;
return (
<ResponsiveContainer>
<RechartsLineChart width={width} height={height}>
{showGrid ? <CartesianGrid strokeDasharray='3 3' /> : null}
<XAxis dataKey='category' type={xAxis.type} allowDuplicatedCategory={false} axisLine={false} tickLine={false} />
<YAxis dataKey='value' axisLine={false} tickLine={false} />
<Tooltip />
<Legend verticalAlign='top' />
{data.map(({ data, name }, index: number) => (
<Line
strokeWidth={line.strokeWidth}
legendType='circle'
type={line.type}
stroke={colors[index % colors.length]}
dataKey='value'
data={data}
name={name}
key={name}
activeDot={line.activeDot}
/>
))}
</RechartsLineChart>
</ResponsiveContainer>
);
}
Example #10
Source File: RegionDailyCasesChart.tsx From covid19map with MIT License | 6 votes |
RegionDailyCasesChart = ({ history }: { history: any }) => {
const theme = useTheme();
return (
<StyledRegionDailyCasesChart>
<h3>Daily Cases</h3>
<div className="chart-wrap">
<ResponsiveContainer>
<LineChart
data={history}
margin={{ left: -30, right: 10, bottom: 20 }}
>
<XAxis
dataKey="date"
label={{
fontSize: 12,
value: "Days since first case detected",
position: "bottom",
}}
tickFormatter={(tick) =>
history.findIndex((x: any) => x.date === tick)
}
/>
<YAxis />
<Line
type="monotone"
dataKey="new"
stroke={theme.teal}
strokeWidth={1}
dot={false}
isAnimationActive={false}
/>
</LineChart>
</ResponsiveContainer>
</div>
</StyledRegionDailyCasesChart>
);
}
Example #11
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 #12
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 #13
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 #14
Source File: TotalChart.tsx From covid19map with MIT License | 5 votes |
TotalChart = ({ summary }: { summary: any }) => {
const theme = useTheme();
return (
<Chart>
<div className="head">Total cases</div>
<div className="chart-wrap">
<ResponsiveContainer>
<LineChart
data={summary}
margin={{ left: -30, right: 10, bottom: 20 }}
>
<XAxis
dataKey="date"
label={{
fill: theme.navy,
fontSize: 12,
value: "Days since first case detected",
position: "bottom",
}}
tickFormatter={(tick) =>
summary.findIndex((x: any) => x.date === tick)
}
/>
<YAxis />
<Line
type="monotone"
dataKey="recoveredTotal"
stroke={theme.green}
strokeWidth={4}
dot={false}
/>
<Line
type="monotone"
dataKey="combinedTotal"
stroke={theme.teal}
strokeWidth={4}
dot={false}
/>
{/* <Line
type="monotone"
dataKey="deathsTotal"
stroke="red"
strokeWidth={2}
dot={false}
/> */}
<ReferenceLine x="2020-03-25T00:00:00.000Z" stroke="#025064" />
</LineChart>
</ResponsiveContainer>
<ChartLegend
items={[
{ title: "Total", color: theme.teal },
{ title: "Recovered", color: theme.green },
// { title: "Lv4 lockdown", color: theme.navy },
]}
/>
</div>
</Chart>
);
}
Example #15
Source File: LocationBar.tsx From covid19map with MIT License | 5 votes |
LocationBar = ({
location,
history,
onClick,
}: {
location: any;
history: any;
onClick?: (event: MouseEvent) => void;
}) => {
const theme = useTheme();
if (!location || !history) {
return <div />;
}
return (
<StyledLocationBar>
<div
className="head"
onClick={() => {
if (onClick) {
onClick(location.name);
gtag.event("View location", "", location.name);
}
}}
>
<div className="stats">
<div>
<span className="name">{location.name}</span>
<CaseCounts>
<ul>
<li>
<img src={require(`../public/active.svg`)} />{" "}
{location.totalCases}
</li>
<li>
<img src={require(`../public/recovered.svg`)} />{" "}
{location.recovered}
</li>
<li>
<img src={require(`../public/deaths.svg`)} />{" "}
{location.deaths}
</li>
</ul>
</CaseCounts>
</div>
<div className="num-cases">
<div className="total-cases">{location.active}</div>
{location.newCases > 0 && <small>+{location.newCases}</small>}
</div>
</div>
<InlineChart>
<ResponsiveContainer>
<LineChart data={history}>
<XAxis dataKey="date" hide />
<Line
type="monotone"
dataKey="new"
stroke={theme.teal}
strokeWidth={1}
dot={false}
isAnimationActive={false}
/>
</LineChart>
</ResponsiveContainer>
</InlineChart>
</div>
</StyledLocationBar>
);
}
Example #16
Source File: InternationalLineChart.tsx From covid19map with MIT License | 5 votes |
TotalChart = ({ data }: { data: any }) => {
const theme = useTheme();
const countries: any = {
NZL: { name: "NZ", color: theme.teal },
AUS: { name: "AU", color: theme.green },
USA: { name: "USA", color: theme.navy },
CHN: { name: "CHINA", color: "#317c3f" },
ITA: { name: "ITALY", color: "#956828" },
GBR: { name: "UK", color: "#d4b074" },
KOR: { name: "S.KOREA", color: theme.yellow },
};
const countriesArray = Object.keys(countries).map((countryName, i) => {
return { key: countryName, ...countries[countryName] };
});
const countriesSortedArray = [...countriesArray].sort((x, y) =>
x.name === "NZ" ? 1 : -1
);
return (
<Chart>
<div className="head">Total cases</div>
<div className="chart-wrap">
<ResponsiveContainer>
<LineChart
data={data}
margin={{ top: 10, left: -5, right: 10, bottom: 20 }}
>
<XAxis
dataKey="day"
label={{
fontSize: 12,
value: "Days since 50 confirmed cases detected",
position: "bottom",
}}
/>
<YAxis scale="log" domain={["auto", "auto"]} />
{countriesSortedArray.map((item, i) => (
<Line
key={i}
type="monotone"
dataKey={item.key}
stroke={item.color}
strokeWidth={item.name === "NZ" ? 5 : 3}
dot={false}
/>
))}
</LineChart>
</ResponsiveContainer>
<ChartLegend
items={[
...countriesArray.map(({ name: title, color }, i) => ({
title,
color,
})),
]}
/>
</div>
</Chart>
);
}
Example #17
Source File: DailyChart.tsx From covid19map with MIT License | 5 votes |
TotalChart = ({ summary }: { summary: any }) => {
const theme = useTheme();
return (
<Chart>
<div className="head">Daily cases</div>
<div className="chart-wrap">
<ResponsiveContainer>
<LineChart
data={summary}
margin={{ left: -30, right: 10, bottom: 20 }}
>
<XAxis
dataKey="date"
label={{
fill: theme.navy,
fontSize: 12,
value: "Days since first case detected",
position: "bottom",
}}
tickFormatter={(tick) =>
summary.findIndex((x: any) => x.date === tick)
}
/>
<YAxis />
<Line
type="monotone"
dataKey="recovered"
stroke="#aacd6e"
strokeWidth={4}
dot={false}
/>
<Line
type="monotone"
dataKey="combined"
stroke="#ffc906"
strokeWidth={4}
dot={false}
/>
<ReferenceLine x="2020-03-25T00:00:00.000Z" stroke="#025064" />
</LineChart>
</ResponsiveContainer>
<ChartLegend
items={[
{ title: "New", color: theme.yellow },
{ title: "Recovered", color: theme.green },
// { title: "Lv4 lockdown", color: theme.navy },
]}
/>
</div>
</Chart>
);
}
Example #18
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 #19
Source File: Chart.tsx From crypto-fees with MIT License | 4 votes |
Chart: React.FC<SeriesChartProps> = ({
data,
primary,
secondary,
loading,
protocols,
server,
events,
}) => {
const [tooltip, setTooltip] = useState<null | ActiveTooltip>(null);
const color = 'blue';
const textColor = 'black';
const Container: any = server ? 'div' : ResponsiveContainer;
const margin = server
? { top: 20, right: 20, bottom: 20, left: 20 }
: { top: 0, right: 10, bottom: 6, left: 0 };
const width = server ? 380 : 500;
return (
<Container height={200}>
<LineChart height={200} width={width} margin={margin} barCategoryGap={1} data={data}>
<XAxis
tickLine={false}
stroke="#efefef"
interval="preserveStartEnd"
tickMargin={14}
minTickGap={0}
tickFormatter={(tick: any) => toNiceDate(tick)}
dataKey="date"
tick={{ fill: textColor }}
type={'number'}
domain={['dataMin', 'dataMax']}
/>
<YAxis
type="number"
orientation="right"
tickFormatter={(tick: any) => '$' + toK(tick)}
stroke="#efefef"
interval="preserveEnd"
minTickGap={80}
yAxisId={0}
tickMargin={16}
tick={{ fill: textColor }}
/>
<Tooltip
cursor={true}
separator={tooltip ? null : ' : '}
formatter={(val: any) => (tooltip ? [tooltip.description] : formattedNum(val))}
labelFormatter={(label: any) => toNiceDateYear(label)}
labelStyle={{ paddingTop: 4 }}
position={tooltip?.point}
contentStyle={{
padding: '10px 14px',
borderRadius: 10,
borderColor: color,
color: 'black',
maxWidth: 250,
whiteSpace: 'normal',
}}
wrapperStyle={{ top: -70, left: -10 }}
/>
<Line
strokeWidth={2}
dot={false}
type="monotone"
name={protocols[primary]}
dataKey="primary"
yAxisId={0}
stroke="#f2a900"
/>
{events?.map((event) => (
<ReferenceDot
key={event.description}
x={dateToTimestamp(event.date)}
y={findFee(data, dateToTimestamp(event.date))}
r={4}
fill="#b957af"
onMouseOver={(e: any) =>
setTooltip({
description: event.description,
point: { x: e.cx + 10, y: e.cy - 10 },
})
}
onMouseOut={() => setTooltip(null)}
/>
))}
{secondary && (
<Line
strokeWidth={2}
dot={false}
type="monotone"
name={protocols[secondary]}
dataKey="secondary"
yAxisId={0}
stroke="#d6d3cc"
/>
)}
{loading && <rect height="100%" width="100%" opacity="0.5" fill="#666" />}
</LineChart>
</Container>
);
}
Example #20
Source File: CostOverviewChart.tsx From backstage with Apache License 2.0 | 4 votes |
CostOverviewChart = ({
dailyCostData,
metric,
metricData,
responsive = true,
}: CostOverviewChartProps) => {
const theme = useTheme<CostInsightsTheme>();
const styles = useStyles(theme);
const data = {
dailyCost: {
dataKey: 'dailyCost',
name: `Daily Cost`,
format: 'currency',
data: dailyCostData,
},
metric: {
dataKey: metric?.kind ?? 'Unknown',
name: metric?.name ?? 'Unknown',
format: metricData?.format ?? 'number',
data: metricData,
},
};
const metricsByDate = data.metric.data
? data.metric.data.aggregation.reduce(groupByDate, {})
: {};
const chartData: ChartData[] = data.dailyCost.data.aggregation
.slice()
.sort(aggregationSort)
.map(entry => ({
date: Date.parse(entry.date),
trend: trendFrom(data.dailyCost.data.trendline!, Date.parse(entry.date)),
dailyCost: entry.amount,
...(metric && data.metric.data
? { [data.metric.dataKey]: metricsByDate[`${entry.date}`] }
: {}),
}));
const tooltipRenderer: ContentRenderer<TooltipProps> = ({
label,
payload = [],
}) => {
if (isInvalid({ label, payload })) return null;
const dataKeys = [data.dailyCost.dataKey, data.metric.dataKey];
const date =
typeof label === 'number'
? DateTime.fromMillis(label)
: DateTime.fromISO(label!);
const title = date.toUTC().toFormat(DEFAULT_DATE_FORMAT);
const items = payload
.filter(p => dataKeys.includes(p.dataKey as string))
.map(p => ({
label:
p.dataKey === data.dailyCost.dataKey
? data.dailyCost.name
: data.metric.name,
value:
p.dataKey === data.dailyCost.dataKey
? formatGraphValue(p.value as number, data.dailyCost.format)
: formatGraphValue(p.value as number, data.metric.format),
fill:
p.dataKey === data.dailyCost.dataKey
? theme.palette.blue
: theme.palette.magenta,
}));
return (
<Tooltip title={title}>
{items.map((item, index) => (
<TooltipItem key={`${item.label}-${index}`} item={item} />
))}
</Tooltip>
);
};
return (
<Box display="flex" flexDirection="column">
<CostOverviewLegend
dailyCostData={dailyCostData}
metric={metric}
metricData={metricData}
/>
<ResponsiveContainer
width={responsive ? '100%' : styles.container.width}
height={styles.container.height}
className="cost-overview-chart"
>
<ComposedChart margin={styles.chart.margin} data={chartData}>
<CartesianGrid stroke={styles.cartesianGrid.stroke} />
<XAxis
dataKey="date"
domain={['dataMin', 'dataMax']}
tickFormatter={overviewGraphTickFormatter}
tickCount={6}
type="number"
stroke={styles.axis.fill}
/>
<YAxis
domain={[() => 0, 'dataMax']}
tick={{ fill: styles.axis.fill }}
tickFormatter={formatGraphValue}
width={styles.yAxis.width}
yAxisId={data.dailyCost.dataKey}
/>
{metric && (
<YAxis
hide
domain={[() => 0, toDataMax(data.metric.dataKey, chartData)]}
width={styles.yAxis.width}
yAxisId={data.metric.dataKey}
/>
)}
<Area
dataKey={data.dailyCost.dataKey}
isAnimationActive={false}
fill={theme.palette.blue}
fillOpacity={0.4}
stroke="none"
yAxisId={data.dailyCost.dataKey}
/>
<Line
activeDot={false}
dataKey="trend"
dot={false}
isAnimationActive={false}
label={false}
strokeWidth={2}
stroke={theme.palette.blue}
yAxisId={data.dailyCost.dataKey}
/>
{metric && (
<Line
dataKey={data.metric.dataKey}
dot={false}
isAnimationActive={false}
label={false}
strokeWidth={2}
stroke={theme.palette.magenta}
yAxisId={data.metric.dataKey}
/>
)}
<RechartsTooltip content={tooltipRenderer} animationDuration={100} />
</ComposedChart>
</ResponsiveContainer>
</Box>
);
}
Example #21
Source File: CoverageHistoryChart.tsx From backstage with Apache License 2.0 | 4 votes |
CoverageHistoryChart = () => {
const { entity } = useEntity();
const codeCoverageApi = useApi(codeCoverageApiRef);
const {
loading: loadingHistory,
error: errorHistory,
value: valueHistory,
} = useAsync(
async () =>
await codeCoverageApi.getCoverageHistoryForEntity({
kind: entity.kind,
namespace: entity.metadata.namespace || 'default',
name: entity.metadata.name,
}),
);
const classes = useStyles();
if (loadingHistory) {
return <Progress />;
}
if (errorHistory) {
return <ResponseErrorPanel error={errorHistory} />;
} else if (!valueHistory) {
return <Alert severity="warning">No history found.</Alert>;
}
if (!valueHistory.history.length) {
return (
<Card>
<CardHeader title="History" />
<CardContent>No coverage history found</CardContent>
</Card>
);
}
const oldestCoverage = valueHistory.history[0];
const [latestCoverage] = valueHistory.history.slice(-1);
const getTrendForCoverage = (type: Coverage) => {
if (!oldestCoverage[type].percentage) {
return 0;
}
return (
((latestCoverage[type].percentage - oldestCoverage[type].percentage) /
oldestCoverage[type].percentage) *
100
);
};
const lineTrend = getTrendForCoverage('line');
const branchTrend = getTrendForCoverage('branch');
return (
<Card>
<CardHeader title="History" />
<CardContent>
<Box px={6} display="flex">
<Box display="flex" mr={4}>
{getTrendIcon(lineTrend, classes)}
<Typography>
Current line: {latestCoverage.line.percentage}%<br />(
{Math.floor(lineTrend)}% change over {valueHistory.history.length}{' '}
builds)
</Typography>
</Box>
<Box display="flex">
{getTrendIcon(branchTrend, classes)}
<Typography>
Current branch: {latestCoverage.branch.percentage}%<br />(
{Math.floor(branchTrend)}% change over{' '}
{valueHistory.history.length} builds)
</Typography>
</Box>
</Box>
<ResponsiveContainer width="100%" height={300}>
<LineChart
data={valueHistory.history}
margin={{ right: 48, top: 32 }}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis
dataKey="timestamp"
tickFormatter={formatDateToHuman}
reversed
/>
<YAxis dataKey="line.percentage" />
<YAxis dataKey="branch.percentage" />
<Tooltip labelFormatter={formatDateToHuman} />
<Legend />
<Line
type="monotone"
dataKey="branch.percentage"
stroke="#8884d8"
/>
<Line type="monotone" dataKey="line.percentage" stroke="#82ca9d" />
</LineChart>
</ResponsiveContainer>
</CardContent>
</Card>
);
}
Example #22
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>
);
}
Example #23
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 #24
Source File: index.tsx From livepeer-com with MIT License | 4 votes |
Chart = ({
data,
multiData,
}: {
data: Array<{ name: number; "Session bitrate": number }>;
multiData?: Array<{
[name: string]: number;
}>;
}) => {
const multistreamNames =
multiData && multiData[0] && Object.keys(multiData[0]);
return (
<Box
css={{
width: "100%",
position: "relative",
".recharts-cartesian-axis-tick": {
fontSize: "$2",
},
}}>
<Text
variant="gray"
size="1"
css={{
transform: "rotate(-90deg)",
position: "absolute",
left: "-70px",
bottom: "70px",
}}>
kbps (multiplied by 1000)
</Text>
<Text
variant="gray"
size="1"
css={{
position: "absolute",
bottom: "-30px",
left: "50px",
}}>
Seconds since stream loaded
</Text>
<ResponsiveContainer width="99%" height={300}>
<LineChart>
<XAxis
type="number"
dataKey="name"
domain={[
data[0]?.name,
data.length < 2 ? 10 : data[data.length - 1].name,
]}
tickCount={7}
allowDataOverflow
/>
<YAxis domain={[0, 1600]} />
<CartesianGrid vertical={false} />
<Tooltip content={<CustomTooltip />} />
<Legend wrapperStyle={{ fontSize: "10px" }} />
<Line
data={data}
cursor="pointer"
type="monotone"
dataKey="Session bitrate"
stroke="#5746AF"
strokeWidth="2px"
/>
{multistreamNames?.map((item, index) => {
if (item !== "name")
return (
<Line
data={multiData}
cursor="pointer"
type="monotone"
dataKey={item}
stroke={getMultistreamColor(index)}
strokeWidth="2px"
/>
);
})}
</LineChart>
</ResponsiveContainer>
</Box>
);
}
Example #25
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>
)
}