Skip to content

Commit e1bb990

Browse files
authored
Merge pull request #1630 from merico-dev/1628-able-to-force-submit-even-when-filter-values-are-not-changed
1628 able to force submit even when filter values are not changed
2 parents df7b99e + 61ccd30 commit e1bb990

File tree

11 files changed

+128
-17
lines changed

11 files changed

+128
-17
lines changed

api/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@devtable/api",
3-
"version": "14.16.1",
3+
"version": "14.17.0",
44
"description": "",
55
"main": "index.js",
66
"scripts": {

dashboard/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@devtable/dashboard",
3-
"version": "14.16.1",
3+
"version": "14.17.0",
44
"license": "Apache-2.0",
55
"publishConfig": {
66
"access": "public",

dashboard/src/components/filter/index.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ import { useDisclosure } from '@mantine/hooks';
33
import { IconChevronsDown, IconChevronsUp } from '@tabler/icons-react';
44
import _ from 'lodash';
55
import { observer } from 'mobx-react-lite';
6-
import { useEffect, useMemo } from 'react';
6+
import { useCallback, useEffect, useMemo } from 'react';
77
import { Controller, useForm, useWatch } from 'react-hook-form';
88
import { useTranslation } from 'react-i18next';
99
import { useRenderContentModelContext } from '~/contexts';
1010
import { FilterMetaInstance, ViewMetaInstance } from '~/model';
1111
import { Filter } from './filter';
1212
import { SearchButton } from './search-button';
1313
import { useUpdateFilterPreviewValues } from './use-update-filter-preview-values';
14+
import { OnFiltersSubmit } from '~/index';
1415

1516
export { type IFormattedFilter, useVisibleFilters } from './use-visible-filters';
1617

@@ -70,7 +71,16 @@ export const Filters = observer(function _Filters({ view }: { view: ViewMetaInst
7071
}
7172
};
7273

73-
const submit = useMemo(() => handleSubmit(content.filters.setValues), [handleSubmit, content.filters.setValues]);
74+
const submit = useCallback<OnFiltersSubmit>(
75+
(props) => {
76+
const force = _.get(props, 'force', false);
77+
handleSubmit(content.filters.setValues);
78+
if (force) {
79+
content.queries.forceReloadVisibleQueries();
80+
}
81+
},
82+
[handleSubmit, content.filters.setValues],
83+
);
7484

7585
return (
7686
<form>
Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,41 @@
1-
import { Button } from '@mantine/core';
1+
import { ActionIcon, Button, Menu } from '@mantine/core';
2+
import { IconChevronDown, IconRefresh } from '@tabler/icons-react';
3+
import { useTranslation } from 'react-i18next';
24
import { useDashboardThemeContext } from '~/contexts';
35
import { RenderSearchButtonProps } from '~/index';
46

57
export const SearchButton = ({ disabled, onSubmit }: RenderSearchButtonProps) => {
8+
const { t } = useTranslation();
69
const { renderSearchButton } = useDashboardThemeContext();
710
if (renderSearchButton) {
811
return renderSearchButton({ disabled, onSubmit });
912
}
1013
return (
11-
<Button color="blue" size="sm" onClick={onSubmit} disabled={disabled}>
12-
Search
13-
</Button>
14+
<Button.Group>
15+
<Button color="blue" size="sm" onClick={() => onSubmit()} disabled={disabled}>
16+
{t('common.actions.search')}
17+
</Button>
18+
<Menu trigger="hover" disabled={disabled} position="bottom-end">
19+
<Menu.Target>
20+
<Button
21+
disabled={disabled}
22+
color="blue"
23+
px="xs"
24+
style={{ borderLeft: `1px solid ${disabled ? 'white' : 'var(--mantine-color-gray-4)'}` }}
25+
>
26+
<IconChevronDown size={16} />
27+
</Button>
28+
</Menu.Target>
29+
<Menu.Dropdown>
30+
<Menu.Item
31+
leftSection={<IconRefresh size={14} />}
32+
disabled={disabled}
33+
onClick={() => onSubmit({ force: true })}
34+
>
35+
{t('common.actions.reload')}
36+
</Menu.Item>
37+
</Menu.Dropdown>
38+
</Menu>
39+
</Button.Group>
1440
);
1541
};

dashboard/src/i18n/en.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,8 @@ export const en = {
299299
copied: 'Copied to clipboard',
300300
action: 'Action',
301301
actions: {
302+
search: 'Search',
303+
reload: 'Reload',
302304
actions: 'Actions',
303305
open: 'Open',
304306
close: 'Close',

dashboard/src/i18n/zh.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,8 @@ export const zh = {
299299
copied: '已复制到剪切板',
300300
action: '操作',
301301
actions: {
302+
search: '查询',
303+
reload: '刷新',
302304
actions: '操作',
303305
open: '打开',
304306
close: '关闭',

dashboard/src/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ export * from './model';
2020
export * from './api-caller/request';
2121
export type { AnyObject } from './types/utils';
2222

23+
export type OnFiltersSubmit = (props?: { force?: boolean }) => void;
24+
2325
export type RenderSearchButtonProps = {
2426
disabled: boolean;
25-
onSubmit: () => void;
27+
onSubmit: OnFiltersSubmit;
2628
};
2729
export interface IDashboardConfig {
2830
basename: string;

dashboard/src/model/render-model/dashboard/content/queries/queries.ts

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import _ from 'lodash';
2-
import { Instance, SnapshotIn, getParent, getRoot, types } from 'mobx-state-tree';
2+
import { Instance, SnapshotIn, flow, getParent, getRoot, types } from 'mobx-state-tree';
33
import { CURRENT_SCHEMA_VERSION, QueryMetaSnapshotIn } from '~/model/meta-model';
44
import { downloadDataAsCSV, downloadDataListAsZip, downloadJSON } from '~/utils/download';
55
import { QueryRenderModel, QueryRenderModelInstance } from './query';
@@ -35,11 +35,11 @@ export const QueriesRenderModel = types
3535
return this.root.name;
3636
},
3737
get contentModel() {
38-
return getParent(self, 1);
38+
// FIXME: type
39+
return getParent(self, 1) as any;
3940
},
4041
get visibleQueryIDSet() {
41-
// FIXME: type
42-
const { views, filters, queries } = this.contentModel as any;
42+
const { views, filters } = this.contentModel;
4343
const queryIDs: string[] = [];
4444

4545
views.visibleViews.forEach((v: any) => {
@@ -62,7 +62,7 @@ export const QueriesRenderModel = types
6262
}
6363
});
6464

65-
queries.findByIDSet(new Set(queryIDs)).forEach((q: QueryRenderModelInstance) => {
65+
this.findByIDSet(new Set(queryIDs)).forEach((q: QueryRenderModelInstance) => {
6666
const config = q.config as TransformQueryMetaInstance;
6767
if (!q.isTransform || config.dep_query_ids.length === 0) {
6868
return;
@@ -77,6 +77,59 @@ export const QueriesRenderModel = types
7777
isQueryInUse(queryID: string) {
7878
return this.visibleQueryIDSet.has(queryID);
7979
},
80+
addTransformDepQueryIDs(targetSet: Set<string>, excludeSet?: Set<string>) {
81+
this.findByIDSet(targetSet).forEach((q: QueryRenderModelInstance) => {
82+
const config = q.config as TransformQueryMetaInstance;
83+
if (!q.isTransform || config.dep_query_ids.length === 0) {
84+
return;
85+
}
86+
config.dep_query_ids.forEach((id) => {
87+
if (excludeSet?.has(id)) {
88+
return;
89+
}
90+
targetSet.add(id);
91+
});
92+
});
93+
},
94+
get querisToForceReload() {
95+
const filterQueryIDSet = new Set<string>();
96+
const panelQueryIDSet = new Set<string>();
97+
98+
const { views, filters } = this.contentModel;
99+
const visibleViewIDs: string[] = _.uniq(views.visibleViews.map((v: any) => v.renderViewIDs).flat());
100+
101+
// make filterQueryIDSet
102+
filters.current.forEach((f: any) => {
103+
const id = _.get(f, 'config.options_query_id');
104+
if (!id) {
105+
return;
106+
}
107+
108+
const visible = visibleViewIDs.some((viewID) => f.visibleInViewsIDSet.has(viewID));
109+
if (visible) {
110+
filterQueryIDSet.add(id);
111+
}
112+
});
113+
this.addTransformDepQueryIDs(filterQueryIDSet);
114+
115+
// make panelQueryIDSet
116+
views.visibleViews.forEach((v: any) => {
117+
v.panels.forEach((p: any) => {
118+
p.queryIDs.forEach((id: string) => {
119+
if (filterQueryIDSet.has(id)) {
120+
return;
121+
}
122+
panelQueryIDSet.add(id);
123+
});
124+
});
125+
});
126+
this.addTransformDepQueryIDs(panelQueryIDSet, filterQueryIDSet);
127+
128+
return {
129+
filterQueries: this.findByIDSet(filterQueryIDSet),
130+
panelQueries: this.findByIDSet(panelQueryIDSet),
131+
};
132+
},
80133
}))
81134
.actions((self) => {
82135
return {
@@ -134,6 +187,22 @@ export const QueriesRenderModel = types
134187
const filename = 'Queries';
135188
downloadJSON(filename, schema);
136189
},
190+
forceReloadVisibleQueries: flow(function* () {
191+
const { filterQueries, panelQueries } = self.querisToForceReload;
192+
console.log('🟡 Force reloading queries');
193+
if (filterQueries.length > 0) {
194+
const result = yield Promise.allSettled(filterQueries.map((q) => q.fetchData(true)));
195+
console.log('🟡 Queries from filters reloaded', result);
196+
} else {
197+
console.log('🟡 Found no query from visible filters, skipping');
198+
}
199+
if (panelQueries.length > 0) {
200+
const result = yield Promise.allSettled(panelQueries.map((q) => q.fetchData(true)));
201+
console.log('🟡 Queries from filters reloaded', result);
202+
} else {
203+
console.log('🟡 Found no query from visible panels, skipping');
204+
}
205+
}),
137206
};
138207
});
139208

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@devtable/root",
3-
"version": "14.16.1",
3+
"version": "14.17.0",
44
"private": true,
55
"workspaces": [
66
"api",

settings-form/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@devtable/settings-form",
3-
"version": "14.16.1",
3+
"version": "14.17.0",
44
"license": "Apache-2.0",
55
"publishConfig": {
66
"access": "public",

0 commit comments

Comments
 (0)