From e155781fcb35a9dd4a75c1dc2ff48bcc85bc12f3 Mon Sep 17 00:00:00 2001 From: Vyacheslav Matyukhin Date: Thu, 5 May 2022 01:02:55 +0400 Subject: [PATCH] feat: scale and domain in charts, fixes a few bugs --- src/web/questions/components/HistoryChart.tsx | 51 +++++++++++++------ 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/src/web/questions/components/HistoryChart.tsx b/src/web/questions/components/HistoryChart.tsx index bde92e9..b7af116 100644 --- a/src/web/questions/components/HistoryChart.tsx +++ b/src/web/questions/components/HistoryChart.tsx @@ -1,4 +1,6 @@ -import { format } from "date-fns"; +import { + addDays, differenceInDays, format, startOfDay, startOfToday, startOfTomorrow +} from "date-fns"; import React from "react"; import { VictoryAxis, VictoryChart, VictoryGroup, VictoryLabel, VictoryLegend, VictoryLine, @@ -35,12 +37,13 @@ type DataSet = { date: Date; probability: number; name: string }[]; const dataAsXy = (data: DataSet) => data.map((datum) => ({ - x: format(datum.date, "yyyy-MM-dd"), + x: datum.date, y: datum.probability, name: datum.name, })); const colors = ["dodgerblue", "crimson", "seagreen", "darkviolet", "turquoise"]; + // can't be replaced with React component, VictoryChart requires VictoryGroup elements to be immediate children const getVictoryGroup = ({ data, i }: { data: DataSet; i: number }) => { return ( @@ -67,14 +70,19 @@ export const HistoryChart: React.FC = ({ question }) => { if (isBinary) { dataSetsNames = ["Yes"]; } + let dataSets: DataSet[] = []; let maxProbability = 0; let longestNameLength = 0; + const sortedHistory = question.history.sort((a, b) => + a.timestamp < b.timestamp ? -1 : 1 + ); + for (const name of dataSetsNames) { let newDataset: DataSet = []; let previousDate = -Infinity; - for (let item of question.history) { + for (let item of sortedHistory) { const relevantItemsArray = item.options.filter((x) => x.name === name); const date = new Date(item.timestamp * 1000); if ( @@ -122,6 +130,18 @@ export const HistoryChart: React.FC = ({ question }) => { symbol: { fill: colors[i] }, })); + const minDate = sortedHistory.length + ? startOfDay(new Date(sortedHistory[0].timestamp * 1000)) + : startOfToday(); + const maxDate = sortedHistory.length + ? addDays( + startOfDay( + new Date(sortedHistory[sortedHistory.length - 1].timestamp * 1000) + ), + 1 + ) + : startOfTomorrow(); + return ( = ({ question }) => { width={width} containerComponent={ `Not shown`} + labels={() => "Not shown"} labelComponent={ = ({ question }) => { /> } voronoiBlacklist={ - ["line-0", "line-1", "line-2", "line-3", "line-4"] - //Array.from(Array(5).keys()).map((x, i) => `line${i}`) + [...Array(5).keys()].map((i) => `line-${i}`) // see: https://github.com/FormidableLabs/victory/issues/545 } /> } + scale={{ + x: "time", + y: "linear", + }} domain={{ + x: [minDate, maxDate], y: [0, domainMax], }} > @@ -177,17 +201,10 @@ export const HistoryChart: React.FC = ({ question }) => { .slice(0, 5) .map((dataset, i) => getVictoryGroup({ data: dataset, i }))} datum.x)} - // tickFormat={dataAsXy.map((datum) => datum.x)} - tickCount={7} + tickCount={Math.min(7, differenceInDays(maxDate, minDate) + 1)} style={{ grid: { stroke: null, strokeWidth: 0.5 }, }} - //axisLabelComponent={ - // - //} tickLabelComponent={ = ({ question }) => { style={{ fontSize: 15, fill: "gray" }} /> } + scale={{ x: "time" }} + tickFormat={(t) => format(t, "yyyy-MM-dd")} /> `${x * 100}%`} style={{ grid: { stroke: "#D3D3D3", strokeWidth: 0.5 }, }} tickLabelComponent={ } + // tickFormat specifies how ticks should be displayed + tickFormat={(x) => `${x * 100}%`} /> );