未验证 提交 059650ef 编写于 作者: A Amy0104 提交者: GitHub

[Feature][UI Next] Add DEPENDENT. (#8556)

上级 8ed2eeb8
......@@ -17,13 +17,14 @@
import { h, unref } from 'vue'
import { NCheckbox, NCheckboxGroup, NSpace } from 'naive-ui'
import { isFunction } from 'lodash'
import type { IJsonItem } from '../types'
export function renderCheckbox(
item: IJsonItem,
fields: { [field: string]: any }
) {
const { props, field, options } = item
const { props, field, options } = isFunction(item) ? item() : item
if (!options) {
return h(NCheckbox, {
...props,
......
......@@ -18,6 +18,7 @@
import { defineComponent, h, unref, renderSlot } from 'vue'
import { useFormItem } from 'naive-ui/es/_mixins'
import { NFormItemGi, NSpace, NButton, NGrid, NGridItem } from 'naive-ui'
import { isFunction } from 'lodash'
import { PlusOutlined, DeleteOutlined } from '@vicons/antd'
import getField from './get-field'
import { formatValidate } from '../utils'
......@@ -67,20 +68,21 @@ const getDefaultValue = (children: IJsonItem[]) => {
ruleParent: { [key: string]: FormItemRule[] | FormItemRule }
) => {
children.forEach((child) => {
if (Array.isArray(child.children)) {
const mergedChild = isFunction(child) ? child() : child
if (Array.isArray(mergedChild.children)) {
const childDefaultValue = {}
const childRuleItem = {}
loop(child.children, childDefaultValue, childRuleItem)
parent[child.field] = [childDefaultValue]
ruleParent[child.field] = {
loop(mergedChild.children, childDefaultValue, childRuleItem)
parent[mergedChild.field] = [childDefaultValue]
ruleParent[mergedChild.field] = {
type: 'array',
fields: childRuleItem
}
return
} else {
parent[child.field] = child.value || null
if (child.validate)
ruleParent[child.field] = formatValidate(child.validate)
parent[mergedChild.field] = mergedChild.value || null
if (mergedChild.validate)
ruleParent[mergedChild.field] = formatValidate(mergedChild.validate)
}
})
}
......@@ -97,20 +99,22 @@ export function renderCustomParameters(
fields: { [field: string]: any },
rules: { [key: string]: FormItemRule | FormItemRule[] }[]
) {
const { field, children = [] } = item
const mergedItem = isFunction(item) ? item() : item
const { field, children = [] } = mergedItem
const { defaultValue, ruleItem } = getDefaultValue(children)
rules.push(ruleItem)
const getChild = (item: object, i: number, disabled: boolean) =>
children.map((child: IJsonItem) => {
const mergedChild = isFunction(child) ? child(i) : child
return h(
NFormItemGi,
{
showLabel: false,
path: `${field}[${i}].${child.field}`,
span: unref(child.span),
class: child.class
path: `${field}[${i}].${mergedChild.field}`,
span: unref(mergedChild.span),
class: mergedChild.class
},
() => getField(child, item)
() => getField(mergedChild, item)
)
})
const getChildren = ({ disabled }: { disabled: boolean }) =>
......
......@@ -15,7 +15,7 @@
* limitations under the License.
*/
import * as Field from './index'
import { camelCase, upperFirst } from 'lodash'
import { camelCase, upperFirst, isFunction } from 'lodash'
import type { FormRules, FormItemRule } from 'naive-ui'
import type { IJsonItem } from '../types'
......@@ -24,15 +24,15 @@ const getField = (
fields: { [field: string]: any },
rules?: FormRules
) => {
const { type = 'input' } = item
const { type = 'input', widget, field } = isFunction(item) ? item() : item
const renderTypeName = `render${upperFirst(camelCase(type))}`
if (type === 'custom') {
return item.widget || null
return widget || null
}
// TODO Support other widgets later
if (type === 'custom-parameters') {
let fieldRules: { [key: string]: FormItemRule }[] = []
if (rules && !rules[item.field]) fieldRules = rules[item.field] = []
if (rules && !rules[field]) fieldRules = rules[field] = []
// @ts-ignore
return Field[renderTypeName](item, fields, fieldRules)
}
......
......@@ -17,20 +17,21 @@
import { h } from 'vue'
import { NInputNumber } from 'naive-ui'
import { isFunction } from 'lodash'
import type { IJsonItem } from '../types'
export function renderInputNumber(
item: IJsonItem,
fields: { [field: string]: any }
) {
const { props, field, slots = {} } = item
const { props, field, slots = {} } = isFunction(item) ? item() : item
return h(
NInputNumber,
{
...props,
value: fields[field],
onUpdateValue: (value) => void (fields[field] = value)
onUpdateValue: (value: number) => void (fields[field] = value)
},
{
...slots
......
......@@ -17,10 +17,11 @@
import { h } from 'vue'
import { NInput } from 'naive-ui'
import { isFunction } from 'lodash'
import type { IJsonItem } from '../types'
export function renderInput(item: IJsonItem, fields: { [field: string]: any }) {
const { props, field } = item
const { props, field } = isFunction(item) ? item() : item
return h(NInput, {
...props,
value: fields[field],
......
......@@ -17,13 +17,14 @@
import { h } from 'vue'
import Editor from '@/components/monaco-editor'
import { isFunction } from 'lodash'
import type { IJsonItem } from '../types'
export function renderEditor(
item: IJsonItem,
fields: { [field: string]: any }
) {
const { props, field } = item
const { props, field } = isFunction(item) ? item() : item
return h(Editor, {
...props,
value: fields[field],
......
......@@ -17,16 +17,9 @@
import { defineComponent, h, unref, renderSlot } from 'vue'
import { useFormItem } from 'naive-ui/es/_mixins'
import {
NFormItemGi,
NSpace,
NButton,
NGrid,
NGridItem,
NInput,
NSelect
} from 'naive-ui'
import { NFormItemGi, NSpace, NButton, NGrid, NGridItem } from 'naive-ui'
import { PlusOutlined, DeleteOutlined } from '@vicons/antd'
import { isFunction } from 'lodash'
import type { IJsonItem, FormItemRule } from '../types'
import getField from '@/components/form/fields/get-field'
import { formatValidate } from '@/components/form/utils'
......@@ -79,23 +72,25 @@ export function renderMultiCondition(
// the fields is the data of the task definition.
// the item is the options of this component in the form.
const { field, children = [] } = item
const { field, children = [] } = isFunction(item) ? item() : item
children.forEach((child: IJsonItem) => {
if (child.validate) {
ruleItem[child.field] = formatValidate(child.validate)
const mergedChild = isFunction(child) ? child() : child
if (mergedChild.validate) {
ruleItem[mergedChild.field] = formatValidate(mergedChild.validate)
}
})
const getChild = (item: object, i: number) =>
children.map((child: IJsonItem) => {
const mergedChild = isFunction(child) ? child() : child
return h(
NFormItemGi,
{
showLabel: child.name ? true : false,
label: child.name ? child.name : '',
path: `${fields[field]}[${i}].${child.field}`,
span: unref(child.span)
path: `${fields[field]}[${i}].${mergedChild.field}`,
span: unref(mergedChild.span)
},
() => getField(child, fields[field][i])
)
......@@ -139,8 +134,9 @@ export function renderMultiCondition(
onAdd: () => {
const newCondition = {} as any
children.map((child: IJsonItem) => {
if (child.field) {
newCondition[child.field] = null
const { field } = isFunction(child) ? child() : child
if (field) {
newCondition[field] = null
}
})
fields[field].push(newCondition)
......
......@@ -25,6 +25,7 @@ import {
NGridItem,
NInput
} from 'naive-ui'
import { isFunction } from 'lodash'
import { PlusOutlined, DeleteOutlined } from '@vicons/antd'
import type { IJsonItem, FormItemRule } from '../types'
......@@ -72,31 +73,32 @@ export function renderMultiInput(
fields: { [field: string]: any },
rules: { [key: string]: FormItemRule }[]
) {
let ruleItem: { [key: string]: FormItemRule } = {}
const { field } = isFunction(item) ? item() : item
// the fields is the data of the task definition.
// the item is the options of this component in the form.
const getChild = (value: string, i: number) => {
const mergedItem = isFunction(item) ? item() : item
return h(
NFormItemGi,
{
showLabel: false,
path: `${item.field}[${i}]`,
span: unref(item.span)
path: `${mergedItem.field}[${i}]`,
span: unref(mergedItem.span)
},
() =>
h(NInput, {
...item.props,
...mergedItem.props,
value: value,
onUpdateValue: (value: string) => void (fields[item.field][i] = value)
onUpdateValue: (value: string) =>
void (fields[mergedItem.field][i] = value)
})
)
}
//initialize the component by using data
const getChildren = ({ disabled }: { disabled: boolean }) =>
fields[item.field].map((value: string, i: number) => {
const getChildren = ({ disabled }: { disabled: boolean }) => {
return fields[field].map((value: string, i: number) => {
return h(NGrid, { xGap: 10 }, () => [
getChild(value, i),
h(
......@@ -113,7 +115,7 @@ export function renderMultiInput(
size: 'small',
disabled,
onClick: () => {
fields[item.field].splice(i, 1)
fields[field].splice(i, 1)
}
},
{
......@@ -123,13 +125,14 @@ export function renderMultiInput(
)
])
})
}
return h(
MultiInput,
{
name: item.field,
name: field,
onAdd: () => {
fields[item.field].push('')
fields[field].push('')
}
},
{
......
......@@ -17,10 +17,11 @@
import { h, unref } from 'vue'
import { NRadio, NRadioGroup, NSpace } from 'naive-ui'
import { isFunction } from 'lodash'
import type { IJsonItem, IOption } from '../types'
export function renderRadio(item: IJsonItem, fields: { [field: string]: any }) {
const { props, field, options } = item
const { props, field, options } = isFunction(item) ? item() : item
if (!options) {
return h(NRadio, {
...props,
......
......@@ -17,17 +17,21 @@
import { h, unref } from 'vue'
import { NSelect } from 'naive-ui'
import { isFunction } from 'lodash'
import type { IJsonItem } from '../types'
export function renderSelect(
item: IJsonItem,
fields: { [field: string]: any }
) {
const { props, field, options = [] } = item
const { props, field, options = [] } = isFunction(item) ? item() : item
return h(NSelect, {
...props,
value: fields[field],
onUpdateValue: (value) => void (fields[field] = value),
onUpdateValue: (value: any) => {
void (fields[field] = value)
if (props?.onUpdateValue) props.onUpdateValue(value)
},
options: unref(options)
})
}
......@@ -17,13 +17,14 @@
import { h } from 'vue'
import { NSwitch } from 'naive-ui'
import { isFunction } from 'lodash'
import type { IJsonItem } from '../types'
export function renderSwitch(
item: IJsonItem,
fields: { [field: string]: any }
) {
const { props, field, slots = {} } = item
const { props, field, slots = {} } = isFunction(item) ? item() : item
return h(
NSwitch,
{
......
......@@ -17,17 +17,18 @@
import { h, unref } from 'vue'
import { NTreeSelect } from 'naive-ui'
import { isFunction } from 'lodash'
import type { IJsonItem } from '../types'
export function renderTreeSelect(
item: IJsonItem,
fields: { [field: string]: any }
) {
const { props = {}, field, options = [] } = item
const { props = {}, field, options = [] } = isFunction(item) ? item() : item
return h(NTreeSelect, {
...props,
value: fields[field],
onUpdateValue: (value) => void (fields[field] = value),
onUpdateValue: (value: []) => void (fields[field] = value),
options: unref(options)
})
}
......@@ -18,7 +18,7 @@
import { toRef, Ref } from 'vue'
import { formatValidate } from './utils'
import getField from './fields/get-field'
import { omit } from 'lodash'
import { omit, isFunction } from 'lodash'
import type { FormRules } from 'naive-ui'
import type { IFormItem, IJsonItem } from './types'
......@@ -30,7 +30,16 @@ export default function getElementByJson(
const initialValues: { [field: string]: any } = {}
const elements: IFormItem[] = []
for (let item of json) {
const { name, value, field, span = 24, children, validate, ...rest } = item
const mergedItem = isFunction(item) ? item() : item
const {
name,
value,
field,
span = 24,
children,
validate,
...rest
} = mergedItem
if (value || value === 0) {
fields[field] = value
initialValues[field] = value
......@@ -42,7 +51,7 @@ export default function getElementByJson(
label: name,
path: !children ? field : '',
widget: () => getField(item, fields, rules),
span: toRef(item, 'span') as Ref<number>
span: toRef(mergedItem, 'span') as Ref<number>
}
elements.push(element)
}
......
......@@ -57,10 +57,10 @@ interface IMeta extends Omit<FormProps, 'model'> {
model: object
}
interface IJsonItem {
interface IJsonItemParams {
field: string
name?: string
props?: object
props?: any
title?: string
type?: IType
validate?: FormItemRule
......@@ -73,6 +73,10 @@ interface IJsonItem {
class?: string
}
type IJsonItemFn = (i?: number) => IJsonItemParams
type IJsonItem = IJsonItemParams | IJsonItemFn
export {
IMeta,
IType,
......
......@@ -790,7 +790,38 @@ const project = {
datax_job_runtime_memory: 'Runtime Memory Limits',
datax_job_runtime_memory_xms: 'Low Limit Value',
datax_job_runtime_memory_xmx: 'High Limit Value',
datax_job_runtime_memory_unit: 'G'
datax_job_runtime_memory_unit: 'G',
current_hour: 'CurrentHour',
last_1_hour: 'Last1Hour',
last_2_hour: 'Last2Hours',
last_3_hour: 'Last3Hours',
last_24_hour: 'Last24Hours',
today: 'today',
last_1_days: 'Last1Days',
last_2_days: 'Last2Days',
last_3_days: 'Last3Days',
last_7_days: 'Last7Days',
this_week: 'ThisWeek',
last_week: 'LastWeek',
last_monday: 'LastMonday',
last_tuesday: 'LastTuesday',
last_wednesday: 'LastWednesday',
last_thursday: 'LastThursday',
last_friday: 'LastFriday',
last_saturday: 'LastSaturday',
last_sunday: 'LastSunday',
this_month: 'ThisMonth',
last_month: 'LastMonth',
last_month_begin: 'LastMonthBegin',
last_month_end: 'LastMonthEnd',
month: 'month',
week: 'week',
day: 'day',
hour: 'hour',
add_dependency: 'Add dependency',
waiting_dependent_start: 'Waiting Dependent start',
check_interval: 'Check interval',
waiting_dependent_complete: 'Waiting Dependent complete'
}
}
......
......@@ -781,7 +781,38 @@ const project = {
datax_job_runtime_memory: '运行内存',
datax_job_runtime_memory_xms: '最小内存',
datax_job_runtime_memory_xmx: '最大内存',
datax_job_runtime_memory_unit: 'G'
datax_job_runtime_memory_unit: 'G',
current_hour: '当前小时',
last_1_hour: '前1小时',
last_2_hour: '前2小时',
last_3_hour: '前3小时',
last_24_hour: '前24小时',
today: '今天',
last_1_days: '昨天',
last_2_days: '前两天',
last_3_days: '前三天',
last_7_days: '前七天',
this_week: '本周',
last_week: '上周',
last_monday: '上周一',
last_tuesday: '上周二',
last_wednesday: '上周三',
last_thursday: '上周四',
last_friday: '上周五',
last_saturday: '上周六',
last_sunday: '上周日',
this_month: '本月',
last_month: '上月',
last_month_begin: '上月初',
last_month_end: '上月末',
month: '',
week: '',
day: '',
hour: '',
add_dependency: '添加依赖',
waiting_dependent_start: '等待依赖启动',
check_interval: '检查间隔',
waiting_dependent_complete: '等待依赖完成'
}
}
......
......@@ -49,10 +49,10 @@ export function createProcessDefinition(
})
}
export function queryAllByProjectCode(code: CodeReq): any {
export function queryAllByProjectCode(code: number): any {
return axios({
url: `/projects/${code}/process-definition/all`,
method: 'post'
method: 'get'
})
}
......@@ -97,7 +97,7 @@ export function batchMoveByCodes(
export function getTaskListByDefinitionCodes(
params: CodesReq,
code: CodeReq
code: number
): any {
return axios({
url: `/projects/${code}/process-definition/batch-query-tasks`,
......@@ -189,8 +189,8 @@ export function release(
}
export function getTasksByDefinitionCode(
code: CodeReq,
processCode: CodeReq
code: number,
processCode: number
): any {
return axios({
url: `/projects/${code}/process-definition/${processCode}/tasks`,
......
......@@ -38,6 +38,7 @@ export { useCustomParams } from './use-custom-params'
export { useSourceType } from './use-sqoop-source-type'
export { useTargetType } from './use-sqoop-target-type'
export { useRelationCustomParams } from './use-relation-custom-params'
export { useDependentTimeout } from './use-dependent-timeout'
export { useShell } from './use-shell'
export { useSpark } from './use-spark'
......@@ -49,3 +50,5 @@ export { useSqoop } from './use-sqoop'
export { useSeaTunnel } from './use-sea-tunnel'
export { useSwitch } from './use-switch'
export { useDataX } from './use-datax'
export { useConditions } from './use-conditions'
export { useDependent } from './use-dependent'
/*
* 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 } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRelationCustomParams, useTimeoutAlarm } from '.'
import type { IJsonItem } from '../types'
export function useConditions(model: { [field: string]: any }): IJsonItem[] {
const { t } = useI18n()
const taskCodeOptions = ref([] as { label: string; value: number }[])
const postTasksOptions = ref([] as { label: string; value: number }[])
const stateOptions = [
{ label: t('project.node.success'), value: 'success' },
{ label: t('project.node.failed'), value: 'failed' }
]
watch(
() => model.preTasks,
() => {
taskCodeOptions.value =
model.preTaskOptions
?.filter((task: { code: number }) =>
model.preTasks?.includes(task.code)
)
.map((task: { code: number; name: string }) => ({
value: task.code,
label: task.name
})) || []
}
)
watch(
() => model.postTaskOptions,
() => {
postTasksOptions.value = model.postTasksOptions.map(
(task: { code: number; name: string }) => ({
value: task.code,
label: task.name
})
)
}
)
return [
{
type: 'select',
field: 'successNode',
name: t('project.node.state'),
span: 12,
props: {
disabled: true
},
options: stateOptions
},
{
type: 'select',
field: 'successBranch',
name: t('project.node.branch_flow'),
span: 12,
props: {
clearable: true
},
options: postTasksOptions
},
{
type: 'select',
field: 'failedNode',
name: t('project.node.state'),
span: 12,
props: {
disabled: true
},
options: stateOptions
},
{
type: 'select',
field: 'failedBranch',
name: t('project.node.branch_flow'),
span: 12,
props: {
clearable: true
},
options: postTasksOptions
},
...useTimeoutAlarm(model),
...useRelationCustomParams({
model,
children: {
type: 'custom-parameters',
field: 'dependItemList',
span: 18,
children: [
{
type: 'select',
field: 'depTaskCode',
span: 10,
options: taskCodeOptions
},
{
type: 'select',
field: 'status',
span: 10,
options: [
{
value: 'SUCCESS',
label: t('project.node.success')
},
{
value: 'FAILURE',
label: t('project.node.failed')
}
]
}
]
},
childrenField: 'dependItemList',
name: 'custom_parameters'
})
]
}
/*
* 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'
import type { IJsonItem } from '../types'
export function useDependentTimeout(model: {
[field: string]: any
}): IJsonItem[] {
const { t } = useI18n()
const timeCompleteSpan = computed(() => (model.timeoutShowFlag ? 24 : 0))
const timeCompleteEnableSpan = computed(() => (model.timeoutFlag ? 12 : 0))
const strategyOptions = [
{
label: t('project.node.timeout_alarm'),
value: 'WARN'
},
{
label: t('project.node.timeout_failure'),
value: 'FAILED'
}
]
watch(
() => model.timeoutFlag,
(timeoutFlag) => {
model.timeoutNotifyStrategy = timeoutFlag ? ['WARN'] : []
model.timeout = timeoutFlag ? 30 : null
}
)
return [
{
type: 'switch',
field: 'timeoutShowFlag',
name: t('project.node.timeout_alarm')
},
{
type: 'switch',
field: 'timeoutFlag',
name: t('project.node.waiting_dependent_complete'),
props: {
'on-update:value': (value: boolean) => {
model.timeoutNotifyStrategy = value ? ['WARN'] : null
model.timeout = value ? 30 : null
}
},
span: timeCompleteSpan
},
{
type: 'input-number',
field: 'timeout',
name: t('project.node.timeout_period'),
span: timeCompleteEnableSpan,
props: {
max: Math.pow(9, 10) - 1
},
slots: {
suffix: () => t('project.node.minute')
},
validate: {
trigger: ['input'],
validator(validate: any, value: number) {
if (model.timeoutFlag && !/^[1-9]\d*$/.test(String(value))) {
return new Error(t('project.node.timeout_period_tips'))
}
}
}
},
{
type: 'checkbox',
field: 'timeoutNotifyStrategy',
name: t('project.node.timeout_strategy'),
options: strategyOptions,
span: timeCompleteEnableSpan,
validate: {
trigger: ['input'],
validator(validate: any, value: []) {
if (model.waitCompleteTimeoutEnable && !value.length) {
return new Error(t('project.node.timeout_strategy_tips'))
}
}
}
}
]
}
/*
* 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, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRelationCustomParams, useDependentTimeout } from '.'
import { queryProjectCreatedAndAuthorizedByUser } from '@/service/modules/projects'
import {
queryAllByProjectCode,
getTasksByDefinitionCode
} from '@/service/modules/process-definition'
import type { IJsonItem, IDependpendItem, IDependTask } from '../types'
export function useDependent(model: { [field: string]: any }): IJsonItem[] {
const { t } = useI18n()
const projectList = ref([] as { label: string; value: number }[])
const processCache = {} as {
[key: number]: { label: string; value: number }[]
}
const taskCache = {} as {
[key: number]: { label: string; value: number }[]
}
const CYCLE_LIST = [
{
value: 'month',
label: t('project.node.month')
},
{
value: 'week',
label: t('project.node.week')
},
{
value: 'day',
label: t('project.node.day')
},
{
value: 'hour',
label: t('project.node.hour')
}
]
const DATE_LSIT = {
hour: [
{
value: 'currentHour',
label: t('project.node.current_hour')
},
{
value: 'last1Hour',
label: t('project.node.last_1_hour')
},
{
value: 'last2Hours',
label: t('project.node.last_2_hour')
},
{
value: 'last3Hours',
label: t('project.node.last_3_hour')
},
{
value: 'last24Hours',
label: t('project.node.last_24_hour')
}
],
day: [
{
value: 'today',
label: t('project.node.today')
},
{
value: 'last1Days',
label: t('project.node.last_1_days')
},
{
value: 'last2Days',
label: t('project.node.last_2_days')
},
{
value: 'last3Days',
label: t('project.node.last_3_days')
},
{
value: 'last7Days',
label: t('project.node.last_7_days')
}
],
week: [
{
value: 'thisWeek',
label: t('project.node.this_week')
},
{
value: 'lastWeek',
label: t('project.node.last_week')
},
{
value: 'lastMonday',
label: t('project.node.last_monday')
},
{
value: 'lastTuesday',
label: t('project.node.last_tuesday')
},
{
value: 'lastWednesday',
label: t('project.node.last_wednesday')
},
{
value: 'lastThursday',
label: t('project.node.last_thursday')
},
{
value: 'lastFriday',
label: t('project.node.last_friday')
},
{
value: 'lastSaturday',
label: t('project.node.last_saturday')
},
{
value: 'lastSunday',
label: t('project.node.last_sunday')
}
],
month: [
{
value: 'thisMonth',
label: t('project.node.this_month')
},
{
value: 'lastMonth',
label: t('project.node.last_month')
},
{
value: 'lastMonthBegin',
label: t('project.node.last_month_begin')
},
{
value: 'lastMonthEnd',
label: t('project.node.last_month_end')
}
]
}
const getProjectList = async () => {
try {
const result = await queryProjectCreatedAndAuthorizedByUser()
projectList.value = result.map(
(item: { code: number; name: string }) => ({
value: item.code,
label: item.name
})
)
return projectList
} catch (err) {}
}
const getProcessList = async (code: number) => {
if (processCache[code]) {
return processCache[code]
}
try {
const result = await queryAllByProjectCode(code)
const processList = result.map(
(item: { processDefinition: { code: number; name: string } }) => ({
value: item.processDefinition.code,
label: item.processDefinition.name
})
)
processCache[code] = processList
return processList
} catch (err) {}
}
const getTaskList = async (code: number, processCode: number) => {
if (taskCache[processCode]) {
return taskCache[processCode]
}
try {
const result = await getTasksByDefinitionCode(code, processCode)
const taskList = result.map((item: { code: number; name: string }) => ({
value: item.code,
label: item.name
}))
taskList.unshift({
value: 0,
label: 'ALL'
})
taskCache[processCode] = taskList
return taskList
} catch (err) {}
}
onMounted(() => {
getProjectList()
})
watch(
() => model.dependTaskList,
(value) => {
value.forEach((item: IDependTask) => {
if (!item.dependItemList?.length) return
item.dependItemList?.forEach(async (dependItem: IDependpendItem) => {
if (dependItem.projectCode) {
dependItem.definitionCodeOptions = await getProcessList(
dependItem.projectCode
)
}
if (dependItem.projectCode && dependItem.definitionCode) {
dependItem.depTaskCodeOptions = await getTaskList(
dependItem.projectCode,
dependItem.definitionCode
)
}
console.log(dependItem)
if (dependItem.cycle) {
dependItem.dateOptions = DATE_LSIT[dependItem.cycle]
}
})
})
}
)
return [
...useDependentTimeout(model),
...useRelationCustomParams({
model,
children: (i: number = 0) => ({
type: 'custom-parameters',
field: 'dependItemList',
span: 18,
children: [
(j = 0) => ({
type: 'select',
field: 'projectCode',
span: 12,
props: {
filterable: true,
onUpdateValue: async (projectCode: number) => {
const item = model.dependTaskList[i].dependItemList[j]
item.definitionCodeOptions = await getProcessList(projectCode)
item.depTaskCode = null
item.definitionCode = null
}
},
options: projectList
}),
(j: number = 0) => ({
type: 'select',
field: 'definitionCode',
span: 12,
props: {
filterable: true,
onUpdateValue: async (processCode: number) => {
const item = model.dependTaskList[i].dependItemList[j]
item.depTaskCodeOptions = await getTaskList(
item.projectCode,
processCode
)
item.depTaskCode = 0
}
},
options:
model.dependTaskList[i]?.dependItemList[j]
?.definitionCodeOptions || []
}),
(j: number = 0) => ({
type: 'select',
field: 'depTaskCode',
span: 12,
props: {
filterable: true
},
options:
model.dependTaskList[i]?.dependItemList[j]?.depTaskCodeOptions ||
[]
}),
(j: number = 0) => ({
type: 'select',
field: 'cycle',
span: 12,
props: {
onUpdateValue: (value: 'month') => {
model.dependTaskList[i].dependItemList[j].dateOptions =
DATE_LSIT[value]
}
},
options: CYCLE_LIST
}),
(j: number = 0) => ({
type: 'select',
field: 'dateValue',
span: 12,
options:
model.dependTaskList[i]?.dependItemList[j]?.dateOptions || []
})
]
}),
childrenField: 'dependItemList',
name: 'add_dependency'
})
]
}
......@@ -14,22 +14,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { computed, h, watchEffect } from 'vue'
import { computed, watchEffect } from 'vue'
import { useI18n } from 'vue-i18n'
import { NButton } from 'naive-ui'
import styles from '../index.module.scss'
import type { IJsonItem } from '../types'
export function useRelationCustomParams({
model,
children,
childrenField
childrenField,
name
}: {
model: {
[field: string]: any
}
children: IJsonItem
childrenField: string
name: string
}): IJsonItem[] {
const { t } = useI18n()
const firstLevelRelationSpan = computed(() =>
......@@ -48,7 +49,7 @@ export function useRelationCustomParams({
return [
{
type: 'custom',
name: t('project.node.custom_parameters'),
name: t(`project.node.${name}`),
field: 'relationLabel',
span: 24,
class: styles['relaction-label']
......
......@@ -36,8 +36,8 @@ export function useTimeoutAlarm(model: { [field: string]: any }): IJsonItem[] {
watch(
() => model.timeoutFlag,
(timeoutFlag) => {
model.strategy = timeoutFlag ? ['WARN'] : []
model.interval = timeoutFlag ? 30 : null
model.timeoutNotifyStrategy = timeoutFlag ? ['WARN'] : []
model.timeout = timeoutFlag ? 30 : null
}
)
......@@ -60,8 +60,7 @@ export function useTimeoutAlarm(model: { [field: string]: any }): IJsonItem[] {
return new Error(t('project.node.timeout_strategy_tips'))
}
}
},
value: ['WARN']
}
},
{
type: 'input-number',
......@@ -81,8 +80,7 @@ export function useTimeoutAlarm(model: { [field: string]: any }): IJsonItem[] {
return new Error(t('project.node.timeout_period_tips'))
}
}
},
value: 30
}
}
]
}
......@@ -15,14 +15,15 @@
* limitations under the License.
*/
import { find, omit } from 'lodash'
import { find, omit, cloneDeep } from 'lodash'
import type {
INodeData,
ITaskData,
ITaskParams,
ISqoopTargetParams,
ISqoopSourceParams,
ILocalParam
ILocalParam,
IDependTask
} from './types'
export function formatParams(data: INodeData): {
......@@ -228,6 +229,24 @@ export function formatParams(data: INodeData): {
taskParams.xms = data.xms
taskParams.xmx = data.xmx
}
if (data.taskType === 'DEPENDENT') {
const dependTaskList = cloneDeep(data.dependTaskList)?.map(
(taskItem: IDependTask) => {
if (taskItem.dependItemList?.length) {
taskItem.dependItemList.forEach((dependItem) => {
delete dependItem.definitionCodeOptions
delete dependItem.depTaskCodeOptions
delete dependItem.dateOptions
})
}
return taskItem
}
)
taskParams.dependence = {
relation: data.relation,
dependTaskList: dependTaskList
}
}
const params = {
processDefinitionCode: data.processName ? String(data.processName) : '',
......
......@@ -15,8 +15,7 @@
* limitations under the License.
*/
import { ref, reactive, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { reactive, watch } from 'vue'
import * as Fields from '../fields/index'
import type { IJsonItem, INodeData, ITaskData } from '../types'
......@@ -31,8 +30,6 @@ export function useConditions({
readonly?: boolean
data?: ITaskData
}) {
const { t } = useI18n()
const taskCodeOptions = ref([] as { label: string; value: number }[])
const model = reactive({
taskType: 'CONDITIONS',
name: '',
......@@ -44,11 +41,12 @@ export function useConditions({
failRetryInterval: 1,
failRetryTimes: 0,
workerGroup: 'default',
delayTime: 0,
timeout: 30,
relation: 'AND',
dependTaskList: [],
preTasks: []
preTasks: [],
successNode: 'success',
failedNode: 'failed'
} as INodeData)
let extra: IJsonItem[] = []
......@@ -66,21 +64,6 @@ export function useConditions({
]
}
watch(
() => model.preTasks,
() => {
taskCodeOptions.value =
model.preTaskOptions
?.filter((task: { code: number }) =>
model.preTasks?.includes(task.code)
)
.map((task: { code: number; name: string }) => ({
value: task.code,
label: task.name
})) || []
}
)
return {
json: [
Fields.useName(),
......@@ -92,40 +75,7 @@ export function useConditions({
Fields.useEnvironmentName(model, !data?.id),
...Fields.useTaskGroup(model, projectCode),
...Fields.useFailed(),
Fields.useDelayTime(model),
...Fields.useTimeoutAlarm(model),
...Fields.useRelationCustomParams({
model,
children: {
type: 'custom-parameters',
field: 'dependItemList',
span: 18,
children: [
{
type: 'select',
field: 'depTaskCode',
span: 10,
options: taskCodeOptions
},
{
type: 'select',
field: 'status',
span: 10,
options: [
{
value: 'SUCCESS',
label: t('project.node.success')
},
{
value: 'FAILURE',
label: t('project.node.failed')
}
]
}
]
},
childrenField: 'dependItemList'
}),
...Fields.useConditions(model),
Fields.usePreTasks(model)
] as IJsonItem[],
model
......
/*
* 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, watch } from 'vue'
import * as Fields from '../fields/index'
import type { IJsonItem, INodeData, ITaskData } from '../types'
export function useDependent({
projectCode,
from = 0,
readonly,
data
}: {
projectCode: number
from?: number
readonly?: boolean
data?: ITaskData
}) {
const taskCodeOptions = ref([] as { label: string; value: number }[])
const model = reactive({
taskType: 'DEPENDENT',
name: '',
flag: 'YES',
description: '',
timeoutShowFlag: false,
localParams: [],
environmentCode: null,
failRetryInterval: 1,
failRetryTimes: 0,
workerGroup: 'default',
delayTime: 0,
relation: 'AND',
dependTaskList: [],
preTasks: [],
timeoutNotifyStrategy: [],
timeout: 30,
timeoutFlag: false,
...data
} as INodeData)
let extra: IJsonItem[] = []
if (from === 1) {
extra = [
Fields.useTaskType(model, readonly),
Fields.useProcessName({
model,
projectCode,
isCreate: !data?.id,
from,
processName: data?.processName,
code: data?.code
})
]
}
watch(
() => model.preTasks,
() => {
taskCodeOptions.value =
model.preTaskOptions
?.filter((task: { code: number }) =>
model.preTasks?.includes(task.code)
)
.map((task: { code: number; name: string }) => ({
value: task.code,
label: task.name
})) || []
}
)
return {
json: [
Fields.useName(),
...extra,
Fields.useRunFlag(),
Fields.useDescription(),
Fields.useTaskPriority(),
Fields.useWorkerGroup(),
Fields.useEnvironmentName(model, !data?.id),
...Fields.useTaskGroup(model, projectCode),
...Fields.useFailed(),
...Fields.useDependent(model),
Fields.usePreTasks(model)
] as IJsonItem[],
model
}
}
......@@ -36,13 +36,14 @@ export function useShell({
flag: 'YES',
description: '',
timeoutFlag: false,
timeoutNotifyStrategy: ['WARN'],
timeout: 30,
localParams: [],
environmentCode: null,
failRetryInterval: 1,
failRetryTimes: 0,
workerGroup: 'default',
delayTime: 0,
timeout: 30,
rawScript: ''
} as INodeData)
......
......@@ -49,11 +49,23 @@ interface ILocalParam {
value?: string
}
interface IDependpendItem {
depTaskCode?: number
status?: 'SUCCESS' | 'FAILURE'
definitionCodeOptions?: IOption[]
depTaskCodeOptions?: IOption[]
dateOptions?: IOption[]
projectCode?: number
definitionCode?: number
cycle?: 'month' | 'week' | 'day' | 'hour'
dateValue?: string
}
interface IDependTask {
condition?: string
nextNode?: number
relation?: RelationType
dependItemList?: { depTaskCode?: number; status?: 'SUCCESS' | 'FAILURE' }[]
dependItemList?: IDependpendItem[]
}
interface ISwitchResult {
......@@ -289,5 +301,7 @@ export {
ModelType,
SourceType,
ISqoopSourceParams,
ISqoopTargetParams
ISqoopTargetParams,
IDependTask,
IDependpendItem
}
......@@ -30,6 +30,7 @@ import { useSeaTunnel } from './tasks/use-sea-tunnel'
import { useSwitch } from './tasks/use-switch'
import { useConditions } from './tasks/use-conditions'
import { useDataX } from './tasks/use-datax'
import { useDependent } from './tasks/use-dependent'
import { IJsonItem, INodeData, ITaskData } from './types'
export function useTask({
......@@ -168,6 +169,14 @@ export function useTask({
data
})
}
if (taskType === 'DEPENDENT') {
node = useDependent({
projectCode,
from,
readonly,
data
})
}
return node
}
......@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { reactive } from 'vue'
import { reactive, onMounted } from 'vue'
import {
genTaskCodeList,
saveSingle,
......@@ -27,7 +27,7 @@ import type { ITaskData, INodeData, ISingleSaveReq, IRecord } from './types'
export function useTask(projectCode: number) {
const initalTask = {
taskType: 'SHELL'
taskType: 'DEPENDENT'
} as ITaskData
const task = reactive({
taskShow: false,
......
......@@ -25,6 +25,7 @@ import {
Ref
} from 'vue'
import { NSelect, NInput } from 'naive-ui'
import { isFunction } from 'lodash'
import Modal from '@/components/modal'
import Form from '@/components/form'
import { useI18n } from 'vue-i18n'
......@@ -97,7 +98,10 @@ const DetailModal = defineComponent({
() => {
if (!state.json?.length) return
state.json.forEach((item) => {
item.name = t('security.alarm_instance' + '.' + item.field)
const mergedItem = isFunction(item) ? item() : item
mergedItem.name = t(
'security.alarm_instance' + '.' + mergedItem.field
)
})
const { rules: fieldsRules, elements: fieldsElements } =
getElementByJson(state.json, state.detailForm)
......
......@@ -16,6 +16,7 @@
*/
import { reactive } from 'vue'
import { isFunction } from 'lodash'
import {
createAlertPluginInstance,
updateAlertPluginInstance,
......@@ -34,7 +35,8 @@ export function useDetail(getFormValues: Function) {
values: { [field: string]: any } = {}
): string => {
json?.forEach((item) => {
item.value = values[item.field]
const mergedItem = isFunction(item) ? item() : item
mergedItem.value = values[mergedItem.field]
})
return JSON.stringify(json)
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册