Skip to content

Commit

Permalink
Merge pull request #1920 from visualize-admin/feat/bar-chart
Browse files Browse the repository at this point in the history
Bar chart
  • Loading branch information
squiles authored Dec 12, 2024
2 parents 617e7d5 + e7e620a commit 5c4a4c9
Show file tree
Hide file tree
Showing 54 changed files with 3,596 additions and 190 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ playwright-report

app/public/storybook

certificates
certificates
.vercel
2 changes: 1 addition & 1 deletion app/charts/area/areas-state-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export const useAreasStateData = (
const data = useChartData(sortedPlottableData, {
chartConfig,
timeRangeDimensionId: xDimension.id,
getXAsDate: getX,
getAxisValueAsDate: getX,
getSegmentAbbreviationOrLabel,
getTimeRangeDate,
});
Expand Down
16 changes: 8 additions & 8 deletions app/charts/area/areas-state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,8 @@ const useAreasState = (
if (normalize) {
return group(
normalizeData(chartData, {
yKey: yMeasure.id,
getY,
key: yMeasure.id,
getAxisValue: getY,
getTotalGroupValue: (d) => {
return sumsByX[getXAsString(d)];
},
Expand All @@ -205,9 +205,9 @@ const useAreasState = (

const chartWideData = useMemo(() => {
return getWideData({
dataGroupedByX: chartDataGroupedByX,
xKey,
getY,
dataGrouped: chartDataGroupedByX,
key: xKey,
getAxisValue: getY,
getSegment,
allSegments: segments,
imputationType: fields.y.imputationType,
Expand Down Expand Up @@ -372,8 +372,8 @@ const useAreasState = (
});
const yValueFormatter = getStackedTooltipValueFormatter({
normalize,
yMeasureId: yMeasure.id,
yMeasureUnit: yMeasure.unit,
measureId: yMeasure.id,
measureUnit: yMeasure.unit,
formatters,
formatNumber,
});
Expand All @@ -394,7 +394,7 @@ const useAreasState = (
xAnchor,
yAnchor,
placement,
xValue: timeFormatUnit(getX(datum), xDimension.timeUnit),
value: timeFormatUnit(getX(datum), xDimension.timeUnit),
datum: {
label: fields.segment && getSegmentAbbreviationOrLabel(datum),
value: yValueFormatter(getY(datum), getIdentityY(datum)),
Expand Down
157 changes: 157 additions & 0 deletions app/charts/bar/bars-grouped-state-props.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import { ascending, rollup, sum } from "d3-array";
import orderBy from "lodash/orderBy";
import { useCallback, useMemo } from "react";

import { usePlottableData } from "@/charts/shared/chart-helpers";
import {
BandYVariables,
BaseVariables,
ChartStateData,
InteractiveFiltersVariables,
NumericalXErrorVariables,
NumericalXVariables,
RenderingVariables,
SegmentVariables,
SortingVariables,
useBandYVariables,
useBaseVariables,
useChartData,
useInteractiveFiltersVariables,
useNumericalXErrorVariables,
useNumericalXVariables,
useSegmentVariables,
} from "@/charts/shared/chart-state";
import { useRenderingKeyVariable } from "@/charts/shared/rendering-utils";
import { BarConfig, useChartConfigFilters } from "@/configurator";
import { Observation, isTemporalEntityDimension } from "@/domain/data";
import { sortByIndex } from "@/utils/array";

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

export type BarsGroupedStateVariables = BaseVariables &
SortingVariables &
BandYVariables &
NumericalXVariables &
NumericalXErrorVariables &
SegmentVariables &
RenderingVariables &
InteractiveFiltersVariables;

export const useBarsGroupedStateVariables = (
props: ChartProps<BarConfig>
): BarsGroupedStateVariables => {
const {
chartConfig,
observations,
dimensions,
dimensionsById,
measures,
measuresById,
} = props;
const { fields, interactiveFiltersConfig } = chartConfig;
const { x, y, segment, animation } = fields;
const yDimension = dimensionsById[y.componentId];
const filters = useChartConfigFilters(chartConfig);

const baseVariables = useBaseVariables(chartConfig);
const numericalXVariables = useNumericalXVariables("bar", x, {
measuresById,
});
const bandYVariables = useBandYVariables(y, {
dimensionsById,
observations,
});
const numericalXErrorVariables = useNumericalXErrorVariables(x, {
getValue: numericalXVariables.getX,
dimensions,
measures,
});
const segmentVariables = useSegmentVariables(segment, {
dimensionsById,
observations,
});
const interactiveFiltersVariables = useInteractiveFiltersVariables(
interactiveFiltersConfig,
{ dimensionsById }
);

const { getY, getYAsDate } = bandYVariables;
const { getX } = numericalXVariables;
const sortData: BarsGroupedStateVariables["sortData"] = useCallback(
(data) => {
const { sortingOrder, sortingType } = y.sorting ?? {};
const yGetter = isTemporalEntityDimension(yDimension)
? (d: Observation) => getYAsDate(d).getTime().toString()
: getY;
const order = [
...rollup(
data,
(v) => sum(v, (d) => getX(d)),
(d) => yGetter(d)
),
]
.sort((a, b) => ascending(a[1], b[1]))
.map((d) => d[0]);

if (sortingType === "byDimensionLabel") {
return orderBy(data, yGetter, sortingOrder);
} else if (sortingType === "byMeasure") {
return sortByIndex({ data, order, getCategory: yGetter, sortingOrder });
} else {
return orderBy(data, yGetter, "asc");
}
},
[getX, getYAsDate, getY, y.sorting, yDimension]
);

const getRenderingKey = useRenderingKeyVariable(
dimensions,
filters,
interactiveFiltersConfig,
animation
);

return {
...baseVariables,
sortData,
...bandYVariables,
...numericalXVariables,
...numericalXErrorVariables,
...segmentVariables,
...interactiveFiltersVariables,
getRenderingKey,
};
};

export const useBarsGroupedStateData = (
chartProps: ChartProps<BarConfig>,
variables: BarsGroupedStateVariables
): ChartStateData => {
const { chartConfig, observations } = chartProps;
const {
sortData,
yDimension,
getYAsDate,
getX,
getSegmentAbbreviationOrLabel,
getTimeRangeDate,
} = variables;
const plottableData = usePlottableData(observations, {
getX,
});
const sortedPlottableData = useMemo(() => {
return sortData(plottableData);
}, [sortData, plottableData]);
const data = useChartData(sortedPlottableData, {
chartConfig,
timeRangeDimensionId: yDimension.id,
getAxisValueAsDate: getYAsDate,
getSegmentAbbreviationOrLabel,
getTimeRangeDate,
});

return {
...data,
allData: sortedPlottableData,
};
};
Loading

0 comments on commit 5c4a4c9

Please sign in to comment.