Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add Combo charts #1199

Merged
merged 65 commits into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
6289c5a
perf: Disable loading of dimension values for preview query
bprusinowski Sep 26, 2023
e59776f
fix: E2E color -> segmentation
bprusinowski Sep 26, 2023
ca64a19
feat: Add initial Combo chart schema
bprusinowski Sep 29, 2023
5f7a36b
feat: Add initial Combo chart adjusters
bprusinowski Sep 29, 2023
bac320e
feat: Add Combo chart to chart type selector
bprusinowski Sep 29, 2023
934e9cc
feat: Further set up of Combo chart
bprusinowski Sep 29, 2023
0aac329
feat: Set up ComboLine and ComboLineColumn charts
bprusinowski Sep 29, 2023
f299ac2
feat: Set up ComboLineDual chart
bprusinowski Sep 29, 2023
9a5ad80
feat: Initial ComboLineSingle state
bprusinowski Sep 29, 2023
383450a
feat: Initial ComboLineSingle
bprusinowski Sep 29, 2023
7d57798
feat: Add Y axis to ComboLineSingle chart
bprusinowski Sep 29, 2023
245ff05
refactor: Introduce getColorLabel function for chart that support col…
bprusinowski Sep 29, 2023
0f40ead
feat: Add color legend to ComboLineSingle chart
bprusinowski Sep 29, 2023
116cd6d
feat: Do not include unit in color legend, as it's shared and visible…
bprusinowski Sep 29, 2023
3a9b077
refactor: Rename parameter
bprusinowski Sep 29, 2023
6362c35
feat: Add X axis and interactions to ComboLineSingle chart
bprusinowski Sep 29, 2023
9e89424
feat: Add BrushTime component to ComboLineSingleChart
bprusinowski Oct 2, 2023
92488ac
refactor: Prepare for yMulti in the options panel
bprusinowski Oct 2, 2023
1e22402
fix: Bump chart config version
bprusinowski Oct 2, 2023
7a2a1c0
fix: Component iri can be missing
bprusinowski Oct 2, 2023
db12090
refactor: Styling improvements
bprusinowski Oct 2, 2023
60805af
fix: Do not trigger onChangeChartType when it's the same chart type
bprusinowski Oct 2, 2023
3bfd883
feat: Add initial ChartComboYField
bprusinowski Oct 2, 2023
d66e27e
refactor: Split ChartCombo into three charts
bprusinowski Oct 2, 2023
07906e0
feat: Initial ComboLineDual implementation
bprusinowski Oct 3, 2023
93d23f2
chore: Clean up
bprusinowski Oct 3, 2023
cb0e4c5
feat: Add AxisHeightLinearDual
bprusinowski Oct 3, 2023
694ffeb
fix: ComboLineDual chart margins
bprusinowski Oct 3, 2023
d129ec4
chore: Remove unused
bprusinowski Oct 3, 2023
fde683e
feat: Include unit in ComboLineDual chart
bprusinowski Oct 3, 2023
a843964
feat: Add initial ComboLineDual Y field UI options
bprusinowski Oct 3, 2023
3e1a082
feat: Allow to bypass rendering of group header
bprusinowski Oct 3, 2023
11e4a18
feat: Group measures by unit in ComboSingleLine chart
bprusinowski Oct 3, 2023
6403bc8
feat: Use line symbols in tooltips for line-based charts
bprusinowski Oct 3, 2023
09fb187
refactor: Rename function
bprusinowski Oct 4, 2023
6c62aec
refactor: Improve ComboLineDual props structure
bprusinowski Oct 4, 2023
3bc22c2
feat: Set up initial ComboLineColumn chart
bprusinowski Oct 4, 2023
7fe25be
fix: Deployment
bprusinowski Oct 4, 2023
b1547bb
feat: Add a way to rotate the Ruler labels
bprusinowski Oct 4, 2023
f208897
refactor: Rename file
bprusinowski Oct 4, 2023
2c0294a
feat: Change default line orientation to right (ComboLineColumn chart)
bprusinowski Oct 4, 2023
4f3bd2e
feat: Add initial drawing logic for ComboLineColumn chart
bprusinowski Oct 4, 2023
50e5855
docs: Update README
bprusinowski Oct 4, 2023
55fbc74
fix: Consider band domain when computing padding (ComboLineColumn)
bprusinowski Oct 4, 2023
e43e620
fix: Add missing prop
bprusinowski Oct 4, 2023
5c2a165
chore: Add comments
bprusinowski Oct 4, 2023
72ba791
feat: Add initial UI options for y field (ComboLineColumn chart)
bprusinowski Oct 4, 2023
0144f02
fix: Use correct symbols in ComboLineColumn tooltip
bprusinowski Oct 4, 2023
ed4159a
fix: Correctly retrieve measures
bprusinowski Oct 4, 2023
009ca91
fix: Show the tooltip when datum didn't change, but user hovered over…
bprusinowski Oct 4, 2023
fc6d92d
feat: Use InteractionColumns for ComboLineColumn chart
bprusinowski Oct 4, 2023
294b12a
feat: Separate regular and combo charts in the chart type selector
bprusinowski Oct 4, 2023
4e05b32
refactor: Share some logic between AxisHeightLinear and AxisHeightLin…
bprusinowski Oct 4, 2023
02d3683
feat: Only allow combo charts if we have measures with more than one …
bprusinowski Oct 4, 2023
2aa97dd
fix: Centering the tooltip (ComboLineSingle)
bprusinowski Oct 4, 2023
6a30418
fix: Correctly initialize combo charts (y measures)
bprusinowski Oct 4, 2023
60c16f9
refactor: Extract type
bprusinowski Oct 4, 2023
a0ed433
fix: Allow ComboLineSingle if there's only one unit
bprusinowski Oct 4, 2023
0dbfd26
refactor: Share some state between combo charts
bprusinowski Oct 5, 2023
768f3b5
feat: Exclude missing observations from Combo charts
bprusinowski Oct 5, 2023
24e97e3
feat: Use rendering key in ComboLineColumn
bprusinowski Oct 5, 2023
6da05ca
feat: Keep chart config when switching to / from Combo charts
bprusinowski Oct 6, 2023
9f5cc50
refactor: Clean up
bprusinowski Oct 6, 2023
a059662
chore: Update comments
bprusinowski Oct 6, 2023
d1ef9f9
Merge branch 'feat/dashboards-1' of github.com:visualize-admin/visual…
bprusinowski Oct 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ You can also check the [release page](https://github.com/visualize-admin/visuali

## Unreleased

Nothing yet.
- Features
- Added a new group of charts – Combo charts – that includes multi-measure line, dual-axis line and column-line charts

# [3.22.8] - 2023-09-29

Expand Down
24 changes: 13 additions & 11 deletions app/charts/area/areas-state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export type AreasState = CommonChartState &
yScale: ScaleLinear<number, number>;
segments: string[];
colors: ScaleOrdinal<string, string>;
getColorLabel: (segment: string) => string;
chartWideData: ArrayLike<Observation>;
series: $FixMe[];
getAnnotationInfo: (d: Observation) => TooltipInfo;
Expand All @@ -89,6 +90,7 @@ const useAreasState = (
segmentsByAbbreviationOrLabel,
getSegment,
getSegmentAbbreviationOrLabel,
getSegmentLabel,
} = variables;
const getIdentityY = useGetIdentityY(yMeasure.iri);
const {
Expand Down Expand Up @@ -230,15 +232,14 @@ const useAreasState = (
}, [chartWideData, segmentSortingOrder, segmentSortingType, segments]);

/** Scales */
const { colors, xScale, interactiveXTimeRangeScale } = useMemo(() => {
const { colors, xScale, xScaleTimeRange } = useMemo(() => {
const xDomain = extent(scalesData, (d) => getX(d)) as [Date, Date];
const xScale = scaleTime().domain(xDomain);
const interactiveXTimeRangeDomain = extent(timeRangeData, (d) =>
getX(d)
) as [Date, Date];
const interactiveXTimeRangeScale = scaleTime().domain(
interactiveXTimeRangeDomain
);
const xScaleTimeRangeDomain = extent(timeRangeData, (d) => getX(d)) as [
Date,
Date
];
const xScaleTimeRange = scaleTime().domain(xScaleTimeRangeDomain);
const colors = scaleOrdinal<string, string>();

if (segmentDimension && fields.segment?.colorMapping) {
Expand Down Expand Up @@ -266,7 +267,7 @@ const useAreasState = (
return {
colors,
xScale,
interactiveXTimeRangeScale,
xScaleTimeRange,
};
}, [
fields.segment?.palette,
Expand Down Expand Up @@ -339,7 +340,7 @@ const useAreasState = (

/** Adjust scales according to dimensions */
xScale.range([0, chartWidth]);
interactiveXTimeRangeScale.range([0, chartWidth]);
xScaleTimeRange.range([0, chartWidth]);
yScale.range([chartHeight, 0]);

/** Tooltip */
Expand Down Expand Up @@ -372,7 +373,7 @@ const useAreasState = (
placement: getCenteredTooltipPlacement({
chartWidth,
xAnchor,
segment: !!fields.segment,
topAnchor: !fields.segment,
}),
xValue: timeFormatUnit(getX(datum), xDimension.timeUnit),
datum: {
Expand Down Expand Up @@ -419,10 +420,11 @@ const useAreasState = (
chartData,
allData,
xScale,
interactiveXTimeRangeScale,
xScaleTimeRange,
yScale,
segments,
colors,
getColorLabel: getSegmentLabel,
chartWideData,
series,
getAnnotationInfo,
Expand Down
66 changes: 66 additions & 0 deletions app/charts/chart-config-ui-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ import {
ColorScaleType,
ColumnConfig,
ColumnSegmentField,
ComboLineColumnConfig,
ComboLineDualConfig,
ComboLineSingleConfig,
ComponentType,
GenericField,
LineConfig,
Expand Down Expand Up @@ -216,6 +219,8 @@ export interface EncodingSpec<T extends ChartConfig = ChartConfig> {
field: EncodingFieldType;
optional: boolean;
componentTypes: ComponentType[];
/** If true, won't use the ChartFieldOption component, but a custom one. Needs to be handled then in ChartOptionsSelector. */
customComponent?: boolean;
/** If false, using a dimension in this encoding will not prevent it to be used in an other encoding. Default: true */
exclusive?: boolean;
filters: boolean;
Expand Down Expand Up @@ -256,6 +261,9 @@ interface ChartSpecs {
pie: ChartSpec<PieConfig>;
scatterplot: ChartSpec<ScatterPlotConfig>;
table: ChartSpec<TableConfig>;
comboLineSingle: ChartSpec<ComboLineSingleConfig>;
comboLineDual: ChartSpec<ComboLineDualConfig>;
comboLineColumn: ChartSpec<ComboLineColumnConfig>;
}

const SEGMENT_COMPONENT_TYPES: ComponentType[] = [
Expand Down Expand Up @@ -872,6 +880,64 @@ const chartConfigOptionsUISpec: ChartSpecs = {
encodings: [],
interactiveFilters: [],
},
comboLineSingle: {
chartType: "comboLineSingle",
encodings: [
{
field: "y",
optional: false,
// TODO: maybe we should even create the components here?
customComponent: true,
componentTypes: ["NumericalMeasure"],
filters: false,
},
{
field: "x",
optional: false,
componentTypes: ["TemporalDimension"],
filters: true,
},
],
interactiveFilters: [],
},
comboLineDual: {
chartType: "comboLineDual",
encodings: [
{
field: "y",
optional: false,
customComponent: true,
componentTypes: ["NumericalMeasure"],
filters: false,
},
{
field: "x",
optional: false,
componentTypes: ["TemporalDimension"],
filters: true,
},
],
interactiveFilters: [],
},
comboLineColumn: {
chartType: "comboLineColumn",
encodings: [
{
field: "y",
optional: false,
customComponent: true,
componentTypes: ["NumericalMeasure"],
filters: false,
},
{
field: "x",
optional: false,
componentTypes: ["TemporalDimension"],
filters: true,
},
],
interactiveFilters: [],
},
};

export const getChartFieldChangeSideEffect = (
Expand Down
19 changes: 10 additions & 9 deletions app/charts/column/columns-grouped-state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export type GroupedColumnsState = CommonChartState &
yScale: ScaleLinear<number, number>;
segments: string[];
colors: ScaleOrdinal<string, string>;
getColorLabel: (segment: string) => string;
grouped: [string, Observation[]][];
getAnnotationInfo: (d: Observation) => TooltipInfo;
};
Expand All @@ -89,6 +90,7 @@ const useColumnsGroupedState = (
segmentsByAbbreviationOrLabel,
getSegment,
getSegmentAbbreviationOrLabel,
getSegmentLabel,
} = variables;
const {
chartData,
Expand Down Expand Up @@ -178,7 +180,7 @@ const useColumnsGroupedState = (
colors,
yScale,
paddingYScale,
interactiveXTimeRangeScale,
xScaleTimeRange,
xScale,
xScaleIn,
xScaleInteraction,
Expand Down Expand Up @@ -232,12 +234,10 @@ const useColumnsGroupedState = (
.paddingOuter(0);
const xScaleIn = scaleBand().domain(segments).padding(PADDING_WITHIN);

const interactiveXTimeRangeDomain = extent(timeRangeData, (d) =>
const xScaleTimeRangeDomain = extent(timeRangeData, (d) =>
getXAsDate(d)
) as [Date, Date];
const interactiveXTimeRangeScale = scaleTime().domain(
interactiveXTimeRangeDomain
);
const xScaleTimeRange = scaleTime().domain(xScaleTimeRangeDomain);

// y
const minValue = Math.min(
Expand Down Expand Up @@ -274,7 +274,7 @@ const useColumnsGroupedState = (
colors,
yScale,
paddingYScale,
interactiveXTimeRangeScale,
xScaleTimeRange,
xScale,
xScaleIn,
xScaleInteraction,
Expand Down Expand Up @@ -352,7 +352,7 @@ const useColumnsGroupedState = (
xScale.range([0, chartWidth]);
xScaleInteraction.range([0, chartWidth]);
xScaleIn.range([0, xScale.bandwidth()]);
interactiveXTimeRangeScale.range([0, chartWidth]);
xScaleTimeRange.range([0, chartWidth]);
yScale.range([chartHeight, 0]);

// Tooltip
Expand Down Expand Up @@ -383,7 +383,7 @@ const useColumnsGroupedState = (
const placement = getCenteredTooltipPlacement({
chartWidth,
xAnchor: xAnchorRaw,
segment: !!fields.segment,
topAnchor: !fields.segment,
});

const getError = (d: Observation) => {
Expand Down Expand Up @@ -424,10 +424,11 @@ const useColumnsGroupedState = (
xScale,
xScaleInteraction,
xScaleIn,
interactiveXTimeRangeScale,
xScaleTimeRange,
yScale,
segments,
colors,
getColorLabel: getSegmentLabel,
grouped,
getAnnotationInfo,
...variables,
Expand Down
19 changes: 10 additions & 9 deletions app/charts/column/columns-stacked-state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export type StackedColumnsState = CommonChartState &
yScale: ScaleLinear<number, number>;
segments: string[];
colors: ScaleOrdinal<string, string>;
getColorLabel: (segment: string) => string;
chartWideData: ArrayLike<Observation>;
series: $FixMe[];
getAnnotationInfo: (
Expand All @@ -97,6 +98,7 @@ const useColumnsStackedState = (
segmentsByAbbreviationOrLabel,
getSegment,
getSegmentAbbreviationOrLabel,
getSegmentLabel,
} = variables;
const getIdentityY = useGetIdentityY(yMeasure.iri);
const {
Expand Down Expand Up @@ -210,7 +212,7 @@ const useColumnsStackedState = (
xScale,
xTimeRangeDomainLabels,
xScaleInteraction,
interactiveXTimeRangeScale,
xScaleTimeRange,
} = useMemo(() => {
const colors = scaleOrdinal<string, string>();

Expand Down Expand Up @@ -271,18 +273,16 @@ const useColumnsStackedState = (
.paddingInner(0)
.paddingOuter(0);

const interactiveXTimeRangeDomain = extent(timeRangeData, (d) =>
const xScaleTimeRangeDomain = extent(timeRangeData, (d) =>
getXAsDate(d)
) as [Date, Date];
const interactiveXTimeRangeScale = scaleTime().domain(
interactiveXTimeRangeDomain
);
const xScaleTimeRange = scaleTime().domain(xScaleTimeRangeDomain);

return {
colors,
xScale,
xTimeRangeDomainLabels,
interactiveXTimeRangeScale,
xScaleTimeRange,
xScaleInteraction,
};
}, [
Expand Down Expand Up @@ -400,7 +400,7 @@ const useColumnsStackedState = (

xScale.range([0, chartWidth]);
xScaleInteraction.range([0, chartWidth]);
interactiveXTimeRangeScale.range([0, chartWidth]);
xScaleTimeRange.range([0, chartWidth]);
yScale.range([chartHeight, 0]);

// Tooltips
Expand Down Expand Up @@ -430,7 +430,7 @@ const useColumnsStackedState = (
const placement = getCenteredTooltipPlacement({
chartWidth,
xAnchor: xAnchorRaw,
segment: !!fields.segment,
topAnchor: !fields.segment,
});

return {
Expand Down Expand Up @@ -479,10 +479,11 @@ const useColumnsStackedState = (
allData,
xScale,
xScaleInteraction,
interactiveXTimeRangeScale,
xScaleTimeRange,
yScale,
segments,
colors,
getColorLabel: getSegmentLabel,
chartWideData,
series,
getAnnotationInfo,
Expand Down
Loading
Loading