Browse Source

copy configs from taskDefinition (#6179)

2.0.7-release
Wangyizhi1 3 years ago committed by GitHub
parent
commit
ca488fcfa6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 232
      dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/_source/copyFromTask.vue
  2. 710
      dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/formModel.vue
  3. 9
      dolphinscheduler-ui/src/js/conf/home/store/dag/actions.js
  4. 4
      dolphinscheduler-ui/src/js/module/i18n/locale/en_US.js
  5. 4
      dolphinscheduler-ui/src/js/module/i18n/locale/zh_CN.js

232
dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/_source/copyFromTask.vue

@ -0,0 +1,232 @@
/*
* 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.
*/
<template>
<list-box>
<div slot="text">{{ $t("Copy from") }}</div>
<div slot="content" class="copy-from" ref="copyFrom">
<div class="copy-from-content">
<el-input
class="copy-from-input"
v-model="searchVal"
:placeholder="getTaskName(value) || $t('Please choose')"
@focus="inputFocus"
@input="searchValChange"
size="small"
:suffix-icon="
dropdownVisible ? 'el-icon-arrow-up' : 'el-icon-arrow-down'
"
></el-input>
<div class="copy-from-dropdown" v-show="dropdownVisible">
<div class="scroll-box">
<ul v-infinite-scroll="load">
<li
v-for="taskDefinition in taskDefinitions"
:key="taskDefinition.code"
class="dropdown-item"
@click="itemClick(taskDefinition)"
>
{{ taskDefinition.name }}
</li>
</ul>
<p class="dropdown-msg" v-if="loading">{{ $t("Loading...") }}</p>
<p class="dropdown-msg" v-if="noMore">{{ $t("No more...") }}</p>
</div>
</div>
</div>
</div>
</list-box>
</template>
<script>
import ListBox from '../tasks/_source/listBox'
import { mapActions } from 'vuex'
export default {
name: 'copy-from-task',
props: {
taskType: String
},
inject: ['formModel'],
data () {
return {
pageNo: 1,
pageSize: 10,
searchVal: '',
value: '',
loading: false,
noMore: false,
taskDefinitions: [],
dropdownVisible: false
}
},
mounted () {
document.addEventListener('click', this.outsideClick)
this.load()
},
destroyed () {
document.removeEventListener('click', this.outsideClick)
},
methods: {
...mapActions('dag', ['getTaskDefinitions']),
outsideClick (e) {
const elem = this.$refs.copyFrom
if (!elem.contains(e.target) && this.dropdownVisible) {
this.dropdownVisible = false
}
},
searchValChange (val) {
this.load(true)
},
load (override) {
if (this.loading) return
if (override) {
this.noMore = false
this.pageNo = 1
}
if (this.noMore) return
this.loading = true
this.getTaskDefinitions({
pageNo: this.pageNo,
pageSize: this.pageSize,
searchVal: this.searchVal,
taskType: this.taskType
}).then((res) => {
this.taskDefinitions = override ? res.totalList : this.taskDefinitions.concat(res.totalList)
this.pageNo = res.currentPage + 1
this.noMore = this.taskDefinitions.length >= res.total
this.loading = false
})
},
itemClick (taskDefinition) {
this.value = taskDefinition.code
this.searchVal = taskDefinition.name
this.dropdownVisible = false
if (this.formModel) {
const backfillItem = this.formModel.taskToBackfillItem(taskDefinition)
this.formModel.backfillRefresh = false
this.$nextTick(() => {
this.formModel.backfillItem = backfillItem
this.formModel.backfill(backfillItem, true)
this.formModel.backfillRefresh = true
})
}
},
inputFocus () {
this.searchVal = ''
this.dropdownVisible = true
},
inputBlur () {
this.dropdownVisible = false
},
getTaskName (code) {
const taskDefinition = this.taskDefinitions.find(
(taskDefinition) => taskDefinition.code === code
)
return taskDefinition ? taskDefinition.name : ''
}
},
components: {
ListBox
}
}
</script>
<style lang="scss" scoped>
.copy-from {
position: relative;
&-content {
width: 100%;
}
&-input {
width: 100%;
}
&-dropdown {
width: 100%;
position: absolute;
padding: 6px 0;
top: 42px;
left: 0;
z-index: 10;
border: 1px solid #e4e7ed;
border-radius: 4px;
background-color: #fff;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
.scroll-box {
width: 100%;
max-height: 200px;
overflow: auto;
}
.dropdown-item {
font-size: 14px;
padding: 0 20px;
position: relative;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #606266;
height: 34px;
line-height: 34px;
box-sizing: border-box;
cursor: pointer;
&:hover {
background-color: #f5f7fa;
}
&.selected {
color: #409eff;
font-weight: 700;
}
}
&:before,
&:after {
content: "";
position: absolute;
display: block;
width: 0;
height: 0;
top: -6px;
left: 35px;
border-width: 6px;
border-top-width: 0;
border-color: transparent;
border-bottom-color: #fff;
border-style: solid;
z-index: 10;
}
&:before {
top: -8px;
left: 33px;
border-width: 8px;
border-top-width: 0;
border-bottom-color: #ebeef5;
z-index: 9;
}
.dropdown-msg {
text-align: center;
color: #666;
font-size: 12px;
line-height: 34px;
margin: 0;
}
}
}
</style>

710
dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/formModel.vue

@ -17,21 +17,38 @@
<template> <template>
<div class="form-model-wrapper" v-clickoutside="_handleClose"> <div class="form-model-wrapper" v-clickoutside="_handleClose">
<div class="title-box"> <div class="title-box">
<span class="name">{{$t('Current node settings')}}</span> <span class="name">{{ $t("Current node settings") }}</span>
<span class="go-subtask"> <span class="go-subtask">
<!-- Component can't pop up box to do component processing --> <!-- Component can't pop up box to do component processing -->
<m-log v-if="taskInstance" :item="backfillItem" :task-instance-id="taskInstance.id"> <m-log
<template slot="history"><a href="javascript:" @click="_seeHistory" ><em class="ansicon el-icon-alarm-clock"></em><em>{{$t('View history')}}</em></a></template> v-if="taskInstance"
<template slot="log"><a href="javascript:"><em class="ansicon el-icon-document"></em><em>{{$t('View log')}}</em></a></template> :item="backfillItem"
:task-instance-id="taskInstance.id"
>
<template slot="history"
><a href="javascript:" @click="_seeHistory"
><em class="ansicon el-icon-alarm-clock"></em
><em>{{ $t("View history") }}</em></a
></template
>
<template slot="log"
><a href="javascript:"
><em class="ansicon el-icon-document"></em
><em>{{ $t("View log") }}</em></a
></template
>
</m-log> </m-log>
<a href="javascript:" @click="_goSubProcess" v-if="_isGoSubProcess"><em class="ansicon ri-node-tree"></em><em>{{$t('Enter this child node')}}</em></a> <a href="javascript:" @click="_goSubProcess" v-if="_isGoSubProcess"
><em class="ansicon ri-node-tree"></em
><em>{{ $t("Enter this child node") }}</em></a
>
</span> </span>
</div> </div>
<div class="content-box" v-if="isContentBox"> <div class="content-box" v-if="isContentBox">
<div class="form-model"> <div class="form-model">
<!-- Node name --> <!-- Node name -->
<m-list-box> <m-list-box>
<div slot="text">{{$t('Node name')}}</div> <div slot="text">{{ $t("Node name") }}</div>
<div slot="content"> <div slot="content">
<el-input <el-input
type="text" type="text"
@ -40,41 +57,50 @@
:disabled="isDetails" :disabled="isDetails"
:placeholder="$t('Please enter name (required)')" :placeholder="$t('Please enter name (required)')"
maxlength="100" maxlength="100"
@blur="_verifName()"> @blur="_verifName()"
>
</el-input> </el-input>
</div> </div>
</m-list-box> </m-list-box>
<!-- Copy from task -->
<copy-from-task v-if="!isDetails" :taskType="nodeData.taskType" />
<!-- Running sign --> <!-- Running sign -->
<m-list-box> <m-list-box>
<div slot="text">{{$t('Run flag')}}</div> <div slot="text">{{ $t("Run flag") }}</div>
<div slot="content"> <div slot="content">
<el-radio-group v-model="runFlag" size="small"> <el-radio-group v-model="runFlag" size="small">
<el-radio :label="'YES'" :disabled="isDetails">{{$t('Normal')}}</el-radio> <el-radio :label="'YES'" :disabled="isDetails">{{
<el-radio :label="'NO'" :disabled="isDetails">{{$t('Prohibition execution')}}</el-radio> $t("Normal")
}}</el-radio>
<el-radio :label="'NO'" :disabled="isDetails">{{
$t("Prohibition execution")
}}</el-radio>
</el-radio-group> </el-radio-group>
</div> </div>
</m-list-box> </m-list-box>
<!-- description --> <!-- description -->
<m-list-box> <m-list-box>
<div slot="text">{{$t('Description')}}</div> <div slot="text">{{ $t("Description") }}</div>
<div slot="content"> <div slot="content">
<el-input <el-input
:rows="2" :rows="2"
type="textarea" type="textarea"
:disabled="isDetails" :disabled="isDetails"
v-model="desc" v-model="desc"
:placeholder="$t('Please enter description')"> :placeholder="$t('Please enter description')"
>
</el-input> </el-input>
</div> </div>
</m-list-box> </m-list-box>
<!-- Task priority --> <!-- Task priority -->
<m-list-box> <m-list-box>
<div slot="text">{{$t('Task priority')}}</div> <div slot="text">{{ $t("Task priority") }}</div>
<div slot="content"> <div slot="content">
<span class="label-box" style="width: 193px;display: inline-block;"> <span class="label-box" style="width: 193px; display: inline-block">
<m-priority v-model="taskInstancePriority"></m-priority> <m-priority v-model="taskInstancePriority"></m-priority>
</span> </span>
</div> </div>
@ -82,207 +108,305 @@
<!-- Worker group and environment --> <!-- Worker group and environment -->
<m-list-box> <m-list-box>
<div slot="text">{{$t('Worker group')}}</div> <div slot="text">{{ $t("Worker group") }}</div>
<div slot="content"> <div slot="content">
<span class="label-box" style="width: 193px;display: inline-block;"> <span class="label-box" style="width: 193px; display: inline-block">
<m-worker-groups v-model="workerGroup"></m-worker-groups> <m-worker-groups v-model="workerGroup"></m-worker-groups>
</span> </span>
<span class="text-b">{{$t('Environment Name')}}</span> <span class="text-b">{{ $t("Environment Name") }}</span>
<m-related-environment v-model="environmentCode" :workerGroup="workerGroup" v-on:environmentCodeEvent="_onUpdateEnvironmentCode"></m-related-environment> <m-related-environment
v-model="environmentCode"
:workerGroup="workerGroup"
v-on:environmentCodeEvent="_onUpdateEnvironmentCode"
></m-related-environment>
</div> </div>
</m-list-box> </m-list-box>
<!-- Number of failed retries --> <!-- Number of failed retries -->
<m-list-box v-if="nodeData.taskType !== 'SUB_PROCESS'"> <m-list-box v-if="nodeData.taskType !== 'SUB_PROCESS'">
<div slot="text">{{$t('Number of failed retries')}}</div> <div slot="text">{{ $t("Number of failed retries") }}</div>
<div slot="content"> <div slot="content">
<m-select-input v-model="maxRetryTimes" :list="[0,1,2,3,4]"></m-select-input> <m-select-input
<span>({{$t('Times')}})</span> v-model="maxRetryTimes"
<span class="text-b">{{$t('Failed retry interval')}}</span> :list="[0, 1, 2, 3, 4]"
<m-select-input v-model="retryInterval" :list="[1,10,30,60,120]"></m-select-input> ></m-select-input>
<span>({{$t('Minute')}})</span> <span>({{ $t("Times") }})</span>
<span class="text-b">{{ $t("Failed retry interval") }}</span>
<m-select-input
v-model="retryInterval"
:list="[1, 10, 30, 60, 120]"
></m-select-input>
<span>({{ $t("Minute") }})</span>
</div> </div>
</m-list-box> </m-list-box>
<!-- Delay execution time --> <!-- Delay execution time -->
<m-list-box v-if="nodeData.taskType !== 'SUB_PROCESS' && nodeData.taskType !== 'CONDITIONS' && nodeData.taskType !== 'DEPENDENT'&& nodeData.taskType !== 'SWITCH'"> <m-list-box
<div slot="text">{{$t('Delay execution time')}}</div> v-if="
nodeData.taskType !== 'SUB_PROCESS' &&
nodeData.taskType !== 'CONDITIONS' &&
nodeData.taskType !== 'DEPENDENT' &&
nodeData.taskType !== 'SWITCH'
"
>
<div slot="text">{{ $t("Delay execution time") }}</div>
<div slot="content"> <div slot="content">
<m-select-input v-model="delayTime" :list="[0,1,5,10]"></m-select-input> <m-select-input
<span>({{$t('Minute')}})</span> v-model="delayTime"
:list="[0, 1, 5, 10]"
></m-select-input>
<span>({{ $t("Minute") }})</span>
</div> </div>
</m-list-box> </m-list-box>
<!-- Branch flow --> <!-- Branch flow -->
<m-list-box v-if="nodeData.taskType === 'CONDITIONS'"> <m-list-box v-if="nodeData.taskType === 'CONDITIONS'">
<div slot="text">{{$t('State')}}</div> <div slot="text">{{ $t("State") }}</div>
<div slot="content"> <div slot="content">
<span class="label-box" style="width: 193px;display: inline-block;"> <span class="label-box" style="width: 193px; display: inline-block">
<el-select style="width: 157px;" size="small" v-model="successNode" :disabled="true"> <el-select
<el-option v-for="item in stateList" :key="item.value" :value="item.value" :label="item.label"></el-option> style="width: 157px"
size="small"
v-model="successNode"
:disabled="true"
>
<el-option
v-for="item in stateList"
:key="item.value"
:value="item.value"
:label="item.label"
></el-option>
</el-select> </el-select>
</span> </span>
<span class="text-b" style="padding-left: 38px">{{$t('Branch flow')}}</span> <span class="text-b" style="padding-left: 38px">{{
<el-select style="width: 157px;" size="small" v-model="successBranch" clearable :disabled="isDetails"> $t("Branch flow")
<el-option v-for="item in postTasks" :key="item.code" :value="item.name" :label="item.name"></el-option> }}</span>
<el-select
style="width: 157px"
size="small"
v-model="successBranch"
clearable
:disabled="isDetails"
>
<el-option
v-for="item in postTasks"
:key="item.code"
:value="item.name"
:label="item.name"
></el-option>
</el-select> </el-select>
</div> </div>
</m-list-box> </m-list-box>
<m-list-box v-if="nodeData.taskType === 'CONDITIONS'"> <m-list-box v-if="nodeData.taskType === 'CONDITIONS'">
<div slot="text">{{$t('State')}}</div> <div slot="text">{{ $t("State") }}</div>
<div slot="content"> <div slot="content">
<span class="label-box" style="width: 193px;display: inline-block;"> <span class="label-box" style="width: 193px; display: inline-block">
<el-select style="width: 157px;" size="small" v-model="failedNode" :disabled="true"> <el-select
<el-option v-for="item in stateList" :key="item.value" :value="item.value" :label="item.label"></el-option> style="width: 157px"
size="small"
v-model="failedNode"
:disabled="true"
>
<el-option
v-for="item in stateList"
:key="item.value"
:value="item.value"
:label="item.label"
></el-option>
</el-select> </el-select>
</span> </span>
<span class="text-b" style="padding-left: 38px">{{$t('Branch flow')}}</span> <span class="text-b" style="padding-left: 38px">{{
<el-select style="width: 157px;" size="small" v-model="failedBranch" clearable :disabled="isDetails"> $t("Branch flow")
<el-option v-for="item in postTasks" :key="item.code" :value="item.name" :label="item.name"></el-option> }}</span>
<el-select
style="width: 157px"
size="small"
v-model="failedBranch"
clearable
:disabled="isDetails"
>
<el-option
v-for="item in postTasks"
:key="item.code"
:value="item.name"
:label="item.name"
></el-option>
</el-select> </el-select>
</div> </div>
</m-list-box> </m-list-box>
<!-- Task timeout alarm --> <div v-if="backfillRefresh">
<m-timeout-alarm <!-- Task timeout alarm -->
v-if="nodeData.taskType !== 'DEPENDENT'" <m-timeout-alarm
ref="timeout" v-if="nodeData.taskType !== 'DEPENDENT'"
:backfill-item="backfillItem" ref="timeout"
@on-timeout="_onTimeout"> :backfill-item="backfillItem"
</m-timeout-alarm> @on-timeout="_onTimeout"
<!-- Dependent timeout alarm --> >
<m-dependent-timeout </m-timeout-alarm>
v-if="nodeData.taskType === 'DEPENDENT'" <!-- Dependent timeout alarm -->
ref="dependentTimeout" <m-dependent-timeout
:backfill-item="backfillItem" v-if="nodeData.taskType === 'DEPENDENT'"
@on-timeout="_onDependentTimeout"> ref="dependentTimeout"
</m-dependent-timeout> :backfill-item="backfillItem"
@on-timeout="_onDependentTimeout"
>
</m-dependent-timeout>
<!-- shell node --> <!-- shell node -->
<m-shell <m-shell
v-if="nodeData.taskType === 'SHELL'" v-if="nodeData.taskType === 'SHELL'"
@on-params="_onParams" @on-params="_onParams"
@on-cache-params="_onCacheParams" @on-cache-params="_onCacheParams"
ref="SHELL" ref="SHELL"
:backfill-item="backfillItem"> :backfill-item="backfillItem"
</m-shell> >
<!-- waterdrop node --> </m-shell>
<m-waterdrop <!-- waterdrop node -->
v-if="nodeData.taskType === 'WATERDROP'" <m-waterdrop
@on-params="_onParams" v-if="nodeData.taskType === 'WATERDROP'"
@on-cache-params="_onCacheParams" @on-params="_onParams"
ref="WATERDROP" @on-cache-params="_onCacheParams"
:backfill-item="backfillItem"> ref="WATERDROP"
</m-waterdrop> :backfill-item="backfillItem"
<!-- sub_process node --> >
<m-sub-process </m-waterdrop>
v-if="nodeData.taskType === 'SUB_PROCESS'" <!-- sub_process node -->
@on-params="_onParams" <m-sub-process
@on-cache-params="_onCacheParams" v-if="nodeData.taskType === 'SUB_PROCESS'"
@on-set-process-name="_onSetProcessName" @on-params="_onParams"
ref="SUB_PROCESS" @on-cache-params="_onCacheParams"
:backfill-item="backfillItem"> @on-set-process-name="_onSetProcessName"
</m-sub-process> ref="SUB_PROCESS"
<!-- procedure node --> :backfill-item="backfillItem"
<m-procedure >
v-if="nodeData.taskType === 'PROCEDURE'" </m-sub-process>
@on-params="_onParams" <!-- procedure node -->
@on-cache-params="_onCacheParams" <m-procedure
ref="PROCEDURE" v-if="nodeData.taskType === 'PROCEDURE'"
:backfill-item="backfillItem"> @on-params="_onParams"
</m-procedure> @on-cache-params="_onCacheParams"
<!-- sql node --> ref="PROCEDURE"
<m-sql :backfill-item="backfillItem"
v-if="nodeData.taskType === 'SQL'" >
@on-params="_onParams" </m-procedure>
@on-cache-params="_onCacheParams" <!-- sql node -->
ref="SQL" <m-sql
:create-node-id="nodeData.id" v-if="nodeData.taskType === 'SQL'"
:backfill-item="backfillItem"> @on-params="_onParams"
</m-sql> @on-cache-params="_onCacheParams"
<!-- spark node --> ref="SQL"
<m-spark :create-node-id="nodeData.id"
v-if="nodeData.taskType === 'SPARK'" :backfill-item="backfillItem"
@on-params="_onParams" >
@on-cache-params="_onCacheParams" </m-sql>
ref="SPARK" <!-- spark node -->
:backfill-item="backfillItem"> <m-spark
</m-spark> v-if="nodeData.taskType === 'SPARK'"
<m-flink @on-params="_onParams"
v-if="nodeData.taskType === 'FLINK'" @on-cache-params="_onCacheParams"
@on-params="_onParams" ref="SPARK"
@on-cache-params="_onCacheParams" :backfill-item="backfillItem"
ref="FLINK" >
:backfill-item="backfillItem"> </m-spark>
</m-flink> <m-flink
<!-- mr node --> v-if="nodeData.taskType === 'FLINK'"
<m-mr @on-params="_onParams"
v-if="nodeData.taskType === 'MR'" @on-cache-params="_onCacheParams"
@on-params="_onParams" ref="FLINK"
@on-cache-params="_onCacheParams" :backfill-item="backfillItem"
ref="MR" >
:backfill-item="backfillItem"> </m-flink>
</m-mr> <!-- mr node -->
<!-- python node --> <m-mr
<m-python v-if="nodeData.taskType === 'MR'"
v-if="nodeData.taskType === 'PYTHON'" @on-params="_onParams"
@on-params="_onParams" @on-cache-params="_onCacheParams"
@on-cache-params="_onCacheParams" ref="MR"
ref="PYTHON" :backfill-item="backfillItem"
:backfill-item="backfillItem"> >
</m-python> </m-mr>
<!-- dependent node --> <!-- python node -->
<m-dependent <m-python
v-if="nodeData.taskType === 'DEPENDENT'" v-if="nodeData.taskType === 'PYTHON'"
@on-dependent="_onDependent" @on-params="_onParams"
@on-cache-dependent="_onCacheDependent" @on-cache-params="_onCacheParams"
ref="DEPENDENT" ref="PYTHON"
:backfill-item="backfillItem"> :backfill-item="backfillItem"
</m-dependent> >
<m-http </m-python>
v-if="nodeData.taskType === 'HTTP'" <!-- dependent node -->
@on-params="_onParams" <m-dependent
@on-cache-params="_onCacheParams" v-if="nodeData.taskType === 'DEPENDENT'"
ref="HTTP" @on-dependent="_onDependent"
:backfill-item="backfillItem"> @on-cache-dependent="_onCacheDependent"
</m-http> ref="DEPENDENT"
<m-datax :backfill-item="backfillItem"
v-if="nodeData.taskType === 'DATAX'" >
@on-params="_onParams" </m-dependent>
@on-cache-params="_onCacheParams" <m-http
ref="DATAX" v-if="nodeData.taskType === 'HTTP'"
:backfill-item="backfillItem"> @on-params="_onParams"
</m-datax> @on-cache-params="_onCacheParams"
<m-sqoop ref="HTTP"
v-if="nodeData.taskType === 'SQOOP'" :backfill-item="backfillItem"
@on-params="_onParams" >
@on-cache-params="_onCacheParams" </m-http>
ref="SQOOP" <m-datax
:backfill-item="backfillItem"> v-if="nodeData.taskType === 'DATAX'"
</m-sqoop> @on-params="_onParams"
<m-conditions @on-cache-params="_onCacheParams"
v-if="nodeData.taskType === 'CONDITIONS'" ref="DATAX"
ref="CONDITIONS" :backfill-item="backfillItem"
@on-dependent="_onDependent" >
@on-cache-dependent="_onCacheDependent" </m-datax>
:backfill-item="backfillItem" <m-sqoop
:prev-tasks="prevTasks"> v-if="nodeData.taskType === 'SQOOP'"
</m-conditions> @on-params="_onParams"
<m-switch @on-cache-params="_onCacheParams"
v-if="nodeData.taskType === 'SWITCH'" ref="SQOOP"
ref="SWITCH" :backfill-item="backfillItem"
@on-switch-result="_onSwitchResult" >
:backfill-item="backfillItem" </m-sqoop>
:nodeData="nodeData" <m-conditions
></m-switch> v-if="nodeData.taskType === 'CONDITIONS'"
ref="CONDITIONS"
@on-dependent="_onDependent"
@on-cache-dependent="_onCacheDependent"
:backfill-item="backfillItem"
:prev-tasks="prevTasks"
>
</m-conditions>
<m-switch
v-if="nodeData.taskType === 'SWITCH'"
ref="SWITCH"
@on-switch-result="_onSwitchResult"
:backfill-item="backfillItem"
:nodeData="nodeData"
></m-switch>
</div>
<!-- Pre-tasks in workflow --> <!-- Pre-tasks in workflow -->
<m-pre-tasks ref="preTasks" v-if="['SHELL', 'SUB_PROCESS'].indexOf(nodeData.taskType) > -1" :code="code"/> <m-pre-tasks
ref="preTasks"
v-if="['SHELL', 'SUB_PROCESS'].indexOf(nodeData.taskType) > -1"
:code="code"
/>
</div> </div>
</div> </div>
<div class="bottom-box"> <div class="bottom-box">
<div class="submit" style="background: #fff;"> <div class="submit" style="background: #fff">
<el-button type="text" size="small" id="cancelBtn"> {{$t('Cancel')}} </el-button> <el-button type="text" size="small" id="cancelBtn">
<el-button type="primary" size="small" round :loading="spinnerLoading" @click="ok()" :disabled="isDetails">{{spinnerLoading ? $t('Loading...') : $t('Confirm add')}} </el-button> {{ $t("Cancel") }}
</el-button>
<el-button
type="primary"
size="small"
round
:loading="spinnerLoading"
@click="ok()"
:disabled="isDetails"
>{{ spinnerLoading ? $t("Loading...") : $t("Confirm add") }}
</el-button>
</div> </div>
</div> </div>
</div> </div>
@ -318,6 +442,7 @@
import disabledState from '@/module/mixin/disabledState' import disabledState from '@/module/mixin/disabledState'
import mPriority from '@/module/components/priority/priority' import mPriority from '@/module/components/priority/priority'
import { findComponentDownward } from '@/module/util/' import { findComponentDownward } from '@/module/util/'
import CopyFromTask from './_source/copyFromTask.vue'
export default { export default {
name: 'form-model', name: 'form-model',
@ -384,7 +509,14 @@
], ],
// for CONDITIONS // for CONDITIONS
postTasks: [], postTasks: [],
prevTasks: [] prevTasks: [],
// refresh part of the formModel, after set backfillItem outside
backfillRefresh: true
}
},
provide () {
return {
formModel: this
} }
}, },
/** /**
@ -408,7 +540,11 @@
id: task.id, id: task.id,
maxRetryTimes: task.failRetryTimes, maxRetryTimes: task.failRetryTimes,
name: task.name, name: task.name,
params: _.omit(task.taskParams, ['conditionResult', 'dependence']), params: _.omit(task.taskParams, [
'conditionResult',
'dependence',
'waitStartTimeout'
]),
retryInterval: task.failRetryInterval, retryInterval: task.failRetryInterval,
runFlag: task.flag, runFlag: task.flag,
taskInstancePriority: task.taskPriority, taskInstancePriority: task.taskPriority,
@ -448,13 +584,17 @@
*/ */
_onDependentTimeout (o) { _onDependentTimeout (o) {
this.timeout = Object.assign(this.timeout, {}, o.waitCompleteTimeout) this.timeout = Object.assign(this.timeout, {}, o.waitCompleteTimeout)
this.waitStartTimeout = Object.assign(this.waitStartTimeout, {}, o.waitStartTimeout) this.waitStartTimeout = Object.assign(
this.waitStartTimeout,
{},
o.waitStartTimeout
)
}, },
/** /**
* Click external to close the current component * Click external to close the current component
*/ */
_handleClose () { _handleClose () {
// this.close() // this.close()
}, },
/** /**
* Jump to task instance * Jump to task instance
@ -468,25 +608,39 @@
*/ */
_goSubProcess () { _goSubProcess () {
if (_.isEmpty(this.backfillItem)) { if (_.isEmpty(this.backfillItem)) {
this.$message.warning(`${i18n.$t('The newly created sub-Process has not yet been executed and cannot enter the sub-Process')}`) this.$message.warning(
`${i18n.$t(
'The newly created sub-Process has not yet been executed and cannot enter the sub-Process'
)}`
)
return return
} }
if (this.router.history.current.name === 'projects-instance-details') { if (this.router.history.current.name === 'projects-instance-details') {
if (!this.taskInstance) { if (!this.taskInstance) {
this.$message.warning(`${i18n.$t('The task has not been executed and cannot enter the sub-Process')}`) this.$message.warning(
`${i18n.$t(
'The task has not been executed and cannot enter the sub-Process'
)}`
)
return return
} }
this.store.dispatch('dag/getSubProcessId', { taskId: this.taskInstance.id }).then(res => { this.store
this.$emit('onSubProcess', { .dispatch('dag/getSubProcessId', { taskId: this.taskInstance.id })
subProcessId: res.data.subProcessInstanceId, .then((res) => {
fromThis: this this.$emit('onSubProcess', {
subProcessId: res.data.subProcessInstanceId,
fromThis: this
})
})
.catch((e) => {
this.$message.error(e.msg || '')
}) })
}).catch(e => {
this.$message.error(e.msg || '')
})
} else { } else {
const processDefinitionId = this.backfillItem.params.processDefinitionId const processDefinitionId =
const process = this.processListS.find(process => process.processDefinition.id === processDefinitionId) this.backfillItem.params.processDefinitionId
const process = this.processListS.find(
(process) => process.processDefinition.id === processDefinitionId
)
this.$emit('onSubProcess', { this.$emit('onSubProcess', {
subProcessCode: process.processDefinition.code, subProcessCode: process.processDefinition.code,
fromThis: this fromThis: this
@ -519,8 +673,16 @@
this.$message.warning(`${i18n.$t('Please enter name (required)')}`) this.$message.warning(`${i18n.$t('Please enter name (required)')}`)
return false return false
} }
if (this.successBranch !== '' && this.successBranch !== null && this.successBranch === this.failedBranch) { if (
this.$message.warning(`${i18n.$t('Cannot select the same node for successful branch flow and failed branch flow')}`) this.successBranch !== '' &&
this.successBranch !== null &&
this.successBranch === this.failedBranch
) {
this.$message.warning(
`${i18n.$t(
'Cannot select the same node for successful branch flow and failed branch flow'
)}`
)
return false return false
} }
if (this.name === this.backfillItem.name) { if (this.name === this.backfillItem.name) {
@ -528,7 +690,7 @@
} }
// Name repeat depends on dom backfill dependent store // Name repeat depends on dom backfill dependent store
const tasks = this.store.state.dag.tasks const tasks = this.store.state.dag.tasks
const task = tasks.find(t => t.name === 'this.name') const task = tasks.find((t) => t.name === 'this.name')
if (task) { if (task) {
this.$message.warning(`${i18n.$t('Name already exists')}`) this.$message.warning(`${i18n.$t('Name already exists')}`)
return false return false
@ -536,11 +698,15 @@
return true return true
}, },
_verifWorkGroup () { _verifWorkGroup () {
let item = this.store.state.security.workerGroupsListAll.find(item => { let item = this.store.state.security.workerGroupsListAll.find((item) => {
return item.id === this.workerGroup return item.id === this.workerGroup
}) })
if (item === undefined) { if (item === undefined) {
this.$message.warning(`${i18n.$t('The Worker group no longer exists, please select the correct Worker group!')}`) this.$message.warning(
`${i18n.$t(
'The Worker group no longer exists, please select the correct Worker group!'
)}`
)
return false return false
} }
return true return true
@ -619,20 +785,29 @@
* set run flag * set run flag
* TODO * TODO
*/ */
_setRunFlag () { _setRunFlag () {},
},
/**
*
*/
_setEdgeLabel () { _setEdgeLabel () {
if (this.successBranch || this.failedBranch) { if (this.successBranch || this.failedBranch) {
const canvas = findComponentDownward(this.dagChart, 'dag-canvas') const canvas = findComponentDownward(this.dagChart, 'dag-canvas')
const edges = canvas.getEdges() const edges = canvas.getEdges()
const successTask = this.postTasks.find(t => t.name === this.successBranch) const successTask = this.postTasks.find(
const failedTask = this.postTasks.find(t => t.name === this.failedBranch) (t) => t.name === this.successBranch
const sEdge = edges.find(edge => successTask && edge.sourceId === this.code && edge.targetId === successTask.code) )
const fEdge = edges.find(edge => failedTask && edge.sourceId === this.code && edge.targetId === failedTask.code) const failedTask = this.postTasks.find(
(t) => t.name === this.failedBranch
)
const sEdge = edges.find(
(edge) =>
successTask &&
edge.sourceId === this.code &&
edge.targetId === successTask.code
)
const fEdge = edges.find(
(edge) =>
failedTask &&
edge.sourceId === this.code &&
edge.targetId === failedTask.code
)
sEdge && canvas.setEdgeLabel(sEdge.id, this.$t('Success')) sEdge && canvas.setEdgeLabel(sEdge.id, this.$t('Success'))
fEdge && canvas.setEdgeLabel(fEdge.id, this.$t('Failed')) fEdge && canvas.setEdgeLabel(fEdge.id, this.$t('Failed'))
} }
@ -659,6 +834,57 @@
flag: flag, flag: flag,
fromThis: this fromThis: this
}) })
},
backfill (backfillItem, copyFromTask) {
const o = backfillItem
// Non-null objects represent backfill
if (!_.isEmpty(o)) {
this.code = o.code
!copyFromTask && (this.name = o.name)
this.taskInstancePriority = o.taskInstancePriority
this.runFlag = o.runFlag || 'YES'
this.desc = o.desc
this.maxRetryTimes = o.maxRetryTimes
this.retryInterval = o.retryInterval
this.delayTime = o.delayTime
if (o.conditionResult) {
this.successBranch = o.conditionResult.successNode[0]
this.failedBranch = o.conditionResult.failedNode[0]
}
// If the workergroup has been deleted, set the default workergroup
for (
let i = 0;
i < this.store.state.security.workerGroupsListAll.length;
i++
) {
let workerGroup = this.store.state.security.workerGroupsListAll[i].id
if (o.workerGroup === workerGroup) {
break
}
}
if (o.workerGroup === undefined) {
this.store
.dispatch('dag/getTaskInstanceList', {
pageSize: 10,
pageNo: 1,
processInstanceId: this.nodeData.instanceId,
name: o.name
})
.then((res) => {
this.workerGroup = res.totalList[0].workerGroup
})
} else {
this.workerGroup = o.workerGroup
}
this.environmentCode = o.environmentCode
this.params = o.params || {}
this.dependence = o.dependence || {}
this.cacheDependence = o.dependence || {}
} else {
this.workerGroup = this.store.state.security.workerGroupsListAll[0].id
}
this.cacheBackfillItem = JSON.parse(JSON.stringify(o))
this.isContentBox = true
} }
}, },
created () { created () {
@ -666,7 +892,7 @@
let taskList = this.store.state.dag.tasks let taskList = this.store.state.dag.tasks
let o = {} let o = {}
if (taskList.length) { if (taskList.length) {
taskList.forEach(task => { taskList.forEach((task) => {
if (task.code === this.nodeData.id) { if (task.code === this.nodeData.id) {
const backfillItem = this.taskToBackfillItem(task) const backfillItem = this.taskToBackfillItem(task)
o = backfillItem o = backfillItem
@ -675,46 +901,7 @@
}) })
} }
this.code = this.nodeData.id this.code = this.nodeData.id
// Non-null objects represent backfill this.backfill(o)
if (!_.isEmpty(o)) {
this.code = o.code
this.name = o.name
this.taskInstancePriority = o.taskInstancePriority
this.runFlag = o.runFlag || 'YES'
this.desc = o.desc
this.maxRetryTimes = o.maxRetryTimes
this.retryInterval = o.retryInterval
this.delayTime = o.delayTime
if (o.conditionResult) {
this.successBranch = o.conditionResult.successNode[0]
this.failedBranch = o.conditionResult.failedNode[0]
}
// If the workergroup has been deleted, set the default workergroup
for (let i = 0; i < this.store.state.security.workerGroupsListAll.length; i++) {
let workerGroup = this.store.state.security.workerGroupsListAll[i].id
if (o.workerGroup === workerGroup) {
break
}
}
if (o.workerGroup === undefined) {
this.store.dispatch('dag/getTaskInstanceList', {
pageSize: 10, pageNo: 1, processInstanceId: this.nodeData.instanceId, name: o.name
}).then(res => {
this.workerGroup = res.totalList[0].workerGroup
})
} else {
this.workerGroup = o.workerGroup
}
this.environmentCode = o.environmentCode
this.params = o.params || {}
this.dependence = o.dependence || {}
this.cacheDependence = o.dependence || {}
} else {
this.workerGroup = this.store.state.security.workerGroupsListAll[0].id
}
this.cacheBackfillItem = JSON.parse(JSON.stringify(o))
this.isContentBox = true
if (this.dagChart) { if (this.dagChart) {
const canvas = findComponentDownward(this.dagChart, 'dag-canvas') const canvas = findComponentDownward(this.dagChart, 'dag-canvas')
@ -736,17 +923,11 @@
self.close() self.close()
}) })
}, },
updated () { updated () {},
}, beforeDestroy () {},
beforeDestroy () { destroyed () {},
},
destroyed () {
},
computed: { computed: {
...mapState('dag', [ ...mapState('dag', ['processListS', 'taskInstances']),
'processListS',
'taskInstances'
]),
/** /**
* Child workflow entry show/hide * Child workflow entry show/hide
*/ */
@ -786,16 +967,17 @@
mPriority, mPriority,
mWorkerGroups, mWorkerGroups,
mRelatedEnvironment, mRelatedEnvironment,
mPreTasks mPreTasks,
CopyFromTask
} }
} }
</script> </script>
<style lang="scss" rel="stylesheet/scss"> <style lang="scss" rel="stylesheet/scss">
@import "./formModel"; @import "./formModel";
.ans-radio-disabled { .ans-radio-disabled {
.ans-radio-inner:after { .ans-radio-inner:after {
background-color: #6F8391 background-color: #6f8391;
}
} }
}
</style> </style>

9
dolphinscheduler-ui/src/js/conf/home/store/dag/actions.js

@ -829,5 +829,14 @@ export default {
reject(e) reject(e)
}) })
}) })
},
getTaskDefinitions ({ state }, payload) {
return new Promise((resolve, reject) => {
io.get(`projects/${state.projectCode}/task-definition`, payload, res => {
resolve(res.data)
}).catch(e => {
reject(e)
})
})
} }
} }

4
dolphinscheduler-ui/src/js/module/i18n/locale/en_US.js

@ -706,5 +706,7 @@ export default {
'Please enter environment desc': 'Please enter environment desc', 'Please enter environment desc': 'Please enter environment desc',
'Please select worker groups': 'Please select worker groups', 'Please select worker groups': 'Please select worker groups',
condition: 'condition', condition: 'condition',
'The condition content cannot be empty': 'The condition content cannot be empty' 'The condition content cannot be empty': 'The condition content cannot be empty',
'Copy from': 'Copy from',
'No more...': 'No more...'
} }

4
dolphinscheduler-ui/src/js/module/i18n/locale/zh_CN.js

@ -705,5 +705,7 @@ export default {
'Please enter environment desc': '请输入详细描述', 'Please enter environment desc': '请输入详细描述',
'Please select worker groups': '请选择Worker分组', 'Please select worker groups': '请选择Worker分组',
condition: '条件', condition: '条件',
'The condition content cannot be empty': '条件内容不能为空' 'The condition content cannot be empty': '条件内容不能为空',
'Copy from': '从任务复制',
'No more...': '没有更多了...'
} }

Loading…
Cancel
Save