Skip to content

Commit

Permalink
Merge branch 'main' into feat/automatic-sort
Browse files Browse the repository at this point in the history
  • Loading branch information
ptbrowne authored Oct 20, 2022
2 parents 8952a91 + 57d4b84 commit 0e9a664
Show file tree
Hide file tree
Showing 10 changed files with 41 additions and 33 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ You can also check the [release page](https://github.com/visualize-admin/visuali
- Enable sorting of Geo dimensions
- Maintain segment sorting type correctly when switching from / to Pie chart
- Fix sorting by measure when undefined values are present in the data
- Enable CSS Color Module Level 3 color specifications in the color picker (instead of just HEX)
- New "Automatic" sorting option using "identifier" or "position" or "label"
- Sorting is enabled for line charts (sorts legend items and tooltip values)
- Map:
- area & symbol layers now use the same approach as for segment field (optional select element), to be more consistent across the app
- it's now possible to use discrete color mapping in symbol layer
- Errors:
- Make missing timeFormat error message more explicit

## [3.10.0] - 2022-10-19

Expand Down
4 changes: 2 additions & 2 deletions app/charts/map/map-legend.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
import React, { useEffect, useMemo, useRef } from "react";

import { MapState } from "@/charts/map/map-state";
import { convertRgbArrayToHex } from "@/charts/shared/colors";
import { rgbArrayToHex } from "@/charts/shared/colors";
import { MapLegendColor } from "@/charts/shared/legend-color";
import { useChartState } from "@/charts/shared/use-chart-state";
import { useChartTheme } from "@/charts/shared/use-chart-theme";
Expand Down Expand Up @@ -301,7 +301,7 @@ const CircleLegend = ({
const maxRadius = radiusScale.range()[1];

const color = interaction.d
? convertRgbArrayToHex(getColor(interaction.d))
? rgbArrayToHex(getColor(interaction.d))
: undefined;

const domainObservations = useMemo(
Expand Down
8 changes: 3 additions & 5 deletions app/charts/map/map-state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ import {
} from "@/domain/data";
import { DimensionMetadataFragment } from "@/graphql/query-hooks";

import { convertHexToRgbArray } from "../shared/colors";
import { colorToRgbArray } from "../shared/colors";

import { getBBox } from "./helpers";

Expand Down Expand Up @@ -169,7 +169,7 @@ const getNumericalColorScale = ({
};

const getFixedColors = (color: FixedColorField) => {
const c = convertHexToRgbArray(color.value, color.opacity * 2.55);
const c = colorToRgbArray(color.value, color.opacity * 2.55);
return { type: "fixed" as "fixed", getColor: (_: Observation) => c };
};

Expand All @@ -183,9 +183,7 @@ const getCategoricalColors = (
) as DimensionMetadataFragment;
const componentValuesByLabel = keyBy(component.values, (d) => d.label);
const domain: string[] = component.values.map((d) => d.value) || [];
const rgbColorMapping = mapValues(color.colorMapping, (d) =>
convertHexToRgbArray(d)
);
const rgbColorMapping = mapValues(color.colorMapping, colorToRgbArray);
const getValue = (d: Observation) =>
d[color.componentIri] !== null ? `${d[color.componentIri]}` : "";

Expand Down
6 changes: 3 additions & 3 deletions app/charts/map/map-tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from "react";

import { MapState } from "@/charts/map/map-state";
import { convertRgbArrayToHex } from "@/charts/shared/colors";
import { rgbArrayToHex } from "@/charts/shared/colors";
import { TooltipBox } from "@/charts/shared/interaction/tooltip-box";
import useChartFormatters from "@/charts/shared/use-chart-formatters";
import { useChartState } from "@/charts/shared/use-chart-state";
Expand Down Expand Up @@ -73,7 +73,7 @@ export const MapTooltip = () => {

const value = colors.getValue(obs || {}) ?? null;
const show = identicalLayerComponentIris || hoverObjectType === "area";
const color = obs ? convertRgbArrayToHex(colors.getColor(obs)) : "#fff";
const color = obs ? rgbArrayToHex(colors.getColor(obs)) : "#fff";
const textColor = getTooltipTextColor(color);
const valueFormatter = (d: number | null) =>
formatNumberWithUnit(
Expand Down Expand Up @@ -109,7 +109,7 @@ export const MapTooltip = () => {

const value = symbolLayer.getValue(interaction.d || {}) ?? null;
const show = identicalLayerComponentIris || hoverObjectType === "symbol";
const color = obs ? convertRgbArrayToHex(colors.getColor(obs)) : "#fff";
const color = obs ? rgbArrayToHex(colors.getColor(obs)) : "#fff";
const textColor = getTooltipTextColor(color);
const valueFormatter = (d: number | null) =>
formatNumberWithUnit(
Expand Down
9 changes: 3 additions & 6 deletions app/charts/shared/colors.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import { color, RGBColor } from "d3";

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

return opacity !== undefined ? [r, g, b, opacity] : [r, g, b];
};

export const convertRgbArrayToHex = (rgbArray: number[]): string => {
export const rgbArrayToHex = (rgbArray: number[]): string => {
switch (rgbArray.length) {
case 3:
return `rgb(${rgbArray.join(",")})`;
Expand Down
6 changes: 2 additions & 4 deletions app/charts/shared/legend-color.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { dfs } from "@/utils/dfs";
import { interlace } from "@/utils/interlace";
import useEvent from "@/utils/use-event";

import { convertRgbArrayToHex } from "./colors";
import { rgbArrayToHex } from "./colors";

type LegendSymbol = "square" | "line" | "circle";

Expand Down Expand Up @@ -256,9 +256,7 @@ export const MapLegendColor = memo(function LegendColor({
getColor={(v) => {
const label = getLabel(v);
const rgb = getColor({ [component.iri]: label });
const hex = convertRgbArrayToHex(rgb);

return hex;
return rgbArrayToHex(rgb);
}}
getLabel={getLabel}
symbol="circle"
Expand Down
9 changes: 8 additions & 1 deletion app/components/hint.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,14 @@ export const LoadingDataError = ({ message }: { message?: string }) => (
</Link>

{message ? (
<pre style={{ marginTop: "0.5rem", marginLeft: "1rem", marginBottom: 0 }}>
<pre
style={{
marginTop: "0.5rem",
marginLeft: "1rem",
marginBottom: 0,
whiteSpace: "pre-wrap",
}}
>
{message}
</pre>
) : null}
Expand Down
17 changes: 7 additions & 10 deletions app/configurator/components/chart-controls/color-picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ export const ColorPicker = ({ selectedColor, colors, onChange }: Props) => {
setInputColorValue(_color);
// Make sure onChange is only called with valid colors
const c = d3Color(_color);

if (c) {
// Type defs of d3-color are not up-to-date
onChange?.((c as $Unexpressable).formatHex());
onChange?.(_color);
}
},
[onChange, setInputColorValue]
Expand All @@ -73,9 +73,9 @@ export const ColorPicker = ({ selectedColor, colors, onChange }: Props) => {
(_color) => {
// Make sure onChange is only called with valid colors
const c = d3Color(_color);

if (c) {
// Type defs of d3-color are not up-to-date
setInputColorValue((c as $Unexpressable).formatHex());
setInputColorValue(_color);
}
},
[setInputColorValue]
Expand All @@ -94,7 +94,6 @@ export const ColorPicker = ({ selectedColor, colors, onChange }: Props) => {
<Box
display="grid"
sx={{
// width: 120,
gridTemplateColumns: "repeat(auto-fill, minmax(1.5rem, 1fr))",
gap: 2,
mb: 2,
Expand All @@ -120,10 +119,7 @@ export const ColorPicker = ({ selectedColor, colors, onChange }: Props) => {
fontSize: "0.875rem",
":focus": { outline: "none", borderColor: "primary" },
}}
inputProps={{
maxLength: 7,
}}
value={`#${inputColorValue.replace(/^#/, "")}`}
value={inputColorValue}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
selectColor(e.currentTarget.value);
}}
Expand Down Expand Up @@ -166,6 +162,7 @@ export const ColorPickerMenu = (props: Props) => {
const borderColor = d3Color(selectedColor)?.darker().toString();
const { isOpen, open, close } = useDisclosure();
const buttonRef = useRef(null);

return (
<ColorPickerBox
sx={{
Expand All @@ -192,7 +189,7 @@ export const ColorPickerMenu = (props: Props) => {
width: "1rem",
height: "1rem",
}}
></Box>
/>
</Box>
</ColorPickerButton>
<Popover anchorEl={buttonRef.current} open={isOpen} onClose={close}>
Expand Down
2 changes: 1 addition & 1 deletion app/docs/rdf-to-visualize.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ called _Shared dimensions_, and their values will be fetched outside the cube.
| `?dimension cube:meta/dataKind schema:GeoCoordinates` | `dim.dataKind = "GeoCoordinates"` |
| `?dimension cube:meta/dataKind schema:GeoShape` | `dim.dataKind = "GeoShape"` |

ℹ️ Temporal dimensions can be interactively filtered with a _time range slider_
ℹ️ Temporal dimensions can be interactively filtered with a _time range slider_. **Important note**: in order to be able to properly parse temporal dimension, make sure it's scale it set to Interval!

ℹ️ GeoCoordinates dimensions can be shown on a map as _points_

Expand Down
10 changes: 9 additions & 1 deletion app/graphql/resolvers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,15 @@ export const resolvers: Resolvers = {
TemporalDimension: {
...mkDimensionResolvers("TemporalDimension"),
timeUnit: ({ data: { timeUnit } }) => timeUnit!,
timeFormat: ({ data: { timeFormat } }) => timeFormat!,
timeFormat: ({ data }) => {
if (data.timeFormat === undefined) {
throw new Error(
`Time format couldn't be retrieved for ${data.name}. Make sure it's set up properly in the Cube Creator – if it is, make sure that the interval scale is selected for this dimension (or remove time description if it's not a temporal dimension).`
);
}

return data.timeFormat;
},
},
GeoCoordinatesDimension: {
...mkDimensionResolvers("GeoCoordinatesDimension"),
Expand Down

0 comments on commit 0e9a664

Please sign in to comment.