diff --git a/app/charts/chart-config-ui-options.ts b/app/charts/chart-config-ui-options.ts index d56065d75..8451d958e 100644 --- a/app/charts/chart-config-ui-options.ts +++ b/app/charts/chart-config-ui-options.ts @@ -47,7 +47,7 @@ import { isTemporalOrdinalDimension, } from "@/domain/data"; import { DimensionMetadataFragment } from "@/graphql/query-hooks"; -import { getDefaultCategoricalPaletteName } from "@/palettes"; +import { getDefaultCategoricalPaletteName, getPalette } from "@/palettes"; /** * This module controls chart controls displayed in the UI. @@ -113,9 +113,31 @@ type EncodingOption = | { field: "useAbbreviations"; } + // TODO: As these are quite chart type specific, they might be handled in + // some other way. | { field: "lineAxisOrientation"; onChange: OnEncodingOptionChange<"left" | "right", ComboLineColumnConfig>; + } + | { + field: "componentIris"; + onChange: OnEncodingOptionChange; + } + | { + field: "leftAxisComponentIri"; + onChange: OnEncodingOptionChange; + } + | { + field: "rightAxisComponentIri"; + onChange: OnEncodingOptionChange; + } + | { + field: "lineComponentIri"; + onChange: OnEncodingOptionChange; + } + | { + field: "columnComponentIri"; + onChange: OnEncodingOptionChange; }; const onColorComponentScaleTypeChange: OnEncodingOptionChange< @@ -894,6 +916,20 @@ const chartConfigOptionsUISpec: ChartSpecs = { customComponent: true, componentTypes: ["NumericalMeasure"], filters: false, + options: { + componentIris: { + onChange: (iris, options) => { + const { chartConfig } = options; + const { fields } = chartConfig; + const { y } = fields; + const palette = getPalette(y.palette); + const newColorMapping = Object.fromEntries( + iris.map((iri, i) => [iri, y.colorMapping[i] ?? palette[i]]) + ); + chartConfig.fields.y.colorMapping = newColorMapping; + }, + }, + }, }, { field: "x", @@ -913,6 +949,32 @@ const chartConfigOptionsUISpec: ChartSpecs = { customComponent: true, componentTypes: ["NumericalMeasure"], filters: false, + options: { + leftAxisComponentIri: { + onChange: (iri, options) => { + const { chartConfig } = options; + const { fields } = chartConfig; + const { y } = fields; + chartConfig.fields.y.colorMapping = { + [iri]: y.colorMapping[y.leftAxisComponentIri], + [y.rightAxisComponentIri]: + y.colorMapping[y.rightAxisComponentIri], + }; + }, + }, + rightAxisComponentIri: { + onChange: (iri, options) => { + const { chartConfig } = options; + const { fields } = chartConfig; + const { y } = fields; + chartConfig.fields.y.colorMapping = { + [y.leftAxisComponentIri]: + y.colorMapping[y.leftAxisComponentIri], + [iri]: y.colorMapping[y.rightAxisComponentIri], + }; + }, + }, + }, }, { field: "x", @@ -933,22 +995,51 @@ const chartConfigOptionsUISpec: ChartSpecs = { componentTypes: ["NumericalMeasure"], filters: false, options: { + lineComponentIri: { + onChange: (iri, options) => { + const { chartConfig } = options; + const { fields } = chartConfig; + const { y } = fields; + const lineColor = y.colorMapping[y.lineComponentIri]; + const columnColor = y.colorMapping[y.columnComponentIri]; + + chartConfig.fields.y.colorMapping = + y.lineAxisOrientation === "left" + ? { [iri]: lineColor, [y.columnComponentIri]: columnColor } + : { [y.columnComponentIri]: columnColor, [iri]: lineColor }; + }, + }, + columnComponentIri: { + onChange: (iri, options) => { + const { chartConfig } = options; + const { fields } = chartConfig; + const { y } = fields; + const columnColor = y.colorMapping[y.columnComponentIri]; + const lineColor = y.colorMapping[y.lineComponentIri]; + + chartConfig.fields.y.colorMapping = + y.lineAxisOrientation === "left" + ? { [y.lineComponentIri]: lineColor, [iri]: columnColor } + : { [iri]: columnColor, [y.lineComponentIri]: lineColor }; + }, + }, lineAxisOrientation: { onChange: (_, options) => { const { chartConfig } = options; + const { fields } = chartConfig; + const { y } = fields; + const lineAxisLeft = y.lineAxisOrientation === "left"; // Need the correct order to not enable "Reset color palette" button. - const firstIri = - chartConfig.fields.y.lineAxisOrientation === "left" - ? chartConfig.fields.y.columnComponentIri - : chartConfig.fields.y.lineComponentIri; - const secondIri = - chartConfig.fields.y.lineAxisOrientation === "left" - ? chartConfig.fields.y.lineComponentIri - : chartConfig.fields.y.columnComponentIri; + const firstIri = lineAxisLeft + ? y.columnComponentIri + : y.lineComponentIri; + const secondIri = lineAxisLeft + ? y.lineComponentIri + : y.columnComponentIri; chartConfig.fields.y.colorMapping = { - [firstIri]: chartConfig.fields.y.colorMapping[secondIri], - [secondIri]: chartConfig.fields.y.colorMapping[firstIri], + [firstIri]: y.colorMapping[secondIri], + [secondIri]: y.colorMapping[firstIri], }; }, }, @@ -992,7 +1083,17 @@ export const getChartFieldOptionChangeSideEffect = ( case "areaLayer.color.scaleType": case "symbolLayer.color.scaleType": return get(encoding, "options.colorComponent.onScaleTypeChange"); + case "y.componentIris": + return get(encoding, "options.componentIris.onChange"); case "y.lineAxisOrientation": return get(encoding, "options.lineAxisOrientation.onChange"); + case "y.leftAxisComponentIri": + return get(encoding, "options.leftAxisComponentIri.onChange"); + case "y.rightAxisComponentIri": + return get(encoding, "options.rightAxisComponentIri.onChange"); + case "y.lineComponentIri": + return get(encoding, "options.lineComponentIri.onChange"); + case "y.columnComponentIri": + return get(encoding, "options.columnComponentIri.onChange"); } }; diff --git a/app/components/form.tsx b/app/components/form.tsx index d9c181360..46441b20c 100644 --- a/app/components/form.tsx +++ b/app/components/form.tsx @@ -5,6 +5,7 @@ import { ButtonBase, FormControlLabel, FormControlLabelProps, + InputLabel, InputProps, ListSubheader, Checkbox as MUICheckbox, @@ -391,7 +392,15 @@ export const Select = ({ width: "100%", }} > - {selectedOption.label} + + {selectedOption.label} + {hint && } ); diff --git a/app/themes/federal.tsx b/app/themes/federal.tsx index 90fd641be..5c39537af 100644 --- a/app/themes/federal.tsx +++ b/app/themes/federal.tsx @@ -577,9 +577,11 @@ theme.components = { MuiSelect: { styleOverrides: { select: { + display: "flex", + alignItems: "center", boxSizing: "border-box", height: "40px", - padding: "8px 14px", + padding: "8px 12px", color: theme.palette.grey[700], textOverflow: "ellipsis", fontSize: theme.typography.body2.fontSize,