@carto/kepler.gl 0.0.33 → 0.0.34-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/index.js +25 -2
- package/dist/components/side-panel/layer-panel/color-dimension-scale-selector.js +45 -0
- package/dist/components/side-panel/layer-panel/layer-configurator.js +108 -33
- package/dist/components/side-panel/layer-panel/vis-config-by-field-selector.js +20 -5
- package/dist/constants/default-settings.js +12 -9
- package/dist/constants/index.js +7 -1
- package/dist/deckgl-layers/layer-utils/cpu-aggregator.js +12 -9
- package/dist/layers/aggregation-layer.js +23 -1
- package/dist/layers/base-layer.js +119 -4
- package/dist/layers/cluster-layer/cluster-layer.js +2 -1
- package/dist/utils/data-scale-utils.js +2 -2
- package/dist/utils/data-utils.js +19 -1
- package/package.json +1 -1
- package/src/components/index.js +5 -0
- package/src/components/side-panel/layer-panel/color-dimension-scale-selector.js +33 -0
- package/src/components/side-panel/layer-panel/layer-configurator.js +103 -23
- package/src/components/side-panel/layer-panel/vis-config-by-field-selector.js +26 -3
- package/src/constants/default-settings.js +21 -13
- package/src/constants/index.js +2 -1
- package/src/deckgl-layers/layer-utils/cpu-aggregator.js +25 -8
- package/src/layers/aggregation-layer.js +19 -1
- package/src/layers/base-layer.js +82 -6
- package/src/layers/cluster-layer/cluster-layer.js +1 -0
- package/src/utils/data-scale-utils.js +2 -4
- package/src/utils/data-utils.d.ts +1 -0
- package/src/utils/data-utils.js +14 -0
- package/umd/keplergl.min.js +31 -31
|
@@ -28,7 +28,8 @@ import {
|
|
|
28
28
|
scaleOrdinal,
|
|
29
29
|
scaleSqrt,
|
|
30
30
|
scaleLog,
|
|
31
|
-
scalePoint
|
|
31
|
+
scalePoint,
|
|
32
|
+
scaleThreshold
|
|
32
33
|
} from 'd3-scale';
|
|
33
34
|
import {
|
|
34
35
|
Layers,
|
|
@@ -306,7 +307,8 @@ export const SCALE_TYPES = keyMirror({
|
|
|
306
307
|
log: null,
|
|
307
308
|
|
|
308
309
|
// ordinal domain to linear range
|
|
309
|
-
point: null
|
|
310
|
+
point: null,
|
|
311
|
+
custom: null
|
|
310
312
|
});
|
|
311
313
|
|
|
312
314
|
export const SCALE_FUNC = {
|
|
@@ -316,7 +318,8 @@ export const SCALE_FUNC = {
|
|
|
316
318
|
[SCALE_TYPES.ordinal]: scaleOrdinal,
|
|
317
319
|
[SCALE_TYPES.sqrt]: scaleSqrt,
|
|
318
320
|
[SCALE_TYPES.log]: scaleLog,
|
|
319
|
-
[SCALE_TYPES.point]: scalePoint
|
|
321
|
+
[SCALE_TYPES.point]: scalePoint,
|
|
322
|
+
[SCALE_TYPES.custom]: scaleThreshold
|
|
320
323
|
};
|
|
321
324
|
|
|
322
325
|
export const ALL_FIELD_TYPES = keyMirror({
|
|
@@ -449,20 +452,20 @@ export const AGGREGATION_TYPES = {
|
|
|
449
452
|
};
|
|
450
453
|
|
|
451
454
|
export const linearFieldScaleFunctions = {
|
|
452
|
-
[CHANNEL_SCALES.color]: [SCALE_TYPES.quantize, SCALE_TYPES.quantile],
|
|
455
|
+
[CHANNEL_SCALES.color]: [SCALE_TYPES.quantize, SCALE_TYPES.quantile, SCALE_TYPES.custom],
|
|
453
456
|
[CHANNEL_SCALES.radius]: [SCALE_TYPES.sqrt],
|
|
454
457
|
[CHANNEL_SCALES.size]: [SCALE_TYPES.linear, SCALE_TYPES.sqrt, SCALE_TYPES.log]
|
|
455
458
|
};
|
|
456
459
|
|
|
457
460
|
export const linearFieldAggrScaleFunctions = {
|
|
458
461
|
[CHANNEL_SCALES.colorAggr]: {
|
|
459
|
-
[AGGREGATION_TYPES.average]: [SCALE_TYPES.quantize, SCALE_TYPES.quantile],
|
|
460
|
-
[AGGREGATION_TYPES.maximum]: [SCALE_TYPES.quantize, SCALE_TYPES.quantile],
|
|
461
|
-
[AGGREGATION_TYPES.minimum]: [SCALE_TYPES.quantize, SCALE_TYPES.quantile],
|
|
462
|
-
[AGGREGATION_TYPES.median]: [SCALE_TYPES.quantize, SCALE_TYPES.quantile],
|
|
463
|
-
[AGGREGATION_TYPES.stdev]: [SCALE_TYPES.quantize, SCALE_TYPES.quantile],
|
|
464
|
-
[AGGREGATION_TYPES.sum]: [SCALE_TYPES.quantize, SCALE_TYPES.quantile],
|
|
465
|
-
[AGGREGATION_TYPES.variance]: [SCALE_TYPES.quantize, SCALE_TYPES.quantile]
|
|
462
|
+
[AGGREGATION_TYPES.average]: [SCALE_TYPES.quantize, SCALE_TYPES.quantile, SCALE_TYPES.custom],
|
|
463
|
+
[AGGREGATION_TYPES.maximum]: [SCALE_TYPES.quantize, SCALE_TYPES.quantile, SCALE_TYPES.custom],
|
|
464
|
+
[AGGREGATION_TYPES.minimum]: [SCALE_TYPES.quantize, SCALE_TYPES.quantile, SCALE_TYPES.custom],
|
|
465
|
+
[AGGREGATION_TYPES.median]: [SCALE_TYPES.quantize, SCALE_TYPES.quantile, SCALE_TYPES.custom],
|
|
466
|
+
[AGGREGATION_TYPES.stdev]: [SCALE_TYPES.quantize, SCALE_TYPES.quantile, SCALE_TYPES.custom],
|
|
467
|
+
[AGGREGATION_TYPES.sum]: [SCALE_TYPES.quantize, SCALE_TYPES.quantile, SCALE_TYPES.custom],
|
|
468
|
+
[AGGREGATION_TYPES.variance]: [SCALE_TYPES.quantize, SCALE_TYPES.quantile, SCALE_TYPES.custom]
|
|
466
469
|
},
|
|
467
470
|
|
|
468
471
|
[CHANNEL_SCALES.sizeAggr]: {
|
|
@@ -486,7 +489,11 @@ export const ordinalFieldAggrScaleFunctions = {
|
|
|
486
489
|
// [CHANNEL_SCALES.colorAggr]: [SCALE_TYPES.ordinal, SCALE_TYPES.linear],
|
|
487
490
|
[CHANNEL_SCALES.colorAggr]: {
|
|
488
491
|
[AGGREGATION_TYPES.mode]: [SCALE_TYPES.ordinal],
|
|
489
|
-
[AGGREGATION_TYPES.countUnique]: [
|
|
492
|
+
[AGGREGATION_TYPES.countUnique]: [
|
|
493
|
+
SCALE_TYPES.quantize,
|
|
494
|
+
SCALE_TYPES.quantile,
|
|
495
|
+
SCALE_TYPES.custom
|
|
496
|
+
]
|
|
490
497
|
},
|
|
491
498
|
|
|
492
499
|
// Currently doesn't support yet
|
|
@@ -509,7 +516,7 @@ export const notSupportAggrOpts = {
|
|
|
509
516
|
*/
|
|
510
517
|
export const DEFAULT_AGGREGATION = {
|
|
511
518
|
[CHANNEL_SCALES.colorAggr]: {
|
|
512
|
-
[AGGREGATION_TYPES.count]: [SCALE_TYPES.quantize, SCALE_TYPES.quantile]
|
|
519
|
+
[AGGREGATION_TYPES.count]: [SCALE_TYPES.quantize, SCALE_TYPES.quantile, SCALE_TYPES.custom]
|
|
513
520
|
},
|
|
514
521
|
[CHANNEL_SCALES.sizeAggr]: {
|
|
515
522
|
[AGGREGATION_TYPES.count]: [SCALE_TYPES.linear, SCALE_TYPES.sqrt, SCALE_TYPES.log]
|
|
@@ -629,6 +636,7 @@ export const DEFAULT_LAYER_COLOR = {
|
|
|
629
636
|
export const DEFAULT_TOOLTIP_FIELDS = [];
|
|
630
637
|
|
|
631
638
|
export const NO_VALUE_COLOR = [0, 0, 0, 0];
|
|
639
|
+
export const UNKNOWN_COLOR = [134, 141, 145];
|
|
632
640
|
|
|
633
641
|
export const LAYER_BLENDINGS = {
|
|
634
642
|
additive: {
|
package/src/constants/index.js
CHANGED
|
@@ -23,7 +23,12 @@ import {AGGREGATION_OPERATION, _BinSorter as BinSorter} from '@deck.gl/aggregati
|
|
|
23
23
|
import {console as Console} from 'global/window';
|
|
24
24
|
|
|
25
25
|
import {aggregate} from 'utils/aggregate-utils';
|
|
26
|
-
import {
|
|
26
|
+
import {
|
|
27
|
+
AGGREGATION_TYPES,
|
|
28
|
+
SCALE_FUNC,
|
|
29
|
+
UNKNOWN_COLOR,
|
|
30
|
+
SCALE_TYPES
|
|
31
|
+
} from 'constants/default-settings';
|
|
27
32
|
|
|
28
33
|
export const DECK_AGGREGATION_MAP = {
|
|
29
34
|
[AGGREGATION_OPERATION.SUM]: AGGREGATION_TYPES.sum,
|
|
@@ -97,7 +102,10 @@ export function getDimensionValueDomain(step, props, dimensionUpdater) {
|
|
|
97
102
|
[props[lowerPercentile.prop], props[upperPercentile.prop]]
|
|
98
103
|
);
|
|
99
104
|
|
|
100
|
-
this._setDimensionState(key, {
|
|
105
|
+
this._setDimensionState(key, {
|
|
106
|
+
// By default sortedBins order by ascending frecuency but if we've an ordinal scale we want to order by descending frecuency
|
|
107
|
+
valueDomain: props[scaleType.prop] === SCALE_TYPES.ordinal ? valueDomain.reverse() : valueDomain
|
|
108
|
+
});
|
|
101
109
|
}
|
|
102
110
|
|
|
103
111
|
export function getDimensionScale(step, props, dimensionUpdater) {
|
|
@@ -112,12 +120,20 @@ export function getDimensionScale(step, props, dimensionUpdater) {
|
|
|
112
120
|
const dimensionRange = props[range.prop];
|
|
113
121
|
const dimensionDomain = props[domain.prop] || this.state.dimensions[key].valueDomain;
|
|
114
122
|
|
|
115
|
-
const
|
|
123
|
+
const scaleTypeProp = scaleType && props[scaleType.prop];
|
|
124
|
+
const scaleFunctor = getScaleFunctor(scaleTypeProp)();
|
|
116
125
|
|
|
117
|
-
const scaleFunc = scaleFunctor
|
|
126
|
+
const scaleFunc = scaleFunctor
|
|
127
|
+
.domain(
|
|
128
|
+
scaleTypeProp === SCALE_TYPES.ordinal
|
|
129
|
+
? dimensionDomain.slice(0, dimensionRange.length)
|
|
130
|
+
: dimensionDomain
|
|
131
|
+
)
|
|
132
|
+
.range(dimensionRange)
|
|
133
|
+
.unknown(UNKNOWN_COLOR);
|
|
118
134
|
|
|
119
135
|
if (typeof onSet === 'object' && typeof props[onSet.props] === 'function') {
|
|
120
|
-
props[onSet.props](
|
|
136
|
+
props[onSet.props](this.state.dimensions[key].valueDomain);
|
|
121
137
|
}
|
|
122
138
|
this._setDimensionState(key, {scaleFunc});
|
|
123
139
|
}
|
|
@@ -180,12 +196,13 @@ function getSubLayerAccessor(dimensionState, dimension, layerProps) {
|
|
|
180
196
|
}
|
|
181
197
|
|
|
182
198
|
const cv = bin && bin.value;
|
|
183
|
-
const domain = scaleFunc.domain();
|
|
199
|
+
// const domain = scaleFunc.domain();
|
|
184
200
|
|
|
185
|
-
const isValueInDomain = cv >= domain[0] && cv <= domain[domain.length - 1];
|
|
201
|
+
// const isValueInDomain = cv >= domain[0] && cv <= domain[domain.length - 1];
|
|
186
202
|
|
|
187
203
|
// if cell value is outside domain, set alpha to 0
|
|
188
|
-
return isValueInDomain ? scaleFunc(cv) : dimension.nullValue;
|
|
204
|
+
// return isValueInDomain ? scaleFunc(cv) : dimension.nullValue;
|
|
205
|
+
return scaleFunc(cv);
|
|
189
206
|
};
|
|
190
207
|
}
|
|
191
208
|
|
|
@@ -53,7 +53,23 @@ export const getValueAggrFunc = (field, aggregation) => {
|
|
|
53
53
|
export const getFilterDataFunc = (filterRange, getFilterValue) => pt =>
|
|
54
54
|
getFilterValue(pt).every((val, i) => val >= filterRange[i][0] && val <= filterRange[i][1]);
|
|
55
55
|
|
|
56
|
-
const getLayerColorRange = colorRange =>
|
|
56
|
+
const getLayerColorRange = colorRange => {
|
|
57
|
+
const {colorMap} = colorRange;
|
|
58
|
+
|
|
59
|
+
if (colorMap) {
|
|
60
|
+
return colorMap.map(cMap => hexToRgb(cMap[1]));
|
|
61
|
+
}
|
|
62
|
+
return colorRange.colors.map(hexToRgb);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const getLayerColorDomain = colorDomain => {
|
|
66
|
+
const {colorMap} = colorDomain;
|
|
67
|
+
|
|
68
|
+
if (colorMap) {
|
|
69
|
+
return colorMap.map(cMap => cMap[0]);
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
};
|
|
57
73
|
|
|
58
74
|
export const aggregateRequiredColumns = ['lat', 'lng'];
|
|
59
75
|
|
|
@@ -64,6 +80,7 @@ export default class AggregationLayer extends Layer {
|
|
|
64
80
|
this.getPositionAccessor = dataContainer =>
|
|
65
81
|
pointPosAccessor(this.config.columns)(dataContainer);
|
|
66
82
|
this.getColorRange = memoize(getLayerColorRange);
|
|
83
|
+
this.getColorDomain = memoize(getLayerColorDomain);
|
|
67
84
|
}
|
|
68
85
|
|
|
69
86
|
get isAggregated() {
|
|
@@ -315,6 +332,7 @@ export default class AggregationLayer extends Layer {
|
|
|
315
332
|
|
|
316
333
|
// color
|
|
317
334
|
colorRange: this.getColorRange(visConfig.colorRange),
|
|
335
|
+
colorDomain: this.getColorDomain(visConfig.colorRange),
|
|
318
336
|
colorScaleType: this.config.colorScale,
|
|
319
337
|
upperPercentile: visConfig.percentile[1],
|
|
320
338
|
lowerPercentile: visConfig.percentile[0],
|
package/src/layers/base-layer.js
CHANGED
|
@@ -35,7 +35,8 @@ import {
|
|
|
35
35
|
FIELD_OPTS,
|
|
36
36
|
SCALE_FUNC,
|
|
37
37
|
CHANNEL_SCALE_SUPPORTED_FIELDS,
|
|
38
|
-
MAX_GPU_FILTERS
|
|
38
|
+
MAX_GPU_FILTERS,
|
|
39
|
+
UNKNOWN_COLOR
|
|
39
40
|
} from 'constants/default-settings';
|
|
40
41
|
import {COLOR_RANGES} from 'constants/color-ranges';
|
|
41
42
|
import {DataVizColors} from 'constants/custom-color-ranges';
|
|
@@ -43,7 +44,6 @@ import {
|
|
|
43
44
|
LAYER_VIS_CONFIGS,
|
|
44
45
|
DEFAULT_TEXT_LABEL,
|
|
45
46
|
DEFAULT_COLOR_UI,
|
|
46
|
-
UNKNOWN_COLOR_KEY,
|
|
47
47
|
DEFAULT_HIGHLIGHT_COLOR,
|
|
48
48
|
DEFAULT_LAYER_LABEL
|
|
49
49
|
} from './layer-factory';
|
|
@@ -636,6 +636,7 @@ class Layer {
|
|
|
636
636
|
});
|
|
637
637
|
}
|
|
638
638
|
|
|
639
|
+
// eslint-disable-next-line complexity
|
|
639
640
|
updateColorRangeByColorUI(newConfig, previous, prop) {
|
|
640
641
|
// only update colorRange if changes in UI is made to 'reversed', 'steps' or steps
|
|
641
642
|
const shouldUpdate =
|
|
@@ -664,6 +665,10 @@ class Layer {
|
|
|
664
665
|
if (update && colorRange.reversed) {
|
|
665
666
|
update = reverseColorRange(true, update);
|
|
666
667
|
}
|
|
668
|
+
|
|
669
|
+
if (update && colorRange.colorMap) {
|
|
670
|
+
update = this.updateColorMap(prop, colorRange.colorMap, update);
|
|
671
|
+
}
|
|
667
672
|
}
|
|
668
673
|
}
|
|
669
674
|
|
|
@@ -676,6 +681,69 @@ class Layer {
|
|
|
676
681
|
}
|
|
677
682
|
}
|
|
678
683
|
|
|
684
|
+
updateColorMap(prop, colorMap, colorRange) {
|
|
685
|
+
// @ts-ignore
|
|
686
|
+
const {field, domain} = Object.values(this.visualChannels).find(value => value.range === prop);
|
|
687
|
+
const type = this.config[field]?.type;
|
|
688
|
+
|
|
689
|
+
if (type === 'string' || type === 'boolean' || type === 'date') {
|
|
690
|
+
return this.updateCategoryColorMap(colorMap, this.config[domain], colorRange);
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
// If no type or type is not string, boolean or date
|
|
694
|
+
return this.updateNumericColorMap(colorMap, this.config[domain], colorRange);
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
updateCategoryColorMap(colorMap, domain, colorRange) {
|
|
698
|
+
const colors = colorRange.colors;
|
|
699
|
+
const assignedCategories = [];
|
|
700
|
+
const newColorMap = colorMap.slice(0, colors.length).map((cMap, index) => {
|
|
701
|
+
assignedCategories.push(cMap[0]);
|
|
702
|
+
return [cMap[0], colors[index]];
|
|
703
|
+
});
|
|
704
|
+
const unassignedColors = colors.slice(newColorMap.length, colors.length);
|
|
705
|
+
|
|
706
|
+
for (const color of unassignedColors) {
|
|
707
|
+
const category = domain.find(d => !assignedCategories.includes(d));
|
|
708
|
+
if (!category) {
|
|
709
|
+
break;
|
|
710
|
+
}
|
|
711
|
+
assignedCategories.push(category);
|
|
712
|
+
newColorMap.push([category, color]);
|
|
713
|
+
}
|
|
714
|
+
return {
|
|
715
|
+
...colorRange,
|
|
716
|
+
colorMap: newColorMap
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
updateNumericColorMap(colorMap, domain, update) {
|
|
721
|
+
const colors = update.colors;
|
|
722
|
+
let newColorMap = colorMap.slice(0, colors.length);
|
|
723
|
+
|
|
724
|
+
newColorMap = newColorMap.map((cMap, index) => {
|
|
725
|
+
const value = index === newColorMap.length - 1 ? null : cMap[0];
|
|
726
|
+
return [value, colors[index]];
|
|
727
|
+
});
|
|
728
|
+
const unassignedColors = colors.slice(newColorMap.length, colors.length);
|
|
729
|
+
|
|
730
|
+
if (unassignedColors.length > 0) {
|
|
731
|
+
const maxValue = domain[domain.length - 1];
|
|
732
|
+
const prevValue = newColorMap[newColorMap.length - 2][0];
|
|
733
|
+
const step = (maxValue - prevValue) / (unassignedColors.length + 1);
|
|
734
|
+
newColorMap[newColorMap.length - 1][0] = prevValue + step;
|
|
735
|
+
|
|
736
|
+
for (const [i, color] of unassignedColors.entries()) {
|
|
737
|
+
const value = i === unassignedColors.length - 1 ? null : prevValue + (step * (i + 2));
|
|
738
|
+
newColorMap.push([value, color]);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
return {
|
|
742
|
+
...update,
|
|
743
|
+
colorMap: newColorMap
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
|
|
679
747
|
/**
|
|
680
748
|
* Check whether layer has all columns
|
|
681
749
|
* @returns {boolean} yes or no
|
|
@@ -724,10 +792,10 @@ class Layer {
|
|
|
724
792
|
});
|
|
725
793
|
|
|
726
794
|
// @ts-ignore d3 scale
|
|
727
|
-
const scale = SCALE_FUNC[
|
|
728
|
-
.domain(cMap.keys())
|
|
729
|
-
.range(cMap.values())
|
|
730
|
-
.unknown(
|
|
795
|
+
const scale = SCALE_FUNC[colorScale]()
|
|
796
|
+
.domain(Array.from(cMap.keys()))
|
|
797
|
+
.range(Array.from(cMap.values()))
|
|
798
|
+
.unknown(UNKNOWN_COLOR);
|
|
731
799
|
return scale;
|
|
732
800
|
}
|
|
733
801
|
|
|
@@ -795,6 +863,14 @@ class Layer {
|
|
|
795
863
|
}
|
|
796
864
|
|
|
797
865
|
getVisChannelScale(scale, domain, range, fixed) {
|
|
866
|
+
if (scale === SCALE_TYPES.ordinal) {
|
|
867
|
+
// @ts-ignore d3-scale type
|
|
868
|
+
return SCALE_FUNC[scale]()
|
|
869
|
+
.domain(domain.slice(0, range.length))
|
|
870
|
+
.range(range)
|
|
871
|
+
.unknown(UNKNOWN_COLOR);
|
|
872
|
+
}
|
|
873
|
+
|
|
798
874
|
// @ts-ignore d3-scale type
|
|
799
875
|
return SCALE_FUNC[fixed ? 'linear' : scale]()
|
|
800
876
|
.domain(domain)
|
|
@@ -93,6 +93,7 @@ export default class ClusterLayer extends AggregationLayer {
|
|
|
93
93
|
|
|
94
94
|
// color
|
|
95
95
|
colorRange: this.getColorRange(visConfig.colorRange),
|
|
96
|
+
colorDomain: this.getColorDomain(visConfig.colorRange),
|
|
96
97
|
colorScaleType: this.config.colorScale,
|
|
97
98
|
colorAggregation: visConfig.colorAggregation,
|
|
98
99
|
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
import {notNullorUndefined, unique} from './data-utils';
|
|
22
22
|
import {extent} from 'd3-array';
|
|
23
|
+
import {uniqueSortedByFrequency} from './data-utils';
|
|
23
24
|
|
|
24
25
|
/**
|
|
25
26
|
* return quantile domain for an array of data
|
|
@@ -37,10 +38,7 @@ export function getQuantileDomain(data, valueAccessor, sortFunc) {
|
|
|
37
38
|
*/
|
|
38
39
|
export function getOrdinalDomain(dataContainer, valueAccessor) {
|
|
39
40
|
const values = dataContainer.mapIndex(valueAccessor);
|
|
40
|
-
|
|
41
|
-
return unique(values)
|
|
42
|
-
.filter(notNullorUndefined)
|
|
43
|
-
.sort();
|
|
41
|
+
return uniqueSortedByFrequency(values);
|
|
44
42
|
}
|
|
45
43
|
|
|
46
44
|
/**
|
|
@@ -12,6 +12,7 @@ export function isNumber(d: any): boolean;
|
|
|
12
12
|
export function isPlainObject(d: any): boolean;
|
|
13
13
|
export function numberSort(a: any, b: any): any;
|
|
14
14
|
export function unique(values: any[]): any[];
|
|
15
|
+
export function uniqueSortedByFrequency(values: any[]): any[];
|
|
15
16
|
export function arrayMove(array: any[], from: number, to: number);
|
|
16
17
|
export function getSortingFunction(fieldType: string): numberSort | undefined;
|
|
17
18
|
export function preciseRound(num: number, decimals: number): string;
|
package/src/utils/data-utils.js
CHANGED
|
@@ -47,6 +47,20 @@ export function unique(values) {
|
|
|
47
47
|
return results;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
export function uniqueSortedByFrequency(values) {
|
|
51
|
+
const frequency = values.reduce((res, value) => {
|
|
52
|
+
if (notNullorUndefined(value)) {
|
|
53
|
+
if (!res[value]) {
|
|
54
|
+
res[value] = 0;
|
|
55
|
+
}
|
|
56
|
+
res[value] += 1;
|
|
57
|
+
}
|
|
58
|
+
return res;
|
|
59
|
+
}, {});
|
|
60
|
+
|
|
61
|
+
return Object.keys(frequency).sort((a, b) => frequency[b] - frequency[a]);
|
|
62
|
+
}
|
|
63
|
+
|
|
50
64
|
/* eslint-disable max-statements */
|
|
51
65
|
/**
|
|
52
66
|
* return center of map from given points
|