You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dolphinscheduler.apache.org by jo...@apache.org on 2020/03/23 02:10:39 UTC

[incubator-dolphinscheduler] branch dev updated: datax add custom and add branch flow node verification (#2218)

This is an automated email from the ASF dual-hosted git repository.

journey pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/incubator-dolphinscheduler.git


The following commit(s) were added to refs/heads/dev by this push:
     new 3ced3d5  datax add custom and add branch flow node verification (#2218)
3ced3d5 is described below

commit 3ced3d594b5318395865738a1fd130f49d5902aa
Author: break60 <79...@qq.com>
AuthorDate: Mon Mar 23 10:10:31 2020 +0800

    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
---
 .../src/js/conf/home/pages/dag/_source/dag.scss    |   2 +-
 .../src/js/conf/home/pages/dag/_source/dag.vue     |  91 +++--
 .../home/pages/dag/_source/formModel/formModel.vue |   4 +-
 .../_source/formModel/tasks/_source/nodeStatus.vue |   4 -
 .../pages/dag/_source/formModel/tasks/datax.vue    | 389 ++++++++++++++-------
 .../src/js/module/components/transfer/resource.vue |   4 +-
 .../src/js/module/i18n/locale/en_US.js             |   5 +-
 .../src/js/module/i18n/locale/zh_CN.js             |   5 +-
 8 files changed, 325 insertions(+), 179 deletions(-)

diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/dag.scss b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/dag.scss
index 6d97856..9973750 100755
--- a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/dag.scss
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/dag.scss
@@ -135,7 +135,7 @@
         width: 36px;
         height: 36px;
         float: left;
-        margin-bottom: 11px;
+        margin-bottom: 8px;
         border-radius: 3px;
         .disabled {
           .icos {
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/dag.vue b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/dag.vue
index a1ccd39..8628fdb 100755
--- a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/dag.vue
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/dag.vue
@@ -326,45 +326,62 @@
        * Storage interface
        */
       _save (sourceType) {
-        return new Promise((resolve, reject) => {
-          this.spinnerLoading = true
-          // Storage store
-          Dag.saveStore().then(res => {
-            if (this.urlParam.id) {
-              /**
-               * Edit
-               * @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.spinnerLoading = false
-                resolve()
-              }).catch(e => {
-                this.$message.error(e.msg || '')
-                this.spinnerLoading = false
-                reject(e)
-              })
-            } else {
-              // New
-              this.saveDAGchart().then(res => {
-                this.$message.success(res.msg)
-                this.spinnerLoading = false
-                // source @/conf/home/pages/dag/_source/editAffirmModel/index.js
-                if (sourceType !== 'affirm') {
-                  // Jump process definition
-                  this.$router.push({ name: 'projects-definition-list' })
-                }
-                resolve()
-              }).catch(e => {
-                this.$message.error(e.msg || '')
-                this.setName('')
-                this.spinnerLoading = false
-                reject(e)
-              })
-            }
+        if(this._verifConditions()) {
+          return new Promise((resolve, reject) => {
+            this.spinnerLoading = true
+            // Storage store
+            Dag.saveStore().then(res => {
+              if (this.urlParam.id) {
+                /**
+                 * Edit
+                 * @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.spinnerLoading = false
+                  resolve()
+                }).catch(e => {
+                  this.$message.error(e.msg || '')
+                  this.spinnerLoading = false
+                  reject(e)
+                })
+              } else {
+                // New
+                this.saveDAGchart().then(res => {
+                  this.$message.success(res.msg)
+                  this.spinnerLoading = false
+                  // source @/conf/home/pages/dag/_source/editAffirmModel/index.js
+                  if (sourceType !== 'affirm') {
+                    // Jump process definition
+                    this.$router.push({ name: 'projects-definition-list' })
+                  }
+                  resolve()
+                }).catch(e => {
+                  this.$message.error(e.msg || '')
+                  this.setName('')
+                  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
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/formModel.vue b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/formModel.vue
index cc1c8b6..017f154 100755
--- a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/formModel.vue
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/formModel.vue
@@ -430,7 +430,7 @@
        * return params
        */
       _onParams (o) {
-        this.params = Object.assign(this.params, {}, o)
+        this.params = Object.assign({}, o)
       },
 
       _onCacheParams (o) {
@@ -470,7 +470,7 @@
           this.$message.warning(`${i18n.$t('Please enter name (required)')}`)
           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')}`)
           return false
         }
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/_source/nodeStatus.vue b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/_source/nodeStatus.vue
index fa7ee89..0c3f743 100644
--- a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/_source/nodeStatus.vue
+++ b/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 => {
               resolve(['ALL'].concat(_.map(res, v => v.name)))
             })
-          } else {
-            this.store.dispatch('dag/getTaskListDefIdAll', { processDefinitionIdList: ids }).then(res => {
-              resolve(res)
-            })
           }
         })
       },
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/datax.vue b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/datax.vue
index 959610f..f1c9b75 100755
--- a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/datax.vue
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/datax.vue
@@ -17,90 +17,127 @@
 <template>
   <div class="datax-model">
     <m-list-box>
-      <div slot="text">{{$t('Datasource')}}</div>
+      <div slot="text">{{$t('Custom template')}}</div>
       <div slot="content">
-        <m-datasource
-                ref="refDs"
-                @on-dsData="_onDsData"
-                :supportType="['MYSQL','POSTGRESQL', 'ORACLE', 'SQLSERVER']"
-                :data="{ type:dsType,datasource:datasource }">
-        </m-datasource>
+        <label class="label-box">
+          <div style="padding-top: 5px;">
+            <x-switch v-model="enable" @on-click="_onSwitch" :disabled="isDetails"></x-switch>
+          </div>
+        </label>
       </div>
     </m-list-box>
-    <m-list-box>
-      <div slot="text">{{$t('SQL Statement')}}</div>
-      <div slot="content">
-        <div class="from-mirror">
-          <textarea
-            id="code-sql-mirror"
-            name="code-sql-mirror"
-            style="opacity: 0;">
-          </textarea>
+    <div v-if="!enable">
+      <m-list-box>
+        <div slot="text">{{$t('Datasource')}}</div>
+        <div slot="content">
+          <m-datasource
+                  ref="refDs"
+                  @on-dsData="_onDsData"
+                  :supportType="['MYSQL','POSTGRESQL', 'ORACLE', 'SQLSERVER']"
+                  :data="{ type:dsType,datasource:datasource }">
+          </m-datasource>
         </div>
-      </div>
-    </m-list-box>
-    <m-list-box>
-      <div slot="text">{{$t('TargetDataBase')}}</div>
-      <div slot="content">
-        <m-datasource
-                ref="refDt"
-                @on-dsData="_onDtData"
-                :supportType="['MYSQL','POSTGRESQL', 'ORACLE', 'SQLSERVER']"
-                :data="{ type:dtType,datasource:datatarget }">
-        </m-datasource>
-      </div>
-    </m-list-box>
-    <m-list-box>
-      <div slot="text">{{$t('TargetTable')}}</div>
-      <div slot="content">
-        <x-input
-          type="input"
-          v-model="targetTable"
-          :placeholder="$t('Please enter the table of target')"
-          autocomplete="off">
-        </x-input>
-      </div>
-    </m-list-box>
-    <m-list-box>
-      <div slot="text">{{$t('TargetDataBase')}}{{$t('Pre Statement')}}</div>
-      <div slot="content">
-        <m-statement-list
-          ref="refPreStatements"
-          @on-statement-list="_onPreStatements"
-          :statement-list="preStatements">
-        </m-statement-list>
-      </div>
-    </m-list-box>
-    <m-list-box>
-      <div slot="text">{{$t('TargetDataBase')}}{{$t('Post Statement')}}</div>
-      <div slot="content">
-        <m-statement-list
-          ref="refPostStatements"
-          @on-statement-list="_onPostStatements"
-          :statement-list="postStatements">
-        </m-statement-list>
-      </div>
-    </m-list-box>
-    <m-list-box>
-      <div slot="text">
-        <span>{{$t('SpeedByte')}}</span>
-      </div>
-      <div slot="content">
-        <m-select-input v-model="jobSpeedByte" :list="[0,1,10,50,100,512]">
-        </m-select-input>
-        <span>({{$t('0 means unlimited by byte')}})</span>
-      </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>
+      </m-list-box>
+      <m-list-box>
+        <div slot="text">{{$t('SQL Statement')}}</div>
+        <div slot="content">
+          <div class="from-mirror">
+            <textarea
+              id="code-sql-mirror"
+              name="code-sql-mirror"
+              style="opacity: 0;">
+            </textarea>
+          </div>
+        </div>
+      </m-list-box>
+      <m-list-box>
+        <div slot="text">{{$t('TargetDataBase')}}</div>
+        <div slot="content">
+          <m-datasource
+                  ref="refDt"
+                  @on-dsData="_onDtData"
+                  :supportType="['MYSQL','POSTGRESQL', 'ORACLE', 'SQLSERVER']"
+                  :data="{ type:dtType,datasource:datatarget }">
+          </m-datasource>
+        </div>
+      </m-list-box>
+      <m-list-box>
+        <div slot="text">{{$t('TargetTable')}}</div>
+        <div slot="content">
+          <x-input
+            type="input"
+            v-model="targetTable"
+            :placeholder="$t('Please enter the table of target')"
+            autocomplete="off">
+          </x-input>
+        </div>
+      </m-list-box>
+      <m-list-box>
+        <div slot="text">{{$t('TargetDataBase')}}{{$t('Pre Statement')}}</div>
+        <div slot="content">
+          <m-statement-list
+            ref="refPreStatements"
+            @on-statement-list="_onPreStatements"
+            :statement-list="preStatements">
+          </m-statement-list>
+        </div>
+      </m-list-box>
+      <m-list-box>
+        <div slot="text">{{$t('TargetDataBase')}}{{$t('Post Statement')}}</div>
+        <div slot="content">
+          <m-statement-list
+            ref="refPostStatements"
+            @on-statement-list="_onPostStatements"
+            :statement-list="postStatements">
+          </m-statement-list>
+        </div>
+      </m-list-box>
+      <m-list-box>
+        <div slot="text">
+          <span>{{$t('SpeedByte')}}</span>
+        </div>
+        <div slot="content">
+          <m-select-input v-model="jobSpeedByte" :list="[0,1,10,50,100,512]">
+          </m-select-input>
+          <span>({{$t('0 means unlimited by byte')}})</span>
+        </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>
 </template>
 <script>
@@ -115,12 +152,15 @@
   import codemirror from '@/conf/home/pages/resource/pages/file/pages/_source/codemirror'
 
   let editor
+  let jsonEditor
 
   export default {
     name: 'datax',
 
     data () {
       return {
+        // Data Custom template
+        enable: false,
         // Data source type
         dsType: '',
         // data source
@@ -135,6 +175,7 @@
         rtDatatarget: '',
         // Sql statement
         sql: '',
+        json: '',
         // target table
         targetTable: '',
         // Pre statements
@@ -145,6 +186,9 @@
         jobSpeedByte: 0,
         // speed record
         jobSpeedRecord: 1000,
+        // Custom parameter
+        localParams: [],
+        customConfig: 0,
       }
     },
     mixins: [disabledState],
@@ -153,6 +197,19 @@
       createNodeId: Number
     },
     methods: {
+      _onSwitch (is) {
+        if(is) {
+          this.customConfig = 1
+          setTimeout(() => {
+            this._handlerJsonEditor()
+          }, 200)
+        } else {
+          this.customConfig = 0
+          setTimeout(() => {
+            this._handlerEditor()
+          }, 200)
+        }
+      },
       /**
        * return data source
        */
@@ -183,50 +240,66 @@
        * verification
        */
       _verification () {
-        if (!editor.getValue()) {
-          this.$message.warning(`${i18n.$t('Please enter a SQL Statement(required)')}`)
-          return false
-        }
+        if(this.customConfig) {
+          if (!jsonEditor.getValue()) {
+            this.$message.warning(`${i18n.$t('Please enter a JSON Statement(required)')}`)
+            return false
+          }
 
-        // datasource Subcomponent verification
-        if (!this.$refs.refDs._verifDatasource()) {
-          return false
-        }
+          // storage
+          this.$emit('on-params', {
+            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
-        if (!this.$refs.refDt._verifDatasource()) {
-          return false
-        }
+          // datasource Subcomponent verification
+          if (!this.$refs.refDs._verifDatasource()) {
+            return false
+          }
 
-        if (!this.targetTable) {
-          this.$message.warning(`${i18n.$t('Please enter a Target Table(required)')}`)
-          return false
-        }
+          // datasource Subcomponent verification
+          if (!this.$refs.refDt._verifDatasource()) {
+            return false
+          }
 
-        // preStatements Subcomponent verification
-        if (!this.$refs.refPreStatements._verifProp()) {
-          return false
-        }
+          if (!this.targetTable) {
+            this.$message.warning(`${i18n.$t('Please enter a Target Table(required)')}`)
+            return false
+          }
 
-        // postStatements Subcomponent verification
-        if (!this.$refs.refPostStatements._verifProp()) {
-          return false
-        }
+          // preStatements Subcomponent verification
+          if (!this.$refs.refPreStatements._verifProp()) {
+            return false
+          }
 
-        // storage
-        this.$emit('on-params', {
-          dsType: this.dsType,
-          dataSource: this.rtDatasource,
-          dtType: this.dtType,
-          dataTarget: this.rtDatatarget,
-          sql: editor.getValue(),
-          targetTable: this.targetTable,
-          jobSpeedByte: this.jobSpeedByte * 1024,
-          jobSpeedRecord: this.jobSpeedRecord,
-          preStatements: this.preStatements,
-          postStatements: this.postStatements
-        })
-        return true
+          // postStatements Subcomponent verification
+          if (!this.$refs.refPostStatements._verifProp()) {
+            return false
+          }
+
+          // storage
+          this.$emit('on-params', {
+            customConfig: this.customConfig,
+            dsType: this.dsType,
+            dataSource: this.rtDatasource,
+            dtType: this.dtType,
+            dataTarget: this.rtDatatarget,
+            sql: editor.getValue(),
+            targetTable: this.targetTable,
+            jobSpeedByte: this.jobSpeedByte * 1024,
+            jobSpeedRecord: this.jobSpeedRecord,
+            preStatements: this.preStatements,
+            postStatements: this.postStatements
+          })
+          return true
+        }
       },
       /**
        * Processing code highlighting
@@ -259,6 +332,34 @@
 
         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 () {
         this.$emit('on-cache-params', {
           dsType: this.dsType,
@@ -279,6 +380,13 @@
           editor.off($('.code-sql-mirror'), 'keypress', this.keypress)
           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 () {
@@ -287,22 +395,37 @@
       // Non-null objects represent backfill
       if (!_.isEmpty(o)) {
         // backfill
-        this.dsType = o.params.dsType || ''
-        this.datasource = o.params.dataSource || ''
-        this.dtType = o.params.dtType || ''
-        this.datatarget = o.params.dataTarget || ''
-        this.sql = o.params.sql || ''
-        this.targetTable = o.params.targetTable || ''
-        this.jobSpeedByte = o.params.jobSpeedByte / 1024 || 0
-        this.jobSpeedRecord = o.params.jobSpeedRecord || 0
-        this.preStatements = o.params.preStatements || []
-        this.postStatements = o.params.postStatements || []
+        if(o.params.customConfig == 0) {
+          this.customConfig = 0
+          this.enable = false
+          this.dsType = o.params.dsType || ''
+          this.datasource = o.params.dataSource || ''
+          this.dtType = o.params.dtType || ''
+          this.datatarget = o.params.dataTarget || ''
+          this.sql = o.params.sql || ''
+          this.targetTable = o.params.targetTable || ''
+          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 () {
-      setTimeout(() => {
-        this._handlerEditor()
-      }, 200)
+      if(this.customConfig) {
+        setTimeout(() => {
+          this._handlerJsonEditor()
+        }, 200)
+      } else {
+        setTimeout(() => {
+          this._handlerEditor()
+        }, 200)
+      }
     },
     destroyed () {
       /**
@@ -312,6 +435,10 @@
         editor.toTextArea() // Uninstall
         editor.off($('.code-sql-mirror'), 'keypress', this.keypress)
       }
+      if (jsonEditor) {
+        jsonEditor.toTextArea() // Uninstall
+        jsonEditor.off($('.code-json-mirror'), 'keypress', this.keypress)
+      }
     },
     watch: {
       //Watch the cacheParams
diff --git a/dolphinscheduler-ui/src/js/module/components/transfer/resource.vue b/dolphinscheduler-ui/src/js/module/components/transfer/resource.vue
index 1192ab2..72205de 100644
--- a/dolphinscheduler-ui/src/js/module/components/transfer/resource.vue
+++ b/dolphinscheduler-ui/src/js/module/components/transfer/resource.vue
@@ -20,8 +20,8 @@
       <div class="clearfix transfer-model" style="width: 660px">
         <div>
             <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="udfResource" @click="_ckUDf">{{$t('UDF 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-group>
         </div>
         <div class="select-list-box">
diff --git a/dolphinscheduler-ui/src/js/module/i18n/locale/en_US.js b/dolphinscheduler-ui/src/js/module/i18n/locale/en_US.js
index 64ab298..819af7c 100755
--- a/dolphinscheduler-ui/src/js/module/i18n/locale/en_US.js
+++ b/dolphinscheduler-ui/src/js/module/i18n/locale/en_US.js
@@ -90,6 +90,7 @@ export default {
   'Please enter other parameters': 'Please enter other parameters',
   'Resources': 'Resources',
   'Custom Parameters': 'Custom Parameters',
+  'Custom template': 'Custom template',
   'Datasource': 'Datasource',
   'methods': 'methods',
   'Please enter method(optional)': 'Please enter method(optional)',
@@ -119,6 +120,7 @@ export default {
   'SQL Statement': 'SQL Statement',
   'UDF Function': 'UDF Function',
   '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',
   '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'
+  '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'
 }
diff --git a/dolphinscheduler-ui/src/js/module/i18n/locale/zh_CN.js b/dolphinscheduler-ui/src/js/module/i18n/locale/zh_CN.js
index 3363eea..fe67bae 100755
--- a/dolphinscheduler-ui/src/js/module/i18n/locale/zh_CN.js
+++ b/dolphinscheduler-ui/src/js/module/i18n/locale/zh_CN.js
@@ -90,6 +90,7 @@ export default {
   'Please enter other parameters': '请输入其他参数',
   'Resources': '资源',
   'Custom Parameters': '自定义参数',
+  'Custom template': '自定义模版',
   'Please enter main class': '请填写主函数的class',
   'Datasource': '数据源',
   'methods': '方法',
@@ -120,6 +121,7 @@ export default {
   'SQL Statement': 'sql语句',
   'UDF Function': 'UDF函数',
   'Please enter a SQL Statement(required)': '请输入sql语句(必填)',
+  'Please enter a JSON Statement(required)': '请输入json语句(必填)',
   'One form or attachment must be selected': '表格、附件必须勾选一个',
   'Recipient required': '收件人邮箱必填',
   'Mail subject required': '邮件主题必填',
@@ -568,5 +570,6 @@ export default {
   'All Columns': '全表导入',
   'Some Columns': '选择列',
   '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': '成功分支流转和失败分支流转必填',
 }