@kanaries/graphic-walker 0.4.12 → 0.4.13
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/graphic-walker.es.js +9108 -9081
- package/dist/graphic-walker.es.js.map +1 -1
- package/dist/graphic-walker.umd.js +118 -116
- package/dist/graphic-walker.umd.js.map +1 -1
- package/dist/main.d.ts +1 -1
- package/dist/renderer/index.d.ts +3 -0
- package/dist/style.css +0 -1
- package/dist/vanilla.d.ts +0 -1
- package/dist/visualSettings/index.d.ts +3 -0
- package/package.json +1 -1
- package/src/App.tsx +4 -2
- package/src/fields/filterField/filterEditDialog.tsx +2 -2
- package/src/main.tsx +1 -0
- package/src/renderer/index.tsx +32 -3
- package/src/vanilla.tsx +0 -1
- package/src/visualSettings/index.tsx +15 -0
package/dist/main.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import './index.css';
|
package/dist/renderer/index.d.ts
CHANGED
|
@@ -7,6 +7,9 @@ interface RendererProps {
|
|
|
7
7
|
dark?: IDarkMode;
|
|
8
8
|
computationFunction: IComputationFunction;
|
|
9
9
|
channelScales?: IChannelScales;
|
|
10
|
+
csvRef?: React.MutableRefObject<{
|
|
11
|
+
download: () => void;
|
|
12
|
+
}>;
|
|
10
13
|
}
|
|
11
14
|
declare const _default: React.MemoExoticComponent<React.ForwardRefExoticComponent<Pick<RendererProps & React.RefAttributes<IReactVegaHandler>, "key" | keyof RendererProps> & React.RefAttributes<IReactVegaHandler>>>;
|
|
12
15
|
export default _default;
|
package/dist/style.css
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
html{margin:0;padding:0;background-color:#fff}@media (prefers-color-scheme: dark){html{background-color:#18181b}}body{margin:0;padding:0}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}
|
package/dist/vanilla.d.ts
CHANGED
|
@@ -5,6 +5,9 @@ import { ToolbarItemProps } from '../components/toolbar';
|
|
|
5
5
|
interface IVisualSettings {
|
|
6
6
|
darkModePreference: IDarkMode;
|
|
7
7
|
rendererHandler?: React.RefObject<IReactVegaHandler>;
|
|
8
|
+
csvHandler?: React.MutableRefObject<{
|
|
9
|
+
download: () => void;
|
|
10
|
+
}>;
|
|
8
11
|
exclude?: string[];
|
|
9
12
|
extra?: ToolbarItemProps[];
|
|
10
13
|
}
|
package/package.json
CHANGED
package/src/App.tsx
CHANGED
|
@@ -174,6 +174,8 @@ const App = observer<IGWProps>(function App(props) {
|
|
|
174
174
|
|
|
175
175
|
const rendererRef = useRef<IReactVegaHandler>(null);
|
|
176
176
|
|
|
177
|
+
const downloadCSVRef = useRef<{ download: () => void }>({download() {}});
|
|
178
|
+
|
|
177
179
|
const reportError = useCallback((msg: string, code?: number) => {
|
|
178
180
|
const err = new Error(`Error${code ? `(${code})`: ''}: ${msg}`);
|
|
179
181
|
console.error(err);
|
|
@@ -208,7 +210,7 @@ const App = observer<IGWProps>(function App(props) {
|
|
|
208
210
|
{enhanceAPI?.features?.askviz && (
|
|
209
211
|
<AskViz api={typeof enhanceAPI.features.askviz === 'string' ? enhanceAPI.features.askviz : ''} headers={enhanceAPI?.header} />
|
|
210
212
|
)}
|
|
211
|
-
<VisualSettings rendererHandler={rendererRef} darkModePreference={dark} exclude={toolbar?.exclude} extra={toolbar?.extra} />
|
|
213
|
+
<VisualSettings csvHandler={downloadCSVRef} rendererHandler={rendererRef} darkModePreference={dark} exclude={toolbar?.exclude} extra={toolbar?.extra} />
|
|
212
214
|
<CodeExport />
|
|
213
215
|
<ExplainData themeKey={themeKey} dark={darkMode}/>
|
|
214
216
|
<VisualConfig />
|
|
@@ -239,7 +241,7 @@ const App = observer<IGWProps>(function App(props) {
|
|
|
239
241
|
}}
|
|
240
242
|
>
|
|
241
243
|
{datasets.length > 0 && (
|
|
242
|
-
<ReactiveRenderer ref={rendererRef} themeKey={themeKey} themeConfig={themeConfig} dark={dark} computationFunction={vizStore.computationFunction} channelScales={props.channelScales} />
|
|
244
|
+
<ReactiveRenderer csvRef={downloadCSVRef} ref={rendererRef} themeKey={themeKey} themeConfig={themeConfig} dark={dark} computationFunction={vizStore.computationFunction} channelScales={props.channelScales} />
|
|
243
245
|
)}
|
|
244
246
|
{vizEmbededMenu.show && (
|
|
245
247
|
<ClickMenu x={vizEmbededMenu.position[0]} y={vizEmbededMenu.position[1]}>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { observer } from "mobx-react-lite";
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { useTranslation } from "react-i18next";
|
|
4
|
-
|
|
4
|
+
import { toJS } from 'mobx';
|
|
5
5
|
import Modal from "../../components/modal";
|
|
6
6
|
import type { IFilterField, IFilterRule } from "../../interfaces";
|
|
7
7
|
import { useGlobalStore } from "../../store";
|
|
@@ -45,7 +45,7 @@ const FilterEditDialog: React.FC = observer(() => {
|
|
|
45
45
|
|
|
46
46
|
React.useEffect(() => {
|
|
47
47
|
if (field !== ufRef.current) {
|
|
48
|
-
setUncontrolledField(field);
|
|
48
|
+
setUncontrolledField(toJS(field) );
|
|
49
49
|
}
|
|
50
50
|
}, [field]);
|
|
51
51
|
|
package/src/main.tsx
CHANGED
package/src/renderer/index.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { observer } from 'mobx-react-lite';
|
|
2
2
|
import React, { useState, useEffect, forwardRef, useRef, useCallback } from 'react';
|
|
3
|
-
import { DeepReadonly, DraggableFieldState, IDarkMode, IRow, IThemeKey, IVisualConfig, IComputationFunction, IChannelScales } from '../interfaces';
|
|
3
|
+
import { DeepReadonly, DraggableFieldState, IDarkMode, IRow, IThemeKey, IVisualConfig, IComputationFunction, IChannelScales, IViewField } from '../interfaces';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
5
|
import SpecRenderer from './specRenderer';
|
|
6
6
|
import { runInAction, toJS } from 'mobx';
|
|
@@ -8,10 +8,12 @@ import { useGlobalStore } from '../store';
|
|
|
8
8
|
import { IReactVegaHandler } from '../vis/react-vega';
|
|
9
9
|
import { unstable_batchedUpdates } from 'react-dom';
|
|
10
10
|
import { useRenderer } from './hooks';
|
|
11
|
-
import { initEncoding } from '../utils/save';
|
|
11
|
+
import { download, initEncoding } from '../utils/save';
|
|
12
12
|
import { useChartIndexControl } from '../utils/chartIndexControl';
|
|
13
13
|
import { LEAFLET_DEFAULT_HEIGHT, LEAFLET_DEFAULT_WIDTH } from '../components/leafletRenderer';
|
|
14
14
|
import { initVisualConfig } from '../utils/save';
|
|
15
|
+
import { getMeaAggKey } from '../utils';
|
|
16
|
+
import { COUNT_FIELD_ID } from '../constants';
|
|
15
17
|
|
|
16
18
|
interface RendererProps {
|
|
17
19
|
themeKey?: IThemeKey;
|
|
@@ -19,13 +21,14 @@ interface RendererProps {
|
|
|
19
21
|
dark?: IDarkMode;
|
|
20
22
|
computationFunction: IComputationFunction;
|
|
21
23
|
channelScales?: IChannelScales;
|
|
24
|
+
csvRef?: React.MutableRefObject<{ download: () => void }>;
|
|
22
25
|
}
|
|
23
26
|
/**
|
|
24
27
|
* Renderer of GraphicWalker editor.
|
|
25
28
|
* Depending on global store.
|
|
26
29
|
*/
|
|
27
30
|
const Renderer = forwardRef<IReactVegaHandler, RendererProps>(function (props, ref) {
|
|
28
|
-
const { themeKey, dark, computationFunction, themeConfig } = props;
|
|
31
|
+
const { themeKey, dark, computationFunction, themeConfig, csvRef, } = props;
|
|
29
32
|
const { vizStore, commonStore } = useGlobalStore();
|
|
30
33
|
const {
|
|
31
34
|
allFields,
|
|
@@ -58,6 +61,32 @@ const Renderer = forwardRef<IReactVegaHandler, RendererProps>(function (props, r
|
|
|
58
61
|
computationFunction,
|
|
59
62
|
});
|
|
60
63
|
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
if (csvRef) {
|
|
66
|
+
csvRef.current = {
|
|
67
|
+
download() {
|
|
68
|
+
const headers = viewDimensions.concat(viewMeasures).map(x => {
|
|
69
|
+
if (x.fid === COUNT_FIELD_ID) {
|
|
70
|
+
return {
|
|
71
|
+
name: 'Count',
|
|
72
|
+
fid: COUNT_FIELD_ID
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (viewConfig.defaultAggregated && x.analyticType === 'measure') {
|
|
76
|
+
return {
|
|
77
|
+
fid: getMeaAggKey(x.fid,x.aggName),
|
|
78
|
+
name: `${x.aggName}(${x.name})`
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return {fid: x.fid, name: x.name};
|
|
82
|
+
});
|
|
83
|
+
const result = `${headers.map(x=>x.name).join(',')}\n${data.map(x => headers.map(f => x[f.fid]).join(',')).join('\n')}`;
|
|
84
|
+
download(result, `${chart.name}.csv`, 'text/plain');
|
|
85
|
+
},
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}, [data,viewDimensions,viewMeasures,visualConfig.defaultAggregated]);
|
|
89
|
+
|
|
61
90
|
// Dependencies that should not trigger effect individually
|
|
62
91
|
const latestFromRef = useRef({
|
|
63
92
|
data,
|
package/src/vanilla.tsx
CHANGED
|
@@ -69,6 +69,7 @@ const FormContainer = styled.div`
|
|
|
69
69
|
interface IVisualSettings {
|
|
70
70
|
darkModePreference: IDarkMode;
|
|
71
71
|
rendererHandler?: React.RefObject<IReactVegaHandler>;
|
|
72
|
+
csvHandler?: React.MutableRefObject<{ download: () => void }>;
|
|
72
73
|
exclude?: string[];
|
|
73
74
|
extra?: ToolbarItemProps[];
|
|
74
75
|
}
|
|
@@ -76,6 +77,7 @@ interface IVisualSettings {
|
|
|
76
77
|
const VisualSettings: React.FC<IVisualSettings> = ({
|
|
77
78
|
rendererHandler,
|
|
78
79
|
darkModePreference,
|
|
80
|
+
csvHandler,
|
|
79
81
|
extra = [],
|
|
80
82
|
exclude = [],
|
|
81
83
|
}) => {
|
|
@@ -109,6 +111,13 @@ const VisualSettings: React.FC<IVisualSettings> = ({
|
|
|
109
111
|
[rendererHandler]
|
|
110
112
|
);
|
|
111
113
|
|
|
114
|
+
const downloadCSV = useCallback(
|
|
115
|
+
throttle(() => {
|
|
116
|
+
csvHandler?.current?.download();
|
|
117
|
+
}, 200),
|
|
118
|
+
[]
|
|
119
|
+
);
|
|
120
|
+
|
|
112
121
|
const dark = useCurrentMediaTheme(darkModePreference) === 'dark';
|
|
113
122
|
|
|
114
123
|
const items = useMemo<ToolbarItemProps[]>(() => {
|
|
@@ -524,6 +533,12 @@ const VisualSettings: React.FC<IVisualSettings> = ({
|
|
|
524
533
|
</FormContainer>
|
|
525
534
|
),
|
|
526
535
|
}]:[],
|
|
536
|
+
{
|
|
537
|
+
key: 'csv',
|
|
538
|
+
label: t('button.export_chart_as', { type: 'csv' }),
|
|
539
|
+
icon: TableCellsIcon,
|
|
540
|
+
onClick: downloadCSV,
|
|
541
|
+
},
|
|
527
542
|
{
|
|
528
543
|
key: 'config',
|
|
529
544
|
label: t('button.config'),
|