Skip to content

Commit

Permalink
feat: Show default color palette in ColorPalette picker
Browse files Browse the repository at this point in the history
...if default colors are there
  • Loading branch information
bprusinowski committed Oct 27, 2022
1 parent dac178e commit a166c0f
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 65 deletions.
81 changes: 62 additions & 19 deletions app/charts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ import {
TableColumn,
TableFields,
} from "@/configurator/config-types";
import { DEFAULT_PALETTE } from "@/configurator/configurator-state";
import { FIELD_VALUE_NONE } from "@/configurator/constants";
import { HierarchyValue } from "@/graphql/resolver-types";
import { getDefaultCategoricalPaletteName } from "@/palettes";
import { visitHierarchy } from "@/rdf/tree-utils";
import { CHART_CONFIG_VERSION } from "@/utils/chart-config/versioning";

Expand Down Expand Up @@ -160,6 +160,8 @@ export const getInitialAreaLayer = ({
// color
measure: NumericalMeasure | OrdinalMeasure;
}): MapAreaLayer => {
const palette = getDefaultCategoricalPaletteName(measure);

return {
componentIri: component.iri,
color: isNumericalMeasure(measure)
Expand All @@ -173,9 +175,9 @@ export const getInitialAreaLayer = ({
: {
type: "categorical",
componentIri: measure.iri,
palette: "oranges",
palette,
colorMapping: mapValueIrisToColor({
palette: DEFAULT_PALETTE,
palette,
dimensionValues: measure.values,
}),
},
Expand Down Expand Up @@ -271,6 +273,9 @@ export const getInitialConfig = ({
const scatterplotSegmentComponent =
getCategoricalDimensions(dimensions)[0] ||
getGeoDimensions(dimensions)[0];
const scatterplotPalette = getDefaultCategoricalPaletteName(
scatterplotSegmentComponent
);

return {
version: CHART_CONFIG_VERSION,
Expand All @@ -288,9 +293,9 @@ export const getInitialConfig = ({
...(scatterplotSegmentComponent
? {
componentIri: scatterplotSegmentComponent.iri,
palette: DEFAULT_PALETTE,
palette: scatterplotPalette,
colorMapping: mapValueIrisToColor({
palette: DEFAULT_PALETTE,
palette: scatterplotPalette,
dimensionValues: scatterplotSegmentComponent.values,
}),
}
Expand All @@ -301,6 +306,7 @@ export const getInitialConfig = ({
const pieSegmentComponent =
getCategoricalDimensions(dimensions)[0] ||
getGeoDimensions(dimensions)[0];
const piePalette = getDefaultCategoricalPaletteName(pieSegmentComponent);

return {
version: CHART_CONFIG_VERSION,
Expand All @@ -311,10 +317,10 @@ export const getInitialConfig = ({
y: { componentIri: numericalMeasures[0].iri },
segment: {
componentIri: pieSegmentComponent.iri,
palette: DEFAULT_PALETTE,
palette: piePalette,
sorting: { sortingType: "byMeasure", sortingOrder: "asc" },
colorMapping: mapValueIrisToColor({
palette: DEFAULT_PALETTE,
palette: piePalette,
dimensionValues: pieSegmentComponent.values,
}),
},
Expand Down Expand Up @@ -602,14 +608,21 @@ const chartConfigsAdjusters: ChartConfigsAdjusters = {
});
},
},
segment: ({ oldValue, oldChartConfig, newChartConfig, dimensions }) => {
segment: ({
oldValue,
oldChartConfig,
newChartConfig,
dimensions,
measures,
}) => {
let newSegment: ColumnSegmentField | undefined;

// When switching from a table chart, a whole fields object is passed as oldValue.
if (oldChartConfig.chartType === "table") {
const tableSegment = convertTableFieldsToSegmentField({
fields: oldValue as TableFields,
dimensions,
measures,
});

if (tableSegment) {
Expand Down Expand Up @@ -673,13 +686,20 @@ const chartConfigsAdjusters: ChartConfigsAdjusters = {
});
},
},
segment: ({ oldValue, oldChartConfig, newChartConfig, dimensions }) => {
segment: ({
oldValue,
oldChartConfig,
newChartConfig,
dimensions,
measures,
}) => {
let newSegment: LineSegmentField | undefined;

if (oldChartConfig.chartType === "table") {
const tableSegment = convertTableFieldsToSegmentField({
fields: oldValue as TableFields,
dimensions,
measures,
});

if (tableSegment) {
Expand Down Expand Up @@ -738,13 +758,20 @@ const chartConfigsAdjusters: ChartConfigsAdjusters = {
});
},
},
segment: ({ oldValue, oldChartConfig, newChartConfig, dimensions }) => {
segment: ({
oldValue,
oldChartConfig,
newChartConfig,
dimensions,
measures,
}) => {
let newSegment: AreaSegmentField | undefined;

if (oldChartConfig.chartType === "table") {
const tableSegment = convertTableFieldsToSegmentField({
fields: oldValue as TableFields,
dimensions,
measures,
});

if (tableSegment) {
Expand Down Expand Up @@ -800,13 +827,20 @@ const chartConfigsAdjusters: ChartConfigsAdjusters = {
return newChartConfig;
},
},
segment: ({ oldValue, oldChartConfig, newChartConfig, dimensions }) => {
segment: ({
oldValue,
oldChartConfig,
newChartConfig,
dimensions,
measures,
}) => {
let newSegment: ScatterPlotSegmentField | undefined;

if (oldChartConfig.chartType === "table") {
const tableSegment = convertTableFieldsToSegmentField({
fields: oldValue as TableFields,
dimensions,
measures,
});

if (tableSegment) {
Expand Down Expand Up @@ -844,13 +878,20 @@ const chartConfigsAdjusters: ChartConfigsAdjusters = {
});
},
},
segment: ({ oldValue, oldChartConfig, newChartConfig, dimensions }) => {
segment: ({
oldValue,
oldChartConfig,
newChartConfig,
dimensions,
measures,
}) => {
let newSegment: PieSegmentField | undefined;

if (oldChartConfig.chartType === "table") {
const tableSegment = convertTableFieldsToSegmentField({
fields: oldValue as TableFields,
dimensions,
measures,
});

if (tableSegment) {
Expand Down Expand Up @@ -1136,9 +1177,11 @@ export const getFieldComponentIri = (fields: GenericFields, field: string) => {
const convertTableFieldsToSegmentField = ({
fields,
dimensions,
measures,
}: {
fields: TableFields;
dimensions: DataCubeMetadata["dimensions"];
measures: DataCubeMetadata["measures"];
}): GenericSegmentField | undefined => {
const groupedColumns = group(Object.values(fields), (d) => d.isGroup)
.get(true)
Expand All @@ -1153,17 +1196,17 @@ const convertTableFieldsToSegmentField = ({

if (component) {
const { componentIri } = component;
const actualComponent = [...dimensions, ...measures].find(
(d) => d.iri === componentIri
) as DimensionMetadataFragment;
const palette = getDefaultCategoricalPaletteName(actualComponent);

return {
componentIri,
palette: DEFAULT_PALETTE,
palette,
colorMapping: mapValueIrisToColor({
palette: DEFAULT_PALETTE,
dimensionValues: (
dimensions.find(
(d) => d.iri === componentIri
) as DimensionMetadataFragment
)?.values,
palette,
dimensionValues: actualComponent.values,
}),
};
}
Expand Down
11 changes: 11 additions & 0 deletions app/charts/shared/colors.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { color, RGBColor } from "d3";

import { DimensionValue } from "@/domain/data";
import { DimensionMetadataFragment } from "@/graphql/query-hooks";

export const colorToRgbArray = (_color: string, opacity?: number): number[] => {
const { r, g, b } = color(_color) as RGBColor;

Expand All @@ -18,3 +21,11 @@ export const rgbArrayToHex = (rgbArray: number[]): string => {
);
}
};

export const hasDimensionDefaultColors = (
d?: DimensionMetadataFragment
): d is DimensionMetadataFragment => {
return !!(d?.values as DimensionValue[] | undefined)?.some(
(d) => d.color !== undefined
);
};
26 changes: 20 additions & 6 deletions app/configurator/components/chart-controls/color-palette.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,21 @@ import { makeStyles } from "@mui/styles";
import get from "lodash/get";
import { useCallback } from "react";

import { hasDimensionDefaultColors } from "@/charts/shared/colors";
import Flex from "@/components/flex";
import { Label } from "@/components/form";
import {
ConfiguratorStateConfiguringChart,
useConfiguratorState,
DEFAULT_PALETTE,
} from "@/configurator";
import { mapValueIrisToColor } from "@/configurator/components/ui-helpers";
import { isNumericalMeasure } from "@/domain/data";
import { DimensionValue, isNumericalMeasure } from "@/domain/data";
import { DimensionMetadataFragment } from "@/graphql/query-hooks";
import {
categoricalPalettes,
DEFAULT_CATEGORICAL_PALETTE_NAME,
divergingSteppedPalettes,
getDefaultCategoricalPalette,
getPalette,
} from "@/palettes";
import useEvent from "@/utils/use-event";
Expand Down Expand Up @@ -58,9 +60,20 @@ export const ColorPalette = ({
}: Props) => {
const [state, dispatch] = useConfiguratorState();
const classes = useStyles();
const hasDefaultColors = hasDimensionDefaultColors(component);
const defaultPalette =
hasDefaultColors && component
? getDefaultCategoricalPalette(
(component.values as DimensionValue[])
.map((d) => d.color)
.filter(Boolean) as string[]
)
: null;

const palettes = isNumericalMeasure(component)
? divergingSteppedPalettes
: defaultPalette
? [defaultPalette, ...categoricalPalettes]
: categoricalPalettes;

const currentPaletteName = get(
Expand All @@ -78,6 +91,7 @@ export const ColorPalette = ({
if (!component || !palette) {
return;
}

dispatch({
type: "CHART_PALETTE_CHANGED",
value: {
Expand Down Expand Up @@ -200,7 +214,7 @@ const ColorPaletteReset = ({
`chartConfig.fields["${field}"].${
colorConfigPath ? `${colorConfigPath}.` : ""
}palette`,
DEFAULT_PALETTE
DEFAULT_CATEGORICAL_PALETTE_NAME
) as string;

const colorMapping = get(
Expand Down Expand Up @@ -233,9 +247,9 @@ const ColorPaletteReset = ({

const nbMatchedColors = colorMappingColors.length;
const matchedColorsInPalette = currentPalette.slice(0, nbMatchedColors);
const same = matchedColorsInPalette.every(
(pc, i) => pc === colorMappingColors[i]
);
const same =
matchedColorsInPalette.every((d, i) => d === colorMappingColors[i]) ||
palette === "default";

return (
<Button
Expand Down
5 changes: 3 additions & 2 deletions app/configurator/components/filters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import React, {
useState,
} from "react";

import { hasDimensionDefaultColors } from "@/charts/shared/colors";
import Flex from "@/components/flex";
import { Loading } from "@/components/hint";
import {
Expand Down Expand Up @@ -397,8 +398,8 @@ const MultiFilterContent = ({
}, [colorConfigPath, config, dimensionIri, colorComponent]);

const hasDefaultColors = useMemo(() => {
return colorComponent?.values?.[0]?.color !== undefined;
}, [colorComponent?.values]);
return hasDimensionDefaultColors(colorComponent);
}, [colorComponent]);

return (
<Box sx={{ position: "relative" }}>
Expand Down
4 changes: 3 additions & 1 deletion app/configurator/components/ui-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,9 @@ export const mapValueIrisToColor = ({

const paletteValues = getPalette(palette);
const colors = dimensionValues.map(
(d, i) => d.color || paletteValues[i % paletteValues.length]
(d, i) =>
(palette === "default" && d.color) ||
paletteValues[i % paletteValues.length]
);
const colorScale = scaleOrdinal<string, string>()
.domain(dimensionValues.map((d) => `${d.value}`))
Expand Down
4 changes: 2 additions & 2 deletions app/configurator/configurator-state.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,7 @@ describe("colorMapping", () => {
color: {
type: "categorical",
componentIri: "areaLayerColorIri",
palette: "oranges",
palette: "default",
colorMapping: {
red: "green",
green: "blue",
Expand Down Expand Up @@ -719,7 +719,7 @@ describe("handleChartOptionChanged", () => {
color: {
type: "categorical",
componentIri: "areaLayerColorIri",
palette: "oranges",
palette: "default",
colorMapping: {
red: "green",
green: "blue",
Expand Down
Loading

0 comments on commit a166c0f

Please sign in to comment.