Skip to content

Commit 46cc441

Browse files
authored
[fix] fix for a crash in getBins when numeric strings are treated as numbers (#3175)
* [fix] fix for a crash in getBins when numeric strings are treated as numbers Signed-off-by: Ihor Dykhta <[email protected]> * nit Signed-off-by: Ihor Dykhta <[email protected]> * nit Signed-off-by: Ihor Dykhta <[email protected]> --------- Signed-off-by: Ihor Dykhta <[email protected]>
1 parent 0850ef2 commit 46cc441

File tree

1 file changed

+22
-9
lines changed

1 file changed

+22
-9
lines changed

src/components/src/side-panel/layer-panel/color-scale-selector.tsx

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
getLegendOfScale,
1414
initCustomPaletteByCustomScale,
1515
histogramFromValues,
16+
histogramFromOrdinal,
1617
histogramFromThreshold,
1718
getHistogramDomain,
1819
hasColorMap
@@ -176,8 +177,17 @@ function ColorScaleSelectorFactory(
176177
: idx => dataset.dataContainer.rowAsArray(idx);
177178
}, [dataset, field]);
178179

180+
const ordinalDomain = useMemo(() => {
181+
return layer.config[layer.visualChannels[channelKey].domain] || [];
182+
}, [channelKey, layer.config, layer.visualChannels]);
183+
179184
// aggregatedBins should be the raw data
180185
const allBins = useMemo(() => {
186+
if (field?.type === ALL_FIELD_TYPES.string) {
187+
// Use ordinal bins for string columns, as d3 could potentially generate invalid numeric bins, and crash
188+
return histogramFromOrdinal(ordinalDomain, dataset.allIndexes, fieldValueAccessor);
189+
}
190+
181191
if (aggregatedBins) {
182192
return histogramFromValues(
183193
Object.values(aggregatedBins).map(bin => bin.i),
@@ -188,16 +198,12 @@ function ColorScaleSelectorFactory(
188198
return columnStats?.bins
189199
? columnStats?.bins
190200
: histogramFromValues(dataset.allIndexes, HISTOGRAM_BINS, fieldValueAccessor);
191-
}, [aggregatedBins, columnStats, dataset, fieldValueAccessor]);
201+
}, [aggregatedBins, columnStats, dataset, fieldValueAccessor, field?.type, ordinalDomain]);
192202

193203
const histogramDomain = useMemo(() => {
194204
return getHistogramDomain({aggregatedBins, columnStats, dataset, fieldValueAccessor});
195205
}, [dataset, fieldValueAccessor, aggregatedBins, columnStats]);
196206

197-
const ordinalDomain = useMemo(() => {
198-
return layer.config[layer.visualChannels[channelKey].domain] || [];
199-
}, [channelKey, layer.config, layer.visualChannels]);
200-
201207
const isFiltered = aggregatedBins
202208
? false
203209
: dataset.filteredIndexForDomain.length !== dataset.allIndexes.length;
@@ -207,16 +213,23 @@ function ColorScaleSelectorFactory(
207213
if (!isFiltered) {
208214
return allBins;
209215
}
210-
// get threholds
216+
if (field?.type === ALL_FIELD_TYPES.string) {
217+
return histogramFromOrdinal(
218+
ordinalDomain as any,
219+
dataset.filteredIndexForDomain,
220+
fieldValueAccessor
221+
);
222+
}
223+
// numeric thresholds
211224
const filterEmptyBins = false;
212-
const threholds = allBins.map(b => b.x0);
225+
const thresholds = allBins.map(b => b.x0);
213226
return histogramFromThreshold(
214-
threholds,
227+
thresholds,
215228
dataset.filteredIndexForDomain,
216229
fieldValueAccessor,
217230
filterEmptyBins
218231
);
219-
}, [dataset, fieldValueAccessor, allBins, isFiltered]);
232+
}, [dataset, fieldValueAccessor, allBins, isFiltered, field?.type, ordinalDomain]);
220233

221234
const onSelectScale = useCallback(
222235
val => {

0 commit comments

Comments
 (0)