Browse Source

[Feature-8565][Fix-8672][UI Next][V1.0.0-Alpha]: Add DATA_QUALITY and modify task type switching bug. (#8698)

3.0.0/version-upgrade
Amy0104 3 years ago committed by GitHub
parent
commit
79733643aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 16
      dolphinscheduler-ui-next/src/components/form/fields/get-field.ts
  2. 1
      dolphinscheduler-ui-next/src/components/form/index.tsx
  3. 3
      dolphinscheduler-ui-next/src/components/form/types.ts
  4. 45
      dolphinscheduler-ui-next/src/locales/modules/en_US.ts
  5. 45
      dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts
  6. 27
      dolphinscheduler-ui-next/src/service/modules/data-quality/index.ts
  7. 24
      dolphinscheduler-ui-next/src/service/modules/data-source/index.ts
  8. 71
      dolphinscheduler-ui-next/src/views/projects/task/components/node/detail-modal.tsx
  9. 90
      dolphinscheduler-ui-next/src/views/projects/task/components/node/detail.tsx
  10. 7
      dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/index.ts
  11. 45
      dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-deploy-mode.ts
  12. 42
      dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-driver-cores.ts
  13. 47
      dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-driver-memory.ts
  14. 42
      dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-executor-cores.ts
  15. 47
      dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-executor-memory.ts
  16. 42
      dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-executor-number.ts
  17. 20
      dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-flink.ts
  18. 4
      dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-http.ts
  19. 214
      dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-rules.ts
  20. 24
      dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-sea-tunnel.ts
  21. 146
      dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-spark.ts
  22. 53
      dolphinscheduler-ui-next/src/views/projects/task/components/node/format-data.ts
  23. 54
      dolphinscheduler-ui-next/src/views/projects/task/components/node/tasks/index.ts
  24. 116
      dolphinscheduler-ui-next/src/views/projects/task/components/node/tasks/use-data-quality.ts
  25. 1
      dolphinscheduler-ui-next/src/views/projects/task/components/node/tasks/use-flink.ts
  26. 1
      dolphinscheduler-ui-next/src/views/projects/task/components/node/tasks/use-pigeon.ts
  27. 1
      dolphinscheduler-ui-next/src/views/projects/task/components/node/tasks/use-sub-process.ts
  28. 58
      dolphinscheduler-ui-next/src/views/projects/task/components/node/types.ts
  29. 181
      dolphinscheduler-ui-next/src/views/projects/task/components/node/use-task.ts
  30. 3
      dolphinscheduler-ui-next/src/views/projects/task/constants/task-type.ts
  31. 2
      dolphinscheduler-ui-next/src/views/projects/task/definition/use-task.ts

16
dolphinscheduler-ui-next/src/components/form/fields/get-field.ts

@ -19,12 +19,28 @@ import { camelCase, upperFirst, isFunction } from 'lodash'
import type { FormRules, FormItemRule } from 'naive-ui' import type { FormRules, FormItemRule } from 'naive-ui'
import type { IJsonItem } from '../types' import type { IJsonItem } from '../types'
const TYPES = [
'input',
'radio',
'editor',
'custom-parameters',
'switch',
'input-number',
'select',
'checkbox',
'tree-select',
'multi-input',
'custom',
'multi-condition'
]
const getField = ( const getField = (
item: IJsonItem, item: IJsonItem,
fields: { [field: string]: any }, fields: { [field: string]: any },
rules?: FormRules rules?: FormRules
) => { ) => {
const { type = 'input', widget, field } = isFunction(item) ? item() : item const { type = 'input', widget, field } = isFunction(item) ? item() : item
if (!TYPES.includes(type)) return null
const renderTypeName = `render${upperFirst(camelCase(type))}` const renderTypeName = `render${upperFirst(camelCase(type))}`
if (type === 'custom') { if (type === 'custom') {
return widget || null return widget || null

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

@ -60,6 +60,7 @@ const Form = defineComponent({
{...formItemProps} {...formItemProps}
span={unref(span) === void 0 ? 24 : unref(span)} span={unref(span) === void 0 ? 24 : unref(span)}
path={path} path={path}
key={path}
> >
{h(widget)} {h(widget)}
</NFormItemGi> </NFormItemGi>

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

@ -85,5 +85,6 @@ export {
FormItemRule, FormItemRule,
FormRules, FormRules,
IFormItem, IFormItem,
GridProps GridProps,
IJsonItemParams
} }

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

@ -787,7 +787,6 @@ const project = {
allow_insert: 'AllowInsert', allow_insert: 'AllowInsert',
concurrency: 'Concurrency', concurrency: 'Concurrency',
concurrency_tips: 'Please enter Concurrency', concurrency_tips: 'Please enter Concurrency',
sea_tunnel_deploy_mode: 'Deploy Mode',
sea_tunnel_master: 'Master', sea_tunnel_master: 'Master',
sea_tunnel_master_url: 'Master URL', sea_tunnel_master_url: 'Master URL',
sea_tunnel_queue: 'Queue', sea_tunnel_queue: 'Queue',
@ -844,7 +843,49 @@ const project = {
add_dependency: 'Add dependency', add_dependency: 'Add dependency',
waiting_dependent_start: 'Waiting Dependent start', waiting_dependent_start: 'Waiting Dependent start',
check_interval: 'Check interval', check_interval: 'Check interval',
waiting_dependent_complete: 'Waiting Dependent complete' waiting_dependent_complete: 'Waiting Dependent complete',
rule_name: 'Rule Name',
null_check: 'NullCheck',
custom_sql: 'CustomSql',
multi_table_accuracy: 'MulTableAccuracy',
multi_table_value_comparison: 'MulTableCompare',
field_length_check: 'FieldLengthCheck',
uniqueness_check: 'UniquenessCheck',
regexp_check: 'RegexpCheck',
timeliness_check: 'TimelinessCheck',
enumeration_check: 'EnumerationCheck',
table_count_check: 'TableCountCheck',
src_connector_type: 'SrcConnType',
src_datasource_id: 'SrcSource',
src_table: 'SrcTable',
src_filter: 'SrcFilter',
src_field: 'SrcField',
statistics_name: 'ActualValName',
check_type: 'CheckType',
operator: 'Operator',
threshold: 'Threshold',
failure_strategy: 'FailureStrategy',
target_connector_type: 'TargetConnType',
target_datasource_id: 'TargetSourceId',
target_table: 'TargetTable',
target_filter: 'TargetFilter',
mapping_columns: 'OnClause',
statistics_execute_sql: 'ActualValExecSql',
comparison_name: 'ExceptedValName',
comparison_execute_sql: 'ExceptedValExecSql',
comparison_type: 'ExceptedValType',
writer_connector_type: 'WriterConnType',
writer_datasource_id: 'WriterSourceId',
target_field: 'TargetField',
field_length: 'FieldLength',
logic_operator: 'LogicOperator',
regexp_pattern: 'RegexpPattern',
deadline: 'Deadline',
datetime_format: 'DatetimeFormat',
enum_list: 'EnumList',
begin_time: 'BeginTime',
fix_value: 'FixValue',
required: 'required'
} }
} }

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

@ -778,7 +778,6 @@ const project = {
allow_insert: '无更新便插入', allow_insert: '无更新便插入',
concurrency: '并发度', concurrency: '并发度',
concurrency_tips: '请输入并发度', concurrency_tips: '请输入并发度',
sea_tunnel_deploy_mode: '部署方式',
sea_tunnel_master: 'Master', sea_tunnel_master: 'Master',
sea_tunnel_master_url: 'Master URL', sea_tunnel_master_url: 'Master URL',
sea_tunnel_queue: '队列', sea_tunnel_queue: '队列',
@ -834,7 +833,49 @@ const project = {
add_dependency: '添加依赖', add_dependency: '添加依赖',
waiting_dependent_start: '等待依赖启动', waiting_dependent_start: '等待依赖启动',
check_interval: '检查间隔', check_interval: '检查间隔',
waiting_dependent_complete: '等待依赖完成' waiting_dependent_complete: '等待依赖完成',
rule_name: '规则名称',
null_check: '空值检测',
custom_sql: '自定义SQL',
multi_table_accuracy: '多表准确性',
multi_table_value_comparison: '两表值比对',
field_length_check: '字段长度校验',
uniqueness_check: '唯一性校验',
regexp_check: '正则表达式',
timeliness_check: '及时性校验',
enumeration_check: '枚举值校验',
table_count_check: '表行数校验',
src_connector_type: '源数据类型',
src_datasource_id: '源数据源',
src_table: '源数据表',
src_filter: '源表过滤条件',
src_field: '源表检测列',
statistics_name: '实际值名',
check_type: '校验方式',
operator: '校验操作符',
threshold: '阈值',
failure_strategy: '失败策略',
target_connector_type: '目标数据类型',
target_datasource_id: '目标数据源',
target_table: '目标数据表',
target_filter: '目标表过滤条件',
mapping_columns: 'ON语句',
statistics_execute_sql: '实际值计算SQL',
comparison_name: '期望值名',
comparison_execute_sql: '期望值计算SQL',
comparison_type: '期望值类型',
writer_connector_type: '输出数据类型',
writer_datasource_id: '输出数据源',
target_field: '目标表检测列',
field_length: '字段长度限制',
logic_operator: '逻辑操作符',
regexp_pattern: '正则表达式',
deadline: '截止时间',
datetime_format: '时间格式',
enum_list: '枚举值列表',
begin_time: '起始时间',
fix_value: '固定值',
required: '必填'
} }
} }

27
dolphinscheduler-ui-next/src/service/modules/data-quality/index.ts

@ -33,3 +33,30 @@ export function queryExecuteResultListPaging(params: ResultListReq): any {
params params
}) })
} }
export function queryRuleList(): any {
return axios({
url: '/data-quality/ruleList',
method: 'get'
})
}
export function getRuleFormCreateJson(ruleId: number): any {
return axios({
url: '/data-quality/getRuleFormCreateJson',
method: 'get',
params: {
ruleId
}
})
}
export function getDatasourceOptionsById(datasourceId: number): any {
return axios({
url: '/data-quality/getDatasourceOptionsById',
method: 'get',
params: {
datasourceId
}
})
}

24
dolphinscheduler-ui-next/src/service/modules/data-source/index.ts

@ -128,3 +128,27 @@ export function connectionTest(id: IdReq): any {
method: 'get' method: 'get'
}) })
} }
export function getDatasourceTablesById(datasourceId: number): any {
return axios({
url: '/datasources/tables',
method: 'get',
params: {
datasourceId
}
})
}
export function getDatasourceTableColumnsById(
datasourceId: number,
tableName: string
): any {
return axios({
url: '/datasources/tableColumns',
method: 'get',
params: {
datasourceId,
tableName
}
})
}

71
dolphinscheduler-ui-next/src/views/projects/task/components/node/detail-modal.tsx

@ -20,15 +20,17 @@ import {
PropType, PropType,
ref, ref,
reactive, reactive,
toRefs,
watch, watch,
nextTick nextTick,
provide,
computed
} from 'vue' } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { omit } from 'lodash'
import Modal from '@/components/modal' import Modal from '@/components/modal'
import Detail from './detail' import Detail from './detail'
import { formatModel } from './format-data' import { formatModel } from './format-data'
import type { ITaskData } from './types' import type { ITaskData, ITaskType } from './types'
const props = { const props = {
show: { show: {
@ -59,17 +61,17 @@ const NodeDetailModal = defineComponent({
emits: ['cancel', 'submit'], emits: ['cancel', 'submit'],
setup(props, { emit }) { setup(props, { emit }) {
const { t } = useI18n() const { t } = useI18n()
const detailRef = ref()
const state = reactive({ const state = reactive({
saving: false, saving: false,
detailRef: ref(),
linkEventShowRef: ref(), linkEventShowRef: ref(),
linkEventTextRef: ref(), linkEventTextRef: ref(),
linkUrlRef: ref() linkUrlRef: ref()
}) })
const onConfirm = async () => { const onConfirm = async () => {
await state.detailRef.form.validate() await detailRef.value.value.validate()
emit('submit', { data: state.detailRef.form.getValues() }) emit('submit', { data: detailRef.value.value.getValues() })
} }
const onCancel = () => { const onCancel = () => {
emit('cancel') emit('cancel')
@ -85,54 +87,45 @@ const NodeDetailModal = defineComponent({
state.linkUrlRef = url state.linkUrlRef = url
} }
const onTaskTypeChange = (taskType: ITaskType) => {
props.data.taskType = taskType
}
provide(
'data',
computed(() => ({
projectCode: props.projectCode,
data: props.data,
from: props.from,
readonly: props.readonly
}))
)
watch( watch(
() => props.data, () => props.data,
async () => { async () => {
if (!props.show) return
await nextTick() await nextTick()
state.detailRef.form.setValues(formatModel(props.data)) detailRef.value.value.setValues(formatModel(props.data))
} }
) )
return { return () => (
t,
...toRefs(state),
getLinkEventText,
onConfirm,
onCancel,
onJumpLink
}
},
render() {
const {
t,
show,
onConfirm,
onCancel,
projectCode,
data,
readonly,
from,
onJumpLink
} = this
return (
<Modal <Modal
show={show} show={props.show}
title={`${t('project.node.current_node_settings')}`} title={`${t('project.node.current_node_settings')}`}
onConfirm={onConfirm} onConfirm={onConfirm}
confirmLoading={false} confirmLoading={false}
confirmDisabled={readonly} confirmDisabled={props.readonly}
onCancel={onCancel} onCancel={onCancel}
linkEventShow={this.linkEventShowRef} linkEventShow={state.linkEventShowRef}
linkEventText={this.linkEventTextRef} linkEventText={state.linkEventTextRef}
onJumpLink={onJumpLink} onJumpLink={onJumpLink}
> >
<Detail <Detail
ref='detailRef' ref={detailRef}
data={data} onTaskTypeChange={onTaskTypeChange}
projectCode={projectCode} key={props.data.taskType}
readonly={readonly}
from={from}
onLinkEventText={this.getLinkEventText}
/> />
</Modal> </Modal>
) )

90
dolphinscheduler-ui-next/src/views/projects/task/components/node/detail.tsx

@ -15,92 +15,58 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, PropType, ref, watch } from 'vue' import { defineComponent, ref, watch, inject, Ref, unref } from 'vue'
import Form from '@/components/form' import Form from '@/components/form'
import { useTask } from './use-task' import { useTask } from './use-task'
import getElementByJson from '@/components/form/get-elements-by-json'
import type { ITaskData } from './types' import type { ITaskData } from './types'
import { useI18n } from 'vue-i18n'
const props = { interface IDetailPanel {
projectCode: { projectCode: number
type: Number as PropType<number>, data: ITaskData
default: 0 readonly: false
}, from: number
data: { detailRef?: Ref
type: Object as PropType<ITaskData>,
default: { taskType: 'SHELL' }
},
readonly: {
type: Boolean as PropType<boolean>,
default: false
},
loading: {
type: Boolean as PropType<boolean>,
default: false
},
from: {
type: Number as PropType<number>,
default: 0
}
} }
const NodeDetail = defineComponent({ const NodeDetail = defineComponent({
name: 'NodeDetail', name: 'NodeDetail',
props, emits: ['taskTypeChange'],
emits: ['linkEventText'],
setup(props, { expose, emit }) { setup(props, { expose, emit }) {
const { data, projectCode, from, readonly } = props const formRef = ref()
const { t } = useI18n() const detailData: IDetailPanel = inject('data') || {
projectCode: 0,
data: {
taskType: 'SHELL'
},
readonly: false,
from: 0
}
const { data, projectCode, from, readonly } = unref(detailData)
const { json, model } = useTask({ const { elementsRef, rulesRef, model } = useTask({
data, data,
projectCode, projectCode,
from, from,
readonly readonly
}) })
const jsonRef = ref(json)
const formRef = ref()
const { rules, elements } = getElementByJson(jsonRef.value, model)
expose({
form: formRef
})
watch( watch(
() => model.taskType, () => model.taskType,
(taskType) => { async (taskType) => {
// TODO: Change task type emit('taskTypeChange', taskType)
if (taskType === 'SUB_PROCESS') {
// TODO: add linkUrl
emit(
'linkEventText',
true,
`${t('project.node.enter_child_node')}`,
''
)
} else {
emit('linkEventText', false, '', '')
}
} }
) )
return { rules, elements, model, formRef } expose(formRef)
},
render(props: { readonly: boolean; loading: boolean }) { return () => (
const { rules, elements, model } = this
return (
<Form <Form
ref='formRef' ref={formRef}
meta={{ meta={{
model, model,
rules, rules: rulesRef.value,
elements, elements: elementsRef.value,
disabled: props.readonly disabled: unref(readonly)
}} }}
loading={props.loading}
layout={{ layout={{
xGap: 10 xGap: 10
}} }}

7
dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/index.ts

@ -39,6 +39,13 @@ export { useSourceType } from './use-sqoop-source-type'
export { useTargetType } from './use-sqoop-target-type' export { useTargetType } from './use-sqoop-target-type'
export { useRelationCustomParams } from './use-relation-custom-params' export { useRelationCustomParams } from './use-relation-custom-params'
export { useDependentTimeout } from './use-dependent-timeout' export { useDependentTimeout } from './use-dependent-timeout'
export { useRules } from './use-rules'
export { useDeployMode } from './use-deploy-mode'
export { useDriverCores } from './use-driver-cores'
export { useDriverMemory } from './use-driver-memory'
export { useExecutorNumber } from './use-executor-number'
export { useExecutorMemory } from './use-executor-memory'
export { useExecutorCores } from './use-executor-cores'
export { useShell } from './use-shell' export { useShell } from './use-shell'
export { useSpark } from './use-spark' export { useSpark } from './use-spark'

45
dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-deploy-mode.ts

@ -0,0 +1,45 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useI18n } from 'vue-i18n'
import type { IJsonItem } from '../types'
export function useDeployMode(span = 24): IJsonItem {
const { t } = useI18n()
return {
type: 'radio',
field: 'deployMode',
name: t('project.node.deploy_mode'),
options: DEPLOY_MODES,
span
}
}
export const DEPLOY_MODES = [
{
label: 'cluster',
value: 'cluster'
},
{
label: 'client',
value: 'client'
},
{
label: 'local',
value: 'local'
}
]

42
dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-driver-cores.ts

@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useI18n } from 'vue-i18n'
import type { IJsonItem } from '../types'
export function useDriverCores(): IJsonItem {
const { t } = useI18n()
return {
type: 'input-number',
field: 'driverCores',
name: t('project.node.driver_cores'),
span: 12,
props: {
placeholder: t('project.node.driver_cores_tips'),
min: 1
},
validate: {
trigger: ['input', 'blur'],
required: true,
validator(validate: any, value: string) {
if (!value) {
return new Error(t('project.node.driver_cores_tips'))
}
}
}
}
}

47
dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-driver-memory.ts

@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useI18n } from 'vue-i18n'
import type { IJsonItem } from '../types'
export function useDriverMemory(): IJsonItem {
const { t } = useI18n()
return {
type: 'input',
field: 'driverMemory',
name: t('project.node.driver_memory'),
span: 12,
props: {
placeholder: t('project.node.driver_memory_tips')
},
validate: {
trigger: ['input', 'blur'],
required: true,
validator(validate: any, value: string) {
if (!value) {
return new Error(t('project.node.driver_memory_tips'))
}
if (!Number.isInteger(parseInt(value))) {
return new Error(
t('project.node.driver_memory') +
t('project.node.positive_integer_tips')
)
}
}
}
}
}

42
dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-executor-cores.ts

@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useI18n } from 'vue-i18n'
import type { IJsonItem } from '../types'
export function useExecutorCores(): IJsonItem {
const { t } = useI18n()
return {
type: 'input-number',
field: 'executorCores',
name: t('project.node.executor_cores'),
span: 12,
props: {
placeholder: t('project.node.executor_cores_tips'),
min: 1
},
validate: {
trigger: ['input', 'blur'],
required: true,
validator(validate: any, value: string) {
if (!value) {
return new Error(t('project.node.executor_cores_tips'))
}
}
}
}
}

47
dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-executor-memory.ts

@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useI18n } from 'vue-i18n'
import type { IJsonItem } from '../types'
export function useExecutorMemory(): IJsonItem {
const { t } = useI18n()
return {
type: 'input',
field: 'executorMemory',
name: t('project.node.executor_memory'),
span: 12,
props: {
placeholder: t('project.node.executor_memory_tips')
},
validate: {
trigger: ['input', 'blur'],
required: true,
validator(validate: any, value: string) {
if (!value) {
return new Error(t('project.node.executor_memory_tips'))
}
if (!Number.isInteger(parseInt(value))) {
return new Error(
t('project.node.executor_memory_tips') +
t('project.node.positive_integer_tips')
)
}
}
}
}
}

42
dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-executor-number.ts

@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useI18n } from 'vue-i18n'
import type { IJsonItem } from '../types'
export function useExecutorNumber(): IJsonItem {
const { t } = useI18n()
return {
type: 'input-number',
field: 'numExecutors',
name: t('project.node.executor_number'),
span: 12,
props: {
placeholder: t('project.node.executor_number_tips'),
min: 1
},
validate: {
trigger: ['input', 'blur'],
required: true,
validator(validate: any, value: string) {
if (!value) {
return new Error(t('project.node.executor_number_tips'))
}
}
}
}
}

20
dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-flink.ts

@ -18,7 +18,7 @@ import { ref, onMounted, computed } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { queryResourceByProgramType } from '@/service/modules/resources' import { queryResourceByProgramType } from '@/service/modules/resources'
import { removeUselessChildren } from './use-shell' import { removeUselessChildren } from './use-shell'
import { useCustomParams } from '.' import { useCustomParams, useDeployMode } from '.'
import type { IJsonItem, ProgramType } from '../types' import type { IJsonItem, ProgramType } from '../types'
export function useFlink(model: { [field: string]: any }): IJsonItem[] { export function useFlink(model: { [field: string]: any }): IJsonItem[] {
@ -116,12 +116,7 @@ export function useFlink(model: { [field: string]: any }): IJsonItem[] {
}, },
options: mainJarOptions options: mainJarOptions
}, },
{ useDeployMode(),
type: 'radio',
field: 'deployMode',
name: t('project.node.deploy_mode'),
options: DeployModes
},
{ {
type: 'select', type: 'select',
field: 'flinkVersion', field: 'flinkVersion',
@ -294,14 +289,3 @@ const FLINK_VERSIONS = [
value: '>=1.10' value: '>=1.10'
} }
] ]
const DeployModes = [
{
label: 'cluster',
value: 'cluster'
},
{
label: 'local',
value: 'local'
}
]

4
dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-http.ts

@ -23,7 +23,7 @@ export function useHttp(model: { [field: string]: any }): IJsonItem[] {
const { t } = useI18n() const { t } = useI18n()
const timeoutSpan = computed(() => (model.timeoutSetting ? 12 : 0)) const timeoutSpan = computed(() => (model.timeoutSetting ? 12 : 0))
const HTTP_CHECK_CONDITIONs = [ const HTTP_CHECK_CONDITIONS = [
{ {
label: t('project.node.status_code_default'), label: t('project.node.status_code_default'),
value: 'STATUS_CODE_DEFAULT' value: 'STATUS_CODE_DEFAULT'
@ -129,7 +129,7 @@ export function useHttp(model: { [field: string]: any }): IJsonItem[] {
type: 'select', type: 'select',
field: 'httpCheckCondition', field: 'httpCheckCondition',
name: t('project.node.http_check_condition'), name: t('project.node.http_check_condition'),
options: HTTP_CHECK_CONDITIONs options: HTTP_CHECK_CONDITIONS
}, },
{ {
type: 'input', type: 'input',

214
dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-rules.ts

@ -0,0 +1,214 @@
/*
* 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 {
queryRuleList,
getRuleFormCreateJson,
getDatasourceOptionsById
} from '@/service/modules/data-quality'
import {
getDatasourceTablesById,
getDatasourceTableColumnsById
} from '@/service/modules/data-source'
import type { IJsonItem, IResponseJsonItem, IJsonItemParams } from '../types'
export function useRules(
model: { [field: string]: any },
updateRules: (items: IJsonItem[], len: number) => void
): IJsonItem[] {
const { t } = useI18n()
const rules = ref([])
const ruleLoading = ref(false)
const srcDatasourceOptions = ref([] as { label: string; value: number }[])
const srcTableOptions = ref([] as { label: string; value: number }[])
const srcTableColumnOptions = ref([] as { label: string; value: number }[])
const targetDatasourceOptions = ref([] as { label: string; value: number }[])
const targetTableOptions = ref([] as { label: string; value: string }[])
const targetTableColumnOptions = ref([] as { label: string; value: number }[])
const writerDatasourceOptions = ref([] as { label: string; value: number }[])
let preItemLen = 0
const getRuleList = async () => {
if (ruleLoading.value) return
ruleLoading.value = true
try {
const result = await queryRuleList()
rules.value = result.map((item: { id: number; name: string }) => {
let name = ''
if (item.name) {
name = item.name.replace('$t(', '').replace(')', '')
}
return {
value: item.id,
label: name ? t(`project.node.${name}`) : ''
}
})
ruleLoading.value = false
} catch (err) {
ruleLoading.value = false
}
}
const getRuleById = async (ruleId: number) => {
if (ruleLoading.value) return
ruleLoading.value = true
try {
const result = await getRuleFormCreateJson(ruleId)
const items = JSON.parse(result).map((item: IResponseJsonItem) =>
formatResponseJson(item)
)
updateRules(items, preItemLen)
preItemLen = items.length
ruleLoading.value = false
} catch (err) {
ruleLoading.value = false
}
}
const formatResponseJson = (
responseItem: IResponseJsonItem
): IJsonItemParams => {
const item: IJsonItemParams = {
field: responseItem.field,
options: responseItem.options,
validate: responseItem.validate,
props: responseItem.props
}
let name = responseItem.name?.replace('$t(', '').replace(')', '')
item.name = name ? t(`project.node.${name}`) : ''
if (responseItem.type !== 'group') {
item.type = responseItem.type
} else {
item.type = 'custom-parameters'
item.children = item.props.rules.map((child: IJsonItemParams) => {
child.span = Math.floor(22 / item.props.rules.length)
return child
})
model[item.field] = []
delete item.props.rules
}
if (responseItem.emit) {
responseItem.emit.forEach((emit) => {
if (emit === 'change') {
item.props.onUpdateValue = (value: string | number) => {
onFieldChange(value, item.field)
}
}
})
}
if (item.field === 'src_datasource_id') {
item.options = srcDatasourceOptions
}
if (item.field === 'target_datasource_id') {
item.options = targetDatasourceOptions
}
if (item.field === 'writer_datasource_id') {
item.options = writerDatasourceOptions
}
if (item.field === 'src_table') {
item.options = srcTableOptions
}
if (item.field === 'target_table') {
item.options = targetTableOptions
}
if (item.field === 'src_field') {
item.options = srcTableColumnOptions
}
if (item.field === 'target_field') {
item.options = targetTableColumnOptions
}
return item
}
const onFieldChange = async (value: string | number, field: string) => {
try {
if (field === 'src_connector_type' && typeof value === 'number') {
const result = await getDatasourceOptionsById(value)
srcDatasourceOptions.value = result || []
srcTableOptions.value = []
model.src_datasource_id = null
model.src_table = null
model.src_field = null
return
}
if (field === 'target_connector_type' && typeof value === 'number') {
const result = await getDatasourceOptionsById(value)
targetDatasourceOptions.value = result || []
targetTableOptions.value = []
model.target_datasource_id = null
model.target_table = null
model.target_field = null
return
}
if (field === 'writer_connector_type' && typeof value === 'number') {
const result = await getDatasourceOptionsById(value)
writerDatasourceOptions.value = result || []
model.writer_datasource_id = null
return
}
if (field === 'src_datasource_id' && typeof value === 'number') {
const result = await getDatasourceTablesById(value)
srcTableOptions.value = result || []
model.src_table = null
model.src_field = null
}
if (field === 'target_datasource_id' && typeof value === 'number') {
const result = await getDatasourceTablesById(value)
targetTableOptions.value = result || []
model.target_table = null
model.target_field = null
}
if (field === 'src_table' && typeof value === 'string') {
const result = await getDatasourceTableColumnsById(
model.src_datasource_id,
value
)
srcTableColumnOptions.value = result || []
model.src_field = null
}
if (field === 'target_table' && typeof value === 'string') {
const result = await getDatasourceTableColumnsById(
model.target_datasource_id,
value
)
targetTableColumnOptions.value = result || []
model.target_field = null
}
} catch (err) {}
}
onMounted(async () => {
await getRuleList()
await getRuleById(model.ruleId)
})
return [
{
type: 'select',
field: 'ruleId',
name: t('project.node.rule_name'),
props: {
loading: ruleLoading,
onUpdateValue: getRuleById
},
options: rules
}
]
}

24
dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-sea-tunnel.ts

@ -17,27 +17,13 @@
import { ref, onMounted, watch, computed } from 'vue' import { ref, onMounted, watch, computed } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { queryResourceList } from '@/service/modules/resources' import { queryResourceList } from '@/service/modules/resources'
import { useDeployMode } from '.'
import type { IJsonItem } from '../types' import type { IJsonItem } from '../types'
export function useSeaTunnel(model: { [field: string]: any }): IJsonItem[] { export function useSeaTunnel(model: { [field: string]: any }): IJsonItem[] {
const { t } = useI18n() const { t } = useI18n()
const options = ref([]) const options = ref([])
const deployModeOptions = [
{
label: 'client',
value: 'client'
},
{
label: 'cluster',
value: 'cluster'
},
{
label: 'local',
value: 'local'
}
]
const masterTypeOptions = [ const masterTypeOptions = [
{ {
label: 'yarn', label: 'yarn',
@ -148,13 +134,7 @@ export function useSeaTunnel(model: { [field: string]: any }): IJsonItem[] {
) )
return [ return [
{ useDeployMode(),
type: 'radio',
field: 'deployMode',
name: t('project.node.sea_tunnel_deploy_mode'),
options: deployModeOptions,
value: model.deployMode
},
{ {
type: 'select', type: 'select',
field: 'master', field: 'master',

146
dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-spark.ts

@ -18,7 +18,15 @@ import { ref, onMounted, computed } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { queryResourceByProgramType } from '@/service/modules/resources' import { queryResourceByProgramType } from '@/service/modules/resources'
import { removeUselessChildren } from './use-shell' import { removeUselessChildren } from './use-shell'
import { useCustomParams } from '.' import {
useCustomParams,
useDeployMode,
useDriverCores,
useDriverMemory,
useExecutorNumber,
useExecutorMemory,
useExecutorCores
} from '.'
import type { IJsonItem, ProgramType } from '../types' import type { IJsonItem, ProgramType } from '../types'
export function useSpark(model: { [field: string]: any }): IJsonItem[] { export function useSpark(model: { [field: string]: any }): IJsonItem[] {
@ -116,12 +124,7 @@ export function useSpark(model: { [field: string]: any }): IJsonItem[] {
}, },
options: mainJarOptions options: mainJarOptions
}, },
{ useDeployMode(),
type: 'radio',
field: 'deployMode',
name: t('project.node.deploy_mode'),
options: DeployModes
},
{ {
type: 'input', type: 'input',
field: 'appName', field: 'appName',
@ -130,115 +133,11 @@ export function useSpark(model: { [field: string]: any }): IJsonItem[] {
placeholder: t('project.node.app_name_tips') placeholder: t('project.node.app_name_tips')
} }
}, },
{ useDriverCores(),
type: 'input-number', useDriverMemory(),
field: 'driverCores', useExecutorNumber(),
name: t('project.node.driver_cores'), useExecutorMemory(),
span: 12, useExecutorCores(),
props: {
placeholder: t('project.node.driver_cores_tips'),
min: 1
},
validate: {
trigger: ['input', 'blur'],
required: true,
validator(validate: any, value: string) {
if (!value) {
return new Error(t('project.node.driver_cores_tips'))
}
}
}
},
{
type: 'input',
field: 'driverMemory',
name: t('project.node.driver_memory'),
span: 12,
props: {
placeholder: t('project.node.driver_memory_tips')
},
validate: {
trigger: ['input', 'blur'],
required: true,
validator(validate: any, value: string) {
if (!value) {
return new Error(t('project.node.driver_memory_tips'))
}
if (!Number.isInteger(parseInt(value))) {
return new Error(
t('project.node.driver_memory') +
t('project.node.positive_integer_tips')
)
}
}
},
value: model.driverMemory
},
{
type: 'input-number',
field: 'numExecutors',
name: t('project.node.executor_number'),
span: 12,
props: {
placeholder: t('project.node.executor_number_tips'),
min: 1
},
validate: {
trigger: ['input', 'blur'],
required: true,
validator(validate: any, value: string) {
if (!value) {
return new Error(t('project.node.executor_number_tips'))
}
}
},
value: model.numExecutors
},
{
type: 'input',
field: 'executorMemory',
name: t('project.node.executor_memory'),
span: 12,
props: {
placeholder: t('project.node.executor_memory_tips')
},
validate: {
trigger: ['input', 'blur'],
required: true,
validator(validate: any, value: string) {
if (!value) {
return new Error(t('project.node.executor_memory_tips'))
}
if (!Number.isInteger(parseInt(value))) {
return new Error(
t('project.node.executor_memory_tips') +
t('project.node.positive_integer_tips')
)
}
}
},
value: model.executorMemory
},
{
type: 'input-number',
field: 'executorCores',
name: t('project.node.executor_cores'),
span: 12,
props: {
placeholder: t('project.node.executor_cores_tips'),
min: 1
},
validate: {
trigger: ['input', 'blur'],
required: true,
validator(validate: any, value: string) {
if (!value) {
return new Error(t('project.node.executor_cores_tips'))
}
}
},
value: model.executorCores
},
{ {
type: 'input', type: 'input',
field: 'mainArgs', field: 'mainArgs',
@ -302,18 +201,3 @@ export const SPARK_VERSIONS = [
value: 'SPARK1' value: 'SPARK1'
} }
] ]
export const DeployModes = [
{
label: 'cluster',
value: 'cluster'
},
{
label: 'client',
value: 'client'
},
{
label: 'local',
value: 'local'
}
]

53
dolphinscheduler-ui-next/src/views/projects/task/components/node/format-data.ts

@ -247,6 +247,34 @@ export function formatParams(data: INodeData): {
dependTaskList: dependTaskList dependTaskList: dependTaskList
} }
} }
if (data.taskType === 'DATA_QUALITY') {
taskParams.ruleId = data.ruleId
taskParams.ruleInputParameter = {
check_type: data.check_type,
comparison_execute_sql: data.comparison_execute_sql,
comparison_name: data.comparison_name,
failure_strategy: data.failure_strategy,
operator: data.operator,
src_connector_type: data.src_connector_type,
src_datasource_id: data.src_datasource_id,
src_table: data.src_table,
statistics_execute_sql: data.statistics_execute_sql,
statistics_name: data.statistics_name,
target_connector_type: data.target_connector_type,
target_datasource_id: data.target_datasource_id,
target_table: data.target_table,
threshold: data.threshold
}
taskParams.sparkParameters = {
deployMode: data.deployMode,
driverCores: data.driverCores,
driverMemory: data.driverMemory,
executorCores: data.executorCores,
executorMemory: data.executorMemory,
numExecutors: data.numExecutors,
others: data.others
}
}
const params = { const params = {
processDefinitionCode: data.processName ? String(data.processName) : '', processDefinitionCode: data.processName ? String(data.processName) : '',
@ -394,6 +422,31 @@ export function formatModel(data: ITaskData) {
params.dependTaskList = data.taskParams?.dependence.dependTaskList || [] params.dependTaskList = data.taskParams?.dependence.dependTaskList || []
params.relation = data.taskParams?.dependence.relation params.relation = data.taskParams?.dependence.relation
} }
if (data.taskParams?.ruleInputParameter) {
params.check_type = data.check_type
params.comparison_execute_sql = data.comparison_execute_sql
params.comparison_name = data.comparison_name
params.failure_strategy = data.failure_strategy
params.operator = data.operator
params.src_connector_type = data.src_connector_type
params.src_datasource_id = data.src_datasource_id
params.src_table = data.src_table
params.statistics_execute_sql = data.statistics_execute_sql
params.statistics_name = data.statistics_name
params.target_connector_type = data.target_connector_type
params.target_datasource_id = data.target_datasource_id
params.target_table = data.target_table
params.threshold = data.threshold
}
if (data.taskParams?.sparkParameters) {
params.deployMode = data.deployMode
params.driverCores = data.driverCores
params.driverMemory = data.driverMemory
params.executorCores = data.executorCores
params.executorMemory = data.executorMemory
params.numExecutors = data.numExecutors
params.others = data.others
}
return params return params
} }

54
dolphinscheduler-ui-next/src/views/projects/task/components/node/tasks/index.ts

@ -0,0 +1,54 @@
/*
* 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 { useFlink } from './use-flink'
import { useShell } from './use-shell'
import { useSubProcess } from './use-sub-process'
import { usePigeon } from './use-pigeon'
import { usePython } from './use-python'
import { useSpark } from './use-spark'
import { useMr } from './use-mr'
import { useHttp } from './use-http'
import { useSql } from './use-sql'
import { useProcedure } from './use-procedure'
import { useSqoop } from './use-sqoop'
import { useSeaTunnel } from './use-sea-tunnel'
import { useSwitch } from './use-switch'
import { useConditions } from './use-conditions'
import { useDataX } from './use-datax'
import { useDependent } from './use-dependent'
import { useDataQuality } from './use-data-quality'
export default {
SHELL: useShell,
SUB_PROCESS: useSubProcess,
PYTHON: usePython,
SPARK: useSpark,
MR: useMr,
FLINK: useFlink,
HTTP: useHttp,
PIGEON: usePigeon,
SQL: useSql,
PROCEDURE: useProcedure,
SQOOP: useSqoop,
SEATUNNEL: useSeaTunnel,
SWITCH: useSwitch,
CONDITIONS: useConditions,
DATAX: useDataX,
DEPENDENT: useDependent,
DATA_QUALITY: useDataQuality
}

116
dolphinscheduler-ui-next/src/views/projects/task/components/node/tasks/use-data-quality.ts

@ -0,0 +1,116 @@
/*
* 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 } from 'vue'
import { useI18n } from 'vue-i18n'
import * as Fields from '../fields/index'
import type { IJsonItem, INodeData, ITaskData } from '../types'
export function useDataQuality({
projectCode,
from = 0,
readonly,
data,
jsonRef
}: {
projectCode: number
from?: number
readonly?: boolean
data?: ITaskData
jsonRef: Ref<IJsonItem[]>
}) {
const { t } = useI18n()
const model = reactive({
taskType: 'DATA_QUALITY',
name: '',
flag: 'YES',
description: '',
timeoutFlag: false,
timeoutNotifyStrategy: ['WARN'],
timeout: 30,
localParams: [],
environmentCode: null,
failRetryInterval: 1,
failRetryTimes: 0,
workerGroup: 'default',
delayTime: 0,
ruleId: 1,
deployMode: 'cluster',
driverCores: 1,
driverMemory: '512M',
numExecutors: 2,
executorMemory: '2G',
executorCores: 2,
others: '--conf spark.yarn.maxAppAttempts=1'
} 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
})
]
}
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.useDelayTime(model),
...Fields.useTimeoutAlarm(model),
...Fields.useRules(model, (items: IJsonItem[], len: number) => {
jsonRef.value.splice(17, len, ...items)
}),
Fields.useDeployMode(),
Fields.useDriverCores(),
Fields.useDriverMemory(),
Fields.useExecutorNumber(),
Fields.useExecutorMemory(),
Fields.useExecutorCores(),
{
type: 'input',
field: 'others',
name: t('project.node.option_parameters'),
props: {
type: 'textarea',
placeholder: t('project.node.option_parameters_tips')
}
},
...Fields.useCustomParams({
model,
field: 'localParams',
isSimple: true
}),
Fields.usePreTasks(model)
] as IJsonItem[],
model
}
}

1
dolphinscheduler-ui-next/src/views/projects/task/components/node/tasks/use-flink.ts

@ -31,6 +31,7 @@ export function useFlink({
data?: ITaskData data?: ITaskData
}) { }) {
const model = reactive<INodeData>({ const model = reactive<INodeData>({
taskType: 'FLINK',
name: '', name: '',
flag: 'YES', flag: 'YES',
description: '', description: '',

1
dolphinscheduler-ui-next/src/views/projects/task/components/node/tasks/use-pigeon.ts

@ -31,6 +31,7 @@ export function usePigeon({
data?: ITaskData data?: ITaskData
}) { }) {
const model = reactive({ const model = reactive({
taskType: 'PIGEON',
name: '', name: '',
flag: 'YES', flag: 'YES',
description: '', description: '',

1
dolphinscheduler-ui-next/src/views/projects/task/components/node/tasks/use-sub-process.ts

@ -31,6 +31,7 @@ export function useSubProcess({
data?: ITaskData data?: ITaskData
}) { }) {
const model = reactive({ const model = reactive({
taskType: 'SUB_PROCESS',
name: '', name: '',
flag: 'YES', flag: 'YES',
description: '', description: '',

58
dolphinscheduler-ui-next/src/views/projects/task/components/node/types.ts

@ -17,9 +17,15 @@
import { VNode } from 'vue' import { VNode } from 'vue'
import type { SelectOption } from 'naive-ui' import type { SelectOption } from 'naive-ui'
import type { IFormItem, IJsonItem } from '@/components/form/types'
import type { TaskType } from '@/views/projects/task/constants/task-type' import type { TaskType } from '@/views/projects/task/constants/task-type'
import type { IDataBase } from '@/service/modules/data-source/types' import type { IDataBase } from '@/service/modules/data-source/types'
import type {
IFormItem,
IJsonItem,
FormRules,
IJsonItemParams
} from '@/components/form/types'
type ProgramType = 'JAVA' | 'SCALA' | 'PYTHON' type ProgramType = 'JAVA' | 'SCALA' | 'PYTHON'
type SourceType = 'MYSQL' | 'HDFS' | 'HIVE' type SourceType = 'MYSQL' | 'HDFS' | 'HIVE'
@ -49,6 +55,11 @@ interface ILocalParam {
value?: string value?: string
} }
interface IResponseJsonItem extends Omit<IJsonItemParams, 'type'> {
type: 'input' | 'select' | 'radio' | 'group'
emit: 'change'[]
}
interface IDependpendItem { interface IDependpendItem {
depTaskCode?: number depTaskCode?: number
status?: 'SUCCESS' | 'FAILURE' status?: 'SUCCESS' | 'FAILURE'
@ -161,6 +172,33 @@ interface ISqoopSourceParams {
hivePartitionKey?: string hivePartitionKey?: string
hivePartitionValue?: string hivePartitionValue?: string
} }
interface ISparkParameters {
deployMode?: string
driverCores?: number
driverMemory?: string
executorCores?: number
executorMemory?: string
numExecutors?: number
others?: string
}
interface IRuleParameters {
check_type?: string
comparison_execute_sql?: string
comparison_name?: string
failure_strategy?: string
operator?: string
src_connector_type?: number
src_datasource_id?: number
src_table?: string
statistics_execute_sql?: string
statistics_name?: string
target_connector_type?: number
target_datasource_id?: number
target_table?: string
threshold?: string
}
interface ITaskParams { interface ITaskParams {
resourceList?: ISourceItem[] resourceList?: ISourceItem[]
mainJar?: ISourceItem mainJar?: ISourceItem
@ -229,6 +267,9 @@ interface ITaskParams {
jobSpeedRecord?: number jobSpeedRecord?: number
xms?: number xms?: number
xmx?: number xmx?: number
sparkParameters?: ISparkParameters
ruleId?: number
ruleInputParameter?: IRuleParameters
} }
interface INodeData interface INodeData
@ -239,9 +280,11 @@ interface INodeData
| 'targetParams' | 'targetParams'
| 'sourceParams' | 'sourceParams'
| 'dependence' | 'dependence'
| 'sparkParameters'
>, >,
ISqoopTargetData, ISqoopTargetData,
ISqoopSourceData { ISqoopSourceData,
IRuleParameters {
id?: string id?: string
taskType?: ITaskType taskType?: ITaskType
processName?: number processName?: number
@ -280,7 +323,7 @@ interface ITaskData
> { > {
name?: string name?: string
taskPriority?: string taskPriority?: string
timeoutFlag: 'OPEN' | 'CLOSE' timeoutFlag?: 'OPEN' | 'CLOSE'
timeoutNotifyStrategy?: string | [] timeoutNotifyStrategy?: string | []
taskParams?: ITaskParams taskParams?: ITaskParams
} }
@ -292,8 +335,6 @@ export {
ITaskType, ITaskType,
ITaskData, ITaskData,
INodeData, INodeData,
IFormItem,
IJsonItem,
ITaskParams, ITaskParams,
IOption, IOption,
IDataBase, IDataBase,
@ -303,5 +344,10 @@ export {
ISqoopSourceParams, ISqoopSourceParams,
ISqoopTargetParams, ISqoopTargetParams,
IDependTask, IDependTask,
IDependpendItem IDependpendItem,
IFormItem,
IJsonItem,
FormRules,
IJsonItemParams,
IResponseJsonItem
} }

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

@ -14,24 +14,10 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { ref, Ref, watch } from 'vue'
import { useFlink } from './tasks/use-flink' import nodes from './tasks'
import { useShell } from './tasks/use-shell' import getElementByJson from '@/components/form/get-elements-by-json'
import { useSubProcess } from './tasks/use-sub-process' import { IFormItem, IJsonItem, INodeData, ITaskData, FormRules } from './types'
import { usePigeon } from './tasks/use-pigeon'
import { usePython } from './tasks/use-python'
import { useSpark } from './tasks/use-spark'
import { useMr } from './tasks/use-mr'
import { useHttp } from './tasks/use-http'
import { useSql } from './tasks/use-sql'
import { useProcedure } from './tasks/use-procedure'
import { useSqoop } from './tasks/use-sqoop'
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({ export function useTask({
data, data,
@ -43,140 +29,39 @@ export function useTask({
projectCode: number projectCode: number
from?: number from?: number
readonly?: boolean readonly?: boolean
}): { json: IJsonItem[]; model: INodeData } { }): {
const { taskType = 'SHELL' } = data elementsRef: Ref<IFormItem[]>
let node = {} as { json: IJsonItem[]; model: INodeData } rulesRef: Ref<FormRules>
if (taskType === 'SHELL') { model: INodeData
node = useShell({ } {
projectCode, const jsonRef = ref([]) as Ref<IJsonItem[]>
from, const elementsRef = ref([]) as Ref<IFormItem[]>
readonly, const rulesRef = ref({})
data const params = {
}) projectCode,
} from,
if (taskType === 'SUB_PROCESS') { readonly,
node = useSubProcess({ data,
projectCode, jsonRef
from,
readonly,
data
})
}
if (taskType === 'PYTHON') {
node = usePython({
projectCode,
from,
readonly,
data
})
}
if (taskType === 'SPARK') {
node = useSpark({
projectCode,
from,
readonly,
data
})
}
if (taskType === 'MR') {
node = useMr({
projectCode,
from,
readonly,
data
})
}
if (taskType === 'FLINK') {
node = useFlink({
projectCode,
from,
readonly,
data
})
}
if (taskType === 'HTTP') {
node = useHttp({
projectCode,
from,
readonly,
data
})
}
if (taskType === 'PIGEON') {
node = usePigeon({
projectCode,
from,
readonly,
data
})
}
if (taskType === 'SQL') {
node = useSql({
projectCode,
from,
readonly,
data
})
}
if (taskType === 'PROCEDURE') {
node = useProcedure({
projectCode,
from,
readonly,
data
})
}
if (taskType === 'SQOOP') {
node = useSqoop({
projectCode,
from,
readonly,
data
})
}
if (taskType === 'SEATUNNEL') {
node = useSeaTunnel({
projectCode,
from,
readonly,
data
})
} }
if (taskType === 'SWITCH') { const { model, json } = nodes[data.taskType || 'SHELL'](params)
node = useSwitch({ jsonRef.value = json
projectCode,
from,
readonly,
data
})
}
if (taskType === 'CONDITIONS') { const getElements = () => {
node = useConditions({ const { rules, elements } = getElementByJson(jsonRef.value, model)
projectCode, elementsRef.value = elements
from, rulesRef.value = rules
readonly,
data
})
} }
if (taskType === 'DATAX') { getElements()
node = useDataX({
projectCode, watch(
from, () => jsonRef.value.length,
readonly, () => {
data getElements()
}) }
} )
if (taskType === 'DEPENDENT') {
node = useDependent({
projectCode,
from,
readonly,
data
})
}
return node return { elementsRef, rulesRef, model }
} }

3
dolphinscheduler-ui-next/src/views/projects/task/constants/task-type.ts

@ -58,6 +58,9 @@ export const TASK_TYPES_MAP = {
CONDITIONS: { CONDITIONS: {
alias: 'CONDITIONS' alias: 'CONDITIONS'
}, },
DATA_QUALITY: {
alias: 'DATA_QUALITY'
},
SWITCH: { SWITCH: {
alias: 'SWITCH' alias: 'SWITCH'
}, },

2
dolphinscheduler-ui-next/src/views/projects/task/definition/use-task.ts

@ -27,7 +27,7 @@ import type { ITaskData, INodeData, ISingleSaveReq, IRecord } from './types'
export function useTask(projectCode: number) { export function useTask(projectCode: number) {
const initalTask = { const initalTask = {
taskType: 'DEPENDENT' taskType: 'SHELL'
} as ITaskData } as ITaskData
const task = reactive({ const task = reactive({
taskShow: false, taskShow: false,

Loading…
Cancel
Save