Quellcode durchsuchen

[Feature][UI Next] Add front-end for Apache Zeppelin task plugin (#9597) (#9810)

* [Feature][UI Next] Add front-end for Apache Zeppelin task plugin (#9597)

* Fix minor bugs of zeppelin server endpoint in common.properties

* Fix several bugs in zeppelin task plugin front-end

* add noteId and paragraphId into ITaskParams

* Fix bug in tasks/use-zeppelin.ts
Eric Gao vor 3 Jahren
Ursprung
Commit
bbf6c4ed62

+ 1 - 1
dolphinscheduler-common/src/main/resources/common.properties

@@ -92,4 +92,4 @@ development.state=false
 alert.rpc.port=50052
 
 # Url endpoint for zeppelin RESTful API
-zeppelin.rest.url="http://localhost:8080"
+zeppelin.rest.url=http://localhost:8080

BIN
dolphinscheduler-ui-next/public/images/task-icons/zeppelin.png


BIN
dolphinscheduler-ui-next/public/images/task-icons/zeppelin_hover.png


+ 4 - 0
dolphinscheduler-ui-next/src/locales/modules/en_US.ts

@@ -920,6 +920,10 @@ const project = {
     required: 'required',
     emr_flow_define_json: 'jobFlowDefineJson',
     emr_flow_define_json_tips: 'Please enter the definition of the job flow.',
+    zeppelin_note_id: 'zeppelinNoteId',
+    zeppelin_note_id_tips: 'Please enter the note id of your zeppelin note',
+    zeppelin_paragraph_id: 'zeppelinParagraphId',
+    zeppelin_paragraph_id_tips: 'Please enter the paragraph id of your zeppelin paragraph',
     send_email: 'Send Email',
     log_display: 'Log display',
     rows_of_result: 'rows of result',

+ 4 - 0
dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts

@@ -909,6 +909,10 @@ const project = {
     required: '必填',
     emr_flow_define_json: 'jobFlowDefineJson',
     emr_flow_define_json_tips: '请输入工作流定义',
+    zeppelin_note_id: 'zeppelin_note_id',
+    zeppelin_note_id_tips: '请输入zeppelin note id',
+    zeppelin_paragraph_id: 'zeppelin_paragraph_id',
+    zeppelin_paragraph_id_tips: '请输入zeppelin paragraph id',
     send_email: '发送邮件',
     log_display: '日志显示',
     rows_of_result: '行查询结果',

+ 1 - 0
dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/index.ts

@@ -61,3 +61,4 @@ export { useDataX } from './use-datax'
 export { useConditions } from './use-conditions'
 export { useDependent } from './use-dependent'
 export { useEmr } from './use-emr'
+export { useZeppelin } from './use-zeppelin'

+ 61 - 0
dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-zeppelin.ts

@@ -0,0 +1,61 @@
+/*
+ * 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 { useI18n } from 'vue-i18n'
+import { useCustomParams } from '.'
+import type { IJsonItem } from '../types'
+
+export function useZeppelin(model: { [field: string]: any }): IJsonItem[] {
+  const { t } = useI18n()
+
+  return [
+    {
+      type: 'input',
+      field: 'zeppelinNoteId',
+      name: t('project.node.zeppelin_note_id'),
+      props: {
+        placeholder: t('project.node.zeppelin_note_id_tips')
+      },
+      validate: {
+        trigger: ['input', 'blur'],
+        required: true,
+        validator(validate: any, value: string) {
+          if (!value) {
+            return new Error(t('project.node.zeppelin_note_id_tips'))
+          }
+        }
+      }
+    },
+    {
+      type: 'input',
+      field: 'zeppelinParagraphId',
+      name: t('project.node.zeppelin_paragraph_id'),
+      props: {
+        placeholder: t('project.node.zeppelin_paragraph_id_tips')
+      },
+      validate: {
+        trigger: ['input', 'blur'],
+        required: true,
+        validator(validate: any, value: string) {
+          if (!value) {
+            return new Error(t('project.node.zeppelin_paragraph_id_tips'))
+          }
+        }
+      }
+    },
+    ...useCustomParams({ model, field: 'localParams', isSimple: false })
+  ]
+}

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

@@ -300,6 +300,12 @@ export function formatParams(data: INodeData): {
     taskParams.type = data.type
     taskParams.jobFlowDefineJson = data.jobFlowDefineJson
   }
+
+  if (data.taskType === 'ZEPPELIN') {
+    taskParams.noteId = data.zeppelinNoteId
+    taskParams.paragraphId = data.zeppelinParagraphId
+  }
+
   if (data.taskType === 'PIGEON') {
     taskParams.targetJobName = data.targetJobName
   }
@@ -500,6 +506,14 @@ export function formatModel(data: ITaskData) {
     params.jobFlowDefineJson = data.taskParams.jobFlowDefineJson
   }
 
+  if (data.taskParams?.zeppelinNoteId) {
+    params.zeppelinNoteId = data.taskParams.zeppelinNoteId
+  }
+
+  if (data.taskParams?.zeppelinParagraphId) {
+    params.zeppelinParagraphId = data.taskParams.zeppelinParagraphId
+  }
+
   if (data.taskParams?.processDefinitionCode) {
     params.processDefinitionCode = data.taskParams.processDefinitionCode
   }

+ 3 - 1
dolphinscheduler-ui-next/src/views/projects/task/components/node/tasks/index.ts

@@ -33,6 +33,7 @@ import { useDataX } from './use-datax'
 import { useDependent } from './use-dependent'
 import { useDataQuality } from './use-data-quality'
 import { useEmr } from './use-emr'
+import { useZeppelin } from './use-zeppelin'
 
 export default {
   SHELL: useShell,
@@ -52,5 +53,6 @@ export default {
   DATAX: useDataX,
   DEPENDENT: useDependent,
   DATA_QUALITY: useDataQuality,
-  EMR: useEmr
+  EMR: useEmr,
+  ZEPPELIN: useZeppelin
 }

+ 80 - 0
dolphinscheduler-ui-next/src/views/projects/task/components/node/tasks/use-zeppelin.ts

@@ -0,0 +1,80 @@
+/*
+ * 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 { reactive } from 'vue'
+import * as Fields from '../fields/index'
+import type { IJsonItem, INodeData, ITaskData  } from '../types'
+
+export function useZeppelin({
+  projectCode,
+  from = 0,
+  readonly,
+  data
+}: {
+  projectCode: number
+  from?: number
+  readonly?: boolean
+  data?: ITaskData
+}) {
+  const model = reactive({
+    name: '',
+    taskType: 'ZEPPELIN',
+    flag: 'YES',
+    description: '',
+    timeoutFlag: false,
+    localParams: [],
+    environmentCode: null,
+    failRetryInterval: 1,
+    failRetryTimes: 0,
+    workerGroup: 'default',
+    delayTime: 0,
+    timeout: 30
+  } as INodeData)
+
+  let extra: IJsonItem[] = []
+  if (from === 1) {
+    extra = [
+      Fields.useTaskType(model, readonly),
+      Fields.useProcessName({
+        model,
+        projectCode,
+        isCreate: !data?.id,
+        from,
+        processName: data?.processName
+      })
+    ]
+  }
+
+  return {
+    json: [
+      Fields.useName(from),
+      ...extra,
+      Fields.useRunFlag(),
+      Fields.useDescription(),
+      Fields.useTaskPriority(),
+      Fields.useWorkerGroup(),
+      Fields.useEnvironmentName(model, !model.id),
+      ...Fields.useTaskGroup(model, projectCode),
+      ...Fields.useFailed(),
+      Fields.useDelayTime(model),
+      ...Fields.useTimeoutAlarm(model),
+      ...Fields.useZeppelin(model),
+      Fields.usePreTasks()
+    ] as IJsonItem[],
+    model
+  }
+}

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

@@ -280,6 +280,10 @@ interface ITaskParams {
   ruleId?: number
   ruleInputParameter?: IRuleParameters
   jobFlowDefineJson?: string
+  zeppelinNoteId?: string
+  zeppelinParagraphId?: string
+  noteId?: string
+  paragraphId?: string
   processDefinitionCode?: number
   conditionResult?: {
     successNode?: number[]

+ 5 - 0
dolphinscheduler-ui-next/src/views/projects/task/constants/task-type.ts

@@ -33,6 +33,7 @@ export type TaskType =
   | 'SWITCH'
   | 'SEATUNNEL'
   | 'EMR'
+  | 'ZEPPELIN'
 
 export const TASK_TYPES_MAP = {
   SHELL: {
@@ -93,5 +94,9 @@ export const TASK_TYPES_MAP = {
   EMR: {
     alias: 'AmazonEMR',
     helperLinkDisable: true
+  },
+  ZEPPELIN: {
+    alias: 'ZEPPELIN',
+    helperLinkDisable: true
   }
 } as { [key in TaskType]: { alias: string; helperLinkDisable?: boolean } }

+ 6 - 0
dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag.module.scss

@@ -155,6 +155,9 @@ $bgLight: #ffffff;
     &.icon-emr {
       background-image: url('/images/task-icons/emr.png');
     }
+    &.icon-zeppelin {
+      background-image: url('/images/task-icons/zeppelin.png');
+    }
   }
 
   &:hover {
@@ -213,6 +216,9 @@ $bgLight: #ffffff;
       &.icon-emr {
         background-image: url('/images/task-icons/emr_hover.png');
       }
+      &.icon-zeppelin {
+        background-image: url('/images/task-icons/zeppelin_hover.png');
+      }
     }
   }
 }