@kanaries/graphic-walker 0.2.14 → 0.2.16

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.
Files changed (128) hide show
  1. package/dist/App.d.ts +5 -2
  2. package/dist/assets/explainer.worker-8428eb12.js.map +1 -1
  3. package/dist/assets/transform.worker-5d54ff09.js.map +1 -0
  4. package/dist/assets/viewQuery.worker-ffefc111.js.map +1 -0
  5. package/dist/components/callout.d.ts +2 -0
  6. package/dist/components/codeExport/index.d.ts +3 -0
  7. package/dist/components/loadingLayer.d.ts +2 -0
  8. package/dist/components/tabs/defaultTab.d.ts +1 -0
  9. package/dist/components/tabs/editableTab.d.ts +1 -2
  10. package/dist/components/toolbar/components.d.ts +4 -1
  11. package/dist/components/toolbar/index.d.ts +2 -0
  12. package/dist/components/toolbar/toolbar-item.d.ts +3 -0
  13. package/dist/components/tooltip.d.ts +2 -0
  14. package/dist/dataSource/dataSelection/config.d.ts +1 -0
  15. package/dist/dataSource/dataSelection/utils.d.ts +2 -0
  16. package/dist/datasets/tmp/test.json +1 -0
  17. package/dist/fields/components.d.ts +0 -1
  18. package/dist/fields/filterField/filterEditDialog.d.ts +1 -1
  19. package/dist/graphic-walker.es.js +23930 -23320
  20. package/dist/graphic-walker.es.js.map +1 -1
  21. package/dist/graphic-walker.umd.js +143 -273
  22. package/dist/graphic-walker.umd.js.map +1 -1
  23. package/dist/index.d.ts +3 -3
  24. package/dist/interfaces.d.ts +23 -1
  25. package/dist/lib/execExp.d.ts +8 -0
  26. package/dist/lib/interfaces.d.ts +22 -0
  27. package/dist/lib/op/aggregate.d.ts +3 -0
  28. package/dist/lib/op/bin.d.ts +3 -0
  29. package/dist/lib/op/fold.d.ts +3 -0
  30. package/dist/lib/op/stat.d.ts +8 -0
  31. package/dist/lib/viewQuery.d.ts +5 -0
  32. package/dist/models/visSpecHistory.d.ts +2 -0
  33. package/dist/renderer/index.d.ts +6 -3
  34. package/dist/renderer/specRenderer.d.ts +13 -0
  35. package/dist/services.d.ts +4 -1
  36. package/dist/store/commonStore.d.ts +6 -0
  37. package/dist/store/index.d.ts +3 -2
  38. package/dist/store/visualSpecStore.d.ts +11 -4
  39. package/dist/utils/dataPrep.d.ts +2 -0
  40. package/dist/utils/index.d.ts +3 -5
  41. package/dist/utils/media.d.ts +2 -1
  42. package/dist/utils/save.d.ts +1 -2
  43. package/dist/vis/react-vega.d.ts +4 -23
  44. package/dist/vis/spec/aggregate.d.ts +4 -0
  45. package/dist/vis/spec/encode.d.ts +19 -0
  46. package/dist/vis/spec/field.d.ts +2 -0
  47. package/dist/vis/spec/mark.d.ts +7 -0
  48. package/dist/vis/spec/stack.d.ts +4 -0
  49. package/dist/vis/spec/view.d.ts +67 -0
  50. package/dist/vis/theme.d.ts +36 -20
  51. package/dist/visualSettings/index.d.ts +2 -1
  52. package/dist/workers/transform.d.ts +2 -0
  53. package/package.json +4 -3
  54. package/src/App.tsx +23 -15
  55. package/src/components/callout.tsx +9 -7
  56. package/src/components/clickMenu.tsx +1 -7
  57. package/src/components/codeExport/index.tsx +114 -0
  58. package/src/components/dataTable/index.tsx +10 -10
  59. package/src/components/loadingLayer.tsx +7 -0
  60. package/src/components/modal.tsx +1 -15
  61. package/src/components/sizeSetting.tsx +2 -2
  62. package/src/components/tabs/defaultTab.tsx +4 -2
  63. package/src/components/tabs/editableTab.tsx +75 -40
  64. package/src/components/toolbar/components.tsx +8 -23
  65. package/src/components/toolbar/index.tsx +11 -4
  66. package/src/components/toolbar/toolbar-button.tsx +2 -1
  67. package/src/components/toolbar/toolbar-item.tsx +17 -12
  68. package/src/components/toolbar/toolbar-select-button.tsx +9 -13
  69. package/src/components/toolbar/toolbar-toggle-button.tsx +2 -1
  70. package/src/components/tooltip.tsx +10 -6
  71. package/src/dataSource/dataSelection/config.ts +11 -0
  72. package/src/dataSource/dataSelection/csvData.tsx +72 -40
  73. package/src/dataSource/dataSelection/gwFile.tsx +2 -2
  74. package/src/dataSource/dataSelection/utils.ts +28 -0
  75. package/src/dataSource/index.tsx +2 -3
  76. package/src/dataSource/utils.ts +8 -3
  77. package/src/fields/components.tsx +13 -50
  78. package/src/fields/datasetFields/index.tsx +3 -4
  79. package/src/fields/datasetFields/meaFields.tsx +12 -4
  80. package/src/fields/encodeFields/singleEncodeEditor.tsx +1 -1
  81. package/src/fields/filterField/filterEditDialog.tsx +63 -99
  82. package/src/fields/filterField/slider.tsx +1 -1
  83. package/src/index.css +4 -4
  84. package/src/index.tsx +22 -22
  85. package/src/insightBoard/mainBoard.tsx +9 -2
  86. package/src/interfaces.ts +30 -3
  87. package/src/lib/execExp.ts +147 -0
  88. package/src/lib/interfaces.ts +39 -0
  89. package/src/lib/op/aggregate.ts +49 -0
  90. package/src/lib/op/bin.ts +25 -0
  91. package/src/lib/op/fold.ts +17 -0
  92. package/src/lib/op/stat.ts +46 -0
  93. package/src/lib/viewQuery.ts +23 -0
  94. package/src/locales/en-US.json +8 -3
  95. package/src/locales/i18n.ts +7 -1
  96. package/src/locales/ja-JP.json +197 -0
  97. package/src/locales/zh-CN.json +8 -3
  98. package/src/main.tsx +1 -1
  99. package/src/models/visSpecHistory.ts +14 -0
  100. package/src/renderer/index.tsx +58 -101
  101. package/src/renderer/specRenderer.tsx +119 -0
  102. package/src/segments/segmentNav.tsx +3 -16
  103. package/src/segments/visNav.tsx +17 -6
  104. package/src/services.ts +37 -1
  105. package/src/store/commonStore.ts +14 -9
  106. package/src/store/index.tsx +11 -4
  107. package/src/store/visualSpecStore.ts +89 -50
  108. package/src/utils/dataPrep.ts +24 -0
  109. package/src/utils/index.ts +16 -17
  110. package/src/utils/media.ts +16 -11
  111. package/src/utils/normalization.ts +3 -1
  112. package/src/utils/save.ts +1 -2
  113. package/src/vis/react-vega.tsx +11 -332
  114. package/src/vis/spec/aggregate.ts +13 -0
  115. package/src/vis/spec/encode.ts +69 -0
  116. package/src/vis/spec/field.ts +10 -0
  117. package/src/vis/spec/mark.ts +30 -0
  118. package/src/vis/spec/stack.ts +11 -0
  119. package/src/vis/spec/view.ts +138 -0
  120. package/src/vis/theme.ts +35 -25
  121. package/src/visualSettings/index.tsx +22 -33
  122. package/src/workers/transform.ts +12 -0
  123. package/src/workers/transform.worker.js +13 -0
  124. package/src/workers/viewQuery.worker.js +16 -0
  125. package/dist/components/container.d.ts +0 -2
  126. package/dist/dataSource/pannel.d.ts +0 -5
  127. package/src/components/container.tsx +0 -25
  128. package/src/dataSource/pannel.tsx +0 -71
@@ -1,113 +1,70 @@
1
- import { runInAction, toJS } from 'mobx';
2
1
  import { observer } from 'mobx-react-lite';
3
- import { Resizable } from 're-resizable';
4
- import React, { useState, useCallback, useEffect, useRef, forwardRef } from 'react';
5
- import { applyFilter } from '../services';
2
+ import React, { useState, useEffect, forwardRef } from 'react';
3
+ import { applyFilter, applyViewQuery, transformDataService } from '../services';
4
+ import { DeepReadonly, DraggableFieldState, IDarkMode, IRow, IThemeKey, IVisualConfig } from '../interfaces';
5
+ import SpecRenderer from './specRenderer';
6
+ import { toJS } from 'mobx';
6
7
  import { useGlobalStore } from '../store';
7
- import ReactVega, { IReactVegaHandler } from '../vis/react-vega';
8
+ import { IReactVegaHandler } from '../vis/react-vega';
9
+ import { unstable_batchedUpdates } from 'react-dom';
10
+ import { initEncoding, initVisualConfig } from '../store/visualSpecStore';
8
11
 
9
-
10
- const ReactiveRenderer = forwardRef<IReactVegaHandler, { themeKey?: 'vega' | 'g2' }>(function ReactiveRenderer ({ themeKey }, ref) {
12
+ interface RendererProps {
13
+ themeKey?: IThemeKey;
14
+ dark?: IDarkMode;
15
+ }
16
+ const Renderer = forwardRef<IReactVegaHandler, RendererProps>(function (props, ref) {
17
+ const { themeKey, dark } = props;
18
+ const [waiting, setWaiting] = useState<boolean>(false);
11
19
  const { vizStore, commonStore } = useGlobalStore();
12
- const { draggableFieldState, visualConfig } = vizStore;
13
- const { geoms, interactiveScale, defaultAggregated, stack, showActions, size, exploration } = visualConfig;
20
+ const { allFields, viewFilters, viewDimensions, viewMeasures } = vizStore;
14
21
  const { currentDataset } = commonStore;
15
- const { filters } = draggableFieldState;
16
-
17
- const rows = toJS(draggableFieldState.rows)
18
- const columns = toJS(draggableFieldState.columns)
19
- const color = toJS(draggableFieldState.color)
20
- const opacity = toJS(draggableFieldState.opacity)
21
- const shape = toJS(draggableFieldState.shape)
22
- const theta = toJS(draggableFieldState.theta)
23
- const radius = toJS(draggableFieldState.radius)
24
- const sizeChannel = toJS(draggableFieldState.size)
25
-
26
- const rowLeftFacetFields = rows.slice(0, -1).filter(f => f.analyticType === 'dimension');
27
- const colLeftFacetFields = columns.slice(0, -1).filter(f => f.analyticType === 'dimension');
28
-
29
- const hasFacet = rowLeftFacetFields.length > 0 || colLeftFacetFields.length > 0;
30
-
31
- const shouldTriggerMenu = exploration.mode === 'none';
32
-
33
- const handleGeomClick = useCallback((values: any, e: any) => {
34
- if (shouldTriggerMenu) {
35
- e.stopPropagation();
36
- runInAction(() => {
37
- commonStore.showEmbededMenu([e.pageX, e.pageY])
38
- commonStore.setFilters(values);
39
- });
40
- }
41
- }, [shouldTriggerMenu]);
42
-
43
- // apply filters
44
22
  const { dataSource } = currentDataset;
23
+ const [viewConfig, setViewConfig] = useState<IVisualConfig>(initVisualConfig);
24
+ const [encodings, setEncodings] = useState<DeepReadonly<DraggableFieldState>>(initEncoding);
45
25
 
46
- const [data, setData] = useState(dataSource);
47
- const pendingPromiseRef = useRef<Promise<typeof data> | null>(null);
26
+ const [viewData, setViewData] = useState<IRow[]>([]);
48
27
 
49
28
  useEffect(() => {
50
- setData(dataSource);
51
- }, [dataSource]);
52
-
53
- useEffect(() => {
54
- const p = filters.length === 0 ? Promise.resolve(dataSource) : applyFilter(dataSource, filters);
55
- pendingPromiseRef.current = p;
56
-
57
- p.then(d => {
58
- if (p !== pendingPromiseRef.current) {
59
- // This promise is out-of-date
60
- return;
61
- }
62
-
63
- setData(d);
64
- }).catch(err => {
65
- console.error(err);
66
- });
67
-
68
- return () => {
69
- pendingPromiseRef.current = null;
70
- };
71
- }, [dataSource, filters]);
29
+ setWaiting(true);
30
+ applyFilter(dataSource, viewFilters)
31
+ .then((data) => transformDataService(data, allFields))
32
+ .then((d) => {
33
+ // setViewData(d);
34
+ const dims = viewDimensions;
35
+ const meas = viewMeasures;
36
+ const config = toJS(vizStore.visualConfig);
37
+ return applyViewQuery(d, dims.concat(meas), {
38
+ op: config.defaultAggregated ? 'aggregate' : 'raw',
39
+ groupBy: dims.map((f) => f.fid),
40
+ agg: Object.fromEntries(meas.map((f) => [f.fid, f.aggName as any])),
41
+ });
42
+ })
43
+ .then((data) => {
44
+ unstable_batchedUpdates(() => {
45
+ setViewData(data);
46
+ setWaiting(false);
47
+ setEncodings(toJS(vizStore.draggableFieldState));
48
+ setViewConfig(toJS(vizStore.visualConfig));
49
+ });
50
+ })
51
+ .catch((err) => {
52
+ console.error(err);
53
+ setWaiting(false);
54
+ });
55
+ }, [dataSource, viewFilters, allFields, viewDimensions, viewMeasures]);
72
56
 
73
- return <Resizable className={(size.mode === 'fixed' && !hasFacet) ? "border-blue-400 border-2 overflow-hidden" : ""}
74
- style={{ padding: '12px' }}
75
- onResizeStop={(e, direction, ref, d) => {
76
- vizStore.setChartLayout({
77
- mode: 'fixed',
78
- width: size.width + d.width,
79
- height: size.height + d.height
80
- })
81
- }}
82
- size={{
83
- width: size.width + 'px',
84
- height: size.height + 'px',
85
- }}>
86
- <ReactVega
87
- layoutMode={size.mode}
88
- interactiveScale={interactiveScale}
89
- geomType={geoms[0]}
90
- defaultAggregate={defaultAggregated}
91
- stack={stack}
92
- dataSource={data}
93
- rows={rows}
94
- columns={columns}
95
- color={color[0]}
96
- theta={theta[0]}
97
- radius={radius[0]}
98
- shape={shape[0]}
99
- opacity={opacity[0]}
100
- size={sizeChannel[0]}
101
- showActions={showActions}
102
- width={size.width - 12 * 4}
103
- height={size.height - 12 * 4}
104
- ref={ref}
105
- brushEncoding={exploration.mode === 'brush' ? exploration.brushDirection : 'none'}
106
- selectEncoding={exploration.mode === 'point' ? 'default' : 'none'}
107
- onGeomClick={handleGeomClick}
108
- themeKey={themeKey}
109
- />
110
- </Resizable>
57
+ return (
58
+ <SpecRenderer
59
+ loading={waiting}
60
+ data={viewData}
61
+ ref={ref}
62
+ themeKey={themeKey}
63
+ dark={dark}
64
+ draggableFieldState={encodings}
65
+ visualConfig={viewConfig}
66
+ />
67
+ );
111
68
  });
112
69
 
113
- export default observer(ReactiveRenderer);
70
+ export default observer(Renderer);
@@ -0,0 +1,119 @@
1
+ import { runInAction } from 'mobx';
2
+ import { Resizable } from 're-resizable';
3
+ import React, { useCallback, forwardRef, useMemo } from 'react';
4
+
5
+ import { useGlobalStore } from '../store';
6
+ import ReactVega, { IReactVegaHandler } from '../vis/react-vega';
7
+ import { DeepReadonly, DraggableFieldState, IDarkMode, IRow, IThemeKey, IVisualConfig } from '../interfaces';
8
+ import LoadingLayer from '../components/loadingLayer';
9
+
10
+ interface SpecRendererProps {
11
+ themeKey?: IThemeKey;
12
+ dark?: IDarkMode;
13
+ data: IRow[];
14
+ loading: boolean;
15
+ draggableFieldState: DeepReadonly<DraggableFieldState>;
16
+ visualConfig: IVisualConfig;
17
+ }
18
+ const SpecRenderer = forwardRef<IReactVegaHandler, SpecRendererProps>(function (
19
+ { themeKey, dark, data, loading, draggableFieldState, visualConfig },
20
+ ref
21
+ ) {
22
+ const { vizStore, commonStore } = useGlobalStore();
23
+ // const { draggableFieldState, visualConfig } = vizStore;
24
+ const { geoms, interactiveScale, defaultAggregated, stack, showActions, size, exploration } = visualConfig;
25
+
26
+ const rows = draggableFieldState.rows;
27
+ const columns = draggableFieldState.columns;
28
+ const color = draggableFieldState.color;
29
+ const opacity = draggableFieldState.opacity;
30
+ const shape = draggableFieldState.shape;
31
+ const theta = draggableFieldState.theta;
32
+ const radius = draggableFieldState.radius;
33
+ const sizeChannel = draggableFieldState.size;
34
+
35
+ const rowLeftFacetFields = useMemo(() => rows.slice(0, -1).filter((f) => f.analyticType === 'dimension'), [rows]);
36
+ const colLeftFacetFields = useMemo(
37
+ () => columns.slice(0, -1).filter((f) => f.analyticType === 'dimension'),
38
+ [columns]
39
+ );
40
+
41
+ const hasFacet = rowLeftFacetFields.length > 0 || colLeftFacetFields.length > 0;
42
+
43
+ const shouldTriggerMenu = exploration.mode === 'none';
44
+
45
+ const handleGeomClick = useCallback(
46
+ (values: any, e: any) => {
47
+ if (shouldTriggerMenu) {
48
+ e.stopPropagation();
49
+ runInAction(() => {
50
+ commonStore.showEmbededMenu([e.pageX, e.pageY]);
51
+ commonStore.setFilters(values);
52
+ });
53
+ }
54
+ },
55
+ [shouldTriggerMenu]
56
+ );
57
+ const enableResize = size.mode === 'fixed' && !hasFacet;
58
+
59
+ return (
60
+ <Resizable
61
+ className={enableResize ? 'border-blue-400 border-2 overflow-hidden' : ''}
62
+ style={{ padding: '12px' }}
63
+ onResizeStop={(e, direction, ref, d) => {
64
+ vizStore.setChartLayout({
65
+ mode: 'fixed',
66
+ width: size.width + d.width,
67
+ height: size.height + d.height,
68
+ });
69
+ }}
70
+ enable={
71
+ enableResize
72
+ ? undefined
73
+ : {
74
+ top: false,
75
+ right: false,
76
+ bottom: false,
77
+ left: false,
78
+ topRight: false,
79
+ bottomRight: false,
80
+ bottomLeft: false,
81
+ topLeft: false,
82
+ }
83
+ }
84
+ size={{
85
+ width: size.width + 'px',
86
+ height: size.height + 'px',
87
+ }}
88
+ >
89
+ {loading && <LoadingLayer />}
90
+ <ReactVega
91
+ layoutMode={size.mode}
92
+ interactiveScale={interactiveScale}
93
+ geomType={geoms[0]}
94
+ defaultAggregate={defaultAggregated}
95
+ stack={stack}
96
+ dataSource={data}
97
+ rows={rows}
98
+ columns={columns}
99
+ color={color[0]}
100
+ theta={theta[0]}
101
+ radius={radius[0]}
102
+ shape={shape[0]}
103
+ opacity={opacity[0]}
104
+ size={sizeChannel[0]}
105
+ showActions={showActions}
106
+ width={size.width - 12 * 4}
107
+ height={size.height - 12 * 4}
108
+ ref={ref}
109
+ brushEncoding={exploration.mode === 'brush' ? exploration.brushDirection : 'none'}
110
+ selectEncoding={exploration.mode === 'point' ? 'default' : 'none'}
111
+ onGeomClick={handleGeomClick}
112
+ themeKey={themeKey}
113
+ dark={dark}
114
+ />
115
+ </Resizable>
116
+ );
117
+ });
118
+
119
+ export default SpecRenderer;
@@ -1,18 +1,14 @@
1
- import React, { Fragment, useCallback } from "react";
1
+ import React, { useCallback } from "react";
2
2
  import { observer } from "mobx-react-lite";
3
3
  import DefaultTab, { ITabOption } from "../components/tabs/defaultTab";
4
4
  import { useGlobalStore } from "../store";
5
- import { ChartBarIcon, ChartPieIcon, CircleStackIcon } from "@heroicons/react/24/outline";
5
+ import { ChartPieIcon, CircleStackIcon } from "@heroicons/react/24/outline";
6
6
  import { ISegmentKey } from "../interfaces";
7
7
  import { useTranslation } from "react-i18next";
8
8
 
9
-
10
- const ADD_KEY = '_add';
11
-
12
9
  const SegmentNav: React.FC = (props) => {
13
10
  const { vizStore, commonStore } = useGlobalStore();
14
- const { visIndex, visList } = vizStore;
15
- const { currentDataset, segmentKey } = commonStore;
11
+ const { segmentKey } = commonStore;
16
12
  const { t } = useTranslation();
17
13
 
18
14
  const tabs: ITabOption[] = [
@@ -30,15 +26,6 @@ const SegmentNav: React.FC = (props) => {
30
26
  }
31
27
  ]
32
28
 
33
- const visSelectionHandler = useCallback((tabKey: string, tabIndex: number) => {
34
- if (tabKey === ADD_KEY) {
35
- vizStore.addVisualization();
36
- vizStore.initMetaState(currentDataset)
37
- } else {
38
- vizStore.selectVisualization(tabIndex);
39
- }
40
- }, [currentDataset, vizStore])
41
-
42
29
  const editLabelHandler = useCallback((content: string, tabIndex: number) => {
43
30
  vizStore.setVisName(tabIndex, content)
44
31
  }, [])
@@ -1,5 +1,6 @@
1
- import React, { useCallback } from "react";
1
+ import React, { useCallback, useEffect } from "react";
2
2
  import { observer } from "mobx-react-lite";
3
+ import { useTranslation } from "react-i18next";
3
4
  import EditableTabs, { ITabOption } from "../components/tabs/editableTab";
4
5
  import { useGlobalStore } from "../store";
5
6
 
@@ -11,25 +12,35 @@ const VisNav: React.FC = (props) => {
11
12
  const { visIndex, visList } = vizStore;
12
13
  const { currentDataset } = commonStore;
13
14
 
15
+ const { t } = useTranslation();
16
+
14
17
  const tabs: ITabOption[] = visList.map((v) => ({
15
18
  key: v.visId,
16
- label: v.name?.[0] || 'vis',
17
- options: v.name?.[1],
19
+ label: v.name ?? 'vis',
20
+ editable: true
18
21
  }));
19
22
 
20
23
  tabs.push({
21
24
  key: ADD_KEY,
22
- label: 'main.tablist.new'
25
+ label: t('main.tablist.new')
23
26
  });
24
27
 
28
+ useEffect(() => {
29
+ if (visList.length === 1) {
30
+ // should set the first vis name when the component is mounted
31
+ vizStore.setVisName(0, t('main.tablist.auto_title', { idx: 1 }));
32
+ }
33
+ // no need to add deps here
34
+ }, [])
35
+
25
36
  const visSelectionHandler = useCallback((tabKey: string, tabIndex: number) => {
26
37
  if (tabKey === ADD_KEY) {
27
- vizStore.addVisualization();
38
+ vizStore.addVisualization(t('main.tablist.auto_title', { idx: visList.length + 1 }));
28
39
  vizStore.initMetaState(currentDataset)
29
40
  } else {
30
41
  vizStore.selectVisualization(tabIndex);
31
42
  }
32
- }, [currentDataset, vizStore])
43
+ }, [currentDataset, vizStore, visList.length])
33
44
 
34
45
  const editLabelHandler = useCallback((content: string, tabIndex: number) => {
35
46
  vizStore.setVisName(tabIndex, content)
package/src/services.ts CHANGED
@@ -10,7 +10,10 @@ import { IRow, Filters, SemanticType, IMeasure, IMutField, IFilterField } from '
10
10
  // eslint-disable-next-line
11
11
  import ExplainerWorker from './workers/explainer.worker?worker&inline';
12
12
  import FilterWorker from './workers/filter.worker?worker&inline';
13
+ import TransformDataWorker from './workers/transform.worker?worker&inline';
14
+ import ViewQueryWorker from './workers/viewQuery.worker?worker&inline';
13
15
  import { IExplaination, IMeasureWithStat } from './insights';
16
+ import { IViewQuery, queryView } from './lib/viewQuery';
14
17
 
15
18
  interface WorkerState {
16
19
  eWorker: Worker | null;
@@ -105,7 +108,8 @@ export function destroyWorker() {
105
108
  let filterWorker: Worker | null = null;
106
109
  let filterWorkerAutoTerminator: NodeJS.Timeout | null = null;
107
110
 
108
- export const applyFilter = async (data: readonly IRow[], filters: readonly IFilterField[]): Promise<IRow[]> => {
111
+ export const applyFilter = async (data: IRow[], filters: readonly IFilterField[]): Promise<IRow[]> => {
112
+ if (filters.length === 0) return data;
109
113
  if (filterWorkerAutoTerminator !== null) {
110
114
  clearTimeout(filterWorkerAutoTerminator);
111
115
  filterWorkerAutoTerminator = null;
@@ -137,3 +141,35 @@ export const applyFilter = async (data: readonly IRow[], filters: readonly IFilt
137
141
  }, 60_000); // Destroy the worker when no request is received for 60 secs
138
142
  }
139
143
  };
144
+
145
+ export const transformDataService = async (data: IRow[], columns: IMutField[]): Promise<IRow[]> => {
146
+ if (columns.length === 0 || data.length === 0) return data;
147
+ const worker = new TransformDataWorker();
148
+ try {
149
+ const res: IRow[] = await workerService(worker, {
150
+ dataSource: data,
151
+ columns: toJS(columns),
152
+ });
153
+ return res;
154
+ } catch (error) {
155
+ throw new Error('Uncaught error in TransformDataWorker', { cause: error });
156
+ } finally {
157
+ worker.terminate();
158
+ }
159
+ }
160
+
161
+ export const applyViewQuery = async (data: IRow[], metas: IMutField[], query: IViewQuery): Promise<IRow[]> => {
162
+ const worker = new ViewQueryWorker();
163
+ try {
164
+ const res: IRow[] = await workerService(worker, {
165
+ dataSource: data,
166
+ metas: toJS(metas),
167
+ query: toJS(query),
168
+ });
169
+ return res;
170
+ } catch (err) {
171
+ throw new Error('Uncaught error in ViewQueryWorker', { cause: err });
172
+ } finally {
173
+ worker.terminate();
174
+ }
175
+ }
@@ -1,7 +1,6 @@
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 { extendCountField } from '../utils';
5
4
 
6
5
  export class CommonStore {
7
6
  public datasets: IDataSet[] = [];
@@ -14,6 +13,7 @@ export class CommonStore {
14
13
  public showInsightBoard: boolean = false;
15
14
  public vizEmbededMenu: { show: boolean; position: [number, number] } = { show: false, position: [0, 0] };
16
15
  public showDataConfig: boolean = false;
16
+ public showCodeExportPanel: boolean = false;
17
17
  public filters: Filters = {};
18
18
  public segmentKey: ISegmentKey = ISegmentKey.vis;
19
19
  constructor () {
@@ -30,12 +30,12 @@ export class CommonStore {
30
30
  if (this.datasets.length > 0) {
31
31
  const dataSourceId = this.datasets[datasetIndex].dsId;
32
32
  const dataSource = this.dataSources.find(d => d.id === dataSourceId);
33
- const rawFields = toJS(this.datasets[datasetIndex].rawFields)
34
- const base = extendCountField((dataSource ? dataSource.data : []), rawFields)
33
+ const rawFields = toJS(this.datasets[datasetIndex].rawFields)//.concat(createCountField())
34
+ // const base = extendCountField((dataSource ? dataSource.data : []), rawFields)
35
35
  return {
36
36
  ...this.datasets[datasetIndex],
37
- dataSource: base.dataSource,
38
- rawFields: base.fields
37
+ dataSource: dataSource?.data ?? [],
38
+ rawFields
39
39
  }
40
40
  }
41
41
  return {
@@ -61,6 +61,9 @@ export class CommonStore {
61
61
  this.vizEmbededMenu.show = true;
62
62
  this.vizEmbededMenu.position = position;
63
63
  }
64
+ public setShowCodeExportPanel (show: boolean) {
65
+ this.showCodeExportPanel = show;
66
+ }
64
67
  public closeEmbededMenu () {
65
68
  this.vizEmbededMenu.show = false;
66
69
  }
@@ -112,11 +115,13 @@ export class CommonStore {
112
115
 
113
116
  public updateTempDS (rawData: IRow[]) {
114
117
  const result = transData(rawData);
115
- // TODO: need fix web-data-loader issue #2
116
- this.tmpDataSource = result.dataSource.slice(0, -1);
118
+ this.tmpDataSource = result.dataSource;
117
119
  this.tmpDSRawFields = result.fields;
118
120
  }
119
-
121
+ /**
122
+ * update temp dataset (standard) with dataset info
123
+ * @param dataset
124
+ */
120
125
  public updateTempSTDDS (dataset: IDataSetInfo) {
121
126
  this.tmpDataSource = dataset.dataSource;
122
127
  this.tmpDSRawFields = dataset.rawFields;
@@ -176,7 +181,7 @@ export class CommonStore {
176
181
  }
177
182
  public createPlaceholderDS() {
178
183
  this.addDS({
179
- name: '新数据源',
184
+ name: 'new dataset',
180
185
  dataSource: [],
181
186
  rawFields: []
182
187
  })
@@ -1,8 +1,8 @@
1
- import React, { useContext, useEffect } from 'react';
1
+ import React, { useContext } from 'react';
2
2
  import { CommonStore } from './commonStore'
3
3
  import { VizSpecStore } from './visualSpecStore'
4
4
 
5
- interface GlobalStore {
5
+ export interface IGlobalStore {
6
6
  commonStore: CommonStore;
7
7
  vizStore: VizSpecStore;
8
8
  }
@@ -10,12 +10,12 @@ interface GlobalStore {
10
10
  const commonStore = new CommonStore();
11
11
  const vizStore = new VizSpecStore(commonStore);
12
12
 
13
- const initStore: GlobalStore = {
13
+ const initStore: IGlobalStore = {
14
14
  commonStore,
15
15
  vizStore
16
16
  }
17
17
 
18
- const StoreContext = React.createContext<GlobalStore>(null!);
18
+ const StoreContext = React.createContext<IGlobalStore>(null!);
19
19
 
20
20
  export function destroyGWStore() {
21
21
  initStore.commonStore.destroy();
@@ -31,16 +31,23 @@ export function rebootGWStore() {
31
31
 
32
32
  interface StoreWrapperProps {
33
33
  keepAlive?: boolean;
34
+ storeRef?: React.MutableRefObject<IGlobalStore | null>;
34
35
  }
35
36
  export class StoreWrapper extends React.Component<StoreWrapperProps> {
36
37
  constructor(props: StoreWrapperProps) {
37
38
  super(props)
39
+ if (props.storeRef) {
40
+ props.storeRef.current = initStore;
41
+ }
38
42
  if (props.keepAlive) {
39
43
  rebootGWStore();
40
44
  }
41
45
  }
42
46
  componentWillUnmount() {
43
47
  if (!this.props.keepAlive) {
48
+ if (this.props.storeRef) {
49
+ this.props.storeRef.current = null;
50
+ }
44
51
  destroyGWStore();
45
52
  }
46
53
  }