@kanaries/graphic-walker 0.3.16 → 0.4.1

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 (87) hide show
  1. package/dist/App.d.ts +9 -2
  2. package/dist/assets/filter.worker-f09fcd6f.js.map +1 -1
  3. package/dist/assets/sort.worker-f77540ac.js.map +1 -0
  4. package/dist/assets/transform.worker-bae8e910.js.map +1 -0
  5. package/dist/assets/{viewQuery.worker-03404216.js.map → viewQuery.worker-bdb6477c.js.map} +1 -1
  6. package/dist/components/askViz/index.d.ts +6 -0
  7. package/dist/components/askViz/schemaTransform.d.ts +2 -0
  8. package/dist/components/dataTable/index.d.ts +9 -5
  9. package/dist/components/pivotTable/store.d.ts +0 -2
  10. package/dist/components/spinner.d.ts +2 -0
  11. package/dist/computation/clientComputation.d.ts +3 -0
  12. package/dist/computation/serverComputation.d.ts +8 -0
  13. package/dist/config.d.ts +3 -1
  14. package/dist/fields/filterField/tabs.d.ts +2 -1
  15. package/dist/graphic-walker.es.js +22268 -21682
  16. package/dist/graphic-walker.es.js.map +1 -1
  17. package/dist/graphic-walker.umd.js +139 -139
  18. package/dist/graphic-walker.umd.js.map +1 -1
  19. package/dist/hooks/index.d.ts +1 -0
  20. package/dist/index.d.ts +2 -0
  21. package/dist/interfaces.d.ts +93 -4
  22. package/dist/lib/execExp.d.ts +4 -4
  23. package/dist/lib/interfaces.d.ts +1 -0
  24. package/dist/lib/viewQuery.d.ts +2 -2
  25. package/dist/renderer/hooks.d.ts +8 -4
  26. package/dist/renderer/index.d.ts +2 -1
  27. package/dist/renderer/pureRenderer.d.ts +17 -1
  28. package/dist/renderer/specRenderer.d.ts +1 -0
  29. package/dist/services.d.ts +8 -5
  30. package/dist/store/commonStore.d.ts +2 -2
  31. package/dist/store/visualSpecStore.d.ts +58 -42
  32. package/dist/utils/save.d.ts +10 -2
  33. package/dist/utils/workflow.d.ts +3 -0
  34. package/dist/vis/react-vega.d.ts +3 -1
  35. package/dist/workers/sort.d.ts +2 -2
  36. package/dist/workers/transform.d.ts +5 -2
  37. package/package.json +2 -2
  38. package/src/App.tsx +46 -7
  39. package/src/components/askViz/index.tsx +93 -0
  40. package/src/components/askViz/schemaTransform.ts +38 -0
  41. package/src/components/dataTable/index.tsx +53 -11
  42. package/src/components/limitSetting.tsx +8 -6
  43. package/src/components/pivotTable/index.tsx +0 -1
  44. package/src/components/pivotTable/store.tsx +0 -16
  45. package/src/components/sizeSetting.tsx +9 -7
  46. package/src/components/spinner.tsx +14 -0
  47. package/src/components/toggle.tsx +2 -2
  48. package/src/components/visualConfig/index.tsx +78 -8
  49. package/src/computation/clientComputation.ts +55 -0
  50. package/src/computation/serverComputation.ts +158 -0
  51. package/src/config.ts +15 -2
  52. package/src/dataSource/datasetConfig/index.tsx +38 -6
  53. package/src/dataSource/table.tsx +15 -2
  54. package/src/fields/filterField/filterEditDialog.tsx +11 -10
  55. package/src/fields/filterField/tabs.tsx +178 -77
  56. package/src/hooks/index.ts +8 -0
  57. package/src/index.tsx +2 -0
  58. package/src/interfaces.ts +108 -5
  59. package/src/lib/execExp.ts +20 -11
  60. package/src/lib/interfaces.ts +1 -0
  61. package/src/lib/op/aggregate.ts +1 -1
  62. package/src/lib/viewQuery.ts +2 -2
  63. package/src/locales/en-US.json +11 -2
  64. package/src/locales/ja-JP.json +11 -2
  65. package/src/locales/zh-CN.json +11 -2
  66. package/src/main.tsx +1 -1
  67. package/src/renderer/hooks.ts +57 -69
  68. package/src/renderer/index.tsx +10 -6
  69. package/src/renderer/pureRenderer.tsx +40 -14
  70. package/src/renderer/specRenderer.tsx +24 -7
  71. package/src/services.ts +7 -8
  72. package/src/store/commonStore.ts +7 -7
  73. package/src/store/visualSpecStore.ts +288 -192
  74. package/src/utils/save.ts +81 -3
  75. package/src/utils/workflow.ts +148 -0
  76. package/src/vis/react-vega.tsx +21 -6
  77. package/src/vis/spec/aggregate.ts +3 -2
  78. package/src/vis/spec/stack.ts +7 -6
  79. package/src/visualSettings/index.tsx +2 -4
  80. package/src/workers/filter.worker.js +1 -1
  81. package/src/workers/sort.ts +3 -4
  82. package/src/workers/sort.worker.ts +2 -2
  83. package/src/workers/transform.ts +7 -8
  84. package/src/workers/transform.worker.js +2 -2
  85. package/src/workers/viewQuery.worker.js +2 -2
  86. package/dist/assets/sort.worker-4299a6a0.js.map +0 -1
  87. package/dist/assets/transform.worker-a12fb3d8.js.map +0 -1
@@ -1,13 +1,15 @@
1
1
  import { observer } from 'mobx-react-lite';
2
- import React, { useState } from 'react';
2
+ import React, { useEffect, useRef, useState } from 'react';
3
3
  import { useGlobalStore } from '../../store';
4
+ import { NonPositionChannelConfigList,PositionChannelConfigList } from '../../config';
5
+
4
6
  import Modal from '../modal';
5
7
  import { IVisualConfig } from '../../interfaces';
6
8
  import PrimaryButton from '../button/primary';
7
9
  import DefaultButton from '../button/default';
8
10
  import { useTranslation } from 'react-i18next';
9
11
  import Toggle from '../toggle';
10
- import { runInAction } from 'mobx';
12
+ import { runInAction, toJS } from 'mobx';
11
13
 
12
14
  const VisualConfigPanel: React.FC = (props) => {
13
15
  const { commonStore, vizStore } = useGlobalStore();
@@ -24,7 +26,27 @@ const VisualConfigPanel: React.FC = (props) => {
24
26
  timeFormat: visualConfig.format.timeFormat,
25
27
  normalizedNumberFormat: visualConfig.format.normalizedNumberFormat,
26
28
  });
29
+ const [resolve, setResolve] = useState<IVisualConfig['resolve']>({
30
+ x: visualConfig.resolve.x,
31
+ y: visualConfig.resolve.y,
32
+ color: visualConfig.resolve.color,
33
+ opacity: visualConfig.resolve.opacity,
34
+ shape: visualConfig.resolve.shape,
35
+ size: visualConfig.resolve.size,
36
+ });
27
37
  const [zeroScale, setZeroScale] = useState<boolean>(visualConfig.zeroScale);
38
+ const [background, setBackground] = useState<string | undefined>(visualConfig.background);
39
+
40
+ useEffect(() => {
41
+ setZeroScale(visualConfig.zeroScale);
42
+ setBackground(visualConfig.background);
43
+ setResolve(toJS(visualConfig.resolve));
44
+ setFormat({
45
+ numberFormat: visualConfig.format.numberFormat,
46
+ timeFormat: visualConfig.format.timeFormat,
47
+ normalizedNumberFormat: visualConfig.format.normalizedNumberFormat,
48
+ });
49
+ }, [showVisualConfigPanel]);
28
50
 
29
51
  return (
30
52
  <Modal
@@ -36,22 +58,22 @@ const VisualConfigPanel: React.FC = (props) => {
36
58
  <div>
37
59
  <h2 className="text-lg mb-4">{t('config.format')}</h2>
38
60
  <p className="text-xs">
39
- Format guides docs:{' '}
61
+ {t(`config.formatGuidesDocs`)}:{' '}
40
62
  <a
41
63
  target="_blank"
42
64
  className="underline text-blue-500"
43
65
  href="https://github.com/d3/d3-format#locale_format"
44
66
  >
45
- read here
67
+ {t(`config.readHere`)}
46
68
  </a>
47
69
  </p>
48
70
  {formatConfigList.map((fc) => (
49
71
  <div className="my-2" key={fc}>
50
- <label className="block text-xs font-medium leading-6 text-gray-900">{t(`config.${fc}`)}</label>
72
+ <label className="block text-xs font-medium leading-6">{t(`config.${fc}`)}</label>
51
73
  <div className="mt-1">
52
74
  <input
53
75
  type="text"
54
- className="block w-full rounded-md border-0 py-1 px-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-1 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
76
+ className="block w-full text-gray-700 dark:text-gray-200 rounded-md border-0 py-1 px-2 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-1 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6 dark:bg-zinc-900 "
55
77
  value={format[fc] ?? ''}
56
78
  onChange={(e) => {
57
79
  setFormat((f) => ({
@@ -63,9 +85,55 @@ const VisualConfigPanel: React.FC = (props) => {
63
85
  </div>
64
86
  </div>
65
87
  ))}
88
+ <h2 className="text-lg">{t('config.background')}</h2>
89
+ <div className="my-2">
90
+ <label className="block text-xs font-medium leading-6">{t(`config.color`)}</label>
91
+ <div className="mt-1">
92
+ <input
93
+ type="text"
94
+ className="block w-full text-gray-700 dark:text-gray-200 rounded-md border-0 py-1 px-2 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-1 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6 dark:bg-zinc-900 "
95
+ value={background ?? ''}
96
+ onChange={(e) => {
97
+ setBackground(e.target.value);
98
+ }}
99
+ />
100
+ </div>
101
+ </div>
102
+ <h2 className="text-lg">{t('config.independence')}</h2>
103
+ <div className="my-2">
104
+ <div className="flex space-x-6">
105
+ {PositionChannelConfigList.map((pc) => (
106
+ <Toggle
107
+ label={t(`config.${pc}`)}
108
+ key={pc}
109
+ enabled={resolve[pc] ?? false}
110
+ onChange={(e) => {
111
+ setResolve((r) => ({
112
+ ...r,
113
+ [pc]: e,
114
+ }));
115
+ }}
116
+ />
117
+ ))}
118
+ {NonPositionChannelConfigList.map((npc) => (
119
+ <Toggle
120
+ label={t(`constant.draggable_key.${npc}`)}
121
+ key={npc}
122
+ enabled={resolve[npc] ?? false}
123
+ onChange={(e) => {
124
+ setResolve((r) => ({
125
+ ...r,
126
+ [npc]: e,
127
+ }));
128
+ }}
129
+ />
130
+ ))}
131
+ </div>
132
+ </div>
133
+ <h2 className="text-lg">{t('config.zeroScale')}</h2>
66
134
  <div className="my-2">
67
135
  <Toggle
68
- label="zero scale"
136
+ label={t(`config.zeroScale`)}
69
137
  enabled={zeroScale}
70
138
  onChange={(en) => {
71
139
  setZeroScale(en);
@@ -80,8 +148,10 @@ const VisualConfigPanel: React.FC = (props) => {
80
148
  runInAction(() => {
81
149
  vizStore.setVisualConfig('format', format);
82
150
  vizStore.setVisualConfig('zeroScale', zeroScale);
151
+ vizStore.setVisualConfig('background', background);
152
+ vizStore.setVisualConfig('resolve', resolve);
83
153
  commonStore.setShowVisualConfigPanel(false);
84
- })
154
+ });
85
155
  }}
86
156
  />
87
157
  <DefaultButton
@@ -0,0 +1,55 @@
1
+ import type { IDataQueryPayload, IDataQueryWorkflowStep, IFilterFiledSimple, IRow } from "../interfaces";
2
+ import { applyFilter, applySort, applyViewQuery, transformDataService } from "../services";
3
+
4
+ export const dataQueryClient = async (
5
+ rawData: IRow[],
6
+ workflow: IDataQueryWorkflowStep[],
7
+ offset?: number,
8
+ limit?: number,
9
+ ): Promise<IRow[]> => {
10
+ let res = rawData;
11
+ for await (const step of workflow) {
12
+ switch (step.type) {
13
+ case 'filter': {
14
+ res = await applyFilter(res, step.filters.map(filter => {
15
+ const res: IFilterFiledSimple = {
16
+ fid: filter.fid,
17
+ rule: null,
18
+ };
19
+ if (filter.rule.type === 'one of') {
20
+ res.rule = {
21
+ type: 'one of',
22
+ value: new Set(filter.rule.value),
23
+ };
24
+ } else {
25
+ res.rule = filter.rule;
26
+ }
27
+ return res;
28
+ }).filter(Boolean));
29
+ break;
30
+ }
31
+ case 'transform': {
32
+ res = await transformDataService(res, step.transform);
33
+ break;
34
+ }
35
+ case 'view': {
36
+ for await (const job of step.query) {
37
+ res = await applyViewQuery(res, job);
38
+ }
39
+ break;
40
+ }
41
+ case 'sort': {
42
+ res = await applySort(res, step.by, step.sort);
43
+ break;
44
+ }
45
+ default: {
46
+ // @ts-expect-error - runtime check
47
+ console.warn(new Error(`Unknown step type: ${step.type}`));
48
+ break;
49
+ }
50
+ }
51
+ }
52
+ return res.slice(offset ?? 0, limit ? ((offset ?? 0) + limit) : undefined);
53
+ };
54
+
55
+ export const getComputation = (rawData: IRow[]) => (payload: IDataQueryPayload) => dataQueryClient(rawData, payload.workflow, payload.offset, payload.limit)
@@ -0,0 +1,158 @@
1
+ import type {
2
+ IComputationFunction,
3
+ IDataQueryPayload,
4
+ IDataQueryWorkflowStep,
5
+ IDatasetStats,
6
+ IFieldStats,
7
+ IRow,
8
+ } from '../interfaces';
9
+
10
+ export const datasetStatsServer = async (service: IComputationFunction): Promise<IDatasetStats> => {
11
+ const res = (await service({
12
+ workflow: [
13
+ {
14
+ type: 'view',
15
+ query: [
16
+ {
17
+ op: 'aggregate',
18
+ groupBy: [],
19
+ measures: [
20
+ {
21
+ field: '*',
22
+ agg: 'count',
23
+ asFieldKey: 'count',
24
+ },
25
+ ],
26
+ },
27
+ ],
28
+ },
29
+ ],
30
+ })) as [{ count: number }];
31
+ return {
32
+ rowCount: res[0]?.count ?? 0,
33
+ };
34
+ };
35
+
36
+ export const dataReadRawServer = async (
37
+ service: IComputationFunction,
38
+ pageSize: number,
39
+ pageOffset = 0
40
+ ): Promise<IRow[]> => {
41
+ const res = await service({
42
+ workflow: [
43
+ {
44
+ type: 'view',
45
+ query: [
46
+ {
47
+ op: 'raw',
48
+ fields: ['*'],
49
+ },
50
+ ],
51
+ },
52
+ ],
53
+ limit: pageSize,
54
+ offset: pageOffset * pageSize,
55
+ });
56
+ return res;
57
+ };
58
+
59
+ export const dataQueryServer = async (
60
+ service: IComputationFunction,
61
+ workflow: IDataQueryWorkflowStep[],
62
+ limit?: number,
63
+ ): Promise<IRow[]> => {
64
+ if (
65
+ workflow.length === 1 &&
66
+ workflow[0].type === 'view' &&
67
+ workflow[0].query.length === 1 &&
68
+ workflow[0].query[0].op === 'raw' &&
69
+ workflow[0].query[0].fields.length === 0
70
+ ) {
71
+ return [];
72
+ }
73
+ const res = await service({
74
+ workflow,
75
+ limit,
76
+ });
77
+ return res;
78
+ };
79
+
80
+ export const fieldStatServer = async (
81
+ service: IComputationFunction,
82
+ field: string,
83
+ options: { values?: boolean; range?: boolean }
84
+ ): Promise<IFieldStats> => {
85
+ const { values = true, range = true } = options;
86
+ const COUNT_ID = `count_${field}`;
87
+ const MIN_ID = `min_${field}`;
88
+ const MAX_ID = `max_${field}`;
89
+ const valuesQueryPayload: IDataQueryPayload = {
90
+ workflow: [
91
+ {
92
+ type: 'view',
93
+ query: [
94
+ {
95
+ op: 'aggregate',
96
+ groupBy: [field],
97
+ measures: [
98
+ {
99
+ field,
100
+ agg: 'count',
101
+ asFieldKey: COUNT_ID,
102
+ },
103
+ ],
104
+ },
105
+ ],
106
+ },
107
+ ],
108
+ };
109
+ const valuesRes = values ? await service(valuesQueryPayload) : [];
110
+ const rangeQueryPayload: IDataQueryPayload = {
111
+ workflow: [
112
+ {
113
+ type: 'view',
114
+ query: [
115
+ {
116
+ op: 'aggregate',
117
+ groupBy: [],
118
+ measures: [
119
+ {
120
+ field,
121
+ agg: 'min',
122
+ asFieldKey: MIN_ID,
123
+ },
124
+ {
125
+ field,
126
+ agg: 'max',
127
+ asFieldKey: MAX_ID,
128
+ },
129
+ ],
130
+ },
131
+ ],
132
+ },
133
+ ],
134
+ };
135
+ const [
136
+ rangeRes = {
137
+ [MIN_ID]: 0,
138
+ [MAX_ID]: 0,
139
+ },
140
+ ] = range
141
+ ? await service(rangeQueryPayload)
142
+ : [
143
+ {
144
+ [MIN_ID]: 0,
145
+ [MAX_ID]: 0,
146
+ },
147
+ ];
148
+
149
+ return {
150
+ values: valuesRes
151
+ .sort((a, b) => b[COUNT_ID] - a[COUNT_ID])
152
+ .map((row) => ({
153
+ value: row[field],
154
+ count: row[COUNT_ID],
155
+ })),
156
+ range: [rangeRes[MIN_ID], rangeRes[MAX_ID]],
157
+ };
158
+ };
package/src/config.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { DraggableFieldState, IStackMode } from "./interfaces";
1
+ import { DraggableFieldState, IStackMode, IVisualConfig } from "./interfaces";
2
2
 
3
3
  export const GEMO_TYPES: Readonly<string[]> = [
4
4
  'auto',
@@ -19,7 +19,8 @@ export const GEMO_TYPES: Readonly<string[]> = [
19
19
  export const STACK_MODE: Readonly<IStackMode[]> = [
20
20
  'none',
21
21
  'stack',
22
- 'normalize'
22
+ 'normalize',
23
+ 'center'
23
24
  ]
24
25
 
25
26
  export const CHART_LAYOUT_TYPE: Readonly<string[]> = [
@@ -57,4 +58,16 @@ export const CHANNEL_LIMIT = {
57
58
  export const MetaFieldKeys: Array<keyof DraggableFieldState> = [
58
59
  'dimensions',
59
60
  'measures',
61
+ ]
62
+
63
+ export const PositionChannelConfigList: Array<keyof IVisualConfig['resolve']> = [
64
+ 'x',
65
+ 'y',
66
+ ]
67
+
68
+ export const NonPositionChannelConfigList: Array<keyof IVisualConfig['resolve']> = [
69
+ 'color',
70
+ 'opacity',
71
+ 'shape',
72
+ 'size'
60
73
  ]
@@ -1,15 +1,47 @@
1
- import React from "react";
1
+ import React, { useEffect, useRef, useState } from "react";
2
2
  import DatasetTable from "../../components/dataTable";
3
3
  import { observer } from "mobx-react-lite";
4
4
  import { useGlobalStore } from "../../store";
5
+ import { useComputationFunc } from "../../renderer/hooks";
6
+ import { datasetStatsServer } from "../../computation/serverComputation";
5
7
 
6
- const DatasetConfig: React.FC = (props) => {
7
- const { commonStore, vizStore } = useGlobalStore();
8
+ const DatasetConfig: React.FC = () => {
9
+ const { commonStore } = useGlobalStore();
8
10
  const { currentDataset } = commonStore;
9
- const { dataSource, rawFields } = currentDataset;
11
+
12
+ const computationFunction = useComputationFunc();
13
+
14
+ const [count, setCount] = useState(0);
15
+ const taskIdRef = useRef(0);
16
+ const [loading, setLoading] = useState(false);
17
+
18
+ useEffect(() => {
19
+ const taskId = ++taskIdRef.current;
20
+ setLoading(true);
21
+ datasetStatsServer(computationFunction).then(res => {
22
+ if (taskId !== taskIdRef.current) {
23
+ return;
24
+ }
25
+ setCount(res.rowCount);
26
+ setLoading(false);
27
+ }).catch(err => {
28
+ if (taskId !== taskIdRef.current) {
29
+ return;
30
+ }
31
+ console.error(err);
32
+ setLoading(false);
33
+ });
34
+ return () => {
35
+ taskIdRef.current++;
36
+ };
37
+ }, [computationFunction]);
38
+
10
39
  return (
11
- <div>
12
- <DatasetTable size={100} data={dataSource} metas={rawFields}
40
+ <div className="relative">
41
+ <DatasetTable size={100}
42
+ total={count}
43
+ dataset={currentDataset}
44
+ loading={loading}
13
45
  onMetaChange={(fid, fIndex, diffMeta) => {
14
46
  commonStore.updateCurrentDatasetMetas(fid, diffMeta)
15
47
  }}
@@ -3,6 +3,7 @@ import { observer } from "mobx-react-lite";
3
3
  import { useGlobalStore } from "../store";
4
4
  import DataTable from "../components/dataTable";
5
5
  import { toJS } from "mobx";
6
+ import { getComputation } from "../computation/clientComputation";
6
7
 
7
8
  interface TableProps {
8
9
  size?: number;
@@ -13,11 +14,23 @@ const Table: React.FC<TableProps> = (props) => {
13
14
  const { commonStore } = useGlobalStore();
14
15
  const { tmpDSRawFields, tmpDataSource } = commonStore;
15
16
 
17
+ const tempDataset = React.useMemo(() => {
18
+ return {
19
+ id: "tmp",
20
+ name: "tmp",
21
+ dataSource: tmpDataSource,
22
+ rawFields: toJS(tmpDSRawFields),
23
+ };
24
+ }, [tmpDataSource, tmpDSRawFields]);
25
+ 9
26
+ const computation = React.useMemo(() => getComputation(tempDataset.dataSource), [tempDataset])
27
+
16
28
  return (
17
29
  <DataTable
18
30
  size={size}
19
- metas={toJS(tmpDSRawFields)}
20
- data={tmpDataSource}
31
+ dataset={tempDataset}
32
+ computation={computation}
33
+ total={tmpDataSource.length}
21
34
  onMetaChange={(fid, fIndex, diffMeta) => {
22
35
  commonStore.updateTempDatasetMetas(fid, diffMeta);
23
36
  }}
@@ -10,27 +10,28 @@ import DefaultButton from "../../components/button/default";
10
10
  import PrimaryButton from "../../components/button/primary";
11
11
  import DropdownSelect from "../../components/dropdownSelect";
12
12
 
13
- const QuantitativeRuleForm: React.FC<RuleFormProps> = ({ field, onChange }) => {
14
- return <Tabs field={field} onChange={onChange} tabs={["range", "one of"]} />;
13
+ const QuantitativeRuleForm: React.FC<RuleFormProps> = ({ dataset, field, onChange }) => {
14
+ return <Tabs field={field} onChange={onChange} tabs={["range", "one of"]} dataset={dataset} />;
15
15
  };
16
16
 
17
- const NominalRuleForm: React.FC<RuleFormProps> = ({ field, onChange }) => {
18
- return <Tabs field={field} onChange={onChange} tabs={["one of"]} />;
17
+ const NominalRuleForm: React.FC<RuleFormProps> = ({ dataset, field, onChange }) => {
18
+ return <Tabs field={field} onChange={onChange} tabs={["one of"]} dataset={dataset} />;
19
19
  };
20
20
 
21
- const OrdinalRuleForm: React.FC<RuleFormProps> = ({ field, onChange }) => {
22
- return <Tabs field={field} onChange={onChange} tabs={["range", "one of"]} />;
21
+ const OrdinalRuleForm: React.FC<RuleFormProps> = ({ dataset, field, onChange }) => {
22
+ return <Tabs field={field} onChange={onChange} tabs={["range", "one of"]} dataset={dataset} />;
23
23
  };
24
24
 
25
- const TemporalRuleForm: React.FC<RuleFormProps> = ({ field, onChange }) => {
26
- return <Tabs field={field} onChange={onChange} tabs={["temporal range", "one of"]} />;
25
+ const TemporalRuleForm: React.FC<RuleFormProps> = ({ dataset, field, onChange }) => {
26
+ return <Tabs field={field} onChange={onChange} tabs={["temporal range", "one of"]} dataset={dataset} />;
27
27
  };
28
28
 
29
29
  const EmptyForm: React.FC<RuleFormProps> = () => <React.Fragment />;
30
30
 
31
31
  const FilterEditDialog: React.FC = observer(() => {
32
- const { vizStore } = useGlobalStore();
32
+ const { vizStore, commonStore } = useGlobalStore();
33
33
  const { editingFilterIdx, draggableFieldState } = vizStore;
34
+ const { currentDataset } = commonStore;
34
35
 
35
36
  const { t } = useTranslation("translation", { keyPrefix: "filters" });
36
37
 
@@ -113,7 +114,7 @@ const FilterEditDialog: React.FC = observer(() => {
113
114
  selectedKey={uncontrolledField.fid}
114
115
  onSelect={handleSelectFilterField}
115
116
  />
116
- <Form field={uncontrolledField} onChange={handleChange} />
117
+ <Form dataset={currentDataset} field={uncontrolledField} onChange={handleChange} />
117
118
  <div className="mt-4">
118
119
  <PrimaryButton
119
120
  onClick={handleSubmit}