Commit 5e8f3caf authored by wenmo's avatar wenmo

面板拖动+滚动条适配

parent 9fdab641
......@@ -12,7 +12,7 @@ export default defineConfig({
babelPlugins: [],
babelOptions: {},
},
webpack5: {
/*webpack5: {
// lazyCompilation: {},
},
},*/
});
......@@ -68,6 +68,7 @@
"nzh": "^1.0.3",
"omit.js": "^2.0.2",
"react": "^17.0.0",
"react-custom-scrollbars": "^4.2.1",
"react-dev-inspector": "^1.1.1",
"react-dom": "^17.0.0",
"react-helmet-async": "^1.0.4",
......
import React, { useRef, useState } from 'react';
import useDraggable from '../../hooks/useDraggable';
import styles from './DraggleLayout.less';
import {connect} from "umi";
import {StateType} from "@/pages/FlinkSqlStudio/model";
function DraggleLayout({
children, // 两列布局
min = 0, // 左侧最小宽度
min = 400, // 左侧最小宽度
max = Infinity, // 左侧最大宽度
containerWidth = 0, // 容器宽度
containerHeight = 0, // 容器高度
initLeftWidth = 0, // 初始左侧容器宽度
handler = null, // 拖拽器
onWidthChange = width => width, // 左侧容器高度变化
}) {
toolWidth,
dispatch
}) {
const ref = useRef(null);
const [position, setPosition] = useState({ x: initLeftWidth, y: 0 });
......@@ -25,6 +29,10 @@ function DraggleLayout({
if (_x > max) _x = max;
if (onWidthChange) onWidthChange(_x);
setPosition({ x: _x, y });
dispatch&&dispatch({
type: "Studio/saveToolWidth",
payload: _x,
});
},
},
{ overbound: false },
......@@ -64,4 +72,6 @@ function DraggleLayout({
);
}
export default DraggleLayout;
export default connect(({Studio}: { Studio: StateType }) => ({
toolWidth: Studio.toolWidth,
}))(DraggleLayout);
.root {
position: relative;
//display: flex;
display: block;
//margin: 24px auto;
.top {
width: 100%;
position: relative;
.handler {
position: absolute;
right: 0;
bottom: 0;
height: auto;
width: 100%;
user-select: none;
color: #fff;
text-align: center;
cursor: n-resize;
display: flex;
flex-direction: column;
justify-content: center;
}
}
.bottom {
width: 100%;
}
}
import React, { useRef, useState } from 'react';
import useDraggable from '../../hooks/useDraggable';
import styles from './DraggleVerticalLayout.less';
import {connect} from "umi";
import {StateType} from "@/pages/FlinkSqlStudio/model";
function DraggleVerticalLayout({
children, // 两行布局
min = 100, // 顶部最小高度
max = Infinity, // 底部最大高度
containerWidth = 0, // 容器宽度
containerHeight = 0, // 容器高度
initTopHeight = 0, // 初始顶部容器高度
handler = null, // 拖拽器
onHeightChange = height => height, // 左侧容器高度变化
toolHeight,
dispatch,
}) {
const ref = useRef(null);
const [position, setPosition] = useState({ x: 0, y: toolHeight });
const [props] = useDraggable(
ref,
{
onMouseMove: ({ x, y }) => {
let _y = y;
if (_y < min) _y = min;
if (_y > max) _y = max;
if (onHeightChange) onHeightChange(_y);
setPosition({ x, y:_y });
dispatch&&dispatch({
type: "Studio/saveToolHeight",
payload: _y,
});
},
},
{ overbound: false },
);
const _handler = handler ? (
React.cloneElement(handler, {
...handler.props,
style: {
...handler.props.style,
pointerEvents: 'none',
},
})
) : (
<span style={{ fontSize: 18, pointerEvents: 'none' }}></span>
);
return (
<div
ref={ref}
className={styles.root}
style={{ width: containerWidth, height: containerHeight }}
>
<div className={styles.top} style={{ height: position.y }}>
{children[0]}
<div className={styles.handler} {...props}>
{_handler}
</div>
</div>
<div
className={styles.bottom}
style={{ height: containerHeight - position.y }}
>
{children[1]}
</div>
</div>
);
}
export default connect(({Studio}: { Studio: StateType }) => ({
toolHeight: Studio.toolHeight,
}))(DraggleVerticalLayout);
import { Tabs,Empty } from "antd";
import {CodeOutlined, TableOutlined,RadarChartOutlined,CalendarOutlined,FileSearchOutlined,DesktopOutlined
,FunctionOutlined,ApartmentOutlined} from "@ant-design/icons";
import {Tabs, Empty} from "antd";
import {
CodeOutlined, TableOutlined, RadarChartOutlined, CalendarOutlined, FileSearchOutlined, DesktopOutlined
, FunctionOutlined, ApartmentOutlined
} from "@ant-design/icons";
import {StateType} from "@/pages/FlinkSqlStudio/model";
import {connect} from "umi";
import styles from "./index.less";
......@@ -10,107 +12,126 @@ import StudioHistory from "./StudioHistory";
import StudioFX from "./StudioFX";
import StudioCA from "./StudioCA";
import StudioProcess from "./StudioProcess";
const { TabPane } = Tabs;
import {Scrollbars} from 'react-custom-scrollbars';
const {TabPane} = Tabs;
const StudioConsole = (props: any) => {
const StudioConsole = (props:any) => {
const {height} = props;
let consoleHeight = (height - 37.6);
return (
<Tabs defaultActiveKey="StudioMsg" size="small" tabPosition="top" style={{
border: "1px solid #f0f0f0",height:"50%",overflow:"auto",width: "100%"}}>
border: "1px solid #f0f0f0", height: height, margin: "0 32px"
}}>
<TabPane
tab={
<span>
<CodeOutlined />
<CodeOutlined/>
信息
</span>
}
key="StudioMsg"
>
<StudioMsg />
<Scrollbars style={{height: consoleHeight}}>
<StudioMsg/>
</Scrollbars>
</TabPane>
<TabPane
tab={
<span>
<TableOutlined />
<TableOutlined/>
结果
</span>
}
key="StudioTable"
>
<StudioTable />
<Scrollbars style={{height: consoleHeight}}>
<StudioTable/>
</Scrollbars>
</TabPane>
<TabPane
tab={
<span>
<RadarChartOutlined />
<RadarChartOutlined/>
指标
</span>
}
key="StudioMetrics"
>
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
<Scrollbars style={{height: consoleHeight}}>
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>
</Scrollbars>
</TabPane>
<TabPane
tab={
<span>
<ApartmentOutlined />
<ApartmentOutlined/>
血缘
</span>
}
key="StudioConsanguinity"
>
<StudioCA />
<Scrollbars style={{height: consoleHeight}}>
<StudioCA/>
</Scrollbars>
</TabPane>
<TabPane
tab={
<span>
<DesktopOutlined />
<DesktopOutlined/>
进程
</span>
}
key="StudioProcess"
>
<StudioProcess />
<Scrollbars style={{height: consoleHeight}}>
<StudioProcess/>
</Scrollbars>
</TabPane>
<TabPane
tab={
<span>
<CalendarOutlined />
<CalendarOutlined/>
历史
</span>
}
key="StudioHistory"
>
<StudioHistory />
<Scrollbars style={{height: consoleHeight}}>
<StudioHistory/>
</Scrollbars>
</TabPane>
<TabPane
tab={
<span>
<FunctionOutlined />
<FunctionOutlined/>
函数
</span>
}
key="StudioFX"
>
<StudioFX />
<Scrollbars style={{height: consoleHeight}}>
<StudioFX/>
</Scrollbars>
</TabPane>
<TabPane
tab={
<span>
<FileSearchOutlined />
<FileSearchOutlined/>
文档
</span>
}
key="StudioDocument"
>
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
<Scrollbars style={{height: consoleHeight}}>
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>
</Scrollbars>
</TabPane>
</Tabs>
);
};
export default connect(({ Studio }: { Studio: StateType }) => ({
export default connect(({Studio}: { Studio: StateType }) => ({
sql: Studio.sql,
}))(StudioConsole);
import {
message, Button, Table, Empty, Divider,
Tooltip,Drawer
Tooltip, Drawer
} from "antd";
import ProDescriptions from '@ant-design/pro-descriptions';
import {StateType} from "@/pages/FlinkSqlStudio/model";
......@@ -15,11 +15,11 @@ import React from "react";
import {showCluster} from "../../StudioEvent/DDL";
import {handleAddOrUpdate} from "@/components/Common/crud";
import ClusterForm from "@/pages/Cluster/components/ClusterForm";
import {SavePointTableListItem} from "@/components/Studio/StudioRightTool/StudioSavePoint/data";
import {Scrollbars} from 'react-custom-scrollbars';
const StudioCluster = (props: any) => {
const {cluster, dispatch} = props;
const {cluster, toolHeight, dispatch} = props;
const [createModalVisible, handleCreateModalVisible] = useState<boolean>(false);
const [row, setRow] = useState<{}>();
......@@ -40,7 +40,7 @@ const StudioCluster = (props: any) => {
title: "集群名",
dataIndex: "alias",
key: "alias",
},{
}, {
title: '名称',
dataIndex: 'name',
},
......@@ -88,7 +88,7 @@ const StudioCluster = (props: any) => {
title: '当前 JobManager 地址',
sorter: true,
dataIndex: 'jobManagerHost',
},{
}, {
title: '版本',
sorter: true,
dataIndex: 'version',
......@@ -209,11 +209,12 @@ const StudioCluster = (props: any) => {
<Tooltip title="刷新 Flink 集群">
<Button
type="text"
icon={<ReloadOutlined />}
icon={<ReloadOutlined/>}
onClick={onRefreshCluster}
/>
</Tooltip>
</div>
<Scrollbars style={{height: (toolHeight - 32)}}>
{cluster.length > 0 ? (
<Table dataSource={cluster} columns={getColumns()} size="small"/>) : (
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>)}
......@@ -252,10 +253,12 @@ const StudioCluster = (props: any) => {
/>
)}
</Drawer>
</Scrollbars>
</>
);
};
export default connect(({Studio}: { Studio: StateType }) => ({
cluster: Studio.cluster,
toolHeight: Studio.toolHeight,
}))(StudioCluster);
......@@ -25,10 +25,11 @@ import {
} from '@ant-design/pro-form';
import ProDescriptions from '@ant-design/pro-descriptions';
import SessionForm from "@/components/Studio/StudioLeftTool/StudioConnector/components/SessionForm";
import { Scrollbars } from 'react-custom-scrollbars';
const StudioConnector = (props: any) => {
const {current, dispatch, currentSession, session} = props;
const {current,toolHeight, dispatch, currentSession, session} = props;
const [tableData, setTableData] = useState<[]>([]);
const [loadings, setLoadings] = useState<boolean[]>([]);
const [searchText, setSearchText] = useState<string>('');
......@@ -295,6 +296,7 @@ const StudioConnector = (props: any) => {
</Tooltip>
</>)}
</div>
<Scrollbars style={{height: (toolHeight - 32)}}>
{currentSession.connectors && currentSession.connectors.length > 0 ? (
<Table dataSource={currentSession.connectors} columns={getColumns()} size="small"/>) : (
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>)}
......@@ -341,6 +343,7 @@ const StudioConnector = (props: any) => {
useRemote: true,
}}
/>
</Scrollbars>
</>
);
};
......@@ -349,4 +352,5 @@ export default connect(({Studio}: { Studio: StateType }) => ({
current: Studio.current,
currentSession: Studio.currentSession,
session: Studio.session,
toolHeight: Studio.toolHeight,
}))(StudioConnector);
......@@ -13,10 +13,11 @@ import {
import React from "react";
import {showDataBase} from "../../StudioEvent/DDL";
import DBForm from "@/pages/DataBase/components/DBForm";
import { Scrollbars } from 'react-custom-scrollbars';
const StudioDataBase = (props: any) => {
const {database, dispatch} = props;
const {database,toolHeight, dispatch} = props;
const [chooseDBModalVisible, handleDBFormModalVisible] = useState<boolean>(false);
const [values, setValues] = useState<any>({});
......@@ -76,6 +77,7 @@ const StudioDataBase = (props: any) => {
/>
</Tooltip>
</div>
<Scrollbars style={{height: (toolHeight - 32)}}>
{database.length > 0 ? (
<Table dataSource={database} columns={getColumns()} size="small"/>) : (
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>)}
......@@ -90,10 +92,12 @@ const StudioDataBase = (props: any) => {
}}
values={values}
/>
</Scrollbars>
</>
);
};
export default connect(({Studio}: { Studio: StateType }) => ({
database: Studio.database,
toolHeight: Studio.toolHeight,
}))(StudioDataBase);
......@@ -13,15 +13,14 @@ import {
} from '@ant-design/icons';
import React from "react";
import {showMetaDataTable} from "@/components/Studio/StudioEvent/DDL";
import {convertToTreeData} from "@/components/Studio/StudioTree/Function";
import {getCatalogueTreeData} from "@/pages/FlinkSqlStudio/service";
import { Scrollbars } from 'react-custom-scrollbars';
const { DirectoryTree } = Tree;
const {Option} = Select;
const StudioMetaData = (props: any) => {
const {database, dispatch} = props;
const {database,toolHeight, dispatch} = props;
const [databaseId, setDataBaseId] = useState<number>();
const [treeData, setTreeData] = useState<[]>([]);
......@@ -78,16 +77,19 @@ const StudioMetaData = (props: any) => {
/>
</Tooltip>
</div>
<Scrollbars style={{height: (toolHeight - 32)}}>
<DirectoryTree
multiple
switcherIcon={<DownOutlined/>}
treeData={treeData}
height={400}
/>
</Scrollbars>
</>
);
};
export default connect(({Studio}: { Studio: StateType }) => ({
database: Studio.database,
toolHeight: Studio.toolHeight,
}))(StudioMetaData);
......@@ -13,9 +13,10 @@ import StudioMetaData from "./StudioMetaData";
const { TabPane } = Tabs;
const StudioLeftTool = (props:any) => {
const {toolHeight} = props;
return (
<Tabs defaultActiveKey="1" size="small" tabPosition="left" style={{ height: "100%"}}>
<Tabs defaultActiveKey="1" size="small" tabPosition="left" style={{ height: toolHeight}}>
<TabPane tab={<span><BarsOutlined/> 目录</span>} key="StudioTree">
<StudioTree/>
</TabPane>
......@@ -40,4 +41,5 @@ const StudioLeftTool = (props:any) => {
export default connect(({ Studio }: { Studio: StateType }) => ({
sql: Studio.sql,
toolHeight: Studio.toolHeight,
}))(StudioLeftTool);
......@@ -8,13 +8,14 @@ import {InfoCircleOutlined,PlusOutlined,MinusSquareOutlined} from "@ant-design/i
import styles from "./index.less";
import {useEffect, useState} from "react";
import {showTables} from "@/components/Studio/StudioEvent/DDL";
import { Scrollbars } from 'react-custom-scrollbars';
const { Option } = Select;
const { Text } = Typography;
const StudioConfig = (props: any) => {
const {current,form,dispatch,tabs,currentSession} = props;
const {current,form,dispatch,tabs,currentSession,toolHeight} = props;
form.setFieldsValue(current.task);
......@@ -50,6 +51,7 @@ const StudioConfig = (props: any) => {
</div>
</Col>
</Row>
<Scrollbars style={{height:(toolHeight-32)}}>
<Form
form={form}
layout="vertical"
......@@ -86,6 +88,7 @@ const StudioConfig = (props: any) => {
}
</Form.Item>
</Form>
</Scrollbars>
</>
);
};
......@@ -95,4 +98,5 @@ export default connect(({Studio}: { Studio: StateType }) => ({
current: Studio.current,
currentSession: Studio.currentSession,
tabs: Studio.tabs,
toolHeight: Studio.toolHeight,
}))(StudioConfig);
import React, {useRef, useState} from "react";
import {DownOutlined, HeartOutlined, PlusOutlined, UserOutlined} from '@ant-design/icons';
import {MinusSquareOutlined} from '@ant-design/icons';
import {ActionType, ProColumns} from "@ant-design/pro-table";
import {Drawer,Table} from 'antd';
import {Drawer,Row,Col,Tooltip,Button} from 'antd';
import ProTable from '@ant-design/pro-table';
import ProDescriptions from '@ant-design/pro-descriptions';
import {queryData} from "@/components/Common/crud";
import {SavePointTableListItem} from "@/components/Studio/StudioRightTool/StudioSavePoint/data";
import {StateType} from "@/pages/FlinkSqlStudio/model";
import {connect} from "umi";
import { Scrollbars } from 'react-custom-scrollbars';
const url = '/api/savepoints';
const StudioSavePoint: React.FC<{}> = (props: any) => {
const {current,dispatch} = props;
const {current,toolHeight,dispatch} = props;
const [row, setRow] = useState<SavePointTableListItem>();
const actionRef = useRef<ActionType>();
......@@ -70,6 +71,19 @@ const StudioSavePoint: React.FC<{}> = (props: any) => {
return (
<>
<Row>
<Col span={24}>
<div style={{float: "right"}}>
<Tooltip title="最小化">
<Button
type="text"
icon={<MinusSquareOutlined />}
/>
</Tooltip>
</div>
</Col>
</Row>
<Scrollbars style={{height:(toolHeight-32)}}>
<ProTable<SavePointTableListItem>
actionRef={actionRef}
rowKey="id"
......@@ -99,10 +113,12 @@ const StudioSavePoint: React.FC<{}> = (props: any) => {
/>
)}
</Drawer>
</Scrollbars>
</>
);
};
export default connect(({ Studio }: { Studio: StateType }) => ({
current: Studio.current,
toolHeight: Studio.toolHeight,
}))(StudioSavePoint);
import {connect} from "umi";
import {StateType} from "@/pages/FlinkSqlStudio/model";
import {Form, InputNumber, Input, Switch, Select, Tag, Row, Col, Badge, Tooltip, Button, Typography,Space} from "antd";
import {InfoCircleOutlined,PlusOutlined,MinusSquareOutlined,MinusCircleOutlined} from "@ant-design/icons";
import {Form, InputNumber, Input, Switch, Select, Tag, Row, Col, Badge, Tooltip, Button, Typography, Space} from "antd";
import {InfoCircleOutlined, PlusOutlined, MinusSquareOutlined, MinusCircleOutlined} from "@ant-design/icons";
import styles from "./index.less";
import {useEffect, useState} from "react";
import { showTables} from "@/components/Studio/StudioEvent/DDL";
import {showTables} from "@/components/Studio/StudioEvent/DDL";
import {JarStateType} from "@/pages/Jar/model";
import {Scrollbars} from 'react-custom-scrollbars';
const { Option } = Select;
const { Text } = Typography;
const {Option} = Select;
const {Text} = Typography;
const StudioSetting = (props: any) => {
const {sessionCluster,clusterConfiguration,current,form,dispatch,tabs,currentSession,jars} = props;
const {sessionCluster, clusterConfiguration, current, form, dispatch, tabs, currentSession, jars, toolHeight} = props;
const getClusterOptions = ()=>{
const getClusterOptions = () => {
let itemList = [(<Option key={0} value={0} label={(<><Tag color="default">Local</Tag>本地环境</>)}>
<Tag color="default">Local</Tag>
本地环境
</Option>)];
for(let item of sessionCluster){
let tag =(<><Tag color={item.enabled?"processing":"error"}>{item.type}</Tag>{item.alias}</>);
for (let item of sessionCluster) {
let tag = (<><Tag color={item.enabled ? "processing" : "error"}>{item.type}</Tag>{item.alias}</>);
itemList.push(<Option key={item.id} value={item.id} label={tag}>
{tag}
</Option>)
......@@ -28,10 +29,10 @@ const StudioSetting = (props: any) => {
return itemList;
};
const getClusterConfigurationOptions = ()=>{
const getClusterConfigurationOptions = () => {
let itemList = [];
for(let item of clusterConfiguration){
let tag =(<><Tag color={item.enabled?"processing":"error"}>{item.type}</Tag>{item.alias}</>);
for (let item of clusterConfiguration) {
let tag = (<><Tag color={item.enabled ? "processing" : "error"}>{item.type}</Tag>{item.alias}</>);
itemList.push(<Option key={item.id} value={item.id} label={tag}>
{tag}
</Option>)
......@@ -39,10 +40,10 @@ const StudioSetting = (props: any) => {
return itemList;
};
const getJarOptions = ()=>{
const getJarOptions = () => {
let itemList = [];
for(let item of jars){
let tag =(<><Tag color={item.enabled?"processing":"error"}>{item.type}</Tag>{item.alias}</>);
for (let item of jars) {
let tag = (<><Tag color={item.enabled ? "processing" : "error"}>{item.type}</Tag>{item.alias}</>);
itemList.push(<Option key={item.id} value={item.id} label={tag}>
{tag}
</Option>)
......@@ -50,29 +51,29 @@ const StudioSetting = (props: any) => {
return itemList;
};
useEffect(()=>{
useEffect(() => {
form.setFieldsValue(current.task);
},[current.task]);
}, [current.task]);
const onValuesChange = (change:any,all:any)=>{
const onValuesChange = (change: any, all: any) => {
let newTabs = tabs;
for(let i=0;i<newTabs.panes.length;i++){
if(newTabs.panes[i].key==newTabs.activeKey){
for(let key in change){
newTabs.panes[i].task[key]=all[key];
for (let i = 0; i < newTabs.panes.length; i++) {
if (newTabs.panes[i].key == newTabs.activeKey) {
for (let key in change) {
newTabs.panes[i].task[key] = all[key];
}
break;
}
}
dispatch&&dispatch({
dispatch && dispatch({
type: "Studio/saveTabs",
payload: newTabs,
});
};
const onChangeClusterSession = ()=>{
showTables(currentSession.session,dispatch);
const onChangeClusterSession = () => {
showTables(currentSession.session, dispatch);
};
return (
<>
......@@ -82,12 +83,13 @@ const StudioSetting = (props: any) => {
<Tooltip title="最小化">
<Button
type="text"
icon={<MinusSquareOutlined />}
icon={<MinusSquareOutlined/>}
/>
</Tooltip>
</div>
</Col>
</Row>
<Scrollbars style={{height: (toolHeight - 32)}}>
<Form
form={form}
layout="vertical"
......@@ -105,18 +107,19 @@ const StudioSetting = (props: any) => {
<Option value="yarn-application">yarn-application</Option>
</Select>
</Form.Item>
{(current.task.type=='yarn-session'||current.task.type=='standalone')?(
{(current.task.type == 'yarn-session' || current.task.type == 'standalone') ? (
<Row>
<Col span={24}>
<Form.Item label="Flink集群" tooltip={`选择Flink集群进行 ${current.task.type} 模式的远程提交任务`} name="clusterId"
className={styles.form_item}>
{
currentSession.session?
(currentSession.sessionConfig&&currentSession.sessionConfig.clusterId?
(<><Badge status="success"/><Text type="success">{currentSession.sessionConfig.clusterName}</Text></>)
:(<><Badge status="error"/><Text type="danger">本地模式</Text></>)
):(<Select
style={{ width: '100%' }}
currentSession.session ?
(currentSession.sessionConfig && currentSession.sessionConfig.clusterId ?
(<><Badge status="success"/><Text
type="success">{currentSession.sessionConfig.clusterName}</Text></>)
: (<><Badge status="error"/><Text type="danger">本地模式</Text></>)
) : (<Select
style={{width: '100%'}}
placeholder="选择Flink集群"
defaultValue={0}
optionLabelProp="label"
......@@ -127,14 +130,15 @@ const StudioSetting = (props: any) => {
}
</Form.Item>
</Col>
</Row>):''}
{(current.task.type=='yarn-per-job'||current.task.type=='yarn-application')?(
</Row>) : ''}
{(current.task.type == 'yarn-per-job' || current.task.type == 'yarn-application') ? (
<Row>
<Col span={24}>
<Form.Item label="Flink集群配置" tooltip={`选择Flink集群配置进行 ${current.task.type} 模式的远程提交任务`} name="clusterConfigurationId"
<Form.Item label="Flink集群配置" tooltip={`选择Flink集群配置进行 ${current.task.type} 模式的远程提交任务`}
name="clusterConfigurationId"
className={styles.form_item}>
<Select
style={{ width: '100%' }}
style={{width: '100%'}}
placeholder="选择Flink集群配置"
defaultValue={0}
optionLabelProp="label"
......@@ -143,14 +147,16 @@ const StudioSetting = (props: any) => {
</Select>
</Form.Item>
</Col>
</Row>):''}
{(current.task.type=='yarn-application')?(
</Row>) : ''}
{(current.task.type == 'yarn-application') ? (
<Row>
<Col span={24}>
<Form.Item label="可执行 Jar" tooltip={`选择可执行 Jar 进行 ${current.task.type} 模式的远程提交 Jar 任务。当该参数项存在值时,将只提交可执行 Jar.`} name="jarId"
<Form.Item label="可执行 Jar"
tooltip={`选择可执行 Jar 进行 ${current.task.type} 模式的远程提交 Jar 任务。当该参数项存在值时,将只提交可执行 Jar.`}
name="jarId"
className={styles.form_item}>
<Select
style={{ width: '100%' }}
style={{width: '100%'}}
placeholder="选择可执行Jar,非必填"
allowClear
optionLabelProp="label"
......@@ -159,12 +165,12 @@ const StudioSetting = (props: any) => {
</Select>
</Form.Item>
</Col>
</Row>):''}
</Row>) : ''}
<Form.Item
label="作业名" className={styles.form_item} name="jobName"
tooltip='设置任务名称,默认为作业名'
>
<Input placeholder="自定义作业名" />
<Input placeholder="自定义作业名"/>
</Form.Item>
<Row>
<Col span={12}>
......@@ -178,7 +184,7 @@ const StudioSetting = (props: any) => {
label="Parallelism" className={styles.form_item} name="parallelism"
tooltip="设置Flink任务的并行度,最小为 1"
>
<InputNumber min={1} max={9999} defaultValue={1} />
<InputNumber min={1} max={9999} defaultValue={1}/>
</Form.Item>
</Col>
</Row>
......@@ -186,7 +192,7 @@ const StudioSetting = (props: any) => {
<Col span={12}>
<Form.Item
label="Fragment" className={styles.form_item} name="fragment" valuePropName="checked"
tooltip={{ title: '【增强特性】 开启FlinkSql片段机制,使用“:=”进行定义(以“;”结束),“${}”进行调用', icon: <InfoCircleOutlined /> }}
tooltip={{title: '【增强特性】 开启FlinkSql片段机制,使用“:=”进行定义(以“;”结束),“${}”进行调用', icon: <InfoCircleOutlined/>}}
>
<Switch checkedChildren="启用" unCheckedChildren="禁用"
/>
......@@ -195,7 +201,10 @@ const StudioSetting = (props: any) => {
<Col span={12}>
<Form.Item
label="启用语句集" className={styles.form_item} name="statementSet" valuePropName="checked"
tooltip={{ title: '【增强特性】 开启语句集机制,将把多个 Insert 语句合成一个 JobGraph 再进行提交,Select 语句无效', icon: <InfoCircleOutlined /> }}
tooltip={{
title: '【增强特性】 开启语句集机制,将把多个 Insert 语句合成一个 JobGraph 再进行提交,Select 语句无效',
icon: <InfoCircleOutlined/>
}}
>
<Switch checkedChildren="启用" unCheckedChildren="禁用"
/>
......@@ -219,40 +228,40 @@ const StudioSetting = (props: any) => {
tooltip='从SavePointPath恢复Flink任务'
>
<Input placeholder="hdfs://..."/>
</Form.Item>):''
</Form.Item>) : ''
}
<Form.Item
label="其他配置" className={styles.form_item}
tooltip={{ title: '其他配置项,将被应用于执行环境,如 pipeline.name', icon: <InfoCircleOutlined /> }}
tooltip={{title: '其他配置项,将被应用于执行环境,如 pipeline.name', icon: <InfoCircleOutlined/>}}
>
<Form.List name="config"
>
{(fields, { add, remove }) => (
{(fields, {add, remove}) => (
<>
{fields.map(({ key, name, fieldKey, ...restField }) => (
<Space key={key} style={{ display: 'flex' }} align="baseline">
{fields.map(({key, name, fieldKey, ...restField}) => (
<Space key={key} style={{display: 'flex'}} align="baseline">
<Form.Item
{...restField}
name={[name, 'key']}
// fieldKey={[fieldKey, 'key']}
style={{ marginBottom: '5px' }}
style={{marginBottom: '5px'}}
>
<Input placeholder="参数" />
<Input placeholder="参数"/>
</Form.Item>
<Form.Item
{...restField}
name={[name, 'value']}
// fieldKey={[fieldKey, 'value']}
style={{ marginBottom: '5px' }}
style={{marginBottom: '5px'}}
>
<Input placeholder="值" />
<Input placeholder="值"/>
</Form.Item>
<MinusCircleOutlined onClick={() => remove(name)} />
<MinusCircleOutlined onClick={() => remove(name)}/>
</Space>
))}
<Form.Item>
<Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}>
<Button type="dashed" onClick={() => add()} block icon={<PlusOutlined/>}>
添加配置项
</Button>
</Form.Item>
......@@ -261,16 +270,18 @@ const StudioSetting = (props: any) => {
</Form.List>
</Form.Item>
</Form>
</Scrollbars>
</>
);
};
export default connect(({Studio,Jar}: { Studio: StateType,Jar: JarStateType }) => ({
export default connect(({Studio, Jar}: { Studio: StateType, Jar: JarStateType }) => ({
sessionCluster: Studio.sessionCluster,
clusterConfiguration: Studio.clusterConfiguration,
current: Studio.current,
tabs: Studio.tabs,
session: Studio.session,
currentSession: Studio.currentSession,
toolHeight: Studio.toolHeight,
jars: Jar.jars,
}))(StudioSetting);
......@@ -7,16 +7,15 @@ import StudioConfig from "./StudioConfig";
import StudioSetting from "./StudioSetting";
import StudioSavePoint from "./StudioSavePoint";
const { TabPane } = Tabs;
const StudioRightTool = (props:any) => {
// const [form] = Form.useForm();
const {form} = props;
const {form,toolHeight} = props;
return (
<Tabs defaultActiveKey="1" size="small" tabPosition="right" style={{ height: "100%",overflow:"auto"}}>
<Tabs defaultActiveKey="1" size="small" tabPosition="right" style={{ height: toolHeight}}>
<TabPane tab={<span><SettingOutlined /> 作业配置</span>} key="StudioSetting" >
<StudioSetting form={form} />
</TabPane>
......@@ -35,4 +34,5 @@ const StudioRightTool = (props:any) => {
export default connect(({ Studio }: { Studio: StateType }) => ({
sql: Studio.sql,
toolHeight: Studio.toolHeight,
}))(StudioRightTool);
import {message, Tabs } from 'antd';
import {message, Tabs} from 'antd';
import React, {useState} from 'react';
import {connect} from "umi";
import {StateType} from "@/pages/FlinkSqlStudio/model";
import styles from './index.less';
import StudioEdit from '../StudioEdit';
import {saveTask} from "@/components/Studio/StudioEvent/DDL";
const { TabPane } = Tabs;
const {TabPane} = Tabs;
const EditorTabs = (props: any) => {
const {tabs,dispatch,current} = props;
const {tabs, dispatch, current, toolHeight,width} = props;
const onChange = (activeKey: any) => {
dispatch({
......@@ -18,11 +19,11 @@ const EditorTabs = (props: any) => {
};
const onEdit = (targetKey: any, action: any) => {
if(action=='add'){
if (action == 'add') {
add();
}else if(action=='remove'){
if(current.isModified){
saveTask(current,dispatch);
} else if (action == 'remove') {
if (current.isModified) {
saveTask(current, dispatch);
}
remove(targetKey);
}
......@@ -32,7 +33,7 @@ const EditorTabs = (props: any) => {
message.warn('敬请期待');
};
const remove = (targetKey:any) => {
const remove = (targetKey: any) => {
let newActiveKey = tabs.activeKey;
let lastIndex = 0;
tabs.panes.forEach((pane, i) => {
......@@ -52,26 +53,25 @@ const EditorTabs = (props: any) => {
dispatch({
type: "Studio/saveTabs",
payload: {
activeKey:newActiveKey,
panes:newPanes,
activeKey: newActiveKey,
panes: newPanes,
},
});
};
return (
<Tabs
hideAdd
type="editable-card"
size="small"
onChange={onChange}
activeKey={tabs.activeKey+''}
activeKey={tabs.activeKey + ''}
onEdit={onEdit}
className={styles["edit-tabs"]}
style={{height:"50%"}}
style={{height: toolHeight}}
>
{tabs.panes.map(pane => (
<TabPane tab={pane.title} key={pane.key} closable={pane.closable}>
<StudioEdit tabsKey={pane.key} height='100%'/>
<StudioEdit tabsKey={pane.key} height={(toolHeight - 32)} width={width}/>
</TabPane>
))}
</Tabs>
......@@ -79,8 +79,9 @@ const EditorTabs = (props: any) => {
)
};
export default connect(({ Studio }: { Studio: StateType }) => ({
export default connect(({Studio}: { Studio: StateType }) => ({
current: Studio.current,
sql: Studio.sql,
tabs: Studio.tabs,
toolHeight: Studio.toolHeight,
}))(EditorTabs);
......@@ -13,6 +13,7 @@ import {
import UpdateCatalogueForm from './components/UpdateCatalogueForm';
import {ActionType} from "@ant-design/pro-table";
import UpdateTaskForm from "@/components/Studio/StudioTree/components/UpdateTaskForm";
import { Scrollbars } from 'react-custom-scrollbars';
const { DirectoryTree } = Tree;
......@@ -48,7 +49,7 @@ const getParentKey = (key, tree) => {
};
const StudioTree: React.FC<StudioTreeProps> = (props) => {
const {rightClickMenu,dispatch,tabs,refs} = props;
const {rightClickMenu,dispatch,tabs,refs,toolHeight} = props;
const [treeData, setTreeData] = useState<TreeDataNode[]>();
const [dataList, setDataList] = useState<[]>();
......@@ -362,6 +363,7 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
</div>
</Col>
</Row>
<Scrollbars style={{height:(toolHeight-32)}}>
{/*<Search style={{marginBottom: 8}} placeholder="Search" onChange={onChange}/>*/}
<DirectoryTree
multiple
......@@ -415,6 +417,7 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
isCreate={isCreate}
/>
) : null}
</Scrollbars>
</div>
);
};
......@@ -425,4 +428,5 @@ export default connect(({Studio}: { Studio: StateType }) => ({
tabs: Studio.tabs,
rightClickMenu: Studio.rightClickMenu,
refs: Studio.refs,
toolHeight: Studio.toolHeight,
}))(StudioTree);
......@@ -17,41 +17,53 @@
background-color: #ffffff;
}
:global {
/* --- tool窗口 滚动条 --- start */
.scrollbars-tool{
height: calc((100vh - 116px)/2 - 32px)!important;
}
/* --- tool窗口 滚动条 --- end */
/* --- 水平 tabs --- start */
.ant-tabs-top > .ant-tabs-nav, .ant-tabs-bottom > .ant-tabs-nav, .ant-tabs-top > div > .ant-tabs-nav, .ant-tabs-bottom > div > .ant-tabs-nav {
margin: 0;
}
/* --- 水平 tabs --- end */
/* --- card 内偏移样式 --- start */
#studio_card > .ant-card-body {
padding: 0px;
}
/* --- card 内偏移样式 --- start */
/* --- card 内偏移样式 --- end */
/* --- list toolbar隐藏滚动条 --- start */
.ant-pro-table-list-toolbar {
overflow-x: hidden;
overflow-y: hidden;
line-height: 1;
}
/* --- list toolbar隐藏滚动条 --- start */
/* --- list toolbar隐藏滚动条 --- end */
/* --- list toolbar修改内偏移 --- start */
.ant-pro-table-list-toolbar-container {
padding: 0;
}
/* --- list toolbar修改内偏移 --- start */
/* --- list toolbar修改内偏移 --- end */
/* --- prodescription item宽度 --- start */
.ant-descriptions-item-content {
width: 100%;
}
/* --- prodescription item宽度 --- start */
/* --- prodescription item宽度 --- end */
/* --- table 宽度 --- start */
.ant-table-wrapper {
width: 100%;
}
/* --- table 宽度 --- start */
/* --- table 宽度 --- end */
/* --- 右键菜单选项 高度 --- start */
.ant-menu-vertical > .ant-menu-item, .ant-menu-vertical-left > .ant-menu-item, .ant-menu-vertical-right > .ant-menu-item, .ant-menu-inline > .ant-menu-item, .ant-menu-vertical > .ant-menu-submenu > .ant-menu-submenu-title, .ant-menu-vertical-left > .ant-menu-submenu > .ant-menu-submenu-title, .ant-menu-vertical-right > .ant-menu-submenu > .ant-menu-submenu-title, .ant-menu-inline > .ant-menu-submenu > .ant-menu-submenu-title {
height: 30px;
line-height: 30px;
}
/* --- 右键菜单选项 高度 --- start */
/* --- 右键菜单选项 高度 --- end */
}
/* --- tabs 垂直样式 --- start */
......
import React, {useEffect, useRef, useState,useCallback} from "react";
import React, {useEffect, useRef, useState, useCallback} from "react";
import {connect} from "umi";
import styles from './index.less';
import {} from "@ant-design/icons";
import StudioMenu from "./StudioMenu";
import {Row, Col, Card, Form,BackTop} from "antd";
import {Row, Col, Card, Form, BackTop} from "antd";
import StudioTabs from "./StudioTabs";
import {StateType} from "@/pages/FlinkSqlStudio/model";
import StudioConsole from "./StudioConsole";
......@@ -15,28 +15,31 @@ import {
} from "@/components/Studio/StudioEvent/DDL";
import {loadSettings} from "@/pages/Settings/function";
import DraggleLayout from "@/components/DraggleLayout";
import DraggleVerticalLayout from "@/components/DraggleLayout/DraggleVerticalLayout";
type StudioProps = {
rightClickMenu:StateType['rightClickMenu'];
dispatch:any;
rightClickMenu: StateType['rightClickMenu'];
dispatch: any;
};
const Studio: React.FC<StudioProps> = (props) => {
const {rightClickMenu,dispatch} = props;
const {rightClickMenu, toolHeight, toolWidth, dispatch} = props;
const [form] = Form.useForm();
const VIEW = {
rightToolWidth:300,
leftToolWidth:300,
marginTop:116,
rightToolWidth: 300,
leftToolWidth: 300,
marginTop: 116,
topHeight: 35.6,
bottomHeight: 153.6,
};
const [size, setSize] = useState({
width: document.documentElement.clientWidth-1,
width: document.documentElement.clientWidth - 1,
height: document.documentElement.clientHeight,
});
const onResize = useCallback(() => {
setSize({
width: document.documentElement.clientWidth-1,
width: document.documentElement.clientWidth - 1,
height: document.documentElement.clientHeight,
})
}, []);
......@@ -50,7 +53,7 @@ const Studio: React.FC<StudioProps> = (props) => {
}, [onResize]);
loadSettings(dispatch);
getFillAllByVersion('',dispatch);
getFillAllByVersion('', dispatch);
showCluster(dispatch);
showSessionCluster(dispatch);
showClusterConfiguration(dispatch);
......@@ -58,9 +61,9 @@ const Studio: React.FC<StudioProps> = (props) => {
listSession(dispatch);
showJars(dispatch);
const onClick=()=>{
if(rightClickMenu){
dispatch&&dispatch({
const onClick = () => {
if (rightClickMenu) {
dispatch && dispatch({
type: "Studio/showRightClickMenu",
payload: false,
});
......@@ -68,15 +71,31 @@ const Studio: React.FC<StudioProps> = (props) => {
};
return (
<div onClick={onClick} style={{'margin':'-24px'}}>
<div onClick={onClick} style={{'margin': '-24px'}}>
<StudioMenu form={form}/>
<Card bordered={false} className={styles.card} size="small" id="studio_card" style={{marginBottom:0}}>
<Card bordered={false} className={styles.card} size="small" id="studio_card" style={{marginBottom: 0}}>
<DraggleVerticalLayout
containerWidth={size.width}
containerHeight={(size.height - VIEW.marginTop)}
min={(VIEW.topHeight)}
max={(size.height - VIEW.bottomHeight)}
initTopHeight={VIEW.topHeight}
handler={
<div
style={{
height: 4,
width: '100%',
background: 'rgb(240, 240, 240)',
}}
/>
}
>
<Row>
<DraggleLayout
containerWidth={size.width-VIEW.rightToolWidth}
containerHeight={(size.height-VIEW.marginTop)/2}
containerWidth={size.width - VIEW.rightToolWidth}
containerHeight={toolHeight}
min={VIEW.leftToolWidth}
max={size.width*(1/2)}
max={size.width * (1 / 2)}
initLeftWidth={VIEW.leftToolWidth}
handler={
<div
......@@ -89,39 +108,34 @@ const Studio: React.FC<StudioProps> = (props) => {
}
>
<Col className={styles["vertical-tabs"]}>
<StudioLeftTool className={styles["vertical-tabs"]} style={{
height: (size.height-VIEW.marginTop),
<StudioLeftTool style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}/>
</Col>
<Col
style={{
height: ((size.height-VIEW.marginTop)),
}}>
<StudioTabs
style={{
height: ((size.height-VIEW.marginTop)/2),
}}
/>
<StudioConsole
style={{
height: ((size.height-VIEW.marginTop)/2),
}}
/>
<Col>
<StudioTabs width={size.width - VIEW.rightToolWidth - toolWidth}/>
</Col>
</DraggleLayout>
<Col id='StudioRightTool' style={{width:VIEW.rightToolWidth,height:(size.height-VIEW.marginTop)}} className={styles["vertical-tabs"]}>
<Col id='StudioRightTool' style={{width: VIEW.rightToolWidth}} className={styles["vertical-tabs"]}>
<StudioRightTool form={form}/>
</Col>
</Row>
<Row>
<Col span={24}>
<StudioConsole height={size.height - toolHeight - VIEW.marginTop}/>
</Col>
</Row>
</DraggleVerticalLayout>
</Card>
<BackTop />
<BackTop/>
</div>
)
};
export default connect(({Studio}: { Studio: StateType }) => ({
rightClickMenu: Studio.rightClickMenu,
toolHeight: Studio.toolHeight,
toolWidth: Studio.toolWidth,
}))(Studio);
......@@ -122,6 +122,8 @@ export type SessionType = {
}
export type StateType = {
toolHeight?: number;
toolWidth?: number;
cluster?: ClusterType[];
sessionCluster?: ClusterType[];
clusterConfiguration?: ClusterConfigurationType[];
......@@ -147,6 +149,8 @@ export type ModelType = {
saveTask: Effect;
};
reducers: {
saveToolHeight: Reducer<StateType>;
saveToolWidth: Reducer<StateType>;
saveSql: Reducer<StateType>;
saveCurrentPath: Reducer<StateType>;
saveMonaco: Reducer<StateType>;
......@@ -169,6 +173,8 @@ export type ModelType = {
const Model: ModelType = {
namespace: 'Studio',
state: {
toolHeight: 400,
toolWidth: 300,
cluster: [],
sessionCluster: [],
clusterConfiguration: [],
......@@ -271,6 +277,17 @@ const Model: ModelType = {
},
reducers: {
saveToolHeight(state, {payload}) {
return {
...state,
toolHeight: payload,
};
},saveToolWidth(state, {payload}) {
return {
...state,
toolWidth: payload,
};
},
saveSql(state, {payload}) {
const tabs = state.tabs;
let newCurrent = state.current;
......
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