You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dolphinscheduler.apache.org by so...@apache.org on 2022/02/25 09:21:12 UTC

[dolphinscheduler] branch dev updated: [Feature][UI Next] Add Dag workflow validation

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

songjian pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/dolphinscheduler.git


The following commit(s) were added to refs/heads/dev by this push:
     new ffd47e7  [Feature][UI Next] Add Dag workflow validation
ffd47e7 is described below

commit ffd47e70ba06f63691169617f2188a7eec73995a
Author: Devosend <de...@gmail.com>
AuthorDate: Fri Feb 25 17:21:00 2022 +0800

    [Feature][UI Next] Add Dag workflow validation
---
 .../src/locales/modules/en_US.ts                   |  7 +-
 .../src/locales/modules/zh_CN.ts                   |  7 +-
 .../service/modules/process-definition/index.ts    |  2 +-
 .../workflow/components/dag/dag-save-modal.tsx     | 85 +++++++++++++++++-----
 .../projects/workflow/components/dag/index.tsx     |  7 ++
 .../projects/workflow/definition/create/index.tsx  | 12 ++-
 .../projects/workflow/definition/detail/index.tsx  | 12 ++-
 7 files changed, 104 insertions(+), 28 deletions(-)

diff --git a/dolphinscheduler-ui-next/src/locales/modules/en_US.ts b/dolphinscheduler-ui-next/src/locales/modules/en_US.ts
index fde10bd..e0feaa5 100644
--- a/dolphinscheduler-ui-next/src/locales/modules/en_US.ts
+++ b/dolphinscheduler-ui-next/src/locales/modules/en_US.ts
@@ -559,7 +559,12 @@ const project = {
     value: 'Value',
     success: 'Success',
     delete_cell: 'Delete selected edges and nodes',
-    online_directly: 'Whether to go online the process definition'
+    online_directly: 'Whether to go online the process definition',
+    dag_name_empty: 'DAG graph name cannot be empty',
+    positive_integer: 'Please enter a positive integer greater than 0',
+    prop_empty: 'prop is empty',
+    prop_repeat: 'prop is repeat',
+    node_not_created: 'Failed to save node not created'
   },
   node: {
     current_node_settings: 'Current node settings',
diff --git a/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts b/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts
index 4ad6a96..d11feda 100644
--- a/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts
+++ b/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts
@@ -557,7 +557,12 @@ const project = {
     value: '值',
     success: '成功',
     delete_cell: '删除选中的线或节点',
-    online_directly: '是否上线流程定义'
+    online_directly: '是否上线流程定义',
+    dag_name_empty: 'DAG图名称不能为空',
+    positive_integer: '请输入大于 0 的正整数',
+    prop_empty: '自定义参数prop不能为空',
+    prop_repeat: 'prop中有重复',
+    node_not_created: '未创建节点保存失败'
   },
   node: {
     current_node_settings: '当前节点设置',
diff --git a/dolphinscheduler-ui-next/src/service/modules/process-definition/index.ts b/dolphinscheduler-ui-next/src/service/modules/process-definition/index.ts
index 6b3d3bc..b177988 100644
--- a/dolphinscheduler-ui-next/src/service/modules/process-definition/index.ts
+++ b/dolphinscheduler-ui-next/src/service/modules/process-definition/index.ts
@@ -139,7 +139,7 @@ export function querySimpleList(code: number): any {
   })
 }
 
-export function verifyName(params: NameReq, code: CodeReq): any {
+export function verifyName(params: NameReq, code: number): any {
   return axios({
     url: `/projects/${code}/process-definition/verify-name`,
     method: 'get',
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag-save-modal.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag-save-modal.tsx
index bef3fdf..8962fcc 100644
--- a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag-save-modal.tsx
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag-save-modal.tsx
@@ -30,6 +30,8 @@ import {
 } from 'naive-ui'
 import { queryTenantList } from '@/service/modules/tenants'
 import { SaveForm, WorkflowDefinition } from './types'
+import { useRoute } from 'vue-router'
+import { verifyName } from '@/service/modules/process-definition'
 import './x6-style.scss'
 
 const props = {
@@ -54,8 +56,10 @@ export default defineComponent({
   props,
   emits: ['update:show', 'save'],
   setup(props, context) {
+    const route = useRoute()
     const { t } = useI18n()
 
+    const projectCode = Number(route.params.projectCode)
     const tenants = ref<Tenant[]>([])
     const tenantsDropdown = computed(() => {
       if (tenants.value) {
@@ -86,33 +90,80 @@ export default defineComponent({
     const formRef = ref()
     const rule = {
       name: {
-        required: true
+        required: true,
+        message: t('project.dag.dag_name_empty')
+      },
+      timeout: {
+        validator() {
+          if (formValue.value.timeoutFlag && formValue.value.timeout <= 0) {
+            return new Error(t('project.dag.positive_integer'))
+          }
+        }
+      },
+      globalParams: {
+        validator() {
+          const props = new Set()
+          for (const param of formValue.value.globalParams) {
+            const prop = param.value
+            if (!prop) {
+              return new Error(t('project.dag.prop_empty'))
+            }
+
+            if (props.has(prop)) {
+              return new Error(t('project.dag.prop_repeat'))
+            }
+
+            props.add(prop)
+          }
+        }
       }
     }
     const onSubmit = () => {
-      context.emit('save', formValue.value)
+      formRef.value.validate(async (valid: any) => {
+        if (!valid) {
+          const params = {
+            name: formValue.value.name
+          }
+          if (
+            props.definition?.processDefinition.name !== formValue.value.name
+          ) {
+            verifyName(params, projectCode)
+              .then(() => context.emit('save', formValue.value))
+              .catch((error: any) => {
+                window.$message.error(error.message)
+              })
+          } else {
+            context.emit('save', formValue.value)
+          }
+        }
+      })
     }
     const onCancel = () => {
       context.emit('update:show', false)
     }
 
-    watch(
-      () => props.definition,
-      () => {
-        const process = props.definition?.processDefinition
-        if (process) {
-          formValue.value.name = process.name
-          formValue.value.description = process.description
-          formValue.value.tenantCode = process.tenantCode
-          if (process.timeout && process.timeout > 0) {
-            formValue.value.timeoutFlag = true
-            formValue.value.timeout = process.timeout
-          }
-          formValue.value.globalParams = process.globalParamList.map(
-            (param) => ({ key: param.prop, value: param.value })
-          )
+    const updateModalData = () => {
+      const process = props.definition?.processDefinition
+      if (process) {
+        formValue.value.name = process.name
+        formValue.value.description = process.description
+        formValue.value.tenantCode = process.tenantCode
+        if (process.timeout && process.timeout > 0) {
+          formValue.value.timeoutFlag = true
+          formValue.value.timeout = process.timeout
         }
+        formValue.value.globalParams = process.globalParamList.map((param) => ({
+          key: param.prop,
+          value: param.value
+        }))
       }
+    }
+
+    onMounted(() => updateModalData())
+
+    watch(
+      () => props.definition?.processDefinition,
+      () => updateModalData()
     )
 
     return () => (
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/index.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/index.tsx
index 4376486..6f469ba 100644
--- a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/index.tsx
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/index.tsx
@@ -25,6 +25,7 @@ import {
   watch,
   onBeforeUnmount
 } from 'vue'
+import { useI18n } from 'vue-i18n'
 import DagToolbar from './dag-toolbar'
 import DagCanvas from './dag-canvas'
 import DagSidebar from './dag-sidebar'
@@ -73,6 +74,7 @@ export default defineComponent({
   props,
   emits: ['refresh', 'save'],
   setup(props, context) {
+    const { t } = useI18n()
     const theme = useThemeStore()
 
     // Whether the graph can be operated
@@ -156,6 +158,11 @@ export default defineComponent({
     const onSave = (saveForm: any) => {
       const edges = graph.value?.getEdges() || []
       const nodes = graph.value?.getNodes() || []
+      if (!nodes.length) {
+        window.$message.error(t('project.dag.node_not_created'))
+        saveModelToggle(false)
+        return
+      }
       const connects = getConnects(nodes, edges, taskDefinitions.value as any)
       const locations = getLocations(nodes)
       context.emit('save', {
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/definition/create/index.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/definition/create/index.tsx
index f2cc259..cb2dcfd 100644
--- a/dolphinscheduler-ui-next/src/views/projects/workflow/definition/create/index.tsx
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/definition/create/index.tsx
@@ -75,10 +75,14 @@ export default defineComponent({
           timeout: saveForm.timeoutFlag ? saveForm.timeout : 0
         },
         projectCode
-      ).then((res: any) => {
-        message.success(t('project.dag.success'))
-        router.push({ path: `/projects/${projectCode}/workflow-definition` })
-      })
+      )
+        .then((res: any) => {
+          message.success(t('project.dag.success'))
+          router.push({ path: `/projects/${projectCode}/workflow-definition` })
+        })
+        .catch((error: any) => {
+          window.$message.error(error.message)
+        })
     }
 
     return () => (
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/definition/detail/index.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/definition/detail/index.tsx
index c14e225..b2aa4b3 100644
--- a/dolphinscheduler-ui-next/src/views/projects/workflow/definition/detail/index.tsx
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/definition/detail/index.tsx
@@ -94,10 +94,14 @@ export default defineComponent({
         },
         code,
         projectCode
-      ).then((res: any) => {
-        message.success(t('project.dag.success'))
-        router.push({ path: `/projects/${projectCode}/workflow-definition` })
-      })
+      )
+        .then((res: any) => {
+          message.success(t('project.dag.success'))
+          router.push({ path: `/projects/${projectCode}/workflow-definition` })
+        })
+        .catch((error: any) => {
+          window.$message.error(error.message)
+        })
     }
 
     onMounted(() => {