@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.
- package/dist/App.d.ts +5 -2
- package/dist/assets/explainer.worker-8428eb12.js.map +1 -1
- package/dist/assets/transform.worker-5d54ff09.js.map +1 -0
- package/dist/assets/viewQuery.worker-ffefc111.js.map +1 -0
- package/dist/components/callout.d.ts +2 -0
- package/dist/components/codeExport/index.d.ts +3 -0
- package/dist/components/loadingLayer.d.ts +2 -0
- package/dist/components/tabs/defaultTab.d.ts +1 -0
- package/dist/components/tabs/editableTab.d.ts +1 -2
- package/dist/components/toolbar/components.d.ts +4 -1
- package/dist/components/toolbar/index.d.ts +2 -0
- package/dist/components/toolbar/toolbar-item.d.ts +3 -0
- package/dist/components/tooltip.d.ts +2 -0
- package/dist/dataSource/dataSelection/config.d.ts +1 -0
- package/dist/dataSource/dataSelection/utils.d.ts +2 -0
- package/dist/datasets/tmp/test.json +1 -0
- package/dist/fields/components.d.ts +0 -1
- package/dist/fields/filterField/filterEditDialog.d.ts +1 -1
- package/dist/graphic-walker.es.js +23930 -23320
- package/dist/graphic-walker.es.js.map +1 -1
- package/dist/graphic-walker.umd.js +143 -273
- package/dist/graphic-walker.umd.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/interfaces.d.ts +23 -1
- package/dist/lib/execExp.d.ts +8 -0
- package/dist/lib/interfaces.d.ts +22 -0
- package/dist/lib/op/aggregate.d.ts +3 -0
- package/dist/lib/op/bin.d.ts +3 -0
- package/dist/lib/op/fold.d.ts +3 -0
- package/dist/lib/op/stat.d.ts +8 -0
- package/dist/lib/viewQuery.d.ts +5 -0
- package/dist/models/visSpecHistory.d.ts +2 -0
- package/dist/renderer/index.d.ts +6 -3
- package/dist/renderer/specRenderer.d.ts +13 -0
- package/dist/services.d.ts +4 -1
- package/dist/store/commonStore.d.ts +6 -0
- package/dist/store/index.d.ts +3 -2
- package/dist/store/visualSpecStore.d.ts +11 -4
- package/dist/utils/dataPrep.d.ts +2 -0
- package/dist/utils/index.d.ts +3 -5
- package/dist/utils/media.d.ts +2 -1
- package/dist/utils/save.d.ts +1 -2
- package/dist/vis/react-vega.d.ts +4 -23
- package/dist/vis/spec/aggregate.d.ts +4 -0
- package/dist/vis/spec/encode.d.ts +19 -0
- package/dist/vis/spec/field.d.ts +2 -0
- package/dist/vis/spec/mark.d.ts +7 -0
- package/dist/vis/spec/stack.d.ts +4 -0
- package/dist/vis/spec/view.d.ts +67 -0
- package/dist/vis/theme.d.ts +36 -20
- package/dist/visualSettings/index.d.ts +2 -1
- package/dist/workers/transform.d.ts +2 -0
- package/package.json +4 -3
- package/src/App.tsx +23 -15
- package/src/components/callout.tsx +9 -7
- package/src/components/clickMenu.tsx +1 -7
- package/src/components/codeExport/index.tsx +114 -0
- package/src/components/dataTable/index.tsx +10 -10
- package/src/components/loadingLayer.tsx +7 -0
- package/src/components/modal.tsx +1 -15
- package/src/components/sizeSetting.tsx +2 -2
- package/src/components/tabs/defaultTab.tsx +4 -2
- package/src/components/tabs/editableTab.tsx +75 -40
- package/src/components/toolbar/components.tsx +8 -23
- package/src/components/toolbar/index.tsx +11 -4
- package/src/components/toolbar/toolbar-button.tsx +2 -1
- package/src/components/toolbar/toolbar-item.tsx +17 -12
- package/src/components/toolbar/toolbar-select-button.tsx +9 -13
- package/src/components/toolbar/toolbar-toggle-button.tsx +2 -1
- package/src/components/tooltip.tsx +10 -6
- package/src/dataSource/dataSelection/config.ts +11 -0
- package/src/dataSource/dataSelection/csvData.tsx +72 -40
- package/src/dataSource/dataSelection/gwFile.tsx +2 -2
- package/src/dataSource/dataSelection/utils.ts +28 -0
- package/src/dataSource/index.tsx +2 -3
- package/src/dataSource/utils.ts +8 -3
- package/src/fields/components.tsx +13 -50
- package/src/fields/datasetFields/index.tsx +3 -4
- package/src/fields/datasetFields/meaFields.tsx +12 -4
- package/src/fields/encodeFields/singleEncodeEditor.tsx +1 -1
- package/src/fields/filterField/filterEditDialog.tsx +63 -99
- package/src/fields/filterField/slider.tsx +1 -1
- package/src/index.css +4 -4
- package/src/index.tsx +22 -22
- package/src/insightBoard/mainBoard.tsx +9 -2
- package/src/interfaces.ts +30 -3
- package/src/lib/execExp.ts +147 -0
- package/src/lib/interfaces.ts +39 -0
- package/src/lib/op/aggregate.ts +49 -0
- package/src/lib/op/bin.ts +25 -0
- package/src/lib/op/fold.ts +17 -0
- package/src/lib/op/stat.ts +46 -0
- package/src/lib/viewQuery.ts +23 -0
- package/src/locales/en-US.json +8 -3
- package/src/locales/i18n.ts +7 -1
- package/src/locales/ja-JP.json +197 -0
- package/src/locales/zh-CN.json +8 -3
- package/src/main.tsx +1 -1
- package/src/models/visSpecHistory.ts +14 -0
- package/src/renderer/index.tsx +58 -101
- package/src/renderer/specRenderer.tsx +119 -0
- package/src/segments/segmentNav.tsx +3 -16
- package/src/segments/visNav.tsx +17 -6
- package/src/services.ts +37 -1
- package/src/store/commonStore.ts +14 -9
- package/src/store/index.tsx +11 -4
- package/src/store/visualSpecStore.ts +89 -50
- package/src/utils/dataPrep.ts +24 -0
- package/src/utils/index.ts +16 -17
- package/src/utils/media.ts +16 -11
- package/src/utils/normalization.ts +3 -1
- package/src/utils/save.ts +1 -2
- package/src/vis/react-vega.tsx +11 -332
- package/src/vis/spec/aggregate.ts +13 -0
- package/src/vis/spec/encode.ts +69 -0
- package/src/vis/spec/field.ts +10 -0
- package/src/vis/spec/mark.ts +30 -0
- package/src/vis/spec/stack.ts +11 -0
- package/src/vis/spec/view.ts +138 -0
- package/src/vis/theme.ts +35 -25
- package/src/visualSettings/index.tsx +22 -33
- package/src/workers/transform.ts +12 -0
- package/src/workers/transform.worker.js +13 -0
- package/src/workers/viewQuery.worker.js +16 -0
- package/dist/components/container.d.ts +0 -2
- package/dist/dataSource/pannel.d.ts +0 -5
- package/src/components/container.tsx +0 -25
- package/src/dataSource/pannel.tsx +0 -71
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { IExpParamter, IExpression, IField, IRow } from "../interfaces";
|
|
2
|
+
|
|
3
|
+
interface IDataFrame {
|
|
4
|
+
[key: string]: any[];
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function execExpression (exp: IExpression, dataFrame: IDataFrame, columns: IField[]): IDataFrame {
|
|
8
|
+
const { op, params } = exp;
|
|
9
|
+
const subFrame: IDataFrame = { ...dataFrame };
|
|
10
|
+
const len = dataFrame[Object.keys(dataFrame)[0]].length;
|
|
11
|
+
for (let param of params) {
|
|
12
|
+
switch (param.type) {
|
|
13
|
+
case 'field':
|
|
14
|
+
subFrame[param.value] = dataFrame[param.value];
|
|
15
|
+
break;
|
|
16
|
+
case 'constant':
|
|
17
|
+
subFrame[param.value] = new Array(len).fill(param.value);
|
|
18
|
+
break;
|
|
19
|
+
case 'expression':
|
|
20
|
+
let f = execExpression(param.value, dataFrame, columns);
|
|
21
|
+
Object.keys(f).forEach(key => {
|
|
22
|
+
subFrame[key] = f[key];
|
|
23
|
+
})
|
|
24
|
+
break;
|
|
25
|
+
case 'value':
|
|
26
|
+
default:
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
switch (op) {
|
|
31
|
+
case 'one':
|
|
32
|
+
return one(exp.as, params, subFrame);
|
|
33
|
+
case 'bin':
|
|
34
|
+
return bin(exp.as, params, subFrame);
|
|
35
|
+
case 'log2':
|
|
36
|
+
return log2(exp.as, params, subFrame);
|
|
37
|
+
case 'log10':
|
|
38
|
+
return log10(exp.as, params, subFrame);
|
|
39
|
+
case 'binCount':
|
|
40
|
+
return binCount(exp.as, params, subFrame);
|
|
41
|
+
default:
|
|
42
|
+
return subFrame;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function bin(resKey: string, params: IExpParamter[], data: IDataFrame, binSize: number | undefined = 10): IDataFrame {
|
|
47
|
+
const { value: fieldKey } = params[0];
|
|
48
|
+
const fieldValues = data[fieldKey] as number[];
|
|
49
|
+
let _min = Infinity;
|
|
50
|
+
let _max = -Infinity;
|
|
51
|
+
for (let i = 0; i < fieldValues.length; i++) {
|
|
52
|
+
let val = fieldValues[i];
|
|
53
|
+
if (val > _max) _max = val;
|
|
54
|
+
if (val < _min) _min = val;
|
|
55
|
+
}
|
|
56
|
+
const step = (_max - _min) / binSize;
|
|
57
|
+
const beaStep = Math.max(-Math.round(Math.log10(_max - _min)) + 2, 0)
|
|
58
|
+
const newValues = fieldValues.map((v: number) => {
|
|
59
|
+
let bIndex = Math.floor((v - _min) / step);
|
|
60
|
+
if (bIndex === binSize) bIndex = binSize - 1;
|
|
61
|
+
return Number(((bIndex * step + _min)).toFixed(beaStep))
|
|
62
|
+
});
|
|
63
|
+
return {
|
|
64
|
+
...data,
|
|
65
|
+
[resKey]: newValues,
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function binCount(resKey: string, params: IExpParamter[], data: IDataFrame, binSize: number | undefined = 10): IDataFrame {
|
|
70
|
+
const { value: fieldKey } = params[0];
|
|
71
|
+
const fieldValues = data[fieldKey] as number[];
|
|
72
|
+
|
|
73
|
+
const valueWithIndices: {val: number; index: number; orderIndex: number }[] = fieldValues.map((v, i) => ({
|
|
74
|
+
val: v,
|
|
75
|
+
index: i
|
|
76
|
+
})).sort((a, b) => a.val - b.val)
|
|
77
|
+
.map((item, i) => ({
|
|
78
|
+
val: item.val,
|
|
79
|
+
index: item.index,
|
|
80
|
+
orderIndex: i
|
|
81
|
+
}))
|
|
82
|
+
|
|
83
|
+
const groupSize = valueWithIndices.length / binSize;
|
|
84
|
+
|
|
85
|
+
const newValues = valueWithIndices.map(item => {
|
|
86
|
+
let bIndex = Math.floor(item.orderIndex / groupSize);
|
|
87
|
+
if (bIndex === binSize) bIndex = binSize - 1;
|
|
88
|
+
return bIndex + 1
|
|
89
|
+
})
|
|
90
|
+
return {
|
|
91
|
+
...data,
|
|
92
|
+
[resKey]: newValues,
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function log2(resKey: string, params: IExpParamter[], data: IDataFrame): IDataFrame {
|
|
97
|
+
const { value } = params[0];
|
|
98
|
+
const field = data[value];
|
|
99
|
+
const newField = field.map((v: number) => Math.log2(v));
|
|
100
|
+
return {
|
|
101
|
+
...data,
|
|
102
|
+
[resKey]: newField,
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function log10(resKey: string, params: IExpParamter[], data: IDataFrame): IDataFrame {
|
|
107
|
+
const { value: fieldKey } = params[0];
|
|
108
|
+
const fieldValues = data[fieldKey];
|
|
109
|
+
const newField = fieldValues.map((v: number) => Math.log10(v));
|
|
110
|
+
return {
|
|
111
|
+
...data,
|
|
112
|
+
[resKey]: newField,
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function one(resKey: string, params: IExpParamter[], data: IDataFrame): IDataFrame {
|
|
117
|
+
// const { value: fieldKey } = params[0];
|
|
118
|
+
if (Object.keys(data).length === 0) return data;
|
|
119
|
+
const len = data[Object.keys(data)[0]].length;
|
|
120
|
+
const newField = new Array(len).fill(1);
|
|
121
|
+
return {
|
|
122
|
+
...data,
|
|
123
|
+
[resKey]: newField,
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function dataset2DataFrame(dataset: IRow[], columns: IField[]): IDataFrame {
|
|
128
|
+
const dataFrame: IDataFrame = {};
|
|
129
|
+
columns.forEach((col) => {
|
|
130
|
+
dataFrame[col.fid] = dataset.map((row) => row[col.fid]);
|
|
131
|
+
});
|
|
132
|
+
return dataFrame;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function dataframe2Dataset(dataFrame: IDataFrame, columns: IField[]): IRow[] {
|
|
136
|
+
if (columns.length === 0) return [];
|
|
137
|
+
const dataset: IRow[] = [];
|
|
138
|
+
const len = dataFrame[Object.keys(dataFrame)[0]].length;
|
|
139
|
+
for (let i = 0; i < len; i++) {
|
|
140
|
+
const row: IRow = {};
|
|
141
|
+
columns.forEach((col) => {
|
|
142
|
+
row[col.fid] = dataFrame[col.fid][i];
|
|
143
|
+
});
|
|
144
|
+
dataset.push(row);
|
|
145
|
+
}
|
|
146
|
+
return dataset;
|
|
147
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface IAggQuery {
|
|
2
|
+
op: 'aggregate';
|
|
3
|
+
groupBy: string[];
|
|
4
|
+
agg: {
|
|
5
|
+
[field: string]:
|
|
6
|
+
| 'sum'
|
|
7
|
+
| 'count'
|
|
8
|
+
| 'max'
|
|
9
|
+
| 'min'
|
|
10
|
+
| 'mean'
|
|
11
|
+
| 'median'
|
|
12
|
+
| 'variance'
|
|
13
|
+
| 'stdev';
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// interface IFilterQuery {
|
|
18
|
+
// op: 'filter';
|
|
19
|
+
// filter: string;
|
|
20
|
+
// }
|
|
21
|
+
|
|
22
|
+
export interface IFoldQuery {
|
|
23
|
+
op: 'fold';
|
|
24
|
+
foldBy: string[];
|
|
25
|
+
newFoldKeyCol: string;
|
|
26
|
+
newFoldValueCol: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface IBinQuery {
|
|
30
|
+
op: 'bin';
|
|
31
|
+
binBy: string;
|
|
32
|
+
newBinCol: string;
|
|
33
|
+
binSize: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
export interface IRawQuery {
|
|
38
|
+
op: 'raw';
|
|
39
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { IRow } from "visual-insights";
|
|
2
|
+
import { IAggQuery } from "../interfaces";
|
|
3
|
+
import { sum, mean, median, stdev, variance, max, min, count } from "./stat";
|
|
4
|
+
|
|
5
|
+
const aggregatorMap = {
|
|
6
|
+
sum,
|
|
7
|
+
mean,
|
|
8
|
+
median,
|
|
9
|
+
stdev,
|
|
10
|
+
variance,
|
|
11
|
+
max,
|
|
12
|
+
min,
|
|
13
|
+
count,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const KEY_JOINER = '___';
|
|
17
|
+
|
|
18
|
+
export function aggregate (data: IRow[], query: IAggQuery): IRow[] {
|
|
19
|
+
const { groupBy, agg } = query;
|
|
20
|
+
const ans: Map<string, IRow> = new Map();
|
|
21
|
+
const groups: Map<string, IRow[]> = new Map();
|
|
22
|
+
for (let row of data) {
|
|
23
|
+
const gk = groupBy.map((k) => row[k]).join(KEY_JOINER);
|
|
24
|
+
|
|
25
|
+
if (!groups.has(gk)) {
|
|
26
|
+
groups.set(gk, []);
|
|
27
|
+
}
|
|
28
|
+
groups.get(gk)?.push(row);
|
|
29
|
+
}
|
|
30
|
+
for (let [gk, subGroup] of groups) {
|
|
31
|
+
if (subGroup.length === 0) {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
let aggRow: IRow = {};
|
|
35
|
+
for (let k of groupBy) {
|
|
36
|
+
aggRow[k] = subGroup[0][k];
|
|
37
|
+
}
|
|
38
|
+
for (let meaKey in agg) {
|
|
39
|
+
if (aggRow[meaKey] === undefined) {
|
|
40
|
+
aggRow[meaKey] = 0;
|
|
41
|
+
}
|
|
42
|
+
const values: number[] = subGroup.map((r) => r[meaKey]) ?? [];
|
|
43
|
+
const aggregator = aggregatorMap[agg[meaKey]] ?? sum;
|
|
44
|
+
aggRow[meaKey] = aggregator(values);
|
|
45
|
+
}
|
|
46
|
+
ans.set(gk, aggRow);
|
|
47
|
+
}
|
|
48
|
+
return Array.from(ans.values());
|
|
49
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { IRow } from "visual-insights";
|
|
2
|
+
import { IBinQuery } from "../interfaces";
|
|
3
|
+
|
|
4
|
+
export function bin (dataSource: IRow[], query: IBinQuery): IRow[] {
|
|
5
|
+
const { binBy, newBinCol, binSize } = query;
|
|
6
|
+
let _min = Infinity;
|
|
7
|
+
let _max = -Infinity;
|
|
8
|
+
for (let i = 0; i < dataSource.length; i++) {
|
|
9
|
+
let val = dataSource[i][binBy];
|
|
10
|
+
if (val > _max) _max = val;
|
|
11
|
+
if (val < _min) _min = val;
|
|
12
|
+
}
|
|
13
|
+
const step = (_max - _min) / binSize;
|
|
14
|
+
// const beaStep = Math.max(-Math.round(Math.log10(_max - _min)) + 2, 0)
|
|
15
|
+
return dataSource.map((r) => {
|
|
16
|
+
let bIndex = Math.floor((r[binBy] - _min) / step);
|
|
17
|
+
if (bIndex === binSize) bIndex = binSize - 1;
|
|
18
|
+
return {
|
|
19
|
+
...r,
|
|
20
|
+
[newBinCol]: [bIndex * step + _min, (bIndex + 1) * step + _min],
|
|
21
|
+
|
|
22
|
+
// [binFid]: Number(((bIndex * step + _min)).toFixed(beaStep)),
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { IRow } from "visual-insights";
|
|
2
|
+
import { IFoldQuery } from "../interfaces";
|
|
3
|
+
|
|
4
|
+
export function fold (data: IRow[], query: IFoldQuery): IRow[] {
|
|
5
|
+
const { foldBy, newFoldKeyCol, newFoldValueCol } = query;
|
|
6
|
+
const ans: IRow[] = [];
|
|
7
|
+
for (let row of data) {
|
|
8
|
+
for (let k of foldBy) {
|
|
9
|
+
const newRow = { ...row };
|
|
10
|
+
newRow[newFoldKeyCol] = k;
|
|
11
|
+
newRow[newFoldValueCol] = row[k];
|
|
12
|
+
delete newRow[k];
|
|
13
|
+
ans.push(newRow);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return ans;
|
|
17
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export function mean(nums: number[]): number {
|
|
2
|
+
return nums.reduce((a, b) => a + b, 0) / nums.length;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function sum(nums: number[]): number {
|
|
6
|
+
return nums.reduce((a, b) => a + b, 0);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function median(nums: number[]): number {
|
|
10
|
+
const sorted = nums.sort((a, b) => a - b);
|
|
11
|
+
const mid = Math.floor(sorted.length / 2);
|
|
12
|
+
return sorted.length % 2 === 0 ? (sorted[mid] + sorted[mid - 1]) / 2 : sorted[mid];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function variance(nums: number[]): number {
|
|
16
|
+
const m = mean(nums);
|
|
17
|
+
return mean(nums.map((x) => (x - m) ** 2));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function stdev(nums: number[]): number {
|
|
21
|
+
return Math.sqrt(variance(nums));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function max(nums: number[]): number {
|
|
25
|
+
let ans = -Infinity;
|
|
26
|
+
for (let n of nums) {
|
|
27
|
+
if (n > ans) {
|
|
28
|
+
ans = n;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return ans;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function min(nums: number[]): number {
|
|
35
|
+
let ans = Infinity;
|
|
36
|
+
for (let n of nums) {
|
|
37
|
+
if (n < ans) {
|
|
38
|
+
ans = n;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return ans;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function count(nums: number[]): number {
|
|
45
|
+
return nums.length;
|
|
46
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { IRow } from "visual-insights";
|
|
2
|
+
import { IMutField } from "../interfaces";
|
|
3
|
+
import { aggregate } from "./op/aggregate";
|
|
4
|
+
import { fold } from "./op/fold";
|
|
5
|
+
import { IAggQuery, IBinQuery, IFoldQuery, IRawQuery } from "./interfaces";
|
|
6
|
+
import { bin } from "./op/bin";
|
|
7
|
+
|
|
8
|
+
export type IViewQuery = IAggQuery | IFoldQuery | IBinQuery | IRawQuery;
|
|
9
|
+
|
|
10
|
+
export function queryView (rawData: IRow[], metas: IMutField[], query: IViewQuery) {
|
|
11
|
+
switch (query.op) {
|
|
12
|
+
case 'aggregate':
|
|
13
|
+
return aggregate(rawData, query);
|
|
14
|
+
case 'fold':
|
|
15
|
+
return fold(rawData, query);
|
|
16
|
+
case 'bin':
|
|
17
|
+
return bin(rawData, query);
|
|
18
|
+
case 'raw':
|
|
19
|
+
default:
|
|
20
|
+
return rawData;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
}
|
package/src/locales/en-US.json
CHANGED
|
@@ -117,7 +117,8 @@
|
|
|
117
117
|
"main": {
|
|
118
118
|
"tablist": {
|
|
119
119
|
"new": "+ New",
|
|
120
|
-
"
|
|
120
|
+
"auto_title": "Chart {{idx}}",
|
|
121
|
+
"chart_name": "Chart Name"
|
|
121
122
|
},
|
|
122
123
|
"tabpanel": {
|
|
123
124
|
"menubar": {
|
|
@@ -167,7 +168,9 @@
|
|
|
167
168
|
"btn": {
|
|
168
169
|
"select_all": "Select All",
|
|
169
170
|
"unselect_all": "Unselect All",
|
|
170
|
-
"reverse": "Reverse Selection"
|
|
171
|
+
"reverse": "Reverse Selection",
|
|
172
|
+
"confirm": "Confirm",
|
|
173
|
+
"cancel": "Cancel"
|
|
171
174
|
}
|
|
172
175
|
},
|
|
173
176
|
"explain": {
|
|
@@ -187,6 +190,8 @@
|
|
|
187
190
|
"actions": {
|
|
188
191
|
"prev": "Previous",
|
|
189
192
|
"next": "Next",
|
|
190
|
-
"drop_field": "Drop Field Here"
|
|
193
|
+
"drop_field": "Drop Field Here",
|
|
194
|
+
"confirm": "Confirm",
|
|
195
|
+
"cancel": "Cancel"
|
|
191
196
|
}
|
|
192
197
|
}
|
package/src/locales/i18n.ts
CHANGED
|
@@ -3,9 +3,9 @@ import { initReactI18next } from 'react-i18next';
|
|
|
3
3
|
import LanguageDetector from 'i18next-browser-languagedetector';
|
|
4
4
|
|
|
5
5
|
import localeEnUs from './en-US.json';
|
|
6
|
+
import localeJaJp from './ja-JP.json';
|
|
6
7
|
import localeZhCn from './zh-CN.json';
|
|
7
8
|
|
|
8
|
-
|
|
9
9
|
const locales: Resource & { 'en-US': any } = {
|
|
10
10
|
'en': {
|
|
11
11
|
translation: localeEnUs,
|
|
@@ -19,6 +19,12 @@ const locales: Resource & { 'en-US': any } = {
|
|
|
19
19
|
'zh-CN': {
|
|
20
20
|
translation: localeZhCn,
|
|
21
21
|
},
|
|
22
|
+
'ja': {
|
|
23
|
+
translation: localeJaJp,
|
|
24
|
+
},
|
|
25
|
+
'ja-JP': {
|
|
26
|
+
translation: localeJaJp,
|
|
27
|
+
}
|
|
22
28
|
} as const;
|
|
23
29
|
|
|
24
30
|
i18n.use(initReactI18next).use(LanguageDetector).init({
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
{
|
|
2
|
+
"constant": {
|
|
3
|
+
"row_count": "行数",
|
|
4
|
+
"analytic_type": {
|
|
5
|
+
"dimension": "次元",
|
|
6
|
+
"measure": "尺度"
|
|
7
|
+
},
|
|
8
|
+
"semantic_type": {
|
|
9
|
+
"nominal": "名義尺度",
|
|
10
|
+
"ordinal": "順序尺度",
|
|
11
|
+
"temporal": "時間尺度",
|
|
12
|
+
"quantitative": "数量尺度"
|
|
13
|
+
},
|
|
14
|
+
"mark_type": {
|
|
15
|
+
"__enum__": "マークタイプ",
|
|
16
|
+
"auto": "自動",
|
|
17
|
+
"bar": "バー",
|
|
18
|
+
"line": "ライン",
|
|
19
|
+
"area": "エリア",
|
|
20
|
+
"trail": "トレイル",
|
|
21
|
+
"point": "散布図",
|
|
22
|
+
"circle": "円",
|
|
23
|
+
"tick": "棒線図",
|
|
24
|
+
"rect": "長方形",
|
|
25
|
+
"arc": "アーク",
|
|
26
|
+
"boxplot": "ボックスプロット"
|
|
27
|
+
},
|
|
28
|
+
"stack_mode": {
|
|
29
|
+
"__enum__": "スタックモード",
|
|
30
|
+
"none": "なし",
|
|
31
|
+
"stack": "スタック",
|
|
32
|
+
"normalize": "正規化"
|
|
33
|
+
},
|
|
34
|
+
"layout_type": {
|
|
35
|
+
"__enum__": "レイアウトタイプ",
|
|
36
|
+
"auto": "自動",
|
|
37
|
+
"fixed": "固定"
|
|
38
|
+
},
|
|
39
|
+
"exploration_mode": {
|
|
40
|
+
"__enum__": "探索モード",
|
|
41
|
+
"none": "オフ",
|
|
42
|
+
"brush": "ブラシ",
|
|
43
|
+
"point": "ポイント"
|
|
44
|
+
},
|
|
45
|
+
"brush_mode": {
|
|
46
|
+
"__enum__": "ブラシの方向",
|
|
47
|
+
"default": "両方",
|
|
48
|
+
"x": "X軸のみ",
|
|
49
|
+
"y": "Y軸のみ"
|
|
50
|
+
},
|
|
51
|
+
"draggable_key": {
|
|
52
|
+
"fields": "フィールド",
|
|
53
|
+
"columns": "X軸",
|
|
54
|
+
"rows": "Y軸",
|
|
55
|
+
"color": "色",
|
|
56
|
+
"opacity": "不透明度",
|
|
57
|
+
"size": "大きさ",
|
|
58
|
+
"shape": "形状",
|
|
59
|
+
"theta": "角度",
|
|
60
|
+
"radius": "半径",
|
|
61
|
+
"filters": "フィルター"
|
|
62
|
+
},
|
|
63
|
+
"aggregator": {
|
|
64
|
+
"sum": "合計",
|
|
65
|
+
"mean": "平均",
|
|
66
|
+
"count": "件数",
|
|
67
|
+
"median": "中央値",
|
|
68
|
+
"min": "最小値",
|
|
69
|
+
"max": "最大値",
|
|
70
|
+
"q1": "第一四分位数",
|
|
71
|
+
"q3": "第三四分位数",
|
|
72
|
+
"stdev": "標準偏差",
|
|
73
|
+
"variance": "分散"
|
|
74
|
+
},
|
|
75
|
+
"filter_type": {
|
|
76
|
+
"one_of": "1つ以上",
|
|
77
|
+
"range": "範囲",
|
|
78
|
+
"temporal_range": "日付範囲"
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
"App": {
|
|
82
|
+
"labels": {
|
|
83
|
+
"data_interpretation": "データ解釈"
|
|
84
|
+
},
|
|
85
|
+
"segments": {
|
|
86
|
+
"vis": "可視化",
|
|
87
|
+
"data": "データ"
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"DataSource": {
|
|
91
|
+
"labels": {
|
|
92
|
+
"cur_dataset": "現在のデータセット"
|
|
93
|
+
},
|
|
94
|
+
"buttons": {
|
|
95
|
+
"create_dataset": "データセットを作成",
|
|
96
|
+
"export_as_file": "ファイルとして保存",
|
|
97
|
+
"import_file": "Graphic Walkerファイルをインポート"
|
|
98
|
+
},
|
|
99
|
+
"dialog": {
|
|
100
|
+
"create_data_source": "新しいデータソース",
|
|
101
|
+
"data_types": "データソースの種類",
|
|
102
|
+
"text_file_data": "ローカルファイル",
|
|
103
|
+
"public_data": "公開データセット",
|
|
104
|
+
"data_source_type": "データソースの種類:{{sourceType}}",
|
|
105
|
+
"file": {
|
|
106
|
+
"open": "開く...",
|
|
107
|
+
"submit": "提出する",
|
|
108
|
+
"dataset_name": "データセット名",
|
|
109
|
+
"choose_file": "データファイルを選択してください",
|
|
110
|
+
"get_start_desc": "データセットの作成を始めましょう。"
|
|
111
|
+
},
|
|
112
|
+
"public": {
|
|
113
|
+
"submit": "提出する"
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
"main": {
|
|
118
|
+
"tablist": {
|
|
119
|
+
"new": "+ 新規作成",
|
|
120
|
+
"auto_title": "グラフ {{idx}}",
|
|
121
|
+
"chart_name": "グラフ名"
|
|
122
|
+
},
|
|
123
|
+
"tabpanel": {
|
|
124
|
+
"menubar": {
|
|
125
|
+
"undo": "元に戻す",
|
|
126
|
+
"redo": "やり直し"
|
|
127
|
+
},
|
|
128
|
+
"settings": {
|
|
129
|
+
"toggle": {
|
|
130
|
+
"aggregation": "集計",
|
|
131
|
+
"stack": "スタック",
|
|
132
|
+
"axes_resize": "軸のサイズ変更",
|
|
133
|
+
"debug": "デバッグ"
|
|
134
|
+
},
|
|
135
|
+
"sort": "並べ替えの順序",
|
|
136
|
+
"button": {
|
|
137
|
+
"ascending": "昇順に並べ替える",
|
|
138
|
+
"descending": "降順に並べ替える",
|
|
139
|
+
"transpose": "転置",
|
|
140
|
+
"export_chart": "エクスポート",
|
|
141
|
+
"export_chart_as": "{{type}}としてエクスポート"
|
|
142
|
+
},
|
|
143
|
+
"size": "サイズ変更",
|
|
144
|
+
"size_setting": {
|
|
145
|
+
"width": "幅",
|
|
146
|
+
"height": "高さ"
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
"DatasetFields": {
|
|
150
|
+
"field_list": "フィールド一覧"
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
"filters": {
|
|
155
|
+
"to_edit": "このルールを編集",
|
|
156
|
+
"empty_rule": "! (空のルール)",
|
|
157
|
+
"editing": "ルールを編集",
|
|
158
|
+
"form": {
|
|
159
|
+
"name": "フィールド",
|
|
160
|
+
"rule": "ルール"
|
|
161
|
+
},
|
|
162
|
+
"header": {
|
|
163
|
+
"visibility": "表示",
|
|
164
|
+
"value": "ラベル",
|
|
165
|
+
"count": "件数"
|
|
166
|
+
},
|
|
167
|
+
"selected_keys": "{{ count }}件が選択されました",
|
|
168
|
+
"btn": {
|
|
169
|
+
"select_all": "すべて選択",
|
|
170
|
+
"unselect_all": "すべての選択を解除",
|
|
171
|
+
"reverse": "選択を反転する",
|
|
172
|
+
"confirm": "確認",
|
|
173
|
+
"cancel": "キャンセル"
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
"explain": {
|
|
177
|
+
"lg_than": "より大きい",
|
|
178
|
+
"sm_than": "より小さい",
|
|
179
|
+
"expection": "期待値",
|
|
180
|
+
"unrecognized": "未認識",
|
|
181
|
+
"score": "スコア",
|
|
182
|
+
"contains": "を含む",
|
|
183
|
+
"reason": {
|
|
184
|
+
"selection_dim_distribution": "次元のヒント",
|
|
185
|
+
"selection_mea_distribution": "尺度のヒント",
|
|
186
|
+
"children_major_factor": "主要要因",
|
|
187
|
+
"children_outlier": "外れ値"
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
"actions": {
|
|
191
|
+
"prev": "前へ",
|
|
192
|
+
"next": "次へ",
|
|
193
|
+
"drop_field": "ここにフィールドをドロップ",
|
|
194
|
+
"confirm": "確認",
|
|
195
|
+
"cancel": "キャンセル"
|
|
196
|
+
}
|
|
197
|
+
}
|
package/src/locales/zh-CN.json
CHANGED
|
@@ -117,7 +117,8 @@
|
|
|
117
117
|
"main": {
|
|
118
118
|
"tablist": {
|
|
119
119
|
"new": "+ 新建",
|
|
120
|
-
"
|
|
120
|
+
"auto_title": "图表 {{idx}}",
|
|
121
|
+
"chart_name": "图表名称"
|
|
121
122
|
},
|
|
122
123
|
"tabpanel": {
|
|
123
124
|
"menubar": {
|
|
@@ -167,7 +168,9 @@
|
|
|
167
168
|
"btn": {
|
|
168
169
|
"select_all": "全部选中",
|
|
169
170
|
"unselect_all": "全部取消",
|
|
170
|
-
"reverse": "选择反向"
|
|
171
|
+
"reverse": "选择反向",
|
|
172
|
+
"confirm": "确认",
|
|
173
|
+
"cancel": "取消"
|
|
171
174
|
}
|
|
172
175
|
},
|
|
173
176
|
"explain": {
|
|
@@ -187,6 +190,8 @@
|
|
|
187
190
|
"actions": {
|
|
188
191
|
"prev": "向前",
|
|
189
192
|
"next": "向后",
|
|
190
|
-
"drop_field": "拖拽字段至此"
|
|
193
|
+
"drop_field": "拖拽字段至此",
|
|
194
|
+
"confirm": "确认",
|
|
195
|
+
"cencel": "取消"
|
|
191
196
|
}
|
|
192
197
|
}
|
package/src/main.tsx
CHANGED
|
@@ -27,6 +27,14 @@ export class VisSpecWithHistory {
|
|
|
27
27
|
|
|
28
28
|
private batchFlag = false;
|
|
29
29
|
|
|
30
|
+
public updateLatest(snapshot: Partial<Readonly<VisSpecWithHistory['snapshots'][0]>>) {
|
|
31
|
+
this.snapshots[this.cursor] = {
|
|
32
|
+
...this.snapshots[this.cursor],
|
|
33
|
+
...snapshot,
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
30
38
|
private commit(snapshot: Partial<Readonly<VisSpecWithHistory['snapshots'][0]>>): void {
|
|
31
39
|
if (this.batchFlag) {
|
|
32
40
|
// batch this commit
|
|
@@ -120,6 +128,12 @@ export class VisSpecWithHistory {
|
|
|
120
128
|
});
|
|
121
129
|
}
|
|
122
130
|
|
|
131
|
+
public clone () {
|
|
132
|
+
const nextVSWH = new VisSpecWithHistory(this.frame);
|
|
133
|
+
nextVSWH.cursor = this.cursor;
|
|
134
|
+
return nextVSWH;
|
|
135
|
+
}
|
|
136
|
+
|
|
123
137
|
public exportGW (): IVisSpec {
|
|
124
138
|
return {
|
|
125
139
|
...this.frame
|