@kanaries/graphic-walker 0.2.12 → 0.2.14
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 +4 -2
- package/dist/assets/explainer.worker-8428eb12.js.map +1 -1
- package/dist/components/button/base.d.ts +1 -0
- package/dist/components/button/defaultMini.d.ts +4 -0
- package/dist/components/button/primaryMini.d.ts +4 -0
- package/dist/components/dataTable/index.d.ts +10 -0
- package/dist/components/dataTable/pagination.d.ts +10 -0
- package/dist/components/dropdownContext/index.d.ts +13 -0
- package/dist/components/dropdownSelect/index.d.ts +17 -0
- package/dist/components/modal.d.ts +1 -0
- package/dist/components/tabs/defaultTab.d.ts +14 -0
- package/dist/components/tabs/{pureTab.d.ts → editableTab.d.ts} +2 -2
- package/dist/components/toolbar/toolbar-item.d.ts +1 -0
- package/dist/dataSource/dataSelection/config.d.ts +2 -0
- package/dist/dataSource/datasetConfig/index.d.ts +3 -0
- package/dist/dataSource/index.d.ts +1 -1
- package/dist/fields/datasetFields/dimFields.d.ts +2 -2
- package/dist/fields/datasetFields/meaFields.d.ts +2 -2
- package/dist/fields/encodeFields/singleEncodeDropDown.d.ts +17 -0
- package/dist/fields/encodeFields/singleEncodeEditor.d.ts +11 -0
- package/dist/fields/obComponents/obPill.d.ts +3 -3
- package/dist/graphic-walker.es.js +21038 -19133
- package/dist/graphic-walker.es.js.map +1 -1
- package/dist/graphic-walker.umd.js +247 -170
- package/dist/graphic-walker.umd.js.map +1 -1
- package/dist/insightBoard/index.d.ts +1 -1
- package/dist/interfaces.d.ts +5 -0
- package/dist/renderer/index.d.ts +3 -1
- package/dist/segments/segmentNav.d.ts +3 -0
- package/dist/store/commonStore.d.ts +7 -1
- package/dist/store/visualSpecStore.d.ts +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/media.d.ts +2 -0
- package/dist/vis/react-vega.d.ts +2 -0
- package/dist/vis/theme.d.ts +130 -0
- package/package.json +2 -1
- package/src/App.tsx +74 -46
- package/src/components/button/base.ts +1 -0
- package/src/components/button/default.tsx +6 -2
- package/src/components/button/defaultMini.tsx +17 -0
- package/src/components/button/primary.tsx +6 -2
- package/src/components/button/primaryMini.tsx +21 -0
- package/src/components/callout.tsx +4 -1
- package/src/components/clickMenu.tsx +4 -2
- package/src/components/container.tsx +9 -0
- package/src/components/dataTable/index.tsx +177 -0
- package/src/components/dataTable/pagination.tsx +44 -0
- package/src/components/dataTypeIcon.tsx +1 -1
- package/src/components/dropdownContext/index.tsx +64 -0
- package/src/components/dropdownSelect/index.tsx +92 -0
- package/src/components/modal.tsx +26 -14
- package/src/components/tabs/defaultTab.tsx +43 -0
- package/src/components/tabs/{pureTab.tsx → editableTab.tsx} +7 -7
- package/src/components/toolbar/components.tsx +18 -1
- package/src/components/toolbar/index.tsx +5 -0
- package/src/components/toolbar/toolbar-button.tsx +6 -1
- package/src/components/toolbar/toolbar-item.tsx +4 -0
- package/src/components/toolbar/toolbar-select-button.tsx +21 -4
- package/src/components/toolbar/toolbar-toggle-button.tsx +6 -1
- package/src/components/tooltip.tsx +4 -1
- package/src/dataSource/dataSelection/config.ts +28 -0
- package/src/dataSource/dataSelection/csvData.tsx +77 -32
- package/src/dataSource/dataSelection/gwFile.tsx +0 -8
- package/src/dataSource/dataSelection/index.tsx +1 -2
- package/src/dataSource/dataSelection/publicData.tsx +2 -3
- package/src/dataSource/datasetConfig/index.tsx +21 -0
- package/src/dataSource/index.tsx +81 -61
- package/src/dataSource/table.tsx +11 -155
- package/src/fields/aestheticFields.tsx +3 -1
- package/src/fields/components.tsx +21 -2
- package/src/fields/datasetFields/dimFields.tsx +43 -35
- package/src/fields/datasetFields/index.tsx +2 -2
- package/src/fields/datasetFields/meaFields.tsx +73 -47
- package/src/fields/encodeFields/singleEncodeDropDown.tsx +92 -0
- package/src/fields/encodeFields/singleEncodeEditor.tsx +78 -0
- package/src/fields/filterField/filterEditDialog.tsx +2 -1
- package/src/fields/filterField/filterPill.tsx +1 -1
- package/src/fields/filterField/slider.tsx +1 -1
- package/src/fields/filterField/tabs.tsx +11 -21
- package/src/fields/obComponents/obPill.tsx +65 -35
- package/src/index.css +13 -0
- package/src/insightBoard/index.tsx +24 -23
- package/src/insightBoard/radioGroupButtons.tsx +7 -0
- package/src/interfaces.ts +6 -0
- package/src/lib/inferMeta.ts +1 -1
- package/src/locales/en-US.json +14 -3
- package/src/locales/zh-CN.json +12 -1
- package/src/main.tsx +1 -1
- package/src/renderer/index.tsx +3 -1
- package/src/segments/segmentNav.tsx +58 -0
- package/src/segments/visNav.tsx +2 -2
- package/src/store/commonStore.ts +28 -2
- package/src/store/visualSpecStore.ts +16 -0
- package/src/utils/index.ts +19 -0
- package/src/utils/media.ts +26 -0
- package/src/utils/normalization.ts +2 -1
- package/src/vis/react-vega.tsx +20 -4
- package/src/vis/theme.ts +126 -0
- package/src/visualSettings/index.tsx +24 -8
|
@@ -16,7 +16,21 @@ const OptionGroup = styled(ToolbarContainer)`
|
|
|
16
16
|
--color: #777;
|
|
17
17
|
--color-hover: #555;
|
|
18
18
|
--blue: #282958;
|
|
19
|
+
--dark-mode-background-color: #1f1f1f;
|
|
20
|
+
--dark-mode-background-color-hover: #2f2f2f;
|
|
21
|
+
--dark-mode-color: #aaa;
|
|
22
|
+
--dark-mode-color-hover: #ccc;
|
|
23
|
+
--dark-mode-blue: #282958;
|
|
19
24
|
background-color: var(--background-color);
|
|
25
|
+
// dark mode
|
|
26
|
+
@media (prefers-color-scheme: dark) {
|
|
27
|
+
/* --dark-mode-background-color: #1f1f1f;
|
|
28
|
+
--dark-mode-background-color-hover: #2f2f2f;
|
|
29
|
+
--dark-mode-color: #aaa;
|
|
30
|
+
--dark-mode-color-hover: #ccc;
|
|
31
|
+
--dark-mode-blue: #282958; */
|
|
32
|
+
background-color: var(--dark-mode-background-color);
|
|
33
|
+
}
|
|
20
34
|
`;
|
|
21
35
|
|
|
22
36
|
const Option = styled(ToolbarItemContainerElement)`
|
|
@@ -115,6 +129,11 @@ const ToolbarSelectButton = memo<IToolbarProps<ToolbarSelectButtonItem>>(functio
|
|
|
115
129
|
const currentOption = options.find(opt => opt.key === value);
|
|
116
130
|
const CurrentIcon = currentOption?.icon;
|
|
117
131
|
|
|
132
|
+
const mergedIconStyles = {
|
|
133
|
+
...styles?.icon,
|
|
134
|
+
...item.styles?.icon,
|
|
135
|
+
};
|
|
136
|
+
|
|
118
137
|
return (
|
|
119
138
|
<>
|
|
120
139
|
<ToolbarItemContainer
|
|
@@ -126,20 +145,18 @@ const ToolbarSelectButton = memo<IToolbarProps<ToolbarSelectButtonItem>>(functio
|
|
|
126
145
|
handlers={handlers}
|
|
127
146
|
aria-haspopup="listbox"
|
|
128
147
|
>
|
|
129
|
-
<Icon style={
|
|
148
|
+
<Icon style={mergedIconStyles} />
|
|
130
149
|
{CurrentIcon && (
|
|
131
150
|
<CurrentIcon
|
|
132
151
|
style={{
|
|
133
|
-
...styles?.icon,
|
|
134
152
|
position: 'absolute',
|
|
135
153
|
left: 'calc(var(--height) - var(--icon-size) * 1.2)',
|
|
136
154
|
bottom: 'calc((var(--height) - var(--icon-size)) * 0.1)',
|
|
137
155
|
width: 'calc(var(--icon-size) * 0.6)',
|
|
138
156
|
height: 'calc(var(--icon-size) * 0.6)',
|
|
139
157
|
margin: 'calc((var(--height) - var(--icon-size)) * 0.2)',
|
|
140
|
-
filter: 'drop-shadow(0 0 0.5px var(--background-color)) '.repeat(4),
|
|
141
158
|
pointerEvents: 'none',
|
|
142
|
-
|
|
159
|
+
...mergedIconStyles,
|
|
143
160
|
}}
|
|
144
161
|
/>
|
|
145
162
|
)}
|
|
@@ -50,6 +50,11 @@ const ToolbarToggleButton = memo<IToolbarProps<ToolbarToggleButtonItem>>(functio
|
|
|
50
50
|
const { icon: Icon, label, disabled, checked, onChange } = item;
|
|
51
51
|
const handlers = useHandlers(() => onChange(!checked), disabled ?? false);
|
|
52
52
|
|
|
53
|
+
const mergedIconStyles = {
|
|
54
|
+
...styles?.icon,
|
|
55
|
+
...item.styles?.icon,
|
|
56
|
+
};
|
|
57
|
+
|
|
53
58
|
return (
|
|
54
59
|
<>
|
|
55
60
|
<ToolbarItemContainer
|
|
@@ -59,7 +64,7 @@ const ToolbarToggleButton = memo<IToolbarProps<ToolbarToggleButtonItem>>(functio
|
|
|
59
64
|
aria-checked={checked}
|
|
60
65
|
>
|
|
61
66
|
<ToggleContainer checked={checked}>
|
|
62
|
-
<Icon style={
|
|
67
|
+
<Icon style={mergedIconStyles} />
|
|
63
68
|
</ToggleContainer>
|
|
64
69
|
</ToolbarItemContainer>
|
|
65
70
|
</>
|
|
@@ -32,6 +32,9 @@ const Bubble = styled.div`
|
|
|
32
32
|
height: 8px;
|
|
33
33
|
transform: translate(-50%, 50%) rotate(45deg);
|
|
34
34
|
background-color: #fff;
|
|
35
|
+
@media (prefers-color-scheme: dark) {
|
|
36
|
+
background-color: #000;
|
|
37
|
+
}
|
|
35
38
|
border-radius: 1px;
|
|
36
39
|
}
|
|
37
40
|
`;
|
|
@@ -125,7 +128,7 @@ const Tooltip = memo<TooltipProps>(function Tooltip({
|
|
|
125
128
|
root &&
|
|
126
129
|
createPortal(
|
|
127
130
|
<Bubble
|
|
128
|
-
className="fixed text-xs p-1 px-3 text-gray-500 bg-white z-50"
|
|
131
|
+
className="fixed text-xs p-1 px-3 text-gray-500 bg-white dark:bg-zinc-900 z-50"
|
|
129
132
|
onMouseOver={() => setHover(true)}
|
|
130
133
|
onMouseOut={() => setHover(false)}
|
|
131
134
|
style={{ left: pos[0], top: pos[1] - 4 }}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { IDropdownSelectOption } from "../../components/dropdownSelect";
|
|
2
|
+
|
|
3
|
+
export const charsetOptions: IDropdownSelectOption[] = [
|
|
4
|
+
{
|
|
5
|
+
label: 'UTF-8',
|
|
6
|
+
value: 'utf-8',
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
label: 'GB2312',
|
|
10
|
+
value: 'gb2312',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
label: 'US-ASCII',
|
|
14
|
+
value: 'us-ascii',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
label: 'Big5',
|
|
18
|
+
value: 'big5',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
label: 'Big5-HKSCS',
|
|
22
|
+
value: 'Big5-HKSCS',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
label: 'GB18030',
|
|
26
|
+
value: 'GB18030',
|
|
27
|
+
},
|
|
28
|
+
]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useRef, useCallback } from "react";
|
|
1
|
+
import React, { useRef, useCallback, useState } from "react";
|
|
2
2
|
import { FileReader } from "@kanaries/web-data-loader";
|
|
3
3
|
import { IRow } from "../../interfaces";
|
|
4
4
|
import Table from "../table";
|
|
@@ -8,25 +8,51 @@ import { observer } from "mobx-react-lite";
|
|
|
8
8
|
import { useTranslation } from "react-i18next";
|
|
9
9
|
import DefaultButton from "../../components/button/default";
|
|
10
10
|
import PrimaryButton from "../../components/button/primary";
|
|
11
|
+
import DropdownSelect from "../../components/dropdownSelect";
|
|
12
|
+
import { charsetOptions } from "./config";
|
|
11
13
|
|
|
12
14
|
const Container = styled.div`
|
|
13
15
|
overflow-x: auto;
|
|
16
|
+
min-height: 300px;
|
|
14
17
|
`;
|
|
15
18
|
|
|
16
19
|
interface ICSVData {}
|
|
17
20
|
const CSVData: React.FC<ICSVData> = (props) => {
|
|
18
21
|
const fileRef = useRef<HTMLInputElement>(null);
|
|
19
22
|
const { commonStore } = useGlobalStore();
|
|
20
|
-
const { tmpDSName, tmpDataSource } = commonStore;
|
|
23
|
+
const { tmpDSName, tmpDataSource, tmpDSRawFields } = commonStore;
|
|
24
|
+
const [encoding, setEncoding] = useState<string>("utf-8");
|
|
21
25
|
|
|
22
26
|
const onSubmitData = useCallback(() => {
|
|
23
27
|
commonStore.commitTempDS();
|
|
24
28
|
}, []);
|
|
25
29
|
|
|
26
30
|
const { t } = useTranslation("translation", { keyPrefix: "DataSource.dialog.file" });
|
|
31
|
+
const fileLoaded = tmpDataSource.length > 0 && tmpDSRawFields.length > 0;
|
|
27
32
|
|
|
28
33
|
return (
|
|
29
34
|
<Container>
|
|
35
|
+
{!fileLoaded && (
|
|
36
|
+
<div className="text-center">
|
|
37
|
+
<svg
|
|
38
|
+
className="mx-auto h-12 w-12 text-gray-400"
|
|
39
|
+
fill="none"
|
|
40
|
+
viewBox="0 0 24 24"
|
|
41
|
+
stroke="currentColor"
|
|
42
|
+
aria-hidden="true"
|
|
43
|
+
>
|
|
44
|
+
<path
|
|
45
|
+
vectorEffect="non-scaling-stroke"
|
|
46
|
+
strokeLinecap="round"
|
|
47
|
+
strokeLinejoin="round"
|
|
48
|
+
strokeWidth={2}
|
|
49
|
+
d="M9 13h6m-3-3v6m-9 1V7a2 2 0 012-2h6l2 2h6a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2z"
|
|
50
|
+
/>
|
|
51
|
+
</svg>
|
|
52
|
+
<h3 className="mt-2 text-sm font-semibold text-gray-900">{t('choose_file')}</h3>
|
|
53
|
+
<p className="mt-1 text-sm text-gray-500">{t('get_start_desc')}</p>
|
|
54
|
+
</div>
|
|
55
|
+
)}
|
|
30
56
|
<input
|
|
31
57
|
style={{ display: "none" }}
|
|
32
58
|
type="file"
|
|
@@ -39,42 +65,61 @@ const CSVData: React.FC<ICSVData> = (props) => {
|
|
|
39
65
|
file,
|
|
40
66
|
config: { type: "reservoirSampling", size: Infinity },
|
|
41
67
|
onLoading: () => {},
|
|
68
|
+
encoding,
|
|
42
69
|
}).then((data) => {
|
|
43
70
|
commonStore.updateTempDS(data as IRow[]);
|
|
44
71
|
});
|
|
45
72
|
}
|
|
46
73
|
}}
|
|
47
74
|
/>
|
|
48
|
-
|
|
49
|
-
<
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
{!fileLoaded && (
|
|
76
|
+
<div className="my-1 flex justify-center">
|
|
77
|
+
<DefaultButton
|
|
78
|
+
className="mr-2"
|
|
79
|
+
onClick={() => {
|
|
80
|
+
if (fileRef.current) {
|
|
81
|
+
fileRef.current.click();
|
|
82
|
+
}
|
|
83
|
+
}}
|
|
84
|
+
text={t("open")}
|
|
85
|
+
/>
|
|
86
|
+
<div className="inline-block relative">
|
|
87
|
+
<DropdownSelect
|
|
88
|
+
buttonClassName="w-36"
|
|
89
|
+
options={charsetOptions}
|
|
90
|
+
selectedKey={encoding}
|
|
91
|
+
onSelect={(k) => {
|
|
92
|
+
setEncoding(k);
|
|
93
|
+
}}
|
|
94
|
+
/>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
)}
|
|
98
|
+
{fileLoaded && (
|
|
99
|
+
<div className="mb-2 mt-6">
|
|
100
|
+
<label className="block text-xs text-gray-800 dark:text-gray-200 mb-1 font-bold">
|
|
101
|
+
{t("dataset_name")}
|
|
102
|
+
</label>
|
|
103
|
+
<input
|
|
104
|
+
type="text"
|
|
105
|
+
placeholder={t("dataset_name")}
|
|
106
|
+
value={tmpDSName}
|
|
107
|
+
onChange={(e) => {
|
|
108
|
+
commonStore.updateTempName(e.target.value);
|
|
109
|
+
}}
|
|
110
|
+
className="text-xs mr-2 p-2 rounded border border-gray-200 dark:border-gray-800 outline-none focus:outline-none focus:border-blue-500 placeholder:italic placeholder:text-slate-400 dark:bg-stone-900"
|
|
111
|
+
/>
|
|
112
|
+
<PrimaryButton
|
|
113
|
+
className="mr-2"
|
|
114
|
+
text={t("submit")}
|
|
115
|
+
disabled={tmpDataSource.length === 0}
|
|
116
|
+
onClick={() => {
|
|
117
|
+
onSubmitData();
|
|
118
|
+
}}
|
|
119
|
+
/>
|
|
120
|
+
</div>
|
|
121
|
+
)}
|
|
122
|
+
{fileLoaded && <Table />}
|
|
78
123
|
</Container>
|
|
79
124
|
);
|
|
80
125
|
};
|
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
import React, { useRef, useCallback } from "react";
|
|
2
|
-
import { FileReader } from "@kanaries/web-data-loader";
|
|
3
|
-
import { IRow } from "../../interfaces";
|
|
4
|
-
import Table from "../table";
|
|
5
|
-
import styled from "styled-components";
|
|
6
2
|
import { useGlobalStore } from "../../store";
|
|
7
3
|
import { observer } from "mobx-react-lite";
|
|
8
|
-
import { useTranslation } from "react-i18next";
|
|
9
4
|
|
|
10
|
-
const Container = styled.div`
|
|
11
|
-
overflow-x: auto;
|
|
12
|
-
`;
|
|
13
5
|
|
|
14
6
|
interface GWFileProps {
|
|
15
7
|
fileRef: React.RefObject<HTMLInputElement>;
|
|
@@ -3,7 +3,7 @@ import { useState } from "react";
|
|
|
3
3
|
import CSVData from "./csvData";
|
|
4
4
|
import PublicData from "./publicData";
|
|
5
5
|
import { useTranslation } from "react-i18next";
|
|
6
|
-
import PureTabs from "../../components/tabs/
|
|
6
|
+
import PureTabs from "../../components/tabs/defaultTab";
|
|
7
7
|
|
|
8
8
|
const DataSelection: React.FC = (props) => {
|
|
9
9
|
const [sourceType, setSourceType] = useState<"file" | "public">("file");
|
|
@@ -26,7 +26,6 @@ const DataSelection: React.FC = (props) => {
|
|
|
26
26
|
setSourceType(sk as "public" | "file");
|
|
27
27
|
}}
|
|
28
28
|
/>
|
|
29
|
-
<hr className="mt-1 mb-1" />
|
|
30
29
|
{sourceType === "file" && <CSVData />}
|
|
31
30
|
{sourceType === "public" && <PublicData />}
|
|
32
31
|
</div>
|
|
@@ -36,20 +36,19 @@ const PublicData: React.FC<IPublicDataProps> = props => {
|
|
|
36
36
|
})
|
|
37
37
|
})
|
|
38
38
|
}}
|
|
39
|
-
className="border rounded border-gray-300 p-2 m-2 cursor-pointer hover:bg-gray-50"
|
|
39
|
+
className="border rounded border-gray-300 dark:border-gray-600 p-2 m-2 cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 dark:text-gray-200"
|
|
40
40
|
>
|
|
41
41
|
<div>{data.title}</div>
|
|
42
42
|
{/* <p>{data.title}</p> */}
|
|
43
43
|
</div>)
|
|
44
44
|
}
|
|
45
45
|
</div>
|
|
46
|
-
<hr className="m-1" />
|
|
47
46
|
<PrimaryButton
|
|
47
|
+
className='my-1'
|
|
48
48
|
disabled={tmpDataSource.length === 0}
|
|
49
49
|
onClick={() => { commonStore.commitTempDS() }}
|
|
50
50
|
text={t('submit')}
|
|
51
51
|
/>
|
|
52
|
-
<hr className="m-1" />
|
|
53
52
|
<Table />
|
|
54
53
|
</div>
|
|
55
54
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import DatasetTable from "../../components/dataTable";
|
|
3
|
+
import { observer } from "mobx-react-lite";
|
|
4
|
+
import { useGlobalStore } from "../../store";
|
|
5
|
+
|
|
6
|
+
const DatasetConfig: React.FC = (props) => {
|
|
7
|
+
const { commonStore, vizStore } = useGlobalStore();
|
|
8
|
+
const { currentDataset } = commonStore;
|
|
9
|
+
const { dataSource, rawFields } = currentDataset;
|
|
10
|
+
return (
|
|
11
|
+
<div>
|
|
12
|
+
<DatasetTable size={100} data={dataSource} metas={rawFields}
|
|
13
|
+
onMetaChange={(fid, fIndex, diffMeta) => {
|
|
14
|
+
commonStore.updateCurrentDatasetMetas(fid, diffMeta)
|
|
15
|
+
}}
|
|
16
|
+
/>
|
|
17
|
+
</div>
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default observer(DatasetConfig);
|
package/src/dataSource/index.tsx
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
|
-
import React, { useRef } from
|
|
2
|
-
import { observer } from
|
|
3
|
-
import { CheckCircleIcon, ArrowPathIcon } from
|
|
4
|
-
import { useTranslation } from
|
|
5
|
-
import { Container } from
|
|
6
|
-
import Modal from
|
|
7
|
-
import { useGlobalStore } from
|
|
8
|
-
import { download } from
|
|
9
|
-
import GwFile from
|
|
10
|
-
import DataSelection from
|
|
11
|
-
import DefaultButton from
|
|
1
|
+
import React, { useRef } from "react";
|
|
2
|
+
import { observer } from "mobx-react-lite";
|
|
3
|
+
import { CheckCircleIcon, ArrowPathIcon } from "@heroicons/react/24/outline";
|
|
4
|
+
import { useTranslation } from "react-i18next";
|
|
5
|
+
import { Container } from "../components/container";
|
|
6
|
+
import Modal from "../components/modal";
|
|
7
|
+
import { useGlobalStore } from "../store";
|
|
8
|
+
import { download } from "../utils/save";
|
|
9
|
+
import GwFile from "./dataSelection/gwFile";
|
|
10
|
+
import DataSelection from "./dataSelection";
|
|
11
|
+
import DefaultButton from "../components/button/default";
|
|
12
|
+
import DropdownSelect from "../components/dropdownSelect";
|
|
13
|
+
import PrimaryButton from "../components/button/primary";
|
|
12
14
|
|
|
13
15
|
interface DSSegmentProps {
|
|
14
16
|
preWorkDone: boolean;
|
|
15
17
|
}
|
|
16
18
|
|
|
17
|
-
const DataSourceSegment: React.FC<DSSegmentProps> = props => {
|
|
19
|
+
const DataSourceSegment: React.FC<DSSegmentProps> = (props) => {
|
|
18
20
|
const { preWorkDone } = props;
|
|
19
21
|
const { commonStore, vizStore } = useGlobalStore();
|
|
20
22
|
const gwFileRef = useRef<HTMLInputElement>(null);
|
|
@@ -22,55 +24,73 @@ const DataSourceSegment: React.FC<DSSegmentProps> = props => {
|
|
|
22
24
|
|
|
23
25
|
const { currentDataset, datasets, showDSPanel } = commonStore;
|
|
24
26
|
|
|
25
|
-
return
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
{
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
27
|
+
return (
|
|
28
|
+
<Container className="flex items-center">
|
|
29
|
+
<GwFile fileRef={gwFileRef} />
|
|
30
|
+
{!preWorkDone && (
|
|
31
|
+
<div className="animate-spin inline-block mr-2 ml-2 w-4 h-4 rounded-full border-t-2 border-l-2 border-blue-500"></div>
|
|
32
|
+
)}
|
|
33
|
+
{/* <label className="text-xs mr-1 whitespace-nowrap self-center h-4">
|
|
34
|
+
{t("DataSource.labels.cur_dataset")}
|
|
35
|
+
</label> */}
|
|
36
|
+
<div className="mr-2">
|
|
37
|
+
<DropdownSelect
|
|
38
|
+
options={datasets.map((d) => ({ label: d.name, value: d.id }))}
|
|
39
|
+
selectedKey={currentDataset.id}
|
|
40
|
+
onSelect={(dsKey) => {
|
|
41
|
+
commonStore.useDS(dsKey);
|
|
42
|
+
}}
|
|
43
|
+
placeholder={t("DataSource.labels.cur_dataset")}
|
|
44
|
+
/>
|
|
45
|
+
</div>
|
|
42
46
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
47
|
+
<PrimaryButton
|
|
48
|
+
className="mr-2"
|
|
49
|
+
text={t("DataSource.buttons.create_dataset")}
|
|
50
|
+
onClick={() => {
|
|
51
|
+
commonStore.startDSBuildingTask();
|
|
52
|
+
}}
|
|
53
|
+
/>
|
|
54
|
+
<DefaultButton
|
|
55
|
+
className="mr-2"
|
|
56
|
+
text={t("DataSource.buttons.export_as_file")}
|
|
57
|
+
onClick={() => {
|
|
58
|
+
const res = vizStore.exportAsRaw();
|
|
59
|
+
download(res, "graphic-walker-notebook.json", "text/plain");
|
|
60
|
+
}}
|
|
61
|
+
/>
|
|
62
|
+
<DefaultButton
|
|
63
|
+
className="mr-2"
|
|
64
|
+
text={t("DataSource.buttons.import_file")}
|
|
65
|
+
onClick={() => {
|
|
66
|
+
if (gwFileRef.current) {
|
|
67
|
+
gwFileRef.current.click();
|
|
68
|
+
}
|
|
69
|
+
}}
|
|
70
|
+
/>
|
|
63
71
|
<Modal
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
72
|
+
title={t("DataSource.dialog.create_data_source")}
|
|
73
|
+
onClose={() => {
|
|
74
|
+
commonStore.setShowDSPanel(false);
|
|
75
|
+
}}
|
|
76
|
+
show={showDSPanel}
|
|
77
|
+
>
|
|
78
|
+
<DataSelection />
|
|
79
|
+
</Modal>
|
|
80
|
+
{/* {showDSPanel && (
|
|
81
|
+
<Modal
|
|
82
|
+
title={t("DataSource.dialog.create_data_source")}
|
|
83
|
+
onClose={() => {
|
|
84
|
+
commonStore.setShowDSPanel(false);
|
|
85
|
+
}}
|
|
86
|
+
>
|
|
87
|
+
<DataSelection />
|
|
88
|
+
</Modal>
|
|
89
|
+
)} */}
|
|
90
|
+
{preWorkDone && <CheckCircleIcon className="text-green-500 w-5 inline-block ml-2" />}
|
|
91
|
+
{!preWorkDone && <ArrowPathIcon className="text-yellow-500 w-5 inline-block ml-2" />}
|
|
92
|
+
</Container>
|
|
93
|
+
);
|
|
94
|
+
};
|
|
75
95
|
|
|
76
|
-
export default observer(DataSourceSegment);
|
|
96
|
+
export default observer(DataSourceSegment);
|