Skip to content

Commit 3fe8131

Browse files
authored
Merge pull request #1670 from merico-dev/1669-add-interaction-operation-switch-tab
1669 add interaction operation switch tab
2 parents 13342a1 + 4b055f9 commit 3fe8131

File tree

12 files changed

+122
-9
lines changed

12 files changed

+122
-9
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.28.0",
3+
"version": "14.29.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.28.0",
3+
"version": "14.29.0",
44
"license": "Apache-2.0",
55
"publishConfig": {
66
"access": "public",

dashboard/src/dashboard-editor/model/views/index.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,19 @@ export const ViewsModel = types
3333
type: v.type as EViewComponentType,
3434
}));
3535
},
36+
get tabViewOptions() {
37+
return this.options.filter((o) => o.type === EViewComponentType.Tabs);
38+
},
39+
tabOptions(viewID: string) {
40+
const view = self.current.find((v) => v.id === viewID && v.type === EViewComponentType.Tabs && v.tabs.length > 0);
41+
if (!view) {
42+
return [];
43+
}
44+
return view.tabs.map((t) => ({
45+
label: t.name,
46+
value: t.id,
47+
}));
48+
},
3649
get editorOptions() {
3750
// @ts-expect-error getRoot type, reading panels
3851
const panels: PanelsModelInstance = getRoot(self).content.panels;

dashboard/src/i18n/en.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,11 @@ export const en = {
216216
label: 'Open View',
217217
view: 'View',
218218
},
219+
switch_tab: {
220+
label: 'Switch Tab',
221+
view: 'View',
222+
tab: 'Tab',
223+
},
219224
scroll_to_panel: {
220225
label: 'Scroll to Panel',
221226
panel: 'Panel',

dashboard/src/i18n/zh.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,11 @@ export const zh = {
216216
label: '唤出视图',
217217
view: '视图',
218218
},
219+
switch_tab: {
220+
label: '切换标签页',
221+
view: '视图',
222+
tab: '标签页',
223+
},
219224
scroll_to_panel: {
220225
label: '滚动到卡片',
221226
panel: '卡片',

dashboard/src/interactions/components/operation-select.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ const OperationSchemaSelect = observer(({ model }: { model: ReadyOperationConfig
110110
withinPortal: true,
111111
zIndex: 340,
112112
}}
113+
maxDropdownHeight={500}
113114
/>
114115
);
115116
});

dashboard/src/interactions/operation/operations/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ import { OpenView } from './open-view';
55
import { SetFilterValues } from './set-filter-values';
66
import { ClearFilterValues } from './clear-filter-values';
77
import { ScrollToPanel } from './scroll-to-panel';
8+
import { SwitchTab } from './switch-tab';
89

910
export const OPERATIONS: IDashboardOperationSchema[] = [
1011
ConsoleLog,
1112
OpenLink,
1213
OpenView,
1314
ScrollToPanel,
1415
SetFilterValues,
16+
SwitchTab,
1517
ClearFilterValues,
1618
];
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { Select, Stack } from '@mantine/core';
2+
import { observer } from 'mobx-react-lite';
3+
import { useTranslation } from 'react-i18next';
4+
import { useStorageData } from '~/components/plugins';
5+
import { useEditContentModelContext } from '~/contexts';
6+
import { IDashboardOperation, IDashboardOperationSchema, IOperationConfigProps } from '~/types/plugin';
7+
import { getSelectChangeHandler } from '~/utils/mantine';
8+
9+
export interface ISwitchTabOperationConfig {
10+
viewID: string;
11+
tab: string;
12+
}
13+
14+
const SwitchTabOperationSettings = observer((props: IOperationConfigProps) => {
15+
const { t } = useTranslation();
16+
const model = useEditContentModelContext();
17+
const { value, set } = useStorageData<ISwitchTabOperationConfig>(props.operation.operationData, 'config');
18+
19+
const { viewID = '', tab = '' } = value ?? {};
20+
const setViewID = (viewID: string) => void set({ viewID, tab });
21+
const setTab = (tab: string) => void set({ viewID, tab });
22+
return (
23+
<Stack gap="xs">
24+
<Select
25+
defaultValue={viewID}
26+
value={viewID}
27+
onChange={getSelectChangeHandler(setViewID)}
28+
label={t('interactions.operation.switch_tab.view')}
29+
data={model.views.tabViewOptions}
30+
comboboxProps={{
31+
withinPortal: true,
32+
zIndex: 340,
33+
}}
34+
maxDropdownHeight={500}
35+
/>
36+
<Select
37+
defaultValue={tab}
38+
value={tab}
39+
onChange={getSelectChangeHandler(setTab)}
40+
label={t('interactions.operation.switch_tab.tab')}
41+
data={model.views.tabOptions(viewID)}
42+
comboboxProps={{
43+
withinPortal: true,
44+
zIndex: 340,
45+
}}
46+
maxDropdownHeight={500}
47+
/>
48+
</Stack>
49+
);
50+
});
51+
52+
async function run(payload: Record<string, unknown>, operation: IDashboardOperation) {
53+
const config = await operation.operationData.getItem<ISwitchTabOperationConfig>('config');
54+
const { viewID, tab } = config;
55+
window.dispatchEvent(new CustomEvent('switch_tab', { detail: { viewID, tab } }));
56+
}
57+
58+
export const SwitchTab: IDashboardOperationSchema = {
59+
displayName: 'interactions.operation.switch_tab.label',
60+
id: 'builtin:op:switch_tab',
61+
configRender: SwitchTabOperationSettings,
62+
run,
63+
};

dashboard/src/interactions/temp-hack.ts

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,41 @@ export function useInteractionOperationHacks(
4545
return;
4646
}
4747
navigate(`#${panelID}`);
48-
const element = document.getElementById(panelID);
49-
if (element) {
50-
element.scrollIntoView({ behavior: 'smooth' });
51-
}
48+
setTimeout(() => {
49+
const element = document.getElementById(panelID);
50+
if (element) {
51+
element.scrollIntoView({ behavior: 'smooth' });
52+
}
53+
}, 300);
5254
};
5355
window.addEventListener('scroll_to_panel', handler);
5456
return () => {
5557
window.removeEventListener('scroll_to_panel', handler);
5658
};
5759
}, [navigate]);
5860

61+
useEffect(() => {
62+
const handler = (e: $TSFixMe) => {
63+
logEvent(e);
64+
65+
const { viewID, tab } = e.detail;
66+
if (!viewID) {
67+
console.error(new Error('[Switch Tab] Needs to pick a view and a tab first'));
68+
return;
69+
}
70+
const view = model.views.findByID(viewID);
71+
if (!view) {
72+
console.error(new Error(`[Switch Tab] View by ID[${viewID}] is not found`));
73+
return;
74+
}
75+
view.setTab(tab);
76+
};
77+
window.addEventListener('switch_tab', handler);
78+
return () => {
79+
window.removeEventListener('switch_tab', handler);
80+
};
81+
}, [model, inEditMode]);
82+
5983
useEffect(() => {
6084
const handler = (e: $TSFixMe) => {
6185
logEvent(e);

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.28.0",
3+
"version": "14.29.0",
44
"private": true,
55
"workspaces": [
66
"api",

0 commit comments

Comments
 (0)