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

lgcareer 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 a34f829  [Improvement][ui] Refactored dag formatting logic (#3703)
a34f829 is described below

commit a34f8296cc14e143eea86fb9250524d541b2e4f0
Author: elonlo <[email protected]>
AuthorDate: Wed Sep 16 18:04:49 2020 +0800

    [Improvement][ui] Refactored dag formatting logic (#3703)
    
    Co-authored-by: dashi <[email protected]>
---
 dolphinscheduler-dist/release-docs/LICENSE         |   1 +
 .../licenses/ui-licenses/LICENSE-dagre             |  19 ++
 dolphinscheduler-ui/package.json                   |   1 +
 .../src/js/conf/home/pages/dag/_source/dag.js      | 212 +++------------------
 4 files changed, 45 insertions(+), 188 deletions(-)

diff --git a/dolphinscheduler-dist/release-docs/LICENSE 
b/dolphinscheduler-dist/release-docs/LICENSE
index 59da274..707ea5c 100644
--- a/dolphinscheduler-dist/release-docs/LICENSE
+++ b/dolphinscheduler-dist/release-docs/LICENSE
@@ -502,6 +502,7 @@ MIT licenses
     vue-router 2.7.0: https://github.com/vuejs/vue-router MIT
     vuex 3.0.0: https://github.com/vuejs/vuex MIT
     vuex-router-sync 4.1.2: https://github.com/vuejs/vuex-router-sync MIT
+    dagre 0.8.5: https://github.com/dagrejs/dagre MIT
 
 ========================================
 Apache 2.0 licenses
diff --git 
a/dolphinscheduler-dist/release-docs/licenses/ui-licenses/LICENSE-dagre 
b/dolphinscheduler-dist/release-docs/licenses/ui-licenses/LICENSE-dagre
new file mode 100644
index 0000000..e3c8f95
--- /dev/null
+++ b/dolphinscheduler-dist/release-docs/licenses/ui-licenses/LICENSE-dagre
@@ -0,0 +1,19 @@
+Copyright (c) 2012-2014 Chris Pettitt
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file
diff --git a/dolphinscheduler-ui/package.json b/dolphinscheduler-ui/package.json
index a5642c8..9624fa6 100644
--- a/dolphinscheduler-ui/package.json
+++ b/dolphinscheduler-ui/package.json
@@ -20,6 +20,7 @@
     "clipboard": "^2.0.1",
     "codemirror": "^5.43.0",
     "d3": "^3.5.17",
+    "dagre": "^0.8.5",
     "dayjs": "^1.7.8",
     "echarts": "4.1.0",
     "html2canvas": "^0.5.0-beta4",
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/dag.js 
b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/dag.js
index ff8a452..d7f2f78 100644
--- a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/dag.js
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/dag.js
@@ -22,6 +22,7 @@ import { jsPlumb } from 'jsplumb'
 import JSP from './plugIn/jsPlumbHandle'
 import DownChart from './plugIn/downChart'
 import store from '@/conf/home/store'
+import dagre from "dagre"
 
 /**
  * Prototype method
@@ -115,202 +116,38 @@ Dag.prototype.toolbarEvent = function ({ item, code, is 
}) {
  */
 Dag.prototype.backfill = function (arg) {
   if (arg) {
-    let locationsValue = store.state.dag.locations
-    const locationsValue1 = store.state.dag.locations
-    const locationsValue2 = store.state.dag.locations
-    const arr = []
-    for (const i in locationsValue1) {
-      const objs = {}
-      objs.id = i
-      arr.push(Object.assign(objs, locationsValue1[i])) // Attributes
-    }
-    const tmp = []
-    for (const i in locationsValue2) {
-      if (locationsValue2[i].targetarr !== '' && 
locationsValue2[i].targetarr.split(',').length > 1) {
-        tmp.push(locationsValue2[i])
-      }
-    }
-
-    const copy = function (array) {
-      const newArray = []
-      for (const item of array) {
-        newArray.push(item)
-      }
-      return newArray
-    }
-
-    const newArr = copy(arr)
-    const getNewArr = function () {
-      for (let i = 0; i < newArr.length; i++) {
-        if (newArr[i].targetarr !== '' && 
newArr[i].targetarr.split(',').length > 1) {
-          newArr[i].targetarr = newArr[i].targetarr.split(',').shift()
-        }
-      }
-      return newArr
-    }
-    getNewArr()
-    /**
-    * @description Transform flat data into a tree structure
-    * @param {Array} arr Flat data
-    * @param {String} pidStr targetarr key name
-    * @param {String} idStr id key name
-    * @param {String} childrenStr children key name
-    */
-    const fommat = function ({ arrayList, pidStr = 'targetarr', idStr = 'id', 
childrenStr = 'children' }) {
-      const listOjb = {} // Used to store objects of the form {key: obj}
-      const treeList = [] // An array to store the final tree structure data
-      // Transform the data into {key: obj} format, which is convenient for 
the following data processing
-      for (let i = 0; i < arrayList.length; i++) {
-        listOjb[arrayList[i][idStr]] = arrayList[i]
-      }
-      // Format data based on pid
-      for (let j = 0; j < arrayList.length; j++) {
-        // Determine if the parent exists
-        // let haveParent = 
arrayList[j].targetarr.split(',').length>1?listOjb[arrayList[j].targetarr.split(',')[0]]:listOjb[arrayList[j][pidStr]]
-        const haveParent = listOjb[arrayList[j][pidStr]]
-        if (haveParent) {
-          // If there is no parent children field, create a children field
-          !haveParent[childrenStr] && (haveParent[childrenStr] = [])
-          // Insert child in parent
-          haveParent[childrenStr].push(arrayList[j])
-        } else {
-          // If there is no parent, insert directly into the outermost layer
-          treeList.push(arrayList[j])
-        }
-      }
-      return treeList
-    }
-    const datas = fommat({ arrayList: newArr, pidStr: 'targetarr' })
-    // Count the number of leaf nodes
-    const getLeafCountTree = function (json) {
-      if (!json.children) {
-        json.colspan = 1
-        return 1
-      } else {
-        let leafCount = 0
-        for (let i = 0; i < json.children.length; i++) {
-          leafCount = leafCount + getLeafCountTree(json.children[i])
-        }
-        json.colspan = leafCount
-        return leafCount
-      }
-    }
-    // Number of tree node levels
-    const countTree = getLeafCountTree(datas[0])
-    const getMaxFloor = function (treeData) {
-      let max = 0
-      function each (data, floor) {
-        data.forEach(e => {
-          e.floor = floor
-          e.x = floor * 170
-          if (floor > max) {
-            max = floor
-          }
-          if (e.children) {
-            each(e.children, floor + 1)
-          }
-        })
-      }
-      each(treeData, 1)
-      return max
-    }
-    getMaxFloor(datas)
-    // The last child of each node
-    let lastchildren = []
-    const forxh = function (list) {
-      for (let i = 0; i < list.length; i++) {
-        const chlist = list[i]
-        if (chlist.children) {
-          forxh(chlist.children)
-        } else {
-          lastchildren.push(chlist)
-        }
-      }
-    }
-    forxh(datas)
-    // Get all parent nodes above the leaf node
-    const treeFindPath = function (tree, func, path, n) {
-      if (!tree) return []
-      for (const data of tree) {
-        path.push(data.name)
-        if (func(data)) return path
-        if (data.children) {
-          const findChildren = treeFindPath(data.children, func, path, n)
-          if (findChildren.length) return findChildren
-        }
-        path.pop()
-      }
-      return []
-    }
-    const toLine = function (data) {
-      return data.reduce((arrData, { id, name, targetarr, x, y, children = [] 
}) =>
-        arrData.concat([{ id, name, targetarr, x, y }], toLine(children)), [])
-    }
-    const listarr = toLine(datas)
-    const listarrs = toLine(datas)
-    const dataObject = {}
-    for (let i = 0; i < listarrs.length; i++) {
-      delete (listarrs[i].id)
-    }
+    const marginX = 100
+    const g = new dagre.graphlib.Graph()
+    g.setGraph({})
+    g.setDefaultEdgeLabel(function () { return {} })
 
-    for (let a = 0; a < listarr.length; a++) {
-      dataObject[listarr[a].id] = listarrs[a]
+    for (const i in store.state.dag.locations) {
+      const location = store.state.dag.locations[i]
+      g.setNode(i, { label: i, width: Math.min(location.name.length * 7, 170), 
height: 150 })
     }
-    // Comparison function
-    const createComparisonFunction = function (propertyName) {
-      return function (object1, object2) {
-        const value1 = object1[propertyName]
-        const value2 = object2[propertyName]
 
-        if (value1 < value2) {
-          return -1
-        } else if (value1 > value2) {
-          return 1
-        } else {
-          return 0
-        }
-      }
+    for (const i in store.state.dag.connects) {
+      const connect = store.state.dag.connects[i]
+      g.setEdge(connect['endPointSourceId'], connect['endPointTargetId'])
     }
+    dagre.layout(g)
 
-    lastchildren = lastchildren.sort(createComparisonFunction('x'))
-
-    // Coordinate value of each leaf node
-    for (let a = 0; a < lastchildren.length; a++) {
-      dataObject[lastchildren[a].id].y = (a + 1) * 120
-    }
-    for (let i = 0; i < lastchildren.length; i++) {
-      const node = treeFindPath(datas, data => data.targetarr === 
lastchildren[i].targetarr, [], i + 1)
-      for (let j = 0; j < node.length; j++) {
-        for (let k = 0; k < listarrs.length; k++) {
-          if (node[j] === listarrs[k].name) {
-            listarrs[k].y = (i + 1) * 120
-          }
-        }
-      }
-    }
-    for (let i = 0; i < tmp.length; i++) {
-      for (const objs in dataObject) {
-        if (tmp[i].name === dataObject[objs].name) {
-          dataObject[objs].targetarr = tmp[i].targetarr
-        }
-      }
-    }
-    for (let a = 0; a < lastchildren.length; a++) {
-      dataObject[lastchildren[a].id].y = (a + 1) * 120
-    }
-    if (countTree > 1) {
-      dataObject[Object.keys(locationsValue1)[0]].y = (countTree / 2) * 120 + 
50
-    }
-
-    locationsValue = dataObject
-    const self = this
+    const dataObject = {}
+    g.nodes().forEach(function (v) {
+      const node = g.node(v)
+      const obj = {}
+      obj.name = node.label
+      obj.x = node.x + marginX
+      obj.y = node.y
+      dataObject[node.label] = obj
+    })
     jsPlumb.ready(() => {
       JSP.init({
         dag: this.dag,
         instance: this.instance,
         options: {
           onRemoveNodes ($id) {
-            self.dag.removeEventModelById($id)
+            this.dag.removeEventModelById($id)
           }
         }
       })
@@ -319,20 +156,19 @@ Dag.prototype.backfill = function (arg) {
         // connects
         connects: _.cloneDeep(store.state.dag.connects),
         // Node location information
-        locations: _.cloneDeep(locationsValue),
+        locations: _.cloneDeep(dataObject),
         // Node data
         largeJson: _.cloneDeep(store.state.dag.tasks)
       })
     })
   } else {
-    const self = this
     jsPlumb.ready(() => {
       JSP.init({
         dag: this.dag,
         instance: this.instance,
         options: {
           onRemoveNodes ($id) {
-            self.dag.removeEventModelById($id)
+            this.dag.removeEventModelById($id)
           }
         }
       })

Reply via email to