Skip to content

Commit

Permalink
fix(bar,summary,xyplot): safely stringify null and undefined cells wh…
Browse files Browse the repository at this point in the history
…en finding unique values

Previously, there would be runtime errors if users switched to columns with cell values that lacked
a toString() method

BREAKING CHANGE: App does not crash when columns contain cell values that do not have toString()
inside, such as "undefined" or "null"
  • Loading branch information
hydrosquall committed Jul 11, 2021
1 parent 741fb67 commit 1b84808
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 28 deletions.
12 changes: 2 additions & 10 deletions src/charts/bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import TooltipContent, { safeDisplayValue } from "../utilities/tooltip-content";
import { numeralFormatting } from "../utilities/utilities";

import * as Dx from "../utilities/types";
import { sortByOrdinalRange } from "./shared";
import { sortByOrdinalRange, getUniqueValues } from "./shared";

interface BarOptions {
selectedDimensions: string[];
Expand Down Expand Up @@ -112,15 +112,7 @@ export const semioticBarChart = (
};
}

const uniqueValues = sortedData.reduce(
(uniques, datapoint) =>
!uniques.find(
(uniqueDimName: string) => uniqueDimName === datapoint[dim1].toString(),
)
? [...uniques, datapoint[dim1].toString()]
: uniques,
[],
);
const uniqueValues = dim1 === "none" ? [] : getUniqueValues(sortedData, dim1);

if (!colorHashOverride && dim1 && dim1 !== "none") {
uniqueValues.forEach((value: string, index: number) => {
Expand Down
21 changes: 20 additions & 1 deletion src/charts/shared.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const sortByOrdinalRange = (
rAccessor: string | (() => void),
secondarySort: string,
data: Dx.DataProps["data"],
): any[] => {
): Dx.DataProps["data"] => {
const subsortData: { [index: string]: SubsortObject } = {};
let subsortArrays: SubsortObject[] = [];
data.forEach((datapoint) => {
Expand Down Expand Up @@ -65,3 +65,22 @@ export const sortByOrdinalRange = (
[],
);
};

/*
Returns uniques values in a column as strings
Safely stringifies different data types, including null/undefined.
*/
export const getUniqueValues = (
points: Dx.DataProps["data"],
accessor: string,
): string[] => {
return [
...new Set(
points.map((d) => {
const value = d[accessor];
// Don't call stringify on a string, as it will add "quote" marks around your value.
return typeof value === "string" ? value : JSON.stringify(value);
}),
),
];
};
10 changes: 2 additions & 8 deletions src/charts/summary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import HTMLLegend from "../components/HTMLLegend";
import TooltipContent, { safeDisplayValue } from "../utilities/tooltip-content";
import * as Dx from "../utilities/types";
import { numeralFormatting } from "../utilities/utilities";
import { getUniqueValues } from "./shared";

interface SummaryOptions {
chart: Dx.Chart;
Expand Down Expand Up @@ -37,14 +38,7 @@ export const semioticSummaryChart = (

const rAccessor = metric1;

const uniqueValues = data.reduce(
(uniqueArray: string[], datapoint) =>
(!uniqueArray.find(
(dimValue: string) => dimValue === datapoint[dim1].toString(),
) && [...uniqueArray, datapoint[dim1].toString()]) ||
uniqueArray,
[],
);
const uniqueValues = dim1 === "none" ? [] : getUniqueValues(data, dim1);

if (!colorHashOverride && dim1 && dim1 !== "none") {
uniqueValues.sort().forEach((dimValue, index) => {
Expand Down
11 changes: 2 additions & 9 deletions src/charts/xyplot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import TooltipContent from "../utilities/tooltip-content";
import { numeralFormatting } from "../utilities/utilities";

import * as Dx from "../utilities/types";
import { sortByOrdinalRange } from "./shared";
import { sortByOrdinalRange, getUniqueValues } from "./shared";

import styled from "styled-components";

Expand Down Expand Up @@ -253,14 +253,7 @@ export const semioticXYPlot = (
dim1 &&
dim1 !== "none"
) {
const uniqueValues = sortedData.reduce(
(uniqueArray, datapoint) =>
(!uniqueArray.find(
(uniqueDim: string) => uniqueDim === datapoint[dim1].toString(),
) && [...uniqueArray, datapoint[dim1].toString()]) ||
uniqueArray,
[],
);
const uniqueValues = getUniqueValues(sortedData, dim1);

if (!colorHashOverride) {
uniqueValues.sort().forEach((dimValue: string, index: number) => {
Expand Down

0 comments on commit 1b84808

Please sign in to comment.