Browse Source

datax add custom and add branch flow node verification (#2218)

* Change DOM label

* Change name to lowercase

* Limit customization file content to no more than 3000 lines

* dd branch flow node verification

* datax

* datax add custom
pull/2/head
break60 4 years ago committed by GitHub
parent
commit
3ced3d594b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/dag.scss
  2. 91
      dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/dag.vue
  3. 4
      dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/formModel.vue
  4. 4
      dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/_source/nodeStatus.vue
  5. 389
      dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/datax.vue
  6. 4
      dolphinscheduler-ui/src/js/module/components/transfer/resource.vue
  7. 5
      dolphinscheduler-ui/src/js/module/i18n/locale/en_US.js
  8. 5
      dolphinscheduler-ui/src/js/module/i18n/locale/zh_CN.js

2
dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/dag.scss

@ -135,7 +135,7 @@
width: 36px; width: 36px;
height: 36px; height: 36px;
float: left; float: left;
margin-bottom: 11px; margin-bottom: 8px;
border-radius: 3px; border-radius: 3px;
.disabled { .disabled {
.icos { .icos {

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

@ -326,45 +326,62 @@
* Storage interface * Storage interface
*/ */
_save (sourceType) { _save (sourceType) {
return new Promise((resolve, reject) => { if(this._verifConditions()) {
this.spinnerLoading = true return new Promise((resolve, reject) => {
// Storage store this.spinnerLoading = true
Dag.saveStore().then(res => { // Storage store
if (this.urlParam.id) { Dag.saveStore().then(res => {
/** if (this.urlParam.id) {
* Edit /**
* @param saveInstanceEditDAGChart => Process instance editing * Edit
* @param saveEditDAGChart => Process definition editing * @param saveInstanceEditDAGChart => Process instance editing
*/ * @param saveEditDAGChart => Process definition editing
this[this.type === 'instance' ? 'updateInstance' : 'updateDefinition'](this.urlParam.id).then(res => { */
this.$message.success(res.msg) this[this.type === 'instance' ? 'updateInstance' : 'updateDefinition'](this.urlParam.id).then(res => {
this.spinnerLoading = false this.$message.success(res.msg)
resolve() this.spinnerLoading = false
}).catch(e => { resolve()
this.$message.error(e.msg || '') }).catch(e => {
this.spinnerLoading = false this.$message.error(e.msg || '')
reject(e) this.spinnerLoading = false
}) reject(e)
} else { })
// New } else {
this.saveDAGchart().then(res => { // New
this.$message.success(res.msg) this.saveDAGchart().then(res => {
this.spinnerLoading = false this.$message.success(res.msg)
// source @/conf/home/pages/dag/_source/editAffirmModel/index.js this.spinnerLoading = false
if (sourceType !== 'affirm') { // source @/conf/home/pages/dag/_source/editAffirmModel/index.js
// Jump process definition if (sourceType !== 'affirm') {
this.$router.push({ name: 'projects-definition-list' }) // Jump process definition
} this.$router.push({ name: 'projects-definition-list' })
resolve() }
}).catch(e => { resolve()
this.$message.error(e.msg || '') }).catch(e => {
this.setName('') this.$message.error(e.msg || '')
this.spinnerLoading = false this.setName('')
reject(e) this.spinnerLoading = false
}) reject(e)
} })
}
})
}) })
}
},
_verifConditions () {
let tasks = this.$store.state.dag.tasks
let bool = true
tasks.map(v=>{
if(v.type == 'CONDITIONS' && (v.conditionResult.successNode[0] =='' || v.conditionResult.successNode[0] == null || v.conditionResult.failedNode[0] =='' || v.conditionResult.failedNode[0] == null)) {
bool = false
return false
}
}) })
if(!bool) {
this.$message.warning(`${i18n.$t('Successful branch flow and failed branch flow are required')}`)
return false
}
return true
}, },
/** /**
* Global parameter * Global parameter

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

@ -430,7 +430,7 @@
* return params * return params
*/ */
_onParams (o) { _onParams (o) {
this.params = Object.assign(this.params, {}, o) this.params = Object.assign({}, o)
}, },
_onCacheParams (o) { _onCacheParams (o) {
@ -470,7 +470,7 @@
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 == this.failedBranch) { if (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')}`) this.$message.warning(`${i18n.$t('Cannot select the same node for successful branch flow and failed branch flow')}`)
return false return false
} }

4
dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/_source/nodeStatus.vue

@ -128,10 +128,6 @@
this.store.dispatch('dag/getProcessTasksList', { processDefinitionId: ids }).then(res => { this.store.dispatch('dag/getProcessTasksList', { processDefinitionId: ids }).then(res => {
resolve(['ALL'].concat(_.map(res, v => v.name))) resolve(['ALL'].concat(_.map(res, v => v.name)))
}) })
} else {
this.store.dispatch('dag/getTaskListDefIdAll', { processDefinitionIdList: ids }).then(res => {
resolve(res)
})
} }
}) })
}, },

389
dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/datax.vue

@ -17,90 +17,127 @@
<template> <template>
<div class="datax-model"> <div class="datax-model">
<m-list-box> <m-list-box>
<div slot="text">{{$t('Datasource')}}</div> <div slot="text">{{$t('Custom template')}}</div>
<div slot="content"> <div slot="content">
<m-datasource <label class="label-box">
ref="refDs" <div style="padding-top: 5px;">
@on-dsData="_onDsData" <x-switch v-model="enable" @on-click="_onSwitch" :disabled="isDetails"></x-switch>
:supportType="['MYSQL','POSTGRESQL', 'ORACLE', 'SQLSERVER']" </div>
:data="{ type:dsType,datasource:datasource }"> </label>
</m-datasource>
</div> </div>
</m-list-box> </m-list-box>
<m-list-box> <div v-if="!enable">
<div slot="text">{{$t('SQL Statement')}}</div> <m-list-box>
<div slot="content"> <div slot="text">{{$t('Datasource')}}</div>
<div class="from-mirror"> <div slot="content">
<textarea <m-datasource
id="code-sql-mirror" ref="refDs"
name="code-sql-mirror" @on-dsData="_onDsData"
style="opacity: 0;"> :supportType="['MYSQL','POSTGRESQL', 'ORACLE', 'SQLSERVER']"
</textarea> :data="{ type:dsType,datasource:datasource }">
</m-datasource>
</div> </div>
</div> </m-list-box>
</m-list-box> <m-list-box>
<m-list-box> <div slot="text">{{$t('SQL Statement')}}</div>
<div slot="text">{{$t('TargetDataBase')}}</div> <div slot="content">
<div slot="content"> <div class="from-mirror">
<m-datasource <textarea
ref="refDt" id="code-sql-mirror"
@on-dsData="_onDtData" name="code-sql-mirror"
:supportType="['MYSQL','POSTGRESQL', 'ORACLE', 'SQLSERVER']" style="opacity: 0;">
:data="{ type:dtType,datasource:datatarget }"> </textarea>
</m-datasource> </div>
</div> </div>
</m-list-box> </m-list-box>
<m-list-box> <m-list-box>
<div slot="text">{{$t('TargetTable')}}</div> <div slot="text">{{$t('TargetDataBase')}}</div>
<div slot="content"> <div slot="content">
<x-input <m-datasource
type="input" ref="refDt"
v-model="targetTable" @on-dsData="_onDtData"
:placeholder="$t('Please enter the table of target')" :supportType="['MYSQL','POSTGRESQL', 'ORACLE', 'SQLSERVER']"
autocomplete="off"> :data="{ type:dtType,datasource:datatarget }">
</x-input> </m-datasource>
</div> </div>
</m-list-box> </m-list-box>
<m-list-box> <m-list-box>
<div slot="text">{{$t('TargetDataBase')}}{{$t('Pre Statement')}}</div> <div slot="text">{{$t('TargetTable')}}</div>
<div slot="content"> <div slot="content">
<m-statement-list <x-input
ref="refPreStatements" type="input"
@on-statement-list="_onPreStatements" v-model="targetTable"
:statement-list="preStatements"> :placeholder="$t('Please enter the table of target')"
</m-statement-list> autocomplete="off">
</div> </x-input>
</m-list-box> </div>
<m-list-box> </m-list-box>
<div slot="text">{{$t('TargetDataBase')}}{{$t('Post Statement')}}</div> <m-list-box>
<div slot="content"> <div slot="text">{{$t('TargetDataBase')}}{{$t('Pre Statement')}}</div>
<m-statement-list <div slot="content">
ref="refPostStatements" <m-statement-list
@on-statement-list="_onPostStatements" ref="refPreStatements"
:statement-list="postStatements"> @on-statement-list="_onPreStatements"
</m-statement-list> :statement-list="preStatements">
</div> </m-statement-list>
</m-list-box> </div>
<m-list-box> </m-list-box>
<div slot="text"> <m-list-box>
<span>{{$t('SpeedByte')}}</span> <div slot="text">{{$t('TargetDataBase')}}{{$t('Post Statement')}}</div>
</div> <div slot="content">
<div slot="content"> <m-statement-list
<m-select-input v-model="jobSpeedByte" :list="[0,1,10,50,100,512]"> ref="refPostStatements"
</m-select-input> @on-statement-list="_onPostStatements"
<span>({{$t('0 means unlimited by byte')}})</span> :statement-list="postStatements">
</div> </m-statement-list>
</m-list-box> </div>
<m-list-box> </m-list-box>
<div slot="text"> <m-list-box>
<span>{{$t('SpeedRecord')}}</span> <div slot="text">
</div> <span>{{$t('SpeedByte')}}</span>
<div slot="content"> </div>
<m-select-input v-model="jobSpeedRecord" :list="[0,500,1000,1500,2000,2500,3000]"> <div slot="content">
</m-select-input> <m-select-input v-model="jobSpeedByte" :list="[0,1,10,50,100,512]">
<span>({{$t('0 means unlimited by count')}})</span> </m-select-input>
</div> <span>({{$t('0 means unlimited by byte')}})</span>
</m-list-box> </div>
</m-list-box>
<m-list-box>
<div slot="text">
<span>{{$t('SpeedRecord')}}</span>
</div>
<div slot="content">
<m-select-input v-model="jobSpeedRecord" :list="[0,500,1000,1500,2000,2500,3000]">
</m-select-input>
<span>({{$t('0 means unlimited by count')}})</span>
</div>
</m-list-box>
</div>
<div v-else>
<m-list-box>
<div slot="text">json</div>
<div slot="content">
<div class="from-mirror">
<textarea
id="code-json-mirror"
name="code-json-mirror"
style="opacity: 0;">
</textarea>
</div>
</div>
</m-list-box>
<m-list-box>
<div slot="text">{{$t('Custom Parameters')}}</div>
<div slot="content">
<m-local-params
ref="refLocalParams"
@on-local-params="_onLocalParams"
:udp-list="localParams"
:hide="false">
</m-local-params>
</div>
</m-list-box>
</div>
</div> </div>
</template> </template>
<script> <script>
@ -115,12 +152,15 @@
import codemirror from '@/conf/home/pages/resource/pages/file/pages/_source/codemirror' import codemirror from '@/conf/home/pages/resource/pages/file/pages/_source/codemirror'
let editor let editor
let jsonEditor
export default { export default {
name: 'datax', name: 'datax',
data () { data () {
return { return {
// Data Custom template
enable: false,
// Data source type // Data source type
dsType: '', dsType: '',
// data source // data source
@ -135,6 +175,7 @@
rtDatatarget: '', rtDatatarget: '',
// Sql statement // Sql statement
sql: '', sql: '',
json: '',
// target table // target table
targetTable: '', targetTable: '',
// Pre statements // Pre statements
@ -145,6 +186,9 @@
jobSpeedByte: 0, jobSpeedByte: 0,
// speed record // speed record
jobSpeedRecord: 1000, jobSpeedRecord: 1000,
// Custom parameter
localParams: [],
customConfig: 0,
} }
}, },
mixins: [disabledState], mixins: [disabledState],
@ -153,6 +197,19 @@
createNodeId: Number createNodeId: Number
}, },
methods: { methods: {
_onSwitch (is) {
if(is) {
this.customConfig = 1
setTimeout(() => {
this._handlerJsonEditor()
}, 200)
} else {
this.customConfig = 0
setTimeout(() => {
this._handlerEditor()
}, 200)
}
},
/** /**
* return data source * return data source
*/ */
@ -183,50 +240,66 @@
* verification * verification
*/ */
_verification () { _verification () {
if (!editor.getValue()) { if(this.customConfig) {
this.$message.warning(`${i18n.$t('Please enter a SQL Statement(required)')}`) if (!jsonEditor.getValue()) {
return false this.$message.warning(`${i18n.$t('Please enter a JSON Statement(required)')}`)
} return false
}
// datasource Subcomponent verification // storage
if (!this.$refs.refDs._verifDatasource()) { this.$emit('on-params', {
return false customConfig: this.customConfig,
} json: jsonEditor.getValue(),
localParams: this.localParams
})
return true
} else {
if (!editor.getValue()) {
this.$message.warning(`${i18n.$t('Please enter a SQL Statement(required)')}`)
return false
}
// datasource Subcomponent verification // datasource Subcomponent verification
if (!this.$refs.refDt._verifDatasource()) { if (!this.$refs.refDs._verifDatasource()) {
return false return false
} }
if (!this.targetTable) { // datasource Subcomponent verification
this.$message.warning(`${i18n.$t('Please enter a Target Table(required)')}`) if (!this.$refs.refDt._verifDatasource()) {
return false return false
} }
// preStatements Subcomponent verification if (!this.targetTable) {
if (!this.$refs.refPreStatements._verifProp()) { this.$message.warning(`${i18n.$t('Please enter a Target Table(required)')}`)
return false return false
} }
// postStatements Subcomponent verification // preStatements Subcomponent verification
if (!this.$refs.refPostStatements._verifProp()) { if (!this.$refs.refPreStatements._verifProp()) {
return false return false
} }
// storage // postStatements Subcomponent verification
this.$emit('on-params', { if (!this.$refs.refPostStatements._verifProp()) {
dsType: this.dsType, return false
dataSource: this.rtDatasource, }
dtType: this.dtType,
dataTarget: this.rtDatatarget, // storage
sql: editor.getValue(), this.$emit('on-params', {
targetTable: this.targetTable, customConfig: this.customConfig,
jobSpeedByte: this.jobSpeedByte * 1024, dsType: this.dsType,
jobSpeedRecord: this.jobSpeedRecord, dataSource: this.rtDatasource,
preStatements: this.preStatements, dtType: this.dtType,
postStatements: this.postStatements dataTarget: this.rtDatatarget,
}) sql: editor.getValue(),
return true targetTable: this.targetTable,
jobSpeedByte: this.jobSpeedByte * 1024,
jobSpeedRecord: this.jobSpeedRecord,
preStatements: this.preStatements,
postStatements: this.postStatements
})
return true
}
}, },
/** /**
* Processing code highlighting * Processing code highlighting
@ -259,6 +332,34 @@
return editor return editor
}, },
_handlerJsonEditor () {
this._destroyJsonEditor()
// jsonEditor
jsonEditor = codemirror('code-json-mirror', {
mode: 'json',
readOnly: this.isDetails
})
this.keypress = () => {
if (!jsonEditor.getOption('readOnly')) {
jsonEditor.showHint({
completeSingle: false
})
}
}
// Monitor keyboard
jsonEditor.on('keypress', this.keypress)
jsonEditor.on('changes', () => {
// this._cacheParams()
})
jsonEditor.setValue(this.json)
return jsonEditor
},
_cacheParams () { _cacheParams () {
this.$emit('on-cache-params', { this.$emit('on-cache-params', {
dsType: this.dsType, dsType: this.dsType,
@ -279,6 +380,13 @@
editor.off($('.code-sql-mirror'), 'keypress', this.keypress) editor.off($('.code-sql-mirror'), 'keypress', this.keypress)
editor.off($('.code-sql-mirror'), 'changes', this.changes) editor.off($('.code-sql-mirror'), 'changes', this.changes)
} }
},
_destroyJsonEditor () {
if (jsonEditor) {
jsonEditor.toTextArea() // Uninstall
jsonEditor.off($('.code-json-mirror'), 'keypress', this.keypress)
jsonEditor.off($('.code-json-mirror'), 'changes', this.changes)
}
} }
}, },
created () { created () {
@ -287,22 +395,37 @@
// Non-null objects represent backfill // Non-null objects represent backfill
if (!_.isEmpty(o)) { if (!_.isEmpty(o)) {
// backfill // backfill
this.dsType = o.params.dsType || '' if(o.params.customConfig == 0) {
this.datasource = o.params.dataSource || '' this.customConfig = 0
this.dtType = o.params.dtType || '' this.enable = false
this.datatarget = o.params.dataTarget || '' this.dsType = o.params.dsType || ''
this.sql = o.params.sql || '' this.datasource = o.params.dataSource || ''
this.targetTable = o.params.targetTable || '' this.dtType = o.params.dtType || ''
this.jobSpeedByte = o.params.jobSpeedByte / 1024 || 0 this.datatarget = o.params.dataTarget || ''
this.jobSpeedRecord = o.params.jobSpeedRecord || 0 this.sql = o.params.sql || ''
this.preStatements = o.params.preStatements || [] this.targetTable = o.params.targetTable || ''
this.postStatements = o.params.postStatements || [] this.jobSpeedByte = o.params.jobSpeedByte / 1024 || 0
this.jobSpeedRecord = o.params.jobSpeedRecord || 0
this.preStatements = o.params.preStatements || []
this.postStatements = o.params.postStatements || []
} else {
this.customConfig = 1
this.enable = true
this.json = o.params.json || []
this.localParams = o.params.localParams || ''
}
} }
}, },
mounted () { mounted () {
setTimeout(() => { if(this.customConfig) {
this._handlerEditor() setTimeout(() => {
}, 200) this._handlerJsonEditor()
}, 200)
} else {
setTimeout(() => {
this._handlerEditor()
}, 200)
}
}, },
destroyed () { destroyed () {
/** /**
@ -312,6 +435,10 @@
editor.toTextArea() // Uninstall editor.toTextArea() // Uninstall
editor.off($('.code-sql-mirror'), 'keypress', this.keypress) editor.off($('.code-sql-mirror'), 'keypress', this.keypress)
} }
if (jsonEditor) {
jsonEditor.toTextArea() // Uninstall
jsonEditor.off($('.code-json-mirror'), 'keypress', this.keypress)
}
}, },
watch: { watch: {
//Watch the cacheParams //Watch the cacheParams

4
dolphinscheduler-ui/src/js/module/components/transfer/resource.vue

@ -20,8 +20,8 @@
<div class="clearfix transfer-model" style="width: 660px"> <div class="clearfix transfer-model" style="width: 660px">
<div> <div>
<x-button-group v-model="checkedValue" size="small"> <x-button-group v-model="checkedValue" size="small">
<x-button type="ghost" value="fileResource" @click="_ckFile">{{$t('File resources')}}</x-button> <x-button type="ghost" value="fileResource" @click="_ckFile">{{$t('File resources')}}</x-button>
<x-button type="ghost" value="udfResource" @click="_ckUDf">{{$t('UDF resources')}}</x-button> <x-button type="ghost" value="udfResource" @click="_ckUDf">{{$t('UDF resources')}}</x-button>
</x-button-group> </x-button-group>
</div> </div>
<div class="select-list-box"> <div class="select-list-box">

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

@ -90,6 +90,7 @@ export default {
'Please enter other parameters': 'Please enter other parameters', 'Please enter other parameters': 'Please enter other parameters',
'Resources': 'Resources', 'Resources': 'Resources',
'Custom Parameters': 'Custom Parameters', 'Custom Parameters': 'Custom Parameters',
'Custom template': 'Custom template',
'Datasource': 'Datasource', 'Datasource': 'Datasource',
'methods': 'methods', 'methods': 'methods',
'Please enter method(optional)': 'Please enter method(optional)', 'Please enter method(optional)': 'Please enter method(optional)',
@ -119,6 +120,7 @@ export default {
'SQL Statement': 'SQL Statement', 'SQL Statement': 'SQL Statement',
'UDF Function': 'UDF Function', 'UDF Function': 'UDF Function',
'Please enter a SQL Statement(required)': 'Please enter a SQL Statement(required)', 'Please enter a SQL Statement(required)': 'Please enter a SQL Statement(required)',
'Please enter a JSON Statement(required)': 'Please enter a JSON Statement(required)',
'One form or attachment must be selected': 'One form or attachment must be selected', 'One form or attachment must be selected': 'One form or attachment must be selected',
'Recipient required': 'Recipient required', 'Recipient required': 'Recipient required',
'Mail subject required': 'Mail subject required', 'Mail subject required': 'Mail subject required',
@ -568,5 +570,6 @@ export default {
'All Columns': 'All Columns', 'All Columns': 'All Columns',
'Some Columns': 'Some Columns', 'Some Columns': 'Some Columns',
'Branch flow': 'Branch flow', 'Branch flow': 'Branch flow',
'Cannot select the same node for successful branch flow and failed branch flow': 'Cannot select the same node for successful branch flow and failed branch flow' 'Cannot select the same node for successful branch flow and failed branch flow': 'Cannot select the same node for successful branch flow and failed branch flow',
'Successful branch flow and failed branch flow are required': 'Successful branch flow and failed branch flow are required'
} }

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

@ -90,6 +90,7 @@ export default {
'Please enter other parameters': '请输入其他参数', 'Please enter other parameters': '请输入其他参数',
'Resources': '资源', 'Resources': '资源',
'Custom Parameters': '自定义参数', 'Custom Parameters': '自定义参数',
'Custom template': '自定义模版',
'Please enter main class': '请填写主函数的class', 'Please enter main class': '请填写主函数的class',
'Datasource': '数据源', 'Datasource': '数据源',
'methods': '方法', 'methods': '方法',
@ -120,6 +121,7 @@ export default {
'SQL Statement': 'sql语句', 'SQL Statement': 'sql语句',
'UDF Function': 'UDF函数', 'UDF Function': 'UDF函数',
'Please enter a SQL Statement(required)': '请输入sql语句(必填)', 'Please enter a SQL Statement(required)': '请输入sql语句(必填)',
'Please enter a JSON Statement(required)': '请输入json语句(必填)',
'One form or attachment must be selected': '表格附件必须勾选一个', 'One form or attachment must be selected': '表格附件必须勾选一个',
'Recipient required': '收件人邮箱必填', 'Recipient required': '收件人邮箱必填',
'Mail subject required': '邮件主题必填', 'Mail subject required': '邮件主题必填',
@ -568,5 +570,6 @@ export default {
'All Columns': '全表导入', 'All Columns': '全表导入',
'Some Columns': '选择列', 'Some Columns': '选择列',
'Branch flow': '分支流转', 'Branch flow': '分支流转',
'Cannot select the same node for successful branch flow and failed branch flow': '成功分支流转和失败分支流转不能选择同一个节点' 'Cannot select the same node for successful branch flow and failed branch flow': '成功分支流转和失败分支流转不能选择同一个节点',
'Successful branch flow and failed branch flow are required': '成功分支流转和失败分支流转必填',
} }

Loading…
Cancel
Save