Skip to content

Commit

Permalink
Merge branch 'main' of github.com:visualize-admin/visualization-tool …
Browse files Browse the repository at this point in the history
…into feat/update-text-style-map
  • Loading branch information
bprusinowski committed Feb 17, 2022
2 parents 5445794 + 9372e75 commit ecf49b9
Show file tree
Hide file tree
Showing 31 changed files with 1,183 additions and 865 deletions.
20 changes: 15 additions & 5 deletions app/charts/chart-config-ui-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,17 @@ export type EncodingOption =
| "chartSubType"
| "sorting"
| "color"
| "imputationType";
| "imputationType"
| "showStandardError";

export type EncodingOptions =
| undefined
| {
field: EncodingOption;
values: string[] | { field: string; values?: string | string[] }[];
values:
| string[]
| boolean[]
| { field: string; values?: string | string[] }[];
}[];
export type EncodingSortingOption = {
sortingType: "byDimensionLabel" | "byTotalSize" | "byMeasure";
Expand Down Expand Up @@ -70,7 +74,13 @@ export const chartConfigOptionsUISpec: ChartSpecs = {
column: {
chartType: "column",
encodings: [
{ field: "y", optional: false, values: ["Measure"], filters: false },
{
field: "y",
optional: false,
values: ["Measure"],
filters: false,
options: [{ field: "showStandardError", values: [true, false] }],
},
{
field: "x",
optional: false,
Expand Down Expand Up @@ -285,13 +295,13 @@ export const chartConfigOptionsUISpec: ChartSpecs = {
field: "areaLayer",
optional: false,
values: ["Measure"],
filters: false,
filters: true,
},
{
field: "symbolLayer",
optional: false,
values: ["Measure"],
filters: false,
filters: true,
},
],
interactiveFilters: [],
Expand Down
6 changes: 5 additions & 1 deletion app/charts/column/chart-column.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ import { BrushTime } from "../shared/brush";
import { ChartContainer, ChartSvg } from "../shared/containers";
import { Tooltip } from "../shared/interaction/tooltip";
import { InteractiveLegendColor, LegendColor } from "../shared/legend-color";
import { ColumnsGrouped } from "./columns-grouped";
import {
ColumnsGrouped,
ErrorWhiskers as ErrorWhiskersGrouped,
} from "./columns-grouped";
import { GroupedColumnChart } from "./columns-grouped-state";
import { Columns, ErrorWhiskers } from "./columns-simple";
import { ColumnsStacked } from "./columns-stacked";
Expand Down Expand Up @@ -144,6 +147,7 @@ export const ChartColumns = memo(
<AxisHeightLinear />
<AxisWidthBand />
<ColumnsGrouped />
<ErrorWhiskersGrouped />
<AxisWidthBandDomain />
<InteractionColumns />
{interactiveFiltersConfig?.time.active && <BrushTime />}
Expand Down
61 changes: 44 additions & 17 deletions app/charts/column/columns-grouped-state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ import {
ScaleTime,
sum,
} from "d3";
import { sortBy } from "lodash";
import { get, sortBy } from "lodash";
import React, { ReactNode, useMemo } from "react";
import { ColumnFields, SortingOrder, SortingType } from "../../configurator";
import {
getPalette,
mkNumber,
useErrorMeasure,
useErrorRange,
useFormatNumber,
} from "../../configurator/components/ui-helpers";
import { Observation } from "../../domain/data";
Expand Down Expand Up @@ -63,29 +65,34 @@ export interface GroupedColumnsState {
xScaleIn: ScaleBand<string>;
xEntireScale: ScaleTime<number, number>;
getY: (d: Observation) => number | null;
getYErrorRange: ((d: Observation) => [number, number]) | null;
yScale: ScaleLinear<number, number>;
getSegment: (d: Observation) => string;
segments: string[];
colors: ScaleOrdinal<string, string>;
yAxisLabel: string;
grouped: [string, Observation[]][];
getAnnotationInfo: (d: Observation) => TooltipInfo;
showStandardError: boolean;
}

const useGroupedColumnsState = ({
data,
fields,
dimensions,
measures,
interactiveFiltersConfig,
aspectRatio,
}: Pick<
ChartProps,
"data" | "dimensions" | "measures" | "interactiveFiltersConfig"
> & {
fields: ColumnFields;
aspectRatio: number;
}): GroupedColumnsState => {
const useGroupedColumnsState = (
chartProps: Pick<
ChartProps,
"data" | "dimensions" | "measures" | "interactiveFiltersConfig"
> & {
fields: ColumnFields;
aspectRatio: number;
}
): GroupedColumnsState => {
const {
data,
fields,
dimensions,
measures,
interactiveFiltersConfig,
aspectRatio,
} = chartProps;
const locale = useLocale();
const width = useWidth();
const formatNumber = useFormatNumber();
Expand All @@ -103,8 +110,12 @@ const useGroupedColumnsState = ({
const getX = useStringVariable(fields.x.componentIri);
const getXAsDate = useTemporalVariable(fields.x.componentIri);
const getY = useOptionalNumericVariable(fields.y.componentIri);
const errorMeasure = useErrorMeasure(chartProps, fields.y.componentIri);
const getYErrorRange = useErrorRange(errorMeasure, getY);
const getSegment = useSegment(fields.segment?.componentIri);

const showStandardError = get(fields, ["y", "showStandardError"], true);

// Sort
const xSortingType = fields.x.sorting?.sortingType;
const xSortingOrder = fields.x.sorting?.sortingOrder;
Expand Down Expand Up @@ -190,6 +201,8 @@ const useGroupedColumnsState = ({
? getSegmentsOrderedByName()
: getSegmentsOrderedByTotalValue();
}, [
dimensions,
fields.segment?.componentIri,
getSegment,
getY,
locale,
Expand Down Expand Up @@ -243,8 +256,20 @@ const useGroupedColumnsState = ({
const xEntireScale = scaleTime().domain(xEntireDomainAsTime);

// y
const minValue = Math.min(mkNumber(min(preparedData, (d) => getY(d))), 0);
const maxValue = Math.max(max(preparedData, (d) => getY(d)) as number, 0);
const minValue = Math.min(
mkNumber(
min(preparedData, (d) =>
getYErrorRange ? getYErrorRange(d)[0] : getY(d) || 0
)
),
0
);
const maxValue = Math.max(
max(preparedData, (d) =>
getYErrorRange ? getYErrorRange(d)[1] : getY(d) || 0
) as number,
0
);

const yScale = scaleLinear()
.domain([mkNumber(minValue), mkNumber(maxValue)])
Expand Down Expand Up @@ -386,6 +411,7 @@ const useGroupedColumnsState = ({
xScaleIn,
xEntireScale,
getY,
getYErrorRange,
yScale,
getSegment,
yAxisLabel,
Expand All @@ -394,6 +420,7 @@ const useGroupedColumnsState = ({
grouped,
getAnnotationInfo,
xIsTime,
showStandardError,
};
};

Expand Down
42 changes: 42 additions & 0 deletions app/charts/column/columns-grouped.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,49 @@
import { useChartState } from "../shared/use-chart-state";
import { VerticalWhisker } from "../whiskers";
import { GroupedColumnsState } from "./columns-grouped-state";
import { Column } from "./rendering-utils";

export const ErrorWhiskers = () => {
const {
bounds,
xScale,
xScaleIn,
getYErrorRange,
yScale,
getSegment,
grouped,
showStandardError,
} = useChartState() as GroupedColumnsState;
const { margins } = bounds;
if (!getYErrorRange || !showStandardError) {
return null;
}

return (
<g transform={`translate(${margins.left} ${margins.top})`}>
{grouped.map((segment) => (
<g key={segment[0]} transform={`translate(${xScale(segment[0])}, 0)`}>
{segment[1].map((d, i) => {
const x0 = xScaleIn(getSegment(d)) as number;
const bandwidth = xScaleIn.bandwidth();
const barwidth = Math.min(bandwidth, 15);
const [y1, y2] = getYErrorRange(d);
return (
<VerticalWhisker
key={i}
x={x0 + bandwidth / 2 - barwidth / 2}
width={barwidth}
y1={yScale(y1)}
y2={yScale(y2)}
/>
);
})}
</g>
))}
</g>
);
};

export const ColumnsGrouped = () => {
const {
bounds,
Expand Down
63 changes: 13 additions & 50 deletions app/charts/column/columns-simple.tsx
Original file line number Diff line number Diff line change
@@ -1,59 +1,22 @@
import { memo } from "react";
import { useTheme } from "../../themes";
import { useChartState } from "../shared/use-chart-state";
import { VerticalWhisker } from "../whiskers";
import { ColumnsState } from "./columns-state";
import { Column } from "./rendering-utils";

export const VerticalWhisker = memo(
({
x,
y1,
y2,
width,
}: {
x: number;
y1: number;
y2: number;
width: number;
color?: string;
}) => {
return (
<>
<rect
x={x}
y={y1}
width={width}
height={2}
fill={"black"}
stroke="none"
/>
<rect
x={x + width / 2 - 1}
y={y2}
width={2}
height={y1 - y2}
fill={"black"}
stroke="none"
/>
<rect
x={x}
y={y2}
width={width}
height={2}
fill={"black"}
stroke="none"
/>
</>
);
}
);

export const ErrorWhiskers = () => {
const { preparedData, bounds, getX, xScale, getY, getYError, yScale } =
useChartState() as ColumnsState;
const { margins } = bounds;
const state = useChartState() as ColumnsState;
const {
getX,
getYErrorRange,
preparedData,
yScale,
xScale,
showStandardError,
} = state;
const { margins } = state.bounds;

if (!getYError) {
if (!getYErrorRange || !showStandardError) {
return null;
}

Expand All @@ -63,7 +26,7 @@ export const ErrorWhiskers = () => {
const x0 = xScale(getX(d)) as number;
const bandwidth = xScale.bandwidth();
const barwidth = Math.min(bandwidth, 15);
const [y1, y2] = getYError(d);
const [y1, y2] = getYErrorRange(d);
return (
<VerticalWhisker
key={i}
Expand Down
Loading

0 comments on commit ecf49b9

Please sign in to comment.