recharts#ComposedChart JavaScript Examples
The following examples show how to use
recharts#ComposedChart.
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: SimpleComposedChart.js From paper-and-ink with MIT License | 6 votes |
function SimpleComposedChart() {
const theme = useTheme();
return (
<ResponsiveContainer width="100%" minWidth={500} height={350}>
<ComposedChart margin={{ top: 0, right: -15, left: -15, bottom: 0 }} data={sales}>
<YAxis ticks={[0, 2500, 5000, 9800]} tick={{ fontSize: 12 }} tickLine={false} />
<XAxis dataKey="month" tick={{ fontSize: 12 }} tickLine={false} />
<Area
type="natural"
dataKey="area"
fill={theme.palette.primary.light}
strokeWidth={0}
activeDot={false}
/>
<Line type="monotone" dataKey="sales" stroke={theme.palette.primary.dark} strokeWidth={2} />
<Line
type="monotone"
dataKey="orders"
stroke={theme.palette.success.light}
strokeWidth={2}
dot={{
stroke: theme.palette.success.dark,
strokeWidth: 2,
fill: theme.palette.success.main
}}
/>
</ComposedChart>
</ResponsiveContainer>
);
}
Example #2
Source File: ComposedCharts.js From gedge-platform with Apache License 2.0 | 6 votes |
ComposedCharts = observer(() => {
return (
<div>
<ComposedChart width={730} height={250} data={data}>
<XAxis dataKey="name" />
<YAxis />
<Tooltip />
<Legend />
<CartesianGrid stroke="#f5f5f5" />
<Area type="monotone" dataKey="amt" fill="#8884d8" stroke="#8884d8" />
<Bar dataKey="pv" barSize={20} fill="#413ea0" />
<Line type="monotone" dataKey="uv" stroke="#ff7300" />
</ComposedChart>
</div>
);
})
Example #3
Source File: FeesChart.js From acy-dex-interface with MIT License | 5 votes |
export default function FeesChart(props) {
const {
data,
loading,
chartHeight,
yaxisWidth,
xaxisTickFormatter,
yaxisTickFormatter,
tooltipFormatter,
tooltipLabelFormatter
} = props
const csvFields = [
// {key: 'swap', name: 'Swap'},
{key: 'margin', name: 'Margin trading'},
{key: 'mint', name: 'Mint ALP'},
{key: 'burn', name: 'Burn ALP'},
{key: 'liquidation', name: 'Liquidation'},
{key: 'cumulative', name: 'Cumulative'}
]
return <ChartWrapper title="Fees" loading={loading} csvFields={csvFields} data={data}>
<ResponsiveContainer width="100%" height={chartHeight}>
<ComposedChart data={data} syncId="syncA">
<CartesianGrid strokeDasharray="3 3" stroke='#333333' />
<XAxis dataKey="timestamp" tickFormatter={xaxisTickFormatter} minTickGap={30} />
<YAxis dataKey="all" interval="preserveStartEnd" tickCount={7} tickFormatter={yaxisTickFormatter} width={yaxisWidth} />
<YAxis dataKey="cumulative" orientation="right" yAxisId="right" tickFormatter={yaxisTickFormatter} width={yaxisWidth} />
<Tooltip
formatter={tooltipFormatter}
labelFormatter={tooltipLabelFormatter}
contentStyle={{ textAlign: 'left' }}
/>
<Legend />
{/* <Bar isAnimationActive={false} type="monotone" dataKey="swap" stackId="a" name="Swap" fill={COLORS[0]} /> */}
<Bar isAnimationActive={false} type="monotone" dataKey="mint" stackId="a" name="Mint ALP" fill={COLORS[1]} />
<Bar isAnimationActive={false} type="monotone" dataKey="burn" stackId="a" name="Burn ALP" fill={COLORS[2]} />
<Bar isAnimationActive={false} type="monotone" dataKey="liquidation" stackId="a" name="Liquidation" fill={COLORS[3]} />
<Bar isAnimationActive={false} type="monotone" dataKey="margin" stackId="a" name="Margin trading" fill={COLORS[4]} />
<Line isAnimationActive={false} type="monotone" strokeWidth={3} dot={false} stroke={COLORS[0]} dataKey="cumulative" yAxisId="right" name="Cumulative" />
</ComposedChart>
</ResponsiveContainer>
<div className="chart-description">
Collected fees. USD value is calculated with token price at the moment of swap, trade, minting or redeeming ALP
</div>
</ChartWrapper>
}
Example #4
Source File: GraphDeathProjection.js From covid-19 with MIT License | 5 votes |
GraphDeathProjectionRender = (props) => {
let data = props.data;
const max_date = props.max_date;
const data_keys = props.data_keys;
data = data.map(d => {
d.name = moment(d.fulldate, "MM/DD/YYYY").format("M/D");
return d;
});
data = data.sort((a, b) => moment(a.fulldate, "MM/DD/YYYY").toDate() - (moment(b.fulldate, "MM/DD/YYYY")).toDate());
const [state, setState] = React.useState({
showall: false,
});
const handleLogScaleToggle = event => {
setState({ ...state, showall: !state.showall });
};
const cutoff = moment().subtract(30, 'days')
const future = moment().add(30, 'days')
data = data.filter(d => {
let day = moment(d.fulldate, "MM/DD/YYYY");
return day.isAfter(cutoff) && day.isBefore(future);
});
const formatYAxis = (tickItem) => {
return myShortNumber(tickItem);
}
return <>
<Grid container alignItems="center" spacing={1}>
<Grid item onClick={handleLogScaleToggle}>
<Typography>
Daily
</Typography>
</Grid>
<Grid item>
<AntSwitch checked={state.showall} onClick={handleLogScaleToggle} />
</Grid>
<Grid item onClick={handleLogScaleToggle}>
<Typography>
Total
</Typography>
</Grid>
<Grid item></Grid>
</Grid>
<ResponsiveContainer height={300} >
<ComposedChart data={data} margin={{ top: 5, right: 30, left: 5, bottom: 5 }} >
<XAxis dataKey="name" />
<YAxis yAxisId={0} tickFormatter={formatYAxis} />
<ReferenceLine x={moment(max_date, "MM/DD/YYYY").format("M/D")} label={{ value: props.max_label, fill: '#a3a3a3' }} stroke="#e3e3e3" strokeWidth={3} />
<CartesianGrid stroke="#d5d5d5" strokeDasharray="5 5" />
<Line type="monotone" dataKey={data_keys.key_mean} stroke="#000000" dot={{ r: 1 }} yAxisId={0} strokeWidth={2} />
<Area type='monotone' dataKey={data_keys.key_lower} stackId="1" stroke='#8884d8' fill='#FFFFFF' />
<Area type='monotone' dataKey={data_keys.key_delta} stackId="1" stroke='#82ca9d' fill='#82ca9d' />
<Line type="monotone" dataKey="actualDeath_daily" stroke="#FF0000" dot={{ r: 1 }} strokeDasharray="2 2" yAxisId={0} strokeWidth={2} />
<Line type="monotone" dataKey="actualDeath_moving_avg" stroke="#FF0000" dot={{ r: 1 }} yAxisId={0} strokeWidth={3} />
{state.showall && <Line type="monotone" dataKey={data_keys.key_mean_cumulative} dot={{ r: 1 }} stroke="#000000" yAxisId={0} strokeWidth={1} />}
{state.showall && <Line type="monotone" dataKey="actualDeath_total" dot={{ r: 1 }} stroke="#ff0000" yAxisId={0} strokeWidth={2} />}
{state.showall && <Area type='monotone' dataKey={data_keys.key_lower_cumulative} stackId="2" stroke='#8884d8' fill='#FFFFFF' />}
{state.showall && <Area type='monotone' dataKey={data_keys.key_delta_cumulative} stackId="2" stroke='#82ca9d' fill='#82ca9d' />}
<Tooltip content={props.tooltip} />
<Legend verticalAlign="top" payload={[
{ value: 'Actual Death', type: 'line', color: '#ff0000' },
{ value: 'Projection', type: 'line', color: '#000000' },
]} />
</ComposedChart>
</ResponsiveContainer>
<Typography variant="body2">
Source: The Institute for Health Metrics and Evaluation
</Typography>
</>
}
Example #5
Source File: Chart.jsx From breviews with MIT License | 5 votes |
Chart = ({ mainpageData }) => {
let chartData = [];
mainpageData.map(obj => {
if(obj.chartData.length !== 0) {
chartData.push(obj.chartData);
}
})
// if chartData is empty use initial data from constants
if (chartData.length === 0) {
chartData = data
}
return (
<div
className="chart-wrapper"
style={{
backgroundColor: "#f2f2f2",
width: "90%",
margin: "0 auto",
padding: "0.8em",
borderRadius: "2px",
color: "#333"
}}
>
<div>
<h4 style={{ marginBottom: "0.2em" }}>Employment Rate</h4>
<span style={{ fontStyle: "italic", fontSize: "11px" }}>
Based on reviews
</span>
</div>
<ResponsiveContainer width={"100%"} height={520}>
<ComposedChart
layout="vertical"
data={chartData}
margin={{
top: 20,
right: 80,
bottom: 20,
left: 120
}}
>
<CartesianGrid stroke="#f7b0c8" />
<XAxis type="number" />
<YAxis dataKey="name" type="category" />
<Tooltip />
<Bar dataKey="rate" barSize={10} fill="#c3352b" />
</ComposedChart>
</ResponsiveContainer>
</div>
);
}
Example #6
Source File: ApiCallMetricsView.jsx From amazon-connect-snippets with MIT No Attribution | 5 votes |
render() {
const {
classes, className: classNameProp, log, indexedLogs,
} = this.props;
// filtering out the following APIs for a better representation of the latency
const apiFilter = new Set([
'getAgentSnapshot',
]);
const latencies = log
.filter((event) => (indexedLogs.has(event._key)))
.flatMap((event) => ({
_localTimestamp: event._ts,
localTimestamp: event.time,
_type: 'LATENCY',
...indexedLogs.get(event._key),
}))
.filter((event) => !(apiFilter.has(event.apiName) || event.type === 'SEND'));
return (
<div className={clsx(classes.root, classNameProp)}>
<Container
title="API Call Metrics"
gutters={false}
>
<div className={classes.content}>
<ResponsiveContainer width="100%" height={300}>
<ComposedChart
data={latencies}
margin={{
top: 5, right: 20, bottom: 5, left: 20,
}}
>
<YAxis>
<Label angle={270} position="left" style={{ textAnchor: 'middle' }}>
Latency (ms)
</Label>
</YAxis>
<XAxis dataKey="_localTimestamp" type="number" scale="time" domain={['auto', 'auto']} tick={this.renderCustomAxisTick} />
<CartesianGrid stroke="#ccc" strokeDasharray="5 5" />
{/* eslint-disable-next-line max-len */}
<Line type="linear" dataKey="latency" stroke="#8884d8" strokeWidth={2} dot={this.renderDots} activeDot={this.renderActiveDots} connectNulls isAnimationActive={false} />
<Tooltip content={this.renderCustomTooltip} />
</ComposedChart>
</ResponsiveContainer>
</div>
</Container>
</div>
);
}
Example #7
Source File: PlotLinReg.js From Otto with MIT License | 5 votes |
export default function PlotLinReg() {
const { model_state } = useModelState();
const { linreg_test_result, linreg_test_set } = model_state;
const { state } = useState();
const data = [];
linreg_test_set.map((point, index) => {
if (linreg_test_result[index][1] >= 0) {
data.push({
x: point[0],
scatter: point[1],
line: linreg_test_result[index][1],
});
}
});
data.sort(compareX);
return (
<>
{!model_state.viz_loading ? (
<ResponsiveContainer
className="graph-wrapper"
width="100%"
height="100%"
>
<ComposedChart
data={data}
margin={{
top: 20,
right: 20,
bottom: 20,
left: 20,
}}
>
<CartesianGrid />
<XAxis dataKey="x" name={model_state.linreg_x_name} type="number">
<Label
value={model_state.linreg_x_name}
position="insideBottom"
offset={-12}
/>
</XAxis>
<YAxis
unit={state.sample_dataset === SampleDataset.BOSTON ? "k$" : ""}
name={model_state.linreg_y_name}
type="number"
>
<Label
value={model_state.linreg_y_name}
angle={-90}
position="insideLeft"
/>
</YAxis>
<Tooltip cursor={{ strokeDasharray: "3 3" }} />
<Legend verticalAlign="top" height={36} />
<Scatter name="Test Data" dataKey="scatter" fill="#e06aa6" />
<Line
dataKey="line"
name="Line of Best Fit (Train Data)"
stroke="#5D5DE1"
dot={false}
/>
</ComposedChart>
</ResponsiveContainer>
) : (
<LoadingComponent />
)}
</>
);
}
Example #8
Source File: VolumeChart.js From acy-dex-interface with MIT License | 5 votes |
export default function VolumeChart(props) {
const {
data,
loading,
chartHeight,
yaxisWidth,
xaxisTickFormatter,
yaxisTickFormatter,
tooltipFormatter,
tooltipLabelFormatter
} = props
const csvFields = [
// {key: 'swap', name: 'Swap'},
{key: 'margin', name: 'Margin trading'},
{key: 'mint', name: 'Mint GLP'},
{key: 'burn', name: 'Burn GLP'},
{key: 'liquidation', name: 'Liquidation'},
{key: 'cumulative', name: 'Cumulative'}
]
useEffect( () => {
console.log("DATA VOLUME CHART:", data);
},[data])
return <ChartWrapper title="Volume" loading={loading} csvFields={csvFields} data={data}>
<ResponsiveContainer width="100%" height={chartHeight}>
<ComposedChart data={data} syncId="syncA">
<CartesianGrid strokeDasharray="3 3" stroke='#333333' />
<XAxis dataKey="timestamp" tickFormatter={xaxisTickFormatter} minTickGap={30} />
<YAxis dataKey="all" interval="preserveStartEnd" tickCount={7} tickFormatter={yaxisTickFormatter} width={yaxisWidth} />
<YAxis dataKey="cumulative" orientation="right" yAxisId="right" tickFormatter={yaxisTickFormatter} width={yaxisWidth} />
<Tooltip
formatter={tooltipFormatter}
labelFormatter={tooltipLabelFormatter}
contentStyle={{ textAlign: 'right' }}
/>
<Legend />
{/* <Bar isAnimationActive={false} type="monotone" dataKey="swap" stackId="a" name="Swap" fill={COLORS[0]} /> */}
<Bar isAnimationActive={false} type="monotone" dataKey="mint" stackId="a" name="Mint GLP" fill={COLORS[1]} />
<Bar isAnimationActive={false} type="monotone" dataKey="burn" stackId="a" name="Burn GLP" fill={COLORS[2]} />
<Bar isAnimationActive={false} type="monotone" dataKey="liquidation" stackId="a" name="Liquidation" fill={COLORS[3]} />
<Bar isAnimationActive={false} type="monotone" dataKey="margin" stackId="a" name="Margin trading" fill={COLORS[4]} />
<Line isAnimationActive={false} type="monotone" dot={false} strokeWidth={3} stroke={COLORS[0]} dataKey="cumulative" yAxisId="right" name="Cumulative" />
</ComposedChart>
</ResponsiveContainer>
</ChartWrapper>
}
Example #9
Source File: MetricsView.jsx From amazon-connect-snippets with MIT No Attribution | 4 votes |
render() {
const {
classes, className: classNameProp, log, indexedLogs,
} = this.props;
const {
skewThreshold,
hideReferenceArea,
referenceAreaOpacities,
hideLatencyGraph,
hideSkewGraph,
} = this.state;
const snapshots = log
.filter((event) => (event.text === 'GET_AGENT_SNAPSHOT succeeded.'))
.flatMap((event) => event.objects.map((object, idx) => ({
...object.snapshot,
_event: event,
_key: `${event._key}-${idx}`,
_date: object.snapshot.snapshotTimestamp.substring(0, 10),
_time: object.snapshot.snapshotTimestamp.substring(11, 23),
_timezone: object.snapshot.snapshotTimestamp.substring(23),
_snapshotTimestamp: dayjs(object.snapshot.snapshotTimestamp).valueOf(),
_localTimestamp: event._ts,
localTimestamp: dayjs(event._ts).toISOString(),
_type: 'SNAPSHOT',
})))
.map((snapshot, idx, arr) => {
const eventKeyFrom = snapshot._event._key;
// eslint-disable-next-line max-len
const eventKeyTo = (idx !== arr.length - 1) ? arr[idx + 1]._event._key : log[log.length - 1]._key;
return {
...snapshot,
// eslint-disable-next-line max-len
_targetEventKeys: Array.from(Array(eventKeyTo - eventKeyFrom), (v, k) => (k + eventKeyFrom)),
};
});
const seqSnapshots = snapshots // removing the duplications in states.
.reduce((acc, x) => {
if (acc.length > 0 && acc[acc.length - 1][0].state.name === x.state.name) {
acc[acc.length - 1].push(x);
} else {
acc.push([x]);
}
return acc;
}, []);
const gradientOffset = () => {
const dataMax = Math.max(...snapshots.map((s) => s.skew));
const dataMin = Math.min(...snapshots.map((s) => s.skew));
const y0 = Math.min(1, Math.max(0, (skewThreshold - dataMin) / (dataMax - dataMin)));
const y1 = Math.min(1, Math.max(0, (-skewThreshold - dataMin) / (dataMax - dataMin)));
return [
1 - y0,
1 - y1,
];
};
const off = gradientOffset();
// filtering out the following APIs for a better representation of the latency
const apiFilter = new Set([
'getAgentSnapshot',
]);
const latencies = log
.filter((event) => (indexedLogs.has(event._key)))
.flatMap((event) => ({
_localTimestamp: event._ts,
localTimestamp: event.time,
_type: 'LATENCY',
...indexedLogs.get(event._key),
}))
.filter((event) => !(apiFilter.has(event.apiName) || event.type === 'SEND'));
const data = () => {
if (hideLatencyGraph && !hideSkewGraph) {
return snapshots;
} if (!hideLatencyGraph && hideSkewGraph) {
return latencies;
}
return snapshots.concat(latencies)
.sort((a, b) => a._localTimestamp - b._localTimestamp);
};
return (
<div className={clsx(classes.root, classNameProp)}>
<Paper>
<div className={classes.header}>
<div className={classes.headerInside}>
<Typography className={classes.title} variant="h6" component="h3">
Metrics
</Typography>
{hideSkewGraph
? (
<Button
className={classes.toggleReferenceArea}
onClick={() => this.handleToggleSkewGraph()}
>
Show Skew Graph
</Button>
)
: (
<Button
className={classes.toggleReferenceArea}
onClick={() => this.handleToggleSkewGraph()}
>
Hide Skew Graph
</Button>
)}
{hideLatencyGraph
? (
<Button
className={classes.toggleReferenceArea}
onClick={() => this.handleToggleLatencyGraph()}
>
Show Latency Graph
</Button>
)
: (
<Button
className={classes.toggleReferenceArea}
onClick={() => this.handleToggleLatencyGraph()}
>
Hide Latency Graph
</Button>
)}
{hideReferenceArea
? (
<Button
className={classes.toggleReferenceArea}
onClick={() => this.handleToggleReferenceArea()}
>
Show Reference Area
</Button>
)
: (
<Button
className={classes.toggleReferenceArea}
onClick={() => this.handleToggleReferenceArea()}
>
Hide Reference Area
</Button>
)}
</div>
</div>
<div className={classes.content}>
<ResponsiveContainer width="100%" height={300}>
<ComposedChart
data={data()}
margin={{
top: 5, right: 20, bottom: 5, left: 20,
}}
>
<YAxis
yAxisId={1}
label={{
value: 'Skew (ms)', angle: -90, offset: 0, position: 'left',
}}
/>
<YAxis
yAxisId={2}
label={{
value: 'Latency (ms)', angle: 90, offset: 0, position: 'right',
}}
orientation="right"
/>
<XAxis dataKey="_localTimestamp" type="number" scale="time" domain={['auto', 'auto']} tick={this.renderCustomAxisTick} />
<CartesianGrid stroke="#ccc" strokeDasharray="5 5" />
{/* eslint-disable-next-line max-len */}
{/* <Line yAxisId={1} type="monotone" dataKey="skew" stroke="#000000" connectNulls={true}/> */}
{!hideSkewGraph
&& <Area yAxisId={1} type="monotone" dataKey="skew" stroke="#000" fill="url(#splitColor)" connectNulls isAnimationActive={false} />}
{!hideLatencyGraph
&& <Line yAxisId={2} type="linear" dataKey="latency" stroke="#0000ff" strokeWidth={2} dot={this.renderDots} activeDot={this.renderActiveDots} connectNulls isAnimationActive={false} />}
<Tooltip content={this.renderCustomTooltip} />
<defs>
<linearGradient id="splitColor" x1="0" y1="0" x2="0" y2="1">
<stop offset={off[0]} stopColor="red" stopOpacity={1} />
<stop offset={off[0]} stopColor="green" stopOpacity={1} />
<stop offset={off[1]} stopColor="green" stopOpacity={1} />
<stop offset={off[1]} stopColor="red" stopOpacity={1} />
</linearGradient>
</defs>
{!hideReferenceArea && seqSnapshots.map((s, i, arr) => {
const s0 = s[0];
const s1 = (i < arr.length - 1)
? arr[i + 1][0] : s[s.length - 1];
const stateHits = Object.keys(colorMap)
.filter((name) => s0.state.name.includes(name));
const color = (stateHits.length > 0)
? colorMap[stateHits[0]] : colorMap.__other;
// eslint-disable-next-line max-len
const opacity = (stateHits.length > 0) ? referenceAreaOpacities[stateHits[0]] : referenceAreaOpacities.__other;
return (
<ReferenceArea
yAxisId={1}
key={s0._key}
className={classes.referenceArea}
x1={s0._localTimestamp}
x2={s1._localTimestamp}
ifOverflow="extendDomain"
opacity={opacity}
fill={color}
/>
);
})}
{!hideReferenceArea && <Legend content={this.renderCustomLegend} />}
</ComposedChart>
</ResponsiveContainer>
</div>
</Paper>
</div>
);
}
Example #10
Source File: SkewMetricsView.jsx From amazon-connect-snippets with MIT No Attribution | 4 votes |
render() {
const {
classes, className: classNameProp, log,
} = this.props;
const {
skewThreshold,
hideReferenceArea,
referenceAreaOpacities,
} = this.state;
const snapshots = log
.filter((event) => (event.text === 'GET_AGENT_SNAPSHOT succeeded.'))
.flatMap((event) => event.objects.map((object, idx) => ({
...object.snapshot,
_event: event,
_key: `${event._key}-${idx}`,
_date: object.snapshot.snapshotTimestamp.substring(0, 10),
_time: object.snapshot.snapshotTimestamp.substring(11, 23),
_timezone: object.snapshot.snapshotTimestamp.substring(23),
_snapshotTimestamp: dayjs(object.snapshot.snapshotTimestamp).valueOf(),
_localTimestamp: event._ts,
localTimestamp: dayjs(event._ts).toISOString(),
_type: 'SNAPSHOT',
})))
.map((snapshot, idx, arr) => {
const eventKeyFrom = snapshot._event._key;
// eslint-disable-next-line max-len
const eventKeyTo = (idx !== arr.length - 1) ? arr[idx + 1]._event._key : log[log.length - 1]._key;
return {
...snapshot,
// eslint-disable-next-line max-len
_targetEventKeys: Array.from(Array(eventKeyTo - eventKeyFrom), (v, k) => (k + eventKeyFrom)),
};
});
const seqSnapshots = snapshots // removing the duplications in states.
.reduce((acc, x) => {
if (acc.length > 0 && acc[acc.length - 1][0].state.name === x.state.name) {
acc[acc.length - 1].push(x);
} else {
acc.push([x]);
}
return acc;
}, []);
const gradientOffset = () => {
const dataMax = Math.max(...snapshots.map((s) => s.skew));
const dataMin = Math.min(...snapshots.map((s) => s.skew));
const y0 = Math.min(1, Math.max(0, (skewThreshold - dataMin) / (dataMax - dataMin)));
const y1 = Math.min(1, Math.max(0, (-skewThreshold - dataMin) / (dataMax - dataMin)));
return [
1 - y0,
1 - y1,
];
};
const off = gradientOffset();
const data = () => snapshots;
return (
<div className={clsx(classes.root, classNameProp)}>
<Container
title="Skew Metrics"
gutters={false}
actionGroup={(
<>
{hideReferenceArea
? (
<Button
className={classes.toggleReferenceArea}
onClick={() => this.handleToggleReferenceArea()}
>
Show Reference Area
</Button>
)
: (
<Button
className={classes.toggleReferenceArea}
onClick={() => this.handleToggleReferenceArea()}
>
Hide Reference Area
</Button>
)}
</>
)}
>
<div className={classes.content}>
<ResponsiveContainer width="100%" height={300}>
<ComposedChart
data={data()}
margin={{
top: 5, right: 20, bottom: 5, left: 20,
}}
>
<YAxis>
<Label angle={270} position="left" style={{ textAnchor: 'middle' }}>
Skew (ms)
</Label>
</YAxis>
<XAxis dataKey="_localTimestamp" type="number" scale="time" domain={['auto', 'auto']} tick={this.renderCustomAxisTick} />
<CartesianGrid stroke="#ccc" strokeDasharray="5 5" />
{/* eslint-disable-next-line max-len */}
<Area type="monotone" dataKey="skew" stroke="#000" fill="url(#splitColor)" connectNulls isAnimationActive={false} />
<Tooltip content={this.renderCustomTooltip} />
<defs>
<linearGradient id="splitColor" x1="0" y1="0" x2="0" y2="1">
<stop offset={off[0]} stopColor="red" stopOpacity={1} />
<stop offset={off[0]} stopColor="green" stopOpacity={1} />
<stop offset={off[1]} stopColor="green" stopOpacity={1} />
<stop offset={off[1]} stopColor="red" stopOpacity={1} />
</linearGradient>
</defs>
{!hideReferenceArea && seqSnapshots.map((s, i, arr) => {
const s0 = s[0];
const s1 = (i < arr.length - 1)
? arr[i + 1][0] : s[s.length - 1];
const stateHits = Object.keys(colorMap)
.filter((name) => s0.state.name.includes(name));
const color = (stateHits.length > 0)
? colorMap[stateHits[0]] : colorMap.__other;
// eslint-disable-next-line max-len
const opacity = (stateHits.length > 0) ? referenceAreaOpacities[stateHits[0]] : referenceAreaOpacities.__other;
return (
<ReferenceArea
key={s0._key}
className={classes.referenceArea}
x1={s0._localTimestamp}
x2={s1._localTimestamp}
ifOverflow="extendDomain"
opacity={opacity}
fill={color}
/>
);
})}
{!hideReferenceArea && <Legend content={this.renderCustomLegend} />}
</ComposedChart>
</ResponsiveContainer>
</div>
</Container>
</div>
);
}
Example #11
Source File: StateIndiaRecoveryProgress.js From covid-19 with MIT License | 4 votes |
StateIndiaRecoveryProgress = props => {
const data = props.data;
let topNData = data.filter((elem) => {
return elem.confirmed > 100 && elem.state != 'State Unassigned';
});
let refinedData = [];
topNData.forEach(element => {
let obj = {};
obj['State'] = element['state'];
obj['% Recovered'] = element['perctRecoverd'];
obj['% Deaths'] = element['perctDeaths'];
obj['active'] = element['active'];
obj['% Active'] = element['perctActive'];
obj['confirmed'] = element['confirmed'];
obj['recovered'] = element['recovered'];
obj['deaths'] = element['deaths'];
obj['State Code'] = INDIA_STATE_CODES[element['state']];
refinedData.push(obj);
});
const CustomTooltip = ({ active, payload, label }) => {
if (active) {
return (
<div className="custom-tooltip">
<p className="label">
<span>{payload[0].payload.State}({`Cases: ${payload[0].payload.confirmed}`})</span>
</p>
<p className="intro">
<span style={{color: '#FFC107'}}>
{`Acive Cases: ${payload[0].payload.active}(${payload[0].payload['% Active']}%)`}
</span> <br />
<span style={{color: '#28A745'}}>
{`Recovered Cases: ${payload[0].payload.recovered}(${payload[0].payload['% Recovered']}%)`}
</span> <br />
<span style={{color: '#DC3545'}}>
{`Death Cases: ${payload[0].payload.deaths}(${payload[0].payload['% Deaths']}%)`}
</span>
</p>
</div>
);
}
return null;
};
const renderCustomizedLabel = (props) => {
const { x, y, width, height, value } = props;
const radius = 18;
return (
<g>
<circle cx={x + width / 2} cy={y - radius} r={radius} fill="#FFF" />
<text x={x + width / 2} y={y - radius} fill="#000" textAnchor="middle" dominantBaseline="middle">
{value}%
</text>
</g>
);
};
return (
<Card>
<Card.Body>
<Card.Title>State: Recovery Progress(Min. 100 Cases)</Card.Title>
<Card.Subtitle className="mb-2 text-muted">
State with the Active, Recovery and Death percentages
</Card.Subtitle>
<ResponsiveContainer width='100%' height={330}>
<ComposedChart data={refinedData}
margin={{
top: 30, right: 0, left: 0, bottom: 5,
}}>
<XAxis dataKey="State Code" />
<YAxis/>
<Tooltip content={<CustomTooltip />} />
<Legend/>
<CartesianGrid strokeDasharray="3 3" />
<Bar dataKey="% Recovered" fill="rgba(40, 167, 69, 1.0)">
<LabelList dataKey="% Recovered" position="top" content={renderCustomizedLabel} />
</Bar>
<Area type='monotone' dataKey='% Active' fill='#FFC107' stroke='#FFC107'/>
<Line type='monotone' dataKey='% Deaths' stroke='#DC3545'/>
</ComposedChart>
</ResponsiveContainer>
</Card.Body>
</Card>
);
}
Example #12
Source File: MultiLinePlot.jsx From covince with MIT License | 4 votes |
MainChart = React.memo((props) => {
const {
activeLineages,
chart,
dateRange,
darkMode,
precision,
preset,
stroke,
tooltipEnabled,
type,
xAxisProps,
yAxisConfig = {},
zoomArea,
...chartProps
} = props
const { lineages, data, dates } = chart
const yAxisDomain = useMemo(() => {
if (yAxisConfig && yAxisConfig.domain) {
return yAxisConfig.domain
}
if (preset === 'percentage' && type === 'area' && lineages.length === Object.keys(activeLineages).length) {
return [0, 100]
}
if (dateRange && data.length) {
if (type === 'area') {
const [minIndex, maxIndex] = xAxisProps.domain
const range = data.slice(minIndex, maxIndex + 1)
let { sumY: max } = range[0]
for (const { sumY } of range.slice(1)) {
max = Math.max(sumY, max)
}
return [0, Math.ceil(max)]
} else {
const [minIndex, maxIndex] = xAxisProps.domain
const range = data.slice(minIndex, maxIndex + 1)
let { maxY: max } = range[0]
for (const { maxY } of range.slice(1)) {
max = Math.max(maxY, max)
}
return [0, Math.ceil(max)]
}
}
if (preset === 'percentage' && type === 'area' && lineages.length) {
return [0, 1]
}
return [0, 'auto']
}, [preset, type, yAxisConfig, lineages, xAxisProps.domain, data])
const yAxisTicks = useMemo(() => {
if (preset === 'percentage') {
if (lineages.length === 0) {
return { ticks: false }
}
const fullScale = lineages.length === Object.keys(activeLineages).length
if (fullScale) {
return {
tickFormatter: value => `${Math.min(parseFloat(value), 100)}%`,
ticks: dateRange ? undefined : [0, 25, 50, 75, 100]
}
}
return {
tickFormatter: value => {
if (value === 0) return '0%'
if (value >= 100) return '100%'
if (!Number.isInteger(value)) return `${value.toFixed(1)}%`
return `${value}%`
}
}
}
return {
tickFormatter: value => {
const valueStr = value.toString()
if (valueStr.length > 4) {
const tripleFigureCount = Math.floor((valueStr.length - 1) / 3)
const prefix = (value / Math.pow(1000, tripleFigureCount))
const prefixStr = prefix.toString()
return (
(prefixStr.length < 4 ? prefixStr : prefix.toPrecision(3)) +
(tripleFigureLabel[tripleFigureCount] || '')
)
}
return value.toLocaleString()
},
ticks: dateRange ? undefined : yAxisConfig.ticks
}
}, [preset, lineages, activeLineages, yAxisConfig, dateRange])
const grid =
<CartesianGrid stroke={tailwindColors[stroke][darkMode ? 500 : 300]} />
const [highlightedLineage, setHighlightedLineage] = useState(null)
const tooltip = useMemo(() =>
(tooltipEnabled && lineages.length > 0)
? <Tooltip
content={ChartTooltip}
cursor={{ stroke: tailwindColors[stroke][darkMode ? 300 : 400] }}
dates={dates}
percentage={preset === 'percentage'}
precision={precision}
sortByValue={type !== 'area'}
highlightedItem={highlightedLineage}
/>
: null
, [tooltipEnabled, stroke, dates, preset, precision, highlightedLineage, type])
const xAxis = useMemo(() =>
<XAxis
{...xAxisProps}
fontSize='12'
tick={data.length}
tickFormatter={i => i in data ? format(new Date(data[i].date), 'd MMM') : ''}
tickMargin='4'
stroke='currentcolor'
/>
, [data, xAxisProps])
const yAxis =
<YAxis
type='number'
allowDataOverflow={dateRange || yAxisConfig.allow_data_overflow || false}
domain={yAxisDomain}
width={48}
stroke='currentcolor'
tickMargin='4'
tick={data.length}
allowDecimals={false}
{...yAxisTicks}
/>
const areas = useMemo(() => {
if (type === 'area') {
return lineages.map(({ lineage, colour = fallbackColour }) => (
<Area
key={lineage}
activeDot={{ stroke: tailwindColors[stroke][400] }}
dataKey={lineage}
dot={false}
fill={colour}
fillOpacity={highlightedLineage === lineage ? 0.8 : undefined}
name={lineage}
stackId='1'
stroke={colour}
type='monotone'
animationDuration={animationDuration}
isAnimationActive={true}
onMouseEnter={({ name }) => { setHighlightedLineage(name) }}
onMouseLeave={() => { setHighlightedLineage(null) }}
/>
))
}
return lineages
.filter(_ => _.average !== 0)
.map(({ lineage, colour = fallbackColour }) => {
const key = `${lineage}_range`
return (
<Area
key={key}
activeDot={false}
dataKey={key}
fill={colour}
name='_range'
strokeWidth={0}
type='monotone'
animationDuration={animationDuration}
isAnimationActive={true}
/>
)
})
}, [lineages, stroke, type, highlightedLineage])
const lines = useMemo(() => {
if (type === 'area') return null
return lineages.map(({ lineage, colour = fallbackColour }) =>
<Line
key={lineage}
activeDot={{ stroke: tailwindColors[stroke][400] }}
dataKey={lineage}
dot={false}
name={lineage}
stroke={colour}
type='monotone'
animationDuration={animationDuration}
isAnimationActive={true}
/>
)
}, [lineages, stroke, type])
const yReference = useMemo(() => {
if (yAxisConfig.reference_line === undefined) return null
return (
<ReferenceLine
y={yAxisConfig.reference_line}
stroke={tailwindColors[stroke][darkMode ? 400 : 600]}
strokeDasharray={[8, 8]}
label=''
strokeWidth={2}
style={{ mixBlendMode: darkMode ? 'screen' : 'multiply' }}
/>
)
}, [yAxisConfig.reference_line, stroke])
return (
<ComposedChart
{...chartProps}
data={[...data] /* new array required for animations */}
>
{grid}
{areas}
{xAxis}
{yAxis}
{tooltip}
{yReference}
{lines}
{zoomArea.start !== undefined
? <ReferenceArea x1={zoomArea.start} x2={zoomArea.end} strokeOpacity={0.3} />
: null}
</ComposedChart>
)
})
Example #13
Source File: MultiLinePlot.jsx From covince with MIT License | 4 votes |
MultiLinePlot = props => {
const {
activeLineages,
area_data,
chartZoom,
className,
darkMode,
date,
groupStackedColours = true,
height = 120,
parameter,
preset: deprecatedPreset,
setDate,
stroke = 'blueGray',
tooltipEnabled,
type,
width,
/* xAxis: xAxisConfig = {}, */
yAxis: yAxisConfig,
zoomEnabled
} = props
const preset = useMemo(() => {
if (parameter && parameter.format === 'percentage') return 'percentage'
// back compat
if (deprecatedPreset) return deprecatedPreset
if (parameter && parameter.id === 'p') return 'percentage'
return null
}, [parameter, deprecatedPreset])
const precision = useMemo(() => {
return parameter ? parameter.precision : undefined
}, [parameter])
const chart = useMemo(() => {
const dataByDate = {}
const lineageSum = {}
for (const d of area_data) {
if (d.parameter === parameter.id && d.lineage !== 'total') {
const next = {
...dataByDate[d.date],
date: d.date,
[d.lineage]: d.mean,
[`${d.lineage}_range`]: d.range
}
if (d.lineage in activeLineages && activeLineages[d.lineage].active) {
next.maxY = Math.max(next.maxY || 0, d.range[1] || d.mean)
next.sumY = (next.sumY || 0) + d.mean
}
dataByDate[d.date] = next
const sum = lineageSum[d.lineage] || 0
lineageSum[d.lineage] = (sum + d.mean)
}
}
const data =
orderBy(Object.values(dataByDate), 'date', 'asc')
.map((d, index) => ({ ...d, index }))
const dates = data.map(_ => _.date)
const lineages = []
for (const lineage of Object.keys(lineageSum)) {
const { active, colour } = activeLineages[lineage]
if (active) {
lineages.push({ lineage, colour, average: lineageSum[lineage] / dates.length })
}
}
const ordered = orderBy(lineages, 'average', 'asc')
let sorted
if (groupStackedColours) {
sorted = []
while (ordered.length > 0) {
const [item] = ordered.splice(0, 1)
if (sorted.includes(item)) continue
sorted.push(item)
for (let i = 0; i < ordered.length; i++) {
const other = ordered[i]
if (item.colour === other.colour) {
sorted.push(other)
}
}
}
} else {
sorted = ordered
}
return {
lineages: sorted,
data,
dates
}
}, [area_data, activeLineages, groupStackedColours])
const { data, dates } = chart
const chartProps = useMemo(() => ({
width,
height,
margin: { top: 12, left: 0, right: 24 }
}), [width, height])
const { dateRange, setChartZoom, clearChartZoom } = chartZoom
const xAxisDomain = useMemo(() => {
const minIndex = 0
const maxIndex = data.length - 1
if (dateRange && dates.length) {
const [minDate, maxDate] = dateRange
const min = minDate ? Math.max(dates.indexOf(minDate), minIndex) : minIndex
let max = maxDate ? dates.indexOf(maxDate) : maxIndex
if (max === -1) max = maxIndex
return min < max ? [min, max] : [max, min]
}
return [minIndex, maxIndex]
}, [dateRange, dates])
const xAxisProps = useMemo(() => {
const indices = Object.keys(dates)
let ticks = indices
if (dateRange) {
const [minIndex, maxIndex] = xAxisDomain
ticks = indices.slice(minIndex, maxIndex + 1)
}
return {
allowDataOverflow: true,
dataKey: 'index',
domain: xAxisDomain,
ticks,
type: 'number'
}
}, [xAxisDomain, dates])
const [zoomArea, setZoomArea] = React.useState({})
const [isHovering, setIsHovering] = React.useState(false)
const eventHandlers = useMemo(() => {
const clickHandlers = {
onClick: item => {
if (date && item && !zoomArea.dragged) { // do not set date if not visible on chart
setDate(data[item.activeLabel].date)
}
if (zoomEnabled) {
setZoomArea({ dragged: zoomArea.dragged })
}
},
onMouseDown: e => {
if (e && zoomEnabled) {
setZoomArea({ start: e.activeLabel, end: e.activeLabel, dragged: false })
}
},
onMouseMove: e => {
if (e) {
setIsHovering(e.activeLabel !== undefined)
if (zoomArea.start === undefined) return
let end = e.activeLabel
if (e.activeLabel === undefined) { // outside of axes
end = xAxisDomain[zoomArea.end >= data.length / 2 ? 1 : 0]
}
setZoomArea({ start: zoomArea.start, end, dragged: true })
}
},
onMouseLeave: e => {
setIsHovering(false)
},
onMouseUp: (_, e) => {
if (zoomArea.end !== zoomArea.start) {
const xStart = data[zoomArea.start].date
const xEnd = data[zoomArea.end].date
const args = xStart < xEnd ? [xStart, xEnd] : [xEnd, xStart]
setChartZoom(...args)
}
setZoomArea({ dragged: zoomArea.dragged })
}
}
if (!tooltipEnabled) { // touch handlers need to be replaced when tooltip is missing
return {
...clickHandlers,
onTouchStart: clickHandlers.onMouseDown,
onTouchMove: clickHandlers.onMouseMove,
onTouchEnd: clickHandlers.onMouseUp
}
}
return clickHandlers
}, [zoomEnabled, data, zoomArea, isHovering])
const cursor = useMemo(() => {
if (zoomArea.start) return 'ew-resize'
if (isHovering) return 'crosshair'
return undefined
}, [zoomArea, isHovering])
return (
<div
className={classNames('relative select-none focus:outline-none', className)}
onDoubleClick={clearChartZoom}
>
<MainChart
{...{
...chartProps,
...eventHandlers,
activeLineages,
chart,
dateRange,
cursor,
darkMode,
precision,
preset,
stroke,
tooltipEnabled,
type,
xAxisProps,
yAxisConfig,
zoomArea
}}
/>
<div className='absolute top-0 left-0 pointer-events-none'>
<ComposedChart {...chartProps} data={data}>
<XAxis
{...xAxisProps}
tick={false}
stroke='none'
/>
<YAxis
width={48}
tick={false}
stroke='none'
/>
<ReferenceLine
x={dates.indexOf(date)}
stroke={tailwindColors[stroke][darkMode ? 300 : 400]}
label=''
strokeWidth={2}
style={{ mixBlendMode: darkMode ? 'screen' : 'multiply' }}
/>
</ComposedChart>
</div>
</div>
)
}
Example #14
Source File: Dashboard.js From react-code-splitting-2021-04-26 with MIT License | 4 votes |
export default function Dashboard(props) {
var classes = useStyles();
var theme = useTheme();
// local
var [mainChartState, setMainChartState] = useState("monthly");
return (
<>
<PageTitle title="Dashboard" button={<Button
variant="contained"
size="medium"
color="secondary"
>
Latest Reports
</Button>} />
<Grid container spacing={4}>
<Grid item lg={3} md={4} sm={6} xs={12}>
<Widget
title="Visits Today"
upperTitle
bodyClass={classes.fullHeightBody}
className={classes.card}
>
<div className={classes.visitsNumberContainer}>
<Grid container item alignItems={"center"}>
<Grid item xs={6}>
<Typography size="xl" weight="medium" noWrap>
12, 678
</Typography>
</Grid>
<Grid item xs={6}>
<LineChart
width={100}
height={30}
data={[
{ value: 10 },
{ value: 15 },
{ value: 10 },
{ value: 17 },
{ value: 18 },
]}
>
<Line
type="natural"
dataKey="value"
stroke={theme.palette.success.main}
strokeWidth={2}
dot={false}
/>
</LineChart>
</Grid>
</Grid>
</div>
<Grid
container
direction="row"
justify="space-between"
alignItems="center"
>
<Grid item xs={4}>
<Typography color="text" colorBrightness="secondary" noWrap>
Registrations
</Typography>
<Typography size="md">860</Typography>
</Grid>
<Grid item xs={4}>
<Typography color="text" colorBrightness="secondary" noWrap>
Sign Out
</Typography>
<Typography size="md">32</Typography>
</Grid>
<Grid item xs={4}>
<Typography color="text" colorBrightness="secondary" noWrap>
Rate
</Typography>
<Typography size="md">3.25%</Typography>
</Grid>
</Grid>
</Widget>
</Grid>
<Grid item lg={3} md={8} sm={6} xs={12}>
<Widget
title="App Performance"
upperTitle
className={classes.card}
bodyClass={classes.fullHeightBody}
>
<div className={classes.performanceLegendWrapper}>
<div className={classes.legendElement}>
<Dot color="warning" />
<Typography
color="text"
colorBrightness="secondary"
className={classes.legendElementText}
>
Integration
</Typography>
</div>
<div className={classes.legendElement}>
<Dot color="primary" />
<Typography
color="text"
colorBrightness="secondary"
className={classes.legendElementText}
>
SDK
</Typography>
</div>
</div>
<div className={classes.progressSection}>
<Typography
size="md"
color="text"
colorBrightness="secondary"
className={classes.progressSectionTitle}
>
Integration
</Typography>
<LinearProgress
variant="determinate"
value={77}
classes={{ barColorPrimary: classes.progressBarPrimary }}
className={classes.progress}
/>
</div>
<div>
<Typography
size="md"
color="text"
colorBrightness="secondary"
className={classes.progressSectionTitle}
>
SDK
</Typography>
<LinearProgress
variant="determinate"
value={73}
classes={{ barColorPrimary: classes.progressBarWarning }}
className={classes.progress}
/>
</div>
</Widget>
</Grid>
<Grid item lg={3} md={8} sm={6} xs={12}>
<Widget
title="Server Overview"
upperTitle
className={classes.card}
bodyClass={classes.fullHeightBody}
>
<div className={classes.serverOverviewElement}>
<Typography
color="text"
colorBrightness="secondary"
className={classes.serverOverviewElementText}
noWrap
>
60% / 37°С / 3.3 Ghz
</Typography>
<div className={classes.serverOverviewElementChartWrapper}>
<ResponsiveContainer height={50} width="99%">
<AreaChart data={getRandomData(10)}>
<Area
type="natural"
dataKey="value"
stroke={theme.palette.secondary.main}
fill={theme.palette.secondary.light}
strokeWidth={2}
fillOpacity="0.25"
/>
</AreaChart>
</ResponsiveContainer>
</div>
</div>
<div className={classes.serverOverviewElement}>
<Typography
color="text"
colorBrightness="secondary"
className={classes.serverOverviewElementText}
noWrap
>
54% / 31°С / 3.3 Ghz
</Typography>
<div className={classes.serverOverviewElementChartWrapper}>
<ResponsiveContainer height={50} width="99%">
<AreaChart data={getRandomData(10)}>
<Area
type="natural"
dataKey="value"
stroke={theme.palette.primary.main}
fill={theme.palette.primary.light}
strokeWidth={2}
fillOpacity="0.25"
/>
</AreaChart>
</ResponsiveContainer>
</div>
</div>
<div className={classes.serverOverviewElement}>
<Typography
color="text"
colorBrightness="secondary"
className={classes.serverOverviewElementText}
noWrap
>
57% / 21°С / 3.3 Ghz
</Typography>
<div className={classes.serverOverviewElementChartWrapper}>
<ResponsiveContainer height={50} width="99%">
<AreaChart data={getRandomData(10)}>
<Area
type="natural"
dataKey="value"
stroke={theme.palette.warning.main}
fill={theme.palette.warning.light}
strokeWidth={2}
fillOpacity="0.25"
/>
</AreaChart>
</ResponsiveContainer>
</div>
</div>
</Widget>
</Grid>
<Grid item lg={3} md={4} sm={6} xs={12}>
<Widget title="Revenue Breakdown" upperTitle className={classes.card}>
<Grid container spacing={2}>
<Grid item xs={6}>
<ResponsiveContainer width="100%" height={144}>
<PieChart>
<Pie
data={PieChartData}
innerRadius={30}
outerRadius={40}
dataKey="value"
>
{PieChartData.map((entry, index) => (
<Cell
key={`cell-${index}`}
fill={theme.palette[entry.color].main}
/>
))}
</Pie>
</PieChart>
</ResponsiveContainer>
</Grid>
<Grid item xs={6}>
<div className={classes.pieChartLegendWrapper}>
{PieChartData.map(({ name, value, color }, index) => (
<div key={color} className={classes.legendItemContainer}>
<Dot color={color} />
<Typography style={{ whiteSpace: "nowrap", fontSize: 12 }} >
{name}
</Typography>
<Typography color="text" colorBrightness="secondary">
{value}
</Typography>
</div>
))}
</div>
</Grid>
</Grid>
</Widget>
</Grid>
<Grid item xs={12}>
<Widget
bodyClass={classes.mainChartBody}
header={
<div className={classes.mainChartHeader}>
<Typography
variant="h5"
color="text"
colorBrightness="secondary"
>
Daily Line Chart
</Typography>
<div className={classes.mainChartHeaderLabels}>
<div className={classes.mainChartHeaderLabel}>
<Dot color="warning" />
<Typography className={classes.mainChartLegentElement}>
Tablet
</Typography>
</div>
<div className={classes.mainChartHeaderLabel}>
<Dot color="primary" />
<Typography className={classes.mainChartLegentElement}>
Mobile
</Typography>
</div>
<div className={classes.mainChartHeaderLabel}>
<Dot color="secondary" />
<Typography className={classes.mainChartLegentElement}>
Desktop
</Typography>
</div>
</div>
<Select
value={mainChartState}
onChange={e => setMainChartState(e.target.value)}
input={
<OutlinedInput
labelWidth={0}
classes={{
notchedOutline: classes.mainChartSelectRoot,
input: classes.mainChartSelect,
}}
/>
}
autoWidth
>
<MenuItem value="daily">Daily</MenuItem>
<MenuItem value="weekly">Weekly</MenuItem>
<MenuItem value="monthly">Monthly</MenuItem>
</Select>
</div>
}
>
<ResponsiveContainer width="100%" minWidth={500} height={350}>
<ComposedChart
margin={{ top: 0, right: -15, left: -15, bottom: 0 }}
data={mainChartData}
>
<YAxis
ticks={[0, 2500, 5000, 7500]}
tick={{ fill: theme.palette.text.hint + "80", fontSize: 14 }}
stroke={theme.palette.text.hint + "80"}
tickLine={false}
/>
<XAxis
tickFormatter={i => i + 1}
tick={{ fill: theme.palette.text.hint + "80", fontSize: 14 }}
stroke={theme.palette.text.hint + "80"}
tickLine={false}
/>
<Area
type="natural"
dataKey="desktop"
fill={theme.palette.background.light}
strokeWidth={0}
activeDot={false}
/>
<Line
type="natural"
dataKey="mobile"
stroke={theme.palette.primary.main}
strokeWidth={2}
dot={false}
activeDot={false}
/>
<Line
type="linear"
dataKey="tablet"
stroke={theme.palette.warning.main}
strokeWidth={2}
dot={{
stroke: theme.palette.warning.dark,
strokeWidth: 2,
fill: theme.palette.warning.main,
}}
/>
</ComposedChart>
</ResponsiveContainer>
</Widget>
</Grid>
{mock.bigStat.map(stat => (
<Grid item md={4} sm={6} xs={12} key={stat.product}>
<BigStat {...stat} />
</Grid>
))}
<Grid item xs={12}>
<Widget
title="Support Requests"
upperTitle
noBodyPadding
bodyClass={classes.tableWidget}
>
<Table data={mock.table} />
</Widget>
</Grid>
</Grid>
</>
);
}
Example #15
Source File: GenericChart.js From acy-dex-interface with MIT License | 4 votes |
export default function GenericChart(props) {
const {
loading,
title,
data,
description,
height = CHART_HEIGHT,
yaxisWidth = YAXIS_WIDTH,
yaxisDataKey = 'all',
yaxisTickFormatter = yaxisFormatter,
yaxisDomain,
xaxisDataKey = 'timestamp',
xaxisTickFormatter = tooltipLabelFormatter_,
tooltipFormatter = tooltipFormatter_,
tooltipLabelFormatter = tooltipLabelFormatter_,
items,
type,
syncId,
children,
rightYaxisDataKey,
isCoinChart
} = props
let ChartComponent
if (type === 'Line') {
ChartComponent = LineChart
} else if (type === 'Bar') {
ChartComponent = BarChart
} else {
ChartComponent = ComposedChart
}
// Previous update
// fill: item.color || (isCoinChart ? COINCOLORS[i % COINCOLORS.length] : COLORS[i % COLORS.length]),
// stroke: item.color || (isCoinChart ? COINCOLORS[i % COINCOLORS.length] : COLORS[i % COLORS.length]),
const htmlItems = (items || []).map((item, i) => {
const props = {
type: "monotone",
dataKey: item.key,
stackId: "a",
name: item.name || item.key,
fill: item.color || COLORS[i % COLORS.length],
stroke: item.color || COLORS[i % COLORS.length],
dot: item.dot || false,
key: 'item-' + i,
unit: item.unit,
strokeWidth: item.strokeWidth,
yAxisId: item.yAxisId
}
if (item.type === 'Line' || type === 'Line') {
return <Line {...props} isAnimationActive={false} />
}
return <Bar {...props} isAnimationActive={false} />
})
const csvFields = items.map(item => ({ key: item.key, name: item.name }))
return <ChartWrapper title={title} loading={loading} data={data} csvFields={csvFields}>
<ResponsiveContainer width="100%" height={height}>
{React.createElement(ChartComponent, { data, syncId }, [
<CartesianGrid strokeDasharray="3 3" stroke='#333333' key="a" />,
<XAxis dataKey={xaxisDataKey} tickFormatter={xaxisTickFormatter} minTickGap={30} key="b" />,
<YAxis domain={yaxisDomain} dataKey={yaxisDataKey} tickFormatter={yaxisTickFormatter} key="c" />,
(
rightYaxisDataKey ?
<YAxis dataKey={rightYaxisDataKey} tickFormatter={yaxisTickFormatter} orientation="right" yAxisId="right" key="c2" />
: null
),
<Tooltip
formatter={tooltipFormatter}
labelFormatter={tooltipLabelFormatter}
contentStyle={{ textAlign: 'left' }}
key="d"
/>,
<Legend key="e" />,
...htmlItems,
children
])}
</ResponsiveContainer>
{description && (
<div className="chart-description">
{description}
</div>
)}
</ChartWrapper>
}
Example #16
Source File: Index.js From acy-dex-interface with MIT License | 4 votes |
Stats = (props) => {
const DEFAULT_GROUP_PERIOD = 86400
const [groupPeriod, setGroupPeriod] = useState(DEFAULT_GROUP_PERIOD)
const [fromValue, setFromValue] = useState()
const [toValue, setToValue] = useState()
const { mode } = props
const setDateRange = useCallback(range => {
setFromValue(new Date(Date.now() - range * 1000).toISOString().slice(0, 10))
setToValue(undefined)
}, [setFromValue, setToValue])
const from = fromValue ? +new Date(fromValue) / 1000 : undefined
const to = toValue ? +new Date(toValue) / 1000 : NOW
const params = { from, to, groupPeriod }
const [borrowRateData, borrowRateLoading] = useBorrowRateData(params)
const [volumeData, volumeLoading] = useVolumeData(params)
const [totalVolume] = useTotalVolumeFromServer()
const totalVolumeDelta = useMemo(() => {
if (!volumeData) {
return null
}
return volumeData[volumeData.length - 1].all
}, [volumeData])
const [volumeTest, volumeTestLoading] = useVolumesData(params)
const [feesData, feesLoading] = useFeesData(params)
const [totalFees, totalFeesDelta] = useMemo(() => {
if (!feesData) {
return []
}
const total = feesData[feesData.length - 1]?.cumulative
const delta = total - feesData[feesData.length - 2]?.cumulative
return [total, delta]
}, [feesData])
const [alpData, alpLoading] = useAlpData(params)
const [totalAum, totalAumDelta] = useMemo(() => {
if (!alpData) {
return []
}
const total = alpData[alpData.length - 1]?.aum
const delta = total - alpData[alpData.length - 2]?.aum
return [total, delta]
}, [alpData])
const [aumPerformanceData, aumPerformanceLoading] = useAumPerformanceData(params)
const [alpPerformanceData, alpPerformanceLoading] = useAlpPerformanceData(alpData, feesData, params)
const [alpPriceData, alpPriceDataLoading] = useAlpPriceData(alpData, feesData, params)
const [tradersData, tradersLoading] = useTradersData(params)
const [openInterest, openInterestDelta] = useMemo(() => {
if (!tradersData) {
return []
}
const total = tradersData.data[tradersData.data.length - 1]?.openInterest
const delta = total - tradersData.data[tradersData.data.length - 2]?.openInterest
return [total, delta]
}, [tradersData])
const [swapSources, swapSourcesLoading] = useSwapSources(params)
const swapSourcesKeys = Object.keys((swapSources || []).reduce((memo, el) => {
Object.keys(el).forEach(key => {
if (key === 'all' || key === 'timestamp') return
memo[key] = true
})
return memo
}, {}))
const [usersData, usersLoading] = useUsersData(params)
const [totalUsers, totalUsersDelta] = useMemo(() => {
if (!usersData) {
return [null, null]
}
const total = usersData[usersData.length - 1]?.uniqueCountCumulative
const prevTotal = usersData[usersData.length - 2]?.uniqueCountCumulative
const delta = total && prevTotal ? total - prevTotal : null
return [
total,
delta
]
}, [usersData])
const [lastSubgraphBlock] = useLastSubgraphBlock()
const [lastBlock] = useLastBlock()
const isObsolete = lastSubgraphBlock && lastBlock && lastBlock.timestamp - lastSubgraphBlock.timestamp > 3600
const [isExperiment, setIsExperiment] = useState(false)
useEffect(() => {
setIsExperiment(window.localStorage.getItem('experiment'))
}, [setIsExperiment])
const showForm = false
const [selectedIndexLine, setselectedIndexLine] = useState(0);
const [selectedDataLine, setselectedDataLine] = useState(0);
const [volumeFeeIndex, setVolumeFeeIndex] = useState(0);
const onLineGraphHover = (newData, newIndex) => {
if (volumeFeeIndex != newIndex) {
}
};
const history = useHistory()
return (
<div className='container'>
<div className="Home">
{/* <h1>Analytics / Arbitrum</h1> */}
{lastSubgraphBlock && lastBlock &&
<p className={cx('page-description', { warning: isObsolete })} style={{ marginTop: '-1rem' }}>
{isObsolete && "Data is obsolete. "}
Updated {moment(lastSubgraphBlock.timestamp * 1000).fromNow()}
at block <a target="_blank" href={`https://arbiscan.io/block/${lastSubgraphBlock.number}`}>{lastSubgraphBlock.number}</a>
</p>
}
<div className={`${styles.colItem}`}>
<a
className={`${styles.colItem} ${styles.optionTab}`}
onClick={() => {
history.push('/statistics/market')
}}
>
Market
</a>
<a className={`${styles.colItem} ${styles.optionTabSelected}`}>Future</a>
<a
className={`${styles.colItem} ${styles.optionTab}`}
onClick={() => {
history.push('/statistics/stablecoin')
}}
>
StableCoin
</a>
</div>
{showForm &&
<div className="form">
<p>
<label>Period</label>
<input type="date" value={fromValue} onChange={evt => setFromValue(evt.target.value)} />
—
<input type="date" value={toValue} onChange={evt => setToValue(evt.target.value)} />
<button onClick={evt => setDateRange(86400 * 29)}>30 days</button>
<button onClick={evt => setDateRange(86400 * 6)}>7 days</button>
</p>
</div>
}
<div className="chart-grid">
<div className="chart-cell stats">
{totalVolume ? <>
<div className="total-stat-label">Total Volume</div>
<div className="total-stat-value">
{formatNumber(totalVolume, { currency: true })}
{totalVolumeDelta &&
<span className="total-stat-delta plus" title="Change since previous day">+{formatNumber(totalVolumeDelta, { currency: true, compact: true })}</span>
}
</div>
</> : <RiLoader5Fill size="3em" className="loader" />}
</div>
<div className="chart-cell stats">
{totalFees ? <>
<div className="total-stat-label">Total Fees</div>
<div className="total-stat-value">
{formatNumber(totalFees, { currency: true })}
<span className="total-stat-delta plus" title="Change since previous day">+{formatNumber(totalFeesDelta, { currency: true, compact: true })}</span>
</div>
</> : <RiLoader5Fill size="3em" className="loader" />}
</div>
<div className="chart-cell stats">
{totalAum ? <>
<div className="total-stat-label">ALP Pool</div>
<div className="total-stat-value">
{formatNumber(totalAum, { currency: true })}
<span className={cx("total-stat-delta", (totalAumDelta > 0 ? 'plus' : 'minus'))} title="Change since previous day">{totalAumDelta > 0 ? '+' : ''}{formatNumber(totalAumDelta, { currency: true, compact: true })}</span>
</div>
</> : <RiLoader5Fill size="3em" className="loader" />}
</div>
<div className="chart-cell stats">
{totalUsers ? <>
<div className="total-stat-label">Total Users</div>
<div className="total-stat-value">
{formatNumber(totalUsers)}
<span className="total-stat-delta plus" title="Change since previous day">+{formatNumber(totalUsersDelta)}</span>
</div>
</> : <RiLoader5Fill size="3em" className="loader" />}
</div>
<div className="chart-cell stats">
{openInterest ? <>
<div className="total-stat-label">Open Interest</div>
<div className="total-stat-value">
{formatNumber(openInterest, { currency: true })}
<span className={cx("total-stat-delta", (openInterestDelta > 0 ? 'plus' : 'minus'))} title="Change since previous day">
{openInterestDelta > 0 ? '+' : ''}{formatNumber(openInterestDelta, { currency: true, compact: true })}
</span>
</div>
</> : <RiLoader5Fill size="3em" className="loader" />}
</div>
<div className="chart-cell">
<VolumeFeesChart
data={volumeData}
loading={volumeLoading}
title="VOLUME 24H"
onHover={onLineGraphHover}
/>
{/* <VolumeChart
data={volumeData}
loading={volumeLoading}
chartHeight={CHART_HEIGHT}
yaxisWidth={YAXIS_WIDTH}
xaxisTickFormatter={tooltipLabelFormatter}
yaxisTickFormatter={yaxisFormatter}
tooltipLabelFormatter={tooltipLabelFormatter}
tooltipFormatter={tooltipFormatter}
/> */}
</div>
<div className="chart-cell">
<VolumeFeesChart
data={feesData}
loading={feesLoading}
title="Fee"
onHover={onLineGraphHover}
/>
{/* <FeesChart
data={feesData?feesData.slice(0,10):feesData}
loading={feesLoading}
chartHeight={CHART_HEIGHT}
yaxisWidth={YAXIS_WIDTH}
xaxisTickFormatter={tooltipLabelFormatter}
yaxisTickFormatter={yaxisFormatter}
tooltipLabelFormatter={tooltipLabelFormatter}
tooltipFormatter={tooltipFormatter}
/> */}
</div>
<div className="chart-cell">
<ChartWrapper title="AUM & Alp Supply" loading={alpLoading} data={alpData} csvFields={[{ key: 'aum' }, { key: 'alpSupply' }]}>
<ResponsiveContainer width="100%" height={CHART_HEIGHT}>
<LineChart data={alpData} syncId="syncAlp">
<CartesianGrid strokeDasharray="3 3" stroke='#333333' />
<XAxis dataKey="timestamp" tickFormatter={tooltipLabelFormatter} minTickGap={30} />
<YAxis dataKey="aum" tickFormatter={yaxisFormatter} width={YAXIS_WIDTH} />
<Tooltip
formatter={tooltipFormatterNumber}
labelFormatter={tooltipLabelFormatter}
contentStyle={{ textAlign: 'left' }}
/>
<Legend />
<Line isAnimationActive={false} type="monotone" strokeWidth={2} unit="$" dot={false} dataKey="aum" stackId="a" name="AUM" stroke={COLORS[0]} />
<Line isAnimationActive={false} type="monotone" strokeWidth={2} dot={false} dataKey="alpSupply" stackId="a" name="Alp Supply" stroke={COLORS[1]} />
</LineChart>
</ResponsiveContainer>
</ChartWrapper>
</div>
<div className="chart-cell">
<ChartWrapper
title="Alp Price Comparison"
loading={alpLoading}
data={alpPriceData}
csvFields={[{ key: 'syntheticPrice' }, { key: 'alpPrice' }, { key: 'alpPlusFees' }, { key: 'lpBtcPrice' }, { key: 'lpEthPrice' }]}
>
<ResponsiveContainer width="100%" height={CHART_HEIGHT}>
<LineChart data={alpPriceData} syncId="syncAlp">
<CartesianGrid strokeDasharray="3 3" stroke='#333333' />
<XAxis dataKey="timestamp" tickFormatter={tooltipLabelFormatter} minTickGap={30} />
<YAxis dataKey="performanceSyntheticCollectedFees" domain={[60, 210]} unit="%" tickFormatter={yaxisFormatterNumber} width={YAXIS_WIDTH} />
<YAxis dataKey="alpPrice" domain={[0.4, 1.7]} orientation="right" yAxisId="right" tickFormatter={yaxisFormatterNumber} width={YAXIS_WIDTH} />
<Tooltip
formatter={tooltipFormatterNumber}
labelFormatter={tooltipLabelFormatter}
contentStyle={{ textAlign: 'left' }}
/>
<Legend />
{/* <Line dot={false} isAnimationActive={false} type="monotone" unit="%" strokeWidth={2} dataKey="performanceLpBtcCollectedFees" name="% LP BTC-USDC (w/ fees)" stroke={COLORS[2]} />
<Line dot={false} isAnimationActive={false} type="monotone" unit="%" strokeWidth={2} dataKey="performanceLpEthCollectedFees" name="% LP ETH-USDC (w/ fees)" stroke={COLORS[4]} />
<Line dot={false} isAnimationActive={false} type="monotone" unit="%" strokeWidth={2} dataKey="performanceSyntheticCollectedFees" name="% Index (w/ fees)" stroke={COLORS[0]} /> */}
{/* <Line isAnimationActive={false} type="monotone" unit="$" strokeWidth={1} yAxisId="right" dot={false} dataKey="syntheticPrice" name="Index Price" stroke={COLORS[2]} /> */}
<Line isAnimationActive={false} type="monotone" unit="$" strokeWidth={1} yAxisId="right" dot={false} dataKey="alpPrice" name="Alp Price" stroke={COLORS[1]} strokeWidth={1} />
<Line isAnimationActive={false} type="monotone" unit="$" strokeWidth={1} yAxisId="right" dot={false} dataKey="alpPlusFees" name="Alp w/ fees" stroke={COLORS[3]} strokeWidth={1} />
{/* <Line isAnimationActive={false} type="monotone" unit="$" strokeWidth={1} yAxisId="right" dot={false} dataKey="lpBtcPrice" name="LP BTC-USDC" stroke={COLORS[2]} />
<Line isAnimationActive={false} type="monotone" unit="$" strokeWidth={1} yAxisId="right" dot={false} dataKey="lpEthPrice" name="LP ETH-USDC" stroke={COLORS[4]} /> */}
</LineChart>
</ResponsiveContainer>
<div className="chart-description">
<p>
<span style={{ color: COLORS[3] }}>Alp with fees</span> is based on ALP share of fees received and excluding esGMX rewards<br />
{/* <span style={{ color: COLORS[0] }}>% of Index (with fees)</span> is Alp with fees / Index Price * 100<br />
<span style={{ color: COLORS[4] }}>% of LP ETH-USDC (with fees)</span> is Alp Price with fees / LP ETH-USDC * 100<br />
<span style={{ color: COLORS[2] }}>Index Price</span> is 25% BTC, 25% ETH, 50% USDC */}
</p>
</div>
</ChartWrapper>
</div>
{isExperiment && <div className="chart-cell experiment">
<ChartWrapper title="Performance vs. Index" loading={alpLoading}>
<ResponsiveContainer width="100%" height={CHART_HEIGHT}>
<LineChart data={alpPerformanceData} syncId="syncAlp">
<CartesianGrid strokeDasharray="3 3" stroke='#333333' />
<XAxis dataKey="timestamp" tickFormatter={tooltipLabelFormatter} minTickGap={30} />
<YAxis dataKey="performanceSyntheticCollectedFees" domain={[80, 120]} unit="%" tickFormatter={yaxisFormatterNumber} width={YAXIS_WIDTH} />
<Tooltip
formatter={tooltipFormatterNumber}
labelFormatter={tooltipLabelFormatter}
contentStyle={{ textAlign: 'left' }}
/>
<Legend />
<Line isAnimationActive={false} dot={false} type="monotone" unit="%" strokeWidth={2} dataKey="performanceSyntheticCollectedFees" name="Collected Fees" stroke={COLORS[0]} />
<Line isAnimationActive={false} dot={false} type="monotone" unit="%" strokeWidth={2} dataKey="performanceSyntheticDistributedUsd" name="Distributed Usd" stroke={COLORS[1]} />
<Line isAnimationActive={false} dot={false} type="monotone" unit="%" strokeWidth={2} dataKey="performanceSyntheticDistributedEth" name="Distributed Eth" stroke={COLORS[2]} />
<Line isAnimationActive={false} dot={false} type="monotone" unit="%" strokeWidth={2} dataKey="performanceSynthetic" name="No Fees" stroke={COLORS[3]} />
</LineChart>
</ResponsiveContainer>
</ChartWrapper>
</div>}
{isExperiment && <div className="chart-cell experiment">
<ChartWrapper title="Performance vs. ETH LP" loading={alpLoading}>
<ResponsiveContainer width="100%" height={CHART_HEIGHT}>
<LineChart data={alpPerformanceData} syncId="syncAlp">
<CartesianGrid strokeDasharray="3 3" stroke='#333333' />
<XAxis dataKey="timestamp" tickFormatter={tooltipLabelFormatter} minTickGap={30} />
<YAxis dataKey="performanceLpEthCollectedFees" domain={[80, 120]} unit="%" tickFormatter={yaxisFormatterNumber} width={YAXIS_WIDTH} />
<Tooltip
formatter={tooltipFormatterNumber}
labelFormatter={tooltipLabelFormatter}
contentStyle={{ textAlign: 'left' }}
/>
<Legend />
<Line isAnimationActive={false} dot={false} type="monotone" unit="%" strokeWidth={2} dataKey="performanceLpEthCollectedFees" name="Collected Fees" stroke={COLORS[0]} />
<Line isAnimationActive={false} dot={false} type="monotone" unit="%" strokeWidth={2} dataKey="performanceLpEthDistributedUsd" name="Distributed Usd" stroke={COLORS[1]} />
<Line isAnimationActive={false} dot={false} type="monotone" unit="%" strokeWidth={2} dataKey="performanceLpEthDistributedEth" name="Distributed Eth" stroke={COLORS[2]} />
<Line isAnimationActive={false} dot={false} type="monotone" unit="%" strokeWidth={2} dataKey="performanceLpEth" name="No Fees" stroke={COLORS[3]} />
</LineChart>
</ResponsiveContainer>
</ChartWrapper>
</div>}
<div className="chart-cell">
<ChartWrapper
title="Traders Net PnL"
loading={tradersLoading}
data={tradersData?.data}
csvFields={[{ key: 'pnl', name: 'Net PnL' }, { key: 'pnlCumulative', name: 'Cumulative PnL' }]}
>
<ResponsiveContainer width="100%" syncId="tradersId" height={CHART_HEIGHT}>
<ComposedChart data={tradersData?.data}>
<CartesianGrid strokeDasharray="3 3" stroke='#333333' />
<XAxis dataKey="timestamp" tickFormatter={tooltipLabelFormatter} minTickGap={30} />
<YAxis domain={[-tradersData?.stats.maxAbsOfPnlAndCumulativePnl * 1.05, tradersData?.stats.maxAbsOfPnlAndCumulativePnl * 1.05]} tickFormatter={yaxisFormatter} width={YAXIS_WIDTH} />
<Tooltip
formatter={tooltipFormatter}
labelFormatter={tooltipLabelFormatter}
contentStyle={{ textAlign: 'left' }}
/>
<Legend />
<Bar type="monotone" fill={mode == "dark" ? "#FFFFFF" : "#000000"} dot={false} dataKey="pnl" name="Net PnL">
{(tradersData?.data || []).map((item, i) => {
return <Cell key={`cell-${i}`} fill={item.pnl > 0 ? '#22c761' : '#f93333'} />
})}
</Bar>
<Line type="monotone" strokeWidth={2} stroke={COLORS[4]} dataKey="pnlCumulative" name="Cumulative PnL" />
</ComposedChart>
</ResponsiveContainer>
<div className="chart-description">
<p>Considers settled (closed) positions</p>
<p>Fees are not factored into PnL</p>
</div>
</ChartWrapper>
</div>
<div className="chart-cell">
<ChartWrapper
title="Traders Profit vs. Loss"
loading={tradersLoading}
data={tradersData?.data}
csvFields={[{ key: 'profit' }, { key: 'loss' }, { key: 'profitCumulative' }, { key: 'lossCumulative' }]}
>
<ResponsiveContainer width="100%" syncId="tradersId" height={CHART_HEIGHT}>
<ComposedChart data={tradersData?.data} barGap={0}>
<CartesianGrid strokeDasharray="3 3" stroke='#333333' />
<XAxis dataKey="timestamp" tickFormatter={tooltipLabelFormatter} minTickGap={30} />
<YAxis domain={[-tradersData?.stats.maxProfitLoss * 1.05, tradersData?.stats.maxProfitLoss * 1.05]} tickFormatter={yaxisFormatter} width={YAXIS_WIDTH} />
<YAxis domain={[-tradersData?.stats.maxCumulativeProfitLoss * 1.1, tradersData?.stats.maxCumulativeProfitLoss * 1.1]} orientation="right" yAxisId="right" tickFormatter={yaxisFormatter} width={YAXIS_WIDTH} />
<Tooltip
formatter={tooltipFormatter}
labelFormatter={tooltipLabelFormatter}
contentStyle={{ textAlign: 'left' }}
/>
<Legend />
<Area yAxisId="right" type="monotone" stroke={0} fill="#22c761" fillOpacity="0.4" dataKey="profitCumulative" name="Cumulative Profit" />
<Area yAxisId="right" type="monotone" stroke={0} fill="#f93333" fillOpacity="0.4" dataKey="lossCumulative" name="Cumulative Loss" />
<Bar type="monotone" fill="#22c761" dot={false} dataKey="profit" name="Profit" />
<Bar type="monotone" fill="#f93333" dot={false} dataKey="loss" name="Loss" />
</ComposedChart>
</ResponsiveContainer>
<div className="chart-description">
<p>Considers settled (closed) positions</p>
<p>Fees are not factored into PnL</p>
</div>
</ChartWrapper>
</div>
<div className="chart-cell">
<GenericChart
loading={borrowRateLoading}
title="Borrowing Rate Annualized"
data={borrowRateData}
yaxisDataKey="ETH"
yaxisTickFormatter={yaxisFormatterPercent}
tooltipFormatter={tooltipFormatterPercent}
items={[{ key: 'ETH' }, { key: 'BTC' }, { key: 'USDC' }, { key: 'USDT' }, { key: 'MATIC' }]}
type="Line"
yaxisDomain={[0, 90 /* ~87% is a maximum yearly borrow rate */]}
isCoinChart={true}
/>
</div>
<div className="chart-cell">
<GenericChart
loading={tradersLoading}
title="Open Interest"
data={tradersData?.data.map(item => ({ all: item.openInterest, ...item }))}
yaxisDataKey="openInterest"
items={[{ key: 'shortOpenInterest', name: 'Short', color: "#f93333" }, { key: 'longOpenInterest', name: 'Long', color: '#22c761' }]}
type="Bar"
/>
</div>
<div className="chart-cell">
<GenericChart
syncId="syncAlp"
loading={aumPerformanceLoading}
title="AUM Performance Annualized"
data={aumPerformanceData}
yaxisDataKey="apr"
yaxisTickFormatter={yaxisFormatterPercent}
tooltipFormatter={tooltipFormatterPercent}
items={[{ key: 'apr', name: 'APR', color: COLORS[0] }]}
description="Formula = Daily Fees / ALP Pool * 365 days * 100"
type="Composed"
/>
</div>
<div className="chart-cell">
<GenericChart
syncId="syncAlp"
loading={aumPerformanceLoading}
title="AUM Daily Usage"
data={aumPerformanceData}
yaxisDataKey="usage"
yaxisTickFormatter={yaxisFormatterPercent}
tooltipFormatter={tooltipFormatterPercent}
items={[{ key: 'usage', name: 'Daily Usage', color: COLORS[4] }]}
description="Formula = Daily Volume / ALP Pool * 100"
type="Composed"
/>
</div>
<div className="chart-cell">
<GenericChart
syncId="syncAlp"
loading={usersLoading}
title="Unique Users"
data={usersData}
yaxisDataKey="uniqueSum"
yaxisTickFormatter={yaxisFormatterNumber}
tooltipFormatter={tooltipFormatterNumber}
tooltipLabelFormatter={tooltipLabelFormatterUnits}
items={[
{ key: 'uniqueSwapCount', name: 'Swaps' },
{ key: 'uniqueMarginCount', name: 'Margin trading' },
{ key: 'uniqueMintBurnCount', name: 'Mint & Burn ALP' }
]}
type="Composed"
/>
</div>
<div className="chart-cell">
<GenericChart
syncId="syncAlp"
loading={usersLoading}
title="New Users"
data={usersData?.map(item => ({ ...item, all: item.newCount }))}
yaxisDataKey="newCount"
rightYaxisDataKey="uniqueCountCumulative"
yaxisTickFormatter={yaxisFormatterNumber}
tooltipFormatter={tooltipFormatterNumber}
tooltipLabelFormatter={tooltipLabelFormatterUnits}
items={[
{ key: 'newSwapCount', name: 'Swap' },
{ key: 'newMarginCount', name: 'Margin trading' },
{ key: 'newMintBurnCount', name: 'Mint & Burn' },
{ key: 'uniqueCountCumulative', name: 'Cumulative', type: 'Line', yAxisId: 'right', strokeWidth: 2, color: COLORS[4] }
]}
type="Composed"
/>
</div>
<div className="chart-cell">
<GenericChart
syncId="syncAlp"
loading={usersLoading}
title="New vs. Existing Users"
data={usersData?.map(item => ({ ...item, all: item.uniqueCount }))}
yaxisDataKey="newCount"
rightYaxisDataKey="oldPercent"
yaxisTickFormatter={yaxisFormatterNumber}
tooltipFormatter={tooltipFormatterNumber}
tooltipLabelFormatter={tooltipLabelFormatterUnits}
items={[
{ key: 'newCount', name: 'New' },
{ key: 'oldCount', name: 'Existing' },
{ key: 'oldPercent', name: 'Existing %', yAxisId: 'right', type: 'Line', strokeWidth: 2, color: COLORS[4], unit: '%' }
]}
type="Composed"
/>
</div>
<div className="chart-cell">
<GenericChart
syncId="syncAlp"
loading={usersLoading}
title="User Actions"
data={(usersData || []).map(item => ({ ...item, all: item.actionCount }))}
yaxisDataKey="actionCount"
yaxisTickFormatter={yaxisFormatterNumber}
tooltipFormatter={tooltipFormatterNumber}
tooltipLabelFormatter={tooltipLabelFormatterUnits}
items={[{ key: 'actionSwapCount', name: 'Swaps' }, { key: 'actionMarginCount', name: 'Margin trading' }, { key: 'actionMintBurnCount', name: 'Mint & Burn ALP' }]}
type="Composed"
/>
</div>
{/* <div className="chart-cell">
<GenericChart
loading={swapSourcesLoading}
title="Swap Sources"
data={swapSources}
items={swapSourcesKeys.map(key => ({ key }))}
/>
</div> */}
</div>
</div>
</div>
);
}
Example #17
Source File: RtcMetricsView.jsx From amazon-connect-snippets with MIT No Attribution | 3 votes |
render() {
const {
classes, className: classNameProp,
type, timeRange, indexRange: [startIndex, endIndex],
} = this.props;
const {
data, originalData,
brushHovering, refAreaLeft, refAreaRight,
} = this.state;
return (
<div className={clsx(classes.root, classNameProp)}>
<Container
title={`WebRTC Metrics - ${type}`}
gutters={false}
actionGroup={(
<Button
className={classes.zoomResetButton}
onClick={this.handleZoomReset}
>
Zoom Reset
</Button>
)}
>
<div className={classes.content}>
{/* Audio Level */}
<ResponsiveContainer width="100%" height={200}>
<LineChart
data={data}
margin={{
top: 5, right: 20, bottom: 5, left: 20,
}}
onMouseDown={this.handleMouseDown}
onMouseMove={this.handleMouseMove}
onMouseUp={this.handleZoom}
>
<YAxis allowDataOverflow type="number">
<Label angle={270} position="left" style={{ textAnchor: 'middle' }}>
Audio Level
</Label>
</YAxis>
<XAxis allowDataOverflow dataKey={TIMESTAMP_KEY} tick={this.renderCustomAxisTick} type="number" domain={timeRange} />
<CartesianGrid />
<Line
type="linear"
dataKey="audioLevel"
stroke={colorMap.audioLevel}
strokeWidth={2}
dot={false}
activeDot
connectNulls={false}
isAnimationActive={false}
/>
<Tooltip content={this.renderCustomTooltip(['audioLevel'])} />
<Legend verticalAlign="bottom" />
{ (refAreaLeft && refAreaRight) && (
<ReferenceArea
x1={refAreaLeft}
x2={refAreaRight}
strokeOpacity={0.3}
/>
)}
</LineChart>
</ResponsiveContainer>
{/* Packets */}
<ResponsiveContainer width="100%" height={200}>
<ComposedChart
data={data}
margin={{
top: 5, right: 20, bottom: 5, left: 20,
}}
onMouseDown={this.handleMouseDown}
onMouseMove={this.handleMouseMove}
onMouseUp={this.handleZoom}
>
<YAxis allowDataOverflow type="number">
<Label angle={270} position="left" style={{ textAnchor: 'middle' }}>
Packets
</Label>
</YAxis>
<XAxis allowDataOverflow dataKey={TIMESTAMP_KEY} tick={this.renderCustomAxisTick} type="number" domain={timeRange} />
<CartesianGrid />
<Line
type="linear"
dataKey="packetsLost"
stroke={colorMap.packetsLost}
strokeWidth={2}
dot={false}
activeDot
connectNulls={false}
isAnimationActive={false}
/>
<Line
type="linear"
dataKey="packetsCount"
stroke={colorMap.packetsCount}
strokeWidth={2}
dot={false}
activeDot
connectNulls={false}
isAnimationActive={false}
/>
<Tooltip content={this.renderCustomTooltip(['packetsLost', 'packetsCount'])} />
<Legend verticalAlign="bottom" />
{ (refAreaLeft && refAreaRight) && (
<ReferenceArea
x1={refAreaLeft}
x2={refAreaRight}
strokeOpacity={0.3}
/>
)}
</ComposedChart>
</ResponsiveContainer>
{/* Jitter Buffer and RTT */}
<ResponsiveContainer width="100%" height={200}>
<ComposedChart
data={data}
margin={{
top: 5, right: 20, bottom: 5, left: 20,
}}
onMouseDown={this.handleMouseDown}
onMouseMove={this.handleMouseMove}
onMouseUp={this.handleZoom}
>
<YAxis allowDataOverflow type="number">
{ type === 'audio_input' && (
<Label angle={270} position="left" style={{ textAnchor: 'middle' }}>
Jitter Buffer (ms)
</Label>
)}
{ type === 'audio_output' && (
<Label angle={270} position="left" style={{ textAnchor: 'middle' }}>
Jitter Buffer & RTT (ms)
</Label>
)}
</YAxis>
<XAxis allowDataOverflow dataKey={TIMESTAMP_KEY} tick={this.renderCustomAxisTick} type="number" domain={timeRange} />
<CartesianGrid />
<Line
type="linear"
dataKey="jitterBufferMillis"
stroke={colorMap.jitterBufferMillis}
strokeWidth={2}
dot={false}
activeDot
connectNulls={false}
isAnimationActive={false}
/>
{ type === 'audio_output' && (
<Line
type="linear"
dataKey="roundTripTimeMillis"
stroke={colorMap.roundTripTimeMillis}
strokeWidth={2}
dot={false}
activeDot
connectNulls={false}
isAnimationActive={false}
/>
)}
<Tooltip
content={
type === 'audio_output'
? this.renderCustomTooltip(['jitterBufferMillis', 'roundTripTimeMillis'])
: this.renderCustomTooltip(['jitterBufferMillis'])
}
/>
<Legend verticalAlign="bottom" />
{ (refAreaLeft && refAreaRight) && (
<ReferenceArea
x1={refAreaLeft}
x2={refAreaRight}
strokeOpacity={0.3}
/>
)}
</ComposedChart>
</ResponsiveContainer>
{/* Brush */}
<ResponsiveContainer width="100%" height={60}>
<ComposedChart
// update data to force re-rendering
data={brushHovering ? originalData : [...originalData]}
margin={{
top: 5, right: 20, bottom: 5, left: 20,
}}
onMouseEnter={() => this.setState({ brushHovering: true })}
onMouseLeave={() => this.setState({ brushHovering: false })}
>
<Brush
className="TimeLineChart-brush"
dataKey={TIMESTAMP_KEY}
stroke="#666666"
startIndex={startIndex || 0}
endIndex={endIndex || originalData.length - 1}
onChange={this.handleChangeBrush}
tickFormatter={this.formatBrushTick}
/>
</ComposedChart>
</ResponsiveContainer>
</div>
</Container>
</div>
);
}