feat: scale and domain in charts, fixes a few bugs

This commit is contained in:
Vyacheslav Matyukhin 2022-05-05 01:02:55 +04:00
parent 9973c25054
commit e155781fcb
No known key found for this signature in database
GPG Key ID: 3D2A774C5489F96C

View File

@ -1,4 +1,6 @@
import { format } from "date-fns"; import {
addDays, differenceInDays, format, startOfDay, startOfToday, startOfTomorrow
} from "date-fns";
import React from "react"; import React from "react";
import { import {
VictoryAxis, VictoryChart, VictoryGroup, VictoryLabel, VictoryLegend, VictoryLine, VictoryAxis, VictoryChart, VictoryGroup, VictoryLabel, VictoryLegend, VictoryLine,
@ -35,12 +37,13 @@ type DataSet = { date: Date; probability: number; name: string }[];
const dataAsXy = (data: DataSet) => const dataAsXy = (data: DataSet) =>
data.map((datum) => ({ data.map((datum) => ({
x: format(datum.date, "yyyy-MM-dd"), x: datum.date,
y: datum.probability, y: datum.probability,
name: datum.name, name: datum.name,
})); }));
const colors = ["dodgerblue", "crimson", "seagreen", "darkviolet", "turquoise"]; const colors = ["dodgerblue", "crimson", "seagreen", "darkviolet", "turquoise"];
// can't be replaced with React component, VictoryChart requires VictoryGroup elements to be immediate children // can't be replaced with React component, VictoryChart requires VictoryGroup elements to be immediate children
const getVictoryGroup = ({ data, i }: { data: DataSet; i: number }) => { const getVictoryGroup = ({ data, i }: { data: DataSet; i: number }) => {
return ( return (
@ -67,14 +70,19 @@ export const HistoryChart: React.FC<Props> = ({ question }) => {
if (isBinary) { if (isBinary) {
dataSetsNames = ["Yes"]; dataSetsNames = ["Yes"];
} }
let dataSets: DataSet[] = []; let dataSets: DataSet[] = [];
let maxProbability = 0; let maxProbability = 0;
let longestNameLength = 0; let longestNameLength = 0;
const sortedHistory = question.history.sort((a, b) =>
a.timestamp < b.timestamp ? -1 : 1
);
for (const name of dataSetsNames) { for (const name of dataSetsNames) {
let newDataset: DataSet = []; let newDataset: DataSet = [];
let previousDate = -Infinity; let previousDate = -Infinity;
for (let item of question.history) { for (let item of sortedHistory) {
const relevantItemsArray = item.options.filter((x) => x.name === name); const relevantItemsArray = item.options.filter((x) => x.name === name);
const date = new Date(item.timestamp * 1000); const date = new Date(item.timestamp * 1000);
if ( if (
@ -122,6 +130,18 @@ export const HistoryChart: React.FC<Props> = ({ question }) => {
symbol: { fill: colors[i] }, 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 ( return (
<VictoryChart <VictoryChart
domainPadding={20} domainPadding={20}
@ -131,7 +151,7 @@ export const HistoryChart: React.FC<Props> = ({ question }) => {
width={width} width={width}
containerComponent={ containerComponent={
<VictoryVoronoiContainer <VictoryVoronoiContainer
labels={({ datum }) => `Not shown`} labels={() => "Not shown"}
labelComponent={ labelComponent={
<VictoryTooltip <VictoryTooltip
constrainToVisibleArea constrainToVisibleArea
@ -154,13 +174,17 @@ export const HistoryChart: React.FC<Props> = ({ question }) => {
/> />
} }
voronoiBlacklist={ voronoiBlacklist={
["line-0", "line-1", "line-2", "line-3", "line-4"] [...Array(5).keys()].map((i) => `line-${i}`)
//Array.from(Array(5).keys()).map((x, i) => `line${i}`)
// see: https://github.com/FormidableLabs/victory/issues/545 // see: https://github.com/FormidableLabs/victory/issues/545
} }
/> />
} }
scale={{
x: "time",
y: "linear",
}}
domain={{ domain={{
x: [minDate, maxDate],
y: [0, domainMax], y: [0, domainMax],
}} }}
> >
@ -177,17 +201,10 @@ export const HistoryChart: React.FC<Props> = ({ question }) => {
.slice(0, 5) .slice(0, 5)
.map((dataset, i) => getVictoryGroup({ data: dataset, i }))} .map((dataset, i) => getVictoryGroup({ data: dataset, i }))}
<VictoryAxis <VictoryAxis
// tickValues specifies both the number of ticks and where tickCount={Math.min(7, differenceInDays(maxDate, minDate) + 1)}
// they are placed on the axis
// tickValues={dataAsXy.map((datum) => datum.x)}
// tickFormat={dataAsXy.map((datum) => datum.x)}
tickCount={7}
style={{ style={{
grid: { stroke: null, strokeWidth: 0.5 }, grid: { stroke: null, strokeWidth: 0.5 },
}} }}
//axisLabelComponent={
// <VictoryLabel dy={40} style={{ fontSize: 10, fill: "gray" }} />
//}
tickLabelComponent={ tickLabelComponent={
<VictoryLabel <VictoryLabel
dy={10} dy={10}
@ -195,17 +212,19 @@ export const HistoryChart: React.FC<Props> = ({ question }) => {
style={{ fontSize: 15, fill: "gray" }} style={{ fontSize: 15, fill: "gray" }}
/> />
} }
scale={{ x: "time" }}
tickFormat={(t) => format(t, "yyyy-MM-dd")}
/> />
<VictoryAxis <VictoryAxis
dependentAxis dependentAxis
// tickFormat specifies how ticks should be displayed
tickFormat={(x) => `${x * 100}%`}
style={{ style={{
grid: { stroke: "#D3D3D3", strokeWidth: 0.5 }, grid: { stroke: "#D3D3D3", strokeWidth: 0.5 },
}} }}
tickLabelComponent={ tickLabelComponent={
<VictoryLabel dy={0} style={{ fontSize: 15, fill: "gray" }} /> <VictoryLabel dy={0} style={{ fontSize: 15, fill: "gray" }} />
} }
// tickFormat specifies how ticks should be displayed
tickFormat={(x) => `${x * 100}%`}
/> />
</VictoryChart> </VictoryChart>
); );