From 9b8108f689c7f16c07795fdf483ac4b778b39ef3 Mon Sep 17 00:00:00 2001 From: ZackYoung Date: Sun, 24 Nov 2024 22:13:55 +0800 Subject: [PATCH] [Feature][Web]Flink jar add form (#3949) Co-authored-by: zackyoungh --- .../org/dinky/controller/TaskController.java | 67 +++++++ .../dinky/data/vo/FlinkJarSqlConvertVO.java | 32 ++++ .../main/resources/templates/executeJar.sql | 6 + .../org/dinky/data/model/JarSubmitParam.java | 96 ++++++++++ .../trans/ExecuteJarParseStrategyUtil.java | 31 +++ .../dinky/trans/dml/ExecuteJarOperation.java | 25 +-- .../trans/parse/ExecuteJarParseStrategy.java | 33 ---- .../job/builder/JobJarStreamGraphBuilder.java | 3 +- .../org/dinky/job/runner/JobJarRunner.java | 3 +- dinky-web/package-lock.json | 46 +++++ .../CenterTabContent/SqlTask/index.tsx | 179 ++++++++++++++---- .../Toolbar/GlobalVariable/index.tsx | 1 + .../Toolbar/Service/Result/index.tsx | 4 +- .../Toolbar/Service/TableData/index.tsx | 16 +- .../DataStudio/Toolbar/Service/index.tsx | 2 +- .../components/RunToolBarButton/index.tsx | 9 +- dinky-web/src/pages/DataStudio/service.tsx | 10 +- dinky-web/src/pages/DataStudio/type.ts | 7 + .../RightTagsRouter/index.tsx | 12 +- .../components/DataSourceModal/index.tsx | 2 +- dinky-web/src/services/endpoints.tsx | 2 + 21 files changed, 470 insertions(+), 116 deletions(-) create mode 100644 dinky-admin/src/main/java/org/dinky/data/vo/FlinkJarSqlConvertVO.java create mode 100644 dinky-admin/src/main/resources/templates/executeJar.sql create mode 100644 dinky-client/dinky-client-base/src/main/java/org/dinky/data/model/JarSubmitParam.java create mode 100644 dinky-client/dinky-client-base/src/main/java/org/dinky/trans/ExecuteJarParseStrategyUtil.java diff --git a/dinky-admin/src/main/java/org/dinky/controller/TaskController.java b/dinky-admin/src/main/java/org/dinky/controller/TaskController.java index a4ecc6c031..bed837eca8 100644 --- a/dinky-admin/src/main/java/org/dinky/controller/TaskController.java +++ b/dinky-admin/src/main/java/org/dinky/controller/TaskController.java @@ -34,17 +34,23 @@ import org.dinky.data.enums.Status; import org.dinky.data.exception.NotSupportExplainExcepition; import org.dinky.data.exception.SqlExplainExcepition; +import org.dinky.data.model.JarSubmitParam; import org.dinky.data.model.Task; import org.dinky.data.result.ProTableResult; import org.dinky.data.result.Result; import org.dinky.data.result.SqlExplainResult; +import org.dinky.data.vo.FlinkJarSqlConvertVO; import org.dinky.gateway.enums.SavePointType; import org.dinky.gateway.result.SavePointResult; import org.dinky.job.JobResult; import org.dinky.mybatis.annotation.Save; import org.dinky.service.TaskService; +import org.dinky.trans.ExecuteJarParseStrategyUtil; +import org.dinky.utils.SqlUtil; +import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -61,7 +67,14 @@ import cn.dev33.satoken.annotation.SaCheckLogin; import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.codec.Base64; +import cn.hutool.core.lang.Dict; +import cn.hutool.core.lang.Opt; import cn.hutool.core.lang.tree.Tree; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.extra.template.TemplateConfig; +import cn.hutool.extra.template.TemplateEngine; +import cn.hutool.extra.template.engine.freemarker.FreemarkerEngine; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; @@ -77,6 +90,8 @@ public class TaskController { private final TaskService taskService; + private static final TemplateEngine ENGINE = + new FreemarkerEngine(new TemplateConfig("templates", TemplateConfig.ResourceMode.CLASSPATH)); @GetMapping("/submitTask") @ApiOperation("Submit Task") @@ -283,4 +298,56 @@ public Result> getMyTask() { int id = StpUtil.getLoginIdAsInt(); return Result.succeed(taskService.getUserTasks(id)); } + + @PostMapping("/flinkJarSqlConvertForm") + @ApiOperation("FlinkJar SqlConvertForm") + public Result flinkJarSqlConvertForm(@RequestBody TaskDTO taskDTO) { + + String sqlStatement = taskDTO.getStatement(); + String[] statements = SqlUtil.getStatements(sqlStatement); + FlinkJarSqlConvertVO flinkJarSqlConvertVO = new FlinkJarSqlConvertVO(); + flinkJarSqlConvertVO.setJarSubmitParam(JarSubmitParam.empty()); + if (ArrayUtil.isEmpty(statements)) { + flinkJarSqlConvertVO.setInitSqlStatement(sqlStatement); + return Result.succeed(flinkJarSqlConvertVO); + } + Integer lastExecuteJarSqlStatementIndex = null; + for (int i = 0; i < statements.length; i++) { + if (ExecuteJarParseStrategyUtil.match(statements[i])) { + lastExecuteJarSqlStatementIndex = i; + } + } + if (lastExecuteJarSqlStatementIndex == null) { + return Result.succeed(flinkJarSqlConvertVO); + } + String lastSqlStatement = statements[lastExecuteJarSqlStatementIndex]; + JarSubmitParam info = JarSubmitParam.getInfo(lastSqlStatement); + flinkJarSqlConvertVO.setJarSubmitParam(info); + String sql = Arrays.stream(ArrayUtil.remove(statements, lastExecuteJarSqlStatementIndex)) + .map(x -> x + ";") + .collect(Collectors.joining("\n")); + flinkJarSqlConvertVO.setInitSqlStatement(sql); + return Result.succeed(flinkJarSqlConvertVO); + } + + @PostMapping("/flinkJarFormConvertSql") + @ApiOperation("FlinkJar FormConvertSql") + public Result flinkJarFormConvertSql(@RequestBody FlinkJarSqlConvertVO dto) { + JarSubmitParam jarSubmitParam = dto.getJarSubmitParam(); + Dict objectMap = Dict.create() + .set("uri", Opt.ofNullable(jarSubmitParam.getUri()).orElse("")) + .set( + "args", + "base64@" + + Base64.encode( + Opt.ofNullable(jarSubmitParam.getArgs()).orElse(""))) + .set("mainClass", Opt.ofNullable(jarSubmitParam.getMainClass()).orElse("")) + .set( + "allowNonRestoredState", + Opt.ofNullable(jarSubmitParam.getAllowNonRestoredState()) + .orElse(false) + .toString()); + String executeJarSql = ENGINE.getTemplate("executeJar.sql").render(objectMap); + return Result.succeed(dto.getInitSqlStatement() + "\n" + executeJarSql, ""); + } } diff --git a/dinky-admin/src/main/java/org/dinky/data/vo/FlinkJarSqlConvertVO.java b/dinky-admin/src/main/java/org/dinky/data/vo/FlinkJarSqlConvertVO.java new file mode 100644 index 0000000000..4c73681e50 --- /dev/null +++ b/dinky-admin/src/main/java/org/dinky/data/vo/FlinkJarSqlConvertVO.java @@ -0,0 +1,32 @@ +/* + * + * 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. + * + */ + +package org.dinky.data.vo; + +import org.dinky.data.model.JarSubmitParam; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class FlinkJarSqlConvertVO { + private String initSqlStatement; + private JarSubmitParam jarSubmitParam; +} diff --git a/dinky-admin/src/main/resources/templates/executeJar.sql b/dinky-admin/src/main/resources/templates/executeJar.sql new file mode 100644 index 0000000000..b16af5a013 --- /dev/null +++ b/dinky-admin/src/main/resources/templates/executeJar.sql @@ -0,0 +1,6 @@ +EXECUTE JAR WITH ( +'uri'='${uri}', +'main-class'='${mainClass}', +'args'='${args}', +'allowNonRestoredState'='${allowNonRestoredState}' +); diff --git a/dinky-client/dinky-client-base/src/main/java/org/dinky/data/model/JarSubmitParam.java b/dinky-client/dinky-client-base/src/main/java/org/dinky/data/model/JarSubmitParam.java new file mode 100644 index 0000000000..dc4bb9b222 --- /dev/null +++ b/dinky-client/dinky-client-base/src/main/java/org/dinky/data/model/JarSubmitParam.java @@ -0,0 +1,96 @@ +/* + * + * 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. + * + */ + +package org.dinky.data.model; + +import org.dinky.parser.SqlSegment; + +import org.apache.flink.runtime.jobgraph.SavepointConfigOptions; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.bean.copier.CopyOptions; +import cn.hutool.core.codec.Base64; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class JarSubmitParam { + protected JarSubmitParam() {} + + private String uri; + private String mainClass; + private String args; + private String parallelism; + private String savepointPath; + private Boolean allowNonRestoredState = SavepointConfigOptions.SAVEPOINT_IGNORE_UNCLAIMED_STATE.defaultValue(); + + public static JarSubmitParam build(String statement) { + JarSubmitParam submitParam = getInfo(statement); + Assert.notBlank(submitParam.getUri()); + return submitParam; + } + + public static JarSubmitParam getInfo(String statement) { + statement = statement.replace("\r\n", " ").replace("\n", " ") + " ENDOFSQL"; + SqlSegment sqlSegment = new SqlSegment("with", "(with\\s+\\()(.+)(\\))", "',"); + sqlSegment.parse(statement); + List bodyPieces = sqlSegment.getBodyPieces(); + Map keyValue = getKeyValue(bodyPieces); + return BeanUtil.toBean( + keyValue, + JarSubmitParam.class, + CopyOptions.create().setFieldNameEditor(s -> StrUtil.toCamelCase(s, '-'))); + } + + private static Map getKeyValue(List list) { + Map map = new HashMap<>(); + Pattern p = Pattern.compile("'(.*?)'\\s*=\\s*'(.*?)'"); + for (String s : list) { + Matcher m = p.matcher(s + "'"); + if (m.find()) { + map.put(m.group(1), m.group(2)); + } + } + return map; + } + + public static JarSubmitParam empty() { + JarSubmitParam jarSubmitParam = new JarSubmitParam(); + jarSubmitParam.setArgs(""); + jarSubmitParam.setMainClass(""); + jarSubmitParam.setUri(""); + return jarSubmitParam; + } + + public String getArgs() { + if (StrUtil.subPre(args, 7).equals("base64@")) { + return Base64.decodeStr(StrUtil.removePrefix(args, "base64@")); + } + return args; + } +} diff --git a/dinky-client/dinky-client-base/src/main/java/org/dinky/trans/ExecuteJarParseStrategyUtil.java b/dinky-client/dinky-client-base/src/main/java/org/dinky/trans/ExecuteJarParseStrategyUtil.java new file mode 100644 index 0000000000..469edcc775 --- /dev/null +++ b/dinky-client/dinky-client-base/src/main/java/org/dinky/trans/ExecuteJarParseStrategyUtil.java @@ -0,0 +1,31 @@ +/* + * + * 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. + * + */ + +package org.dinky.trans; + +import org.dinky.trans.parse.ExecuteJarParseStrategy; + +import cn.hutool.core.lang.Singleton; + +public class ExecuteJarParseStrategyUtil { + + public static boolean match(String statement) { + return Singleton.get(ExecuteJarParseStrategy.class).match(statement); + } +} diff --git a/dinky-client/dinky-client-base/src/main/java/org/dinky/trans/dml/ExecuteJarOperation.java b/dinky-client/dinky-client-base/src/main/java/org/dinky/trans/dml/ExecuteJarOperation.java index b164b87d4f..851d5728d6 100644 --- a/dinky-client/dinky-client-base/src/main/java/org/dinky/trans/dml/ExecuteJarOperation.java +++ b/dinky-client/dinky-client-base/src/main/java/org/dinky/trans/dml/ExecuteJarOperation.java @@ -23,10 +23,10 @@ import org.dinky.config.Dialect; import org.dinky.context.TaskContextHolder; +import org.dinky.data.model.JarSubmitParam; import org.dinky.executor.CustomTableEnvironment; import org.dinky.trans.AbstractOperation; import org.dinky.trans.ExtendOperation; -import org.dinky.trans.parse.ExecuteJarParseStrategy; import org.dinky.utils.FlinkStreamEnvironmentUtil; import org.dinky.utils.URLUtils; @@ -34,7 +34,6 @@ import org.apache.flink.client.program.PackagedProgram; import org.apache.flink.client.program.PackagedProgramUtils; import org.apache.flink.configuration.Configuration; -import org.apache.flink.runtime.jobgraph.SavepointConfigOptions; import org.apache.flink.runtime.jobgraph.SavepointRestoreSettings; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.streaming.api.graph.StreamGraph; @@ -47,11 +46,8 @@ import java.util.Optional; import cn.hutool.core.convert.Convert; -import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Opt; import cn.hutool.core.util.StrUtil; -import lombok.Getter; -import lombok.Setter; public class ExecuteJarOperation extends AbstractOperation implements ExtendOperation { @@ -148,23 +144,4 @@ public Pipeline explainJar(CustomTableEnvironment tEnv) { public Pipeline explain(CustomTableEnvironment tEnv, List classpaths) { return getStreamGraph(tEnv, classpaths); } - - @Setter - @Getter - public static class JarSubmitParam { - protected JarSubmitParam() {} - - private String uri; - private String mainClass; - private String args; - private String parallelism; - private String savepointPath; - private Boolean allowNonRestoredState = SavepointConfigOptions.SAVEPOINT_IGNORE_UNCLAIMED_STATE.defaultValue(); - - public static JarSubmitParam build(String statement) { - JarSubmitParam submitParam = ExecuteJarParseStrategy.getInfo(statement); - Assert.notBlank(submitParam.getUri()); - return submitParam; - } - } } diff --git a/dinky-client/dinky-client-base/src/main/java/org/dinky/trans/parse/ExecuteJarParseStrategy.java b/dinky-client/dinky-client-base/src/main/java/org/dinky/trans/parse/ExecuteJarParseStrategy.java index 02d2f1f675..256b200a13 100644 --- a/dinky-client/dinky-client-base/src/main/java/org/dinky/trans/parse/ExecuteJarParseStrategy.java +++ b/dinky-client/dinky-client-base/src/main/java/org/dinky/trans/parse/ExecuteJarParseStrategy.java @@ -19,22 +19,13 @@ package org.dinky.trans.parse; -import org.dinky.parser.SqlSegment; import org.dinky.trans.dml.ExecuteJarOperation; import org.apache.flink.table.operations.Operation; import org.apache.flink.table.planner.parse.AbstractRegexParseStrategy; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; import java.util.regex.Pattern; -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.bean.copier.CopyOptions; -import cn.hutool.core.util.StrUtil; - public class ExecuteJarParseStrategy extends AbstractRegexParseStrategy { private static final String PATTERN_STR = "^EXECUTE\\s+JAR\\s+WITH\\s*\\(.+\\)"; private static final Pattern PATTERN = Pattern.compile(PATTERN_STR, Pattern.CASE_INSENSITIVE | Pattern.DOTALL); @@ -44,30 +35,6 @@ public ExecuteJarParseStrategy() { super(PATTERN); } - public static ExecuteJarOperation.JarSubmitParam getInfo(String statement) { - statement = statement.replace("\r\n", " ").replace("\n", " ") + " ENDOFSQL"; - SqlSegment sqlSegment = new SqlSegment("with", "(with\\s+\\()(.+)(\\))", "',"); - sqlSegment.parse(statement); - List bodyPieces = sqlSegment.getBodyPieces(); - Map keyValue = getKeyValue(bodyPieces); - return BeanUtil.toBean( - keyValue, - ExecuteJarOperation.JarSubmitParam.class, - CopyOptions.create().setFieldNameEditor(s -> StrUtil.toCamelCase(s, '-'))); - } - - private static Map getKeyValue(List list) { - Map map = new HashMap<>(); - Pattern p = Pattern.compile("'(.*?)'\\s*=\\s*'(.*?)'"); - for (String s : list) { - Matcher m = p.matcher(s + "'"); - if (m.find()) { - map.put(m.group(1), m.group(2)); - } - } - return map; - } - @Override public Operation convert(String statement) { return new ExecuteJarOperation(statement); diff --git a/dinky-core/src/main/java/org/dinky/job/builder/JobJarStreamGraphBuilder.java b/dinky-core/src/main/java/org/dinky/job/builder/JobJarStreamGraphBuilder.java index eadfe071c5..9268f840c4 100644 --- a/dinky-core/src/main/java/org/dinky/job/builder/JobJarStreamGraphBuilder.java +++ b/dinky-core/src/main/java/org/dinky/job/builder/JobJarStreamGraphBuilder.java @@ -23,6 +23,7 @@ import org.dinky.classloader.DinkyClassLoader; import org.dinky.data.exception.DinkyException; import org.dinky.data.job.SqlType; +import org.dinky.data.model.JarSubmitParam; import org.dinky.data.result.InsertResult; import org.dinky.data.result.SqlExplainResult; import org.dinky.gateway.Gateway; @@ -200,7 +201,7 @@ public List getUris(String statement) { for (String sql : statements) { String sqlStatement = executor.pretreatStatement(sql); if (ExecuteJarParseStrategy.INSTANCE.match(sqlStatement)) { - uriList.add(ExecuteJarParseStrategy.getInfo(statement).getUri()); + uriList.add(JarSubmitParam.getInfo(statement).getUri()); break; } } diff --git a/dinky-core/src/main/java/org/dinky/job/runner/JobJarRunner.java b/dinky-core/src/main/java/org/dinky/job/runner/JobJarRunner.java index 1202b49181..130d83fde3 100644 --- a/dinky-core/src/main/java/org/dinky/job/runner/JobJarRunner.java +++ b/dinky-core/src/main/java/org/dinky/job/runner/JobJarRunner.java @@ -24,6 +24,7 @@ import org.dinky.data.exception.DinkyException; import org.dinky.data.job.JobStatement; import org.dinky.data.job.SqlType; +import org.dinky.data.model.JarSubmitParam; import org.dinky.data.result.InsertResult; import org.dinky.data.result.SqlExplainResult; import org.dinky.gateway.Gateway; @@ -222,7 +223,7 @@ public List getUris(String statement) { for (String sql : statements) { String sqlStatement = jobManager.getExecutor().pretreatStatement(sql); if (ExecuteJarParseStrategy.INSTANCE.match(sqlStatement)) { - uriList.add(ExecuteJarParseStrategy.getInfo(statement).getUri()); + uriList.add(JarSubmitParam.getInfo(statement).getUri()); break; } } diff --git a/dinky-web/package-lock.json b/dinky-web/package-lock.json index f85cd6470d..344429dbf3 100644 --- a/dinky-web/package-lock.json +++ b/dinky-web/package-lock.json @@ -59,6 +59,7 @@ "react-sortablejs": "^6.1.4", "react-spring": "^9.7.3", "react-use-cookie": "^1.6.1", + "react-virtualized": "^9.22.5", "redux-persist": "^6.0.0", "remark-gfm": "^4.0.0", "screenfull": "^6.0.2", @@ -81,6 +82,7 @@ "@types/react-grid-layout": "^1.3.5", "@types/react-helmet": "^6.1.9", "@types/react-lottie": "^1.2.10", + "@types/react-virtualized": "^9.22.0", "@types/sortablejs": "^1.15.8", "@umijs/lint": "^4.3.24", "@umijs/max": "^4.3.24", @@ -8111,6 +8113,16 @@ "redux": "^4.0.0" } }, + "node_modules/@types/react-virtualized": { + "version": "9.22.0", + "resolved": "https://registry.npmjs.org/@types/react-virtualized/-/react-virtualized-9.22.0.tgz", + "integrity": "sha512-JL/YCCFZ123za//cj10Apk54F0UGFMrjOE0QHTuXt1KBMFrzLOGv9/x6Uc/pZ0Gaf4o6w61Fostvlw0DwuPXig==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "@types/react": "*" + } + }, "node_modules/@types/resolve": { "version": "1.20.6", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz", @@ -15803,6 +15815,15 @@ "utila": "~0.4" } }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "node_modules/dom-serializer": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", @@ -28162,6 +28183,31 @@ "react": ">=16.8" } }, + "node_modules/react-virtualized": { + "version": "9.22.5", + "resolved": "https://registry.npmjs.org/react-virtualized/-/react-virtualized-9.22.5.tgz", + "integrity": "sha512-YqQMRzlVANBv1L/7r63OHa2b0ZsAaDp1UhVNEdUaXI8A5u6hTpA5NYtUueLH2rFuY/27mTGIBl7ZhqFKzw18YQ==", + "dependencies": { + "@babel/runtime": "^7.7.2", + "clsx": "^1.0.4", + "dom-helpers": "^5.1.3", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-lifecycles-compat": "^3.0.4" + }, + "peerDependencies": { + "react": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0", + "react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-virtualized/node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "engines": { + "node": ">=6" + } + }, "node_modules/reactcss": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz", diff --git a/dinky-web/src/pages/DataStudio/CenterTabContent/SqlTask/index.tsx b/dinky-web/src/pages/DataStudio/CenterTabContent/SqlTask/index.tsx index fd5c1d0f16..fa65f56f21 100644 --- a/dinky-web/src/pages/DataStudio/CenterTabContent/SqlTask/index.tsx +++ b/dinky-web/src/pages/DataStudio/CenterTabContent/SqlTask/index.tsx @@ -17,13 +17,13 @@ * */ -import {CenterTab, DataStudioState} from '@/pages/DataStudio/model'; -import {Button, Col, Divider, Flex, Row, Skeleton, TabsProps} from 'antd'; +import { CenterTab, DataStudioState } from '@/pages/DataStudio/model'; +import { Button, Col, Divider, Flex, Row, Skeleton, TabsProps } from 'antd'; import '../index.less'; -import React, {memo, useCallback, useEffect, useRef, useState} from 'react'; -import {registerEditorKeyBindingAndAction} from '@/utils/function'; -import {Monaco} from '@monaco-editor/react'; -import {Panel, PanelGroup} from 'react-resizable-panels'; +import React, { memo, useCallback, useEffect, useRef, useState } from 'react'; +import { registerEditorKeyBindingAndAction } from '@/utils/function'; +import { Monaco } from '@monaco-editor/react'; +import { Panel, PanelGroup } from 'react-resizable-panels'; import { ApartmentOutlined, BugOutlined, @@ -42,38 +42,51 @@ import { XFilled } from '@ant-design/icons'; import RunToolBarButton from '@/pages/DataStudio/components/RunToolBarButton'; -import {connect, useModel} from '@umijs/max'; +import { connect, useModel } from '@umijs/max'; import CusPanelResizeHandle from '@/pages/DataStudio/components/CusPanelResizeHandle'; -import {ProForm, ProFormInstance} from '@ant-design/pro-components'; -import {useAsyncEffect, useFullscreen} from 'ahooks'; -import {SelectFlinkEnv} from '@/pages/DataStudio/CenterTabContent/RunToolbar/SelectFlinkEnv'; -import {SelectFlinkRunMode} from '@/pages/DataStudio/CenterTabContent/RunToolbar/SelectFlinkRunMode'; -import {mapDispatchToProps} from '@/pages/DataStudio/DvaFunction'; -import {TaskInfo} from '@/pages/DataStudio/CenterTabContent/SqlTask/TaskInfo'; -import {HistoryVersion} from '@/pages/DataStudio/CenterTabContent/SqlTask/HistoryVersion'; -import {FlinkTaskRunType, StudioLineageParams, TaskState} from '@/pages/DataStudio/type'; -import {JOB_LIFE_CYCLE} from '@/pages/DevOps/constants'; -import {debounce} from 'lodash'; +import { + ProForm, + ProFormInstance, + ProFormSwitch, + ProFormText, + ProFormTextArea +} from '@ant-design/pro-components'; +import { useAsyncEffect, useFullscreen } from 'ahooks'; +import { SelectFlinkEnv } from '@/pages/DataStudio/CenterTabContent/RunToolbar/SelectFlinkEnv'; +import { SelectFlinkRunMode } from '@/pages/DataStudio/CenterTabContent/RunToolbar/SelectFlinkRunMode'; +import { mapDispatchToProps } from '@/pages/DataStudio/DvaFunction'; +import { TaskInfo } from '@/pages/DataStudio/CenterTabContent/SqlTask/TaskInfo'; +import { HistoryVersion } from '@/pages/DataStudio/CenterTabContent/SqlTask/HistoryVersion'; +import { + FlinkTaskRunType, + SqlConvertForm, + StudioLineageParams, + TaskState +} from '@/pages/DataStudio/type'; +import { JOB_LIFE_CYCLE } from '@/pages/DevOps/constants'; +import { debounce } from 'lodash'; import { cancelTask, changeTaskLife, debugTask, executeSql, explainSql, + flinkJarFormConvertSql, + flinkJarSqlConvertForm, getJobPlan, getTaskDetails } from '@/pages/DataStudio/service'; -import {l} from '@/utils/intl'; -import {editor} from 'monaco-editor'; -import {DataStudioActionType} from '@/pages/DataStudio/data.d'; -import {getDataByParams, handlePutDataJson, queryDataByParams} from '@/services/BusinessCrud'; -import {API_CONSTANTS} from '@/services/endpoints'; -import {Jobs, LineageDetailInfo} from '@/types/DevOps/data'; -import {lockTask, matchLanguage} from '@/pages/DataStudio/function'; -import {PushpinIcon} from '@/components/Icons/CustomIcons'; -import {assert, isSql} from '@/pages/DataStudio/utils'; -import {DIALECT} from '@/services/constants'; -import {SysConfigStateType} from '@/pages/SettingCenter/GlobalSetting/model'; +import { l } from '@/utils/intl'; +import { editor } from 'monaco-editor'; +import { DataStudioActionType } from '@/pages/DataStudio/data.d'; +import { getDataByParams, handlePutDataJson, queryDataByParams } from '@/services/BusinessCrud'; +import { API_CONSTANTS } from '@/services/endpoints'; +import { Jobs, LineageDetailInfo } from '@/types/DevOps/data'; +import { lockTask, matchLanguage } from '@/pages/DataStudio/function'; +import { PushpinIcon } from '@/components/Icons/CustomIcons'; +import { assert, isSql } from '@/pages/DataStudio/utils'; +import { DIALECT } from '@/services/constants'; +import { SysConfigStateType } from '@/pages/SettingCenter/GlobalSetting/model'; import CodeEdit from '@/components/CustomEditor/CodeEdit'; import DiffModal from '@/pages/DataStudio/CenterTabContent/SqlTask/DiffModal'; import TaskConfig from '@/pages/DataStudio/CenterTabContent/SqlTask/TaskConfig'; @@ -87,6 +100,14 @@ export type FlinkSqlProps = { }; const toolbarSize = 40; const dividerHeight = 24; +export type JarSubmitParam = { + uri: string; + mainClass: string; + args: string; + parallelism: number; + savepointPath: string; + allowNonRestoredState: boolean; +}; export const SqlTask = memo((props: FlinkSqlProps & any) => { const { @@ -109,6 +130,10 @@ export const SqlTask = memo((props: FlinkSqlProps & any) => { const [selectRightToolbar, setSelectRightToolbar] = useState(undefined); const [loading, setLoading] = useState(true); + // sql转换form + const [sqlForm, setSqlForm] = useState({ + enable: false + }); const [originStatementValue, setOriginStatementValue] = useState(''); const [currentState, setCurrentState] = useState({ alertGroupId: -1, @@ -162,15 +187,36 @@ export const SqlTask = memo((props: FlinkSqlProps & any) => { setCurrentState(newParams); updateCenterTab({ ...props.tabData, params: newParams }); - setOriginStatementValue(statement); - if (params?.statement && params?.statement !== taskDetail.statement) { - setDiff([{ key: 'statement', server: taskDetail.statement, cache: params.statement }]); - setOpenDiffModal(true); - updateCenterTab({ - ...props.tabData, - isUpdate: true, - params: { ...newParams } - }); + if (taskDetail.dialect.toLowerCase() === DIALECT.FLINKJAR) { + const sqlConvertForm = await flinkJarSqlConvertForm(taskDetail.statement); + setSqlForm({ enable: true, ...sqlConvertForm }); + setCurrentState((prevState) => ({ + ...prevState, + statement: sqlConvertForm?.initSqlStatement ?? '' + })); + setOriginStatementValue(sqlConvertForm?.initSqlStatement ?? ''); + if (params?.statement && params?.statement !== sqlConvertForm?.initSqlStatement) { + setDiff([ + { key: 'statement', server: sqlConvertForm?.initSqlStatement, cache: params.statement } + ]); + setOpenDiffModal(true); + updateCenterTab({ + ...props.tabData, + isUpdate: true, + params: { ...newParams } + }); + } + } else { + setOriginStatementValue(statement); + if (params?.statement && params?.statement !== taskDetail.statement) { + setDiff([{ key: 'statement', server: taskDetail.statement, cache: params.statement }]); + setOpenDiffModal(true); + updateCenterTab({ + ...props.tabData, + isUpdate: true, + params: { ...newParams } + }); + } } } setLoading(false); @@ -330,10 +376,13 @@ export const SqlTask = memo((props: FlinkSqlProps & any) => { }); const handleSave = useCallback(async () => { - // await putTask(currentState) - await handlePutDataJson(API_CONSTANTS.TASK, currentState); + const statement = + currentState.dialect.toLowerCase() === DIALECT.FLINKJAR + ? (await flinkJarFormConvertSql(sqlForm))!! + : currentState.statement; + await handlePutDataJson(API_CONSTANTS.TASK, { ...currentState, statement }); updateCenterTab({ ...props.tabData, isUpdate: false }); - }, [currentState, updateCenterTab, props.tabData]); + }, [currentState, updateCenterTab, props.tabData, sqlForm]); const handleCheck = useCallback(async () => { const res = await explainSql( @@ -409,7 +458,7 @@ export const SqlTask = memo((props: FlinkSqlProps & any) => { status: result.data.status === 'SUCCESS' ? 'RUNNING' : result.data.status }; }); - if (result.data.status === 'SUCCESS'){ + if (result.data.status === 'SUCCESS') { setIsRunning(true); } if (isSql(currentState.dialect) && result?.data?.result?.success) { @@ -463,7 +512,7 @@ export const SqlTask = memo((props: FlinkSqlProps & any) => { : res.data.status }; }); - if (res.data.status === 'SUCCESS' && res.data.pipeline){ + if (res.data.status === 'SUCCESS' && res.data.pipeline) { setIsRunning(true); } } @@ -812,6 +861,52 @@ export const SqlTask = memo((props: FlinkSqlProps & any) => { }} /> + {sqlForm.enable && ( + <> + + + + { + setSqlForm((prevState) => ({ + ...prevState, + jarSubmitParam: values + })); + }} + > + + + + + + + + + )} {selectRightToolbar && ( <> diff --git a/dinky-web/src/pages/DataStudio/Toolbar/GlobalVariable/index.tsx b/dinky-web/src/pages/DataStudio/Toolbar/GlobalVariable/index.tsx index 6881b3c5eb..b9d44fb0da 100644 --- a/dinky-web/src/pages/DataStudio/Toolbar/GlobalVariable/index.tsx +++ b/dinky-web/src/pages/DataStudio/Toolbar/GlobalVariable/index.tsx @@ -57,6 +57,7 @@ const GlobalVariable = () => { return ( + className={'datastudio-theme'} showHeader={false} tableStyle={{ margin: 0, paddingInline: 0 }} search={false} diff --git a/dinky-web/src/pages/DataStudio/Toolbar/Service/Result/index.tsx b/dinky-web/src/pages/DataStudio/Toolbar/Service/Result/index.tsx index b2a9038b2a..d39475e6aa 100644 --- a/dinky-web/src/pages/DataStudio/Toolbar/Service/Result/index.tsx +++ b/dinky-web/src/pages/DataStudio/Toolbar/Service/Result/index.tsx @@ -323,12 +323,12 @@ export default (props: { }); }; return ( -
+
{dataList.length == 0 ?? } { } }, []); - const rowRenderer = ({ key, index, style }: { key: string; index: number; style: React.CSSProperties }) => ( + const rowRenderer = ({ + key, + index, + style + }: { + key: string; + index: number; + style: React.CSSProperties; + }) => (
{data[index]}
diff --git a/dinky-web/src/pages/DataStudio/Toolbar/Service/index.tsx b/dinky-web/src/pages/DataStudio/Toolbar/Service/index.tsx index da68d4e9fa..89d7d6f45e 100644 --- a/dinky-web/src/pages/DataStudio/Toolbar/Service/index.tsx +++ b/dinky-web/src/pages/DataStudio/Toolbar/Service/index.tsx @@ -289,7 +289,7 @@ const Service = (props: { showDesc: boolean; tabs: CenterTab[]; action: any }) = })); }} style={{ height: '100%' }} - tabBarStyle={{marginBottom: '5px'}} + tabBarStyle={{ marginBottom: '5px' }} /> ); } diff --git a/dinky-web/src/pages/DataStudio/components/RunToolBarButton/index.tsx b/dinky-web/src/pages/DataStudio/components/RunToolBarButton/index.tsx index f28cc375c7..9e1e9a53a0 100644 --- a/dinky-web/src/pages/DataStudio/components/RunToolBarButton/index.tsx +++ b/dinky-web/src/pages/DataStudio/components/RunToolBarButton/index.tsx @@ -17,7 +17,7 @@ * */ -import React, { ReactNode, useCallback, useEffect, useState } from 'react'; +import React, { CSSProperties, ReactNode, useCallback, useEffect, useState } from 'react'; import { Button, Tooltip } from 'antd'; import { sleep } from '@antfu/utils'; @@ -37,6 +37,7 @@ export type RunToolBarButtonProps = { hotKey?: HotKeyProps; isShow?: boolean; disabled?: boolean; + style?: CSSProperties; }; export default (props: RunToolBarButtonProps) => { @@ -49,10 +50,10 @@ export default (props: RunToolBarButtonProps) => { sleepTime, hotKey, isShow = true, - disabled = false + disabled = false, + style } = props; const [loading, setLoading] = useState(false); - const style = color ? { color: color } : {}; const onClickHandle = useCallback(async () => { setLoading(true); @@ -92,7 +93,7 @@ export default (props: RunToolBarButtonProps) => { type='text' icon={icon} onClick={onClickHandle} - style={{ ...style, padding: '1px 6px' }} + style={{ ...style, padding: '1px 6px', color: color }} > {showDesc ? desc : ''} diff --git a/dinky-web/src/pages/DataStudio/service.tsx b/dinky-web/src/pages/DataStudio/service.tsx index ce2586bd79..02a4017807 100644 --- a/dinky-web/src/pages/DataStudio/service.tsx +++ b/dinky-web/src/pages/DataStudio/service.tsx @@ -24,7 +24,7 @@ import { queryDataByParams } from '@/services/BusinessCrud'; import { API_CONSTANTS } from '@/services/endpoints'; -import { TaskState } from '@/pages/DataStudio/type'; +import { SqlConvertForm, TaskState } from '@/pages/DataStudio/type'; import { postAll } from '@/services/api'; export async function explainSql(title: string, params: any) { @@ -98,3 +98,11 @@ export function querySuggestionData(params: any) { export async function getTaskSortTypeData() { return (await postAll(API_CONSTANTS.CATALOGUE_GET_CATALOGUE_SORT_TYPE_DATA)).data; } +export async function flinkJarSqlConvertForm( + statement: string +): Promise { + return (await postAll(API_CONSTANTS.FLINK_JAR_SQL_CONVERT_FORM, { statement: statement })).data; +} +export async function flinkJarFormConvertSql(form: SqlConvertForm): Promise { + return (await postAll(API_CONSTANTS.FLINK_JAR_FORM_CONVERT_SQL, form)).data; +} diff --git a/dinky-web/src/pages/DataStudio/type.ts b/dinky-web/src/pages/DataStudio/type.ts index 03b8285b69..978c311161 100644 --- a/dinky-web/src/pages/DataStudio/type.ts +++ b/dinky-web/src/pages/DataStudio/type.ts @@ -27,6 +27,7 @@ import { Alert, DataSources } from '@/types/RegCenter/data'; import { DefaultOptionType } from 'antd/es/select'; import { TaskExtConfig } from '@/types/Studio/data'; import { SuggestionInfo } from '@/types/Public/data'; +import { JarSubmitParam } from '@/pages/DataStudio/CenterTabContent/SqlTask'; /** * @description: @@ -302,3 +303,9 @@ export type JobRunningMsgType = { jobState: string; runningLog: string; }; + +export type SqlConvertForm = { + enable: boolean; + initSqlStatement?: string; + jarSubmitParam?: JarSubmitParam; +}; diff --git a/dinky-web/src/pages/RegCenter/DataSource/components/DataSourceDetail/RightTagsRouter/index.tsx b/dinky-web/src/pages/RegCenter/DataSource/components/DataSourceDetail/RightTagsRouter/index.tsx index e807d2d37c..d79cdb59b6 100644 --- a/dinky-web/src/pages/RegCenter/DataSource/components/DataSourceDetail/RightTagsRouter/index.tsx +++ b/dinky-web/src/pages/RegCenter/DataSource/components/DataSourceDetail/RightTagsRouter/index.tsx @@ -43,12 +43,13 @@ type RightTagsRouterProps = { rightButtons?: React.ReactNode; queryParams: QueryParams; tagDisabled?: boolean; + className?: string; }; const RightTagsRouter: React.FC = (props) => { const access = useAccess(); - const { queryParams, tagDisabled = false, rightButtons } = props; + const { queryParams, tagDisabled = false, rightButtons, className } = props; const [tableInfo, setTableInfo] = useState>({}); useAsyncEffect(async () => { const fetchData = async () => { @@ -127,7 +128,14 @@ const RightTagsRouter: React.FC = (props) => { /** * render */ - return ; + return ( + + ); }; export default RightTagsRouter; diff --git a/dinky-web/src/pages/RegCenter/DataSource/components/DataSourceModal/index.tsx b/dinky-web/src/pages/RegCenter/DataSource/components/DataSourceModal/index.tsx index 07f3c8c567..66fb2d7647 100644 --- a/dinky-web/src/pages/RegCenter/DataSource/components/DataSourceModal/index.tsx +++ b/dinky-web/src/pages/RegCenter/DataSource/components/DataSourceModal/index.tsx @@ -154,7 +154,7 @@ const DataSourceModal: React.FC = (props) => { width={'50%'} open={visible} - modalProps={{ onCancel: handleCancel, maskClosable:false }} + modalProps={{ onCancel: handleCancel, maskClosable: false }} title={values.id ? l('rc.ds.modify') : l('rc.ds.create')} form={form} onValuesChange={handleTypeChange} diff --git a/dinky-web/src/services/endpoints.tsx b/dinky-web/src/services/endpoints.tsx index 33c4d60293..3c0fa3cb06 100644 --- a/dinky-web/src/services/endpoints.tsx +++ b/dinky-web/src/services/endpoints.tsx @@ -286,6 +286,8 @@ export enum API_CONSTANTS { SAVEPOINT = '/api/task/savepoint', RESTART_TASK_FROM_CHECKPOINT = '/api/task/selectSavePointRestartTask', LIST_FLINK_SQL_ENV = '/api/task/listFlinkSQLEnv', + FLINK_JAR_SQL_CONVERT_FORM = '/api/task/flinkJarSqlConvertForm', + FLINK_JAR_FORM_CONVERT_SQL = '/api/task/flinkJarFormConvertSql', // ------------------------------------ task record ------------------------------------ HISTORY_LIST = '/api/history/list',