Commit 87addd4d authored by zhumingye's avatar zhumingye

fix:

   修复任务重命名的bug
add:
   增加SQLStudio 的多tab 右键关闭菜单(关闭其他/关闭所有(会将草稿关闭))
parent 2a2d4f6b
...@@ -88,6 +88,7 @@ public class CatalogueServiceImpl extends SuperServiceImpl<CatalogueMapper, Cata ...@@ -88,6 +88,7 @@ public class CatalogueServiceImpl extends SuperServiceImpl<CatalogueMapper, Cata
}else{ }else{
Task task = new Task(); Task task = new Task();
task.setId(oldCatalogue.getTaskId()); task.setId(oldCatalogue.getTaskId());
task.setName(catalogue.getName());
task.setAlias(catalogue.getName()); task.setAlias(catalogue.getName());
taskService.updateById(task); taskService.updateById(task);
this.updateById(catalogue); this.updateById(catalogue);
......
import {message, Tabs} from 'antd'; import {message, Tabs, Menu, Dropdown} from 'antd';
import React, {useState} from 'react'; import React, {useState} from 'react';
import {connect} from "umi"; import {connect} from 'umi';
import {StateType} from "@/pages/FlinkSqlStudio/model"; import {StateType} from '@/pages/FlinkSqlStudio/model';
import styles from './index.less'; import styles from './index.less';
import StudioEdit from '../StudioEdit'; import StudioEdit from '../StudioEdit';
import {saveTask} from "@/components/Studio/StudioEvent/DDL"; import {saveTask} from '@/components/Studio/StudioEvent/DDL';
import { DIALECT } from '../conf'; import {DIALECT} from '../conf';
const {TabPane} = Tabs; const {TabPane} = Tabs;
const EditorTabs = (props: any) => { const EditorTabs = (props: any) => {
const {tabs, dispatch, current, toolHeight,width} = props; const {tabs, dispatch, current, toolHeight, width} = props;
const onChange = (activeKey: any) => { const onChange = (activeKey: any) => {
dispatch&&dispatch({ dispatch &&
type: "Studio/saveToolHeight", dispatch({
payload: toolHeight-0.0001, type: 'Studio/saveToolHeight',
payload: toolHeight - 0.0001,
}); });
dispatch({ dispatch({
type: "Studio/changeActiveKey", type: 'Studio/changeActiveKey',
payload: activeKey, payload: activeKey,
}); });
}; };
...@@ -27,9 +28,10 @@ const EditorTabs = (props: any) => { ...@@ -27,9 +28,10 @@ const EditorTabs = (props: any) => {
if (action == 'add') { if (action == 'add') {
add(); add();
} else if (action == 'remove') { } else if (action == 'remove') {
dispatch&&dispatch({ dispatch &&
type: "Studio/saveToolHeight", dispatch({
payload: toolHeight-0.0001, type: 'Studio/saveToolHeight',
payload: toolHeight - 0.0001,
}); });
if (current.isModified) { if (current.isModified) {
saveTask(current, dispatch); saveTask(current, dispatch);
...@@ -51,7 +53,7 @@ const EditorTabs = (props: any) => { ...@@ -51,7 +53,7 @@ const EditorTabs = (props: any) => {
} }
}); });
let panes = tabs.panes; let panes = tabs.panes;
const newPanes = panes.filter(pane => pane.key.toString() != targetKey); const newPanes = panes.filter((pane) => pane.key.toString() != targetKey);
if (newPanes.length && newActiveKey.toString() === targetKey) { if (newPanes.length && newActiveKey.toString() === targetKey) {
if (lastIndex > 0) { if (lastIndex > 0) {
newActiveKey = newPanes[lastIndex].key; newActiveKey = newPanes[lastIndex].key;
...@@ -60,13 +62,49 @@ const EditorTabs = (props: any) => { ...@@ -60,13 +62,49 @@ const EditorTabs = (props: any) => {
} }
} }
dispatch({ dispatch({
type: "Studio/saveTabs", type: 'Studio/saveTabs',
payload: { payload: {
activeKey: newActiveKey, activeKey: newActiveKey,
panes: newPanes, panes: newPanes,
}, },
}); });
}; };
const handleClickMenu = (e: any, current) => {
dispatch({
type: 'Studio/closeTabs',
payload: {
deleteType: e.key,
current
},
});
};
const menu = (pane) => (
<Menu onClick={(e) => handleClickMenu(e, pane)}>
<Menu.Item key="CLOSE_OTHER">
<span>关闭其他</span>
</Menu.Item>
<Menu.Item key="CLOSE_ALL">
<span>关闭所有</span>
</Menu.Item>
</Menu>
);
const Tab = (pane: any) => (
<span>
{pane.key === 0 ? (
pane.title
) : (
<Dropdown overlay={menu(pane)} trigger={['contextMenu']}>
<span className="ant-dropdown-link">
{pane.title}
</span>
</Dropdown>
)}
</span>
);
return ( return (
<Tabs <Tabs
hideAdd hideAdd
...@@ -75,18 +113,21 @@ const EditorTabs = (props: any) => { ...@@ -75,18 +113,21 @@ const EditorTabs = (props: any) => {
onChange={onChange} onChange={onChange}
activeKey={tabs.activeKey + ''} activeKey={tabs.activeKey + ''}
onEdit={onEdit} onEdit={onEdit}
className={styles["edit-tabs"]} className={styles['edit-tabs']}
style={{height: toolHeight}} style={{height: toolHeight}}
> >
{tabs.panes.map(pane => ( {tabs.panes.map((pane) => (
<TabPane tab={pane.title} key={pane.key} closable={pane.closable}> <TabPane tab={Tab(pane)} key={pane.key} closable={pane.closable}>
<StudioEdit tabsKey={pane.key} height={(toolHeight - 32)} width={width} <StudioEdit
language={current.task.dialect===DIALECT.JAVA?'java':'sql'}/> tabsKey={pane.key}
height={toolHeight - 32}
width={width}
language={current.task.dialect === DIALECT.JAVA ? 'java' : 'sql'}
/>
</TabPane> </TabPane>
))} ))}
</Tabs> </Tabs>
);
)
}; };
export default connect(({Studio}: { Studio: StateType }) => ({ export default connect(({Studio}: { Studio: StateType }) => ({
......
import type {Effect, Reducer} from "umi";
import {
handleAddOrUpdate
} from "@/components/Common/crud";
import type {SqlMetaData} from "@/components/Studio/StudioEvent/data";
export type ClusterType = {
id: number,
name: string,
alias: string,
type: string,
hosts: string,
jobManagerHost: string,
status: number,
note: string,
enabled: boolean,
createTime: Date,
updateTime: Date,
}
export type ClusterConfigurationType = {
id: number,
name: string,
alias: string,
type: string,
config: any,
available: boolean,
note: string,
enabled: boolean,
createTime: Date,
updateTime: Date,
}
export type DataBaseType = {
id: number,
name: string,
alias: string,
groupName: string,
type: string,
url: string,
username: string,
password: string,
note: string,
dbVersion: string,
status: boolean,
healthTime: Date,
heartbeatTime: Date,
enabled: boolean,
createTime: Date,
updateTime: Date,
};
export type EnvType = {
id?: number,
name?: string,
alias?: string,
fragment?: boolean,
};
export type TaskType = {
id?: number,
catalogueId?: number,
name?: string,
alias?: string,
dialect?: string,
type?: string,
checkPoint?: number,
savePointStrategy?: number,
savePointPath?: string,
parallelism?: number,
fragment?: boolean,
statementSet?: boolean,
config?: [],
clusterId?: any,
clusterName?: string,
clusterConfigurationId?: number,
clusterConfigurationName?: string,
databaseId?: number,
databaseName?: string,
jarId?: number,
envId?: number,
note?: string,
enabled?: boolean,
createTime?: Date,
updateTime?: Date,
statement?: string,
session: string;
maxRowNum: number;
jobName: string;
useResult: boolean;
useChangeLog: boolean;
useAutoCancel: boolean;
useSession: boolean;
useRemote: boolean;
};
export type ConsoleType = {
result: {};
}
export type TabsItemType = {
title: string;
key: number,
value: string;
closable: boolean;
path: string[];
task?: TaskType;
console: ConsoleType;
monaco?: any;
isModified: boolean;
sqlMetaData?: SqlMetaData;
}
export type TabsType = {
activeKey: number;
panes?: TabsItemType[];
}
export type ConnectorType = {
tablename: string;
}
export type SessionType = {
session?: string;
sessionConfig?: {
type?: string;
useRemote?: boolean;
clusterId?: number;
clusterName?: string;
address?: string;
}
createUser?: string;
createTime?: string;
connectors: ConnectorType[];
}
export type StateType = {
toolHeight?: number;
toolRightWidth?: number;
toolLeftWidth?: number;
cluster?: ClusterType[];
sessionCluster?: ClusterType[];
clusterConfiguration?: ClusterConfigurationType[];
database?: DataBaseType[];
env?: EnvType[];
currentSession?: SessionType;
current?: TabsItemType;
sql?: string;
monaco?: any;
currentPath?: string[];
tabs?: TabsType;
session?: SessionType[];
result?: {};
rightClickMenu?: boolean;
refs?: {
history: any;
};
};
export type ModelType = {
namespace: string;
state: StateType;
effects: {
saveTask: Effect;
};
reducers: {
saveToolHeight: Reducer<StateType>;
saveToolRightWidth: Reducer<StateType>;
saveToolLeftWidth: Reducer<StateType>;
saveSql: Reducer<StateType>;
saveCurrentPath: Reducer<StateType>;
saveMonaco: Reducer<StateType>;
saveSqlMetaData: Reducer<StateType>;
saveTabs: Reducer<StateType>;
changeActiveKey: Reducer<StateType>;
saveTaskData: Reducer<StateType>;
saveSession: Reducer<StateType>;
showRightClickMenu: Reducer<StateType>;
refreshCurrentSession: Reducer<StateType>;
quitCurrentSession: Reducer<StateType>;
saveResult: Reducer<StateType>;
saveCluster: Reducer<StateType>;
saveSessionCluster: Reducer<StateType>;
saveClusterConfiguration: Reducer<StateType>;
saveDataBase: Reducer<StateType>;
saveEnv: Reducer<StateType>;
};
};
const Model: ModelType = {
namespace: 'Studio',
state: {
toolHeight: 400,
toolRightWidth: 300,
toolLeftWidth: 300,
cluster: [],
sessionCluster: [],
clusterConfiguration: [],
database: [],
env: [],
currentSession: {
connectors: [],
},
current: {
title: '草稿',
key: 0,
value: '',
closable: false,
path: ['草稿'],
isModified: false,
task: {
jobName: '草稿',
type: 'local',
checkPoint: 0,
savePointStrategy: 0,
savePointPath: '',
parallelism: 1,
fragment: true,
statementSet: false,
clusterId: 0,
clusterName: "本地环境",
clusterConfigurationId: undefined,
clusterConfigurationName: undefined,
databaseId: undefined,
databaseName: undefined,
jarId: undefined,
envId: undefined,
maxRowNum: 100,
config: [],
session: '',
alias: '草稿',
dialect: 'FlinkSql',
useResult: true,
useChangeLog: false,
useAutoCancel: false,
useSession: false,
useRemote: false,
},
console: {
result: {},
},
monaco: {},
sqlMetaData: undefined,
},
sql: '',
monaco: {},
currentPath: ['草稿'],
tabs: {
activeKey: 0,
panes: [{
title: '草稿',
key: 0,
value: '',
closable: false,
isModified: false,
path: ['草稿'],
task: {
jobName: '草稿',
type: 'local',
checkPoint: 0,
savePointStrategy: 0,
savePointPath: '',
parallelism: 1,
fragment: true,
statementSet: false,
clusterId: 0,
clusterName: "本地环境",
clusterConfigurationId: undefined,
clusterConfigurationName: undefined,
databaseId: undefined,
databaseName: undefined,
jarId: undefined,
envId: undefined,
session: '',
config: [],
maxRowNum: 100,
alias: '草稿',
dialect: 'FlinkSql',
useResult: true,
useChangeLog: false,
useAutoCancel: false,
useSession: false,
useRemote: false,
},
console: {
result: {},
},
monaco: {},
sqlMetaData: undefined,
}],
},
session: [],
result: {},
rightClickMenu: false,
refs: {
history: {},
}
},
effects: {
* saveTask({payload}, {call, put}) {
const para = payload;
para.configJson = JSON.stringify(payload.config);
yield call(handleAddOrUpdate, 'api/task', para);
yield put({
type: 'saveTaskData',
payload,
});
},
},
reducers: {
saveToolHeight(state, {payload}) {
return {
...state,
toolHeight: payload,
};
}, saveToolRightWidth(state, {payload}) {
return {
...state,
toolRightWidth: payload,
};
}, saveToolLeftWidth(state, {payload}) {
return {
...state,
toolLeftWidth: payload,
};
},
saveSql(state, {payload}) {
const {tabs} = state;
const newCurrent = state.current;
newCurrent.value = payload;
for (let i = 0; i < tabs.panes.length; i++) {
if (tabs.panes[i].key == tabs.activeKey) {
tabs.panes[i].value = payload;
tabs.panes[i].task && (tabs.panes[i].task.statement = payload);
}
}
return {
...state,
current: {
...newCurrent
},
tabs: {
...tabs
},
};
},
saveCurrentPath(state, {payload}) {
return {
...state,
currentPath: payload,
};
},
saveMonaco(state, {payload}) {
return {
...state,
monaco: {
...payload
},
};
},
saveSqlMetaData(state, {payload}) {
const newCurrent = state.current;
const newTabs = state.tabs;
if (newCurrent.key == payload.activeKey) {
newCurrent.sqlMetaData = payload.sqlMetaData;
newCurrent.isModified = payload.isModified;
}
for (let i = 0; i < newTabs.panes.length; i++) {
if (newTabs.panes[i].key == payload.activeKey) {
newTabs.panes[i].sqlMetaData = payload.sqlMetaData;
newTabs.panes[i].isModified = payload.isModified;
break;
}
}
return {
...state,
current: newCurrent,
tabs: newTabs,
};
},
saveTabs(state, {payload}) {
let newCurrent = state.current;
for (let i = 0; i < payload.panes.length; i++) {
if (payload.panes[i].key == payload.activeKey) {
newCurrent = payload.panes[i];
}
}
return {
...state,
current: {
...newCurrent,
isModified: false,
},
tabs: {
...payload,
},
};
},
deleteTabByKey(state, {payload}) {
const newTabs = state.tabs;
for (let i = 0; i < newTabs.panes.length; i++) {
if (newTabs.panes[i].key == payload) {
newTabs.panes.splice(i, 1);
break;
}
}
const newCurrent = newTabs.panes[newTabs.panes.length - 1];
if (newTabs.activeKey == payload) {
newTabs.activeKey = newCurrent.key;
}
return {
...state,
current: {
...newCurrent,
},
tabs: {
...newTabs,
},
};
},
closeTabs(state, {payload}) {
const {deleteType, current} = payload
const newTabs = state.tabs;
const firstKey = newTabs.panes[0].key
let newCurrent = newTabs.panes[0]
if (deleteType === 'CLOSE_OTHER') {
const keys = [firstKey, current.key];
newCurrent = {...current}
newTabs.activeKey = current.key
newTabs.panes = newTabs.panes.filter(item => keys.includes(item.key));
} else {
newTabs.panes = [];
newTabs.activeKey = firstKey
}
return {
...state,
current: {
...newCurrent
},
tabs: {
...newTabs,
}
};
},
changeActiveKey(state, {payload}) {
const {tabs} = state;
tabs.activeKey = payload;
let newCurrent = state.current;
for (let i = 0; i < tabs.panes.length; i++) {
if (tabs.panes[i].key == tabs.activeKey) {
newCurrent = tabs.panes[i];
}
}
return {
...state,
current: {
...newCurrent,
},
tabs: {
...tabs,
},
currentPath: newCurrent.path,
};
},
saveTaskData(state, {payload}) {
const newTabs = state.tabs;
for (let i = 0; i < newTabs.panes.length; i++) {
if (newTabs.panes[i].key == newTabs.activeKey) {
newTabs.panes[i].task = payload;
}
}
return {
...state,
tabs: {
...newTabs,
},
};
},
saveSession(state, {payload}) {
return {
...state,
session: [...payload],
};
},
showRightClickMenu(state, {payload}) {
return {
...state,
rightClickMenu: payload,
};
},
refreshCurrentSession(state, {payload}) {
return {
...state,
currentSession: {
...state?.currentSession,
...payload
}
};
},
quitCurrentSession(state) {
return {
...state,
currentSession: {
connectors: [],
}
};
},
saveResult(state, {payload}) {
return {
...state,
result: {
...payload
},
};
},
saveCluster(state, {payload}) {
return {
...state,
cluster: payload,
};
}, saveSessionCluster(state, {payload}) {
return {
...state,
sessionCluster: payload,
};
}, saveClusterConfiguration(state, {payload}) {
return {
...state,
clusterConfiguration: payload,
};
}, saveDataBase(state, {payload}) {
return {
...state,
database: payload,
};
}, saveEnv(state, {payload}) {
return {
...state,
env: payload,
};
},
},
};
export default Model;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment