[Feature][UI Next] Add SHELL into project(#8339)
parent
60a11ff050
commit
4c5a90987b
|
|
@ -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 }))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -15,13 +15,48 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { h } from 'vue'
|
||||
import { NFormItem, NSpace, NButton, NIcon } from 'naive-ui'
|
||||
import { defineComponent, h, renderSlot } from 'vue'
|
||||
import { useFormItem } from 'naive-ui/es/_mixins'
|
||||
import { NFormItemGi, NSpace, NButton, NIcon, NGrid } from 'naive-ui'
|
||||
import { PlusCircleOutlined, DeleteOutlined } from '@vicons/antd'
|
||||
import { omit } from 'lodash'
|
||||
import getField from './get-field'
|
||||
import { formatValidate } from '../utils'
|
||||
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(
|
||||
item: IJsonItem,
|
||||
fields: { [field: string]: any },
|
||||
|
|
@ -30,6 +65,7 @@ export function renderCustomParameters(
|
|||
const { field, children = [] } = item
|
||||
let defaultValue: { [field: string]: any } = {}
|
||||
let ruleItem: { [key: string]: FormItemRule } = {}
|
||||
|
||||
children.forEach((child) => {
|
||||
defaultValue[child.field] = child.value || null
|
||||
if (child.validate) ruleItem[child.field] = formatValidate(child.validate)
|
||||
|
|
@ -37,18 +73,19 @@ export function renderCustomParameters(
|
|||
const getChild = (item: object, i: number) =>
|
||||
children.map((child: IJsonItem) => {
|
||||
return h(
|
||||
NFormItem,
|
||||
NFormItemGi,
|
||||
{
|
||||
showLabel: false,
|
||||
path: `${field}[${i}].${child.field}`
|
||||
...omit(item, ['field', 'type', 'props', 'options']),
|
||||
path: `${field}[${i}].${child.field}`,
|
||||
span: 6
|
||||
},
|
||||
() => getField(child, item)
|
||||
)
|
||||
})
|
||||
|
||||
const getChildren = () =>
|
||||
const getChildren = ({ disabled }: { disabled: boolean }) =>
|
||||
fields[field].map((item: object, i: number) => {
|
||||
return h(NSpace, { ':key': i }, () => [
|
||||
return h(NGrid, { xGap: 10 }, () => [
|
||||
...getChild(item, i),
|
||||
h(
|
||||
NButton,
|
||||
|
|
@ -56,6 +93,7 @@ export function renderCustomParameters(
|
|||
tertiary: true,
|
||||
circle: true,
|
||||
type: 'error',
|
||||
disabled,
|
||||
onClick: () => {
|
||||
fields[field].splice(i, 1)
|
||||
rules.splice(i, 1)
|
||||
|
|
@ -66,20 +104,16 @@ export function renderCustomParameters(
|
|||
])
|
||||
})
|
||||
|
||||
return h(NSpace, null, () => [
|
||||
...getChildren(),
|
||||
h(
|
||||
NButton,
|
||||
{
|
||||
tertiary: true,
|
||||
circle: true,
|
||||
type: 'info',
|
||||
onClick: () => {
|
||||
rules.push(ruleItem)
|
||||
fields[field].push({ ...defaultValue })
|
||||
}
|
||||
},
|
||||
() => h(NIcon, { size: 24 }, () => h(PlusCircleOutlined))
|
||||
)
|
||||
])
|
||||
return h(
|
||||
CustomParameters,
|
||||
{
|
||||
onAdd: () => {
|
||||
rules.push(ruleItem)
|
||||
fields[field].push({ ...defaultValue })
|
||||
}
|
||||
},
|
||||
{
|
||||
default: getChildren
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,3 +22,5 @@ export { renderCustomParameters } from './custom-parameters'
|
|||
export { renderSwitch } from './switch'
|
||||
export { renderInputNumber } from './input-number'
|
||||
export { renderSelect } from './select'
|
||||
export { renderCheckbox } from './checkbox'
|
||||
export { renderTreeSelect } from './tree-select'
|
||||
|
|
|
|||
|
|
@ -23,11 +23,17 @@ export function renderInputNumber(
|
|||
item: IJsonItem,
|
||||
fields: { [field: string]: any }
|
||||
) {
|
||||
const { props, field } = item
|
||||
const { props, field, slots = {} } = item
|
||||
|
||||
return h(NInputNumber, {
|
||||
...props,
|
||||
value: fields[field],
|
||||
onUpdateValue: (value) => void (fields[field] = value)
|
||||
})
|
||||
return h(
|
||||
NInputNumber,
|
||||
{
|
||||
...props,
|
||||
value: fields[field],
|
||||
onUpdateValue: (value) => void (fields[field] = value)
|
||||
},
|
||||
{
|
||||
...slots
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
})
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { toRef } from 'vue'
|
||||
import { formatValidate } from './utils'
|
||||
import getField from './fields/get-field'
|
||||
import { omit } from 'lodash'
|
||||
|
|
@ -29,18 +30,20 @@ export default function getElementByJson(
|
|||
const initialValues: { [field: string]: any } = {}
|
||||
const elements = []
|
||||
for (let item of json) {
|
||||
const { name, value, field, children, validate, ...rest } = item
|
||||
if (value) {
|
||||
const { name, value, field, span, children, validate, ...rest } = item
|
||||
if (value || value === 0) {
|
||||
fields[field] = value
|
||||
initialValues[field] = value
|
||||
}
|
||||
if (validate) rules[field] = formatValidate(validate)
|
||||
const spanRef = span === void 0 ? 24 : toRef(item, 'span')
|
||||
elements.push({
|
||||
showLabel: !!name,
|
||||
...omit(rest, ['type', 'props', 'options']),
|
||||
label: name,
|
||||
path: !children ? field : '',
|
||||
widget: () => getField(item, fields, rules)
|
||||
widget: () => getField(item, fields, rules),
|
||||
span: spanRef
|
||||
})
|
||||
}
|
||||
return { rules, elements, initialValues }
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* 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 { useForm } from './use-form'
|
||||
import type { GridProps, IMeta } from './types'
|
||||
|
|
@ -55,7 +55,11 @@ const Form = defineComponent({
|
|||
{elements.map((element) => {
|
||||
const { span = 24, path, widget, ...formItemProps } = element
|
||||
return (
|
||||
<NFormItemGi {...formItemProps} span={span} path={path}>
|
||||
<NFormItemGi
|
||||
{...formItemProps}
|
||||
span={isRef(span) ? span.value : span}
|
||||
path={path}
|
||||
>
|
||||
{h(widget)}
|
||||
</NFormItemGi>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -14,14 +14,15 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Ref } from 'vue'
|
||||
import type {
|
||||
GridProps,
|
||||
FormProps,
|
||||
FormItemGiProps,
|
||||
FormItemRule,
|
||||
FormRules,
|
||||
SelectOption
|
||||
SelectOption,
|
||||
TreeSelectOption
|
||||
} from 'naive-ui'
|
||||
|
||||
type IType =
|
||||
|
|
@ -32,11 +33,16 @@ type IType =
|
|||
| 'switch'
|
||||
| 'input-number'
|
||||
| '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
|
||||
span?: any
|
||||
}
|
||||
|
||||
interface IMeta extends Omit<FormProps, 'model'> {
|
||||
|
|
@ -54,6 +60,8 @@ interface IJsonItem {
|
|||
value?: any
|
||||
options?: IOption[]
|
||||
children?: IJsonItem[]
|
||||
slots?: object
|
||||
span?: number | Ref<number>
|
||||
}
|
||||
|
||||
export {
|
||||
|
|
|
|||
|
|
@ -18,3 +18,6 @@
|
|||
.container {
|
||||
width: 600px;
|
||||
}
|
||||
.modal-card {
|
||||
max-height: 100vh;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,11 @@ const Modal = defineComponent({
|
|||
mask-closable={false}
|
||||
auto-focus={this.autoFocus}
|
||||
>
|
||||
<NCard title={this.title}>
|
||||
<NCard
|
||||
title={this.title}
|
||||
class={styles['modal-card']}
|
||||
contentStyle={{ overflowY: 'auto' }}
|
||||
>
|
||||
{{
|
||||
default: () => renderSlot($slots, 'default'),
|
||||
footer: () => (
|
||||
|
|
|
|||
|
|
@ -98,17 +98,30 @@ export default defineComponent({
|
|||
}
|
||||
}
|
||||
)
|
||||
watch(
|
||||
() => formItem.mergedDisabledRef.value,
|
||||
(value) => {
|
||||
editor?.updateOptions({ readOnly: value })
|
||||
}
|
||||
)
|
||||
|
||||
onMounted(async () => {
|
||||
await nextTick()
|
||||
const dom = editorRef.value
|
||||
if (dom) {
|
||||
editor = monaco.editor.create(dom, props.options, {
|
||||
value: props.defaultValue ?? props.value,
|
||||
language: props.language,
|
||||
readOnly: props.readOnly,
|
||||
automaticLayout: true
|
||||
})
|
||||
editor = monaco.editor.create(
|
||||
dom,
|
||||
{
|
||||
...props.options,
|
||||
readOnly:
|
||||
formItem.mergedDisabledRef.value || props.options?.readOnly
|
||||
},
|
||||
{
|
||||
value: props.defaultValue ?? props.value,
|
||||
language: props.language,
|
||||
automaticLayout: true
|
||||
}
|
||||
)
|
||||
editor.onDidChangeModelContent(() => {
|
||||
const { onUpdateValue, 'onUpdate:value': _onUpdateValue } = props
|
||||
const value = editor?.getValue() || ''
|
||||
|
|
|
|||
|
|
@ -497,6 +497,67 @@ const project = {
|
|||
rows: 'Rows',
|
||||
cols: 'Cols',
|
||||
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'
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -496,6 +496,62 @@ const project = {
|
|||
rows: '行数',
|
||||
cols: '列数',
|
||||
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: '前置任务'
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
interface ListReq {
|
||||
pageNo: number
|
||||
pageSize: number
|
||||
searchVal?: string
|
||||
projectCode?: number
|
||||
}
|
||||
|
||||
interface TaskGroupIdReq {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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'
|
||||
|
|
@ -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')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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')
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -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')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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'
|
||||
}
|
||||
]
|
||||
|
|
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -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'
|
||||
}
|
||||
}
|
||||
|
|
@ -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'))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -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'
|
||||
}
|
||||
}
|
||||
|
|
@ -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.
|
||||
*/
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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…
Reference in New Issue