Skip to content

Commit 64d8a96

Browse files
committed
feat(website): support quickStart to create new file && code review
1 parent ab5d94c commit 64d8a96

File tree

7 files changed

+185
-97
lines changed

7 files changed

+185
-97
lines changed

website/src/components/tabs/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const Tabs = ({ data }: IProps) => {
3434
data={p}
3535
className={classNames(
3636
'tabs-item',
37-
currentId === p.id && 'tabs-item-active '
37+
currentId === p.id && 'tabs-item-active'
3838
)}
3939
onClick={() => handelChangeTab(p.id)}
4040
/>

website/src/consts/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ export const QUICK_GITHUB_HREF = [
3030
];
3131

3232
export const SQL_LANGUAGES = [
33-
'FlinkSQL',
34-
'SparkSQL',
3533
'HiveSQL',
34+
'SparkSQL',
35+
'FlinkSQL',
3636
'MySQL',
3737
'PGSQL',
3838
'TrinoSQL',

website/src/extensions/view/explorer.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,28 @@ export const ExtendsExplorer: IExtension = {
66
contributes: {},
77
activate: function (molecule): void {
88
molecule.explorer.onPanelToolbarClick((toolbar, panelId) => {
9-
if (panelId === 'FlinkSQL') {
9+
const {
10+
EXPLORER_TOOLBAR_CLOSE_ALL,
11+
EXPLORER_TOOLBAR_SAVE_ALL,
12+
EXPLORER_ITEM_OPEN_EDITOR
13+
} = molecule.builtin.getState().constants;
14+
if (panelId === EXPLORER_ITEM_OPEN_EDITOR) {
1015
switch (toolbar.id) {
11-
case 'explorer.contextMenu.createFile': {
16+
case EXPLORER_TOOLBAR_CLOSE_ALL: {
17+
molecule.editor.closeAll();
1218
break;
1319
}
20+
21+
case EXPLORER_TOOLBAR_SAVE_ALL: {
22+
molecule.editor.getState().groups.forEach((group) => {
23+
const unsaved = group.data
24+
.filter((tab) => tab.modified)
25+
.map((t) => t.id);
26+
molecule.editor.saveTabs(unsaved, group.id);
27+
});
28+
break;
29+
}
30+
1431
default:
1532
break;
1633
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import { useCallback, useState } from 'react';
2+
import { IEditorTab, IMenuItemProps, IMoleculeContext } from '@dtinsight/molecule';
3+
import * as monaco from 'monaco-editor';
4+
import { randomId } from '@/utils/tool';
5+
import { FILE_PATH, PARSE_LANGUAGE } from '@/consts';
6+
import { IFile } from '@/workbench/sourceSpace/components/parser';
7+
8+
export const useFileManager = ({ molecule }: { molecule: IMoleculeContext }) => {
9+
const [fileData, setFileData] = useState<Record<string, any> | null>(null);
10+
const [explorerData, setExplorerData] = useState<Record<string, any>>({});
11+
12+
// 更新状态栏路径
13+
const updateStatusBarPath = useCallback((file: IEditorTab<IFile>) => {
14+
const filePath = `${file.language}/${file.name}`;
15+
molecule.statusBar.update({
16+
id: FILE_PATH,
17+
name: filePath
18+
});
19+
}, []);
20+
21+
// 更新状态栏语言
22+
const updateStatusBarLang = useCallback((file: IEditorTab<IFile>) => {
23+
const language = file.language?.toLowerCase();
24+
molecule.statusBar.update({
25+
id: PARSE_LANGUAGE,
26+
name: language
27+
});
28+
}, []);
29+
30+
// 打开文件到编辑器
31+
const updateEditor = useCallback((file: IEditorTab<IFile>) => {
32+
const uri = monaco.Uri.parse(`${file.language}/${file.name}`);
33+
let model = monaco.editor.getModel(uri);
34+
if (!model) {
35+
model = monaco.editor.createModel('', file.language?.toLowerCase(), uri);
36+
}
37+
38+
const defaultGroupId = molecule.editor.getState().groups?.[0]?.id || -1;
39+
// todo: 已经保存的再次打开,需要把文件的 value 保存下来
40+
molecule.editor.open({ ...file }, defaultGroupId);
41+
42+
if (model && file.language) {
43+
monaco.editor.setModelLanguage(model, file.language.toLowerCase());
44+
}
45+
}, []);
46+
47+
// 打开文件逻辑
48+
const openFile = useCallback(
49+
(file: IEditorTab<IFile>) => {
50+
updateStatusBarPath(file);
51+
updateStatusBarLang(file);
52+
53+
const groupId = molecule.editor.getState().groups?.[0]?.id || -1;
54+
const groups = molecule.editor.getGroups();
55+
56+
// 已激活则返回
57+
if (groups.some((group) => group.activeTab === file.id)) return;
58+
59+
// 已打开则激活
60+
const allTabs = groups.flatMap((group) => group.data);
61+
const hasOpened = allTabs.find((tab) => tab.id === file.id);
62+
if (hasOpened && groupId) {
63+
molecule.editor.setCurrent(file.id, groupId);
64+
return;
65+
}
66+
// 否则新打开
67+
updateEditor(file);
68+
},
69+
[updateEditor, updateStatusBarLang, updateStatusBarPath]
70+
);
71+
72+
// FIXME:快速创建 & 点击 explore 创建的时候,数据没有共用
73+
const updateExplorer = useCallback(
74+
(file: IEditorTab<IFile>) => {
75+
const curSQL = file.language;
76+
if (!curSQL) return;
77+
const next = { ...explorerData };
78+
if (!next[curSQL]) next[curSQL] = [];
79+
next[curSQL].push(file);
80+
setExplorerData(next);
81+
return next[curSQL];
82+
},
83+
[explorerData]
84+
);
85+
86+
// 新建文件
87+
const addFile = useCallback(
88+
(item: IMenuItemProps) => {
89+
const { id } = item;
90+
const curSQL = (id as string).split('_')?.[1];
91+
const fileName = `${curSQL.toLowerCase()}_file_${randomId()}.sql`;
92+
93+
const newFile = { name: fileName, icon: 'file', id: fileName, language: curSQL };
94+
95+
const next = { ...fileData };
96+
if (!next[curSQL]) next[curSQL] = [];
97+
next[curSQL].push(newFile);
98+
setFileData(next);
99+
},
100+
[fileData, setFileData, openFile]
101+
);
102+
103+
return { fileData, explorerData, addFile, openFile, updateExplorer };
104+
};

website/src/workbench/sourceSpace/components/parser/index.tsx

Lines changed: 21 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,106 +1,48 @@
1-
import { IEditorTab, IMenuItemProps, IMoleculeContext, slots, UniqueId } from '@dtinsight/molecule';
1+
import { IMenuItemProps, IMoleculeContext, slots, UniqueId } from '@dtinsight/molecule';
22

3-
import { useState } from 'react';
43
import { Tree } from '@dtinsight/molecule/esm/client/components';
54
import { randomId } from '@/utils/tool';
6-
import * as monaco from 'monaco-editor';
7-
8-
import { FILE_PATH, PARSE_LANGUAGE } from '@/consts';
95

106
import './style.css';
7+
import { useFileManager } from '@/hooks/useFileManage';
118

12-
interface IFile {
9+
export interface IFile {
1310
name: string;
1411
icon: string;
1512
}
1613

1714
const { Explorer } = slots;
1815

1916
const Parser = ({ molecule }: { molecule: IMoleculeContext }) => {
20-
const [fileData, setFileData] = useState<Record<string, IEditorTab<IFile>[]>>({});
21-
22-
const addFile = (item: IMenuItemProps) => {
17+
const {
18+
updateExplorer,
19+
openFile: handleEditorOpen,
20+
addFile
21+
} = useFileManager({
22+
molecule
23+
});
24+
25+
const handleAddFile = (item: IMenuItemProps) => {
2326
const { id } = item;
2427
const curSQL = (id as string).split('_')?.[1];
2528
const fileName = `${curSQL.toLocaleLowerCase()}_file_${randomId()}.sql`;
26-
let curFileArray = fileData[curSQL];
27-
if (!fileData[curSQL]?.length) {
28-
curFileArray = [];
29-
}
30-
curFileArray.push({ name: fileName, icon: 'file', id: fileName, language: curSQL });
31-
setFileData({
32-
...fileData,
33-
[curSQL]: curFileArray
29+
addFile(item);
30+
31+
const curFileArray = updateExplorer({
32+
name: fileName,
33+
icon: 'file',
34+
id: fileName,
35+
language: curSQL
3436
});
3537

3638
molecule.explorer.update({
3739
id: curSQL,
3840
render: () => {
39-
return <Tree data={curFileArray as any} onSelect={handleOpenFile}></Tree>;
41+
return <Tree data={curFileArray as any} onSelect={handleEditorOpen}></Tree>;
4042
}
4143
});
4244
};
4345

44-
const handleUpdateStatusBarPath = (file: IEditorTab<IFile>) => {
45-
const filePath = `${file.language}/${file.name}`;
46-
molecule.statusBar.update({
47-
id: FILE_PATH,
48-
name: filePath
49-
});
50-
};
51-
52-
const handleUpdateStatusBarLang = (file: IEditorTab<IFile>) => {
53-
const language = file.language?.toLocaleLowerCase();
54-
molecule.statusBar.update({
55-
id: PARSE_LANGUAGE,
56-
name: language
57-
});
58-
};
59-
60-
const handleUpdateEditor = (file: IEditorTab<IFile>) => {
61-
// 打开文件,需要确定不同的 sql 类型, 使用不同的 sql 解析器
62-
let model = monaco.editor.getModel(monaco.Uri.parse(`${file.language}/${file.name}`));
63-
if (!model) {
64-
model = monaco.editor.createModel(
65-
'', // 空内容
66-
file.language?.toLocaleLowerCase(), // 指定语言(比如空文件用 plaintext)
67-
monaco.Uri.parse(`${file.language}/${file.name}`)
68-
);
69-
}
70-
71-
monaco.editor.getModel(model.uri);
72-
const defaultGroupId = molecule.editor.getState().groups?.at(0)?.id || -1;
73-
// todo: 已经保存的再次打开,需要把文件的 value 保存下来
74-
molecule.editor.open({ ...file }, defaultGroupId);
75-
if (model && file.language) {
76-
monaco.editor.setModelLanguage(model, file.language.toLocaleLowerCase());
77-
}
78-
};
79-
80-
const handleOpenFile = (file: IEditorTab<IFile>) => {
81-
handleUpdateStatusBarPath(file);
82-
handleUpdateStatusBarLang(file);
83-
84-
// analystProblems(nextTab);
85-
86-
const groupId = molecule.editor.getState().groups?.at(0)?.id || -1;
87-
// 如果已经 active, 则不走逻辑
88-
const curActiveTab = molecule.editor.getCurrentTab();
89-
const isAgainOpenTab = curActiveTab?.id === file.id;
90-
if (isAgainOpenTab) {
91-
return;
92-
}
93-
// 如果已经打开不是 active ,则 active
94-
const currentTabs = molecule.editor.getCurrentTabs();
95-
const hasOpened = currentTabs?.find((item) => item.id === file.id);
96-
if (hasOpened && groupId) {
97-
molecule.editor.setCurrent(file.id, groupId);
98-
return;
99-
}
100-
// 如果新打开的文件, 则走下面的逻辑
101-
handleUpdateEditor(file);
102-
};
103-
10446
const handleClick = (activeKeys: UniqueId[]) => {
10547
molecule.explorer.setActive(activeKeys);
10648
};
@@ -109,7 +51,7 @@ const Parser = ({ molecule }: { molecule: IMoleculeContext }) => {
10951
<div className="folder-tree">
11052
<Explorer
11153
{...(molecule.explorer as any)}
112-
onToolbarClick={addFile}
54+
onToolbarClick={handleAddFile}
11355
onCollapseChange={handleClick}
11456
></Explorer>
11557
</div>

website/src/workbench/sourceSpace/index.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import Tabs from '@/components/tabs';
2-
import { SOURCE_FILE, SOURCE_OUTLINE } from '@/consts';
2+
import { SOURCE_FILE } from '@/consts';
33
import Parser from './components/parser';
44
import { IMoleculeContext } from '@dtinsight/molecule';
55
const SourceSpace = ({ molecule }: { molecule: IMoleculeContext }) => {
@@ -9,12 +9,6 @@ const SourceSpace = ({ molecule }: { molecule: IMoleculeContext }) => {
99
key: SOURCE_FILE,
1010
name: '文件',
1111
children: <Parser molecule={molecule} />
12-
},
13-
{
14-
id: SOURCE_OUTLINE,
15-
key: SOURCE_OUTLINE,
16-
name: '大纲',
17-
children: <div>待开发</div>
1812
}
1913
];
2014

website/src/workbench/welcome/index.tsx

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,37 @@
11
import './style.css';
2-
import { components, IMoleculeContext } from '@dtinsight/molecule';
2+
import { components, IEditorTab, IMoleculeContext } from '@dtinsight/molecule';
33
import quickStart from '@/assets/quickStart.svg';
44
import checkDemo from '@/assets/checkDemo.svg';
55
import { ACTIVITY_API, ACTIVITY_FOLDER, ACTIVITY_SQL, defaultLanguage } from '@/consts';
6+
import { randomId } from '@/utils/tool';
7+
8+
import { Tree } from '@dtinsight/molecule/esm/client/components';
9+
import { useFileManager } from '@/hooks/useFileManage';
10+
import { IFile } from '../sourceSpace/components/parser';
611

712
const Welcome = ({ context: molecule }: { context: IMoleculeContext }) => {
8-
const handleClickApiDoc = (key: string) => {
13+
const { openFile: openEditorFile, updateExplorer } = useFileManager({
14+
molecule
15+
});
16+
17+
const switchWorkspaceView = (key: string) => {
918
switch (key) {
10-
case 'quickStart':
19+
case 'quickStart': {
1120
molecule.sidebar.setCurrent(ACTIVITY_FOLDER);
1221
molecule.activityBar.setCurrent(ACTIVITY_FOLDER);
1322
molecule.explorer.setActive([defaultLanguage]);
23+
const fileName = `${defaultLanguage.toLocaleLowerCase()}_file_${randomId()}.sql`;
24+
const initFile = {
25+
name: fileName,
26+
icon: 'file',
27+
id: fileName,
28+
language: defaultLanguage
29+
};
30+
openEditorFile(initFile);
31+
handleUpdateExplorer(initFile);
1432
molecule.editor.setEntry(null);
1533
break;
34+
}
1635
case 'viewApiDoc':
1736
molecule.sidebar.setCurrent(ACTIVITY_API);
1837
molecule.activityBar.setCurrent(ACTIVITY_API);
@@ -26,21 +45,33 @@ const Welcome = ({ context: molecule }: { context: IMoleculeContext }) => {
2645
}
2746
};
2847

48+
const handleUpdateExplorer = (file: IEditorTab<IFile>) => {
49+
const explorerData = updateExplorer(file);
50+
molecule.explorer.update({
51+
id: defaultLanguage,
52+
render: () => {
53+
return (
54+
!!explorerData && <Tree data={explorerData} onSelect={openEditorFile}></Tree>
55+
);
56+
}
57+
});
58+
};
59+
2960
return (
3061
<div className="welcome">
3162
<div className="welcome-header">
3263
<components.Text>monaco-sql-languages</components.Text>
3364
</div>
3465
<ul>
35-
<li key={'quickStart'} onClick={() => handleClickApiDoc('quickStart')}>
66+
<li key={'quickStart'} onClick={() => switchWorkspaceView('quickStart')}>
3667
<img src={quickStart} alt="quickStart" />
3768
<span className="text-sm">快速开始</span>
3869
</li>
39-
<li key={'viewApiDoc'} onClick={() => handleClickApiDoc('viewApiDoc')}>
70+
<li key={'viewApiDoc'} onClick={() => switchWorkspaceView('viewApiDoc')}>
4071
<img src={checkDemo} alt="viewApiDoc" />
4172
<span className="text-sm">接口文档</span>
4273
</li>
43-
<li key={'checkDemo'} onClick={() => handleClickApiDoc('checkDemo')}>
74+
<li key={'checkDemo'} onClick={() => switchWorkspaceView('checkDemo')}>
4475
<img src={checkDemo} alt="checkDemo" />
4576
<span className="text-sm">查看 Demo</span>
4677
</li>

0 commit comments

Comments
 (0)