You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dolphinscheduler.apache.org by ke...@apache.org on 2022/10/31 04:22:34 UTC

[dolphinscheduler] branch 3.1.1-prepare updated: [Improvement][UI] Support to view the process variables on the page of DAG. (#12609) (#12616)

This is an automated email from the ASF dual-hosted git repository.

kerwin pushed a commit to branch 3.1.1-prepare
in repository https://gitbox.apache.org/repos/asf/dolphinscheduler.git


The following commit(s) were added to refs/heads/3.1.1-prepare by this push:
     new 64360e5b69 [Improvement][UI] Support to view the process variables on the page of DAG. (#12609) (#12616)
64360e5b69 is described below

commit 64360e5b690f5fa668a0f937b550187e744da3c0
Author: Kerwin <37...@users.noreply.github.com>
AuthorDate: Mon Oct 31 12:22:29 2022 +0800

    [Improvement][UI] Support to view the process variables on the page of DAG. (#12609) (#12616)
    
    Co-authored-by: calvin <ji...@163.com>
---
 .../controller/ProcessDefinitionController.java    | 24 ++++++
 .../apache/dolphinscheduler/api/enums/Status.java  |  3 +
 .../api/service/ProcessDefinitionService.java      |  9 +++
 .../service/impl/ProcessDefinitionServiceImpl.java | 91 ++++++++++++++++++++++
 .../ProcessDefinitionControllerTest.java           | 14 ++++
 .../api/service/ProcessDefinitionServiceTest.java  | 22 ++++++
 .../service/modules/process-definition/index.ts    |  8 ++
 .../src/service/modules/process-instances/index.ts |  1 +
 .../workflow/components/dag/dag-toolbar.tsx        | 66 ++++++++--------
 .../instance/components/variables-view.tsx         | 21 +++--
 10 files changed, 222 insertions(+), 37 deletions(-)

diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/ProcessDefinitionController.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/ProcessDefinitionController.java
index 3c3186d5f1..1d71d9f9ba 100644
--- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/ProcessDefinitionController.java
+++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/ProcessDefinitionController.java
@@ -27,6 +27,7 @@ import static org.apache.dolphinscheduler.api.enums.Status.ENCAPSULATION_TREEVIE
 import static org.apache.dolphinscheduler.api.enums.Status.GET_TASKS_LIST_BY_PROCESS_DEFINITION_ID_ERROR;
 import static org.apache.dolphinscheduler.api.enums.Status.IMPORT_PROCESS_DEFINE_ERROR;
 import static org.apache.dolphinscheduler.api.enums.Status.QUERY_DETAIL_OF_PROCESS_DEFINITION_ERROR;
+import static org.apache.dolphinscheduler.api.enums.Status.QUERY_PROCESS_DEFINITION_ALL_VARIABLES_ERROR;
 import static org.apache.dolphinscheduler.api.enums.Status.QUERY_PROCESS_DEFINITION_LIST;
 import static org.apache.dolphinscheduler.api.enums.Status.QUERY_PROCESS_DEFINITION_LIST_PAGING_ERROR;
 import static org.apache.dolphinscheduler.api.enums.Status.QUERY_PROCESS_DEFINITION_VERSIONS_ERROR;
@@ -903,4 +904,27 @@ public class ProcessDefinitionController extends BaseController {
         return returnDataList(
                 processDefinitionService.releaseWorkflowAndSchedule(loginUser, projectCode, code, releaseState));
     }
+
+    /**
+     * query process definition global variables and local variables
+     *
+     * @param loginUser login user
+     * @param code process definition code
+     * @return variables data
+     */
+    @Operation(summary = "viewVariables", description = "QUERY_PROCESS_DEFINITION_GLOBAL_VARIABLES_AND_LOCAL_VARIABLES_NOTES")
+    @Parameters({
+            @Parameter(name = "code", description = "PROCESS_DEFINITION_CODE", required = true, schema = @Schema(implementation = long.class, example = "100"))
+    })
+    @GetMapping(value = "/{code}/view-variables")
+    @ResponseStatus(HttpStatus.OK)
+    @ApiException(QUERY_PROCESS_DEFINITION_ALL_VARIABLES_ERROR)
+    @AccessLogAnnotation
+    public Result viewVariables(@Parameter(hidden = true) @RequestAttribute(value = Constants.SESSION_USER) User loginUser,
+                                @Parameter(name = "projectCode", description = "PROJECT_CODE", required = true) @PathVariable long projectCode,
+                                @PathVariable("code") Long code) {
+        Map<String, Object> result = processDefinitionService.viewVariables(loginUser, projectCode, code);
+        return returnDataList(result);
+    }
+
 }
diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/Status.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/Status.java
index 85a940d359..47bb5dbbbf 100644
--- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/Status.java
+++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/Status.java
@@ -436,6 +436,9 @@ public enum Status {
     USER_PASSWORD_LENGTH_ERROR(1300017, "user's password length error", "用户密码长度错误"),
     QUERY_CAN_USE_K8S_NAMESPACE_ERROR(1300018, "login user query can used namespace list error", "查询可用命名空间错误"),
 
+    QUERY_PROCESS_DEFINITION_ALL_VARIABLES_ERROR(1300100, "query process definition all variables error",
+            "查询工作流自定义变量信息错误"),
+
     NO_CURRENT_OPERATING_PERMISSION(1400001, "The current user does not have this permission.", "当前用户无此权限"),
     FUNCTION_DISABLED(1400002, "The current feature is disabled.", "当前功能已被禁用"),
     SCHEDULE_TIME_NUMBER(1400003, "The number of complement dates exceed 100.", "补数日期个数超过100"),
diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionService.java
index beab02207a..feeed31424 100644
--- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionService.java
+++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionService.java
@@ -469,4 +469,13 @@ public interface ProcessDefinitionService {
      * @return Json String
      */
     String doOtherOperateProcess(User loginUser, ProcessDefinition processDefinition);
+
+    /**
+     * view process variables
+     * @param loginUser    login user
+     * @param projectCode project code
+     * @param code process definition code
+     * @return variables data
+     */
+    Map<String, Object> viewVariables(User loginUser, long projectCode, long code);
 }
diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProcessDefinitionServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProcessDefinitionServiceImpl.java
index 6002a16276..06f5fdfb95 100644
--- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProcessDefinitionServiceImpl.java
+++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProcessDefinitionServiceImpl.java
@@ -31,11 +31,17 @@ import static org.apache.dolphinscheduler.api.constants.ApiFuncIdentificationCon
 import static org.apache.dolphinscheduler.api.constants.ApiFuncIdentificationConstant.WORKFLOW_SWITCH_TO_THIS_VERSION;
 import static org.apache.dolphinscheduler.api.constants.ApiFuncIdentificationConstant.WORKFLOW_TREE_VIEW;
 import static org.apache.dolphinscheduler.api.constants.ApiFuncIdentificationConstant.WORKFLOW_UPDATE;
+import static org.apache.dolphinscheduler.api.enums.Status.PROCESS_DEFINE_NOT_EXIST;
 import static org.apache.dolphinscheduler.common.constants.CommandKeyConstants.CMD_PARAM_SUB_PROCESS_DEFINE_CODE;
 import static org.apache.dolphinscheduler.common.constants.Constants.COPY_SUFFIX;
+import static org.apache.dolphinscheduler.common.constants.Constants.DATA_LIST;
 import static org.apache.dolphinscheduler.common.constants.Constants.DEFAULT_WORKER_GROUP;
 import static org.apache.dolphinscheduler.common.constants.Constants.EMPTY_STRING;
+import static org.apache.dolphinscheduler.common.constants.Constants.GLOBAL_PARAMS;
 import static org.apache.dolphinscheduler.common.constants.Constants.IMPORT_SUFFIX;
+import static org.apache.dolphinscheduler.common.constants.Constants.LOCAL_PARAMS;
+import static org.apache.dolphinscheduler.plugin.task.api.TaskConstants.LOCAL_PARAMS_LIST;
+import static org.apache.dolphinscheduler.plugin.task.api.TaskConstants.TASK_TYPE;
 import static org.apache.dolphinscheduler.plugin.task.api.TaskConstants.TASK_TYPE_SQL;
 
 import org.apache.dolphinscheduler.api.dto.DagDataSchedule;
@@ -102,6 +108,7 @@ import org.apache.dolphinscheduler.dao.model.PageListingResult;
 import org.apache.dolphinscheduler.dao.repository.ProcessDefinitionDao;
 import org.apache.dolphinscheduler.plugin.task.api.enums.SqlType;
 import org.apache.dolphinscheduler.plugin.task.api.enums.TaskTimeoutStrategy;
+import org.apache.dolphinscheduler.plugin.task.api.model.Property;
 import org.apache.dolphinscheduler.plugin.task.api.parameters.ParametersNode;
 import org.apache.dolphinscheduler.plugin.task.api.parameters.SqlParameters;
 import org.apache.dolphinscheduler.service.model.TaskNode;
@@ -128,6 +135,7 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
+import java.util.TreeSet;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.Function;
 import java.util.stream.Collectors;
@@ -2594,6 +2602,89 @@ public class ProcessDefinitionServiceImpl extends BaseServiceImpl implements Pro
         return null;
     }
 
+    /**
+     * view process variables
+     * @param loginUser    login user
+     * @param projectCode project code
+     * @param code        process definition code
+     * @return variables data
+     */
+    @Override
+    public Map<String, Object> viewVariables(User loginUser, long projectCode, long code) {
+
+        Project project = projectMapper.queryByCode(projectCode);
+
+        // check user access for project
+        Map<String, Object> result =
+                projectService.checkProjectAndAuth(loginUser, project, projectCode, WORKFLOW_DEFINITION);
+        if (result.get(Constants.STATUS) != Status.SUCCESS) {
+            return result;
+        }
+
+        ProcessDefinition processDefinition = processDefinitionMapper.queryByCode(code);
+
+        if (Objects.isNull(processDefinition) || projectCode != processDefinition.getProjectCode()) {
+            logger.error("Process definition does not exist, projectCode:{}, processDefinitionCode:{}.", projectCode,
+                    code);
+            putMsg(result, PROCESS_DEFINE_NOT_EXIST, code);
+            return result;
+        }
+
+        // global params
+        List<Property> globalParams = processDefinition.getGlobalParamList();
+
+        Map<String, Map<String, Object>> localUserDefParams = getLocalParams(processDefinition);
+
+        Map<String, Object> resultMap = new HashMap<>();
+
+        if (Objects.nonNull(globalParams)) {
+            resultMap.put(GLOBAL_PARAMS, globalParams);
+        }
+
+        if (Objects.nonNull(localUserDefParams)) {
+            resultMap.put(LOCAL_PARAMS, localUserDefParams);
+        }
+
+        result.put(DATA_LIST, resultMap);
+        putMsg(result, Status.SUCCESS);
+        return result;
+    }
+
+    /**
+     * get local params
+     */
+    private Map<String, Map<String, Object>> getLocalParams(ProcessDefinition processDefinition) {
+        Map<String, Map<String, Object>> localUserDefParams = new HashMap<>();
+
+        Set<Long> taskCodeSet = new TreeSet<>();
+
+        processTaskRelationMapper.queryByProcessCode(processDefinition.getProjectCode(), processDefinition.getCode())
+                .forEach(processTaskRelation -> {
+                    if (processTaskRelation.getPreTaskCode() > 0) {
+                        taskCodeSet.add(processTaskRelation.getPreTaskCode());
+                    }
+                    if (processTaskRelation.getPostTaskCode() > 0) {
+                        taskCodeSet.add(processTaskRelation.getPostTaskCode());
+                    }
+                });
+
+        taskDefinitionMapper.queryByCodeList(taskCodeSet)
+                .stream().forEach(taskDefinition -> {
+                    Map<String, Object> localParamsMap = new HashMap<>();
+                    String localParams = JSONUtils.getNodeString(taskDefinition.getTaskParams(), LOCAL_PARAMS);
+                    if (!StringUtils.isEmpty(localParams)) {
+                        List<Property> localParamsList = JSONUtils.toList(localParams, Property.class);
+                        localParamsMap.put(TASK_TYPE, taskDefinition.getTaskType());
+                        localParamsMap.put(LOCAL_PARAMS_LIST, localParamsList);
+                        if (CollectionUtils.isNotEmpty(localParamsList)) {
+                            localUserDefParams.put(taskDefinition.getName(), localParamsMap);
+                        }
+                    }
+                });
+
+        return localUserDefParams;
+    }
+
     /**
      * delete other relation
      * @param project
diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/ProcessDefinitionControllerTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/ProcessDefinitionControllerTest.java
index eced71ef7a..e8f16f1b15 100644
--- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/ProcessDefinitionControllerTest.java
+++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/ProcessDefinitionControllerTest.java
@@ -437,4 +437,18 @@ public class ProcessDefinitionControllerTest {
         Assert.assertEquals(Status.SUCCESS.getCode(), (int) result.getCode());
     }
 
+    @Test
+    public void testViewVariables() {
+        long projectCode = 1L;
+        Map<String, Object> resultMap = new HashMap<>();
+        putMsg(resultMap, Status.SUCCESS);
+
+        Mockito.when(processDefinitionService.viewVariables(user, projectCode, 1))
+                .thenReturn(resultMap);
+
+        Result result = processDefinitionController.viewVariables(user, projectCode, 1L);
+
+        Assertions.assertEquals(Status.SUCCESS.getCode(), result.getCode().intValue());
+    }
+
 }
diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionServiceTest.java
index a2170bd080..e232028a67 100644
--- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionServiceTest.java
+++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionServiceTest.java
@@ -859,6 +859,28 @@ public class ProcessDefinitionServiceTest {
         Assert.assertEquals(2, newName3.split(Constants.IMPORT_SUFFIX).length);
     }
 
+    @Test
+    public void testViewVariables() {
+        Mockito.when(projectMapper.queryByCode(projectCode)).thenReturn(getProject(projectCode));
+
+        Project project = getProject(projectCode);
+
+        ProcessDefinition processDefinition = getProcessDefinition();
+
+        Map<String, Object> result = new HashMap<>();
+        putMsg(result, Status.PROJECT_NOT_FOUND, projectCode);
+
+        // project check auth fail
+        Mockito.when(projectService.checkProjectAndAuth(user, project, projectCode, WORKFLOW_DEFINITION))
+                .thenReturn(result);
+
+        Map<String, Object> map =
+                processDefinitionService.viewVariables(user, processDefinition.getProjectCode(),
+                        processDefinition.getCode());
+
+        Assertions.assertEquals(Status.PROJECT_NOT_FOUND, map.get(Constants.STATUS));
+    }
+
     /**
      * get mock processDefinition
      *
diff --git a/dolphinscheduler-ui/src/service/modules/process-definition/index.ts b/dolphinscheduler-ui/src/service/modules/process-definition/index.ts
index e202f0ccf6..6b16e560e2 100644
--- a/dolphinscheduler-ui/src/service/modules/process-definition/index.ts
+++ b/dolphinscheduler-ui/src/service/modules/process-definition/index.ts
@@ -247,3 +247,11 @@ export function viewTree(
     params
   })
 }
+
+export function viewProcessDefinitionVariables(code: number, processCode: number): any {
+  return axios({
+    url: `/projects/${code}/process-definition/${processCode}/view-variables`,
+    method: 'get'
+  })
+}
+
diff --git a/dolphinscheduler-ui/src/service/modules/process-instances/index.ts b/dolphinscheduler-ui/src/service/modules/process-instances/index.ts
index be8c019600..dd02b1eff4 100644
--- a/dolphinscheduler-ui/src/service/modules/process-instances/index.ts
+++ b/dolphinscheduler-ui/src/service/modules/process-instances/index.ts
@@ -130,3 +130,4 @@ export function viewVariables(id: number, code: number): any {
     method: 'get'
   })
 }
+
diff --git a/dolphinscheduler-ui/src/views/projects/workflow/components/dag/dag-toolbar.tsx b/dolphinscheduler-ui/src/views/projects/workflow/components/dag/dag-toolbar.tsx
index 519fa5bc01..398e31baa9 100644
--- a/dolphinscheduler-ui/src/views/projects/workflow/components/dag/dag-toolbar.tsx
+++ b/dolphinscheduler-ui/src/views/projects/workflow/components/dag/dag-toolbar.tsx
@@ -215,48 +215,50 @@ export default defineComponent({
             }}
           ></NTooltip>
         )}
-        <div class={Styles['toolbar-left-part']}>
-          {route.name !== 'workflow-instance-detail' &&
-            props.definition?.processDefinition?.releaseState === 'ONLINE' && (
-              <NTag round size='small' type='info'>
-                {t('project.dag.online')}
-              </NTag>
-            )}
-          {route.name === 'workflow-instance-detail' && (
-            <>
-              <NTooltip
-                v-slots={{
-                  trigger: () => (
+        {props.definition?.processDefinition?.name && (
+          <NTooltip
+              v-slots={{
+                trigger: () => (
                     <NPopover
-                      placement='bottom'
-                      trigger='click'
-                      scrollable
-                      style={{ maxWidth: '50vw', maxHeight: '70vh' }}
+                        placement='bottom'
+                        trigger='click'
+                        scrollable
+                        style={{ maxWidth: '50vw', maxHeight: '70vh' }}
                     >
                       {{
                         trigger: () => (
-                          <NButton
-                            quaternary
-                            circle
-                            class={Styles['toolbar-btn']}
-                          >
-                            <NIcon>
-                              <FundViewOutlined />
-                            </NIcon>
-                          </NButton>
+                            <NButton
+                                quaternary
+                                circle
+                                class={Styles['toolbar-btn']}
+                            >
+                              <NIcon>
+                                <FundViewOutlined />
+                              </NIcon>
+                            </NButton>
                         ),
                         header: () => (
-                          <NText strong depth={1}>
-                            {t('project.workflow.parameters_variables')}
-                          </NText>
+                            <NText strong depth={1}>
+                              {t('project.workflow.parameters_variables')}
+                            </NText>
                         ),
                         default: () => <VariablesView onCopy={copy} />
                       }}
                     </NPopover>
-                  ),
-                  default: () => t('project.dag.view_variables')
-                }}
-              ></NTooltip>
+                ),
+                default: () => t('project.dag.view_variables')
+              }}
+          ></NTooltip>
+        )}
+        <div class={Styles['toolbar-left-part']}>
+          {route.name !== 'workflow-instance-detail' &&
+            props.definition?.processDefinition?.releaseState === 'ONLINE' && (
+              <NTag round size='small' type='info'>
+                {t('project.dag.online')}
+              </NTag>
+            )}
+          {route.name === 'workflow-instance-detail' && (
+            <>
               <NTooltip
                 v-slots={{
                   trigger: () => (
diff --git a/dolphinscheduler-ui/src/views/projects/workflow/instance/components/variables-view.tsx b/dolphinscheduler-ui/src/views/projects/workflow/instance/components/variables-view.tsx
index ae1adb4ff5..2f75fd3e54 100644
--- a/dolphinscheduler-ui/src/views/projects/workflow/instance/components/variables-view.tsx
+++ b/dolphinscheduler-ui/src/views/projects/workflow/instance/components/variables-view.tsx
@@ -19,9 +19,11 @@ import { useRoute } from 'vue-router'
 import { defineComponent, onMounted, ref, computed } from 'vue'
 import { useI18n } from 'vue-i18n'
 import { viewVariables } from '@/service/modules/process-instances'
+import { viewProcessDefinitionVariables } from "@/service/modules/process-definition";
 import styles from './variables.module.scss'
 import { NButton } from 'naive-ui'
 
+
 export default defineComponent({
   name: 'variables-view',
   emits: ['copy'],
@@ -30,20 +32,29 @@ export default defineComponent({
     const route = useRoute()
 
     const projectCode = Number(route.params.projectCode)
+
     const instanceId = Number(route.params.id)
 
+    const processCode = Number(route.params.code)
+
     const globalParams = computed(() => {
-      return paramsRef.value ? paramsRef.value.globalParams : []
+      return paramsRef.value && paramsRef.value.globalParams ? paramsRef.value.globalParams : []
     })
 
     const localParams = computed(() => {
-      return paramsRef.value ? paramsRef.value.localParams : {}
+      return paramsRef.value && paramsRef.value.localParams ? paramsRef.value.localParams : {}
     })
 
     const getViewVariables = () => {
-      viewVariables(instanceId, projectCode).then((res: any) => {
-        paramsRef.value = res
-      })
+      if (Number.isNaN(instanceId)) {
+        viewProcessDefinitionVariables(projectCode, processCode).then((res: any) => {
+          paramsRef.value = res
+        })
+      } else {
+        viewVariables(instanceId, projectCode).then((res: any) => {
+          paramsRef.value = res
+        })
+      }
     }
 
     const handleCopy = (text: string) => {