Skip to content

Commit

Permalink
feat(OurChartCollection): includes cumulative testing timeseries
Browse files Browse the repository at this point in the history
  • Loading branch information
JayWelsh committed Mar 22, 2020
1 parent 3795b2e commit 56a9cab
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 31 deletions.
16 changes: 11 additions & 5 deletions src/components/OurChartCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import OurHorizontalBarChartVX from "./vx/OurHorizontalBarChartVX";
import OurChartContainerVX from "./vx/OurChartContainerVX";
import {isConsideredMobile} from "../utils";

const OurChartCollection = ({confirmedCasesGroupedByDate = [], confirmedCasesHeaderData = []}) => {
const OurChartCollection = ({confirmedCasesGroupedByDate = [], confirmedCasesHeaderData = [], testingCasesTimeseries = []}) => {
const [provinceNewCasesHorizontalChartData, setProvinceNewCasesHorizontalChartData] = useState(false);
const [provinceCumulativeCasesHorizontalChartData, setProvinceCumulativeCasesHorizontalChartData] = useState(false);
const [newCasesLineChartData, setNewCasesLineChartData] = useState(false);
const [cumulativeCasesLineChartData, setCumulativeCasesLineChartData] = useState(false);

useEffect(() => {
let indexOfProvince = confirmedCasesHeaderData.indexOf("province");
let dateToCollection = {};
Expand Down Expand Up @@ -81,15 +82,15 @@ const OurChartCollection = ({confirmedCasesGroupedByDate = [], confirmedCasesHea
setProvinceCumulativeCasesHorizontalChartData(provinceCumulativeCasesHorizontalChartData.reverse());
setCumulativeCasesLineChartData(cumulativeCasesLineChartData);
setNewCasesLineChartData(newCasesLineChartData);
}, [confirmedCasesGroupedByDate, confirmedCasesHeaderData])
}, [confirmedCasesGroupedByDate, confirmedCasesHeaderData, testingCasesTimeseries])

let graphPadding = isConsideredMobile() ? { paddingLeft: '10px', paddingRight: '10px', paddingTop: '25px', paddingBottom: '25px' } : { paddingLeft: '50px', paddingRight: '50px', paddingTop: '25px', paddingBottom: '25px' }
return (
<Fragment>
<h1 class="white-monospace center-text" style={{paddingTop: '25px'}}>Charts</h1>
<h1 className="white-monospace center-text" style={{paddingTop: '25px'}}>Charts</h1>
<div style={{...graphPadding}}>
{cumulativeCasesLineChartData &&
<OurChartContainerVX enableCurveStepAfter={false} chartTitle={"Cumulative Cases"} chartSubtitle={"South Africa"} chartData={cumulativeCasesLineChartData} chartValueLabel={"Cases"} />
<OurChartContainerVX isUpGood={false} enableCurveStepAfter={false} chartTitle={"Cumulative Cases"} chartSubtitle={"South Africa"} chartData={cumulativeCasesLineChartData} chartValueLabel={"Cases"} />
}
</div>
<div style={{height: '600px'}}>
Expand All @@ -105,7 +106,7 @@ const OurChartCollection = ({confirmedCasesGroupedByDate = [], confirmedCasesHea
</div>
<div style={{...graphPadding, marginTop: '115px'}}>
{cumulativeCasesLineChartData &&
<OurChartContainerVX enableCurveStepAfter={false} chartTitle={"New Cases"} chartSubtitle={"South Africa"} chartData={newCasesLineChartData} chartValueLabel={"New"} />
<OurChartContainerVX isChangeNeutral={true} enableCurveStepAfter={false} chartTitle={"New Cases"} chartSubtitle={"South Africa"} chartData={newCasesLineChartData} chartValueLabel={"New"} />
}
</div>
<div style={{height: '600px'}}>
Expand All @@ -119,6 +120,11 @@ const OurChartCollection = ({confirmedCasesGroupedByDate = [], confirmedCasesHea
</ParentSize>
}
</div>
<div style={{...graphPadding, marginTop: '115px'}}>
{testingCasesTimeseries &&
<OurChartContainerVX isUpGood={true} decimals={0} enableCurveStepAfter={false} chartTitle={"Cumulative Testing"} chartSubtitle={"South Africa"} chartData={testingCasesTimeseries} chartValueLabel={"Tests"} />
}
</div>
<div style={{height: '150px', position: 'relative'}}>
</div>
</Fragment>
Expand Down
5 changes: 5 additions & 0 deletions src/components/layout.css
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,11 @@ pre tt:after {
font-family: monospace!important;
}

.display-flex-space-between {
display: flex;
justify-content: space-between;
}

.flex-column {
display: flex;
flex-direction: column;
Expand Down
8 changes: 7 additions & 1 deletion src/components/seo.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import PropTypes from "prop-types"
import Helmet from "react-helmet"
import { useStaticQuery, graphql } from "gatsby"

function SEO({ description, lang, meta, title }) {
function SEO({ description, lang, meta, title, image }) {
const { site } = useStaticQuery(
graphql`
query {
Expand All @@ -12,6 +12,7 @@ function SEO({ description, lang, meta, title }) {
title
description
author
image
}
}
}
Expand Down Expand Up @@ -44,6 +45,10 @@ function SEO({ description, lang, meta, title }) {
property: `og:type`,
content: `website`,
},
{
property: `og:image`,
content: site.siteMetadata.image
},
{
name: `twitter:card`,
content: `summary`,
Expand Down Expand Up @@ -74,6 +79,7 @@ SEO.defaultProps = {
SEO.propTypes = {
description: PropTypes.string,
lang: PropTypes.string,
image: PropTypes.string,
meta: PropTypes.arrayOf(PropTypes.object),
title: PropTypes.string.isRequired,
}
Expand Down
29 changes: 17 additions & 12 deletions src/components/vx/OurChartContainerVX.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,23 @@ const styles = theme => ({
flexDirection: 'column',
alignItems: 'flex-end'
},
vxValueIncrease: {
color: 'red'
},
vxValueDecrease: {
vxValueGoodChange: {
color: 'limegreen'
},
vxValueBadChange: {
color: 'red'
}
});

class OurChartContainerVX extends React.Component {

constructor(props) {
super(props);
this.state = {
hasIncreased: true,
}
}
render() {
const { classes, margin, primaryValueSubtitle = false, chartTitle, chartSubtitle, isConsideredMobile, chartData, parentWidth, parentHeight, isChartLoading, chartValueLabel, enableCurveStepAfter = false } = this.props;
const { classes, margin, isChangeNeutral = false, primaryValueSubtitle = false, chartTitle, chartSubtitle, isConsideredMobile, chartData, parentWidth, parentHeight, isChartLoading, chartValueLabel, enableCurveStepAfter = false, decimals = 2, isUpGood = false } = this.props;
let currentValue = 0;
let diffValue = 0;
let hasIncreased = true;
Expand All @@ -103,8 +108,8 @@ class OurChartContainerVX extends React.Component {
yAxisValue: chartData[key].yAxisValue
};
})
let previousLatestValue = values[values.length - 2].yAxisValue;
currentValue = values[values.length - 1].yAxisValue;
let previousLatestValue = values[values.length - 2].yAxisValue * 1;
currentValue = values[values.length - 1].yAxisValue * 1;
percentDiff = ((currentValue * 100) / previousLatestValue) - 100;
diffValue = currentValue - previousLatestValue;
hasIncreased = diffValue >= 0;
Expand All @@ -130,21 +135,21 @@ class OurChartContainerVX extends React.Component {
<div className={classes.rightTitles}>
<div>
<Typography className={classes.vxChartTitle + " monospace no-padding-bottom"} variant="h5" component="h2">
{valueFormatDisplay(currentValue, 2, chartValueLabel)}
{valueFormatDisplay(currentValue, decimals, chartValueLabel)}
</Typography>
</div>
<div>
{!primaryValueSubtitle &&
<Typography className={classes.vxChartSubtitle + " monospace no-padding-top " + (hasIncreased ? classes.vxValueIncrease : classes.vxValueDecrease)} component="p">
{hasIncreased ? ("+ " + valueFormatDisplay(percentDiff, 2, "%")) : ("- " + valueFormatDisplay(percentDiff * -1, 2, "%"))}
<Typography className={classes.vxChartSubtitle + " monospace no-padding-top " + (!isChangeNeutral && (hasIncreased && isUpGood || (!hasIncreased && !isUpGood) ? classes.vxValueGoodChange : classes.vxValueBadChange))} component="p">
{hasIncreased ? ("+ " + valueFormatDisplay(percentDiff, decimals, "%")) : ("- " + valueFormatDisplay(percentDiff * -1, decimals, "%"))}
</Typography>
}
{primaryValueSubtitle}
</div>
</div>
</div>
<div className={classes.innerContainer}>
<OurChartVX enableCurveStepAfter={enableCurveStepAfter} isConsideredMobile={isConsideredMobile} chartValueLabel={chartValueLabel} margin={useMargin} data={values} />
<OurChartVX decimals={decimals} enableCurveStepAfter={enableCurveStepAfter} isConsideredMobile={isConsideredMobile} chartValueLabel={chartValueLabel} margin={useMargin} data={values} />
</div>
</div>
</div>
Expand Down
10 changes: 5 additions & 5 deletions src/components/vx/OurChartVX.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@ class OurChartVX extends React.Component {
}

render() {
const { data, parentWidth, parentHeight, margin, tooltipLeft, tooltipTop, tooltipData, hideTooltip, isConsideredMobile, chartValueLabel, enableCurveStepAfter} = this.props;
const { data, decimals = 2, parentWidth, parentHeight, margin, tooltipLeft, tooltipTop, tooltipData, hideTooltip, isConsideredMobile, chartValueLabel, enableCurveStepAfter} = this.props;
const {shiftTooltipLeft, shiftTooltipRight} = this.state;

const width = parentWidth - margin.left - margin.right;
const height = parentHeight - margin.top - margin.bottom;
const tooltipAnimation = 'all .25s cubic-bezier(.42,.2,.5,1)';
const tooltipAnimation = 'all .25s ease-out';

let tooltipValueTranslate = 'translateX(0%)';
let tooltipDateTranslate = 'translateX(-50%)';
Expand Down Expand Up @@ -182,7 +182,7 @@ class OurChartVX extends React.Component {
stroke={"#424242"}
/>
<text className={"monospace"} y={yScale(maxValue)} fill="white" dy="1.3em" dx="1em" fontSize="14">
{valueFormatDisplay(maxValue , 2, chartValueLabel)}
{valueFormatDisplay(maxValue , decimals, chartValueLabel)}
</text>
</g>
<g>
Expand All @@ -194,7 +194,7 @@ class OurChartVX extends React.Component {
stroke={"#424242"}
/>
<text className={"monospace"} y={yScale(minValue)} dy="-.5em" fill="white" dx="1em" fontSize="14">
{valueFormatDisplay(minValue, 2, chartValueLabel)}
{valueFormatDisplay(minValue, decimals, chartValueLabel)}
</text>
</g>
<Bar
Expand Down Expand Up @@ -260,7 +260,7 @@ class OurChartVX extends React.Component {
{tooltipData &&
<div>
<Tooltip top={setTooltipLabelTop} left={tooltipLeft + 12} style={{backgroundColor: '#272727', color: '#FFFFFF', pointerEvents: 'none', transform: tooltipValueTranslate, transition: tooltipAnimation, whiteSpace: 'pre', boxShadow: '0px 5px 5px -3px rgba(0,0,0,0.2), 0px 8px 10px 1px rgba(0,0,0,0.14), 0px 3px 14px 2px rgba(0,0,0,0.12)'}}>
<b className={"monospace"}>{valueFormatDisplay(y(tooltipData), 2, chartValueLabel)}</b>
<b className={"monospace"}>{valueFormatDisplay(y(tooltipData), decimals, chartValueLabel)}</b>
</Tooltip>
<Tooltip top={yScale(minValue)} left={tooltipLeft} style={{backgroundColor: '#272727', color: '#FFFFFF', transform: tooltipDateTranslate, pointerEvents: 'none', display: 'table', transition: tooltipAnimation, whiteSpace: 'pre', boxShadow: '0px 5px 5px -3px rgba(0,0,0,0.2), 0px 8px 10px 1px rgba(0,0,0,0.14), 0px 3px 14px 2px rgba(0,0,0,0.12)'}}>
<b className={"monospace"}>{formatDateTimeTooltip(xData(tooltipData))}</b>
Expand Down
37 changes: 29 additions & 8 deletions src/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import BubbleChartIcon from '@material-ui/icons/BubbleChart';
import BorderChartIcon from '@material-ui/icons/GridOn';
import ChartsIcon from '@material-ui/icons/Timeline';
import MapIcon from '@material-ui/icons/Map';
import moment from 'moment';

import Layout from "../components/layout";
import SEO from "../components/seo";
Expand Down Expand Up @@ -44,6 +45,7 @@ const IndexPage = () => {
let [nextDataType, setNextDataType] = useState(false);
let [confirmedCasesHeaderData, setConfirmedCasesHeaderData] = useState(false);
let [hospitalData, setHospitalData] = useState(false);
let [testingCasesTimeseries, setTestingCasesTimeseries] = useState(false);

let mobile = isConsideredMobile();

Expand Down Expand Up @@ -91,21 +93,36 @@ const IndexPage = () => {
useEffect(() => {
axios.all([
axios.get(`https://raw.githubusercontent.com/dsfsi/covid19za/master/data/covid19za_timeline_confirmed.csv`),
// axios.get(`https://raw.githubusercontent.com/dsfsi/covid19za/master/data/covid19za_timeline_testing.csv`),
axios.get(`https://raw.githubusercontent.com/dsfsi/covid19za/master/data/covid19za_timeline_testing.csv`),
// axios.get(`https://raw.githubusercontent.com/dsfsi/covid19za/master/data/health_system_za_public_hospitals.csv`)
]).then(res => {
let { data: confirmedCasesData } = res[0];
// let { data: testingData } = res[1];
let { data: testingData } = res[1];
// let { data: hospitalLocationData } = res[2];


let testingCasesInstance = Papa.parse(testingData);
let parsedTestingCasesData = testingCasesInstance.data;

let testingCasesIndexOfDate = parsedTestingCasesData[0].indexOf("YYYYMMDD");
let testingCasesIndexOfCumulativeCount = parsedTestingCasesData[0].indexOf("cumulative_tests");
let useTestingCasesTimeseries = [];
for (let i = 1; i < parsedTestingCasesData.length; i++) {
if (
parsedTestingCasesData[i][testingCasesIndexOfDate] &&
parsedTestingCasesData[i][testingCasesIndexOfCumulativeCount]
) {
let date = parsedTestingCasesData[i][testingCasesIndexOfDate];
let cumulation = parsedTestingCasesData[i][testingCasesIndexOfCumulativeCount];
useTestingCasesTimeseries.push({xAxisValue: moment(date), yAxisValue: cumulation})
}
}

let parsedConfirmedCasesInstance = Papa.parse(confirmedCasesData);
let parsedConfirmedCasesData = parsedConfirmedCasesInstance.data;
// let parsedHospitalLocationInstance = Papa.parse(hospitalLocationData);
// let parsedHospitalLocationData = parsedHospitalLocationInstance.data;

let confirmedCasesHeaderRow = parsedConfirmedCasesData[0];
let confirmedCasesIndexOfProvince = parsedConfirmedCasesData[0].indexOf("province");
let confirmedCasesIndexOfDate = parsedConfirmedCasesData[0].indexOf("YYYYMMDD");
let confirmedCasesIndexOfProvince = confirmedCasesHeaderRow.indexOf("province");
let confirmedCasesIndexOfDate = confirmedCasesHeaderRow.indexOf("YYYYMMDD");
let confirmedCasesGroupedByProvince = {};
let confirmedCasesGroupedByDate = {};
// let confirmedCasesGroupedByAge = {};
Expand All @@ -132,6 +149,9 @@ const IndexPage = () => {
}
}

// let parsedHospitalLocationInstance = Papa.parse(hospitalLocationData);
// let parsedHospitalLocationData = parsedHospitalLocationInstance.data;

// let hospitalData = [];
// let hospitalDataIndexOfName = parsedHospitalLocationData[0].indexOf("Name");
// let hospitalDataIndexOfLongitude = parsedHospitalLocationData[0].indexOf("Long");
Expand All @@ -152,6 +172,7 @@ const IndexPage = () => {
setConfirmedCasesHeaderData(confirmedCasesHeaderRow);
setConfirmedCasesGroupedByProvince(confirmedCasesGroupedByProvince);
setConfirmedCasesGroupedByDate(confirmedCasesGroupedByDate);
setTestingCasesTimeseries(useTestingCasesTimeseries);
// setHospitalData(hospitalData);
setTotalCases(currentTotalCases);

Expand Down Expand Up @@ -206,7 +227,7 @@ const IndexPage = () => {
</a>
</SiteControlBottomLeftContainer>
}
{(confirmedCasesGroupedByDate && confirmedCasesHeaderData && dataType === "charts") && <OurChartCollection confirmedCasesHeaderData={confirmedCasesHeaderData} confirmedCasesGroupedByDate={confirmedCasesGroupedByDate}/>}
{(confirmedCasesGroupedByDate && confirmedCasesHeaderData && dataType === "charts") && <OurChartCollection testingCasesTimeseries={testingCasesTimeseries} confirmedCasesHeaderData={confirmedCasesHeaderData} confirmedCasesGroupedByDate={confirmedCasesGroupedByDate}/>}
{(confirmedCasesGroupedByProvince && dataType === "map") && <OurMap mapType={mapType} prefersLightMode={prefersLightMode} hospitalData={hospitalData} confirmedCasesGroupedByProvince={confirmedCasesGroupedByProvince}/>}
</Layout>
)
Expand Down
Binary file added static/images/site-preview.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 56a9cab

Please sign in to comment.