recharts#ReferenceArea JavaScript Examples

The following examples show how to use recharts#ReferenceArea. 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: MainLineChart.js    From covid with GNU General Public License v3.0 4 votes vote down vote up
MainLineChart = () => {
    const chartData = useSelector(state => state.chartData.data);
    const maximums = useSelector(state => state.chartData.maximums);
    const dataParams = useSelector(state => state.dataParams);
    const nType = useSelector(state => state.dataParams.nType);
    const dType = useSelector(state => state.dataParams.dType);
    const currentVariable = useSelector(state => state.currentVariable);
    const currentData = useSelector(state => state.currentData);
    const selectionKeys = useSelector(state => state.selectionKeys);
    const selectionNames = useSelector(state => state.selectionNames);
    const storedData = useSelector(state => state.storedData);
    const currentTable = useSelector(state => state.currentTable);
    const populationNormalized = useSelector(state => state.chartParams.populationNormalized);

    const [logChart, setLogChart] = useState(false);
    const [showSummarized, setShowSummarized] = useState(true);
    const [activeLine, setActiveLine] = useState(false);

    const dispatch = useDispatch();

    const handleSwitch = () => setLogChart(prev => !prev)
    const handlePopSwitch = () => dispatch(setChartParams({populationNormalized: !populationNormalized}))
    const handleSummarizedSwitch = () => setShowSummarized(prev => !prev)
    const handleChange = (newValue) => {
        if (nType === "time-series" && dType === "time-series") {
            dispatch(setVariableParams({nIndex: newValue, dIndex: newValue}))
        } else if (nType === "time-series") {
            dispatch(setVariableParams({nIndex: newValue}))
        } else if (dType === "time-series") {
            dispatch(setVariableParams({dIndex: newValue}))
        } else if (currentVariable.includes('Testing')){
            dispatch(setVariableParams({nIndex: newValue}))
        }
    };
    const chartSetDate = (e) => {
        if (e?.activeTooltipIndex !== undefined) {
            if (storedData[currentTable.numerator].dates.indexOf(e.activeTooltipIndex) !== -1) {
                handleChange(e.activeTooltipIndex)
            } else {
                handleChange(storedData[currentTable.numerator].dates.reduce((a, b) => {return Math.abs(b - e.activeTooltipIndex) < Math.abs(a - e.activeTooltipIndex) ? b : a}))
            }
        }
    }    

    const rangeIncrement = ( maximum ) => {
        let returnArray = []
        const increment = 2*10**(`${maximum}`.length-1);
        for (let i=0; i<maximum; i+=increment) {
            returnArray.push(i)
        }

        return returnArray;
    }

    const handleLegendHover = (o) => {
        setActiveLine(o.dataKey)
    }

    const handleLegendLeave = () => {
        setActiveLine(false)
    }

    if (maximums && chartData) {
        return (
            <ChartContainer id="lineChart">
                {(selectionNames.length < 2) ?
                    <ChartTitle>Total Cases and 7-Day Average New Cases {selectionNames.length ? `: ${selectionNames[0]}` : ''}</ChartTitle>
                    : 
                    <ChartTitle>7-Day Average New Cases</ChartTitle>
                }
                <ResponsiveContainer width="100%" height="80%">
                    <LineChart
                        data={chartData}
                        margin={{
                            top: 0, right: 10, left: 10, bottom: 20,
                        }}
                        onClick={nType === 'characteristic' ? '' : chartSetDate}
                    >
                        <XAxis 
                            dataKey="date"
                            ticks={dateRange}
                            minTickGap={-50}
                            tick={
                                <CustomTick
                                style={{
                                    fill: `${colors.white}88`,
                                    fontSize: "10px",
                                    fontFamily: "Lato",
                                    fontWeight: 600,
                                    transform:'translateY(10px)'
                                }}
                                labelFormatter={dateFormatter}
                                />
                            }
                        />
                        <YAxis yAxisId="left" type="number" scale={logChart ? "log" : "linear"} domain={[0.01, 'dataMax']} allowDataOverflow 
                            ticks={selectionKeys.length === 0 ? rangeIncrement({maximum: maximums.sum}) : []} 
                            minTickGap={1}
                            tick={
                                <CustomTick
                                style={{
                                    fill: colors.lightgray,
                                    fontSize: "10px",
                                    fontFamily: "Lato",
                                    fontWeight: 600
                                }}
                                labelFormatter={numberFormatter}
                                />
                            }
                            >
                            <Label value="Total Cases" position='insideLeft' style={{marginTop:10, fill:colors.lightgray, fontFamily: 'Lato', fontWeight: 600}} angle={-90}  />
                        </YAxis>
                        <YAxis yAxisId="right" orientation="right" scale={logChart ? "log" : "linear"} domain={[0.01, 'dataMax']} allowDataOverflow 
                            ticks={selectionKeys.length === 0 ? rangeIncrement({maximum: maximums.count}) : []}
                            minTickGap={1}
                            tick={
                                <CustomTick
                                    style={{
                                        fill: colors.yellow,
                                        fontSize: "10px",
                                        fontFamily: "Lato",
                                        fontWeight: 600,
                                    }}
                                    labelFormatter={numberFormatter}
                                />
                            }
                            >
                            <Label value="7-Day Average New Cases" position='insideTopRight' style={{marginTop:10, fill:(selectionKeys.length < 2 ? colors.yellow : colors.lightgray), fontFamily: 'Lato', fontWeight: 600}} angle={-90}  />
                        </YAxis>
                        <Tooltip
                            content={CustomTooltip}
                        />
                        <ReferenceArea 
                            yAxisId="left"
                            x1={dataParams.nRange === null ? 
                                dataParams.variableName.indexOf('Testing') !== -1 ? dataParams.nIndex - 7 : 0
                                : dataParams.nIndex-dataParams.nRange}
                            x2={dataParams.nIndex}
                            fill="white" 
                            fillOpacity={0.15}
                            isAnimationActive={false}
                        />
                        {selectionKeys.length < 2 && <Line type="monotone" yAxisId="left" dataKey={"sum"} name="Total Cases" stroke={colors.lightgray} dot={false} isAnimationActive={false} /> }
                        {selectionKeys.length < 2 && <Line type="monotone" yAxisId="right" dataKey={selectionKeys.length > 0 ? selectionNames[0] : "count"} name="7-Day Average New Cases" stroke={colors.yellow} dot={false} isAnimationActive={false} /> }
                        
                        {(selectionKeys.length > 1 && showSummarized) &&
                                <Line 
                                    type='monotone'
                                    yAxisId='right'
                                    dataKey='sum'
                                    name='Total For Selection' 
                                    stroke={colors.lightgray}
                                    strokeWidth={3} 
                                    dot={false} 
                                    isAnimationActive={false}  
                                />
                        }
                        {selectionKeys.length > 1 && 
                            selectionNames.map((key,index) => {
                                return <Line 
                                    type='monotone'
                                    yAxisId='left' 
                                    dataKey={key} 
                                    name={key + ' 7-Day Ave'} 
                                    stroke={selectionKeys.length > colors.qualtitiveScale.length ? 'white' : colors.qualtitiveScale[index]} 
                                    dot={false} 
                                    isAnimationActive={false}  
                                    strokeOpacity={activeLine === key ? 1 : 0.7}
                                    strokeWidth={activeLine === key ? 3 : 1}
                                />}
                            )
                        }
                        {selectionKeys.length < colors.qualtitiveScale.length && <Legend 
                            onMouseEnter={handleLegendHover} 
                            onMouseLeave={handleLegendLeave}
                        />}
                    </LineChart>
                </ResponsiveContainer>
                <SwitchesContainer>
                    <StyledSwitch>
                        <Switch
                            checked={logChart}
                            onChange={handleSwitch}
                            name='log chart switch'
                            inputProps={{ 'aria-label': 'secondary checkbox' }}
                        />
                        <p>{logChart ? 'Log Scale' : 'Linear Scale'}</p>
                    </StyledSwitch>
                    <StyledSwitch>
                        <Switch
                            checked={populationNormalized}
                            onChange={handlePopSwitch}
                            name='population normalized chart switch'
                            inputProps={{ 'aria-label': 'secondary checkbox' }}
                        />
                        <p>{populationNormalized ? 'Per 100k' : 'Counts'}</p>
                    </StyledSwitch>
                    {selectionKeys.length > 1 && <StyledSwitch>
                        <Switch
                            checked={showSummarized}
                            onChange={handleSummarizedSwitch}
                            name='show summarized chart switch'
                            inputProps={{ 'aria-label': 'secondary checkbox' }}
                        />
                        <p>{showSummarized ? `Show ${populationNormalized ? 'Average' : 'Total'} For Selection` : `Show ${currentData.includes('state') ? 'States' : 'Counties'}` }</p>
                    </StyledSwitch>}
                </SwitchesContainer>
            </ChartContainer>
        );
    } else {
        return <div></div>
    }
}
Example #2
Source File: MetricsView.jsx    From amazon-connect-snippets with MIT No Attribution 4 votes vote down vote up
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 #3
Source File: SkewMetricsView.jsx    From amazon-connect-snippets with MIT No Attribution 4 votes vote down vote up
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 #4
Source File: MultiLinePlot.jsx    From covince with MIT License 4 votes vote down vote up
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 #5
Source File: AdvancedGraph.js    From covid-19 with MIT License 4 votes vote down vote up
Chart = (props) => {
  const ordered = (props.specs || []).sort((a, b) => {
    if (a.derived && !b.derived) {
      return -1;
    } else if (!a.derived && b.derived) {
      return 1;
    } else {
      return a.label < b.label ? -1 : 1;
    }
  });

  let YAxis0Color = "black";
  let YAxis1Color = undefined;
  for (const s of ordered) {
    if (s.rightAxis) {
      YAxis1Color = s.color;
    } else {
      YAxis0Color = s.color;
    }
  }

  function getvRefLines(lines) {
    let result = (lines || []).map((l, idx) => {
      return <ReferenceLine key={`vrefline${idx}`}
        x={l.date}
        stroke="#e3e3e3"
        strokeWidth={1}
      >
        <Label value={l.label} position={"insideTop"} fill="#b3b3b3" />
      </ReferenceLine>
    }
    );
    return result;
  }

  function getvRefAreas(lines) {
    let result = (lines || []).map((l, idx) => {
      const startdate = l.date;
      const today = moment().unix();
      let enddate = startdate + 14 * 24 * 60 * 60;
      while (enddate > today) {
        enddate -= 24 * 60 * 60;
      }
      return <ReferenceArea key={`vrefarea${idx}`}
        x1={startdate} x2={enddate}
        // stroke="red"
        // strokeOpacity={0.3}
        fillOpacity={0.15}
      />
    }
    );
    return result;
  }


  function gethRefLines(lines) {
    let result = (lines || []).map((l, idx) => {
      return <ReferenceLine key={`hrefline${idx}`}
        y={l.value}
        stroke="#e3e3e3"
        strokeWidth={1}
      >
        <Label value={l.label} position={"insideLeft"} ></Label>
      </ReferenceLine>
    }
    );
    return result;
  }

  let vRefLines = getvRefLines(props.vRefLines);
  let hRefLines = gethRefLines(props.hRefLines);

  return (
    <ResponsiveContainer height={300}>
      <LineChart data={props.data} margin={{ left: -4, right: 8 }}>
        {vRefLines}
        {hRefLines}
        {getvRefAreas(props.vRefLines)}
        <Tooltip
          formatter={valueFormatter}
          labelFormatter={props.timestampFormatter}
        />
        <XAxis
          dataKey="timestamp"
          tickFormatter={props.timestampFormatter}
        />
        <YAxis
          yAxisId={0}
          tick={{ fill: YAxis0Color }}
          scale={props.scale === 'Log' ? logScale : props.scale}
          width={50}
          tickFormatter={props.yAxisFormatter}
        />
        {YAxis1Color &&
          <YAxis
            yAxisId={1}
            tickFormatter={props.yAxisFormatter}
            width={35}
            tick={{ fill: YAxis1Color }}
            orientation="right"
          />
        }
        <CartesianGrid stroke="#d5d5d5" strokeDasharray="5 5" />

        {ordered.flatMap(spec => specToElements(spec))}
      </LineChart>
    </ResponsiveContainer>
  );
}
Example #6
Source File: RtcMetricsView.jsx    From amazon-connect-snippets with MIT No Attribution 3 votes vote down vote up
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 &amp; 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>
        );
    }