Skip to content

Commit

Permalink
feat: Set up ComboLineDual chart
Browse files Browse the repository at this point in the history
  • Loading branch information
bprusinowski committed Sep 29, 2023
1 parent 0aac329 commit f299ac2
Show file tree
Hide file tree
Showing 10 changed files with 304 additions and 154 deletions.
15 changes: 11 additions & 4 deletions app/charts/combo/chart-combo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { memo } from "react";

import { ChartLoadingWrapper } from "@/charts/chart-loading-wrapper";
import { ComboLineColumnChart } from "@/charts/combo/combo-line-column-state";
import { ComboLineChart } from "@/charts/combo/combo-line-state";
import { ComboLineDualChart } from "@/charts/combo/combo-line-dual-state";
import { ComboLineSingleChart } from "@/charts/combo/combo-line-single-state";
import { extractComponentIris } from "@/charts/shared/chart-helpers";
import { ComboConfig, DataSource, QueryFilters } from "@/config-types";
import {
Expand Down Expand Up @@ -70,9 +71,15 @@ export const ChartCombo = memo((props: ChartProps<ComboConfig>) => {
const { chartConfig } = props;

return chartConfig.chartSubtype === "line" ? (
<ComboLineChart aspectRatio={0.4} {...props}>
<Box>ComboLineChart</Box>
</ComboLineChart>
chartConfig.fields.y.axisMode === "single" ? (
<ComboLineSingleChart aspectRatio={0.4} {...props}>
<Box>ComboLineSingleChart</Box>
</ComboLineSingleChart>
) : (
<ComboLineDualChart aspectRatio={0.4} {...props}>
<Box>ComboLineDualChart</Box>
</ComboLineDualChart>
)
) : (
<ComboLineColumnChart aspectRatio={0.4} {...props}>
<Box>ComboLineColumnChart</Box>
Expand Down
97 changes: 97 additions & 0 deletions app/charts/combo/combo-line-dual-state-props.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React from "react";

import { BaseYGetter, sortData } from "@/charts/combo/combo-state-props";
import { getLabelWithUnit } from "@/charts/shared/chart-helpers";
import {
BaseVariables,
ChartStateData,
TemporalXVariables,
useBaseVariables,
useChartData,
useTemporalXVariables,
} from "@/charts/shared/chart-state";
import { ComboConfig } from "@/configurator";

import { ChartProps } from "../shared/ChartProps";

type NumericalYComboLineDualVariables = {
y: {
lineLeft: BaseYGetter;
lineRight: BaseYGetter;
};
};

export type ComboLineDualStateVariables = BaseVariables &
TemporalXVariables &
NumericalYComboLineDualVariables;

export const useComboLineDualStateVariables = (
props: ChartProps<ComboConfig> & { aspectRatio: number }
): ComboLineDualStateVariables => {
const { chartConfig, dimensionsByIri, measuresByIri } = props;
const { fields } = chartConfig;
const { x } = fields;

const baseVariables = useBaseVariables(chartConfig);
const temporalXVariables = useTemporalXVariables(x, {
dimensionsByIri,
});

if (chartConfig.chartSubtype !== "line") {
throw new Error("This hook is only for line charts!");
}

if (chartConfig.fields.y.axisMode !== "dual") {
throw new Error("This hook is only for dual axis line charts!");
}

const leftIri = chartConfig.fields.y.leftAxisComponentIri;
const rightIri = chartConfig.fields.y.rightAxisComponentIri;
const numericalYVariables: NumericalYComboLineDualVariables = {
y: {
lineLeft: {
iri: leftIri,
label: getLabelWithUnit(measuresByIri[leftIri]),
getY: (d) => {
return d[leftIri] !== null ? Number(d[leftIri]) : null;
},
},
lineRight: {
iri: rightIri,
label: getLabelWithUnit(measuresByIri[rightIri]),
getY: (d) => {
return d[rightIri] !== null ? Number(d[rightIri]) : null;
},
},
},
};

return {
...baseVariables,
...temporalXVariables,
...numericalYVariables,
};
};

export const useComboLineDualStateData = (
chartProps: ChartProps<ComboConfig> & { aspectRatio: number },
variables: ComboLineDualStateVariables
): ChartStateData => {
const { chartConfig, observations } = chartProps;
// FIXME: handle properly.
const plottableData = observations;
const sortedPlottableData = React.useMemo(() => {
return sortData(plottableData, {
getX: variables.getX,
});
}, [plottableData, variables.getX]);
const data = useChartData(sortedPlottableData, {
chartConfig,
getXAsDate: variables.getX,
});

return {
...data,
allData: sortedPlottableData,
};
};
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { ScaleLinear, ScaleOrdinal, ScaleTime } from "d3";

import {
ComboLineStateVariables,
useComboLineStateData,
useComboLineStateVariables,
} from "@/charts/combo/combo-line-state-props";
ComboLineDualStateVariables,
useComboLineDualStateData,
useComboLineDualStateVariables,
} from "@/charts/combo/combo-line-dual-state-props";
import {
ChartContext,
ChartStateData,
Expand All @@ -19,8 +19,8 @@ import { Observation } from "@/domain/data";

import { ChartProps } from "../shared/ChartProps";

export type ComboLineState = CommonChartState &
ComboLineStateVariables &
export type ComboLineDualState = CommonChartState &
ComboLineDualStateVariables &
InteractiveXTimeRangeState & {
chartType: "combo";
xKey: string;
Expand All @@ -31,38 +31,38 @@ export type ComboLineState = CommonChartState &
getAnnotationInfo: (d: Observation) => TooltipInfo;
};

const useComboLineState = (
const useComboLineDualState = (
chartProps: ChartProps<ComboConfig> & { aspectRatio: number },
variables: ComboLineStateVariables,
variables: ComboLineDualStateVariables,
data: ChartStateData
): ComboLineState => {
return {} as unknown as ComboLineState;
): ComboLineDualState => {
return {} as unknown as ComboLineDualState;
};

const ComboLineChartProvider = (
const ComboLineDualChartProvider = (
props: React.PropsWithChildren<
ChartProps<ComboConfig> & { aspectRatio: number }
>
) => {
const { children, ...chartProps } = props;
const variables = useComboLineStateVariables(chartProps);
const data = useComboLineStateData(chartProps, variables);
const state = useComboLineState(chartProps, variables, data);
const variables = useComboLineDualStateVariables(chartProps);
const data = useComboLineDualStateData(chartProps, variables);
const state = useComboLineDualState(chartProps, variables, data);

return (
<ChartContext.Provider value={state}>{children}</ChartContext.Provider>
);
};

export const ComboLineChart = (
export const ComboLineDualChart = (
props: React.PropsWithChildren<
ChartProps<ComboConfig> & { aspectRatio: number }
>
) => {
return (
<Observer>
<InteractionProvider>
<ComboLineChartProvider {...props} />
<ComboLineDualChartProvider {...props} />
</InteractionProvider>
</Observer>
);
Expand Down
9 changes: 9 additions & 0 deletions app/charts/combo/combo-line-dual.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ComboLineDualState } from "@/charts/combo/combo-line-dual-state";
import { useChartState } from "@/charts/shared/chart-state";

export const ComboLineDual = () => {
const state = useChartState() as ComboLineDualState;
console.log(state);

return null;
};
87 changes: 87 additions & 0 deletions app/charts/combo/combo-line-single-state-props.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import React from "react";

import { BaseYGetter, sortData } from "@/charts/combo/combo-state-props";
import { getLabelWithUnit } from "@/charts/shared/chart-helpers";
import {
BaseVariables,
ChartStateData,
TemporalXVariables,
useBaseVariables,
useChartData,
useTemporalXVariables,
} from "@/charts/shared/chart-state";
import { ComboConfig } from "@/configurator";

import { ChartProps } from "../shared/ChartProps";

type NumericalYComboLineSingleVariables = {
y: {
lines: BaseYGetter[];
};
};

export type ComboLineSingleStateVariables = BaseVariables &
TemporalXVariables &
NumericalYComboLineSingleVariables;

export const useComboLineSingleStateVariables = (
props: ChartProps<ComboConfig> & { aspectRatio: number }
): ComboLineSingleStateVariables => {
const { chartConfig, dimensionsByIri, measuresByIri } = props;
const { fields } = chartConfig;
const { x } = fields;

const baseVariables = useBaseVariables(chartConfig);
const temporalXVariables = useTemporalXVariables(x, {
dimensionsByIri,
});

if (chartConfig.chartSubtype !== "line") {
throw new Error("This hook is only for line charts!");
}

if (chartConfig.fields.y.axisMode !== "single") {
throw new Error("This hook is only for single axis line charts!");
}

const numericalYVariables: NumericalYComboLineSingleVariables = {
y: {
lines: chartConfig.fields.y.componentIris.map((iri) => ({
iri,
label: getLabelWithUnit(measuresByIri[iri]),
getY: (d) => {
return d[iri] !== null ? Number(d[iri]) : null;
},
})),
},
};

return {
...baseVariables,
...temporalXVariables,
...numericalYVariables,
};
};

export const useComboLineSingleStateData = (
chartProps: ChartProps<ComboConfig> & { aspectRatio: number },
variables: ComboLineSingleStateVariables
): ChartStateData => {
const { chartConfig, observations } = chartProps;
// FIXME: handle properly.
const plottableData = observations;
const sortedPlottableData = React.useMemo(() => {
return sortData(plottableData, {
getX: variables.getX,
});
}, [plottableData, variables.getX]);
const data = useChartData(sortedPlottableData, {
chartConfig,
getXAsDate: variables.getX,
});

return {
...data,
allData: sortedPlottableData,
};
};
69 changes: 69 additions & 0 deletions app/charts/combo/combo-line-single-state.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { ScaleLinear, ScaleOrdinal, ScaleTime } from "d3";

import {
ComboLineSingleStateVariables,
useComboLineSingleStateData,
useComboLineSingleStateVariables,
} from "@/charts/combo/combo-line-single-state-props";
import {
ChartContext,
ChartStateData,
CommonChartState,
InteractiveXTimeRangeState,
} from "@/charts/shared/chart-state";
import { TooltipInfo } from "@/charts/shared/interaction/tooltip";
import { InteractionProvider } from "@/charts/shared/use-interaction";
import { Observer } from "@/charts/shared/use-width";
import { ComboConfig } from "@/configurator";
import { Observation } from "@/domain/data";

import { ChartProps } from "../shared/ChartProps";

export type ComboLineSingleState = CommonChartState &
ComboLineSingleStateVariables &
InteractiveXTimeRangeState & {
chartType: "combo";
xKey: string;
xScale: ScaleTime<number, number>;
yScale: ScaleLinear<number, number>;
colors: ScaleOrdinal<string, string>;
chartWideData: ArrayLike<Observation>;
getAnnotationInfo: (d: Observation) => TooltipInfo;
};

const useComboLineSingleState = (
chartProps: ChartProps<ComboConfig> & { aspectRatio: number },
variables: ComboLineSingleStateVariables,
data: ChartStateData
): ComboLineSingleState => {
return {} as unknown as ComboLineSingleState;
};

const ComboLineSingleChartProvider = (
props: React.PropsWithChildren<
ChartProps<ComboConfig> & { aspectRatio: number }
>
) => {
const { children, ...chartProps } = props;
const variables = useComboLineSingleStateVariables(chartProps);
const data = useComboLineSingleStateData(chartProps, variables);
const state = useComboLineSingleState(chartProps, variables, data);

return (
<ChartContext.Provider value={state}>{children}</ChartContext.Provider>
);
};

export const ComboLineSingleChart = (
props: React.PropsWithChildren<
ChartProps<ComboConfig> & { aspectRatio: number }
>
) => {
return (
<Observer>
<InteractionProvider>
<ComboLineSingleChartProvider {...props} />
</InteractionProvider>
</Observer>
);
};
9 changes: 9 additions & 0 deletions app/charts/combo/combo-line-single.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ComboLineSingleState } from "@/charts/combo/combo-line-single-state";
import { useChartState } from "@/charts/shared/chart-state";

export const ComboLineSingle = () => {
const state = useChartState() as ComboLineSingleState;
console.log(state);

return null;
};
Loading

0 comments on commit f299ac2

Please sign in to comment.