@kanaries/graphic-walker 0.4.1 → 0.4.3
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/App.d.ts +5 -1
- package/dist/assets/buildMetricTable.worker-5555966a.js.map +1 -0
- package/dist/components/leafletRenderer/ChoroplethRenderer.d.ts +22 -0
- package/dist/components/leafletRenderer/POIRenderer.d.ts +20 -0
- package/dist/components/leafletRenderer/encodings.d.ts +7 -0
- package/dist/components/leafletRenderer/geoConfigPanel.d.ts +3 -0
- package/dist/components/leafletRenderer/index.d.ts +15 -0
- package/dist/components/leafletRenderer/tooltip.d.ts +9 -0
- package/dist/components/leafletRenderer/utils.d.ts +2 -0
- package/dist/components/pivotTable/index.d.ts +2 -1
- package/dist/components/pivotTable/inteface.d.ts +6 -2
- package/dist/components/pivotTable/leftTree.d.ts +1 -0
- package/dist/components/pivotTable/topTree.d.ts +2 -0
- package/dist/components/pivotTable/utils.d.ts +1 -2
- package/dist/config.d.ts +3 -2
- package/dist/graphic-walker.es.js +37811 -30386
- package/dist/graphic-walker.es.js.map +1 -1
- package/dist/graphic-walker.umd.js +145 -137
- package/dist/graphic-walker.umd.js.map +1 -1
- package/dist/interfaces.d.ts +28 -0
- package/dist/renderer/specRenderer.d.ts +2 -1
- package/dist/services.d.ts +7 -1
- package/dist/store/commonStore.d.ts +6 -0
- package/dist/store/visualSpecStore.d.ts +180 -4
- package/dist/utils/save.d.ts +1 -0
- package/dist/workers/buildPivotTable.d.ts +7 -0
- package/package.json +14 -2
- package/src/App.tsx +18 -4
- package/src/components/leafletRenderer/ChoroplethRenderer.tsx +312 -0
- package/src/components/leafletRenderer/POIRenderer.tsx +189 -0
- package/src/components/leafletRenderer/encodings.ts +194 -0
- package/src/components/leafletRenderer/geoConfigPanel.tsx +197 -0
- package/src/components/leafletRenderer/index.tsx +70 -0
- package/src/components/leafletRenderer/tooltip.tsx +24 -0
- package/src/components/leafletRenderer/utils.ts +52 -0
- package/src/components/pivotTable/index.tsx +171 -67
- package/src/components/pivotTable/inteface.ts +6 -2
- package/src/components/pivotTable/leftTree.tsx +24 -11
- package/src/components/pivotTable/metricTable.tsx +15 -10
- package/src/components/pivotTable/topTree.tsx +50 -17
- package/src/components/pivotTable/utils.ts +70 -11
- package/src/components/visualConfig/index.tsx +17 -1
- package/src/config.ts +27 -16
- package/src/dataSource/table.tsx +7 -11
- package/src/fields/aestheticFields.tsx +4 -0
- package/src/fields/fieldsContext.tsx +3 -0
- package/src/fields/posFields/index.tsx +8 -2
- package/src/global.d.ts +4 -4
- package/src/index.tsx +11 -9
- package/src/interfaces.ts +35 -0
- package/src/locales/en-US.json +27 -2
- package/src/locales/ja-JP.json +27 -2
- package/src/locales/zh-CN.json +27 -2
- package/src/renderer/hooks.ts +1 -1
- package/src/renderer/index.tsx +24 -1
- package/src/renderer/pureRenderer.tsx +27 -13
- package/src/renderer/specRenderer.tsx +46 -30
- package/src/services.ts +32 -23
- package/src/shadow-dom.tsx +7 -0
- package/src/store/commonStore.ts +29 -1
- package/src/store/visualSpecStore.ts +38 -23
- package/src/utils/save.ts +28 -1
- package/src/utils/vegaApiExport.ts +3 -0
- package/src/visualSettings/index.tsx +58 -6
- package/src/workers/buildMetricTable.worker.js +27 -0
- package/src/workers/buildPivotTable.ts +27 -0
package/src/store/commonStore.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DataSet, Filters, IDataSet, IDataSetInfo, IDataSource, IMutField, IRow, ISegmentKey } from '../interfaces';
|
|
2
2
|
import { makeAutoObservable, observable, toJS } from 'mobx';
|
|
3
3
|
import { transData } from '../dataSource/utils';
|
|
4
|
+
import { INestNode } from '../components/pivotTable/inteface';
|
|
4
5
|
|
|
5
6
|
export class CommonStore {
|
|
6
7
|
public datasets: IDataSet[] = [];
|
|
@@ -15,15 +16,18 @@ export class CommonStore {
|
|
|
15
16
|
public showDataConfig: boolean = false;
|
|
16
17
|
public showCodeExportPanel: boolean = false;
|
|
17
18
|
public showVisualConfigPanel: boolean = false;
|
|
19
|
+
public showGeoJSONConfigPanel: boolean = false;
|
|
18
20
|
public filters: Filters = {};
|
|
19
21
|
public segmentKey: ISegmentKey = ISegmentKey.vis;
|
|
22
|
+
public tableCollapsedHeaderMap: Map<string, INestNode["path"]> = new Map();
|
|
20
23
|
constructor () {
|
|
21
24
|
this.datasets = [];
|
|
22
25
|
this.dataSources = [];
|
|
23
26
|
makeAutoObservable(this, {
|
|
24
27
|
dataSources: observable.ref,
|
|
25
28
|
tmpDataSource: observable.ref,
|
|
26
|
-
filters: observable.ref
|
|
29
|
+
filters: observable.ref,
|
|
30
|
+
tableCollapsedHeaderMap: observable.ref,
|
|
27
31
|
});
|
|
28
32
|
}
|
|
29
33
|
public get currentDataset (): DataSet {
|
|
@@ -68,6 +72,30 @@ export class CommonStore {
|
|
|
68
72
|
public setShowVisualConfigPanel (show: boolean) {
|
|
69
73
|
this.showVisualConfigPanel = show;
|
|
70
74
|
}
|
|
75
|
+
public updateTableCollapsedHeader (node: INestNode) {
|
|
76
|
+
const {uniqueKey, height} = node;
|
|
77
|
+
if (height < 1) return;
|
|
78
|
+
const updatedMap = new Map(this.tableCollapsedHeaderMap)
|
|
79
|
+
// if some child nodes of the incoming node are collapsed, remove them first
|
|
80
|
+
updatedMap.forEach((existingPath, existingKey) => {
|
|
81
|
+
if (existingKey.startsWith(uniqueKey) && existingKey.length > uniqueKey.length) {
|
|
82
|
+
updatedMap.delete(existingKey)
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
if (!updatedMap.has(uniqueKey)) {
|
|
86
|
+
updatedMap.set(uniqueKey, node.path)
|
|
87
|
+
} else {
|
|
88
|
+
updatedMap.delete(uniqueKey)
|
|
89
|
+
}
|
|
90
|
+
this.tableCollapsedHeaderMap = updatedMap
|
|
91
|
+
}
|
|
92
|
+
public resetTableCollapsedHeader () {
|
|
93
|
+
const updatedMap: Map<string, INestNode["path"]> = new Map();
|
|
94
|
+
this.tableCollapsedHeaderMap = updatedMap;
|
|
95
|
+
}
|
|
96
|
+
public setShowGeoJSONConfigPanel (show: boolean) {
|
|
97
|
+
this.showGeoJSONConfigPanel = show;
|
|
98
|
+
}
|
|
71
99
|
public closeEmbededMenu () {
|
|
72
100
|
this.vizEmbededMenu.show = false;
|
|
73
101
|
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { IReactionDisposer, makeAutoObservable, observable, computed, reaction, toJS } from 'mobx';
|
|
2
2
|
import produce from 'immer';
|
|
3
|
+
import { feature } from 'topojson-client';
|
|
4
|
+
import type { FeatureCollection } from "geojson";
|
|
3
5
|
import {
|
|
4
6
|
DataSet,
|
|
5
7
|
DraggableFieldState,
|
|
6
8
|
IFilterRule,
|
|
9
|
+
IGeographicData,
|
|
7
10
|
ISortMode,
|
|
8
11
|
IStackMode,
|
|
9
12
|
IViewField,
|
|
@@ -25,6 +28,7 @@ import {
|
|
|
25
28
|
initVisualConfig,
|
|
26
29
|
forwardVisualConfigs,
|
|
27
30
|
visSpecDecoder,
|
|
31
|
+
initEncoding,
|
|
28
32
|
} from '../utils/save';
|
|
29
33
|
import { CommonStore } from './commonStore';
|
|
30
34
|
import { createCountField } from '../utils';
|
|
@@ -68,24 +72,6 @@ function geomAdapter(geom: string) {
|
|
|
68
72
|
}
|
|
69
73
|
}
|
|
70
74
|
|
|
71
|
-
export function initEncoding(): DraggableFieldState {
|
|
72
|
-
return {
|
|
73
|
-
dimensions: [],
|
|
74
|
-
measures: [],
|
|
75
|
-
rows: [],
|
|
76
|
-
columns: [],
|
|
77
|
-
color: [],
|
|
78
|
-
opacity: [],
|
|
79
|
-
size: [],
|
|
80
|
-
shape: [],
|
|
81
|
-
radius: [],
|
|
82
|
-
theta: [],
|
|
83
|
-
details: [],
|
|
84
|
-
filters: [],
|
|
85
|
-
text: [],
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
|
|
89
75
|
function stackValueTransform(vlValue: string | undefined | null): IStackMode {
|
|
90
76
|
if (vlValue === 'center') return 'center';
|
|
91
77
|
if (vlValue === 'normalize') return 'normalize';
|
|
@@ -117,6 +103,12 @@ function isDraggableStateEmpty(state: DeepReadonly<DraggableFieldState>): boolea
|
|
|
117
103
|
return Object.values(state).every((value) => value.length === 0);
|
|
118
104
|
}
|
|
119
105
|
|
|
106
|
+
function withTimeout<T extends any[], U>(f: (...args: T) => Promise<U>, timeout: number){
|
|
107
|
+
return (...args: T) => Promise.race([f(...args), new Promise<never>((_, reject) => {
|
|
108
|
+
setTimeout(() => reject(new Error('timeout')), timeout)
|
|
109
|
+
})])
|
|
110
|
+
}
|
|
111
|
+
|
|
120
112
|
export class VizSpecStore {
|
|
121
113
|
// public fields: IViewField[] = [];
|
|
122
114
|
private commonStore: CommonStore;
|
|
@@ -159,7 +151,7 @@ export class VizSpecStore {
|
|
|
159
151
|
public canRedo = false;
|
|
160
152
|
public editingFilterIdx: number | null = null;
|
|
161
153
|
// TODO
|
|
162
|
-
public
|
|
154
|
+
public computationFunction: IComputationFunction = async () => [];
|
|
163
155
|
constructor(commonStore: CommonStore) {
|
|
164
156
|
this.commonStore = commonStore;
|
|
165
157
|
this.draggableFieldState = initEncoding();
|
|
@@ -174,7 +166,7 @@ export class VizSpecStore {
|
|
|
174
166
|
);
|
|
175
167
|
makeAutoObservable(this, {
|
|
176
168
|
visList: observable.shallow,
|
|
177
|
-
|
|
169
|
+
computationFunction: observable.ref,
|
|
178
170
|
// @ts-expect-error private fields are not supported
|
|
179
171
|
reactions: false,
|
|
180
172
|
});
|
|
@@ -387,10 +379,12 @@ export class VizSpecStore {
|
|
|
387
379
|
public setVisualConfig<K extends keyof IVisualConfig>(configKey: K, value: IVisualConfig[K]) {
|
|
388
380
|
this.useMutable(({ config }) => {
|
|
389
381
|
switch (true) {
|
|
390
|
-
case ['defaultAggregated', 'defaultStack', 'showActions', 'interactiveScale'].includes(configKey): {
|
|
382
|
+
case ['defaultAggregated', 'defaultStack', 'showActions', 'interactiveScale', 'scaleIncludeUnmatchedChoropleth'].includes(configKey): {
|
|
391
383
|
return ((config as unknown as { [k: string]: boolean })[configKey] = Boolean(value));
|
|
392
384
|
}
|
|
393
385
|
case configKey === 'geoms' && Array.isArray(value):
|
|
386
|
+
case configKey === "showTableSummary":
|
|
387
|
+
case configKey === "coordSystem":
|
|
394
388
|
case configKey === 'size' && typeof value === 'object':
|
|
395
389
|
case configKey === 'sorted':
|
|
396
390
|
case configKey === 'zeroScale':
|
|
@@ -511,6 +505,10 @@ export class VizSpecStore {
|
|
|
511
505
|
|
|
512
506
|
encodings.columns = encodings.rows;
|
|
513
507
|
encodings.rows = fieldsInCup as typeof encodings.rows; // assume this as writable
|
|
508
|
+
|
|
509
|
+
const fieldsInCup2 = encodings.longitude;
|
|
510
|
+
encodings.longitude = encodings.latitude;
|
|
511
|
+
encodings.latitude = fieldsInCup2 as typeof encodings.latitude; // assume this as writable
|
|
514
512
|
});
|
|
515
513
|
}
|
|
516
514
|
public createBinField(stateKey: keyof DraggableFieldState, index: number, binType: 'bin' | 'binCount'): string {
|
|
@@ -819,6 +817,23 @@ export class VizSpecStore {
|
|
|
819
817
|
const content = parseGWContent(raw);
|
|
820
818
|
this.importStoInfo(content);
|
|
821
819
|
}
|
|
820
|
+
|
|
821
|
+
public setGeographicData(data: IGeographicData, geoKey: string) {
|
|
822
|
+
const geoJSON = data.type === 'GeoJSON' ? data.data : feature(data.data, data.objectKey || Object.keys(data.data.objects)[0]) as unknown as FeatureCollection;
|
|
823
|
+
if (!('features' in geoJSON)) {
|
|
824
|
+
console.error('Invalid GeoJSON: GeoJSON must be a FeatureCollection, but got', geoJSON);
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
this.useMutable(({ config }) => {
|
|
828
|
+
config.geojson = geoJSON;
|
|
829
|
+
config.geoKey = geoKey;
|
|
830
|
+
});
|
|
831
|
+
}
|
|
832
|
+
public updateGeoKey(key: string) {
|
|
833
|
+
this.useMutable(({ config }) => {
|
|
834
|
+
config.geoKey = key;
|
|
835
|
+
});
|
|
836
|
+
}
|
|
822
837
|
|
|
823
838
|
private visSpecEncoder(visList: IVisSpec[]): IVisSpecForExport[] {
|
|
824
839
|
const updatedVisList = visList.map((visSpec) => {
|
|
@@ -876,7 +891,7 @@ export class VizSpecStore {
|
|
|
876
891
|
);
|
|
877
892
|
}
|
|
878
893
|
|
|
879
|
-
public setComputationFunction(f: IComputationFunction) {
|
|
880
|
-
this.
|
|
894
|
+
public setComputationFunction(f: IComputationFunction, timeout = 60000) {
|
|
895
|
+
this.computationFunction = withTimeout(f, timeout);
|
|
881
896
|
}
|
|
882
897
|
}
|
package/src/utils/save.ts
CHANGED
|
@@ -11,15 +11,40 @@ export function parseGWPureSpec(list: IVisSpec[]): VisSpecWithHistory[] {
|
|
|
11
11
|
return list.map((l) => new VisSpecWithHistory(l));
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
export function initEncoding(): DraggableFieldState {
|
|
15
|
+
return {
|
|
16
|
+
dimensions: [],
|
|
17
|
+
measures: [],
|
|
18
|
+
rows: [],
|
|
19
|
+
columns: [],
|
|
20
|
+
color: [],
|
|
21
|
+
opacity: [],
|
|
22
|
+
size: [],
|
|
23
|
+
shape: [],
|
|
24
|
+
radius: [],
|
|
25
|
+
theta: [],
|
|
26
|
+
longitude: [],
|
|
27
|
+
latitude: [],
|
|
28
|
+
geoId: [],
|
|
29
|
+
details: [],
|
|
30
|
+
filters: [],
|
|
31
|
+
text: [],
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
14
35
|
export function initVisualConfig(): IVisualConfig {
|
|
36
|
+
const [ geom ] = GEMO_TYPES.generic;
|
|
15
37
|
return {
|
|
16
38
|
defaultAggregated: true,
|
|
17
|
-
geoms: [
|
|
39
|
+
geoms: [geom],
|
|
40
|
+
showTableSummary: false,
|
|
41
|
+
coordSystem: 'generic',
|
|
18
42
|
stack: 'stack',
|
|
19
43
|
showActions: false,
|
|
20
44
|
interactiveScale: false,
|
|
21
45
|
sorted: 'none',
|
|
22
46
|
zeroScale: true,
|
|
47
|
+
scaleIncludeUnmatchedChoropleth: false,
|
|
23
48
|
background: undefined,
|
|
24
49
|
size: {
|
|
25
50
|
mode: "auto",
|
|
@@ -31,6 +56,7 @@ export function initVisualConfig(): IVisualConfig {
|
|
|
31
56
|
timeFormat: undefined,
|
|
32
57
|
normalizedNumberFormat: undefined,
|
|
33
58
|
},
|
|
59
|
+
geoKey: 'name',
|
|
34
60
|
resolve: {
|
|
35
61
|
x: false,
|
|
36
62
|
y: false,
|
|
@@ -60,6 +86,7 @@ export function visSpecDecoder(visList: IVisSpecForExport[]): IVisSpec[] {
|
|
|
60
86
|
return {
|
|
61
87
|
...visSpec,
|
|
62
88
|
encodings: {
|
|
89
|
+
...initEncoding(),
|
|
63
90
|
...visSpec.encodings,
|
|
64
91
|
filters: updatedFilters,
|
|
65
92
|
},
|
|
@@ -89,6 +89,7 @@ export const useVegaExportApi = (
|
|
|
89
89
|
nCols: 0,
|
|
90
90
|
nRows: 0,
|
|
91
91
|
charts: [],
|
|
92
|
+
chartType: 'vega',
|
|
92
93
|
};
|
|
93
94
|
}
|
|
94
95
|
if (ctx.renderStatus !== 'idle') {
|
|
@@ -114,6 +115,7 @@ export const useVegaExportApi = (
|
|
|
114
115
|
nCols: 0,
|
|
115
116
|
nRows: 0,
|
|
116
117
|
charts: [],
|
|
118
|
+
chartType: 'vega',
|
|
117
119
|
};
|
|
118
120
|
} finally {
|
|
119
121
|
dispose?.();
|
|
@@ -139,6 +141,7 @@ export const useVegaExportApi = (
|
|
|
139
141
|
container() {
|
|
140
142
|
return containerRef.current;
|
|
141
143
|
},
|
|
144
|
+
chartType: 'vega',
|
|
142
145
|
};
|
|
143
146
|
if (mode === 'data-url') {
|
|
144
147
|
const imgData = await renderHandle.getCanvasData();
|
|
@@ -19,6 +19,11 @@ import {
|
|
|
19
19
|
LightBulbIcon,
|
|
20
20
|
CodeBracketSquareIcon,
|
|
21
21
|
Cog6ToothIcon,
|
|
22
|
+
TableCellsIcon,
|
|
23
|
+
MapPinIcon,
|
|
24
|
+
GlobeAltIcon,
|
|
25
|
+
RectangleGroupIcon,
|
|
26
|
+
GlobeAmericasIcon,
|
|
22
27
|
HashtagIcon,
|
|
23
28
|
} from '@heroicons/react/24/outline';
|
|
24
29
|
import { observer } from 'mobx-react-lite';
|
|
@@ -26,7 +31,7 @@ import React, { SVGProps, useCallback, useMemo } from 'react';
|
|
|
26
31
|
import styled from 'styled-components';
|
|
27
32
|
import { useTranslation } from 'react-i18next';
|
|
28
33
|
import { ResizeDialog } from '../components/sizeSetting';
|
|
29
|
-
import { GEMO_TYPES, STACK_MODE, CHART_LAYOUT_TYPE } from '../config';
|
|
34
|
+
import { GEMO_TYPES, STACK_MODE, CHART_LAYOUT_TYPE, COORD_TYPES } from '../config';
|
|
30
35
|
import { useGlobalStore } from '../store';
|
|
31
36
|
import { IStackMode, IDarkMode } from '../interfaces';
|
|
32
37
|
import { IReactVegaHandler } from '../vis/react-vega';
|
|
@@ -82,6 +87,8 @@ const VisualSettings: React.FC<IVisualSettings> = ({
|
|
|
82
87
|
const {
|
|
83
88
|
defaultAggregated,
|
|
84
89
|
geoms: [markType],
|
|
90
|
+
showTableSummary,
|
|
91
|
+
coordSystem = 'generic',
|
|
85
92
|
stack,
|
|
86
93
|
interactiveScale,
|
|
87
94
|
size: { mode: sizeMode, width, height },
|
|
@@ -163,7 +170,7 @@ const VisualSettings: React.FC<IVisualSettings> = ({
|
|
|
163
170
|
color: 'rgb(294,115,22)',
|
|
164
171
|
},
|
|
165
172
|
},
|
|
166
|
-
options: GEMO_TYPES.map((g) => ({
|
|
173
|
+
options: GEMO_TYPES[coordSystem].map((g) => ({
|
|
167
174
|
key: g,
|
|
168
175
|
label: tGlobal(`constant.mark_type.${g}`),
|
|
169
176
|
icon: {
|
|
@@ -348,6 +355,8 @@ const VisualSettings: React.FC<IVisualSettings> = ({
|
|
|
348
355
|
/>
|
|
349
356
|
</svg>
|
|
350
357
|
),
|
|
358
|
+
poi: MapPinIcon,
|
|
359
|
+
choropleth: RectangleGroupIcon,
|
|
351
360
|
}[g],
|
|
352
361
|
})),
|
|
353
362
|
value: markType,
|
|
@@ -393,6 +402,15 @@ const VisualSettings: React.FC<IVisualSettings> = ({
|
|
|
393
402
|
icon: BarsArrowDownIcon,
|
|
394
403
|
onClick: () => vizStore.applyDefaultSort('descending'),
|
|
395
404
|
},
|
|
405
|
+
{
|
|
406
|
+
key: 'table:summary',
|
|
407
|
+
label: t('table.summary'),
|
|
408
|
+
icon: TableCellsIcon,
|
|
409
|
+
checked: showTableSummary,
|
|
410
|
+
onChange: checked => {
|
|
411
|
+
vizStore.setVisualConfig('showTableSummary', checked);
|
|
412
|
+
},
|
|
413
|
+
},
|
|
396
414
|
'-',
|
|
397
415
|
{
|
|
398
416
|
key: 'axes_resize',
|
|
@@ -438,6 +456,34 @@ const VisualSettings: React.FC<IVisualSettings> = ({
|
|
|
438
456
|
),
|
|
439
457
|
},
|
|
440
458
|
'-',
|
|
459
|
+
{
|
|
460
|
+
key: 'coord_system',
|
|
461
|
+
label: tGlobal('constant.coord_system.__enum__'),
|
|
462
|
+
icon: StopIcon,
|
|
463
|
+
options: COORD_TYPES.map(c => ({
|
|
464
|
+
key: c,
|
|
465
|
+
label: tGlobal(`constant.coord_system.${c}`),
|
|
466
|
+
icon: {
|
|
467
|
+
generic: (props: SVGProps<SVGSVGElement>) => <svg stroke="currentColor" fill="none" strokeWidth="1.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden {...props}><path strokeLinecap="round" strokeLinejoin="round" d="M2 12h20M12 2v20" /><path strokeLinecap="round" strokeLinejoin="round" d="M12 7h2M12 16h2M7 12v-2M16 12v-2"/></svg>,
|
|
468
|
+
geographic: GlobeAltIcon,
|
|
469
|
+
}[c],
|
|
470
|
+
})),
|
|
471
|
+
value: coordSystem,
|
|
472
|
+
onSelect: value => {
|
|
473
|
+
const coord = value as typeof COORD_TYPES[number];
|
|
474
|
+
vizStore.setVisualConfig('coordSystem', coord);
|
|
475
|
+
vizStore.setVisualConfig('geoms', [GEMO_TYPES[coord][0]]);
|
|
476
|
+
},
|
|
477
|
+
},
|
|
478
|
+
coordSystem === 'geographic' && markType === 'choropleth' && {
|
|
479
|
+
key: 'geojson',
|
|
480
|
+
label: t('button.geojson'),
|
|
481
|
+
icon: GlobeAmericasIcon,
|
|
482
|
+
onClick: () => {
|
|
483
|
+
commonStore.setShowGeoJSONConfigPanel(true);
|
|
484
|
+
},
|
|
485
|
+
},
|
|
486
|
+
'-',
|
|
441
487
|
{
|
|
442
488
|
key: 'debug',
|
|
443
489
|
label: t('toggle.debug'),
|
|
@@ -447,7 +493,7 @@ const VisualSettings: React.FC<IVisualSettings> = ({
|
|
|
447
493
|
vizStore.setVisualConfig('showActions', checked);
|
|
448
494
|
},
|
|
449
495
|
},
|
|
450
|
-
{
|
|
496
|
+
...coordSystem === 'generic' ?[{
|
|
451
497
|
key: 'export_chart',
|
|
452
498
|
label: t('button.export_chart'),
|
|
453
499
|
icon: PhotoIcon,
|
|
@@ -477,7 +523,7 @@ const VisualSettings: React.FC<IVisualSettings> = ({
|
|
|
477
523
|
</button>
|
|
478
524
|
</FormContainer>
|
|
479
525
|
),
|
|
480
|
-
},
|
|
526
|
+
}]:[],
|
|
481
527
|
{
|
|
482
528
|
key: 'config',
|
|
483
529
|
label: 'config',
|
|
@@ -529,17 +575,23 @@ const VisualSettings: React.FC<IVisualSettings> = ({
|
|
|
529
575
|
</a>
|
|
530
576
|
),
|
|
531
577
|
},
|
|
532
|
-
] as ToolbarItemProps[];
|
|
578
|
+
].filter(Boolean) as ToolbarItemProps[];
|
|
533
579
|
|
|
534
580
|
const items = builtInItems.filter((item) => typeof item === 'string' || !exclude.includes(item.key));
|
|
535
581
|
|
|
536
|
-
|
|
582
|
+
switch (vizStore.visualConfig.geoms[0]) {
|
|
583
|
+
case 'table':
|
|
584
|
+
return items;
|
|
585
|
+
default:
|
|
586
|
+
return items.filter(item => typeof item === 'string' || item.key !== 'table:summary');
|
|
587
|
+
}
|
|
537
588
|
}, [
|
|
538
589
|
vizStore,
|
|
539
590
|
canUndo,
|
|
540
591
|
canRedo,
|
|
541
592
|
defaultAggregated,
|
|
542
593
|
markType,
|
|
594
|
+
coordSystem,
|
|
543
595
|
stack,
|
|
544
596
|
interactiveScale,
|
|
545
597
|
sizeMode,
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/* eslint no-restricted-globals: 0 */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
import { buildPivotTable } from "./buildPivotTable"
|
|
4
|
+
/**
|
|
5
|
+
* @param {import('../interfaces').IViewField[]} dimsInRow
|
|
6
|
+
* @param {import('../interfaces').IViewField[]} dimsInColumn
|
|
7
|
+
* @param {import('../interfaces').IRow[]} allData
|
|
8
|
+
* @param {import('../interfaces').IRow} aggData
|
|
9
|
+
* @param {string[]} collapsedKeyList
|
|
10
|
+
* @param {boolean} showTableSummary
|
|
11
|
+
* @return {{lt: import('../components/pivotTable/inteface').INestNode, tt: import('../components/pivotTable/inteface').INestNode, metric: import('../interfaces').(IRow | null)[][]}}
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {MessageEvent<{ dimsInRow: import('../interfaces').IViewField[]; dimsInColumn: import('../interfaces').IViewField[]; allData: import('../interfaces').IRow[]; aggData: import('../interfaces').IRow[]; collapsedKeyList: string[]; showTableSummary: boolean }>} e
|
|
16
|
+
*/
|
|
17
|
+
const main = e => {
|
|
18
|
+
const { dimsInRow, dimsInColumn, allData, aggData, collapsedKeyList, showTableSummary } = e.data;
|
|
19
|
+
try {
|
|
20
|
+
const ans = buildPivotTable(dimsInRow, dimsInColumn, allData, aggData, collapsedKeyList, showTableSummary);
|
|
21
|
+
self.postMessage(ans);
|
|
22
|
+
} catch (error) {
|
|
23
|
+
self.postMessage({ error: error.message });
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
self.addEventListener('message', main, false);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { INestNode } from "../components/pivotTable/inteface";
|
|
2
|
+
import { buildMetricTableFromNestTree, buildNestTree } from "../components/pivotTable/utils"
|
|
3
|
+
import { IViewField, IRow } from "../interfaces"
|
|
4
|
+
|
|
5
|
+
export function buildPivotTable (
|
|
6
|
+
dimsInRow: IViewField[],
|
|
7
|
+
dimsInColumn: IViewField[],
|
|
8
|
+
allData: IRow[],
|
|
9
|
+
aggData: IRow[],
|
|
10
|
+
collapsedKeyList: string[],
|
|
11
|
+
showTableSummary: boolean
|
|
12
|
+
): {lt: INestNode, tt: INestNode, metric: (IRow | null)[][]} {
|
|
13
|
+
const lt = buildNestTree(
|
|
14
|
+
dimsInRow.map((d) => d.fid),
|
|
15
|
+
allData,
|
|
16
|
+
collapsedKeyList,
|
|
17
|
+
showTableSummary
|
|
18
|
+
);
|
|
19
|
+
const tt = buildNestTree(
|
|
20
|
+
dimsInColumn.map((d) => d.fid),
|
|
21
|
+
allData,
|
|
22
|
+
collapsedKeyList,
|
|
23
|
+
showTableSummary
|
|
24
|
+
);
|
|
25
|
+
const metric = buildMetricTableFromNestTree(lt, tt, [...allData, ...aggData])
|
|
26
|
+
return {lt, tt, metric}
|
|
27
|
+
}
|