Unverified Commit 7785f5af authored by aiwenmo's avatar aiwenmo Committed by GitHub

[Optimization-1123][admin,web] Optimizate UDFTemplate manager and process console refresh (#1124)

Co-authored-by: 's avatarwenmo <32723967+wenmo@users.noreply.github.com>
parent ca30c57b
......@@ -48,6 +48,7 @@ import lombok.extern.slf4j.Slf4j;
@RestController
@RequestMapping("/api/udf")
public class UDFController {
@Resource
UDFTemplateService udfTemplateService;
......@@ -58,7 +59,7 @@ public class UDFController {
@PutMapping("/template/")
public Result<String> addTemplate(@RequestBody UDFTemplate udfTemplate) {
return udfTemplateService.save(udfTemplate) ? Result.succeed("操作成功") : Result.failed("操作失败");
return udfTemplateService.saveOrUpdate(udfTemplate) ? Result.succeed("操作成功") : Result.failed("操作失败");
}
@DeleteMapping("/template/list")
......
......@@ -27,11 +27,12 @@ import com.dlink.model.UDFTemplate;
* @since 0.6.8
*/
public interface UDFTemplateService extends ISuperService<UDFTemplate> {
/**
* 保存
*
* @param udfTemplate udf模板
* @return boolean
*/
boolean save(UDFTemplate udfTemplate);
boolean saveOrUpdate(UDFTemplate udfTemplate);
}
......@@ -19,6 +19,7 @@
package com.dlink.service.impl;
import com.dlink.assertion.Asserts;
import com.dlink.db.service.impl.SuperServiceImpl;
import com.dlink.exception.BusException;
import com.dlink.mapper.UDFTemplateMapper;
......@@ -32,27 +33,23 @@ import org.springframework.stereotype.Service;
* @since 0.6.8
*/
@Service
public class UDFTemplateServiceImpl extends SuperServiceImpl<UDFTemplateMapper, UDFTemplate> implements UDFTemplateService {
public class UDFTemplateServiceImpl extends SuperServiceImpl<UDFTemplateMapper, UDFTemplate>
implements
UDFTemplateService {
@Override
public boolean save(UDFTemplate udfTemplate) {
public boolean saveOrUpdate(UDFTemplate udfTemplate) {
UDFTemplate selectOne = query().eq("name", udfTemplate.getName()).one();
if (udfTemplate.getId() == 0) {
// 添加
udfTemplate.setId(null);
if (Asserts.isNull(udfTemplate.getId())) {
if ((selectOne != null)) {
throw new BusException("模板名已经存在");
}
return save(udfTemplate);
} else {
// 修改
if (selectOne == null) {
return saveOrUpdate(udfTemplate);
}
if (!udfTemplate.getId().equals(selectOne.getId())) {
if (Asserts.isNotNull(selectOne) && !udfTemplate.getId().equals(selectOne.getId())) {
throw new BusException("模板名已经存在");
}
return updateById(udfTemplate);
}
return saveOrUpdate(udfTemplate);
}
}
......@@ -945,7 +945,48 @@ UPDATE `dlink_task_statement` SET `tenant_id` = 1;
UPDATE `dlink_task_version` SET `tenant_id` = 1;
UPDATE `dlink_job_history` SET `tenant_id` = 1;
DROP TABLE IF EXISTS `dlink_udf`;
CREATE TABLE `dlink_udf` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL COMMENT 'udf名',
`class_name` varchar(50) DEFAULT NULL COMMENT '完整的类名',
`source_code` text COMMENT '源码',
`compiler_code` binary(255) DEFAULT NULL COMMENT '编译产物',
`version_id` int(11) DEFAULT NULL COMMENT '版本',
`version_description` varchar(50) DEFAULT NULL COMMENT '版本描述',
`is_default` tinyint(1) DEFAULT NULL COMMENT '是否默认',
`document_id` int(11) DEFAULT NULL COMMENT '对应文档id',
`from_version_id` int(11) DEFAULT NULL COMMENT '基于udf版本id',
`code_md5` varchar(50) DEFAULT NULL COMMENT '源码',
`dialect` varchar(50) DEFAULT NULL COMMENT '方言',
`type` varchar(50) DEFAULT NULL COMMENT '类型',
`step` int(255) DEFAULT NULL COMMENT '作业生命周期',
`enable` tinyint(1) DEFAULT NULL COMMENT '是否启用',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Table structure for dlink_udf_template
-- ----------------------------
DROP TABLE IF EXISTS `dlink_udf_template`;
CREATE TABLE `dlink_udf_template` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL COMMENT '模板名称',
`code_type` varchar(10) DEFAULT NULL COMMENT '代码类型',
`function_type` varchar(10) DEFAULT NULL COMMENT '函数类型',
`template_code` text COMMENT '模板代码',
`enabled` tinyint(1) DEFAULT NULL,
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Records of dlink_udf_template
-- ----------------------------
INSERT INTO `dlink_udf_template` (`id`, `name`, `code_type`, `function_type`, `template_code`, `enabled`, `create_time`, `update_time`) VALUES (1, 'java_udf', 'java', 'UDF', 'package ${package};\n\nimport org.apache.flink.table.functions.ScalarFunction;\n\npublic class ${className} extends ScalarFunction {\n public String eval(String s) {\n return null;\n }\n}', NULL, '2022-10-19 09:17:37', '2022-10-19 09:17:37');
INSERT INTO `dlink_udf_template` (`id`, `name`, `code_type`, `function_type`, `template_code`, `enabled`, `create_time`, `update_time`) VALUES (2, 'java_udtf', 'java', 'UDTF', 'package ${package};\n\nimport org.apache.flink.table.functions.ScalarFunction;\n\n@FunctionHint(output = @DataTypeHint(\"ROW<word STRING, length INT>\"))\npublic static class ${className} extends TableFunction<Row> {\n\n public void eval(String str) {\n for (String s : str.split(\" \")) {\n // use collect(...) to emit a row\n collect(Row.of(s, s.length()));\n }\n }\n}', NULL, '2022-10-19 09:22:58', '2022-10-19 10:01:57');
SET FOREIGN_KEY_CHECKS = 1;
......@@ -897,4 +897,53 @@ UPDATE `dlink_savepoints` SET `tenant_id` = 1;
UPDATE `dlink_task` SET `tenant_id` = 1 ;
UPDATE `dlink_task_statement` SET `tenant_id` = 1;
UPDATE `dlink_task_version` SET `tenant_id` = 1;
UPDATE `dlink_job_history` SET `tenant_id` = 1;
\ No newline at end of file
UPDATE `dlink_job_history` SET `tenant_id` = 1;
-- 0.6.8 2022-10-19
-- -----------------------
DROP TABLE IF EXISTS `dlink_udf`;
CREATE TABLE `dlink_udf` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL COMMENT 'udf名',
`class_name` varchar(50) DEFAULT NULL COMMENT '完整的类名',
`source_code` text COMMENT '源码',
`compiler_code` binary(255) DEFAULT NULL COMMENT '编译产物',
`version_id` int(11) DEFAULT NULL COMMENT '版本',
`version_description` varchar(50) DEFAULT NULL COMMENT '版本描述',
`is_default` tinyint(1) DEFAULT NULL COMMENT '是否默认',
`document_id` int(11) DEFAULT NULL COMMENT '对应文档id',
`from_version_id` int(11) DEFAULT NULL COMMENT '基于udf版本id',
`code_md5` varchar(50) DEFAULT NULL COMMENT '源码',
`dialect` varchar(50) DEFAULT NULL COMMENT '方言',
`type` varchar(50) DEFAULT NULL COMMENT '类型',
`step` int(255) DEFAULT NULL COMMENT '作业生命周期',
`enable` tinyint(1) DEFAULT NULL COMMENT '是否启用',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Table structure for dlink_udf_template
-- ----------------------------
DROP TABLE IF EXISTS `dlink_udf_template`;
CREATE TABLE `dlink_udf_template` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL COMMENT '模板名称',
`code_type` varchar(10) DEFAULT NULL COMMENT '代码类型',
`function_type` varchar(10) DEFAULT NULL COMMENT '函数类型',
`template_code` text COMMENT '模板代码',
`enabled` tinyint(1) DEFAULT NULL,
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Records of dlink_udf_template
-- ----------------------------
BEGIN;
INSERT INTO `dlink_udf_template` (`id`, `name`, `code_type`, `function_type`, `template_code`, `enabled`, `create_time`, `update_time`) VALUES (1, 'java_udf', 'java', 'UDF', 'package ${package};\n\nimport org.apache.flink.table.functions.ScalarFunction;\n\npublic class ${className} extends ScalarFunction {\n public String eval(String s) {\n return null;\n }\n}', NULL, '2022-10-19 09:17:37', '2022-10-19 09:17:37');
INSERT INTO `dlink_udf_template` (`id`, `name`, `code_type`, `function_type`, `template_code`, `enabled`, `create_time`, `update_time`) VALUES (2, 'java_udtf', 'java', 'UDTF', 'package ${package};\n\nimport org.apache.flink.table.functions.ScalarFunction;\n\n@FunctionHint(output = @DataTypeHint(\"ROW<word STRING, length INT>\"))\npublic static class ${className} extends TableFunction<Row> {\n\n public void eval(String str) {\n for (String s : str.split(\" \")) {\n // use collect(...) to emit a row\n collect(Row.of(s, s.length()));\n }\n }\n}', NULL, '2022-10-19 09:22:58', '2022-10-19 10:01:57');
COMMIT;
\ No newline at end of file
/*
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
import MonacoEditor from "react-monaco-editor";
import {useState} from "react";
export type CodeEditFormProps = {
height?: string;
width?: string;
language?: string;
options?: any;
onChange: (val: string) => void;
code: string;
};
const CodeEdit = (props: CodeEditFormProps) => {
const {
height = '100%',
width = '100%',
language = 'sql',
options = {
selectOnLineNumbers: true,
renderSideBySide: false,
autoIndent: 'None',
},
onChange,
code,
} = props;
return (<>
<MonacoEditor
width={width}
height={height}
language={language}
value={code}
options={options}
onChange={onChange}
theme='vs-dark'
/>
</>)
};
export default CodeEdit;
......@@ -45,7 +45,6 @@ const CodeShow = (props: CodeShowFormProps) => {
code,
} = props;
return (<>
<MonacoEditor
width={width}
......@@ -53,7 +52,7 @@ const CodeShow = (props: CodeShowFormProps) => {
language={language}
value={code}
options={options}
theme={theme}
theme='vs-dark'
/>
</>)
};
......
......@@ -22,32 +22,32 @@ import {connect} from "umi";
import React, {useEffect, useState} from "react";
import CodeShow from "@/components/Common/CodeShow";
import {getConsoleInfo} from "@/pages/SettingCenter/ProcessList/service";
import {RedoOutlined} from "@ant-design/icons";
import {Button} from "antd";
const StudioMsg = (props: any) => {
const {current} = props;
const {current, height, isActive} = props;
const [consoleInfo, setConsoleInfo] = useState<string>("");
useEffect(() => {
refreshConsoleInfo();
}, []);
let dataPolling = setInterval(refreshConsoleInfo, 3000);
return () => {
clearInterval(dataPolling);
};
}, [isActive]);
const refreshConsoleInfo = () => {
const res = getConsoleInfo();
res.then((result) => {
result.datas && setConsoleInfo(result.datas);
});
if (isActive) {
const res = getConsoleInfo();
res.then((result) => {
result.datas && setConsoleInfo(result.datas);
});
}
}
return (
<><Button
icon={<RedoOutlined/>}
onClick={refreshConsoleInfo}
></Button>
<CodeShow code={consoleInfo} language='java'
height='500px' theme="vs-dark"/>
<>
<CodeShow code={consoleInfo} language='java' height={height} theme="vs"/>
</>
);
};
......
......@@ -21,7 +21,7 @@
import {Tabs, Empty} from "antd";
import {
CodeOutlined, TableOutlined, RadarChartOutlined, CalendarOutlined, FileSearchOutlined, DesktopOutlined
, FunctionOutlined, ApartmentOutlined,BarChartOutlined
, FunctionOutlined, ApartmentOutlined, BarChartOutlined
} from "@ant-design/icons";
import {StateType} from "@/pages/DataStudio/model";
import {connect} from "umi";
......@@ -34,7 +34,8 @@ import StudioCA from "./StudioCA";
import StudioProcess from "./StudioProcess";
import {Scrollbars} from 'react-custom-scrollbars';
import Chart from "@/components/Chart";
import { useIntl } from 'umi';
import {useIntl} from 'umi';
import {useEffect, useState} from "react";
const {TabPane} = Tabs;
......@@ -42,12 +43,18 @@ const StudioConsole = (props: any) => {
const intl = useIntl();
const {height,current} = props;
const {height, current} = props;
let consoleHeight = (height - 37.6);
const [activeKey, setActiveKey] = useState<string>("StudioMsg");
const onTabsChange = (key: string) => {
setActiveKey(key);
}
return (
<Tabs defaultActiveKey="StudioMsg" size="small" tabPosition="top" style={{
border: "1px solid #f0f0f0", height: height, margin: "0 32px"
}}>
}} onChange={onTabsChange}>
<TabPane
tab={
<span>
......@@ -58,7 +65,7 @@ const StudioConsole = (props: any) => {
key="StudioMsg"
>
<Scrollbars style={{height: consoleHeight}}>
{current?<StudioMsg/>:<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>}
<StudioMsg height={consoleHeight} isActive={activeKey === "StudioMsg"}/>
</Scrollbars>
</TabPane>
<TabPane
......@@ -71,20 +78,20 @@ const StudioConsole = (props: any) => {
key="StudioTable"
>
<Scrollbars style={{height: consoleHeight}}>
{current?<StudioTable/>:<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>}
{current ? <StudioTable/> : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>}
</Scrollbars>
</TabPane>
<TabPane
tab={
<span>
<BarChartOutlined />
<BarChartOutlined/>
BI
</span>
}
key="StudioChart"
>
<Scrollbars style={{height: consoleHeight}}>
{current? <Chart height={consoleHeight} />:<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>}
{current ? <Chart height={consoleHeight}/> : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>}
</Scrollbars>
</TabPane>
<TabPane
......@@ -97,7 +104,7 @@ const StudioConsole = (props: any) => {
key="StudioConsanguinity"
>
<Scrollbars style={{height: consoleHeight}}>
{current?<StudioCA/>:<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>}
{current ? <StudioCA/> : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>}
</Scrollbars>
</TabPane>
<TabPane
......
......@@ -18,7 +18,7 @@
*/
export type UDFTemplateItem = {
id: number,
id: number | null,
name: string,
codeType: string,
functionType: string,
......
......@@ -22,11 +22,11 @@ import ProTable, {ActionType, ProColumns} from "@ant-design/pro-table";
import {PageContainer} from '@ant-design/pro-layout';
import {UDFTemplateItem} from "@/pages/SettingCenter/UDFTemplate/data";
import {addTemplate, deleteTemplate, getTemplate} from "@/pages/SettingCenter/UDFTemplate/service";
import {Button, Col, Drawer, Form, Input, Row, Select, Space} from "antd";
import {Button, Col, Drawer, Form, Input, Modal, Row, Select, Space} from "antd";
import {DeleteOutlined, FormOutlined, PlusOutlined} from "@ant-design/icons";
import 'antd/dist/antd.css';
import './index.css';
import {ProCoreActionType} from "@ant-design/pro-utils/lib/typing";
import CodeEdit from "@/components/Common/CodeEdit";
const {Option} = Select;
......@@ -35,7 +35,7 @@ const UDFTemplate: React.FC<{}> = (props) => {
const [open, setOpen] = useState(false);
const initData: UDFTemplateItem = {
id: 0,
id: null,
name: "",
codeType: "java",
functionType: "UDF",
......@@ -45,39 +45,36 @@ const UDFTemplate: React.FC<{}> = (props) => {
const [tModel, setTModel] = useState<UDFTemplateItem>(initData);
const actionRef = useRef<ActionType>();
const addModel = () => {
setTModel({
id: 0,
name: "",
codeType: "java",
functionType: "UDF",
templateCode: ""
})
setTModel(initData);
}
const changeModel = (record: UDFTemplateItem) => {
setTModel(record)
setOpen(true)
setTModel(record);
setOpen(true);
}
const showDrawer = () => {
addModel()
addModel();
setOpen(true);
};
const onClose = () => {
actionRef.current.reload()
actionRef.current?.reload();
setOpen(false);
};
const Box = () => {
const [form] = Form.useForm();
const [code, setCode] = useState<string>(tModel.templateCode);
const add = async () => {
try {
const values = await form.validateFields();
values["id"] = tModel.id
await addTemplate(values)
onClose()
values["id"] = tModel.id;
values["templateCode"] = code;
await addTemplate(values);
onClose();
} catch (errorInfo) {
console.log('Failed:', errorInfo);
}
......@@ -85,11 +82,10 @@ const UDFTemplate: React.FC<{}> = (props) => {
return <Drawer
visible={open}
title="添加或修改UDF模板"
title={(tModel.id ? '修改' : '添加') + "UDF模板"}
width={720}
onClose={onClose}
open={open}
bodyStyle={{paddingBottom: 80}}
extra={
<Space>
<Button onClick={onClose}>取消</Button>
......@@ -139,7 +135,7 @@ const UDFTemplate: React.FC<{}> = (props) => {
</Form.Item>
</Col>
</Row>
<Row gutter={16}>
<Row>
<Col span={24}>
<Form.Item
name="templateCode"
......@@ -151,7 +147,12 @@ const UDFTemplate: React.FC<{}> = (props) => {
},
]}
>
<Input.TextArea rows={20} placeholder="请编辑模板代码"/>
{/*<Input.TextArea rows={20} placeholder="请编辑模板代码"/>*/}
<CodeEdit code={code} language='java'
height='400px' onChange={async (val) => {
// setTModel({...tModel,templateCode:val});
setCode(val);
}}/>
</Form.Item>
</Col>
</Row>
......@@ -159,6 +160,18 @@ const UDFTemplate: React.FC<{}> = (props) => {
</Drawer>
}
const deleteUDFTemplate = (id: number) => {
Modal.confirm({
title: '删除集群',
content: '确定删除该集群吗?',
okText: '确认',
cancelText: '取消',
onOk: async () => {
await deleteTemplate(id)
actionRef.current?.reloadAndRest?.();
}
});
}
const columns: ProColumns<UDFTemplateItem>[] = [
{
......@@ -210,17 +223,20 @@ const UDFTemplate: React.FC<{}> = (props) => {
'UDAF': {text: 'UDAF'},
},
onFilter: true
}, {
}, {
title: '操作',
key: 'action',
render: (text, record,_,action) => (
render: (text, record, _, action) => (
<Space size="middle">
<Button type="primary" icon={<FormOutlined/>} onClick={() => changeModel(record)}></Button>
<Button type="primary" icon={<DeleteOutlined/>} onClick={() => {deleteTemplate(record.id);action?.reload()}}></Button>
<Button type="primary" icon={<DeleteOutlined/>} onClick={() => {
deleteUDFTemplate(record.id)
}}></Button>
</Space>
),
}
];
return (
<PageContainer title={false}>
{<Box/>}
......
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