Skip to content

Commit

Permalink
fix: Scatterplot issues with optional segment
Browse files Browse the repository at this point in the history
...by making it required (otherwise chart always shows one data point)
  • Loading branch information
bprusinowski committed Sep 30, 2022
1 parent b50ccdd commit 29ac226
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 43 deletions.
9 changes: 7 additions & 2 deletions app/charts/chart-config-ui-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,10 +233,15 @@ export const chartConfigOptionsUISpec: ChartSpecs = {
values: ["Measure"],
filters: false,
},
{ field: "y", optional: false, values: ["Measure"], filters: false },
{
field: "y",
optional: false,
values: ["Measure"],
filters: false,
},
{
field: "segment",
optional: true,
optional: false,
values: [
"NominalDimension",
"OrdinalDimension",
Expand Down
11 changes: 8 additions & 3 deletions app/charts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,10 @@ export const getInitialConfig = ({
},
};
case "scatterplot":
const segmentComponent =
getCategoricalDimensions(dimensions)[0] ||
getGeoDimensions(dimensions)[0];

return {
version: CHART_CONFIG_VERSION,
chartType: "scatterplot",
Expand All @@ -214,11 +218,11 @@ export const getInitialConfig = ({
measures.length > 1 ? measures[1].iri : measures[0].iri,
},
segment: {
componentIri: getCategoricalDimensions(dimensions)[0].iri,
componentIri: segmentComponent.iri,
palette: DEFAULT_PALETTE,
colorMapping: mapValueIrisToColor({
palette: DEFAULT_PALETTE,
dimensionValues: getCategoricalDimensions(dimensions)[0]?.values,
dimensionValues: segmentComponent.values,
}),
},
},
Expand Down Expand Up @@ -943,6 +947,7 @@ export const getPossibleChartType = ({

const hasZeroQ = measures.length === 0;
const hasMultipleQ = measures.length > 1;
const hasCat = getCategoricalDimensions(dimensions).length > 0;
const hasGeo = getGeoDimensions(dimensions).length > 0;
const hasTime = getTimeDimensions(dimensions).length > 0;

Expand All @@ -957,7 +962,7 @@ export const getPossibleChartType = ({
} else {
possibles.push(...catBased);

if (hasMultipleQ) {
if (hasMultipleQ && (hasCat || hasGeo)) {
possibles.push(...multipleQ);
}

Expand Down
20 changes: 3 additions & 17 deletions app/charts/scatterplot/scatterplot-simple.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,10 @@ import { memo } from "react";

import { ScatterplotState } from "@/charts/scatterplot/scatterplot-state";
import { useChartState } from "@/charts/shared/use-chart-state";
import { useTheme } from "@/themes";

export const Scatterplot = () => {
const {
data,
bounds,
getX,
xScale,
getY,
yScale,
hasSegment,
getSegment,
colors,
} = useChartState() as ScatterplotState;

const theme = useTheme();
const { data, bounds, getX, xScale, getY, yScale, getSegment, colors } =
useChartState() as ScatterplotState;
const { margins } = bounds;

return (
Expand All @@ -28,9 +16,7 @@ export const Scatterplot = () => {
key={index}
cx={xScale(getX(d) ?? NaN)}
cy={yScale(getY(d) ?? NaN)}
color={
hasSegment ? colors(getSegment(d)) : theme.palette.primary.main
}
color={colors(getSegment(d))}
/>
);
})}
Expand Down
22 changes: 10 additions & 12 deletions app/charts/scatterplot/scatterplot-state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ import {
mkNumber,
useFormatNumber,
} from "@/configurator/components/ui-helpers";
import { Observation } from "@/domain/data";
import { DimensionValue, Observation } from "@/domain/data";
import { DimensionMetadataFragment } from "@/graphql/query-hooks";
import { estimateTextWidth } from "@/utils/estimate-text-width";

export interface ScatterplotState {
Expand All @@ -41,7 +42,6 @@ export interface ScatterplotState {
xScale: ScaleLinear<number, number>;
getY: (d: Observation) => number | null;
yScale: ScaleLinear<number, number>;
hasSegment: boolean;
getSegment: (d: Observation) => string;
colors: ScaleOrdinal<string, string>;
xAxisLabel: string;
Expand Down Expand Up @@ -119,16 +119,15 @@ const useScatterplotState = ({
const yDomain = [yMinValue, yMaxValue];
const yScale = scaleLinear().domain(yDomain).nice();

const hasSegment = fields.segment ? true : false;
const segments = useMemo(() => {
return [...new Set(plottableSortedData.map(getSegment))];
}, [getSegment, plottableSortedData]); // get *visible* segments

// Map ordered segments to colors
const colors = scaleOrdinal<string, string>();
const segmentDimension = dimensions.find(
(d) => d.iri === fields.segment?.componentIri
) as $FixMe;
(d) => d.iri === fields.segment.componentIri
) as DimensionMetadataFragment;

const getSegmentLabel = useMemo(() => {
const segmentValuesByValue = keyBy(segmentDimension.values, (x) => x.value);
Expand All @@ -137,23 +136,23 @@ const useScatterplotState = ({
};
}, [segmentDimension.values]);

if (fields.segment && segmentDimension && fields.segment.colorMapping) {
if (fields.segment.colorMapping) {
const orderedSegmentLabelsAndColors = segments.map((segment) => {
const dvIri = segmentDimension.values.find(
(s: $FixMe) => s.label === segment
(d: DimensionValue) => d.label === segment
)?.value;

return {
label: segment,
color: fields.segment!.colorMapping![dvIri] ?? "#006699",
color: fields.segment.colorMapping![dvIri] ?? "#006699",
};
});

colors.domain(orderedSegmentLabelsAndColors.map((s) => s.label));
colors.range(orderedSegmentLabelsAndColors.map((s) => s.color));
} else {
colors.domain(segments);
colors.range(getPalette(fields.segment?.palette));
colors.range(getPalette(fields.segment.palette));
}
// Dimensions
const left = Math.max(
Expand Down Expand Up @@ -206,7 +205,7 @@ const useScatterplotState = ({
xValue: formatNumber(getX(datum)),
tooltipContent: (
<TooltipScatterplot
firstLine={fields.segment && getSegment(datum)}
firstLine={getSegment(datum)}
secondLine={
xMeasure.unit
? `${xMeasure.label}: ${formatNumber(getX(datum))}${
Expand All @@ -224,7 +223,7 @@ const useScatterplotState = ({
/>
),
datum: {
label: fields.segment && getSegment(datum),
label: getSegment(datum),
value: formatNumber(getY(datum)),
color: colors(getSegment(datum)) as string,
},
Expand All @@ -240,7 +239,6 @@ const useScatterplotState = ({
xScale,
getY,
yScale,
hasSegment,
getSegment,
colors,
xAxisLabel,
Expand Down
14 changes: 5 additions & 9 deletions app/configurator/config-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,15 +289,11 @@ export type AreaConfig = t.TypeOf<typeof AreaConfig>;
const ScatterPlotSegmentField = GenericSegmentField;
export type ScatterPlotSegmentField = t.TypeOf<typeof ScatterPlotSegmentField>;

const ScatterPlotFields = t.intersection([
t.type({
x: GenericField,
y: GenericField,
}),
t.partial({
segment: ScatterPlotSegmentField,
}),
]);
const ScatterPlotFields = t.type({
x: GenericField,
y: GenericField,
segment: ScatterPlotSegmentField,
});
const ScatterPlotConfig = t.type(
{
version: t.string,
Expand Down

0 comments on commit 29ac226

Please sign in to comment.