Browse Source

[Feature][UI Next] Add process name and pre tasks into SHELL. (#8437)

Amy0104 3 years ago
parent
commit
2f953fb945

+ 1 - 1
dolphinscheduler-ui-next/src/service/modules/task-definition/types.ts

@@ -123,7 +123,7 @@ interface TaskDefinitionVersionRes {
 }
 
 interface ISingleSaveReq {
-  processDefinitionCode: string
+  processDefinitionCode?: string
   upstreamCodes: string
   taskDefinitionJsonObj: string
 }

+ 3 - 2
dolphinscheduler-ui-next/src/views/projects/task/components/node/detail.tsx

@@ -24,7 +24,8 @@ import { useI18n } from 'vue-i18n'
 
 const props = {
   projectCode: {
-    type: Number as PropType<number>
+    type: Number as PropType<number>,
+    default: 0
   },
   data: {
     type: Object as PropType<ITaskData>,
@@ -53,7 +54,7 @@ const NodeDetail = defineComponent({
     const { t } = useI18n()
 
     const { json, model } = useTask({
-      taskType: data.taskType,
+      data,
       projectCode,
       from,
       readonly

+ 16 - 5
dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-pre-tasks.ts

@@ -15,17 +15,29 @@
  * limitations under the License.
  */
 
-import { ref, onMounted } from 'vue'
+import { ref, watch } from 'vue'
 import { useI18n } from 'vue-i18n'
 import type { IJsonItem } from '../types'
 
-export function usePreTasks(): IJsonItem {
+export function usePreTasks(model: { [field: string]: any }): IJsonItem {
   const { t } = useI18n()
 
   const options = ref([])
-  const loading = ref(false)
 
-  onMounted(() => {})
+  const getOptions = () => {
+    if (!model.preTaskOptions?.length) return []
+    return model.preTaskOptions.map((task: { code: number; name: string }) => ({
+      value: task.code,
+      label: task.name
+    }))
+  }
+
+  watch(
+    () => model.preTaskOptions,
+    () => {
+      options.value = getOptions()
+    }
+  )
 
   return {
     type: 'select',
@@ -33,7 +45,6 @@ export function usePreTasks(): IJsonItem {
     span: 24,
     name: t('project.node.pre_tasks'),
     props: {
-      loading,
       multiple: true,
       filterable: true
     },

+ 86 - 6
dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-process-name.ts

@@ -17,13 +17,29 @@
 
 import { ref, onMounted } from 'vue'
 import { useI18n } from 'vue-i18n'
-import { querySimpleList } from '@/service/modules/process-definition'
+import { uniqBy } from 'lodash'
+import {
+  querySimpleList,
+  queryProcessDefinitionByCode
+} from '@/service/modules/process-definition'
 import type { IJsonItem } from '../types'
+import { number } from 'echarts'
 
-export function useProcessName(
-  projectCode: number,
+export function useProcessName({
+  model,
+  projectCode,
+  isCreate,
+  from,
+  processName,
+  code
+}: {
+  model: { [field: string]: any }
+  projectCode: number
   isCreate: boolean
-): IJsonItem {
+  from?: number
+  processName?: number
+  code?: number
+}): IJsonItem {
   const { t } = useI18n()
 
   const options = ref([] as { label: string; value: string }[])
@@ -43,19 +59,83 @@ export function useProcessName(
       loading.value = false
     }
   }
+  const getProcessListByCode = async (processCode: number) => {
+    if (!processCode) return
+    try {
+      const res = await queryProcessDefinitionByCode(processCode, projectCode)
+      getTaskOptions(res)
+    } catch (err) {}
+  }
+  const getTaskOptions = (processDefinition: {
+    processTaskRelationList: []
+    taskDefinitionList: []
+  }) => {
+    const { processTaskRelationList = [], taskDefinitionList = [] } =
+      processDefinition
+
+    const preTaskOptions: { code: number; name: string }[] = []
+    const tasks: { [field: number]: string } = {}
+    taskDefinitionList.forEach(
+      (task: { code: number; taskType: string; name: string }) => {
+        tasks[task.code] = task.name
+        if (task.code === code) return
+        if (
+          task.taskType === 'CONDITIONS' &&
+          processTaskRelationList.filter(
+            (relation: { preTaskCode: number }) =>
+              relation.preTaskCode === task.code
+          ).length >= 2
+        ) {
+          return
+        }
+        preTaskOptions.push({
+          code: task.code,
+          name: task.name
+        })
+      }
+    )
+    model.preTaskOptions = uniqBy(preTaskOptions, 'code')
+
+    if (!code) return
+    const preTasks: number[] = []
+    const postTaskOptions: { code: number; name: string }[] = []
+    processTaskRelationList.forEach(
+      (relation: { preTaskCode: number; postTaskCode: number }) => {
+        if (relation.preTaskCode === code) {
+          postTaskOptions.push({
+            code: relation.postTaskCode,
+            name: tasks[relation.postTaskCode]
+          })
+        }
+        if (relation.postTaskCode === code && relation.preTaskCode !== 0) {
+          preTasks.push(relation.preTaskCode)
+        }
+      }
+    )
+    model.preTasks = preTasks
+    model.postTaskOptions = postTaskOptions
+  }
+
+  const onChange = (code: number) => {
+    getProcessListByCode(code)
+  }
 
   onMounted(() => {
+    if (from === 1 && processName) {
+      getProcessListByCode(processName)
+    }
     getProcessList()
   })
 
   return {
     type: 'select',
-    field: 'processCode',
+    field: 'processName',
     span: 24,
     name: t('project.node.process_name'),
     props: {
       loading: loading,
-      disabled: !isCreate
+      disabled: !isCreate,
+      'on-update:value': onChange
     },
     options: options
   }

+ 12 - 10
dolphinscheduler-ui-next/src/views/projects/task/components/node/format-data.ts

@@ -24,11 +24,10 @@ export function formatParams(data: INodeData): {
   taskDefinitionJsonObj: object
 } {
   const params = {
-    processDefinitionCode: data.processCode ? String(data.processCode) : '',
-    upstreamCodes: '',
+    processDefinitionCode: data.processName ? String(data.processName) : '',
+    upstreamCodes: data?.preTasks?.join(','),
     taskDefinitionJsonObj: {
       ...omit(data, [
-        'processCode',
         'delayTime',
         'environmentCode',
         'failRetryTimes',
@@ -37,7 +36,11 @@ export function formatParams(data: INodeData): {
         'localParams',
         'timeoutFlag',
         'timeoutNotifyStrategy',
-        'resourceList'
+        'resourceList',
+        'postTaskOptions',
+        'preTaskOptions',
+        'preTasks',
+        'processName'
       ]),
       code: data.code,
       delayTime: data.delayTime ? '0' : String(data.delayTime),
@@ -46,7 +49,7 @@ export function formatParams(data: INodeData): {
       failRetryInterval: data.failRetryTimes
         ? String(data.failRetryTimes)
         : '0',
-      taskGroupId: data.taskGroupId || '',
+      taskGroupId: data.taskGroupId || 0,
       taskParams: {
         localParams: data.localParams,
         rawScript: data.rawScript,
@@ -86,11 +89,10 @@ export function formatModel(data: ITaskData) {
     delayTime: data.delayTime,
     timeoutFlag: data.timeoutFlag === 'OPEN',
     timeoutNotifyStrategy: [data.timeoutNotifyStrategy] || [],
-    resourceList: data.taskParams.resourceList,
+    resourceList: data.taskParams?.resourceList || [],
     timeout: data.timeout,
-    rawScript: data.taskParams.rawScript,
-    localParams: data.taskParams.localParams,
-    preTasks: [],
+    rawScript: data.taskParams?.rawScript,
+    localParams: data.taskParams?.localParams || [],
     id: data.id,
     code: data.code
   } as {
@@ -100,7 +102,7 @@ export function formatModel(data: ITaskData) {
   if (data.timeoutNotifyStrategy === 'WARNFAILED') {
     params.timeoutNotifyStrategy = ['WARN', 'FAILED']
   }
-  if (data.taskParams.resourceList) {
+  if (data.taskParams?.resourceList) {
     params.resourceList = data.taskParams.resourceList.map(
       (item: { id: number }) => item.id
     )

+ 14 - 5
dolphinscheduler-ui-next/src/views/projects/task/components/node/tasks/use-shell.ts

@@ -17,16 +17,18 @@
 
 import { reactive } from 'vue'
 import * as Fields from '../fields/index'
-import type { IJsonItem, INodeData } from '../types'
+import type { IJsonItem, INodeData, ITaskData } from '../types'
 
 export function useShell({
   projectCode,
   from = 0,
-  readonly
+  readonly,
+  data
 }: {
   projectCode: number
   from?: number
   readonly?: boolean
+  data?: ITaskData
 }) {
   const model = reactive({
     name: '',
@@ -47,7 +49,14 @@ export function useShell({
   if (from === 1) {
     extra = [
       Fields.useTaskType(model, readonly),
-      Fields.useProcessName(projectCode, !model.id)
+      Fields.useProcessName({
+        model,
+        projectCode,
+        isCreate: !data?.id,
+        from,
+        processName: data?.processName,
+        code: data?.code
+      })
     ]
   }
 
@@ -59,13 +68,13 @@ export function useShell({
       Fields.useDescription(),
       Fields.useTaskPriority(),
       Fields.useWorkerGroup(),
-      Fields.useEnvironmentName(model, !model.id),
+      Fields.useEnvironmentName(model, !data?.id),
       ...Fields.useTaskGroup(model, projectCode),
       ...Fields.useFailed(),
       Fields.useDelayTime(),
       ...Fields.useTimeoutAlarm(model),
       ...Fields.useShell(model),
-      Fields.usePreTasks()
+      Fields.usePreTasks(model)
     ] as IJsonItem[],
     model
   }

+ 5 - 4
dolphinscheduler-ui-next/src/views/projects/task/components/node/types.ts

@@ -40,7 +40,7 @@ type ITaskType = TaskType
 interface INodeData {
   id?: string
   taskType?: ITaskType
-  processCode?: string
+  processName?: number
   delayTime?: number
   description?: string
   environmentCode?: number | null
@@ -59,6 +59,9 @@ interface INodeData {
   resourceList?: number[]
   code?: number
   name?: string
+  preTasks?: []
+  preTaskOptions?: []
+  postTaskOptions?: []
 }
 
 interface ITaskData
@@ -67,16 +70,14 @@ interface ITaskData
     'timeoutFlag' | 'taskPriority' | 'timeoutNotifyStrategy'
   > {
   name?: string
-  processName?: number
   taskPriority?: string
   timeoutFlag: 'OPEN' | 'CLOSE'
   timeoutNotifyStrategy?: string | []
-  taskParams: {
+  taskParams?: {
     resourceList: []
     rawScript: string
     localParams: ILocalParam[]
   }
-  preTasks?: []
 }
 
 export {

+ 12 - 7
dolphinscheduler-ui-next/src/views/projects/task/components/node/use-task.ts

@@ -16,23 +16,28 @@
  */
 
 import { useShell } from './tasks/use-shell'
-import { IJsonItem, ITaskType, INodeData } from './types'
+import { IJsonItem, INodeData, ITaskData } from './types'
 
 export function useTask({
-  taskType = 'SHELL',
+  data,
   projectCode,
   from,
   readonly
 }: {
-  taskType?: ITaskType
+  data: ITaskData
+  projectCode: number
   from?: number
-  projectCode?: number
   readonly?: boolean
 }): { json: IJsonItem[]; model: INodeData } {
-  console.log(taskType, 'taskType')
+  const { taskType = 'SHELL' } = data
   let node = {} as { json: IJsonItem[]; model: INodeData }
-  if (taskType === 'SHELL' && projectCode) {
-    node = useShell({ projectCode, from, readonly })
+  if (taskType === 'SHELL') {
+    node = useShell({
+      projectCode,
+      from,
+      readonly,
+      data
+    })
   }
   return node
 }

+ 3 - 1
dolphinscheduler-ui-next/src/views/projects/task/definition/index.tsx

@@ -46,7 +46,8 @@ const TaskDefinition = defineComponent({
     const projectCode = Number(route.params.projectCode)
     const { t } = useI18n()
 
-    const { task, onToggleShow, onTaskSave, onEditTask } = useTask(projectCode)
+    const { task, onToggleShow, onTaskSave, onEditTask, onInitTask } =
+      useTask(projectCode)
 
     const { variables, getTableData, createColumns } = useTable(onEditTask)
 
@@ -80,6 +81,7 @@ const TaskDefinition = defineComponent({
     }
     const onTaskCancel = () => {
       onToggleShow(false)
+      onInitTask()
     }
     const onTaskSubmit = async (params: { data: INodeData }) => {
       const result = await onTaskSave(params.data)

+ 24 - 8
dolphinscheduler-ui-next/src/views/projects/task/definition/use-task.ts

@@ -26,19 +26,26 @@ import { formatParams as formatData } from '../components/node/format-data'
 import type { ITaskData, INodeData, ISingleSaveReq, IRecord } from './types'
 
 export function useTask(projectCode: number) {
+  const initalTask = {
+    taskType: 'SHELL'
+  } as ITaskData
   const task = reactive({
     taskShow: false,
-    taskData: {
-      taskType: 'SHELL'
-    },
+    taskData: { ...initalTask },
     taskSaving: false,
     taskReadonly: false
   } as { taskShow: boolean; taskData: ITaskData; taskSaving: boolean; taskReadonly: boolean })
 
-  const formatParams = (data: INodeData): ISingleSaveReq => {
+  const formatParams = (data: INodeData, isCreate: boolean): ISingleSaveReq => {
     const params = formatData(data)
+    if (isCreate) {
+      return {
+        processDefinitionCode: params.processDefinitionCode,
+        upstreamCodes: params.upstreamCodes,
+        taskDefinitionJsonObj: JSON.stringify(params.taskDefinitionJsonObj)
+      }
+    }
     return {
-      processDefinitionCode: params.processDefinitionCode,
       upstreamCodes: params.upstreamCodes,
       taskDefinitionJsonObj: JSON.stringify(params.taskDefinitionJsonObj)
     }
@@ -61,11 +68,14 @@ export function useTask(projectCode: number) {
           (await updateWithUpstream(
             projectCode,
             data.code,
-            formatParams({ ...data, code: data.code })
+            formatParams({ ...data, code: data.code }, false)
           ))
       } else {
         const taskCode = await getTaskCode()
-        await saveSingle(projectCode, formatParams({ ...data, code: taskCode }))
+        await saveSingle(
+          projectCode,
+          formatParams({ ...data, code: taskCode }, true)
+        )
       }
 
       task.taskSaving = false
@@ -88,10 +98,16 @@ export function useTask(projectCode: number) {
     }
   }
 
+  const onInitTask = () => {
+    task.taskData = { ...initalTask }
+    task.taskReadonly = false
+  }
+
   return {
     task,
     onToggleShow,
     onTaskSave,
-    onEditTask
+    onEditTask,
+    onInitTask
   }
 }