Browse Source

[Feature][UI Next] Add SHELL into project(#8339)

3.0.0/version-upgrade
Amy0104 3 years ago committed by GitHub
parent
commit
4c5a90987b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 45
      dolphinscheduler-ui-next/src/components/form/fields/checkbox.ts
  2. 68
      dolphinscheduler-ui-next/src/components/form/fields/custom-parameters.ts
  3. 2
      dolphinscheduler-ui-next/src/components/form/fields/index.ts
  4. 12
      dolphinscheduler-ui-next/src/components/form/fields/input-number.ts
  5. 33
      dolphinscheduler-ui-next/src/components/form/fields/tree-select.ts
  6. 9
      dolphinscheduler-ui-next/src/components/form/get-elements-by-json.ts
  7. 8
      dolphinscheduler-ui-next/src/components/form/index.tsx
  8. 16
      dolphinscheduler-ui-next/src/components/form/types.ts
  9. 3
      dolphinscheduler-ui-next/src/components/modal/index.module.scss
  10. 6
      dolphinscheduler-ui-next/src/components/modal/index.tsx
  11. 19
      dolphinscheduler-ui-next/src/components/monaco-editor/index.tsx
  12. 61
      dolphinscheduler-ui-next/src/locales/modules/en_US.ts
  13. 56
      dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts
  14. 2
      dolphinscheduler-ui-next/src/service/modules/task-group/types.ts
  15. 81
      dolphinscheduler-ui-next/src/views/projects/node/detail-modal.tsx
  16. 73
      dolphinscheduler-ui-next/src/views/projects/node/detail.tsx
  17. 29
      dolphinscheduler-ui-next/src/views/projects/node/fields/index.ts
  18. 31
      dolphinscheduler-ui-next/src/views/projects/node/fields/use-delay-time.ts
  19. 32
      dolphinscheduler-ui-next/src/views/projects/node/fields/use-description.ts
  20. 94
      dolphinscheduler-ui-next/src/views/projects/node/fields/use-environment-name.ts
  21. 42
      dolphinscheduler-ui-next/src/views/projects/node/fields/use-failed.ts
  22. 36
      dolphinscheduler-ui-next/src/views/projects/node/fields/use-name.ts
  23. 41
      dolphinscheduler-ui-next/src/views/projects/node/fields/use-pre-tasks.ts
  24. 38
      dolphinscheduler-ui-next/src/views/projects/node/fields/use-run-flag.ts
  25. 191
      dolphinscheduler-ui-next/src/views/projects/node/fields/use-shell.ts
  26. 85
      dolphinscheduler-ui-next/src/views/projects/node/fields/use-task-group.ts
  27. 92
      dolphinscheduler-ui-next/src/views/projects/node/fields/use-task-priority.ts
  28. 86
      dolphinscheduler-ui-next/src/views/projects/node/fields/use-timeout-alarm.ts
  29. 59
      dolphinscheduler-ui-next/src/views/projects/node/fields/use-worker-group.ts
  30. 16
      dolphinscheduler-ui-next/src/views/projects/node/tasks/index.ts
  31. 65
      dolphinscheduler-ui-next/src/views/projects/node/tasks/use-shell.ts
  32. 104
      dolphinscheduler-ui-next/src/views/projects/node/types.ts
  33. 84
      dolphinscheduler-ui-next/src/views/projects/node/use-data.ts
  34. 33
      dolphinscheduler-ui-next/src/views/projects/node/use-detail.ts
  35. 32
      dolphinscheduler-ui-next/src/views/projects/node/use-task.ts

45
dolphinscheduler-ui-next/src/components/form/fields/checkbox.ts

@ -0,0 +1,45 @@
/*
* 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 { h } from 'vue'
import { NCheckbox, NCheckboxGroup, NSpace } from 'naive-ui'
import type { IJsonItem } from '../types'
export function renderCheckbox(
item: IJsonItem,
fields: { [field: string]: any }
) {
const { props, field, options } = item
if (!options || options.length === 0) {
return h(NCheckbox, {
...props,
value: fields[field],
onUpdateChecked: (checked: boolean) => void (fields[field] = checked)
})
}
return h(
NCheckboxGroup,
{
value: fields[field],
onUpdateValue: (value) => void (fields[field] = value)
},
() =>
h(NSpace, null, () =>
options.map((option: object) => h(NCheckbox, { ...option }))
)
)
}

68
dolphinscheduler-ui-next/src/components/form/fields/custom-parameters.ts

@ -15,13 +15,48 @@
* limitations under the License. * limitations under the License.
*/ */
import { h } from 'vue' import { defineComponent, h, renderSlot } from 'vue'
import { NFormItem, NSpace, NButton, NIcon } from 'naive-ui' import { useFormItem } from 'naive-ui/es/_mixins'
import { NFormItemGi, NSpace, NButton, NIcon, NGrid } from 'naive-ui'
import { PlusCircleOutlined, DeleteOutlined } from '@vicons/antd' import { PlusCircleOutlined, DeleteOutlined } from '@vicons/antd'
import { omit } from 'lodash'
import getField from './get-field' import getField from './get-field'
import { formatValidate } from '../utils' import { formatValidate } from '../utils'
import type { IJsonItem, FormItemRule } from '../types' import type { IJsonItem, FormItemRule } from '../types'
const CustomParameters = defineComponent({
name: 'CustomParameters',
emits: ['add'],
setup(props, ctx) {
const formItem = useFormItem({})
const onAdd = () => void ctx.emit('add')
return { onAdd, disabled: formItem.mergedDisabledRef }
},
render() {
const { disabled, $slots, onAdd } = this
return h(NSpace, null, {
default: () => {
return [
renderSlot($slots, 'default', { disabled }),
h(
NButton,
{
tertiary: true,
circle: true,
type: 'info',
disabled,
onClick: onAdd
},
() => h(NIcon, { size: 24 }, () => h(PlusCircleOutlined))
)
]
}
})
}
})
export function renderCustomParameters( export function renderCustomParameters(
item: IJsonItem, item: IJsonItem,
fields: { [field: string]: any }, fields: { [field: string]: any },
@ -30,6 +65,7 @@ export function renderCustomParameters(
const { field, children = [] } = item const { field, children = [] } = item
let defaultValue: { [field: string]: any } = {} let defaultValue: { [field: string]: any } = {}
let ruleItem: { [key: string]: FormItemRule } = {} let ruleItem: { [key: string]: FormItemRule } = {}
children.forEach((child) => { children.forEach((child) => {
defaultValue[child.field] = child.value || null defaultValue[child.field] = child.value || null
if (child.validate) ruleItem[child.field] = formatValidate(child.validate) if (child.validate) ruleItem[child.field] = formatValidate(child.validate)
@ -37,18 +73,19 @@ export function renderCustomParameters(
const getChild = (item: object, i: number) => const getChild = (item: object, i: number) =>
children.map((child: IJsonItem) => { children.map((child: IJsonItem) => {
return h( return h(
NFormItem, NFormItemGi,
{ {
showLabel: false, showLabel: false,
path: `${field}[${i}].${child.field}` ...omit(item, ['field', 'type', 'props', 'options']),
path: `${field}[${i}].${child.field}`,
span: 6
}, },
() => getField(child, item) () => getField(child, item)
) )
}) })
const getChildren = ({ disabled }: { disabled: boolean }) =>
const getChildren = () =>
fields[field].map((item: object, i: number) => { fields[field].map((item: object, i: number) => {
return h(NSpace, { ':key': i }, () => [ return h(NGrid, { xGap: 10 }, () => [
...getChild(item, i), ...getChild(item, i),
h( h(
NButton, NButton,
@ -56,6 +93,7 @@ export function renderCustomParameters(
tertiary: true, tertiary: true,
circle: true, circle: true,
type: 'error', type: 'error',
disabled,
onClick: () => { onClick: () => {
fields[field].splice(i, 1) fields[field].splice(i, 1)
rules.splice(i, 1) rules.splice(i, 1)
@ -66,20 +104,16 @@ export function renderCustomParameters(
]) ])
}) })
return h(NSpace, null, () => [ return h(
...getChildren(), CustomParameters,
h(
NButton,
{ {
tertiary: true, onAdd: () => {
circle: true,
type: 'info',
onClick: () => {
rules.push(ruleItem) rules.push(ruleItem)
fields[field].push({ ...defaultValue }) fields[field].push({ ...defaultValue })
} }
}, },
() => h(NIcon, { size: 24 }, () => h(PlusCircleOutlined)) {
default: getChildren
}
) )
])
} }

2
dolphinscheduler-ui-next/src/components/form/fields/index.ts

@ -22,3 +22,5 @@ export { renderCustomParameters } from './custom-parameters'
export { renderSwitch } from './switch' export { renderSwitch } from './switch'
export { renderInputNumber } from './input-number' export { renderInputNumber } from './input-number'
export { renderSelect } from './select' export { renderSelect } from './select'
export { renderCheckbox } from './checkbox'
export { renderTreeSelect } from './tree-select'

12
dolphinscheduler-ui-next/src/components/form/fields/input-number.ts

@ -23,11 +23,17 @@ export function renderInputNumber(
item: IJsonItem, item: IJsonItem,
fields: { [field: string]: any } fields: { [field: string]: any }
) { ) {
const { props, field } = item const { props, field, slots = {} } = item
return h(NInputNumber, { return h(
NInputNumber,
{
...props, ...props,
value: fields[field], value: fields[field],
onUpdateValue: (value) => void (fields[field] = value) onUpdateValue: (value) => void (fields[field] = value)
}) },
{
...slots
}
)
} }

33
dolphinscheduler-ui-next/src/components/form/fields/tree-select.ts

@ -0,0 +1,33 @@
/*
* 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 { h } from 'vue'
import { NTreeSelect } from 'naive-ui'
import type { IJsonItem } from '../types'
export function renderTreeSelect(
item: IJsonItem,
fields: { [field: string]: any }
) {
const { props = {}, field, options = [] } = item
return h(NTreeSelect, {
...props,
value: fields[field],
onUpdateValue: (value) => void (fields[field] = value),
options
})
}

9
dolphinscheduler-ui-next/src/components/form/get-elements-by-json.ts

@ -15,6 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { toRef } from 'vue'
import { formatValidate } from './utils' import { formatValidate } from './utils'
import getField from './fields/get-field' import getField from './fields/get-field'
import { omit } from 'lodash' import { omit } from 'lodash'
@ -29,18 +30,20 @@ export default function getElementByJson(
const initialValues: { [field: string]: any } = {} const initialValues: { [field: string]: any } = {}
const elements = [] const elements = []
for (let item of json) { for (let item of json) {
const { name, value, field, children, validate, ...rest } = item const { name, value, field, span, children, validate, ...rest } = item
if (value) { if (value || value === 0) {
fields[field] = value fields[field] = value
initialValues[field] = value initialValues[field] = value
} }
if (validate) rules[field] = formatValidate(validate) if (validate) rules[field] = formatValidate(validate)
const spanRef = span === void 0 ? 24 : toRef(item, 'span')
elements.push({ elements.push({
showLabel: !!name, showLabel: !!name,
...omit(rest, ['type', 'props', 'options']), ...omit(rest, ['type', 'props', 'options']),
label: name, label: name,
path: !children ? field : '', path: !children ? field : '',
widget: () => getField(item, fields, rules) widget: () => getField(item, fields, rules),
span: spanRef
}) })
} }
return { rules, elements, initialValues } return { rules, elements, initialValues }

8
dolphinscheduler-ui-next/src/components/form/index.tsx

@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, PropType, toRefs, h } from 'vue' import { defineComponent, PropType, toRefs, h, toRef, isRef } from 'vue'
import { NSpin, NGrid, NForm, NFormItemGi } from 'naive-ui' import { NSpin, NGrid, NForm, NFormItemGi } from 'naive-ui'
import { useForm } from './use-form' import { useForm } from './use-form'
import type { GridProps, IMeta } from './types' import type { GridProps, IMeta } from './types'
@ -55,7 +55,11 @@ const Form = defineComponent({
{elements.map((element) => { {elements.map((element) => {
const { span = 24, path, widget, ...formItemProps } = element const { span = 24, path, widget, ...formItemProps } = element
return ( return (
<NFormItemGi {...formItemProps} span={span} path={path}> <NFormItemGi
{...formItemProps}
span={isRef(span) ? span.value : span}
path={path}
>
{h(widget)} {h(widget)}
</NFormItemGi> </NFormItemGi>
) )

16
dolphinscheduler-ui-next/src/components/form/types.ts

@ -14,14 +14,15 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { Ref } from 'vue'
import type { import type {
GridProps, GridProps,
FormProps, FormProps,
FormItemGiProps, FormItemGiProps,
FormItemRule, FormItemRule,
FormRules, FormRules,
SelectOption SelectOption,
TreeSelectOption
} from 'naive-ui' } from 'naive-ui'
type IType = type IType =
@ -32,11 +33,16 @@ type IType =
| 'switch' | 'switch'
| 'input-number' | 'input-number'
| 'select' | 'select'
| 'checkbox'
| 'tree-select'
type IOption = SelectOption interface IOption extends SelectOption, TreeSelectOption {
label: string
}
interface IFormItem extends FormItemGiProps { interface IFormItem extends Omit<FormItemGiProps, 'span'> {
widget: any widget: any
span?: any
} }
interface IMeta extends Omit<FormProps, 'model'> { interface IMeta extends Omit<FormProps, 'model'> {
@ -54,6 +60,8 @@ interface IJsonItem {
value?: any value?: any
options?: IOption[] options?: IOption[]
children?: IJsonItem[] children?: IJsonItem[]
slots?: object
span?: number | Ref<number>
} }
export { export {

3
dolphinscheduler-ui-next/src/components/modal/index.module.scss

@ -18,3 +18,6 @@
.container { .container {
width: 600px; width: 600px;
} }
.modal-card {
max-height: 100vh;
}

6
dolphinscheduler-ui-next/src/components/modal/index.tsx

@ -81,7 +81,11 @@ const Modal = defineComponent({
mask-closable={false} mask-closable={false}
auto-focus={this.autoFocus} auto-focus={this.autoFocus}
> >
<NCard title={this.title}> <NCard
title={this.title}
class={styles['modal-card']}
contentStyle={{ overflowY: 'auto' }}
>
{{ {{
default: () => renderSlot($slots, 'default'), default: () => renderSlot($slots, 'default'),
footer: () => ( footer: () => (

19
dolphinscheduler-ui-next/src/components/monaco-editor/index.tsx

@ -98,17 +98,30 @@ export default defineComponent({
} }
} }
) )
watch(
() => formItem.mergedDisabledRef.value,
(value) => {
editor?.updateOptions({ readOnly: value })
}
)
onMounted(async () => { onMounted(async () => {
await nextTick() await nextTick()
const dom = editorRef.value const dom = editorRef.value
if (dom) { if (dom) {
editor = monaco.editor.create(dom, props.options, { editor = monaco.editor.create(
dom,
{
...props.options,
readOnly:
formItem.mergedDisabledRef.value || props.options?.readOnly
},
{
value: props.defaultValue ?? props.value, value: props.defaultValue ?? props.value,
language: props.language, language: props.language,
readOnly: props.readOnly,
automaticLayout: true automaticLayout: true
}) }
)
editor.onDidChangeModelContent(() => { editor.onDidChangeModelContent(() => {
const { onUpdateValue, 'onUpdate:value': _onUpdateValue } = props const { onUpdateValue, 'onUpdate:value': _onUpdateValue } = props
const value = editor?.getValue() || '' const value = editor?.getValue() || ''

61
dolphinscheduler-ui-next/src/locales/modules/en_US.ts

@ -497,6 +497,67 @@ const project = {
rows: 'Rows', rows: 'Rows',
cols: 'Cols', cols: 'Cols',
copy_success: 'Copy Success' copy_success: 'Copy Success'
},
node: {
current_node_settings: 'Current node settings',
instructions: 'Instructions',
view_history: 'View history',
view_log: 'View log',
enter_this_child_node: 'Enter this child node',
name: 'Node name',
name_tips: 'Please enter name (required)',
task_type: 'Task Type',
task_type_tips: 'Please select a task type (required)',
process_name: 'Process Name',
run_flag: 'Run flag',
normal: 'Normal',
prohibition_execution: 'Prohibition execution',
description: 'Description',
description_tips: 'Please enter description',
task_priority: 'Task priority',
worker_group: 'Worker group',
worker_group_tips:
'The Worker group no longer exists, please select the correct Worker group!',
environment_name: 'Environment Name',
task_group_name: 'Task group name',
task_group_queue_priority: 'Priority',
number_of_failed_retries: 'Number of failed retries',
times: 'Times',
failed_retry_interval: 'Failed retry interval',
minute: 'Minute',
delay_execution_time: 'Delay execution time',
state: 'State',
branch_flow: 'Branch flow',
cancel: 'Cancel',
loading: 'Loading...',
confirm: 'Confirm',
success: 'Success',
failed: 'Failed',
backfill_tips:
'The newly created sub-Process has not yet been executed and cannot enter the sub-Process',
task_instance_tips:
'The task has not been executed and cannot enter the sub-Process',
branch_tips:
'Cannot select the same node for successful branch flow and failed branch flow',
timeout_alarm: 'Timeout alarm',
timeout_strategy: 'Timeout strategy',
timeout_strategy_tips: 'Timeout strategy must be selected',
timeout_failure: 'Timeout failure',
timeout_period: 'Timeout period',
timeout_period_tips: 'Timeout must be a positive integer',
script: 'Script',
script_tips: 'Please enter script(required)',
resources: 'Resources',
resources_tips: 'Please select resources',
non_resources_tips: 'Please delete all non-existent resources',
useless_resources_tips: 'Unauthorized or deleted resources',
custom_parameters: 'Custom Parameters',
copy_success: 'Copy success',
copy_failed: 'The browser does not support automatic copying',
prop_tips: 'prop(required)',
prop_repeat: 'prop is repeat',
value_tips: 'value(optional)',
pre_tasks: 'Pre tasks'
} }
} }

56
dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts

@ -496,6 +496,62 @@ const project = {
rows: '行数', rows: '行数',
cols: '列数', cols: '列数',
copy_success: '复制成功' copy_success: '复制成功'
},
node: {
current_node_settings: '当前节点设置',
instructions: '使用说明',
view_history: '查看历史',
view_log: '查看日志',
enter_this_child_node: '进入该子节点',
name: '节点名称',
name_tips: '请输入名称(必填)',
task_type: '任务类型',
task_type_tips: '请选择任务类型(必选)',
process_name: '工作流名称',
run_flag: '运行标志',
normal: '正常',
prohibition_execution: '禁止执行',
description: '描述',
description_tips: '请输入描述',
task_priority: '任务优先级',
worker_group: 'Worker分组',
worker_group_tips: '该Worker分组已经不存在,请选择正确的Worker分组!',
environment_name: '环境名称',
task_group_name: '任务组名称',
task_group_queue_priority: '组内优先级',
number_of_failed_retries: '失败重试次数',
times: '次',
failed_retry_interval: '失败重试间隔',
minute: '分',
delay_execution_time: '延时执行时间',
state: '状态',
branch_flow: '分支流转',
cancel: '取消',
loading: '正在努力加载中...',
confirm: '确定',
success: '成功',
failed: '失败',
backfill_tips: '新创建子工作流还未执行,不能进入子工作流',
task_instance_tips: '该任务还未执行,不能进入子工作流',
branch_tips: '成功分支流转和失败分支流转不能选择同一个节点',
timeout_alarm: '超时告警',
timeout_strategy: '超时策略',
timeout_strategy_tips: '超时策略必须选一个',
timeout_failure: '超时失败',
timeout_period: '超时时长',
timeout_period_tips: '超时时长必须为正整数',
script: '脚本',
script_tips: '请输入脚本(必填)',
resources: '资源',
resources_tips: '请选择资源',
no_resources_tips: '请删除所有未授权或已删除资源',
useless_resources_tips: '未授权或已删除资源',
custom_parameters: '自定义参数',
copy_failed: '该浏览器不支持自动复制',
prop_tips: 'prop(必填)',
prop_repeat: 'prop中有重复',
value_tips: 'value(选填)',
pre_tasks: '前置任务'
} }
} }

2
dolphinscheduler-ui-next/src/service/modules/task-group/types.ts

@ -18,7 +18,7 @@
interface ListReq { interface ListReq {
pageNo: number pageNo: number
pageSize: number pageSize: number
searchVal?: string projectCode?: number
} }
interface TaskGroupIdReq { interface TaskGroupIdReq {

81
dolphinscheduler-ui-next/src/views/projects/node/detail-modal.tsx

@ -0,0 +1,81 @@
/*
* 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 { defineComponent, PropType, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import Modal from '@/components/modal'
import Detail from './detail'
import type { IDataNode, ITask } from './types'
const props = {
show: {
type: Boolean as PropType<boolean>,
default: false
},
nodeData: {
type: Object as PropType<IDataNode>,
default: {
taskType: 'SHELL'
}
},
type: {
type: String as PropType<string>,
default: ''
},
taskDefinition: {
type: Object as PropType<ITask>
}
}
const NodeDetailModal = defineComponent({
name: 'NodeDetailModal',
props,
emits: ['cancel', 'update'],
setup(props, { emit }) {
const { t } = useI18n()
const detailRef = ref()
const onConfirm = () => {
detailRef.value.onSubmit()
}
const onCancel = () => {
emit('cancel')
}
return {
t,
detailRef,
onConfirm,
onCancel
}
},
render() {
const { t, show, onConfirm, onCancel } = this
return (
<Modal
show={show}
title={`${t('project.node.current_node_settings')}`}
onConfirm={onConfirm}
confirmLoading={false}
onCancel={() => void onCancel()}
>
<Detail ref='detailRef' taskType='SHELL' projectCode={111} />
</Modal>
)
}
})
export default NodeDetailModal

73
dolphinscheduler-ui-next/src/views/projects/node/detail.tsx

@ -0,0 +1,73 @@
/*
* 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 { defineComponent, PropType, ref, toRefs } from 'vue'
import Form from '@/components/form'
import { useTask } from './use-task'
import { useDetail } from './use-detail'
import type { ITaskType } from './types'
import getElementByJson from '@/components/form/get-elements-by-json'
const props = {
projectCode: {
type: Number as PropType<number>
},
taskType: {
type: String as PropType<ITaskType>,
default: 'SHELL',
required: true
}
}
const NodeDetail = defineComponent({
name: 'NodeDetail',
props,
setup(props, { expose }) {
const { taskType, projectCode } = props
const { json, model } = useTask({ taskType, projectCode })
const { state, onSubmit } = useDetail()
const jsonRef = ref(json)
const { rules, elements } = getElementByJson(jsonRef.value, model)
expose({
onSubmit: () => void onSubmit(model)
})
return { rules, elements, model, ...toRefs(state) }
},
render() {
const { rules, elements, model } = this
return (
<Form
ref='formRef'
meta={{
model,
rules,
elements
}}
layout={{
xGap: 10
}}
></Form>
)
}
})
export default NodeDetail

29
dolphinscheduler-ui-next/src/views/projects/node/fields/index.ts

@ -0,0 +1,29 @@
/*
* 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.
*/
export { useName } from './use-name'
export { useRunFlag } from './use-run-flag'
export { useDescription } from './use-description'
export { useTaskPriority } from './use-task-priority'
export { useWorkerGroup } from './use-worker-group'
export { useEnvironmentName } from './use-environment-name'
export { useTaskGroup } from './use-task-group'
export { useFailed } from './use-failed'
export { useDelayTime } from './use-delay-time'
export { useTimeoutAlarm } from './use-timeout-alarm'
export { usePreTasks } from './use-pre-tasks'
export { useShell } from './use-shell'

31
dolphinscheduler-ui-next/src/views/projects/node/fields/use-delay-time.ts

@ -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.
*/
import { useI18n } from 'vue-i18n'
export function useDelayTime() {
const { t } = useI18n()
return {
type: 'input-number',
field: 'delayTime',
name: t('project.node.delay_execution_time'),
span: 12,
slots: {
suffix: () => t('project.node.minute')
}
}
}

32
dolphinscheduler-ui-next/src/views/projects/node/fields/use-description.ts

@ -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.
*/
import { useI18n } from 'vue-i18n'
export function useDescription() {
const { t } = useI18n()
return {
type: 'input',
field: 'desc',
name: t('project.node.description'),
props: {
placeholder: t('project.node.description_tips'),
rows: 2,
type: 'textarea'
}
}
}

94
dolphinscheduler-ui-next/src/views/projects/node/fields/use-environment-name.ts

@ -0,0 +1,94 @@
/*
* 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 { ref, reactive, onMounted, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { queryAllEnvironmentList } from '@/service/modules/environment'
import type { IEnvironmentNameOption } from '../types'
export function useEnvironmentName(
model: { [field: string]: any },
isCreate: boolean
) {
const { t } = useI18n()
let environmentList = [] as IEnvironmentNameOption[]
const options = ref([] as IEnvironmentNameOption[])
const loading = ref(false)
const value = ref()
const getEnvironmentList = async () => {
if (loading.value) return
loading.value = true
try {
const res = await queryAllEnvironmentList()
environmentList = res.map((item: { code: string; name: string }) => ({
label: item.name,
value: item.code
}))
options.value = environmentList.filter((option: IEnvironmentNameOption) =>
filterByWorkerGroup(option)
)
loading.value = false
} catch (err) {
loading.value = false
}
}
const filterByWorkerGroup = (option: IEnvironmentNameOption) => {
if (!model.workerGroup) return false
if (!option?.workerGroups?.length) return false
if (option.workerGroups.indexOf(model.workerGroup) === -1) return false
return true
}
watch(
() => options.value.length,
() => {
if (isCreate && options.value.length === 1 && !value.value) {
model.environmentCode = options.value[0].value
}
if (options.value.length === 0) model.environmentCode = null
}
)
watch(
() => model.workerGroup,
() => {
if (!model.workerGroup) return
options.value = environmentList.filter((option: IEnvironmentNameOption) =>
filterByWorkerGroup(option)
)
}
)
onMounted(() => {
getEnvironmentList()
})
return {
type: 'select',
field: 'environmentCode',
span: 12,
name: t('project.node.environment_name'),
props: {
loading: loading,
clearable: true
},
options: options
}
}

42
dolphinscheduler-ui-next/src/views/projects/node/fields/use-failed.ts

@ -0,0 +1,42 @@
/*
* 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'
export function useFailed() {
const { t } = useI18n()
return [
{
type: 'input-number',
field: 'maxRetryTimes',
name: t('project.node.number_of_failed_retries'),
span: 12,
slots: {
suffix: () => t('project.node.times')
}
},
{
type: 'input-number',
field: 'retryInterval',
name: t('project.node.failed_retry_interval'),
span: 12,
slots: {
suffix: () => t('project.node.minute')
}
}
]
}

36
dolphinscheduler-ui-next/src/views/projects/node/fields/use-name.ts

@ -0,0 +1,36 @@
/*
* 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'
export function useName() {
const { t } = useI18n()
return {
type: 'input',
field: 'name',
name: t('project.node.name'),
props: {
placeholder: t('project.node.name_tips'),
maxLength: 100
},
validate: {
trigger: ['input', 'blur'],
required: true,
message: t('project.node.name_tips')
}
}
}

41
dolphinscheduler-ui-next/src/views/projects/node/fields/use-pre-tasks.ts

@ -0,0 +1,41 @@
/*
* 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 { ref, onMounted } from 'vue'
import { useI18n } from 'vue-i18n'
export function usePreTasks() {
const { t } = useI18n()
const options = ref([])
const loading = ref(false)
onMounted(() => {})
return {
type: 'select',
field: 'preTasks',
span: 24,
name: t('project.node.pre_tasks'),
props: {
loading,
multiple: true,
filterable: true
},
options
}
}

38
dolphinscheduler-ui-next/src/views/projects/node/fields/use-run-flag.ts

@ -0,0 +1,38 @@
/*
* 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'
export function useRunFlag() {
const { t } = useI18n()
const options = [
{
label: t('project.node.normal'),
value: 'YES'
},
{
label: t('project.node.prohibition_execution'),
value: 'NO'
}
]
return {
type: 'radio',
field: 'runFlag',
name: t('project.node.run_flag'),
options: options
}
}

191
dolphinscheduler-ui-next/src/views/projects/node/fields/use-shell.ts

@ -0,0 +1,191 @@
/*
* 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 { ref, onMounted } from 'vue'
import { useI18n } from 'vue-i18n'
import { queryResourceList } from '@/service/modules/resources'
export function useShell(model: { [field: string]: any }) {
const { t } = useI18n()
const options = ref([])
const loading = ref(false)
const getResourceList = async () => {
if (loading.value) return
loading.value = true
try {
const res = await queryResourceList({ type: 'FILE' })
removeUselessChildren(res)
options.value = res || []
loading.value = false
} catch (err) {
loading.value = false
}
}
onMounted(() => {
getResourceList()
})
return [
{
type: 'editor',
field: 'shell',
name: t('project.node.script'),
validate: {
trigger: ['input', 'trigger'],
required: true,
message: t('project.node.script_tips')
}
},
{
type: 'tree-select',
field: 'resourceList',
name: t('project.node.resources'),
options,
props: {
multiple: true,
checkable: true,
cascade: true,
showPath: true,
checkStrategy: 'child',
placeholder: t('project.node.resources_tips'),
keyField: 'id',
labelField: 'name',
loading
}
},
{
type: 'custom-parameters',
field: 'localParams',
name: t('project.node.custom_parameters'),
children: [
{
type: 'input',
field: 'prop',
span: 6,
props: {
placeholder: t('project.node.prop_tips'),
maxLength: 256
},
validate: {
trigger: ['input', 'blur'],
required: true,
validator(validate: any, value: string) {
if (!value) {
return new Error(t('project.node.prop_tips'))
}
const sameItems = model.localParams.filter(
(item: { prop: string }) => item.prop === value
)
if (sameItems.length > 1) {
return new Error(t('project.node.prop_repeat'))
}
}
}
},
{
type: 'select',
field: 'direct',
span: 4,
options: DIRECT_LIST,
value: 'IN'
},
{
type: 'select',
field: 'type',
span: 6,
options: TYPE_LIST,
value: 'VARCHAR'
},
{
type: 'input',
field: 'value',
span: 6,
props: {
placeholder: t('project.node.value_tips'),
maxLength: 256
}
}
]
}
]
}
function removeUselessChildren(list: { children?: [] }[]) {
if (!list.length) return
list.forEach((item) => {
if (!item.children) return
if (item.children.length === 0) {
delete item.children
return
}
removeUselessChildren(item.children)
})
}
export const TYPE_LIST = [
{
value: 'VARCHAR',
label: 'VARCHAR'
},
{
value: 'INTEGER',
label: 'INTEGER'
},
{
value: 'LONG',
label: 'LONG'
},
{
value: 'FLOAT',
label: 'FLOAT'
},
{
value: 'DOUBLE',
label: 'DOUBLE'
},
{
value: 'DATE',
label: 'DATE'
},
{
value: 'TIME',
label: 'TIME'
},
{
value: 'TIMESTAMP',
label: 'TIMESTAMP'
},
{
value: 'BOOLEAN',
label: 'BOOLEAN'
}
]
export const DIRECT_LIST = [
{
value: 'IN',
label: 'IN'
},
{
value: 'OUT',
label: 'OUT'
}
]

85
dolphinscheduler-ui-next/src/views/projects/node/fields/use-task-group.ts

@ -0,0 +1,85 @@
/*
* 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 { ref, watch, computed, onMounted } from 'vue'
import { useI18n } from 'vue-i18n'
import { queryTaskGroupListPagingByProjectCode } from '@/service/modules/task-group'
export function useTaskGroup(
model: { [field: string]: any },
projectCode: number
) {
const { t } = useI18n()
const options = ref([])
const loading = ref(false)
const priorityDisabled = computed(() => !model.taskGroupId)
const getTaskGroupList = async () => {
if (loading.value) return
loading.value = true
try {
const { totalList = [] } = await queryTaskGroupListPagingByProjectCode({
pageNo: 1,
pageSize: 2147483647,
projectCode
})
options.value = totalList.map((item: { id: string; name: string }) => ({
label: item.name,
value: item.id
}))
loading.value = false
} catch (err) {
loading.value = false
}
}
onMounted(() => {
getTaskGroupList()
})
watch(
() => model.taskGroupId,
(taskGroupId) => {
if (!taskGroupId) model.taskGroupPriority = 0
}
)
return [
{
type: 'select',
field: 'taskGroupId',
span: 12,
name: t('project.node.task_group_name'),
props: {
loading
},
options
},
{
type: 'input-number',
field: 'taskGroupPriority',
name: t('project.node.task_group_queue_priority'),
props: {
max: Math.pow(10, 60) - 1,
disabled: priorityDisabled
},
span: 12,
value: 0
}
]
}

92
dolphinscheduler-ui-next/src/views/projects/node/fields/use-task-priority.ts

@ -0,0 +1,92 @@
/*
* 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 { h, markRaw, VNode, VNodeChild } from 'vue'
import { NIcon } from 'naive-ui'
import { useI18n } from 'vue-i18n'
import { ArrowUpOutlined, ArrowDownOutlined } from '@vicons/antd'
import type { ITaskPriorityOption } from '../types'
export function useTaskPriority() {
const { t } = useI18n()
const options = markRaw([
{
label: 'HIGHEST',
value: 'HIGHEST',
icon: ArrowUpOutlined,
color: '#ff0000'
},
{
label: 'HIGH',
value: 'HIGH',
icon: ArrowUpOutlined,
color: '#ff0000'
},
{
label: 'MEDIUM',
value: 'MEDIUM',
icon: ArrowUpOutlined,
color: '#EA7D24'
},
{
label: 'LOW',
value: 'LOW',
icon: ArrowDownOutlined,
color: '#2A8734'
},
{
label: 'LOWEST',
value: 'LOWEST',
icon: ArrowDownOutlined,
color: '#2A8734'
}
])
const renderOption = ({
node,
option
}: {
node: VNode
option: ITaskPriorityOption
}): VNodeChild =>
h(node, null, {
default: () => [
h(
NIcon,
{
color: option.color
},
{
default: () => h(option.icon)
}
),
option.label as string
]
})
return {
type: 'select',
field: 'taskInstancePriority',
name: t('project.node.task_priority'),
options,
validate: {
required: true
},
props: {
renderOption
},
value: 'MEDIUM'
}
}

86
dolphinscheduler-ui-next/src/views/projects/node/fields/use-timeout-alarm.ts

@ -0,0 +1,86 @@
/*
* 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 { computed, watch } from 'vue'
import { useI18n } from 'vue-i18n'
export function useTimeoutAlarm(model: { [field: string]: any }) {
const { t } = useI18n()
const span = computed(() => (model.enable ? 12 : 0))
const strategyOptions = [
{
label: t('project.node.timeout_alarm'),
value: 'WARN'
},
{
label: t('project.node.timeout_failure'),
value: 'FAILED'
}
]
watch(
() => model.enable,
(enable) => {
model.strategy = enable ? ['WARN'] : []
model.interval = enable ? 30 : null
}
)
return [
{
type: 'switch',
field: 'enable',
name: t('project.node.timeout_alarm')
},
{
type: 'checkbox',
field: 'strategy',
name: t('project.node.timeout_strategy'),
options: strategyOptions,
span: span,
validate: {
trigger: ['input'],
validator(validate: any, value: []) {
if (model.enable && !value.length) {
return new Error(t('project.node.timeout_strategy_tips'))
}
}
},
value: ['WARN']
},
{
type: 'input-number',
field: 'interval',
name: t('project.node.timeout_period'),
span,
props: {
max: Math.pow(10, 10) - 1
},
slots: {
suffix: () => t('project.node.minute')
},
validate: {
trigger: ['input'],
validator(validate: any, value: number) {
if (model.enable && !/^[1-9]\d*$/.test(String(value))) {
return new Error(t('project.node.timeout_period_tips'))
}
}
}
}
]
}

59
dolphinscheduler-ui-next/src/views/projects/node/fields/use-worker-group.ts

@ -0,0 +1,59 @@
/*
* 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 { ref, onMounted } from 'vue'
import { useI18n } from 'vue-i18n'
import { queryAllWorkerGroups } from '@/service/modules/worker-groups'
export function useWorkerGroup() {
const { t } = useI18n()
const options = ref([] as { label: string; value: string }[])
const loading = ref(false)
const getWorkerGroups = async () => {
if (loading.value) return
loading.value = true
try {
const res = await queryAllWorkerGroups()
options.value = res.map((item: string) => ({ label: item, value: item }))
loading.value = false
} catch (err) {
loading.value = false
}
}
onMounted(() => {
getWorkerGroups()
})
return {
type: 'select',
field: 'workerGroup',
span: 12,
name: t('project.node.worker_group'),
props: {
loading: loading
},
options: options,
validate: {
trigger: ['input', 'blur'],
required: true,
message: t('project.node.worker_group_tips')
},
value: 'default'
}
}

16
dolphinscheduler-ui-next/src/views/projects/node/tasks/index.ts

@ -0,0 +1,16 @@
/*
* 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.
*/

65
dolphinscheduler-ui-next/src/views/projects/node/tasks/use-shell.ts

@ -0,0 +1,65 @@
/*
* 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 { IJsonItem } from '../types'
export function useShell({
isCreate,
projectCode
}: {
isCreate: boolean
projectCode: number
}) {
const model = reactive({
name: '',
runFlag: 'YES',
desc: '',
enable: false,
localParams: [],
environmentCode: null,
workerGroup: 'default'
} as {
name: string
runFlag: string
desc: string
workerGroup: string
taskGroupId: string
enable: boolean
localParams: []
environmentCode: string | null
})
return {
json: [
Fields.useName(),
Fields.useRunFlag(),
Fields.useDescription(),
Fields.useTaskPriority(),
Fields.useWorkerGroup(),
Fields.useEnvironmentName(model, isCreate),
...Fields.useTaskGroup(model, projectCode),
...Fields.useFailed(),
Fields.useDelayTime(),
...Fields.useTimeoutAlarm(model),
...Fields.useShell(model),
Fields.usePreTasks()
] as IJsonItem[],
model
}
}

104
dolphinscheduler-ui-next/src/views/projects/node/types.ts

@ -0,0 +1,104 @@
/*
* 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 { VNode } from 'vue'
import type { SelectOption } from 'naive-ui'
import type { IFormItem, IJsonItem } from '@/components/form/types'
interface ITaskPriorityOption extends SelectOption {
icon: VNode
color: string
}
interface IEnvironmentNameOption {
label: string
value: string
workerGroups?: string[]
}
interface ILocalParam {
prop: string
direct: string
type: string
value?: string
}
interface ITaskParams {
conditionResult?: string
switchResult?: string
delayTime?: string
dependence?: string
waitStartTimeout?: string
}
interface ITimeout {
enable: boolean
timeout?: number
strategy?: string
}
type ITaskType =
| 'SHELL'
| 'SUB_PROCESS'
| 'PROCEDURE'
| 'SQL'
| 'SPARK'
| 'FLINK'
| 'MapReduce'
| 'PYTHON'
| 'DEPENDENT'
| 'HTTP'
| 'DataX'
| 'PIGEON'
| 'SQOOP'
| 'CONDITIONS'
| 'DATA_QUALITY'
| 'SWITCH'
| 'SEATUNNEL'
interface ITask {
code?: string
timeoutNotifyStrategy?: string
taskParams: ITaskParams
description?: string
id: number
delayTime?: number
failRetryTimes?: number
name: string
params?: object
failRetryInterval?: number
flag: string
taskPriority?: number
timeout: ITimeout
timeoutFlag: 'CLOSE' | 'OPEN'
taskType?: ITaskType
workerGroup?: string
environmentCode?: string
taskGroupId?: string
taskGroupPriority?: number
}
interface IDataNode {
id?: string
taskType: ITaskType
}
export {
ITaskPriorityOption,
IEnvironmentNameOption,
ILocalParam,
ITaskType,
ITask,
IDataNode,
IFormItem,
IJsonItem
}

84
dolphinscheduler-ui-next/src/views/projects/node/use-data.ts

@ -0,0 +1,84 @@
/*
* 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 { omit } from 'lodash'
import type { IDataNode, ITask } from './types'
export function useData({
nodeData,
type,
taskDefinition
}: {
nodeData: IDataNode
type: string
taskDefinition?: ITask
}) {
const data = {
backfill: {},
isCreate: false
}
if (type === 'task-definition') {
if (taskDefinition) {
data.backfill = formatBackfill(taskDefinition, nodeData.taskType)
data.isCreate = false
}
} else {
}
return {
code: nodeData.id
}
}
export function formatBackfill(task: ITask, taskType: string) {
let strategy: string | undefined = task.timeoutNotifyStrategy
if (taskType === 'DEPENDENT' && task.timeoutNotifyStrategy === 'WARNFAILED') {
strategy = 'WARN,FAILED'
}
return {
code: task.code,
conditionResult: task.taskParams.conditionResult,
switchResult: task.taskParams.switchResult,
delayTime: task.delayTime,
dependence: task.taskParams.dependence,
desc: task.description,
id: task.id,
maxRetryTimes: task.failRetryTimes,
name: task.name,
params: omit(task.taskParams, [
'conditionResult',
'dependence',
'waitStartTimeout',
'switchResult'
]),
retryInterval: task.failRetryInterval,
runFlag: task.flag,
taskInstancePriority: task.taskPriority,
timeout: {
interval: task.timeout,
strategy,
enable: task.timeoutFlag === 'OPEN'
},
type: task.taskType,
waitStartTimeout: task.taskParams.waitStartTimeout,
workerGroup: task.workerGroup,
environmentCode: task.environmentCode,
taskGroupId: task.taskGroupId,
taskGroupPriority: task.taskGroupPriority
}
}

33
dolphinscheduler-ui-next/src/views/projects/node/use-detail.ts

@ -0,0 +1,33 @@
/*
* 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, ref } from 'vue'
export function useDetail() {
const state = reactive({
formRef: ref(),
loading: false,
saving: false
})
const onSubmit = async (model: object) => {
await state.formRef.validate()
}
return {
state,
onSubmit
}
}

32
dolphinscheduler-ui-next/src/views/projects/node/use-task.ts

@ -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.
*/
import { useShell } from './tasks/use-shell'
import { IJsonItem, ITaskType } from './types'
export function useTask({
taskType,
projectCode
}: {
taskType: ITaskType
projectCode?: number
}): { json: IJsonItem[]; model: object } {
let node = {} as { json: IJsonItem[]; model: object }
if (taskType === 'SHELL' && projectCode) {
node = useShell({ isCreate: true, projectCode: projectCode })
}
return node
}
Loading…
Cancel
Save