You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dolphinscheduler.apache.org by le...@apache.org on 2021/09/06 08:15:10 UTC
[dolphinscheduler] branch json_split_two updated:
[Feature-5498][JsonSplit-api] refactor of dolphin-scheduler-ui/dag (#6098)
This is an automated email from the ASF dual-hosted git repository.
leonbao pushed a commit to branch json_split_two
in repository https://gitbox.apache.org/repos/asf/dolphinscheduler.git
The following commit(s) were added to refs/heads/json_split_two by this push:
new d4f5012 [Feature-5498][JsonSplit-api] refactor of dolphin-scheduler-ui/dag (#6098)
d4f5012 is described below
commit d4f5012f422f9319e21e0c71852b2385a4985ad5
Author: Wangyizhi1 <87...@users.noreply.github.com>
AuthorDate: Mon Sep 6 16:14:48 2021 +0800
[Feature-5498][JsonSplit-api] refactor of dolphin-scheduler-ui/dag (#6098)
* refactor of dolphin-scheduler-ui/dag
* copy task feature and code optimization
* fix review & ut bugs
* add newline at end of file
* add license header
Co-authored-by: chenxiwei <cx...@139.com>
Co-authored-by: chenxiwei <ch...@cmss.chinamobile.com>
---
dolphinscheduler-ui/package.json | 2 +
.../{plugIn/dragZoom.js => canvas/canvas.scss} | 52 +-
.../conf/home/pages/dag/_source/canvas/canvas.vue | 739 +++++++++++++
.../dragZoom.js => canvas/contextMenu.scss} | 42 +-
.../home/pages/dag/_source/canvas/contextMenu.vue | 155 +++
.../dragZoom.js => canvas/draggableBox.vue} | 54 +-
.../pages/dag/_source/canvas/edgeEditModel.vue | 114 ++
.../{plugIn/dragZoom.js => canvas/menuItem.vue} | 46 +-
.../{plugIn/dragZoom.js => canvas/statusMenu.scss} | 24 +-
.../home/pages/dag/_source/canvas/statusMenu.vue | 70 ++
.../home/pages/dag/_source/canvas/taskbar.scss | 167 +++
.../conf/home/pages/dag/_source/canvas/taskbar.vue | 64 ++
.../home/pages/dag/_source/canvas/toolbar.scss | 113 ++
.../conf/home/pages/dag/_source/canvas/toolbar.vue | 199 ++++
.../home/pages/dag/_source/canvas/x6-helper.js | 323 ++++++
.../{plugIn/dragZoom.js => canvas/x6-style.scss} | 32 +-
.../src/js/conf/home/pages/dag/_source/dag.js | 195 ----
.../src/js/conf/home/pages/dag/_source/dag.scss | 563 +---------
.../src/js/conf/home/pages/dag/_source/dag.vue | 1143 +++++++-------------
.../home/pages/dag/_source/formModel/formModel.vue | 220 ++--
.../conf/home/pages/dag/_source/formModel/log.vue | 1 +
.../dag/_source/formModel/tasks/sub_process.vue | 32 +-
.../pages/dag/_source/images/full-screen-close.png | Bin 0 -> 463 bytes
.../dag/_source/images/full-screen-close_hover.png | Bin 0 -> 652 bytes
.../pages/dag/_source/images/full-screen-open.png | Bin 0 -> 575 bytes
.../dag/_source/images/full-screen-open_hover.png | Bin 0 -> 575 bytes
.../home/pages/dag/_source/images/graph-format.png | Bin 0 -> 458 bytes
.../dag/_source/images/graph-format_hover.png | Bin 0 -> 461 bytes
.../pages/dag/_source/images/startup-params.png | Bin 0 -> 903 bytes
.../dag/_source/images/startup-params_hover.png | Bin 0 -> 903 bytes
.../dag/_source/images/task-icos/conditions.png | Bin 0 -> 812 bytes
.../_source/images/task-icos/conditions_hover.png | Bin 0 -> 736 bytes
.../pages/dag/_source/images/task-icos/datax.png | Bin 0 -> 1122 bytes
.../dag/_source/images/task-icos/datax_hover.png | Bin 0 -> 1127 bytes
.../dag/_source/images/task-icos/dependent.png | Bin 0 -> 743 bytes
.../_source/images/task-icos/dependent_hover.png | Bin 0 -> 745 bytes
.../pages/dag/_source/images/task-icos/flink.png | Bin 0 -> 1443 bytes
.../dag/_source/images/task-icos/flink_hover.png | Bin 0 -> 1348 bytes
.../pages/dag/_source/images/task-icos/http.png | Bin 0 -> 707 bytes
.../dag/_source/images/task-icos/http_hover.png | Bin 0 -> 709 bytes
.../home/pages/dag/_source/images/task-icos/mr.png | Bin 0 -> 930 bytes
.../dag/_source/images/task-icos/mr_hover.png | Bin 0 -> 862 bytes
.../dag/_source/images/task-icos/procedure.png | Bin 0 -> 1555 bytes
.../_source/images/task-icos/procedure_hover.png | Bin 0 -> 1436 bytes
.../pages/dag/_source/images/task-icos/python.png | Bin 0 -> 1618 bytes
.../dag/_source/images/task-icos/python_hover.png | Bin 0 -> 1233 bytes
.../pages/dag/_source/images/task-icos/shell.png | Bin 0 -> 747 bytes
.../dag/_source/images/task-icos/shell_hover.png | Bin 0 -> 745 bytes
.../pages/dag/_source/images/task-icos/spark.png | Bin 0 -> 1067 bytes
.../dag/_source/images/task-icos/spark_hover.png | Bin 0 -> 1066 bytes
.../pages/dag/_source/images/task-icos/sql.png | Bin 0 -> 1317 bytes
.../dag/_source/images/task-icos/sql_hover.png | Bin 0 -> 1262 bytes
.../pages/dag/_source/images/task-icos/sqoop.png | Bin 0 -> 896 bytes
.../dag/_source/images/task-icos/sqoop_hover.png | Bin 0 -> 897 bytes
.../dag/_source/images/task-icos/sub_process.png | Bin 0 -> 692 bytes
.../_source/images/task-icos/sub_process_hover.png | Bin 0 -> 693 bytes
.../dag/_source/images/task-icos/waterdrop.png | Bin 0 -> 1086 bytes
.../_source/images/task-icos/waterdrop_hover.png | Bin 0 -> 1054 bytes
.../pages/dag/_source/images/view-variables.png | Bin 0 -> 858 bytes
.../dag/_source/images/view-variables_hover.png | Bin 0 -> 858 bytes
.../home/pages/dag/_source/plugIn/downChart.js | 122 ---
.../home/pages/dag/_source/plugIn/jsPlumbHandle.js | 814 --------------
.../home/pages/dag/_source/plugIn/multiDrag.js | 67 --
.../js/conf/home/pages/dag/_source/plugIn/util.js | 171 ---
.../pages/dag/_source/udp/_source/selectTenant.vue | 7 +-
.../src/js/conf/home/pages/dag/_source/udp/udp.vue | 16 +-
.../js/conf/home/pages/dag/definitionDetails.vue | 8 +-
.../pages/definition/pages/list/_source/list.vue | 12 +-
.../pages/definition/pages/list/_source/start.vue | 4 +-
.../src/js/conf/home/router/index.js | 28 +-
.../src/js/conf/home/store/dag/actions.js | 221 ++--
.../src/js/conf/home/store/dag/mutations.js | 54 +-
.../src/js/conf/home/store/dag/state.js | 6 +-
73 files changed, 2707 insertions(+), 3173 deletions(-)
diff --git a/dolphinscheduler-ui/package.json b/dolphinscheduler-ui/package.json
index f1810e6..fe21c59 100644
--- a/dolphinscheduler-ui/package.json
+++ b/dolphinscheduler-ui/package.json
@@ -15,6 +15,8 @@
"build:release": "npm run clean && cross-env NODE_ENV=production PUBLIC_PATH=/dolphinscheduler/ui webpack --config ./build/webpack.config.release.js"
},
"dependencies": {
+ "@antv/layout": "^0.1.18",
+ "@antv/x6": "^1.25.5",
"@form-create/element-ui": "^1.0.18",
"@riophae/vue-treeselect": "^0.4.0",
"axios": "^0.16.2",
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/dragZoom.js b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/canvas.scss
similarity index 58%
copy from dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/dragZoom.js
copy to dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/canvas.scss
index 009c82b..e02ca68 100644
--- a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/dragZoom.js
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/canvas.scss
@@ -1,4 +1,3 @@
-import d3 from 'd3'
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -15,24 +14,39 @@ import d3 from 'd3'
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+.dag-canvas {
+ display: flex;
+ overflow: hidden;
+ height: calc(100% - 50px);
+ padding: 10px 0 0 0;
+ box-sizing: border-box;
-const DragZoom = function () {
- this.element = {}
- this.zoom = {}
- this.scale = 1
-}
+ .dag-container {
+ height: 100%;
+ flex: 1;
+ overflow: hidden;
+ position: relative;
+
+ .paper {
+ width: 100%;
+ height: 100%;
+ }
+
+ .minimap {
+ position: absolute;
+ width: 300px;
+ height: 200px;
+ right: 10px;
+ bottom: 10px;
+ border: dashed 1px #e4e4e4;
+ z-index: 9;
+ }
-DragZoom.prototype.init = function () {
- const $canvas = $('#canvas')
- this.element = d3.select('#canvas')
- this.zoom = d3.behavior.zoom()
- .scaleExtent([0.5, 2])
- .on('zoom', () => {
- this.scale = d3.event.scale
- $canvas.css('transform', 'scale(' + this.scale + ')')
- $canvas.css('transform-origin', '0 0')
- })
- this.element.call(this.zoom).on('dblclick.zoom', null)
+ .context-menu{
+ position: absolute;
+ left: 100px;
+ top: 100px;
+ }
+
+ }
}
-
-export default new DragZoom()
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/canvas.vue b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/canvas.vue
new file mode 100644
index 0000000..fd4109f
--- /dev/null
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/canvas.vue
@@ -0,0 +1,739 @@
+/*
+ * 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>
+ <div class="dag-canvas">
+ <dag-taskbar @on-drag-start="_onDragStart" />
+ <div
+ class="dag-container"
+ ref="container"
+ @dragenter.prevent
+ @dragover.prevent
+ @dragleave.prevent
+ @drop.stop.prevent="_onDrop"
+ >
+ <div ref="paper" class="paper"></div>
+ <div ref="minimap" class="minimap"></div>
+ <context-menu ref="contextMenu" />
+ <status-menu ref="statusMenu" />
+ </div>
+ </div>
+</template>
+
+<script>
+ import { Graph, DataUri } from '@antv/x6'
+ import dagTaskbar from './taskbar.vue'
+ import contextMenu from './contextMenu.vue'
+ import statusMenu from './statusMenu.vue'
+ import {
+ NODE_PROPS,
+ EDGE_PROPS,
+ PORT_PROPS,
+ X6_NODE_NAME,
+ X6_PORT_OUT_NAME,
+ X6_PORT_IN_NAME,
+ X6_EDGE_NAME,
+ NODE_HIGHLIGHT_PROPS,
+ PORT_HIGHLIGHT_PROPS,
+ EDGE_HIGHLIGHT_PROPS
+ } from './x6-helper'
+ import { DagreLayout } from '@antv/layout'
+ import { tasksType } from '../config'
+ import _ from 'lodash'
+ import { mapActions, mapMutations } from 'vuex'
+
+ export default {
+ name: 'dag-canvas',
+ data () {
+ return {
+ graph: null,
+ // Used to calculate the context menu location
+ originalScrollPosition: {
+ left: 0,
+ top: 0
+ },
+ editable: true,
+ dragging: {
+ // Distance from the mouse to the top-left corner of the dragging element
+ x: 0,
+ y: 0,
+ type: ''
+ }
+ }
+ },
+ provide () {
+ return {
+ dagCanvas: this
+ }
+ },
+ inject: ['dagChart'],
+ components: {
+ dagTaskbar,
+ contextMenu,
+ statusMenu
+ },
+ methods: {
+ ...mapActions('dag', ['genTaskCodeList']),
+ ...mapMutations('dag', ['removeTask']),
+ /**
+ * Recalculate the paper width and height
+ */
+ paperResize () {
+ const w = this.$el.offsetWidth
+ const h = this.$el.offsetHeight
+ this.graph.resize(w, h)
+ },
+ /**
+ * Init graph
+ * This will be called in the dag-chart mounted event
+ * @param {boolean} uneditable
+ */
+ graphInit (editable) {
+ const self = this
+ this.editable = !!editable
+ const paper = this.$refs.paper
+ const minimap = this.$refs.minimap
+ const graph = (this.graph = new Graph({
+ container: paper,
+ selecting: {
+ enabled: true,
+ multiple: true,
+ rubberband: true,
+ rubberEdge: true,
+ movable: true,
+ showNodeSelectionBox: false
+ },
+ scroller: true,
+ grid: {
+ size: 10,
+ visible: true
+ },
+ snapline: true,
+ minimap: {
+ enabled: true,
+ container: minimap
+ },
+ interacting: {
+ edgeLabelMovable: false,
+ nodeMovable: !!editable,
+ magnetConnectable: !!editable
+ },
+ connecting: {
+ snap: {
+ radius: 30
+ },
+ // Whether multiple edges can be created between the same start node and end
+ allowMulti: false,
+ // Whether a point is allowed to connect to a blank position on the canvas
+ allowBlank: false,
+ // The start node and the end node are the same node
+ allowLoop: false,
+ // Whether an edge is allowed to link to another edge
+ allowEdge: false,
+ // Whether edges are allowed to link to nodes
+ allowNode: true,
+ // Whether to allow edge links to ports
+ allowPort: true,
+ // Whether all available ports or nodes are highlighted when you drag the edge
+ highlight: true,
+ createEdge () {
+ return graph.createEdge({ shape: X6_EDGE_NAME })
+ },
+ validateMagnet ({ magnet }) {
+ return magnet.getAttribute('port-group') !== X6_PORT_IN_NAME
+ },
+ validateConnection (data) {
+ const { sourceCell, targetCell, sourceMagnet, targetMagnet } = data
+ // Connections can only be created from the output link post
+ if (
+ !sourceMagnet ||
+ sourceMagnet.getAttribute('port-group') !== X6_PORT_OUT_NAME
+ ) {
+ return false
+ }
+
+ // Can only be connected to the input link post
+ if (
+ !targetMagnet ||
+ targetMagnet.getAttribute('port-group') !== X6_PORT_IN_NAME
+ ) {
+ return false
+ }
+
+ if (
+ sourceCell &&
+ targetCell &&
+ sourceCell.isNode() &&
+ targetCell.isNode()
+ ) {
+ const edgeData = {
+ sourceId: Number(sourceCell.id),
+ targetId: Number(targetCell.id)
+ }
+ if (!self.dagChart.edgeIsValid(edgeData)) {
+ return false
+ }
+ }
+
+ return true
+ }
+ },
+ highlighting: {
+ nodeAvailable: {
+ name: 'className',
+ args: {
+ className: 'available'
+ }
+ },
+ magnetAvailable: {
+ name: 'className',
+ args: {
+ className: 'available'
+ }
+ },
+ magnetAdsorbed: {
+ name: 'className',
+ args: {
+ className: 'adsorbed'
+ }
+ }
+ }
+ }))
+ // TODO will be deleted
+ window._graph = graph
+ this.registerX6Shape()
+ this.bindGraphEvent()
+ this.originalScrollPosition = graph.getScrollbarPosition()
+ },
+ /**
+ * Register custom shapes
+ */
+ registerX6Shape () {
+ Graph.unregisterNode(X6_NODE_NAME)
+ Graph.unregisterEdge(X6_EDGE_NAME)
+ Graph.registerNode(X6_NODE_NAME, { ...NODE_PROPS })
+ Graph.registerEdge(X6_EDGE_NAME, { ...EDGE_PROPS })
+ },
+ /**
+ * Bind grap event
+ */
+ bindGraphEvent () {
+ // nodes and edges hover
+ this.graph.on('cell:mouseenter', (data) => {
+ const { cell, e } = data
+ const { left: cL, top: cT } =
+ this.$refs.container.getBoundingClientRect()
+ const cX = e.clientX - cL
+ const cY = e.clientY - cT
+ const isStatusIcon = (tagName) =>
+ tagName && tagName.toLocaleLowerCase() === 'i'
+ if (isStatusIcon(e.target.tagName)) {
+ this.$refs.statusMenu.show(cX, cY)
+ this.$refs.statusMenu.setCurrentTask({
+ name: cell.data.taskName,
+ type: cell.data.taskType,
+ code: Number(cell.id)
+ })
+ } else {
+ this.setHighlight(cell)
+ }
+ })
+ this.graph.on('cell:mouseleave', ({ cell }) => {
+ if (!this.graph.isSelected(cell)) {
+ this.resetHighlight(cell)
+ }
+ this.$refs.statusMenu.hide()
+ })
+ // select
+ this.graph.on('cell:selected', ({ cell }) => {
+ this.setHighlight(cell)
+ })
+ this.graph.on('cell:unselected', ({ cell }) => {
+ if (!this.graph.isSelected(cell)) {
+ this.resetHighlight(cell)
+ }
+ })
+ // right click
+ this.graph.on('node:contextmenu', ({ x, y, cell }) => {
+ const { left, top } = this.graph.getScrollbarPosition()
+ const o = this.originalScrollPosition
+ this.$refs.contextMenu.show(x + (o.left - left), y + (o.top - top))
+ this.$refs.contextMenu.setCurrentTask({
+ name: cell.data.taskName,
+ type: cell.data.taskType,
+ code: Number(cell.id)
+ })
+ })
+ // node double click
+ this.graph.on('node:dblclick', ({ cell }) => {
+ this.dagChart.openFormModel(Number(cell.id), cell.data.taskType)
+ })
+ // create edge label
+ this.graph.on('edge:dblclick', ({ cell }) => {
+ const labelName = this.getEdgeLabelName(cell)
+ this.dagChart.$refs.edgeEditModel.show({
+ id: cell.id,
+ label: labelName
+ })
+ })
+ },
+ /**
+ * @param {Edge|string} edge
+ */
+ getEdgeLabelName (edge) {
+ if (typeof edge === 'string') edge = this.graph.getCellById(edge)
+ const labels = edge.getLabels()
+ const labelName = _.get(labels, ['0', 'attrs', 'label', 'text'], '')
+ return labelName
+ },
+ /**
+ * Set edge label by id
+ * @param {string} id
+ * @param {string} label
+ */
+ setEdgeLabel (id, label) {
+ const edge = this.graph.getCellById(id)
+ edge.setLabels(label)
+ if (this.graph.isSelected(edge)) {
+ this.setEdgeHighlight(edge)
+ }
+ },
+ /**
+ * @param {number} limit
+ * @param {string} text
+ * Each Chinese character is equal to two chars
+ */
+ truncateText (text, n) {
+ const exp = /[\u4E00-\u9FA5]/
+ let res = ''
+ let len = text.length
+ let chinese = text.match(new RegExp(exp, 'g'))
+ if (chinese) {
+ len += chinese.length
+ }
+ if (len > n) {
+ let i = 0
+ let acc = 0
+ while (true) {
+ let char = text[i]
+ if (exp.test(char)) {
+ acc += 2
+ } else {
+ acc++
+ }
+ if (acc > n) break
+ res += char
+ i++
+ }
+ res += '...'
+ } else {
+ res = text
+ }
+ return res
+ },
+ /**
+ * Set node name by id
+ * @param {string|number} id
+ * @param {string} name
+ */
+ setNodeName (id, name) {
+ id += ''
+ const node = this.graph.getCellById(id)
+ if (node) {
+ const truncation = this.truncateText(name, 18)
+ node.attr('title/text', truncation)
+ node.setData({ taskName: name })
+ }
+ },
+ /**
+ * Set node highlight
+ * @param {Node} node
+ */
+ setNodeHighlight (node) {
+ const url = require(`../images/task-icos/${node.data.taskType.toLocaleLowerCase()}_hover.png`)
+ node.setAttrs(NODE_HIGHLIGHT_PROPS.attrs)
+ node.setAttrByPath('image/xlink:href', url)
+ node.setPortProp(
+ X6_PORT_OUT_NAME,
+ 'attrs',
+ PORT_HIGHLIGHT_PROPS[X6_PORT_OUT_NAME].attrs
+ )
+ },
+ /**
+ * Reset node style
+ * @param {Node} node
+ */
+ resetNodeStyle (node) {
+ const url = require(`../images/task-icos/${node.data.taskType.toLocaleLowerCase()}.png`)
+ node.setAttrs(NODE_PROPS.attrs)
+ node.setAttrByPath('image/xlink:href', url)
+ node.setPortProp(
+ X6_PORT_OUT_NAME,
+ 'attrs',
+ PORT_PROPS.groups[X6_PORT_OUT_NAME].attrs
+ )
+ },
+ /**
+ * Set edge highlight
+ * @param {Edge} edge
+ */
+ setEdgeHighlight (edge) {
+ edge.setAttrs(EDGE_HIGHLIGHT_PROPS.attrs)
+ const labelName = this.getEdgeLabelName(edge)
+ if (labelName) {
+ edge.setLabels([
+ _.merge(EDGE_HIGHLIGHT_PROPS.defaultLabel, {
+ attrs: {
+ label: {
+ text: labelName
+ }
+ }
+ })
+ ])
+ }
+ },
+ /**
+ * Reset edge style
+ * @param {Edge} edge
+ */
+ resetEdgeStyle (edge) {
+ edge.setAttrs(EDGE_PROPS.attrs)
+ const labelName = this.getEdgeLabelName(edge)
+ if (labelName) {
+ edge.setLabels([
+ {
+ attrs: {
+ label: {
+ fill: EDGE_PROPS.defaultLabel.attrs.label.fill,
+ text: labelName
+ },
+ body: {
+ stroke: EDGE_PROPS.defaultLabel.attrs.body.stroke
+ }
+ }
+ }
+ ])
+ }
+ },
+ /**
+ * Set cell highlight
+ * @param {Cell} cell
+ */
+ setHighlight (cell) {
+ if (cell.isEdge()) {
+ this.setEdgeHighlight(cell)
+ } else if (cell.isNode()) {
+ this.setNodeHighlight(cell)
+ }
+ },
+ /**
+ * Reset cell highlight
+ * @param {Cell} cell
+ */
+ resetHighlight (cell) {
+ if (cell.isEdge()) {
+ this.resetEdgeStyle(cell)
+ } else if (cell.isNode()) {
+ this.resetNodeStyle(cell)
+ }
+ },
+ /**
+ * Convert the graph to JSON
+ * @return {{cells:Cell[]}}
+ */
+ toJSON () {
+ return this.graph.toJSON()
+ },
+ /**
+ * Generate graph with JSON
+ */
+ fromJSON (json) {
+ this.graph.fromJSON(json)
+ },
+ /**
+ * getNodes
+ * @return {Node[]}
+ */
+ // interface Node {
+ // id: number;
+ // position: {x:number;y:number};
+ // data: {taskType:string;taskName:string;}
+ // }
+ getNodes () {
+ const nodes = this.graph.getNodes()
+ return nodes.map((node) => {
+ const position = node.getPosition()
+ const data = node.getData()
+ return {
+ id: Number(node.id),
+ position: position,
+ data: data
+ }
+ })
+ },
+ /**
+ * getEdges
+ * @return {Edge[]} Edge is inherited from the Cell
+ */
+ // interface Edge {
+ // label: string;
+ // sourceId: number;
+ // targetId: number;
+ // }
+ getEdges () {
+ const edges = this.graph.getEdges()
+ return edges.map((edge) => {
+ const labelData = edge.getLabelAt(0)
+ return {
+ label: _.get(labelData, ['attrs', 'label', 'text'], ''),
+ sourceId: Number(edge.getSourceCellId()),
+ targetId: Number(edge.getTargetCellId())
+ }
+ })
+ },
+ /**
+ * downloadPNG
+ * @param {string} filename
+ */
+ downloadPNG (fileName = 'chart') {
+ this.graph.toPNG(
+ (dataUri) => {
+ DataUri.downloadDataUri(dataUri, `${fileName}.png`)
+ },
+ {
+ padding: {
+ top: 50,
+ right: 50,
+ bottom: 50,
+ left: 50
+ },
+ backgroundColor: '#f2f3f7'
+ }
+ )
+ },
+ /**
+ * format
+ * @desc Auto layout use @antv/layout
+ */
+ format () {
+ const dagreLayout = new DagreLayout({
+ type: 'dagre',
+ rankdir: 'LR',
+ align: 'UL',
+ // Calculate the node spacing based on the edge label length
+ ranksepFunc: (d) => {
+ const edges = this.graph.getOutgoingEdges(d.id)
+ let max = 0
+ if (edges && edges.length > 0) {
+ edges.forEach((edge) => {
+ const edgeView = this.graph.findViewByCell(edge)
+ const labelWidth = +edgeView.findAttr(
+ 'width',
+ _.get(edgeView, ['labelSelectors', '0', 'body'], null)
+ )
+ max = Math.max(max, labelWidth)
+ })
+ }
+ return 50 + max
+ },
+ nodesep: 50,
+ controlPoints: true
+ })
+ const json = this.toJSON()
+ const nodes = json.cells.filter((cell) => cell.shape === X6_NODE_NAME)
+ const edges = json.cells.filter((cell) => cell.shape === X6_EDGE_NAME)
+ const newModel = dagreLayout.layout({
+ nodes: nodes,
+ edges: edges
+ })
+ this.fromJSON(newModel)
+ },
+ /**
+ * add a node to the graph
+ * @param {string|number} id
+ * @param {string} taskType
+ * @param {{x:number;y:number}} coordinate Default is { x: 100, y: 100 }
+ */
+ addNode (id, taskType, coordinate = { x: 100, y: 100 }) {
+ id += ''
+ if (!tasksType[taskType]) {
+ console.warn(`taskType:${taskType} is invalid!`)
+ return
+ }
+ const node = this.genNodeJSON(id, taskType, '', coordinate)
+ this.graph.addNode(node)
+ },
+ /**
+ * generate node json
+ * @param {number|string} id
+ * @param {string} taskType
+ * @param {{x:number;y:number}} coordinate Default is { x: 100, y: 100 }
+ */
+ genNodeJSON (id, taskType, taskName, coordinate = { x: 100, y: 100 }) {
+ id += ''
+ const url = require(`../images/task-icos/${taskType.toLocaleLowerCase()}.png`)
+ const truncation = taskName ? this.truncateText(taskName, 18) : id
+ return {
+ id: id,
+ shape: X6_NODE_NAME,
+ x: coordinate.x,
+ y: coordinate.y,
+ data: {
+ taskType: taskType,
+ taskName: taskName
+ },
+ attrs: {
+ image: {
+ // Use href instead of xlink:href, you may lose the icon when downloadPNG
+ 'xlink:href': url
+ },
+ title: {
+ text: truncation
+ }
+ }
+ }
+ },
+ /**
+ * generate edge json
+ * @param {number|string} sourceId
+ * @param {number|string} targetId
+ * @param {string} label
+ */
+ genEdgeJSON (sourceId, targetId, label = '') {
+ sourceId += ''
+ targetId += ''
+ return {
+ shape: X6_EDGE_NAME,
+ source: {
+ cell: sourceId,
+ port: X6_PORT_OUT_NAME
+ },
+ target: {
+ cell: targetId,
+ port: X6_PORT_IN_NAME
+ },
+ labels: label ? [label] : undefined
+ }
+ },
+ /**
+ * remove a node
+ * @param {string|number} id NodeId
+ */
+ removeNode (id) {
+ id += ''
+ this.graph.removeNode(id)
+ this.removeTask(id)
+ },
+ /**
+ * remove an edge
+ * @param {string|number} id EdgeId
+ */
+ removeEdge (id) {
+ id += ''
+ this.graph.removeEdge(id)
+ },
+ /**
+ * remove multiple cells
+ * @param {Cell[]} cells
+ */
+ removeCells (cells) {
+ this.graph.removeCells(cells)
+ cells.forEach((cell) => {
+ if (cell.isNode()) {
+ this.removeTask(cell.id)
+ }
+ })
+ },
+ /**
+ * Gets the current selections
+ * @return {Cell[]}
+ */
+ getSelections () {
+ return this.graph.getSelectedCells()
+ },
+ /**
+ * Lock scroller
+ */
+ lockScroller () {
+ this.graph.lockScroller()
+ },
+ /**
+ * Unlock scroller
+ */
+ unlockScroller () {
+ this.graph.unlockScroller()
+ },
+ /**
+ * Drag && Drop Event
+ */
+ _onDragStart (e, taskType) {
+ if (!this.editable) {
+ e.preventDefault()
+ return
+ }
+ this.dragging = {
+ x: e.offsetX,
+ y: e.offsetY,
+ type: taskType.name
+ }
+ },
+ calcGraphCoordinate (mClientX, mClientY) {
+ // Distance from the mouse to the top-left corner of the container;
+ const { left: cX, top: cY } =
+ this.$refs.container.getBoundingClientRect()
+ const mouseX = mClientX - cX
+ const mouseY = mClientY - cY
+
+ // The distance that paper has been scrolled
+ const { left: sLeft, top: sTop } = this.graph.getScrollbarPosition()
+ const { left: oLeft, top: oTop } = this.originalScrollPosition
+ const scrollX = sLeft - oLeft
+ const scrollY = sTop - oTop
+
+ // Distance from the mouse to the top-left corner of the dragging element;
+ const { x: eX, y: eY } = this.dragging
+
+ return {
+ x: mouseX + scrollX - eX,
+ y: mouseY + scrollY - eY
+ }
+ },
+ _onDrop (e) {
+ const { type } = this.dragging
+ const { x, y } = this.calcGraphCoordinate(e.clientX, e.clientY)
+ this.genTaskCodeList({
+ genNum: 1
+ })
+ .then((res) => {
+ const [code] = res
+ this.addNode(code, type, { x, y })
+ this.dagChart.openFormModel(code, type)
+ })
+ .catch((err) => {
+ console.error(err)
+ })
+ }
+ }
+ }
+</script>
+
+<style lang="scss" scoped>
+@import "./canvas";
+</style>
+
+<style lang="scss">
+@import "./x6-style";
+</style>
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/dragZoom.js b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/contextMenu.scss
similarity index 60%
copy from dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/dragZoom.js
copy to dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/contextMenu.scss
index 009c82b..6ea9a3c 100644
--- a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/dragZoom.js
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/contextMenu.scss
@@ -1,4 +1,3 @@
-import d3 from 'd3'
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -15,24 +14,29 @@ import d3 from 'd3'
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+.dag-context-menu{
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100px;
+ background-color: #ffffff;
+ box-shadow: 0 2px 10px rgba(0,0,0,0.12);
-const DragZoom = function () {
- this.element = {}
- this.zoom = {}
- this.scale = 1
-}
+ .menu-item{
+ padding: 5px 10px;
+ border-bottom: solid 1px #f2f3f7;
+ cursor: pointer;
+ color: rgb(89, 89, 89);
+ font-size: 12px;
-DragZoom.prototype.init = function () {
- const $canvas = $('#canvas')
- this.element = d3.select('#canvas')
- this.zoom = d3.behavior.zoom()
- .scaleExtent([0.5, 2])
- .on('zoom', () => {
- this.scale = d3.event.scale
- $canvas.css('transform', 'scale(' + this.scale + ')')
- $canvas.css('transform-origin', '0 0')
- })
- this.element.call(this.zoom).on('dblclick.zoom', null)
-}
+ &:hover:not(.disabled){
+ color: #262626;
+ background-color: #f5f5f5;
+ }
-export default new DragZoom()
+ &.disabled{
+ cursor: not-allowed;
+ color: rgba(89, 89, 89, .4);
+ }
+ }
+}
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/contextMenu.vue b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/contextMenu.vue
new file mode 100644
index 0000000..dafd521
--- /dev/null
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/contextMenu.vue
@@ -0,0 +1,155 @@
+/*
+ * 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>
+ <div
+ class="dag-context-menu"
+ v-show="visible"
+ :style="{
+ left: `${left}px`,
+ top: `${top}px`,
+ }"
+ >
+ <menu-item :disabled="!startAvailable" @on-click="onStart">
+ {{ $t("Start") }}
+ </menu-item>
+ <menu-item :disabled="readOnly" @on-click="onEdit">
+ {{ $t("Edit") }}
+ </menu-item>
+ <menu-item :disabled="readOnly" @on-click="onCopy">
+ {{ $t("Copy") }}
+ </menu-item>
+ <menu-item :disabled="readOnly" @on-click="onDelete">
+ {{ $t("Delete") }}
+ </menu-item>
+ </div>
+</template>
+
+<script>
+ import { mapState, mapActions, mapMutations } from 'vuex'
+ import { findComponentDownward, uuid } from '@/module/util/'
+ import MenuItem from './menuItem.vue'
+
+ export default {
+ name: 'dag-context-menu',
+ inject: ['dagChart', 'dagCanvas'],
+ components: {
+ MenuItem
+ },
+ data () {
+ return {
+ visible: false,
+ left: 0,
+ top: 0,
+ canvasRef: null,
+ currentTask: {
+ code: 0,
+ name: '',
+ type: ''
+ }
+ }
+ },
+ computed: {
+ ...mapState('dag', ['isDetails', 'releaseState', 'tasks']),
+ startAvailable () {
+ return (
+ this.$route.name === 'projects-definition-details' &&
+ this.releaseState !== 'NOT_RELEASE'
+ )
+ },
+ readOnly () {
+ return this.isDetails
+ }
+ },
+ mounted () {
+ document.addEventListener('click', (e) => {
+ this.hide()
+ })
+ },
+ methods: {
+ ...mapActions('dag', ['genTaskCodeList']),
+ ...mapMutations('dag', ['addTask']),
+ getDagCanvasRef () {
+ if (this.canvasRef) {
+ return this.canvasRef
+ } else {
+ const canvas = findComponentDownward(this.dagChart, 'dag-canvas')
+ this.canvasRef = canvas
+ return canvas
+ }
+ },
+ setCurrentTask (task) {
+ this.currentTask = { ...this.currentTask, ...task }
+ },
+ onStart () {
+ this.dagChart.startRunning(this.currentTask.name)
+ },
+ onEdit () {
+ this.dagChart.openFormModel(this.currentTask.code, this.currentTask.type)
+ },
+ onCopy () {
+ const nodes = this.dagCanvas.getNodes()
+ const targetNode = nodes.find(
+ (node) => node.id === this.currentTask.code
+ )
+ const targetTask = this.tasks.find(
+ (task) => task.code === this.currentTask.code
+ )
+
+ if (!targetNode || !targetTask) return
+
+ this.genTaskCodeList({
+ genNum: 1
+ })
+ .then((res) => {
+ const [code] = res
+ const taskName = uuid(targetTask.name + '_')
+ const task = {
+ ...targetTask,
+ code,
+ name: taskName
+ }
+ this.dagCanvas.addNode(code, this.currentTask.type, {
+ x: targetNode.position.x + 100,
+ y: targetNode.position.y + 100
+ })
+ this.addTask(task)
+ this.dagCanvas.setNodeName(code, taskName)
+ })
+ .catch((err) => {
+ console.error(err)
+ })
+ },
+ onDelete () {
+ this.dagCanvas.removeNode(this.currentTask.code)
+ },
+ show (x = 0, y = 0) {
+ this.dagCanvas.lockScroller()
+ this.visible = true
+ this.left = x + 10
+ this.top = y + 10
+ },
+ hide () {
+ this.dagCanvas.unlockScroller()
+ this.visible = false
+ }
+ }
+ }
+</script>
+
+<style lang="scss" scoped>
+@import "./contextMenu";
+</style>
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/dragZoom.js b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/draggableBox.vue
similarity index 59%
copy from dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/dragZoom.js
copy to dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/draggableBox.vue
index 009c82b..cf824da 100644
--- a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/dragZoom.js
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/draggableBox.vue
@@ -1,4 +1,3 @@
-import d3 from 'd3'
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -15,24 +14,37 @@ import d3 from 'd3'
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+<template>
+ <div
+ class="draggable-box"
+ ref="draggable"
+ draggable="true"
+ @dragstart="onDragstart"
+ @drag="onDrag"
+ @dragend="onDragend"
+ >
+ <slot></slot>
+ </div>
+</template>
-const DragZoom = function () {
- this.element = {}
- this.zoom = {}
- this.scale = 1
-}
-
-DragZoom.prototype.init = function () {
- const $canvas = $('#canvas')
- this.element = d3.select('#canvas')
- this.zoom = d3.behavior.zoom()
- .scaleExtent([0.5, 2])
- .on('zoom', () => {
- this.scale = d3.event.scale
- $canvas.css('transform', 'scale(' + this.scale + ')')
- $canvas.css('transform-origin', '0 0')
- })
- this.element.call(this.zoom).on('dblclick.zoom', null)
-}
-
-export default new DragZoom()
+<script>
+ export default {
+ name: 'draggable-box',
+ data () {
+ return {
+ tmp: null
+ }
+ },
+ methods: {
+ onDragstart (e) {
+ this.$emit('onDragstart', e)
+ },
+ onDrag (e) {
+ this.$emit('onDrag', e)
+ },
+ onDragend (e) {
+ this.$emit('onDragend', e)
+ }
+ }
+ }
+</script>
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/edgeEditModel.vue b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/edgeEditModel.vue
new file mode 100644
index 0000000..686ac4e
--- /dev/null
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/edgeEditModel.vue
@@ -0,0 +1,114 @@
+/*
+ * 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>
+ <el-drawer
+ :visible.sync="drawerVisible"
+ :wrapperClosable="false"
+ size=""
+ :with-header="false"
+ >
+ <div class="form-model-wrapper">
+ <div class="title-box">
+ <span class="name">{{ $t("Current connection settings") }}</span>
+ </div>
+ <div class="content-box">
+ <div class="form-model">
+ <!-- Node name -->
+ <div class="clearfix list">
+ <div class="text-box">
+ <span>{{ $t("Connection name") }}</span>
+ </div>
+ <div class="cont-box">
+ <label class="label-box">
+ <el-input
+ type="text"
+ size="small"
+ v-model="label"
+ :disabled="isDetails"
+ :placeholder="$t('Please enter name')"
+ maxlength="100"
+ >
+ </el-input>
+ </label>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="bottom-box">
+ <div class="submit" style="background: #fff">
+ <el-button type="text" size="small" @click="cancel()">
+ {{ $t("Cancel") }}
+ </el-button>
+ <el-button
+ type="primary"
+ size="small"
+ @click="ok()"
+ :disabled="isDetails"
+ >{{ $t("Confirm add") }}
+ </el-button>
+ </div>
+ </div>
+ </div>
+ </el-drawer>
+</template>
+<script>
+ import disabledState from '@/module/mixin/disabledState'
+ import { mapState } from 'vuex'
+ import { findComponentDownward } from '@/module/util/'
+
+ export default {
+ name: 'edge-edit-model',
+ data () {
+ return {
+ id: '',
+ label: '',
+ drawerVisible: false
+ }
+ },
+ inject: ['dagChart'],
+ mixins: [disabledState],
+ computed: {
+ ...mapState('dag', ['isDetails'])
+ },
+ methods: {
+ getDagCanvasRef () {
+ if (this.canvasRef) {
+ return this.canvasRef
+ } else {
+ const canvas = findComponentDownward(this.dagChart, 'dag-canvas')
+ this.canvasRef = canvas
+ return canvas
+ }
+ },
+ show ({ id, label }) {
+ this.id = id
+ this.label = label
+ this.drawerVisible = true
+ },
+ cancel () {
+ this.drawerVisible = false
+ this.id = ''
+ this.label = ''
+ },
+ ok () {
+ const canvas = this.getDagCanvasRef()
+ canvas.setEdgeLabel(this.id, this.label)
+ this.cancel()
+ }
+ }
+ }
+</script>
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/dragZoom.js b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/menuItem.vue
similarity index 59%
copy from dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/dragZoom.js
copy to dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/menuItem.vue
index 009c82b..127a025 100644
--- a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/dragZoom.js
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/menuItem.vue
@@ -1,4 +1,3 @@
-import d3 from 'd3'
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -15,24 +14,29 @@ import d3 from 'd3'
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+<template>
+ <div class="menu-item" :class="disabled ? 'disabled' : ''" @click="onClick">
+ <slot></slot>
+ </div>
+</template>
-const DragZoom = function () {
- this.element = {}
- this.zoom = {}
- this.scale = 1
-}
-
-DragZoom.prototype.init = function () {
- const $canvas = $('#canvas')
- this.element = d3.select('#canvas')
- this.zoom = d3.behavior.zoom()
- .scaleExtent([0.5, 2])
- .on('zoom', () => {
- this.scale = d3.event.scale
- $canvas.css('transform', 'scale(' + this.scale + ')')
- $canvas.css('transform-origin', '0 0')
- })
- this.element.call(this.zoom).on('dblclick.zoom', null)
-}
-
-export default new DragZoom()
+<script>
+ export default {
+ name: 'dag-context-menu-item',
+ props: {
+ disabled: {
+ type: Boolean,
+ default: false
+ }
+ },
+ data () {
+ return {}
+ },
+ methods: {
+ onClick (e) {
+ if (this.disabled) return
+ this.$emit('on-click', e)
+ }
+ }
+ }
+</script>
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/dragZoom.js b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/statusMenu.scss
similarity index 59%
copy from dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/dragZoom.js
copy to dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/statusMenu.scss
index 009c82b..c6a5afe 100644
--- a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/dragZoom.js
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/statusMenu.scss
@@ -1,4 +1,3 @@
-import d3 from 'd3'
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -14,25 +13,4 @@ import d3 from 'd3'
* 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.
- */
-
-const DragZoom = function () {
- this.element = {}
- this.zoom = {}
- this.scale = 1
-}
-
-DragZoom.prototype.init = function () {
- const $canvas = $('#canvas')
- this.element = d3.select('#canvas')
- this.zoom = d3.behavior.zoom()
- .scaleExtent([0.5, 2])
- .on('zoom', () => {
- this.scale = d3.event.scale
- $canvas.css('transform', 'scale(' + this.scale + ')')
- $canvas.css('transform-origin', '0 0')
- })
- this.element.call(this.zoom).on('dblclick.zoom', null)
-}
-
-export default new DragZoom()
+ */
\ No newline at end of file
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/statusMenu.vue b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/statusMenu.vue
new file mode 100644
index 0000000..2bbfec4
--- /dev/null
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/statusMenu.vue
@@ -0,0 +1,70 @@
+/*
+ * 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>
+ <div
+ class="dag-status-menu"
+ v-show="visible"
+ :style="{
+ left: `${left}px`,
+ top: `${top}px`,
+ }"
+ >
+ </div>
+</template>
+
+<script>
+ import { mapState } from 'vuex'
+
+ export default {
+ name: 'dag-status-menu',
+ inject: ['dagChart', 'dagCanvas'],
+ data () {
+ return {
+ visible: false,
+ left: 0,
+ top: 0,
+ currentTask: {
+ code: 0,
+ name: '',
+ type: ''
+ }
+ }
+ },
+ computed: {
+ ...mapState('dag', ['tasks'])
+ },
+ methods: {
+ setCurrentTask (task) {
+ this.currentTask = { ...this.currentTask, ...task }
+ },
+ show (x = 0, y = 0) {
+ this.dagCanvas.lockScroller()
+ this.visible = true
+ this.left = x
+ this.top = y
+ },
+ hide () {
+ this.dagCanvas.unlockScroller()
+ this.visible = false
+ }
+ }
+ }
+</script>
+
+<style lang="scss" scoped>
+@import "./contextMenu";
+</style>
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/taskbar.scss b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/taskbar.scss
new file mode 100644
index 0000000..3ad2416
--- /dev/null
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/taskbar.scss
@@ -0,0 +1,167 @@
+/*
+ * 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.
+ */
+.dag-taskbar {
+ width: 190px;
+ height: 100%;
+ background-color: #fff;
+ margin-right: 20px;
+
+ .taskbar-title {
+ display: flex;
+ border-bottom: dashed 1px #e5e5e5;
+ height: 42px;
+ padding: 0 20px;
+ align-items: center;
+
+ h4 {
+ color: #666;
+ font-size: 14px;
+ }
+ }
+
+ .tasks {
+ width: 100%;
+ padding: 10px 20px;
+ display: flex;
+ flex-wrap: wrap;
+ box-sizing: border-box;
+ max-height: calc(100% - 42px);
+ overflow: auto;
+
+ .draggable-box {
+ cursor: move;
+ width: 100%;
+ height: 32px;
+ margin-bottom: 10px;
+
+ .task-item {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ border: 1px dashed #e4e4e4;
+ padding: 0 10px;
+ border-radius: 4px;
+
+ em {
+ margin-right: 10px;
+ display: block;
+ width: 18px;
+ height: 18px;
+ background-size: 100% 100%;
+ &.icos-shell {
+ background-image: url("../images/task-icos/shell.png");
+ }
+ &.icos-sub_process {
+ background-image: url("../images/task-icos/sub_process.png");
+ }
+ &.icos-procedure {
+ background-image: url("../images/task-icos/procedure.png");
+ }
+ &.icos-sql {
+ background-image: url("../images/task-icos/sql.png");
+ }
+ &.icos-flink {
+ background-image: url("../images/task-icos/flink.png");
+ }
+ &.icos-mr {
+ background-image: url("../images/task-icos/mr.png");
+ }
+ &.icos-python {
+ background-image: url("../images/task-icos/python.png");
+ }
+ &.icos-dependent {
+ background-image: url("../images/task-icos/dependent.png");
+ }
+ &.icos-http {
+ background-image: url("../images/task-icos/http.png");
+ }
+ &.icos-datax {
+ background-image: url("../images/task-icos/datax.png");
+ }
+ &.icos-sqoop {
+ background-image: url("../images/task-icos/sqoop.png");
+ }
+ &.icos-conditions {
+ background-image: url("../images/task-icos/conditions.png");
+ }
+ &.icos-waterdrop {
+ background-image: url("../images/task-icos/waterdrop.png");
+ }
+ &.icos-spark {
+ background-image: url("../images/task-icos/spark.png");
+ }
+ }
+
+ span {
+ font-size: 12px;
+ }
+
+ &:hover {
+ color: #288fff;
+ border: 1px dashed #288fff;
+ background-color: rgba(40, 143, 255, 0.1);
+
+ em {
+ &.icos-shell {
+ background-image: url("../images/task-icos/shell_hover.png");
+ }
+ &.icos-sub_process {
+ background-image: url("../images/task-icos/sub_process_hover.png");
+ }
+ &.icos-procedure {
+ background-image: url("../images/task-icos/procedure_hover.png");
+ }
+ &.icos-sql {
+ background-image: url("../images/task-icos/sql_hover.png");
+ }
+ &.icos-flink {
+ background-image: url("../images/task-icos/flink_hover.png");
+ }
+ &.icos-mr {
+ background-image: url("../images/task-icos/mr_hover.png");
+ }
+ &.icos-python {
+ background-image: url("../images/task-icos/python_hover.png");
+ }
+ &.icos-dependent {
+ background-image: url("../images/task-icos/dependent_hover.png");
+ }
+ &.icos-http {
+ background-image: url("../images/task-icos/http_hover.png");
+ }
+ &.icos-datax {
+ background-image: url("../images/task-icos/datax_hover.png");
+ }
+ &.icos-sqoop {
+ background-image: url("../images/task-icos/sqoop_hover.png");
+ }
+ &.icos-conditions {
+ background-image: url("../images/task-icos/conditions_hover.png");
+ }
+ &.icos-waterdrop {
+ background-image: url("../images/task-icos/waterdrop_hover.png");
+ }
+ &.icos-spark {
+ background-image: url("../images/task-icos/spark_hover.png");
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/taskbar.vue b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/taskbar.vue
new file mode 100644
index 0000000..0ffc40c
--- /dev/null
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/taskbar.vue
@@ -0,0 +1,64 @@
+/*
+ * 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>
+ <div class="dag-taskbar">
+ <div class="taskbar-title">
+ <h4>{{$t('Toolbar')}}</h4>
+ </div>
+ <div class="tasks">
+ <template v-for="taskType in tasksTypeList">
+ <draggable-box
+ :key="taskType.name"
+ @onDragstart="(e) => $emit('on-drag-start', e, taskType)"
+ >
+ <div class="task-item">
+ <em :class="`icos-${taskType.name.toLocaleLowerCase()}`"></em>
+ <span>{{ taskType.name }}</span>
+ </div>
+ </draggable-box>
+ </template>
+ </div>
+ </div>
+</template>
+
+<script>
+ import draggableBox from './draggableBox.vue'
+ import { tasksType } from '../config.js'
+
+ export default {
+ name: 'dag-taskbar',
+ components: {
+ draggableBox
+ },
+ data () {
+ const tasksTypeList = Object.keys(tasksType).map((type) => {
+ return {
+ name: type,
+ desc: tasksType[type].desc
+ }
+ })
+
+ return {
+ tasksTypeList
+ }
+ }
+ }
+</script>
+
+<style lang="scss" scoped>
+@import "./taskbar";
+</style>
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/toolbar.scss b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/toolbar.scss
new file mode 100644
index 0000000..03578f3
--- /dev/null
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/toolbar.scss
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+.dag-toolbar {
+ width: 100%;
+ height: 50px;
+ background-color: #fff;
+ padding: 0 20px;
+ display: flex;
+ align-items: center;
+ box-sizing: border-box;
+
+ h3 {
+ font-size: 14px;
+ font-weight: bold;
+ margin: 0 10px 0 0;
+ }
+
+ .transparent {
+ width: 1px;
+ height: 1px;
+ opacity: 0;
+ }
+
+ .toolbar-operation {
+ font-size: 18px;
+ cursor: pointer;
+ margin-left: 20px;
+ color: #666666;
+ &:hover {
+ color: #288fff;
+ }
+ &.last{
+ margin-right: 10px;
+ }
+ }
+
+ .toolbar-btn {
+ font-size: 16px;
+ }
+
+ .toolbar-left {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ }
+
+ .toolbar-right {
+ justify-self: flex-end;
+ display: flex;
+ align-items: center;
+ }
+
+ .toolbar-el-btn{
+ margin-right: 0;
+ margin-left: 10px;
+ }
+
+ .custom-ico{
+ display: block;
+ width: 18px;
+ height: 18px;
+ background-size: 100% 100%;
+
+ &.view-variables{
+ background-image: url('../images/view-variables.png');
+ &:hover{
+ background-image: url('../images/view-variables_hover.png');
+ }
+ }
+
+ &.startup-parameters{
+ background-image: url('../images/startup-params.png');
+ &:hover{
+ background-image: url('../images/startup-params_hover.png');
+ }
+ }
+
+ &.full-screen-open{
+ background-image: url('../images/full-screen-open.png');
+ &:hover{
+ background-image: url('../images/full-screen-open_hover.png');
+ }
+ }
+
+ &.full-screen-close{
+ background-image: url('../images/full-screen-close.png');
+ &:hover{
+ background-image: url('../images/full-screen-close_hover.png');
+ }
+ }
+
+ &.graph-format{
+ background-image: url('../images/graph-format.png');
+ &:hover{
+ background-image: url('../images/graph-format_hover.png');
+ }
+ }
+ }
+}
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/toolbar.vue b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/toolbar.vue
new file mode 100644
index 0000000..1a7e5ab
--- /dev/null
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/toolbar.vue
@@ -0,0 +1,199 @@
+/*
+ * 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>
+ <div class="dag-toolbar">
+ <h3>{{ dagChart.name || $t("Create process") }}</h3>
+ <el-tooltip
+ v-if="dagChart.name"
+ class="toolbar-operation"
+ :content="$t('Copy name')"
+ placement="bottom"
+ >
+ <i class="el-icon-copy-document" @click="copyName"></i>
+ </el-tooltip>
+ <textarea ref="textarea" cols="30" rows="10" class="transparent"></textarea>
+ <div class="toolbar-left">
+ <el-tooltip
+ :content="$t('View variables')"
+ placement="bottom"
+ class="toolbar-operation"
+ >
+ <i
+ class="custom-ico view-variables"
+ v-if="$route.name === 'projects-instance-details'"
+ @click="toggleVariableView"
+ ></i>
+ </el-tooltip>
+ <el-tooltip
+ :content="$t('Startup parameter')"
+ placement="bottom"
+ class="toolbar-operation"
+ >
+ <i
+ class="custom-ico startup-parameters"
+ v-if="$route.name === 'projects-instance-details'"
+ @click="toggleParamView"
+ ></i>
+ </el-tooltip>
+ </div>
+ <div class="toolbar-right">
+ <el-tooltip
+ class="toolbar-operation"
+ :content="$t('Delete selected lines or nodes')"
+ placement="bottom"
+ >
+ <i class="el-icon-delete" @click="removeCells"></i>
+ </el-tooltip>
+ <el-tooltip
+ class="toolbar-operation"
+ :content="$t('Download')"
+ placement="bottom"
+ >
+ <i class="el-icon-download" @click="downloadPNG"></i>
+ </el-tooltip>
+ <el-tooltip
+ class="toolbar-operation"
+ :content="$t('Full Screen')"
+ placement="bottom"
+ >
+ <i
+ :class="[
+ 'custom-ico',
+ dagChart.fullScreen
+ ? 'full-screen-close'
+ : 'full-screen-open',
+ ]"
+ @click="toggleFullScreen"
+ ></i>
+ </el-tooltip>
+ <el-tooltip
+ class="toolbar-operation last"
+ :content="$t('Format DAG')"
+ placement="bottom"
+ >
+ <i class="custom-ico graph-format" @click="chartFormat"></i>
+ </el-tooltip>
+ <el-button
+ class="toolbar-el-btn"
+ type="primary"
+ size="mini"
+ @click="saveProcess"
+ >{{ $t("Save") }}</el-button
+ >
+ <el-button
+ class="toolbar-el-btn"
+ v-if="$route.query.subProcessCodes"
+ type="primary"
+ size="mini"
+ icon="el-icon-back"
+ @click="dagChart.returnToPrevProcess"
+ >
+ {{ $t("Return_1") }}
+ </el-button>
+ <el-button
+ class="toolbar-el-btn"
+ type="primary"
+ icon="el-icon-switch-button"
+ size="mini"
+ v-if="type === 'instance' || 'definition'"
+ @click="returnToListPage"
+ >
+ {{ $t("Close") }}
+ </el-button>
+ </div>
+ </div>
+</template>
+
+<script>
+ import { findComponentDownward } from '@/module/util/'
+
+ export default {
+ name: 'dag-toolbar',
+ inject: ['dagChart'],
+ data () {
+ return {
+ canvasRef: null
+ }
+ },
+ methods: {
+ getDagCanvasRef () {
+ if (this.canvasRef) {
+ return this.canvasRef
+ } else {
+ const canvas = findComponentDownward(this.dagChart, 'dag-canvas')
+ this.canvasRef = canvas
+ return canvas
+ }
+ },
+ toggleVariableView () {
+ findComponentDownward(this.$root, 'assist-dag-index')._toggleView()
+ },
+ toggleParamView () {
+ findComponentDownward(
+ this.$root,
+ 'starting-params-dag-index'
+ )._toggleParam()
+ },
+ toggleFullScreen () {
+ this.dagChart.toggleFullScreen()
+ },
+ saveProcess () {
+ const canvas = this.getDagCanvasRef()
+ const nodes = canvas.getNodes()
+ if (!nodes.length) {
+ this.$message.error(this.$t('Failed to create node to save'))
+ return
+ }
+ this.dagChart.toggleSaveDialog(true)
+ },
+ downloadPNG () {
+ const canvas = this.getDagCanvasRef()
+ canvas.downloadPNG(this.processName)
+ },
+ removeCells () {
+ const canvas = this.getDagCanvasRef()
+ const selections = canvas.getSelections()
+ canvas.removeCells(selections)
+ },
+ copyName () {
+ const textarea = this.$refs.textarea
+ textarea.value = this.dagChart.name
+ textarea.select()
+ document.execCommand('copy')
+ this.$message(this.$t('Copy success'))
+ },
+ chartFormat () {
+ const canvas = this.getDagCanvasRef()
+ canvas.format()
+ },
+ // TODO
+ refreshTaskState () {},
+ returnToListPage () {
+ let $name = this.$route.name
+ if ($name && $name.indexOf('definition') !== -1) {
+ this.$router.push({ name: 'projects-definition-list' })
+ } else {
+ this.$router.push({ name: 'projects-instance-list' })
+ }
+ }
+ }
+ }
+</script>
+
+<style lang="scss" scoped>
+@import "./toolbar";
+</style>
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/x6-helper.js b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/x6-helper.js
new file mode 100644
index 0000000..ec53090
--- /dev/null
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/x6-helper.js
@@ -0,0 +1,323 @@
+/*
+ * 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.
+ */
+export const X6_NODE_NAME = 'dag-task'
+export const X6_EDGE_NAME = 'dag-edge'
+export const X6_PORT_OUT_NAME = 'dag-port-out'
+export const X6_PORT_IN_NAME = 'dag-port-in'
+
+const EDGE = '#999999'
+const BG_BLUE = 'rgba(40, 143, 255, 0.1)'
+const BG_WHITE = '#FFFFFF'
+const NODE_BORDER = '#e4e4e4'
+const TITLE = '#333'
+const STROKE_BLUE = '#288FFF'
+
+export const PORT_PROPS = {
+ groups: {
+ [X6_PORT_OUT_NAME]: {
+ position: {
+ name: 'absolute',
+ args: {
+ x: 200,
+ y: 24
+ }
+ },
+ markup: [
+ {
+ tagName: 'g',
+ selector: 'body',
+ children: [
+ {
+ tagName: 'circle',
+ selector: 'circle-outer'
+ },
+ {
+ tagName: 'text',
+ selector: 'plus-text'
+ },
+ {
+ tagName: 'circle',
+ selector: 'circle-inner'
+ }
+ ]
+ }
+ ],
+ attrs: {
+ body: {
+ magnet: true
+ },
+ 'plus-text': {
+ fontSize: 12,
+ fill: EDGE,
+ text: '+',
+ textAnchor: 'middle',
+ x: 0,
+ y: 3
+ },
+ 'circle-outer': {
+ stroke: EDGE,
+ strokeWidth: 1,
+ r: 6,
+ fill: BG_WHITE
+ },
+ 'circle-inner': {
+ r: 4,
+ fill: 'transparent'
+ }
+ }
+ },
+ [X6_PORT_IN_NAME]: {
+ position: {
+ name: 'absolute',
+ args: {
+ x: 0,
+ y: 24
+ }
+ },
+ markup: [
+ {
+ tagName: 'g',
+ selector: 'body',
+ className: 'in-port-body',
+ children: [{
+ tagName: 'circle',
+ selector: 'circle',
+ className: 'circle'
+ }]
+ }
+ ],
+ attrs: {
+ body: {
+ magnet: true
+ },
+ circle: {
+ r: 4,
+ strokeWidth: 0,
+ fill: 'transparent'
+ }
+ }
+ }
+ }
+}
+
+export const PORT_HIGHLIGHT_PROPS = {
+ [X6_PORT_OUT_NAME]: {
+ attrs: {
+ 'circle-outer': {
+ stroke: STROKE_BLUE,
+ fill: BG_BLUE
+ },
+ 'plus-text': {
+ fill: STROKE_BLUE
+ },
+ 'circle-inner': {
+ fill: STROKE_BLUE
+ }
+ }
+ },
+ [X6_PORT_IN_NAME]: {}
+}
+
+export const NODE_PROPS = {
+ width: 220,
+ height: 48,
+ markup: [
+ {
+ tagName: 'rect',
+ selector: 'body'
+ },
+ {
+ tagName: 'image',
+ selector: 'image'
+ },
+ {
+ tagName: 'text',
+ selector: 'title'
+ }
+ // {
+ // tagName: 'foreignObject',
+ // selector: 'fo',
+ // children: [
+ // {
+ // tagName: 'body',
+ // selector: 'fo-body',
+ // ns: 'http://www.w3.org/1999/xhtml',
+ // children: [{
+ // tagName: 'i',
+ // selector: 'state',
+ // className: 'state-icon el-icon-circle-check'
+ // }]
+ // }
+ // ]
+ // }
+ ],
+ attrs: {
+ body: {
+ refWidth: '100%',
+ refHeight: '100%',
+ rx: 6,
+ ry: 6,
+ pointerEvents: 'visiblePainted',
+ fill: BG_WHITE,
+ stroke: NODE_BORDER,
+ strokeWidth: 1
+ },
+ image: {
+ width: 30,
+ height: 30,
+ refX: 12,
+ refY: 9
+ },
+ title: {
+ refX: 45,
+ refY: 18,
+ fontFamily: 'Microsoft Yahei',
+ fontSize: 12,
+ fontWeight: 'bold',
+ fill: TITLE,
+ strokeWidth: 0
+ },
+ fo: {
+ refX: '46%',
+ refY: -25,
+ width: 18,
+ height: 18
+ },
+ state: {
+ style: {
+ display: 'block',
+ width: '100%',
+ height: '100%',
+ fontSize: '18px'
+ }
+ }
+ },
+ ports: {
+ ...PORT_PROPS,
+ items: [
+ {
+ id: X6_PORT_OUT_NAME,
+ group: X6_PORT_OUT_NAME
+ },
+ {
+ id: X6_PORT_IN_NAME,
+ group: X6_PORT_IN_NAME
+ }
+ ]
+ }
+}
+
+export const NODE_HIGHLIGHT_PROPS = {
+ attrs: {
+ body: {
+ fill: BG_BLUE,
+ stroke: STROKE_BLUE,
+ strokeDasharray: '5,2'
+ },
+ title: {
+ fill: STROKE_BLUE
+ }
+ }
+}
+
+export const EDGE_PROPS = {
+ attrs: {
+ line: {
+ stroke: EDGE,
+ strokeWidth: 0.8,
+ targetMarker: {
+ tagName: 'path',
+ fill: EDGE,
+ strokeWidth: 0,
+ d: 'M 6 -3 0 0 6 3 Z'
+ }
+ }
+ },
+ connector: {
+ name: 'rounded'
+ },
+ router: {
+ name: 'er',
+ args: {
+ offset: 20,
+ min: 20,
+ direction: 'L'
+ }
+ },
+ defaultLabel: {
+ markup: [
+ {
+ tagName: 'rect',
+ selector: 'body'
+ },
+ {
+ tagName: 'text',
+ selector: 'label'
+ }
+ ],
+ attrs: {
+ label: {
+ fill: EDGE,
+ fontSize: 14,
+ textAnchor: 'middle',
+ textVerticalAnchor: 'middle',
+ pointerEvents: 'none'
+ },
+ body: {
+ ref: 'label',
+ fill: BG_WHITE,
+ stroke: EDGE,
+ strokeWidth: 1,
+ rx: 4,
+ ry: 4,
+ refWidth: '140%',
+ refHeight: '140%',
+ refX: '-20%',
+ refY: '-20%'
+ }
+ },
+ position: {
+ distance: 0.5,
+ options: {
+ absoluteDistance: true,
+ reverseDistance: true
+ }
+ }
+ }
+}
+
+export const EDGE_HIGHLIGHT_PROPS = {
+ attrs: {
+ line: {
+ stroke: STROKE_BLUE,
+ targetMarker: {
+ fill: STROKE_BLUE
+ }
+ }
+ },
+ defaultLabel: {
+ attrs: {
+ label: {
+ fill: STROKE_BLUE
+ },
+ body: {
+ fill: BG_WHITE,
+ stroke: STROKE_BLUE
+ }
+ }
+ }
+}
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/dragZoom.js b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/x6-style.scss
similarity index 60%
rename from dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/dragZoom.js
rename to dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/x6-style.scss
index 009c82b..b86b51a 100644
--- a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/dragZoom.js
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/canvas/x6-style.scss
@@ -1,4 +1,3 @@
-import d3 from 'd3'
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -15,24 +14,17 @@ import d3 from 'd3'
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+$STROKE_BLUE: #288FFF;
+$BG_WHITE: #FFFFFF;
-const DragZoom = function () {
- this.element = {}
- this.zoom = {}
- this.scale = 1
+.x6-node[data-shape="dag-task"]{
+ .in-port-body{
+ &.adsorbed,&.available{
+ .circle {
+ stroke: $STROKE_BLUE;
+ stroke-width: 4;
+ fill: $BG_WHITE;
+ }
+ }
+ }
}
-
-DragZoom.prototype.init = function () {
- const $canvas = $('#canvas')
- this.element = d3.select('#canvas')
- this.zoom = d3.behavior.zoom()
- .scaleExtent([0.5, 2])
- .on('zoom', () => {
- this.scale = d3.event.scale
- $canvas.css('transform', 'scale(' + this.scale + ')')
- $canvas.css('transform-origin', '0 0')
- })
- this.element.call(this.zoom).on('dblclick.zoom', null)
-}
-
-export default new DragZoom()
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
deleted file mode 100644
index 66509a6..0000000
--- a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/dag.js
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import Vue from 'vue'
-import _ from 'lodash'
-import i18n from '@/module/i18n'
-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
- */
-const Dag = function () {
- this.dag = {}
- this.instance = {}
-}
-
-/**
- * init
- * @dag dag vue instance
- */
-Dag.prototype.init = function ({ dag, instance }) {
- this.dag = dag
- this.instance = instance
-}
-
-/**
- * set init config
- */
-Dag.prototype.setConfig = function (o) {
- JSP.setConfig(o)
-}
-
-/**
- * create dag
- */
-Dag.prototype.create = function () {
- const self = this
- const plumbIns = jsPlumb.getInstance()
- plumbIns.reset()
- plumbIns.ready(() => {
- JSP.init({
- dag: this.dag,
- instance: this.instance,
- options: {
- onRemoveNodes ($id) {
- self.dag.removeEventModelById($id)
- }
- }
- })
-
- // init event
- JSP.handleEvent()
-
- // init draggable
- JSP.draggable()
- })
-}
-
-/**
- * Action event on the right side of the toolbar
- */
-Dag.prototype.toolbarEvent = function ({ item, code, is }) {
- const self = this
- switch (code) {
- case 'pointer':
- JSP.handleEventPointer(is)
- break
- case 'line':
- JSP.handleEventLine(is)
- break
- case 'remove':
- JSP.handleEventRemove()
- break
- case 'screen':
- JSP.handleEventScreen({ item, is })
- break
- case 'download':
- Vue.prototype.$confirm(`${i18n.$t('Please confirm whether the workflow has been saved before downloading')}`, `${i18n.$t('Download')}`, {
- confirmButtonText: `${i18n.$t('Confirm')}`,
- cancelButtonText: `${i18n.$t('Cancel')}`,
- type: 'warning'
- }).then(() => {
- DownChart.download({
- dagThis: self.dag
- })
- }).catch(() => {
- })
- break
- }
-}
-
-/**
- * Echo data display
- */
-Dag.prototype.backfill = function (arg) {
- const that = this
- if (arg) {
- const marginX = 100
- const g = new dagre.graphlib.Graph()
- g.setGraph({})
- g.setDefaultEdgeLabel(function () { return {} })
-
- 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 })
- }
-
- for (const i in store.state.dag.connects) {
- const connect = store.state.dag.connects[i]
- g.setEdge(connect.endPointSourceId, connect.endPointTargetId)
- }
- dagre.layout(g)
-
- const dataObject = {}
- g.nodes().forEach(function (v) {
- const node = g.node(v)
- const location = store.state.dag.locations[node.label]
- const obj = {}
- obj.name = location.name
- obj.x = node.x + marginX
- obj.y = node.y
- obj.targetarr = location.targetarr
- dataObject[node.label] = obj
- })
- jsPlumb.ready(() => {
- JSP.init({
- dag: this.dag,
- instance: this.instance,
- options: {
- onRemoveNodes ($id) {
- that.dag.removeEventModelById($id)
- }
- }
- })
- // Backfill
- JSP.jspBackfill({
- // connects
- connects: _.cloneDeep(store.state.dag.connects),
- // Node location information
- locations: _.cloneDeep(dataObject),
- // Node data
- largeJson: _.cloneDeep(store.state.dag.tasks)
- })
- })
- } else {
- const plumbIns = jsPlumb.getInstance()
- plumbIns.reset()
- plumbIns.ready(() => {
- JSP.init({
- dag: this.dag,
- instance: this.instance,
- options: {
- onRemoveNodes ($id) {
- that.dag.removeEventModelById($id)
- }
- }
- })
- // Backfill
- JSP.jspBackfill({
- // connects
- connects: _.cloneDeep(store.state.dag.connects),
- // Node location information
- locations: _.cloneDeep(store.state.dag.locations),
- // Node data
- largeJson: _.cloneDeep(store.state.dag.tasks)
- })
- })
- }
-}
-
-/**
- * Get dag storage format data
- */
-Dag.prototype.saveStore = function () {
- return JSP.saveStore()
-}
-
-export default new Dag()
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
old mode 100755
new mode 100644
index 08f2fec..6ceccb0
--- a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/dag.scss
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/dag.scss
@@ -14,558 +14,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-.dag-model {
- background: url("../img/dag_bg.png");
- height: calc(100vh - 100px);
- ::selection {
- background:transparent;
- }
- ::-moz-selection {
- background:transparent;
- }
- ::-webkit-selection {
- background:transparent;
- }
- .jsplumb-connector {
- z-index: 1;
- }
- .endpoint-tasks {
- margin-top:22px;
- }
- .draggable {
- > span {
- text-align: center;
- display: block;
- margin-top: -4px;
- padding: 0 4px;
- width: 200px;
- margin-left: -81px;
- position: absolute;
- left: 0;
- bottom: -12px;
- }
- .fa {
- display: inline-block;
- position: absolute;
- right: -8px;
- top: -8px;
- z-index: 2;
- cursor: pointer;
- }
- .icos {
- display: inline-block;
- cursor: pointer;
- }
- &.active-tasks {
- span {
- color: #0296DF;
- }
- }
- }
- .icos {
- width: 32px;
- height: 32px;
- margin: 2px;
- border-radius: 3px;
- position: relative;
- z-index: 9;
- }
- .icos-SHELL {
- background: url("../img/toolbar_SHELL.png") no-repeat 50% 50%;
- }
- .icos-WATERDROP {
- background: url("../img/toolbar_WATERDROP.png") no-repeat 50% 50%;
- }
- .icos-SUB_PROCESS {
- background: url("../img/toolbar_SUB_PROCESS.png") no-repeat 50% 50%;
- }
- .icos-PROCEDURE {
- background: url("../img/toolbar_PROCEDURE.png") no-repeat 50% 50%;
- }
- .icos-SQL {
- background: url("../img/toolbar_SQL.png") no-repeat 50% 50%;
- }
- .icos-SPARK {
- background: url("../img/toolbar_SPARK.png") no-repeat 50% 50%;
- }
- .icos-FLINK {
- background: url("../img/toolbar_FLINK.png") no-repeat 50% 50%;
- }
- .icos-MR {
- background: url("../img/toolbar_MR.png") no-repeat 50% 50%;
- }
- .icos-PYTHON {
- background: url("../img/toolbar_PYTHON.png") no-repeat 50% 50%;
- }
- .icos-DEPENDENT {
- background: url("../img/toolbar_DEPENDENT.png") no-repeat 50% 50%;
- }
- .icos-HTTP {
- background: url("../img/toolbar_HTTP.png") no-repeat 50% 50%;
- }
- .icos-DATAX {
- background: url("../img/toolbar_DATAX.png") no-repeat 50% 50%;
- }
- .icos-SQOOP {
- background: url("../img/toolbar_SQOOP.png") no-repeat 50% 50%;
- }
- .icos-CONDITIONS {
- background: url("../img/toolbar_CONDITIONS.png") no-repeat 50% 50%;
- }
- .toolbar {
- width: 60px;
- height: 100%;
- background: #F2F3F7;
- float: left;
- border-radius: 0 0 0 3px;
- .title {
- height: 40px;
- line-height: 40px;
- background: #40434C;
- text-align: center;
- border-radius: 3px 0 0 0;
- span {
- font-size: 14px;
- color: #fff;
- font-weight: bold;
- }
- }
- .toolbar-btn {
- overflow: hidden;
- padding: 8px 11px 0 11px;
- .bar-box {
- width: 36px;
- height: 36px;
- float: left;
- margin-bottom: 3px;
- border-radius: 3px;
- .disabled {
- .icos {
- opacity: .6;
- -webkit-filter: grayscale(100%);
- -moz-filter: grayscale(100%);
- -ms-filter: grayscale(100%);
- -o-filter: grayscale(100%);
- filter: grayscale(100%);
- filter: gray;
- }
- }
- &:nth-child(odd) {
- margin-right: 6px;
- }
- &.active {
- background: #e1e2e3;
- }
- }
- }
- }
- .dag-contect {
- float: left;
- width: calc(100% - 60px);
- height: 100%;
- .dag-toolbar {
- height: 40px;
- background: #F2F3F7;
- position: relative;
- border-radius: 0 3px 0 0;
- .ans-btn-text {
- color: #337ab7;
- .ans-icon {
- font-size: 16px;
- }
- }
- .assist-btn {
- position: absolute;
- left: 10px;
- top: 7px;
- >.name {
- padding-left: 6px;
- vertical-align: middle;
- }
- >.copy-name {
- cursor: pointer;
- padding-left: 4px;
- position: relative;
- top: -2px;
- &:hover {
- i {
- color: #47c3ff;
- }
- }
- i {
- color: #333;
- font-size: 18px;
- vertical-align: middle;
- }
- }
- }
- .save-btn {
- position: absolute;
- right: 8px;
- top: 6px;
- .operation {
- overflow: hidden;
- display: inline-block;
- a {
- float: left;
- width: 28px;
- height: 28px;
- text-align: center;
- line-height: 28px;
- margin-left: 6px;
- border-radius: 3px;
- vertical-align: middle;
- i {
- color: #333;
- }
- &.active {
- // background: #e1e2e3;
- i {
- color: #2d8cf0;
- }
- }
- &.disable {
- i {
- color: #bbb;
- }
- }
- }
- }
- }
- }
- .dag-container {
- height: calc(100% - 40px);
- overflow-x: auto;
- &::-webkit-scrollbar{
- width: 9px;
- }
- }
- }
- .tools-model {
- height: 60px;
- background: #F4F5F4;
- border-radius: 3px 3px 0px 0px;
- }
-}
-#screen {
- margin-right: 5px;
-}
-.v-modal-custom-log {
- z-index: 101;
-}
-
-svg path:hover {
- cursor: pointer;
-}
-
-#chart-container .ui-selecting {
- span {
- color: #0296DF;
- }
-}
-#chart-container .ui-selected {
- span {
- color: #0296DF;
- }
-}
-
-.contextmenu {
- position: fixed;
- width: 90px;
- background: #fff;
- border-radius: 3px;
- box-shadow: 0 2px 4px 1px rgba(0, 0, 0, 0.1);
- padding: 4px 4px;
- visibility:hidden;
- z-index: 10000;
- a {
- height: 30px;
- line-height: 28px;
- display: block;
- i {
- font-size: 16px;
- vertical-align: middle;
- margin-left: 10px;
- }
- span {
- vertical-align: middle;
- font-size: 12px;
- color: #666;
- padding-left: 2px;
- }
- &:hover {
- background: #f6faff;
- }
- &#startRunning {
- i {
- color: #35cd75;
- }
- }
- &#editNodes {
- i {
- color: #0097e0;
- }
- }
- &#removeNodes {
- i {
- color: #f04d4e;
- }
- }
- &#copyNodes {
- i {
- color: #FABC05;
- }
- }
- &.disbled {
- i,span {
- color: #aaa !important;
- }
- }
- }
-}
-
-.jtk-demo {
- //min-width: calc(100% - 220px);
- width: 8000px;
- height: 5000px;
- svg:not(:root){
- z-index: 11;
- }
-}
-
-.jtk-demo-canvas {
- position: relative;
- height: 100%;
- display: flex;
-}
-
-.jtk-bootstrap {
- min-height: 100vh;
- display: flex;
- flex-direction: column;
-}
-
-.jtk-bootstrap .jtk-page-container {
- display: flex;
- width: 100vw;
- justify-content: center;
- flex: 1;
-}
-
-.jtk-bootstrap .jtk-container {
- width: 60%;
- max-width: 800px;
-}
-
-.jtk-bootstrap-wide .jtk-container {
- width: 80%;
- max-width: 1187px;
-}
-
-.jtk-demo-main {
- position: relative;
- margin-top: 98px;
-}
-
-.jtk-demo-main .description {
- font-size: 13px;
- margin-top: 25px;
- padding: 13px;
- margin-bottom: 22px;
- background-color: #f4f5ef;
-}
-
-.jtk-demo-main .description li {
- list-style-type: disc !important;
-}
-
-.canvas-wide {
- padding-top: 10px;
- margin-left: 0;
- -ms-transition: all .1s ease-out;
- -moz-transition: all .1s ease-out;
- -webkit-transition: all .1s ease-out;
- -o-transition: all .1s ease-out;
-}
-
-.jtk-demo-dataset {
- text-align: left;
- max-height: 600px;
- overflow: auto;
-}
-
-.demo-title {
- float: left;
- font-size: 18px;
-}
-
-.controls {
- top: 25px;
- color: #FFF;
- margin-right: 10px;
- position: absolute;
- left: 25px;
- z-index: 1;
-}
-
-.controls i {
- background-color: #3E7E9C;
- border-radius: 4px;
- cursor: pointer;
- margin-right: 0;
- padding: 4px;
-}
-.w {
- position: absolute;
- z-index: 4;
- font-size: 11px;
- -webkit-transition: background-color 0.25s ease-in;
- -moz-transition: background-color 0.25s ease-in;
- transition: background-color 0.25s ease-in;
- border: 7px solid transparent;
- border-bottom: 30px solid transparent;
- .icos {
- width: 50px;
- height: 50px;
- box-shadow: 2px 2px 19px #e0e0e0;
- -o-box-shadow: 2px 2px 19px #e0e0e0;
- -webkit-box-shadow: 2px 2px 19px #e0e0e0;
- -moz-box-shadow: 2px 2px 19px #e0e0e0;
- -moz-border-radius: 8px;
- border-radius: 8px;
- opacity: 0.8;
- cursor: move;
- background-color: #fff;
- }
- .name-p {
- position: absolute;
- left: 50%;
- top: 58px;
- width: 200px;
- text-align: center;
- margin-left: -100px;
- word-break:break-all;
- }
- .ban-p {
- position: absolute;
- left: -4px;
- top: 36px;
- z-index: 21;
- i {
- font-size: 18px;
- color: #ff0000;
- cursor: pointer;
- }
- }
- .state-p {
- width: 20px;
- height: 20px;
- position: absolute;
- top: -20px;
- left: 18px;
- text-align: center;
- cursor: pointer;
- b {
- font-weight: normal;
- }
- }
-}
-
-.aLabel {
- -webkit-transition: background-color 0.25s ease-in;
- -moz-transition: background-color 0.25s ease-in;
- transition: background-color 0.25s ease-in;
- background-color: white;
- opacity: 0.8;
- padding: 0.3em;
- border-radius: 0.5em;
- border: 1px solid #346789;
- cursor: pointer;
-}
-
-.aLabel.jtk-hover,
-.jtk-source-hover,
-.jtk-target-hover {
- .icos {
- background-color: #333;
- color: #333;
- -ms-transition: all 0.6s ease-out;
- -moz-transition: all 0.6s ease-out;
- -webkit-transition: all 0.6s ease-out;
- -o-transition: all 0.6s ease-out;
- }
-}
-
-.jtk-tasks-active {
- .icos {
- background-color: #2db7f5;
- color: #0097e0;
- -ms-transition: all 0.6s ease-out;
- -moz-transition: all 0.6s ease-out;
- -webkit-transition: all 0.6s ease-out;
- -o-transition: all 0.6s ease-out;
- }
-}
-
-
-.jtk-ep {
- .ep {
- display: block;
- }
-}
-
-.ep {
- position: absolute;
- top: -4%;
- right: -1px;
- width: 1em;
- height: 1em;
- z-index: 12;
- background-color: orange;
- cursor: pointer;
- box-shadow: 0 0 2px black;
- -webkit-transition: -webkit-box-shadow 0.25s ease-in;
- -moz-transition: -moz-box-shadow 0.25s ease-in;
- transition: box-shadow 0.25s ease-in;
- border-radius:100%;
- display: none;
-}
-
-.ep:hover {
- box-shadow: 0 0 6px black;
-}
-
-.statemachine-demo .jtk-endpoint {
- z-index: 3;
-}
-
-#canvas {
- .dot-style {
- opacity: 0;
- }
-}
-
-.form-mirror {
+
+.dag-chart {
width: 100%;
- position: relative;
- z-index: 0;
- .CodeMirror {
- height:auto;
- min-height: 72px;
- }
+ height: calc(100vh - 100px);
+ padding: 10px;
+ background: #f2f3f7;
- .CodeMirror-scroll {
- height:auto;
- min-height: 72px;
- overflow-y: hidden;
- overflow-x: auto;
+ &.full-screen {
+ position: fixed;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+ z-index: 9999;
}
}
-
-.ans-modal-box.ans-drawer.ans-drawer-right.dagMask.mask {
- width: 628px;
- left: auto;
-}
-
-
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
old mode 100755
new mode 100644
index b927a29..e7169b1
--- a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/dag.vue
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/dag.vue
@@ -15,890 +15,477 @@
* limitations under the License.
*/
<template>
- <div class="clearfix dag-model" >
- <div class="toolbar">
- <div class="title"><span>{{$t('Toolbar')}}</span></div>
- <div class="toolbar-btn">
- <div class="bar-box roundedRect jtk-draggable jtk-droppable jtk-endpoint-anchor jtk-connected"
- :class="v === dagBarId ? 'active' : ''"
- :id="v"
- :key="v"
- v-for="(item,v) in tasksTypeList"
- @mousedown="_getDagId(v)">
- <div data-toggle="tooltip" :title="item.desc">
- <div class="icos" :class="'icos-' + v" ></div>
- </div>
- </div>
- </div>
- </div>
- <div class="dag-contect">
- <div class="dag-toolbar">
- <div class="assist-btn">
- <el-tooltip :content="$t('View variables')" placement="top" :enterable="false">
- <span>
- <el-button
- style="vertical-align: middle;"
- type="primary"
- size="mini"
- :disabled="$route.name !== 'projects-instance-details'"
- @click="_toggleView"
- icon="el-icon-c-scale-to-original">
- </el-button>
- </span>
- </el-tooltip>
- <el-tooltip :content="$t('Startup parameter')" placement="top" :enterable="false">
- <span>
- <el-button
- style="vertical-align: middle;"
- type="primary"
- size="mini"
- :disabled="$route.name !== 'projects-instance-details'"
- @click="_toggleParam"
- icon="el-icon-arrow-right">
- </el-button>
- </span>
- </el-tooltip>
- <span class="name">{{name}}</span>
-
- <span v-if="name" class="copy-name" @click="_copyName" :data-clipboard-text="name"><em class="el-icon-copy-document" data-container="body" data-toggle="tooltip" :title="$t('Copy name')" ></em></span>
- </div>
- <div class="save-btn">
- <div class="operation" style="vertical-align: middle;">
- <a href="javascript:"
- v-for="(item,$index) in toolOperList"
- :class="_operationClass(item)"
- :id="item.code"
- :key="$index"
- @click="_ckOperation(item,$event)">
- <el-tooltip :content="item.desc" placement="top" :enterable="false">
- <span><el-button type="text" class="operBtn" :icon="item.icon"></el-button></span>
- </el-tooltip>
- </a>
- </div>
- <el-tooltip :content="$t('Format DAG')" placement="top" :enterable="false">
- <span>
- <el-button
- type="primary"
- icon="el-icon-caret-right"
- size="mini"
- v-if="(type === 'instance' || 'definition') && urlParam.id !=undefined"
- style="vertical-align: middle;"
- @click="dagAutomaticLayout">
- </el-button>
- </span>
- </el-tooltip>
- <el-tooltip :content="$t('Refresh DAG status')" placement="top" :enterable="false">
- <span>
- <el-button
- style="vertical-align: middle;"
- icon="el-icon-refresh"
- type="primary"
- :loading="isRefresh"
- v-if="type === 'instance'"
- @click="!isRefresh && _refresh()"
- size="mini" >
- </el-button>
- </span>
- </el-tooltip>
- <el-button
- v-if="isRtTasks"
- style="vertical-align: middle;"
- type="primary"
- size="mini"
- icon="el-icon-back"
- @click="_rtNodesDag" >
- {{$t('Return_1')}}
- </el-button>
- <span>
- <el-button
- type="primary"
- icon="el-icon-switch-button"
- size="mini"
- v-if="(type === 'instance' || 'definition') "
- style="vertical-align: middle;"
- @click="_closeDAG">
- {{$t('Close')}}
- </el-button>
- </span>
- <el-button
- style="vertical-align: middle;"
- type="primary"
- size="mini"
- :loading="spinnerLoading"
- @click="_saveChart"
- icon="el-icon-document-checked"
- >
- {{spinnerLoading ? 'Loading...' : $t('Save')}}
- </el-button>
- <span>
- <el-button
- style="vertical-align: middle;"
- type="primary"
- size="mini"
- :loading="spinnerLoading"
- @click="_version"
- :disabled="$route.params.id == null"
- icon="el-icon-info">
- {{spinnerLoading ? 'Loading...' : $t('Version Info')}}
- </el-button>
- </span>
- </div>
- </div>
- <div class="scrollbar dag-container">
- <div class="jtk-demo" id="jtk-demo">
- <div class="jtk-demo-canvas canvas-wide statemachine-demo jtk-surface jtk-surface-nopan jtk-draggable" id="canvas" ></div>
- </div>
- </div>
- <el-drawer
- :visible.sync="drawer"
- size=""
- :with-header="false">
- <m-versions :versionData = versionData :isInstance="type === 'instance'" @mVersionSwitchProcessDefinitionVersion="mVersionSwitchProcessDefinitionVersion" @mVersionGetProcessDefinitionVersionsPage="mVersionGetProcessDefinitionVersionsPage" @mVersionDeleteProcessDefinitionVersion="mVersionDeleteProcessDefinitionVersion" @closeVersion="closeVersion"></m-versions>
- </el-drawer>
- <el-drawer
- :visible.sync="nodeDrawer"
- size=""
- :with-header="false">
- <m-form-model v-if="nodeDrawer" :nodeData=nodeData @seeHistory="seeHistory" @addTaskInfo="addTaskInfo" @cacheTaskInfo="cacheTaskInfo" @close="close" @onSubProcess="onSubProcess"></m-form-model>
- </el-drawer>
- <el-drawer
- :visible.sync="lineDrawer"
- size=""
- :wrapperClosable="false"
- :with-header="false">
- <m-form-line-model :lineData = lineData @addLineInfo="addLineInfo" @cancel="cancel"></m-form-line-model>
- </el-drawer>
- <el-drawer
- :visible.sync="udpDrawer"
- size=""
- :wrapperClosable="false"
- :with-header="false">
- <m-udp></m-udp>
- </el-drawer>
- <el-dialog
- :title="$t('Set the DAG diagram name')"
- :visible.sync="dialogVisible"
- width="auto">
- <m-udp ref="mUdp" @onUdp="onUdpDialog" @close="closeDialog"></m-udp>
- </el-dialog>
- <el-dialog
- :title="$t('Please set the parameters before starting')"
- :visible.sync="startDialog"
- width="auto">
- <m-start :startData= "startData" :startNodeList="startNodeList" :sourceType="sourceType" @onUpdateStart="onUpdateStart" @closeStart="closeStart"></m-start>
- </el-dialog>
- </div>
+ <div :class="['dag-chart', fullScreen ? 'full-screen' : '']">
+ <dag-toolbar />
+ <dag-canvas ref="canvas" />
+ <el-drawer
+ :visible.sync="taskDrawer"
+ size=""
+ :with-header="false"
+ :wrapperClosable="false"
+ >
+ <m-form-model
+ v-if="taskDrawer"
+ :nodeData="nodeData"
+ @seeHistory="seeHistory"
+ @addTaskInfo="addTaskInfo"
+ @close="closeTaskDrawer"
+ @onSubProcess="toSubProcess"
+ ></m-form-model>
+ </el-drawer>
+ <el-dialog
+ :title="$t('Set the DAG diagram name')"
+ :visible.sync="saveDialog"
+ width="auto"
+ >
+ <m-udp ref="mUdp" @onUdp="onSave" @close="cancelSave"></m-udp>
+ </el-dialog>
+ <el-dialog
+ :title="$t('Please set the parameters before starting')"
+ :visible.sync="startDialog"
+ width="auto"
+ >
+ <m-start
+ :startData="{ code: definitionCode, name: name }"
+ :startNodeList="startTaskName"
+ :sourceType="'contextmenu'"
+ @onUpdateStart="onUpdateStart"
+ @closeStart="closeStart"
+ ></m-start>
+ </el-dialog>
+ <edge-edit-model ref="edgeEditModel" />
</div>
</template>
+
<script>
- import _ from 'lodash'
- import Dag from './dag'
- import mUdp from './udp/udp'
- import i18n from '@/module/i18n'
- import { jsPlumb } from 'jsplumb'
- import Clipboard from 'clipboard'
- import { allNodesId } from './plugIn/util'
- import { toolOper, tasksType } from './config'
- import mFormModel from './formModel/formModel'
- import mFormLineModel from './formModel/formLineModel'
- import { formatDate } from '@/module/filter/filter'
- import { findComponentDownward } from '@/module/util/'
- import disabledState from '@/module/mixin/disabledState'
+ import { debounce } from 'lodash'
+ import dagToolbar from './canvas/toolbar.vue'
+ import dagCanvas from './canvas/canvas.vue'
+ import mFormModel from '../_source/formModel/formModel.vue'
import { mapActions, mapState, mapMutations } from 'vuex'
- import mStart from '../../projects/pages/definition/pages/list/_source/start'
- import mVersions from '../../projects/pages/definition/pages/list/_source/versions'
+ import mUdp from '../_source/udp/udp.vue'
+ import mStart from '../../projects/pages/definition/pages/list/_source/start.vue'
+ import edgeEditModel from './canvas/edgeEditModel.vue'
- let eventModel
+ const DEFAULT_NODE_DATA = {
+ id: null,
+ taskType: '',
+ self: {},
+ preNode: [],
+ rearList: [],
+ instanceId: null
+ }
export default {
name: 'dag-chart',
- data () {
+ components: {
+ dagCanvas,
+ dagToolbar,
+ mFormModel,
+ mUdp,
+ mStart,
+ edgeEditModel
+ },
+ provide () {
return {
- tasksTypeList: tasksType,
- toolOperList: toolOper(this),
- dagBarId: null,
- toolOperCode: '',
- spinnerLoading: false,
- urlParam: {
- id: this.$route.params.id || null
- },
- isRtTasks: false,
- isRefresh: false,
- isLoading: false,
- taskId: null,
- arg: false,
- versionData: {
- processDefinition: {
- id: null,
- version: '',
- releaseState: ''
- },
- processDefinitionVersions: [],
- total: null,
- pageNo: null,
- pageSize: null
- },
- drawer: false,
- nodeData: {
- id: null,
- taskType: '',
- self: {},
- preNode: [],
- rearList: [],
- instanceId: null
- },
- nodeDrawer: false,
- lineData: {
- id: null,
- sourceId: '',
- targetId: ''
- },
- lineDrawer: false,
- udpDrawer: false,
- dialogVisible: false,
- startDialog: false,
- startData: {},
- startNodeList: '',
- sourceType: ''
+ dagChart: this
}
},
- mixins: [disabledState],
props: {
type: String,
releaseState: String
},
- methods: {
- ...mapActions('dag', ['saveDAGchart', 'updateInstance', 'updateDefinition', 'getTaskState', 'switchProcessDefinitionVersion', 'getProcessDefinitionVersionsPage', 'deleteProcessDefinitionVersion']),
- ...mapMutations('dag', ['addTasks', 'cacheTasks', 'resetParams', 'setIsEditDag', 'setName', 'addConnects', 'resetLocalParam']),
- startRunning (item, startNodeList, sourceType) {
- this.startData = item
- this.startNodeList = startNodeList
- this.sourceType = sourceType
- this.startDialog = true
- },
- onUpdateStart () {
- this.startDialog = false
- },
- closeStart () {
- this.startDialog = false
- },
- // DAG automatic layout
- dagAutomaticLayout () {
- if (this.store.state.dag.isEditDag) {
- this.$message.warning(`${i18n.$t('Please save the DAG before formatting')}`)
- return false
- }
- $('#canvas').html('')
+ data () {
+ return {
+ fullScreen: false,
+ taskDrawer: false,
+ nodeData: { ...DEFAULT_NODE_DATA },
+ saveDialog: false,
+ isLoading: false,
+ definitionCode: 0,
+ startDialog: false,
+ startTaskName: ''
+ }
+ },
+ mounted () {
+ // TODO
+ window._debug = this
- // Destroy round robin
- Dag.init({
- dag: this,
- instance: jsPlumb.getInstance({
- Endpoint: [
- 'Dot', { radius: 1, cssClass: 'dot-style' }
- ],
- Connector: 'Bezier',
- PaintStyle: { lineWidth: 2, stroke: '#456' }, // Connection style
- ConnectionOverlays: [
- [
- 'Arrow',
- {
- location: 1,
- id: 'arrow',
- length: 12,
- foldback: 0.8
- }
- ],
- ['Label', {
- location: 0.5,
- id: 'label'
- }]
- ],
- Container: 'canvas',
- ConnectionsDetachable: true
- })
- })
- if (this.tasks.length) {
- Dag.backfill(true)
- if (this.type === 'instance') {
- this._getTaskState(false).then(res => {})
- }
- } else {
- Dag.create()
- }
- },
+ if (this.type === 'instance') {
+ this.definitionCode = this.$route.query.id
+ } else if (this.type === 'definition') {
+ this.definitionCode = this.$route.params.code
+ }
- init (args) {
- if (this.tasks.length) {
- Dag.backfill(args)
- // Process instances can view status
- if (this.type === 'instance') {
- this._getTaskState(false).then(res => {})
- // Round robin acquisition status
- this.setIntervalP = setInterval(() => {
- this._getTaskState(true).then(res => {})
- }, 90000)
- }
- } else {
- Dag.create()
- }
- },
+ this.resizeDebounceFunc = debounce(this.canvasResize, 200)
+ window.addEventListener('resize', this.resizeDebounceFunc)
+ this.$refs.canvas.graphInit(!this.isDetails)
+
+ this.backfill()
+ },
+ unmounted () {
+ window.removeEventListener('resize', this.resizeDebounceFunc)
+ },
+ computed: {
+ ...mapState('dag', [
+ 'tasks',
+ 'locations',
+ 'connects',
+ 'isEditDag',
+ 'name',
+ 'isDetails',
+ 'projectCode'
+ ])
+ },
+ methods: {
+ ...mapActions('dag', [
+ 'saveDAGchart',
+ 'updateInstance',
+ 'updateDefinition',
+ 'getTaskState',
+ 'getStartCheck',
+ 'genTaskCodeList',
+ 'switchProcessDefinitionVersion',
+ 'getProcessDefinitionVersionsPage',
+ 'deleteProcessDefinitionVersion'
+ ]),
+ ...mapMutations('dag', [
+ 'addTask',
+ 'setTasks',
+ 'setConnects',
+ 'resetParams',
+ 'setIsEditDag',
+ 'setName',
+ 'setLocations',
+ 'resetLocalParam'
+ ]),
/**
- * copy name
+ * Toggle full screen
*/
- _copyName () {
- let clipboard = new Clipboard('.copy-name')
- clipboard.on('success', e => {
- this.$message.success(`${i18n.$t('Copy success')}`)
- // Free memory
- clipboard.destroy()
- })
- clipboard.on('error', e => {
- // Copy is not supported
- this.$message.warning(`${i18n.$t('The browser does not support automatic copying')}`)
- // Free memory
- clipboard.destroy()
- })
+ canvasResize () {
+ const canvas = this.$refs.canvas
+ canvas && canvas.paperResize()
+ },
+ toggleFullScreen () {
+ this.fullScreen = !this.fullScreen
+ this.$nextTick(this.canvasResize)
},
/**
- * Get state interface
- * @param isReset Whether to manually refresh
+ * Task Drawer
+ * @param {boolean} visible
*/
- _getTaskState (isReset) {
- return new Promise((resolve, reject) => {
- this.getTaskState(this.urlParam.id).then(res => {
- let data = res.list
- let state = res.processInstanceState
- let taskList = res.taskList
- let idArr = allNodesId()
- const titleTpl = (item, desc) => {
- let $item = _.filter(taskList, v => v.name === item.name)[0]
- return `<div style="text-align: left">${i18n.$t('Name')}:${$item.name}</br>${i18n.$t('State')}:${desc}</br>${i18n.$t('type')}:${$item.taskType}</br>${i18n.$t('host')}:${$item.host || '-'}</br>${i18n.$t('Retry Count')}:${$item.retryTimes}</br>${i18n.$t('Submit Time')}:${formatDate($item.submitTime)}</br>${i18n.$t('Start Time')}:${formatDate($item.startTime)}</br>${i18n.$t('End Time')}:${$item.endTime ? formatDate($item.endTime) : '-'}</br></div>`
- }
-
- // remove tip state dom
- $('.w').find('.state-p').html('')
- const newTask = []
- data.forEach(v1 => {
- idArr.forEach(v2 => {
- if (v2.name === v1.name) {
- let dom = $(`#${v2.id}`)
- let state = dom.find('.state-p')
- let depState = ''
- taskList.forEach(item => {
- if (item.name === v1.name) {
- depState = item.state
- const params = item.taskJson ? JSON.parse(item.taskJson).params : ''
- let localParam = params.localParams || []
- newTask.push({
- id: v2.id,
- localParam
- })
- }
- })
- dom.attr('data-state-id', v1.stateId)
- dom.attr('data-dependent-result', v1.dependentResult || '')
- dom.attr('data-dependent-depState', depState)
- state.append(`<strong class="${v1.icoUnicode} ${v1.isSpin ? 'as as-spin' : ''}" style="color:${v1.color}" data-toggle="tooltip" data-html="true" data-container="body"></strong>`)
- state.find('strong').attr('title', titleTpl(v2, v1.desc))
- }
- })
- })
- if (state === 'PAUSE' || state === 'STOP' || state === 'FAILURE' || this.state === 'SUCCESS') {
- // Manual refresh does not regain large json
- if (isReset) {
- findComponentDownward(this.$root, `${this.type}-details`)._reset()
- }
- }
- if (!isReset) {
- this.resetLocalParam(newTask)
- }
- resolve()
- })
- })
+ toggleTaskDrawer (visible) {
+ this.taskDrawer = visible
},
/**
- * Get the action bar id
- * @param item
+ * Set the current node data
*/
- _getDagId (v) {
- // if (this.isDetails) {
- // return
- // }
- this.dagBarId = v
+ setNodeData (nodeData) {
+ this.nodeData = Object.assign(DEFAULT_NODE_DATA, nodeData)
},
/**
- * operating
+ * open form model
+ * @desc Edit task config
+ * @param {number} taskCode
+ * @param {string} taskType
*/
- _ckOperation (item) {
- let is = true
- let code = ''
-
- if (item.disable) {
- return
- }
-
- if (this.toolOperCode === item.code) {
- this.toolOperCode = ''
- code = item.code
- is = false
- } else {
- this.toolOperCode = item.code
- code = this.toolOperCode
- is = true
- }
-
- // event type
- Dag.toolbarEvent({
- item: item,
- code: code,
- is: is
+ openFormModel (taskCode, taskType) {
+ this.setNodeData({
+ id: taskCode,
+ taskType: taskType
})
+ this.toggleTaskDrawer(true)
+ },
+ addTaskInfo ({ item, fromThis }) {
+ this.addTask(item)
+ this.$refs.canvas.setNodeName(item.code, item.name)
+ this.taskDrawer = false
},
- _operationClass (item) {
- return this.toolOperCode === item.code ? 'active' : ''
- // if (item.disable) {
- // return this.toolOperCode === item.code ? 'active' : ''
- // } else {
- // return 'disable'
- // }
+ closeTaskDrawer ({ item, flag, fromThis }) {
+ if (flag) {
+ const canvas = this.$refs.canvas
+ canvas.removeNode(this.nodeData.id)
+ }
+ this.taskDrawer = false
},
/**
- * Storage interface
+ * Save dialog
*/
- _save (sourceType) {
+ toggleSaveDialog (value) {
+ this.saveDialog = value
+ },
+ onSave (sourceType) {
+ this.toggleSaveDialog(false)
return new Promise((resolve, reject) => {
- this.spinnerLoading = true
- // Storage store
- Dag.saveStore().then(res => {
- if (this._verifConditions(res.tasks)) {
- 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.isLoading = true
+
+ let tasks = this.tasks || []
+ const edges = this.$refs.canvas.getEdges()
+ const nodes = this.$refs.canvas.getNodes()
+
+ const connects = this.buildConnects(edges, tasks)
+
+ this.setConnects(connects)
+
+ const locations = nodes.map(node => {
+ return {
+ taskCode: node.id,
+ x: node.position.x,
+ y: node.position.y
+ }
+ })
+
+ this.setLocations(locations)
+
+ resolve({
+ connects: connects,
+ tasks: tasks,
+ locations: locations
+ })
+ }).then((res) => {
+ if (this._verifConditions(res.tasks)) {
+ const definitionCode = this.definitionCode
+ if (definitionCode) {
+ /**
+ * Edit
+ * @param saveInstanceEditDAGChart => Process instance editing
+ * @param saveEditDAGChart => Process definition editing
+ */
+ return this[
+ this.type === 'instance' ? 'updateInstance' : 'updateDefinition'
+ ](definitionCode)
+ .then((res) => {
// this.$message.success(res.msg)
this.$message({
message: res.msg,
type: 'success',
offset: 80
})
- this.spinnerLoading = false
+ this.isLoading = false
// Jump process definition
if (this.type === 'instance') {
- this.$router.push({ path: `/projects/${this.projectId}/instance/list/${this.urlParam.id}` })
+ this.$router.push({
+ path: `/projects/${this.projectCode}/instance/list/${definitionCode}`
+ })
} else {
- this.$router.push({ path: `/projects/${this.projectId}/definition/list/${this.urlParam.id}` })
+ this.$router.push({
+ path: `/projects/${this.projectCode}/definition/list/${definitionCode}`
+ })
}
- resolve()
- }).catch(e => {
+ })
+ .catch((e) => {
this.$message.error(e.msg || '')
- this.spinnerLoading = false
- reject(e)
+ this.isLoading = false
})
- } else {
- // New
- this.saveDAGchart().then(res => {
+ } else {
+ // New
+ return this.saveDAGchart()
+ .then((res) => {
this.$message.success(res.msg)
- this.spinnerLoading = false
+ this.isLoading = 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 => {
+ })
+ .catch((e) => {
this.$message.error(e.msg || '')
this.setName('')
- this.spinnerLoading = false
- reject(e)
+ this.isLoading = false
})
- }
}
- })
+ }
})
},
- _closeDAG () {
- let $name = this.$route.name
- if ($name && $name.indexOf('definition') !== -1) {
- this.$router.push({ name: 'projects-definition-list' })
- } else {
- this.$router.push({ name: 'projects-instance-list' })
- }
- },
_verifConditions (value) {
let tasks = value
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)) {
+ tasks.map((v) => {
+ if (
+ v.taskType === 'CONDITIONS' &&
+ (v.taskParams.conditionResult.successNode[0] === '' ||
+ v.taskParams.conditionResult.successNode[0] === null ||
+ v.taskParams.conditionResult.failedNode[0] === '' ||
+ v.taskParams.conditionResult.failedNode[0] === null)
+ ) {
bool = false
return false
}
})
if (!bool) {
- this.$message.warning(`${i18n.$t('Successful branch flow and failed branch flow are required')}`)
- this.spinnerLoading = false
+ this.$message.warning(
+ `${this.$t(
+ 'Successful branch flow and failed branch flow are required'
+ )}`
+ )
+ this.isLoading = false
return false
}
return true
},
- onUdpDialog () {
- this._save()
- this.dialogVisible = false
- },
- closeDialog () {
- this.dialogVisible = false
+ cancelSave () {
+ this.toggleSaveDialog(false)
},
/**
- * Save chart
+ * build graph json
*/
- _saveChart () {
- // Verify node
- if (!this.tasks.length) {
- this.$message.warning(`${i18n.$t('Failed to create node to save')}`)
- return
- }
-
- this.dialogVisible = true
- this.$nextTick(() => {
- this.$refs.mUdp.reloadParam()
+ buildGraphJSON (tasks, locations, connects) {
+ const nodes = []
+ const edges = []
+ tasks.forEach((task) => {
+ const location = locations.find(l => l.taskCode === task.code) || {}
+ const node = this.$refs.canvas.genNodeJSON(
+ task.code,
+ task.taskType,
+ task.name,
+ {
+ x: location.x,
+ y: location.y
+ }
+ )
+ nodes.push(node)
+ })
+ connects.filter(r => !!r.preTaskCode).forEach((c) => {
+ const edge = this.$refs.canvas.genEdgeJSON(
+ c.preTaskCode,
+ c.postTaskCode,
+ c.name
+ )
+ edges.push(edge)
})
+ return {
+ nodes,
+ edges
+ }
},
/**
- * Return to the previous child node
+ * Build connects by edges and tasks
+ * @param {Edge[]} edges
+ * @param {Task[]} tasks
+ * @returns
*/
- _rtNodesDag () {
- let getIds = this.$route.query.subProcessIds
- let idsArr = getIds.split(',')
- let ids = idsArr.slice(0, idsArr.length - 1)
- let id = idsArr[idsArr.length - 1]
- let query = {}
+ buildConnects (edges, tasks) {
+ const preTaskMap = {}
+ const tasksMap = {}
- if (id !== idsArr[0]) {
- query = { subProcessIds: ids.join(',') }
- }
- let $name = this.$route.name.split('-')
- this.$router.push({ path: `/${$name[0]}/${$name[1]}/list/${id}`, query: query })
+ edges.forEach((edge) => {
+ preTaskMap[edge.targetId] = {
+ sourceId: edge.sourceId,
+ edgeLabel: edge.label || ''
+ }
+ })
+ tasks.forEach(task => {
+ tasksMap[task.code] = task
+ })
+
+ return tasks.map(task => {
+ const preTask = preTaskMap[task.code]
+ return {
+ name: preTask ? preTask.edgeLabel : '',
+ preTaskCode: preTask ? preTask.sourceId : 0,
+ preTaskVersion: preTask ? tasksMap[preTask.sourceId].version : 0,
+ postTaskCode: task.code,
+ postTaskVersion: tasksMap[task.code].version || 0,
+ // conditionType and conditionParams are reserved
+ conditionType: 0,
+ conditionParams: {}
+ }
+ })
+ },
+ backfill () {
+ const tasks = this.tasks
+ const locations = this.locations
+ const connects = this.connects
+ const json = this.buildGraphJSON(tasks, locations, connects)
+ this.$refs.canvas.fromJSON(json)
},
/**
- * Subprocess processing
- * @param subProcessId Subprocess ID
+ * Return to the previous process
*/
- _subProcessHandle (subProcessId) {
- let subProcessIds = []
- let getIds = this.$route.query.subProcessIds
+ returnToPrevProcess () {
+ let $name = this.$route.name.split('-')
+ let subProcessCodes = this.$route.query.subProcessCodes
+ let codes = subProcessCodes.split(',')
+ const last = codes.pop()
+ this.$router.push({
+ path: `/${$name[0]}/${this.projectId}/${$name[1]}/list/${last}`,
+ query: codes.length > 0 ? { subProcessCodes: codes.join(',') } : null
+ })
+ },
+ toSubProcess ({ subProcessCode, fromThis }) {
+ let subProcessCodes = []
+ let getIds = this.$route.query.subProcessCodes
if (getIds) {
let newId = getIds.split(',')
- newId.push(this.urlParam.id)
- subProcessIds = newId
+ newId.push(this.definitionCode)
+ subProcessCodes = newId
} else {
- subProcessIds.push(this.urlParam.id)
+ subProcessCodes.push(this.definitionCode)
}
let $name = this.$route.name.split('-')
- this.$router.push({ path: `/${$name[0]}/${$name[1]}/list/${subProcessId}`, query: { subProcessIds: subProcessIds.join(',') } })
- },
- /**
- * Refresh data
- */
- _refresh () {
- this.isRefresh = true
- this._getTaskState(false).then(res => {
- setTimeout(() => {
- this.isRefresh = false
- this.$message.success(`${i18n.$t('Refresh status succeeded')}`)
- }, 2200)
+ this.$router.push({
+ path: `/${$name[0]}/${this.projectCode}/${$name[1]}/list/${subProcessCode}`,
+ query: { subProcessCodes: subProcessCodes.join(',') }
})
},
- /**
- * View variables
- */
- _toggleView () {
- findComponentDownward(this.$root, 'assist-dag-index')._toggleView()
- },
-
- /**
- * Starting parameters
- */
- _toggleParam () {
- findComponentDownward(this.$root, 'starting-params-dag-index')._toggleParam()
- },
- addLineInfo ({ item, fromThis }) {
- this.addConnects(item)
- this.lineDrawer = false
- },
- cancel ({ fromThis }) {
- this.lineDrawer = false
- },
-
- /**
- * Create a node popup layer
- * @param Object id
- */
- _createLineLabel ({ id, sourceId, targetId }) {
- this.lineData.id = id
- this.lineData.sourceId = sourceId
- this.lineData.targetId = targetId
- this.lineDrawer = true
- },
-
seeHistory (taskName) {
- this.nodeData.self.$router.push({
+ this.$router.push({
name: 'task-instance',
query: {
- processInstanceId: this.nodeData.self.$route.params.id,
+ processInstanceId: this.$route.params.code,
taskName: taskName
}
})
},
-
- addTaskInfo ({ item, fromThis }) {
- this.addTasks(item)
- this.nodeDrawer = false
- },
-
- cacheTaskInfo ({ item, fromThis }) {
- this.cacheTasks(item)
- },
-
- close ({ item, flag, fromThis }) {
- this.addTasks(item)
- // Edit status does not allow deletion of nodes
- if (flag) {
- jsPlumb.remove(this.nodeData.id)
- }
- this.nodeDrawer = false
- },
- onSubProcess ({ subProcessId, fromThis }) {
- this._subProcessHandle(subProcessId)
- },
-
- _createNodes ({ id, type }) {
- let self = this
- let preNode = []
- let rearNode = []
- let rearList = []
- $('div[data-targetarr*="' + id + '"]').each(function () {
- rearNode.push($(this).attr('id'))
- })
-
- if (rearNode.length > 0) {
- rearNode.forEach(v => {
- let rearobj = {}
- rearobj.value = $(`#${v}`).find('.name-p').text()
- rearobj.label = $(`#${v}`).find('.name-p').text()
- rearList.push(rearobj)
- })
- } else {
- rearList = []
- }
- let targetarr = $(`#${id}`).attr('data-targetarr')
- if (targetarr) {
- let nodearr = targetarr.split(',')
- nodearr.forEach(v => {
- let nodeobj = {}
- nodeobj.value = $(`#${v}`).find('.name-p').text()
- nodeobj.label = $(`#${v}`).find('.name-p').text()
- preNode.push(nodeobj)
- })
- } else {
- preNode = []
- }
-
- this.taskId = id
- type = type || self.dagBarId
-
- this.nodeData.id = id
- this.nodeData.taskType = type
- this.nodeData.self = self
- this.nodeData.preNode = preNode
- this.nodeData.rearList = rearList
- this.nodeData.instanceId = this.$route.params.id
-
- this.nodeDrawer = true
- },
- removeEventModelById ($id) {
- if (eventModel && this.taskId === $id) {
- eventModel.remove()
- }
- },
-
/**
- * switch version in process definition version list
- *
- * @param version the version user want to change
- * @param processDefinitionId the process definition id
- * @param fromThis fromThis
- */
- mVersionSwitchProcessDefinitionVersion ({ version, processDefinitionId, fromThis }) {
- this.$store.state.dag.isSwitchVersion = true
- this.switchProcessDefinitionVersion({
- version: version,
- processDefinitionId: processDefinitionId
- }).then(res => {
- this.$message.success($t('Switch Version Successfully'))
- this.$router.push({ path: `/projects/${this.projectId}/definition/list/${processDefinitionId}` })
- }).catch(e => {
- this.$store.state.dag.isSwitchVersion = false
- this.$message.error(e.msg || '')
- })
+ * Start dialog
+ */
+ startRunning (taskName) {
+ this.startTaskName = taskName
+ this.getStartCheck({ processDefinitionCode: this.definitionCode }).then(
+ (res) => {
+ this.startDialog = true
+ }
+ )
},
-
- /**
- * Paging event of process definition versions
- *
- * @param pageNo page number
- * @param pageSize page size
- * @param processDefinitionId the process definition id of page version
- * @param fromThis fromThis
- */
- mVersionGetProcessDefinitionVersionsPage ({ pageNo, pageSize, processDefinitionCode, fromThis }) {
- this.getProcessDefinitionVersionsPage({
- pageNo: pageNo,
- pageSize: pageSize,
- processDefinitionCode: processDefinitionCode
- }).then(res => {
- this.versionData.processDefinitionVersions = res.data.totalList
- this.versionData.total = res.data.total
- this.versionData.pageSize = res.data.pageSize
- this.versionData.pageNo = res.data.currentPage
- }).catch(e => {
- this.$message.error(e.msg || '')
- })
+ onUpdateStart () {
+ this.startDialog = false
},
-
- /**
- * delete one version of process definition
- *
- * @param version the version need to delete
- * @param processDefinitionId the process definition id user want to delete
- * @param fromThis fromThis
- */
- mVersionDeleteProcessDefinitionVersion ({ version, processDefinitionId, processDefinitionCode, fromThis }) {
- this.deleteProcessDefinitionVersion({
- version: version,
- processDefinitionId: processDefinitionId
- }).then(res => {
- this.$message.success(res.msg || '')
- this.mVersionGetProcessDefinitionVersionsPage({
- pageNo: 1,
- pageSize: 10,
- processDefinitionCode: processDefinitionCode,
- fromThis: fromThis
- })
- }).catch(e => {
- this.$message.error(e.msg || '')
- })
+ closeStart () {
+ this.startDialog = false
},
/**
- * query the process definition pagination version
+ * Verify whether edge is valid
+ * The number of edges start with CONDITIONS task cannot be greater than 2
*/
- _version (item) {
- this.getProcessDefinitionVersionsPage({
- pageNo: 1,
- pageSize: 10,
- processDefinitionCode: this.store.state.dag.code
- }).then(res => {
- let processDefinitionVersions = res.data.totalList
- let total = res.data.total
- let pageSize = res.data.pageSize
- let pageNo = res.data.currentPage
- this.versionData.processDefinition.id = this.urlParam.id
- this.versionData.processDefinition.code = this.store.state.dag.code
- this.versionData.processDefinition.version = this.$store.state.dag.version
- this.versionData.processDefinition.releaseState = this.releaseState
- this.versionData.processDefinitionVersions = processDefinitionVersions
- this.versionData.total = total
- this.versionData.pageNo = pageNo
- this.versionData.pageSize = pageSize
- this.drawer = true
- }).catch(e => {
- this.$message.error(e.msg || '')
- })
- },
-
- closeVersion () {
- this.drawer = false
- }
- },
- watch: {
- tasks: {
- deep: true,
- handler (o) {
- // Edit state does not allow deletion of node a...
- this.setIsEditDag(true)
+ edgeIsValid (edge) {
+ const { sourceId } = edge
+ const sourceTask = this.tasks.find(task => task.code === sourceId)
+ if (sourceTask.taskType === 'CONDITIONS') {
+ const edges = this.$refs.canvas.getEdges()
+ return edges.filter(e => e.sourceId === sourceTask.code).length <= 2
}
+ return true
}
- },
- created () {
- // Edit state does not allow deletion of node a...
- this.setIsEditDag(false)
-
- if (this.$route.query.subProcessIds) {
- this.isRtTasks = true
- }
-
- Dag.init({
- dag: this,
- instance: jsPlumb.getInstance({
- Endpoint: [
- 'Dot', { radius: 1, cssClass: 'dot-style' }
- ],
- Connector: 'Bezier',
- PaintStyle: { lineWidth: 2, stroke: '#456' }, // Connection style
- ConnectionOverlays: [
- [
- 'Arrow',
- {
- location: 1,
- id: 'arrow',
- length: 12,
- foldback: 0.8
- }
- ],
- ['Label', {
- location: 0.5,
- id: 'label'
- }]
- ],
- Container: 'canvas',
- ConnectionsDetachable: true
- })
- })
- },
- mounted () {
- this.init(this.arg)
- },
- beforeDestroy () {
- this.resetParams()
-
- // Destroy round robin
- clearInterval(this.setIntervalP)
- },
- destroyed () {
- if (eventModel) {
- eventModel.remove()
- }
- },
- computed: {
- ...mapState('dag', ['tasks', 'locations', 'connects', 'isEditDag', 'name', 'projectId'])
- },
- components: { mVersions, mFormModel, mFormLineModel, mUdp, mStart }
+ }
}
</script>
-<style lang="scss" rel="stylesheet/scss">
- @import "./dag";
- .operBtn {
- padding: 8px 6px;
- }
+<style lang="scss" scoped>
+.dag-chart {
+ width: 100%;
+ height: calc(100vh - 100px);
+ padding: 10px;
+ background: #f2f3f7;
- .el-drawer__body {
- ::selection {
- background: #409EFF;
- color: white;
- }
+ &.full-screen {
+ position: fixed;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+ z-index: 9999;
}
-
+}
</style>
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 7dfcbc6..20f5187 100644
--- 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
@@ -50,8 +50,8 @@
<div slot="text">{{$t('Run flag')}}</div>
<div slot="content">
<el-radio-group v-model="runFlag" size="small">
- <el-radio :label="'NORMAL'" :disabled="isDetails">{{$t('Normal')}}</el-radio>
- <el-radio :label="'FORBIDDEN'" :disabled="isDetails">{{$t('Prohibition execution')}}</el-radio>
+ <el-radio :label="'YES'" :disabled="isDetails">{{$t('Normal')}}</el-radio>
+ <el-radio :label="'NO'" :disabled="isDetails">{{$t('Prohibition execution')}}</el-radio>
</el-radio-group>
</div>
</m-list-box>
@@ -259,11 +259,12 @@
:pre-node="nodeData.preNode">
</m-conditions>
<!-- Pre-tasks in workflow -->
- <m-pre-tasks
+ <!-- TODO -->
+ <!-- <m-pre-tasks
v-if="['SHELL', 'SUB_PROCESS'].indexOf(nodeData.taskType) > -1"
@on-pre-tasks="_onPreTasks"
ref="PRE_TASK"
- :backfill-item="backfillItem"></m-pre-tasks>
+ :backfill-item="backfillItem"></m-pre-tasks> -->
</div>
</div>
<div class="bottom-box">
@@ -276,7 +277,7 @@
</template>
<script>
import _ from 'lodash'
- import { mapActions } from 'vuex'
+ import { mapActions, mapState } from 'vuex'
import mLog from './log'
import mMr from './tasks/mr'
import mSql from './tasks/sql'
@@ -287,7 +288,6 @@
import mSpark from './tasks/spark'
import mFlink from './tasks/flink'
import mPython from './tasks/python'
- import JSP from './../plugIn/jsPlumbHandle'
import mProcedure from './tasks/procedure'
import mDependent from './tasks/dependent'
import mHttp from './tasks/http'
@@ -299,10 +299,9 @@
import mTimeoutAlarm from './_source/timeoutAlarm'
import mDependentTimeout from './_source/dependentTimeout'
import mWorkerGroups from './_source/workerGroups'
- import mPreTasks from './tasks/pre_tasks'
+ // import mPreTasks from './tasks/pre_tasks'
import clickoutside from '@/module/util/clickoutside'
import disabledState from '@/module/mixin/disabledState'
- import { isNameExDag, rtBantpl } from './../plugIn/util'
import mPriority from '@/module/components/priority/priority'
export default {
@@ -337,7 +336,7 @@
// Current node params data
params: {},
// Running sign
- runFlag: 'NORMAL',
+ runFlag: 'YES',
// The second echo problem caused by the node data is specifically which node hook caused the unfinished special treatment
isContentBox: false,
// Number of failed retries
@@ -380,6 +379,31 @@
},
methods: {
...mapActions('dag', ['getTaskInstanceList']),
+ taskToBackfillItem (task) {
+ return {
+ code: task.code,
+ conditionResult: task.taskParams.conditionResult,
+ delayTime: task.delayTime,
+ dependence: task.taskParams.dependence,
+ desc: task.description,
+ id: task.id,
+ maxRetryTimes: task.failRetryTimes,
+ name: task.name,
+ params: _.omit(task.taskParams, ['conditionResult', 'dependence']),
+ preTasks: [],
+ retryInterval: task.failRetryInterval,
+ runFlag: task.flag,
+ taskInstancePriority: task.taskPriority,
+ timeout: {
+ interval: task.timeout,
+ strategy: task.timeoutNotifyStrategy,
+ enable: task.timeoutFlag === 'OPEN'
+ },
+ type: task.taskType,
+ waitStartTimeout: task.waitStartTimeout,
+ workerGroup: task.workerGroup
+ }
+ },
/**
* depend
*/
@@ -449,8 +473,10 @@
this.$message.error(e.msg || '')
})
} else {
+ const processDefinitionId = this.backfillItem.params.processDefinitionId
+ const process = this.processListS.find(process => process.processDefinition.id === processDefinitionId)
this.$emit('onSubProcess', {
- subProcessId: this.backfillItem.params.processDefinitionId,
+ subProcessCode: process.processDefinition.code,
fromThis: this
})
}
@@ -461,39 +487,7 @@
_onParams (o) {
this.params = Object.assign({}, o)
},
-
- _onCacheParams (o) {
- this.params = Object.assign(this.params, {}, o)
- this._cacheItem()
- },
-
- _cacheItem () {
- this.conditionResult.successNode[0] = this.successBranch
- this.conditionResult.failedNode[0] = this.failedBranch
- this.$emit('cacheTaskInfo', {
- item: {
- type: this.nodeData.taskType,
- id: this.nodeData.id,
- name: this.name,
- code: this.code,
- params: this.params,
- desc: this.desc,
- runFlag: this.runFlag,
- conditionResult: this.conditionResult,
- dependence: this.cacheDependence,
- maxRetryTimes: this.maxRetryTimes,
- retryInterval: this.retryInterval,
- delayTime: this.delayTime,
- timeout: this.timeout,
- waitStartTimeout: this.waitStartTimeout,
- taskInstancePriority: this.taskInstancePriority,
- workerGroup: this.workerGroup,
- status: this.status,
- branch: this.branch
- },
- fromThis: this
- })
- },
+ _onCacheParams (o) {},
/**
* verification name
*/
@@ -510,7 +504,9 @@
return true
}
// Name repeat depends on dom backfill dependent store
- if (isNameExDag(this.name, _.isEmpty(this.backfillItem) ? 'dom' : 'backfill')) {
+ const tasks = this.store.state.dag.tasks
+ const task = tasks.find(t => t.name === 'this.name')
+ if (task) {
this.$message.warning(`${i18n.$t('Name already exists')}`)
return false
}
@@ -558,66 +554,35 @@
if (!this.$refs.PRE_TASK._verification()) {
return
} else {
- // Sync data-targetarr
- $(`#${this.nodeData.id}`).attr(
- 'data-targetarr', this.preTaskIdsInWorkflow ? this.preTaskIdsInWorkflow.join(',') : '')
-
- // Update JSP connections
- let plumbIns = JSP.JspInstance
- let targetId = this.nodeData.id
-
- // Update new connections
- this.preTasksToAdd.map(sourceId => {
- plumbIns.connect({
- source: sourceId,
- target: targetId,
- type: 'basic',
- paintStyle: { strokeWidth: 2, stroke: '#2d8cf0' },
- HoverPaintStyle: { stroke: '#ccc', strokeWidth: 3 }
- })
- })
+ // TODO sync preTasks to graph
- // Update remove connections
- let currentConnects = plumbIns.getAllConnections()
- let len = currentConnects.length
- for (let i = 0; i < len; i++) {
- if (this.preTasksToDelete.indexOf(currentConnects[i].sourceId) > -1 && currentConnects[i].targetId === targetId) {
- plumbIns.deleteConnection(currentConnects[i])
- i -= 1
- len -= 1
- }
- }
}
}
-
- $(`#${this.nodeData.id}`).find('span').text(this.name)
this.conditionResult.successNode[0] = this.successBranch
this.conditionResult.failedNode[0] = this.failedBranch
- // Store the corresponding node data structure
this.$emit('addTaskInfo', {
item: {
- type: this.nodeData.taskType,
- id: this.nodeData.id,
+ code: this.nodeData.id,
name: this.name,
- code: this.code,
- params: this.params,
- desc: this.desc,
- runFlag: this.runFlag,
- conditionResult: this.conditionResult,
- dependence: this.dependence,
- maxRetryTimes: this.maxRetryTimes,
- retryInterval: this.retryInterval,
- delayTime: this.delayTime,
- timeout: this.timeout,
- waitStartTimeout: this.waitStartTimeout,
- taskInstancePriority: this.taskInstancePriority,
+ description: this.desc,
+ taskType: this.nodeData.taskType,
+ taskParams: {
+ ...this.params,
+ dependence: this.cacheDependence,
+ conditionResult: this.conditionResult
+ },
+ flag: this.runFlag,
+ taskPriority: this.taskInstancePriority,
workerGroup: this.workerGroup,
- status: this.status,
- branch: this.branch
+ failRetryTimes: this.maxRetryTimes,
+ failRetryInterval: this.retryInterval,
+ timeoutFlag: this.timeout.enable ? 'OPEN' : 'CLOSE',
+ timeoutNotifyStrategy: this.timeout.strategy,
+ timeout: this.timeout.interval || 0,
+ delayTime: this.delayTime
},
fromThis: this
})
-
// set run flag
this._setRunFlag()
},
@@ -629,13 +594,10 @@
},
/**
* set run flag
+ * TODO
*/
_setRunFlag () {
- let dom = $(`#${this.nodeData.id}`).find('.ban-p')
- dom.html('')
- if (this.runFlag === 'FORBIDDEN') {
- dom.append(rtBantpl())
- }
+
},
/**
* Submit verification
@@ -661,42 +623,25 @@
})
}
},
- watch: {
- /**
- * Watch the item change, cache the value it changes
- **/
- _item (val) {
- // this._cacheItem()
- }
- },
created () {
- // Unbind copy and paste events
- JSP.removePaste()
// Backfill data
let taskList = this.store.state.dag.tasks
-
- // fillback use cacheTasks
- let cacheTasks = this.store.state.dag.cacheTasks
let o = {}
- if (cacheTasks[this.nodeData.id]) {
- o = cacheTasks[this.nodeData.id]
- this.backfillItem = cacheTasks[this.nodeData.id]
- } else {
- if (taskList.length) {
- taskList.forEach(v => {
- if (v.id === this.nodeData.id) {
- o = v
- this.backfillItem = v
- }
- })
- }
+ if (taskList.length) {
+ taskList.forEach(task => {
+ if (task.code === this.nodeData.id) {
+ const backfillItem = this.taskToBackfillItem(task)
+ o = backfillItem
+ this.backfillItem = backfillItem
+ }
+ })
}
// Non-null objects represent backfill
if (!_.isEmpty(o)) {
this.code = o.code
this.name = o.name
this.taskInstancePriority = o.taskInstancePriority
- this.runFlag = o.runFlag || 'NORMAL'
+ this.runFlag = o.runFlag || 'YES'
this.desc = o.desc
this.maxRetryTimes = o.maxRetryTimes
this.retryInterval = o.retryInterval
@@ -755,33 +700,14 @@
destroyed () {
},
computed: {
+ ...mapState('dag', [
+ 'processListS'
+ ]),
/**
* Child workflow entry show/hide
*/
_isGoSubProcess () {
return this.nodeData.taskType === 'SUB_PROCESS' && this.name
- },
-
- // Define the item model
- _item () {
- return {
- type: this.nodeData.taskType,
- id: this.nodeData.id,
- code: this.code,
- name: this.name,
- desc: this.desc,
- runFlag: this.runFlag,
- dependence: this.cacheDependence,
- maxRetryTimes: this.maxRetryTimes,
- retryInterval: this.retryInterval,
- delayTime: this.delayTime,
- timeout: this.timeout,
- waitStartTimeout: this.waitStartTimeout,
- taskInstancePriority: this.taskInstancePriority,
- workerGroup: this.workerGroup,
- successBranch: this.successBranch,
- failedBranch: this.failedBranch
- }
}
},
components: {
@@ -805,8 +731,8 @@
mTimeoutAlarm,
mDependentTimeout,
mPriority,
- mWorkerGroups,
- mPreTasks
+ mWorkerGroups
+ // mPreTasks
}
}
</script>
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/log.vue b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/log.vue
index 81d59d8..4a0cf69 100644
--- a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/log.vue
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/log.vue
@@ -79,6 +79,7 @@
store,
router,
isLog: false,
+ // TODO
stateId: $(`#${this.item.id}`).attr('data-state-id') || null,
isScreen: false,
loadingIndex: 0,
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/sub_process.vue b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/sub_process.vue
index 71fce10..189f92f 100644
--- a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/sub_process.vue
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/sub_process.vue
@@ -30,7 +30,7 @@
v-for="city in processDefinitionList"
:key="city.code"
:value="city.id"
- :label="city.code">
+ :label="city.name">
</el-option>
</el-select>
</div>
@@ -74,14 +74,14 @@
/**
* The selected process defines the upper component name padding
*/
- _handleWdiChanged (o) {
- this.$emit('on-set-process-name', this._handleName(o))
+ _handleWdiChanged (id) {
+ this.$emit('on-set-process-name', this._handleName(id))
},
/**
* Return the name according to the process definition id
*/
_handleName (id) {
- return _.filter(this.processDefinitionList, v => id === v.id)[0].code
+ return _.filter(this.processDefinitionList, v => id === v.id)[0].name
}
},
watch: {
@@ -93,22 +93,20 @@
},
created () {
let processListS = _.cloneDeep(this.store.state.dag.processListS)
- let id = null
+ let code = null
if (this.router.history.current.name === 'projects-instance-details') {
- id = this.router.history.current.query.id || null
+ code = this.router.history.current.query.code || null
} else {
- id = this.router.history.current.params.id || null
+ code = this.router.history.current.params.code || null
}
- this.processDefinitionList = (() => {
- let a = _.map(processListS, v => {
- return {
- id: v.id,
- code: v.name,
- disabled: false
- }
- })
- return _.filter(a, v => +v.id !== +id)
- })()
+ this.processDefinitionList = processListS.map(v => {
+ return {
+ id: v.processDefinition.id,
+ code: v.processDefinition.code,
+ name: v.processDefinition.name,
+ disabled: false
+ }
+ }).filter(a => (a.code + '') !== code)
let o = this.backfillItem
// Non-null objects represent backfill
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/full-screen-close.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/full-screen-close.png
new file mode 100755
index 0000000..316fff7
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/full-screen-close.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/full-screen-close_hover.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/full-screen-close_hover.png
new file mode 100755
index 0000000..5ad8804
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/full-screen-close_hover.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/full-screen-open.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/full-screen-open.png
new file mode 100755
index 0000000..2443cc7
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/full-screen-open.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/full-screen-open_hover.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/full-screen-open_hover.png
new file mode 100755
index 0000000..d33ba67
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/full-screen-open_hover.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/graph-format.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/graph-format.png
new file mode 100755
index 0000000..ce0ca79
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/graph-format.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/graph-format_hover.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/graph-format_hover.png
new file mode 100755
index 0000000..97d359a
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/graph-format_hover.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/startup-params.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/startup-params.png
new file mode 100755
index 0000000..987e1f9
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/startup-params.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/startup-params_hover.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/startup-params_hover.png
new file mode 100755
index 0000000..83b9a82
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/startup-params_hover.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/conditions.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/conditions.png
new file mode 100755
index 0000000..0849964
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/conditions.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/conditions_hover.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/conditions_hover.png
new file mode 100755
index 0000000..a0c4551
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/conditions_hover.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/datax.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/datax.png
new file mode 100755
index 0000000..22519a9
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/datax.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/datax_hover.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/datax_hover.png
new file mode 100755
index 0000000..986470d
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/datax_hover.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/dependent.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/dependent.png
new file mode 100755
index 0000000..3f0b732
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/dependent.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/dependent_hover.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/dependent_hover.png
new file mode 100755
index 0000000..4b4b866
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/dependent_hover.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/flink.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/flink.png
new file mode 100755
index 0000000..568efbe
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/flink.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/flink_hover.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/flink_hover.png
new file mode 100755
index 0000000..7c8e521
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/flink_hover.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/http.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/http.png
new file mode 100755
index 0000000..1d80cd0
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/http.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/http_hover.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/http_hover.png
new file mode 100755
index 0000000..31403be
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/http_hover.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/mr.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/mr.png
new file mode 100755
index 0000000..59d082f
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/mr.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/mr_hover.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/mr_hover.png
new file mode 100755
index 0000000..e4cfd96
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/mr_hover.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/procedure.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/procedure.png
new file mode 100755
index 0000000..e681c28
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/procedure.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/procedure_hover.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/procedure_hover.png
new file mode 100755
index 0000000..82ad43d
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/procedure_hover.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/python.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/python.png
new file mode 100755
index 0000000..8bc4d51
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/python.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/python_hover.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/python_hover.png
new file mode 100755
index 0000000..f94a4f7
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/python_hover.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/shell.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/shell.png
new file mode 100755
index 0000000..4e40b6e
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/shell.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/shell_hover.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/shell_hover.png
new file mode 100755
index 0000000..b615f55
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/shell_hover.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/spark.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/spark.png
new file mode 100755
index 0000000..e9ff012
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/spark.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/spark_hover.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/spark_hover.png
new file mode 100755
index 0000000..b0fbc56
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/spark_hover.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/sql.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/sql.png
new file mode 100755
index 0000000..3415486
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/sql.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/sql_hover.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/sql_hover.png
new file mode 100755
index 0000000..fabce22
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/sql_hover.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/sqoop.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/sqoop.png
new file mode 100755
index 0000000..2c754d3
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/sqoop.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/sqoop_hover.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/sqoop_hover.png
new file mode 100755
index 0000000..dd64890
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/sqoop_hover.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/sub_process.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/sub_process.png
new file mode 100755
index 0000000..fb12061
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/sub_process.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/sub_process_hover.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/sub_process_hover.png
new file mode 100755
index 0000000..d6b4abc
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/sub_process_hover.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/waterdrop.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/waterdrop.png
new file mode 100755
index 0000000..bf2f83e
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/waterdrop.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/waterdrop_hover.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/waterdrop_hover.png
new file mode 100755
index 0000000..e6affd6
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/task-icos/waterdrop_hover.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/view-variables.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/view-variables.png
new file mode 100755
index 0000000..44cbc90
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/view-variables.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/view-variables_hover.png b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/view-variables_hover.png
new file mode 100755
index 0000000..7f8e08c
Binary files /dev/null and b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/images/view-variables_hover.png differ
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/downChart.js b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/downChart.js
deleted file mode 100644
index 1c851a1..0000000
--- a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/downChart.js
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import _ from 'lodash'
-import canvg from 'canvg'
-import { tasksAll } from './util'
-import html2canvas from 'html2canvas'
-import { findComponentDownward } from '@/module/util/'
-
-const DownChart = function () {
- this.dag = {}
-}
-
-/**
- * Get interception location information
- */
-DownChart.prototype.maxVal = function () {
- return new Promise((resolve, reject) => {
- // All nodes
- const tasksAllList = tasksAll()
- const dom = $('.dag-container')
- const y = parseInt(_.maxBy(tasksAllList, 'y').y + 60)
- const x = parseInt(_.maxBy(tasksAllList, 'x').x + 100)
-
- resolve({
- width: (x > 600 ? x : dom.width()) + 100,
- height: (y > 500 ? y : dom.height()) + 100
- })
- })
-}
-
-/**
- * Download to image
- */
-DownChart.prototype.download = function ({ dagThis }) {
- this.dag = dagThis
-
- this.maxVal().then(({ width, height }) => {
- // Dom to save
- const copyDom = $('#canvas')
- // gain
- const scale = 1
- // divReport is the id of the dom that needs to be intercepted into a picture
- const svgElem = copyDom.find('svg')
- svgElem.each((index, node) => {
- // svg handle
- const nodesToRecover = []
- const nodesToRemove = []
- const parentNode = node.parentNode
- const svg = node.outerHTML.trim()
- const canvas = document.createElement('canvas')
- canvg(canvas, svg)
- if (node.style.position) {
- canvas.style.position += node.style.position
- canvas.style.left += node.style.left
- canvas.style.top += node.style.top
- }
- nodesToRecover.push({
- parent: parentNode,
- child: node
- })
- parentNode.removeChild(node)
- nodesToRemove.push({
- parent: parentNode,
- child: canvas
- })
- parentNode.appendChild(canvas)
- })
-
- const canvas = document.createElement('canvas')
- // canvas width
- canvas.width = width * scale
- // canvas height
- canvas.height = height * scale
-
- const content = canvas.getContext('2d')
- content.scale(scale, scale)
- // Get the offset of the element relative to the inspection
- const rect = copyDom.get(0).getBoundingClientRect()
- // Set the context position, the value is a negative value relative to the window offset, let the picture reset
- content.translate(-rect.left, -rect.top)
-
- html2canvas(copyDom[0], {
- dpi: window.devicePixelRatio * 2,
- scale: scale,
- width: width,
- canvas: canvas,
- heigth: height,
- useCORS: true // Enable cross-domain configuration
- }).then((canvas) => {
- const name = `${this.dag.name}.png`
- const url = canvas.toDataURL('image/png', 1)
- setTimeout(() => {
- const triggerDownload = $('<a>').attr('href', url).attr('download', name).appendTo('body')
- triggerDownload[0].click()
- triggerDownload.remove()
- }, 100)
-
- // To refresh the dag instance, otherwise you can't re-plot
- setTimeout(() => {
- // Refresh current dag
- findComponentDownward(this.dag.$root, `${this.dag.type}-details`).init()
- }, 500)
- })
- })
-}
-
-export default new DownChart()
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/jsPlumbHandle.js b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/jsPlumbHandle.js
deleted file mode 100755
index fbc00b0..0000000
--- a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/jsPlumbHandle.js
+++ /dev/null
@@ -1,814 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import 'jquery-ui/ui/widgets/draggable'
-import 'jquery-ui/ui/widgets/droppable'
-import 'jquery-ui/ui/widgets/resizable'
-import _ from 'lodash'
-import i18n from '@/module/i18n'
-import { jsPlumb } from 'jsplumb'
-import DragZoom from './dragZoom'
-import store from '@/conf/home/store'
-import router from '@/conf/home/router'
-import { uuid, findComponentDownward } from '@/module/util/'
-
-import {
- tasksAll,
- rtTasksTpl,
- setSvgColor,
- saveTargetarr,
- rtTargetarrArr,
- computeScale
-} from './util'
-import multiDrag from './multiDrag'
-
-const JSP = function () {
- this.dag = {}
- this.selectedElement = {}
-
- this.config = {
- // Whether to drag
- isDrag: true,
- // Whether to allow connection
- isAttachment: false,
- // Whether to drag a new node
- isNewNodes: true,
- // Whether to support double-click node events
- isDblclick: true,
- // Whether to support right-click menu events
- isContextmenu: true,
- // Whether to allow click events
- isClick: false
- }
-}
-/**
- * dag init
- */
-JSP.prototype.init = function ({ dag, instance, options }) {
- // Get the dag component instance
- this.dag = dag
- // Get jsplumb instance
- this.JspInstance = instance
- // Get JSP options
- this.options = options || {}
- // Register jsplumb connection type and configuration
- this.JspInstance.registerConnectionType('basic', {
- anchor: 'Continuous',
- connector: 'Bezier' // Line type
- })
-
- // Initial configuration
- this.setConfig({
- isDrag: !store.state.dag.isDetails,
- isAttachment: false,
- isNewNodes: !store.state.dag.isDetails, // Permissions.getAuth() === false ? false : !store.state.dag.isDetails,
- isDblclick: true,
- isContextmenu: true,
- isClick: false
- })
-
- // Monitor line click
- this.JspInstance.bind('click', e => {
- // Untie event
- if (this.config.isClick) {
- this.connectClick(e)
- } else {
- findComponentDownward(this.dag.$root, 'dag-chart')._createLineLabel({ id: e._jsPlumb.overlays.label.canvas.id, sourceId: e.sourceId, targetId: e.targetId })
- }
- })
-
- // Drag and drop
- if (this.config.isNewNodes) {
- DragZoom.init()
- }
-
- // support multi drag
- multiDrag()
-}
-
-/**
- * set config attribute
- */
-JSP.prototype.setConfig = function (o) {
- this.config = Object.assign(this.config, {}, o)
-}
-
-/**
- * Node binding event
- */
-JSP.prototype.tasksEvent = function (selfId) {
- const tasks = $(`#${selfId}`)
- // Bind right event
- tasks.on('contextmenu', e => {
- this.tasksContextmenu(e)
- return false
- })
-
- // Binding double click event
- tasks.find('.icos').bind('dblclick', e => {
- this.tasksDblclick(e)
- })
-
- // Binding click event
- tasks.on('click', e => {
- this.tasksClick(e)
- })
-}
-
-/**
- * Dag node drag and drop processing
- */
-JSP.prototype.draggable = function () {
- if (this.config.isNewNodes) {
- let selfId
- const self = this
- $('.toolbar-btn .roundedRect').draggable({
- scope: 'plant',
- helper: 'clone',
- containment: $('.dag-model'),
- stop: function (e, ui) {
- },
- drag: function () {
- $('body').find('.tooltip.fade.top.in').remove()
- }
- })
-
- $('#canvas').droppable({
- scope: 'plant',
- drop: function (ev, ui) {
- let id = 'tasks-' + Math.ceil(Math.random() * 100000) // eslint-disable-line
-
- let scale = computeScale($(this))
- scale = scale || 1
-
- // Get mouse coordinates and after scale coordinate
- const left = parseInt(ui.offset.left - $(this).offset().left) / scale
- const top = parseInt(ui.offset.top - $(this).offset().top) / scale
- // Generate template node
- $('#canvas').append(rtTasksTpl({
- id: id,
- name: id,
- x: left,
- y: top,
- isAttachment: self.config.isAttachment,
- taskType: findComponentDownward(self.dag.$root, 'dag-chart').dagBarId
- }))
-
- // Get the generated node
- const thisDom = jsPlumb.getSelector('.statemachine-demo .w')
-
- // Generating a connection node
- self.JspInstance.batch(() => {
- self.initNode(thisDom[thisDom.length - 1])
- })
- selfId = id
-
- self.tasksEvent(selfId)
-
- // Dom structure is not generated without pop-up form form
- if ($(`#${selfId}`).html()) {
- // dag event
- findComponentDownward(self.dag.$root, 'dag-chart')._createNodes({
- id: selfId
- })
- }
- }
- })
- }
-}
-
-/**
- * Echo json processing and old data structure processing
- */
-JSP.prototype.jsonHandle = function ({ largeJson, locations }) {
- _.map(largeJson, v => {
- // Generate template
- $('#canvas').append(rtTasksTpl({
- id: v.id,
- name: v.name,
- x: locations[v.id].x,
- y: locations[v.id].y,
- targetarr: locations[v.id].targetarr,
- isAttachment: this.config.isAttachment,
- taskType: v.type,
- runFlag: v.runFlag,
- nodenumber: locations[v.id].nodenumber,
- successNode: v.conditionResult === undefined ? '' : v.conditionResult.successNode[0],
- failedNode: v.conditionResult === undefined ? '' : v.conditionResult.failedNode[0]
- }))
-
- // contextmenu event
- $(`#${v.id}`).on('contextmenu', e => {
- this.tasksContextmenu(e)
- return false
- })
-
- // dblclick event
- $(`#${v.id}`).find('.icos').bind('dblclick', e => {
- this.tasksDblclick(e)
- })
-
- // click event
- $(`#${v.id}`).bind('click', e => {
- this.tasksClick(e)
- })
- })
-}
-
-/**
- * Initialize a single node
- */
-JSP.prototype.initNode = function (el) {
- // Whether to drag
- if (this.config.isDrag) {
- this.JspInstance.draggable(el, {
- containment: 'dag-container'
- })
- }
-
- // Node attribute configuration
- this.JspInstance.makeSource(el, {
- filter: '.ep',
- anchor: 'Continuous',
- connectorStyle: {
- stroke: '#2d8cf0',
- strokeWidth: 2,
- outlineStroke: 'transparent',
- outlineWidth: 4
- },
- // This place is leaking
- // connectionType: "basic",
- extract: {
- action: 'the-action'
- },
- maxConnections: -1
- })
-
- // Node connection property configuration
- this.JspInstance.makeTarget(el, {
- dropOptions: { hoverClass: 'dragHover' },
- anchor: 'Continuous',
- allowLoopback: false // Forbid yourself to connect yourself
- })
- this.JspInstance.fire('jsPlumbDemoNodeAdded', el)
-}
-
-/**
- * Node right click menu
- */
-JSP.prototype.tasksContextmenu = function (event) {
- if (this.config.isContextmenu) {
- const routerName = router.history.current.name
- // state
- const isOne = routerName === 'projects-definition-details' && this.dag.releaseState !== 'NOT_RELEASE'
- // hide
- const isTwo = store.state.dag.isDetails
-
- const html = [
- `<a href="javascript:" id="startRunning" class="${isOne ? '' : 'disbled'}"><em class="el-icon-video-play"></em><span>${i18n.$t('Start')}</span></a>`,
- `<a href="javascript:" id="editNodes" class="${isTwo ? 'disbled' : ''}"><em class="el-icon-edit-outline"></em><span>${i18n.$t('Edit')}</span></a>`,
- `<a href="javascript:" id="copyNodes" class="${isTwo ? 'disbled' : ''}"><em class="el-icon-copy-document"></em><span>${i18n.$t('Copy')}</span></a>`,
- `<a href="javascript:" id="removeNodes" class="${isTwo ? 'disbled' : ''}"><em class="el-icon-delete"></em><span>${i18n.$t('Delete')}</span></a>`
- ]
-
- const operationHtml = () => {
- return html.splice(',')
- }
-
- const e = event
- const $id = e.currentTarget.id
- const $contextmenu = $('#contextmenu')
- const $name = $(`#${$id}`).find('.name-p').text()
- const $left = e.pageX + document.body.scrollLeft - 5
- const $top = e.pageY + document.body.scrollTop - 5
- $contextmenu.css({
- left: $left,
- top: $top,
- visibility: 'visible'
- })
- // Action bar
- $contextmenu.html('').append(operationHtml)
-
- if (isOne) {
- // start run
- $('#startRunning').on('click', () => {
- const name = store.state.dag.name
- const id = router.history.current.params.id
- store.dispatch('dag/getStartCheck', { processDefinitionId: id }).then(res => {
- this.dag.startRunning({ id: id, name: name }, $name, 'contextmenu')
- })
- })
- }
- if (!isTwo) {
- // edit node
- $('#editNodes').click(ev => {
- findComponentDownward(this.dag.$root, 'dag-chart')._createNodes({
- id: $id,
- type: $(`#${$id}`).attr('data-tasks-type')
- })
- })
- // delete node
- $('#removeNodes').click(ev => {
- this.removeNodes($id)
- })
-
- // copy node
- $('#copyNodes').click(res => {
- this.copyNodes($id)
- })
- }
- }
-}
-
-/**
- * Node double click event
- */
-JSP.prototype.tasksDblclick = function (e) {
- // Untie event
- if (this.config.isDblclick) {
- const id = $(e.currentTarget.offsetParent).attr('id')
- findComponentDownward(this.dag.$root, 'dag-chart')._createNodes({
- id: id,
- type: $(`#${id}`).attr('data-tasks-type')
- })
- }
-}
-
-/**
- * Node click event
- */
-JSP.prototype.tasksClick = function (e) {
- let $id
- const self = this
- const $body = $('body')
- if (this.config.isClick) {
- const $connect = this.selectedElement.connect
- $('.w').removeClass('jtk-tasks-active')
- $(e.currentTarget).addClass('jtk-tasks-active')
- if ($connect) {
- setSvgColor($connect, '#2d8cf0')
- this.selectedElement.connect = null
- }
- this.selectedElement.id = $(e.currentTarget).attr('id')
-
- // Unbind copy and paste events
- $body.unbind('copy').unbind('paste')
- // Copy binding id
- $id = self.selectedElement.id
-
- $body.bind({
- copy: function () {
- $id = self.selectedElement.id
- },
- paste: function () {
- $id && self.copyNodes($id)
- }
- })
- }
-}
-
-/**
- * Remove binding events
- * paste
- */
-JSP.prototype.removePaste = function () {
- const $body = $('body')
- // Unbind copy and paste events
- $body.unbind('copy').unbind('paste')
- // Remove selected node parameters
- this.selectedElement.id = null
- // Remove node selection effect
- $('.w').removeClass('jtk-tasks-active')
-}
-
-/**
- * Line click event
- */
-JSP.prototype.connectClick = function (e) {
- // Set svg color
- setSvgColor(e, '#0097e0')
- const $id = this.selectedElement.id
- if ($id) {
- $(`#${$id}`).removeClass('jtk-tasks-active')
- this.selectedElement.id = null
- }
- this.selectedElement.connect = e
-}
-
-/**
- * toolbarEvent
- * @param {Pointer}
- */
-JSP.prototype.handleEventPointer = function (is) {
- this.setConfig({
- isClick: is,
- isAttachment: false
- })
-}
-
-/**
- * toolbarEvent
- * @param {Line}
- */
-JSP.prototype.handleEventLine = function (is) {
- const wDom = $('.w')
- this.setConfig({
- isAttachment: is
- })
- is ? wDom.addClass('jtk-ep') : wDom.removeClass('jtk-ep')
-}
-
-/**
- * toolbarEvent
- * @param {Remove}
- */
-JSP.prototype.handleEventRemove = function () {
- const $id = this.selectedElement.id || null
- const $connect = this.selectedElement.connect || null
- if ($id) {
- this.removeNodes(this.selectedElement.id)
- } else {
- this.removeConnect($connect)
- }
-
- // Monitor whether to edit DAG
- store.commit('dag/setIsEditDag', true)
-}
-
-/**
- * Delete node
- */
-JSP.prototype.removeNodes = function ($id) {
- // Delete node processing(data-targetarr)
- _.map(tasksAll(), v => {
- const targetarr = v.targetarr.split(',')
- if (targetarr.length) {
- const newArr = _.filter(targetarr, v1 => v1 !== $id)
- $(`#${v.id}`).attr('data-targetarr', newArr.toString())
- }
- })
- // delete node
- this.JspInstance.remove($id)
-
- // delete dom
- $(`#${$id}`).remove()
-
- // callback onRemoveNodes event
- this.options && this.options.onRemoveNodes && this.options.onRemoveNodes($id)
- const connects = []
- _.map(this.JspInstance.getConnections(), v => {
- connects.push({
- endPointSourceId: v.sourceId,
- endPointTargetId: v.targetId,
- label: v._jsPlumb.overlays.label.canvas.innerText
- })
- })
- // Storage line dependence
- store.commit('dag/setConnects', connects)
-}
-
-/**
- * Delete connection
- */
-JSP.prototype.removeConnect = function ($connect) {
- if (!$connect) {
- return
- }
- // Remove connections and remove node and node dependencies
- const targetId = $connect.targetId
- const sourceId = $connect.sourceId
- let targetarr = rtTargetarrArr(targetId)
- if (targetarr.length) {
- targetarr = _.filter(targetarr, v => v !== sourceId)
- $(`#${targetId}`).attr('data-targetarr', targetarr.toString())
- }
- if ($(`#${sourceId}`).attr('data-tasks-type') === 'CONDITIONS') {
- $(`#${sourceId}`).attr('data-nodenumber', Number($(`#${sourceId}`).attr('data-nodenumber')) - 1)
- }
- this.JspInstance.deleteConnection($connect)
-
- this.selectedElement = {}
-}
-
-/**
- * Copy node
- */
-JSP.prototype.copyNodes = function ($id) {
- let newNodeInfo = _.cloneDeep(_.find(store.state.dag.tasks, v => v.id === $id))
- const newNodePors = store.state.dag.locations[$id]
- // Unstored nodes do not allow replication
- if (!newNodePors) {
- return
- }
- // Generate random id
- const newUuId = `${uuid() + uuid()}`
- const id = newNodeInfo.id.length > 8 ? newNodeInfo.id.substr(0, 7) : newNodeInfo.id
- const name = newNodeInfo.name.length > 8 ? newNodeInfo.name.substr(0, 7) : newNodeInfo.name
-
- // new id
- const newId = `${id || ''}-${newUuId}`
- // new name
- const newName = `${name || ''}-${newUuId}`
- // coordinate x
- const newX = newNodePors.x + 100
- // coordinate y
- const newY = newNodePors.y + 40
-
- // Generate template node
- $('#canvas').append(rtTasksTpl({
- id: newId,
- name: newName,
- x: newX,
- y: newY,
- isAttachment: this.config.isAttachment,
- taskType: newNodeInfo.type
- }))
-
- // Get the generated node
- const thisDom = jsPlumb.getSelector('.statemachine-demo .w')
-
- // Copy node information
- newNodeInfo = Object.assign(newNodeInfo, {
- id: newId,
- name: newName
- })
-
- // Add new node
- store.commit('dag/addTasks', newNodeInfo)
- // Add node location information
- store.commit('dag/addLocations', {
- [newId]: {
- name: newName,
- targetarr: '',
- nodenumber: 0,
- x: newX,
- y: newY
- }
- })
-
- // Generating a connection node
- this.JspInstance.batch(() => {
- this.initNode(thisDom[thisDom.length - 1])
- // Add events to nodes
- this.tasksEvent(newId)
- })
-}
-/**
- * toolbarEvent
- * @param {Screen}
- */
-JSP.prototype.handleEventScreen = function ({ item, is }) {
- let screenOpen = true
- if (is) {
- item.icon = 'el-icon-aim'
- screenOpen = true
- } else {
- item.icon = 'el-icon-full-screen'
- screenOpen = false
- }
- const $mainLayoutModel = $('.main-layout-model')
- if (screenOpen) {
- $mainLayoutModel.addClass('dag-screen')
- } else {
- $mainLayoutModel.removeClass('dag-screen')
- }
-}
-/**
- * save task
- * @param tasks
- * @param locations
- * @param connects
- */
-JSP.prototype.saveStore = function () {
- return new Promise((resolve, reject) => {
- const connects = []
- const locations = {}
- const tasks = []
-
- const is = (id) => {
- return !!_.filter(tasksAll(), v => v.id === id).length
- }
-
- // task
- _.map(_.cloneDeep(store.state.dag.tasks), v => {
- if (is(v.id)) {
- const preTasks = []
- const id = $(`#${v.id}`)
- const tar = id.attr('data-targetarr')
- const idDep = tar ? id.attr('data-targetarr').split(',') : []
- if (idDep.length) {
- _.map(idDep, v1 => {
- preTasks.push($(`#${v1}`).find('.name-p').text())
- })
- }
-
- let tasksParam = _.assign(v, {
- preTasks: preTasks,
- depList: null
- })
-
- // Sub-workflow has no retries and interval
- if (v.type === 'SUB_PROCESS') {
- tasksParam = _.omit(tasksParam, ['maxRetryTimes', 'retryInterval'])
- }
-
- tasks.push(tasksParam)
- }
- })
-
- if (store.state.dag.connects.length === this.JspInstance.getConnections().length) {
- _.map(store.state.dag.connects, u => {
- connects.push({
- endPointSourceId: u.endPointSourceId,
- endPointTargetId: u.endPointTargetId,
- label: u.label
- })
- })
- } else if (store.state.dag.connects.length > 0 && store.state.dag.connects.length < this.JspInstance.getConnections().length) {
- _.map(this.JspInstance.getConnections(), v => {
- connects.push({
- endPointSourceId: v.sourceId,
- endPointTargetId: v.targetId,
- label: v._jsPlumb.overlays.label.canvas.innerText
- })
- })
- _.map(store.state.dag.connects, u => {
- _.map(connects, v => {
- if (u.label && u.endPointSourceId === v.endPointSourceId && u.endPointTargetId === v.endPointTargetId) {
- v.label = u.label
- }
- })
- })
- } else if (store.state.dag.connects.length === 0) {
- _.map(this.JspInstance.getConnections(), v => {
- connects.push({
- endPointSourceId: v.sourceId,
- endPointTargetId: v.targetId,
- label: v._jsPlumb.overlays.label.canvas.innerText
- })
- })
- } else if (store.state.dag.connects.length > this.JspInstance.getConnections().length) {
- _.map(this.JspInstance.getConnections(), v => {
- connects.push({
- endPointSourceId: v.sourceId,
- endPointTargetId: v.targetId,
- label: v._jsPlumb.overlays.label.canvas.innerText
- })
- })
- }
-
- _.map(tasksAll(), v => {
- locations[v.id] = {
- name: v.name,
- targetarr: v.targetarr,
- nodenumber: v.nodenumber,
- x: v.x,
- y: v.y
- }
- })
-
- // Storage node
- store.commit('dag/setTasks', tasks)
- // Store coordinate information
- store.commit('dag/setLocations', locations)
- // Storage line dependence
- store.commit('dag/setConnects', connects)
-
- resolve({
- connects: connects,
- tasks: tasks,
- locations: locations
- })
- })
-}
-/**
- * Event processing
- */
-
-JSP.prototype.handleEvent = function () {
- this.JspInstance.bind('beforeDrop', function (info) {
- const sourceId = info.sourceId// 出
- const targetId = info.targetId// 入
- /**
- * Recursive search for nodes
- */
- let recursiveVal
- const recursiveTargetarr = (arr, targetId) => {
- for (const i in arr) {
- if (arr[i] === targetId) {
- recursiveVal = targetId
- } else {
- recursiveTargetarr(rtTargetarrArr(arr[i]), targetId)
- }
- }
- return recursiveVal
- }
-
- // Connection to connected nodes is not allowed
- if (_.findIndex(rtTargetarrArr(targetId), v => v === sourceId) !== -1) {
- return false
- }
-
- // Recursive form to find if the target Targetarr has a sourceId
- if (recursiveTargetarr(rtTargetarrArr(sourceId), targetId)) {
- return false
- }
-
- if ($(`#${sourceId}`).attr('data-tasks-type') === 'CONDITIONS' && $(`#${sourceId}`).attr('data-nodenumber') === 2) {
- return false
- } else {
- $(`#${sourceId}`).attr('data-nodenumber', Number($(`#${sourceId}`).attr('data-nodenumber')) + 1)
- }
-
- // Storage node dependency information
- saveTargetarr(sourceId, targetId)
-
- // Monitor whether to edit DAG
- store.commit('dag/setIsEditDag', true)
-
- return true
- })
-}
-/**
- * Backfill data processing
- */
-JSP.prototype.jspBackfill = function ({ connects, locations, largeJson }) {
- // Backfill nodes
- this.jsonHandle({
- largeJson: largeJson,
- locations: locations
- })
-
- const wNodes = jsPlumb.getSelector('.statemachine-demo .w')
-
- // Backfill line
- this.JspInstance.batch(() => {
- for (let i = 0; i < wNodes.length; i++) {
- this.initNode(wNodes[i])
- }
- _.map(connects, v => {
- let sourceId = v.endPointSourceId.split('-')
- let targetId = v.endPointTargetId.split('-')
- const labels = v.label
- if (sourceId.length === 4 && targetId.length === 4) {
- sourceId = `${sourceId[0]}-${sourceId[1]}-${sourceId[2]}`
- targetId = `${targetId[0]}-${targetId[1]}-${targetId[2]}`
- } else {
- sourceId = v.endPointSourceId
- targetId = v.endPointTargetId
- }
-
- if ($(`#${sourceId}`).attr('data-tasks-type') === 'CONDITIONS' && $(`#${sourceId}`).attr('data-successnode') === $(`#${targetId}`).find('.name-p').text()) {
- this.JspInstance.connect({
- source: sourceId,
- target: targetId,
- type: 'basic',
- paintStyle: { strokeWidth: 2, stroke: '#4caf50' },
- HoverPaintStyle: { stroke: '#ccc', strokeWidth: 3 },
- overlays: [['Label', { label: labels }]]
- })
- } else if ($(`#${sourceId}`).attr('data-tasks-type') === 'CONDITIONS' && $(`#${sourceId}`).attr('data-failednode') === $(`#${targetId}`).find('.name-p').text()) {
- this.JspInstance.connect({
- source: sourceId,
- target: targetId,
- type: 'basic',
- paintStyle: { strokeWidth: 2, stroke: '#252d39' },
- HoverPaintStyle: { stroke: '#ccc', strokeWidth: 3 },
- overlays: [['Label', { label: labels }]]
- })
- } else {
- this.JspInstance.connect({
- source: sourceId,
- target: targetId,
- type: 'basic',
- paintStyle: { strokeWidth: 2, stroke: '#2d8cf0' },
- HoverPaintStyle: { stroke: '#ccc', strokeWidth: 3 },
- overlays: [['Label', { label: labels }]]
- })
- }
- })
- })
-
- jsPlumb.fire('jsPlumbDemoLoaded', this.JspInstance)
-
- // Connection monitoring
- this.handleEvent()
-
- // Drag and drop new nodes
- this.draggable()
-}
-
-export default new JSP()
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/multiDrag.js b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/multiDrag.js
deleted file mode 100644
index a68c529..0000000
--- a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/multiDrag.js
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import JSP from './jsPlumbHandle'
-/**
- * when and only ctrl or meta key pressing, we can select one or more dags to drag
- */
-export default function () {
- // init
- let selectableObjects = []
- JSP.JspInstance.clearDragSelection()
- let ctrlPress = false
-
- let nodes = null
- const $window = $(window)
-
- $window.bind('keydown', function (event) {
- if (event.ctrlKey || event.metaKey) {
- if (nodes) {
- nodes.unbind('mousedown', select)
- }
- nodes = $('.jtk-draggable')
- nodes.bind('mousedown', select)
- ctrlPress = true
- }
- })
- $window.bind('keyup', function (event) {
- clear()
- })
-
- function select (event) {
- if (ctrlPress && event.button === 0) {
- let index = null
- if ((index = selectableObjects.indexOf(this)) !== -1) {
- selectableObjects.splice(index, 1)
- JSP.JspInstance.removeFromDragSelection(this)
- $(this).css('border-color', '')
- } else {
- selectableObjects.push(this)
- JSP.JspInstance.addToDragSelection(this)
- $(this).css('border-color', '#4af')
- }
- }
- }
-
- function clear () {
- ctrlPress = false
- selectableObjects.map(item => {
- $(item).css('border-color', '')
- })
- selectableObjects = []
- JSP.JspInstance.clearDragSelection()
- }
-}
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/util.js b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/util.js
deleted file mode 100755
index 34a23e8..0000000
--- a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/plugIn/util.js
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import _ from 'lodash'
-import i18n from '@/module/i18n'
-import store from '@/conf/home/store'
-
-/**
- * Node, to array
- */
-const rtTargetarrArr = (id) => {
- const ids = $(`#${id}`).attr('data-targetarr')
- return ids ? ids.split(',') : []
-}
-
-/**
- * Store node id to targetarr
- */
-const saveTargetarr = (valId, domId) => {
- const $target = $(`#${domId}`)
- const targetStr = $target.attr('data-targetarr') ? $target.attr('data-targetarr') + `,${valId}` : `${valId}`
- $target.attr('data-targetarr', targetStr)
-}
-
-const rtBantpl = () => {
- return `<em class="ri-indeterminate-circle-line" data-toggle="tooltip" data-html="true" data-container="body" data-placement="left" title="${i18n.$t('Prohibition execution')}"></em>`
-}
-
-/**
- * return node html
- */
-const rtTasksTpl = ({ id, name, x, y, targetarr, isAttachment, taskType, runFlag, nodenumber, successNode, failedNode }) => {
- let tpl = ''
- tpl += `<div class="w jtk-draggable jtk-droppable jtk-endpoint-anchor jtk-connected ${isAttachment ? 'jtk-ep' : ''}" data-targetarr="${targetarr || ''}" data-successNode="${successNode || ''}" data-failedNode="${failedNode || ''}" data-nodenumber="${nodenumber || 0}" data-tasks-type="${taskType}" id="${id}" style="left: ${x}px; top: ${y}px;">`
- tpl += '<div>'
- tpl += '<div class="state-p"></div>'
- tpl += `<div class="icos icos-${taskType}"></div>`
- tpl += `<span class="name-p">${name}</span>`
- tpl += '</div>'
- tpl += '<div class="ep"></div>'
- tpl += '<div class="ban-p">'
- if (runFlag === 'FORBIDDEN') {
- tpl += rtBantpl()
- }
- tpl += '</div>'
- tpl += '</div>'
-
- return tpl
-}
-
-/**
- * Get all tasks nodes
- */
-const tasksAll = () => {
- const a = []
- $('#canvas .w').each(function (idx, elem) {
- const e = $(elem)
- a.push({
- id: e.attr('id'),
- name: e.find('.name-p').text(),
- targetarr: e.attr('data-targetarr') || '',
- nodenumber: e.attr('data-nodenumber'),
- x: parseInt(e.css('left'), 10),
- y: parseInt(e.css('top'), 10)
- })
- })
- return a
-}
-
-/**
- * Determine if name is in the current dag map
- * rely dom / backfill
- */
-const isNameExDag = (name, rely) => {
- if (rely === 'dom') {
- return _.findIndex(tasksAll(), v => v.name === name) !== -1
- } else {
- return _.findIndex(store.state.dag.tasks, v => v.name === name) !== -1
- }
-}
-
-/**
- * Change svg line color
- */
-const setSvgColor = (e, color) => {
- // Traverse clear all colors
- $('.jtk-connector').each((i, o) => {
- _.map($(o)[0].childNodes, v => {
- if ($(v).attr('fill') === '#ccc') {
- $(v).attr('fill', '#2d8cf0')
- }
- if ($(v).attr('fill') === '#4caf50') {
- $(v).attr('fill', '#4caf50').attr('stroke', '#4caf50').attr('stroke-width', 2)
- $(v).prev().attr('stroke', '#4caf50').attr('stroke-width', 2)
- } else if ($(v).attr('fill') === '#252d39') {
- $(v).attr('stroke', '#252d39').attr('stroke-width', 2)
- $(v).prev().attr('stroke', '#252d39').attr('stroke-width', 2)
- } else {
- $(v).attr('stroke', '#2d8cf0').attr('stroke-width', 2)
- }
- })
- })
-
- // Add color to the selection
- _.map($(e.canvas)[0].childNodes, (v, i) => {
- if ($(v).attr('fill') === '#2d8cf0') {
- $(v).attr('fill', '#ccc')
- }
- $(v).attr('stroke', '#ccc')
- if ($(v).attr('class')) {
- $(v).attr('stroke-width', 2)
- }
- })
-}
-
-/**
- * Get all node ids
- */
-const allNodesId = () => {
- const idArr = []
- $('.w').each((i, o) => {
- const $obj = $(o)
- const $span = $obj.find('.name-p').text()
- if ($span) {
- idArr.push({
- id: $obj.attr('id'),
- name: $span
- })
- }
- })
- return idArr
-}
-/**
- * compute scale,because it cant get from jquery directly
- * @param el element
- * @returns {boolean|number}
- */
-const computeScale = function (el) {
- const matrix = el.css('transform')
- if (!matrix || matrix === 'none') {
- return false
- }
- const values = matrix.split('(')[1].split(')')[0].split(',')
- return Math.sqrt(values[0] * values[0] + values[1] * values[1])
-}
-
-export {
- rtTargetarrArr,
- saveTargetarr,
- rtTasksTpl,
- tasksAll,
- isNameExDag,
- setSvgColor,
- allNodesId,
- rtBantpl,
- computeScale
-}
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/udp/_source/selectTenant.vue b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/udp/_source/selectTenant.vue
index e3611ba..0a491f9 100644
--- a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/udp/_source/selectTenant.vue
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/udp/_source/selectTenant.vue
@@ -61,8 +61,11 @@
}
},
methods: {
- _onChange (o) {
- this.$emit('tenantSelectEvent', o)
+ _onChange (id) {
+ const tenant = this.itemList.find(item => item.id === id)
+ if (tenant) {
+ this.$emit('tenantSelectEvent', tenant.tenantCode)
+ }
}
},
watch: {
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/udp/udp.vue b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/udp/udp.vue
index 9196e96..2d5af38 100644
--- a/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/udp/udp.vue
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/udp/udp.vue
@@ -42,7 +42,7 @@
<div class="title" style="padding-top: 6px;">
<span class="text-b">{{$t('select tenant')}}</span>
- <form-tenant v-model="tenantId"></form-tenant>
+ <form-tenant v-model="tenantCode"></form-tenant>
</div>
<div class="title" style="padding-top: 6px;">
<span class="text-b">{{$t('warning of timeout')}}</span>
@@ -117,8 +117,8 @@
syncDefine: true,
// Timeout alarm
timeout: 0,
-
- tenantId: -1,
+ // tenant code
+ tenantCode: 'default',
// checked Timeout alarm
checkedTimeout: true
}
@@ -150,7 +150,7 @@
this.store.commit('dag/setName', _.cloneDeep(this.name))
this.store.commit('dag/setTimeout', _.cloneDeep(this.timeout))
- this.store.commit('dag/setTenantId', _.cloneDeep(this.tenantId))
+ this.store.commit('dag/setTenantCode', _.cloneDeep(this.tenantCode))
this.store.commit('dag/setDesc', _.cloneDeep(this.description))
this.store.commit('dag/setSyncDefine', this.syncDefine)
this.store.commit('dag/setReleaseState', this.releaseState)
@@ -257,10 +257,10 @@
this.timeout = dag.timeout || 0
this.checkedTimeout = this.timeout !== 0
this.$nextTick(() => {
- if (dag.tenantId > -1) {
- this.tenantId = dag.tenantId
- } else if (this.store.state.user.userInfo.tenantId) {
- this.tenantId = this.store.state.user.userInfo.tenantId
+ if (dag.tenantCode) {
+ this.tenantCode = dag.tenantCode
+ } else {
+ this.tenantCode = this.store.state.user.userInfo.tenantCode || 'default'
}
})
},
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/dag/definitionDetails.vue b/dolphinscheduler-ui/src/js/conf/home/pages/dag/definitionDetails.vue
index 65510bf..1a5cc63 100644
--- a/dolphinscheduler-ui/src/js/conf/home/pages/dag/definitionDetails.vue
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/dag/definitionDetails.vue
@@ -53,7 +53,7 @@
// Promise Get node needs data
Promise.all([
// Node details
- this.getProcessDetails(this.$route.params.id),
+ this.getProcessDetails(this.$route.params.code),
// get process definition
this.getProcessList(),
// get project
@@ -69,8 +69,8 @@
this.getTenantList()
]).then((data) => {
let item = data[0]
- this.setIsDetails(item.releaseState === 'ONLINE')
- this.releaseState = item.releaseState
+ this.setIsDetails(item.processDefinition.releaseState === 'ONLINE')
+ this.releaseState = item.processDefinition.releaseState
this.isLoading = false
// Whether to pop up the box?
Affirm.init(this.$root)
@@ -82,7 +82,7 @@
* Redraw (refresh operation)
*/
_reset () {
- this.getProcessDetails(this.$route.params.id).then(res => {
+ this.getProcessDetails(this.$route.params.code).then(res => {
let item = res
this.setIsDetails(item.releaseState === 'ONLINE')
this.releaseState = item.releaseState
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/projects/pages/definition/pages/list/_source/list.vue b/dolphinscheduler-ui/src/js/conf/home/pages/projects/pages/definition/pages/list/_source/list.vue
index bf4eefd..fe55531 100644
--- a/dolphinscheduler-ui/src/js/conf/home/pages/projects/pages/definition/pages/list/_source/list.vue
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/projects/pages/definition/pages/list/_source/list.vue
@@ -25,7 +25,7 @@
<el-popover trigger="hover" placement="top">
<p>{{ scope.row.name }}</p>
<div slot="reference" class="name-wrapper">
- <router-link :to="{ path: `/projects/${projectId}/definition/list/${scope.row.id}` }" tag="a" class="links">
+ <router-link :to="{ path: `/projects/${projectCode}/definition/list/${scope.row.code}` }" tag="a" class="links">
<span class="ellipsis">{{scope.row.name}}</span>
</router-link>
</div>
@@ -256,7 +256,7 @@
}
// remove one
this.deleteDefinition({
- processDefinitionId: item.id
+ code: item.code
}).then(res => {
this._onUpdate()
this.$message.success(res.msg)
@@ -268,14 +268,14 @@
* edit
*/
_edit (item) {
- this.$router.push({ path: `/projects/${this.projectId}/definition/list/${item.id}` })
+ this.$router.push({ path: `/projects/${this.projectCode}/definition/list/${item.code}` })
},
/**
* Offline
*/
_downline (item) {
this._upProcessState({
- processId: item.id,
+ ...item,
releaseState: 'OFFLINE'
})
},
@@ -284,7 +284,7 @@
*/
_poponline (item) {
this._upProcessState({
- processId: item.id,
+ ...item,
releaseState: 'ONLINE'
})
},
@@ -520,7 +520,7 @@
mounted () {
},
computed: {
- ...mapState('dag', ['projectId'])
+ ...mapState('dag', ['projectId', 'projectCode'])
},
components: { mVersions, mStart, mTiming, mRelatedItems }
}
diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/projects/pages/definition/pages/list/_source/start.vue b/dolphinscheduler-ui/src/js/conf/home/pages/projects/pages/definition/pages/list/_source/start.vue
index 982a156..0454868 100644
--- a/dolphinscheduler-ui/src/js/conf/home/pages/projects/pages/definition/pages/list/_source/start.vue
+++ b/dolphinscheduler-ui/src/js/conf/home/pages/projects/pages/definition/pages/list/_source/start.vue
@@ -265,7 +265,7 @@
}
}
let param = {
- processDefinitionId: this.startData.id,
+ processDefinitionCode: this.startData.code,
scheduleTime: this.scheduleTime.length && this.scheduleTime.join(',') || '',
failureStrategy: this.failureStrategy,
warningType: this.warningType,
@@ -319,7 +319,7 @@
}
},
_getGlobalParams () {
- this.store.dispatch('dag/getProcessDetails', this.startData.id).then(res => {
+ this.store.dispatch('dag/getProcessDetails', this.startData.code).then(res => {
this.definitionGlobalParams = _.cloneDeep(this.store.state.dag.globalParams)
this.udpList = _.cloneDeep(this.store.state.dag.globalParams)
})
diff --git a/dolphinscheduler-ui/src/js/conf/home/router/index.js b/dolphinscheduler-ui/src/js/conf/home/router/index.js
index f73dba2..a0f7ce4 100644
--- a/dolphinscheduler-ui/src/js/conf/home/router/index.js
+++ b/dolphinscheduler-ui/src/js/conf/home/router/index.js
@@ -92,7 +92,7 @@ const router = new Router({
}
},
{
- path: '/projects/:projectId/kinship',
+ path: '/projects/:projectCode/kinship',
name: 'projects-kinship',
component: resolve => require(['../pages/projects/pages/kinship/index'], resolve),
meta: {
@@ -101,7 +101,7 @@ const router = new Router({
}
},
{
- path: '/projects/:projectId/definition',
+ path: '/projects/:projectCode/definition',
name: 'definition',
component: resolve => require(['../pages/projects/pages/definition/index'], resolve),
meta: {
@@ -113,7 +113,7 @@ const router = new Router({
},
children: [
{
- path: '/projects/:projectId/definition/list',
+ path: '/projects/:projectCode/definition/list',
name: 'projects-definition-list',
component: resolve => require(['../pages/projects/pages/definition/pages/list/index'], resolve),
meta: {
@@ -122,7 +122,7 @@ const router = new Router({
}
},
{
- path: '/projects/:projectId/definition/list/:id',
+ path: '/projects/:projectCode/definition/list/:code',
name: 'projects-definition-details',
component: resolve => require(['../pages/projects/pages/definition/pages/details/index'], resolve),
meta: {
@@ -131,7 +131,7 @@ const router = new Router({
}
},
{
- path: '/projects/:projectId/definition/create',
+ path: '/projects/:projectCode/definition/create',
name: 'definition-create',
component: resolve => require(['../pages/projects/pages/definition/pages/create/index'], resolve),
meta: {
@@ -139,7 +139,7 @@ const router = new Router({
}
},
{
- path: '/projects/:projectId/definition/tree/:id',
+ path: '/projects/:projectCode/definition/tree/:id',
name: 'definition-tree-view-index',
component: resolve => require(['../pages/projects/pages/definition/pages/tree/index'], resolve),
meta: {
@@ -148,7 +148,7 @@ const router = new Router({
}
},
{
- path: '/projects/:projectId/definition/list/timing/:code',
+ path: '/projects/:projectCode/definition/list/timing/:code',
name: 'definition-timing-details',
component: resolve => require(['../pages/projects/pages/definition/timing/index'], resolve),
meta: {
@@ -159,7 +159,7 @@ const router = new Router({
]
},
{
- path: '/projects/:projectId/instance',
+ path: '/projects/:projectCode/instance',
name: 'instance',
component: resolve => require(['../pages/projects/pages/instance/index'], resolve),
meta: {
@@ -170,7 +170,7 @@ const router = new Router({
},
children: [
{
- path: '/projects/:projectId/instance/list',
+ path: '/projects/:projectCode/instance/list',
name: 'projects-instance-list',
component: resolve => require(['../pages/projects/pages/instance/pages/list/index'], resolve),
meta: {
@@ -179,7 +179,7 @@ const router = new Router({
}
},
{
- path: '/projects/:projectId/instance/list/:id',
+ path: '/projects/:projectCode/instance/list/:id',
name: 'projects-instance-details',
component: resolve => require(['../pages/projects/pages/instance/pages/details/index'], resolve),
meta: {
@@ -188,7 +188,7 @@ const router = new Router({
}
},
{
- path: '/projects/:projectId/instance/gantt/:id',
+ path: '/projects/:projectCode/instance/gantt/:id',
name: 'instance-gantt-index',
component: resolve => require(['../pages/projects/pages/instance/pages/gantt/index'], resolve),
meta: {
@@ -199,7 +199,7 @@ const router = new Router({
]
},
{
- path: '/projects/:projectId/task-instance',
+ path: '/projects/:projectCode/task-instance',
name: 'task-instance',
component: resolve => require(['../pages/projects/pages/taskInstance'], resolve),
meta: {
@@ -209,7 +209,7 @@ const router = new Router({
},
{
- path: '/projects/:projectId/task-record',
+ path: '/projects/:projectCode/task-record',
name: 'task-record',
component: resolve => require(['../pages/projects/pages/taskRecord'], resolve),
meta: {
@@ -218,7 +218,7 @@ const router = new Router({
}
},
{
- path: '/projects/:projectId/history-task-record',
+ path: '/projects/:projectCode/history-task-record',
name: 'history-task-record',
component: resolve => require(['../pages/projects/pages/historyTaskRecord'], resolve),
meta: {
diff --git a/dolphinscheduler-ui/src/js/conf/home/store/dag/actions.js b/dolphinscheduler-ui/src/js/conf/home/store/dag/actions.js
index 63bce50..9ac787d 100644
--- a/dolphinscheduler-ui/src/js/conf/home/store/dag/actions.js
+++ b/dolphinscheduler-ui/src/js/conf/home/store/dag/actions.js
@@ -19,32 +19,13 @@ import _ from 'lodash'
import io from '@/module/io'
import { tasksState } from '@/conf/home/pages/dag/_source/config'
-// delete 'definitionList' from tasks
-const deleteDefinitionList = (tasks) => {
- const newTasks = []
- tasks.forEach(item => {
- const newItem = Object.assign({}, item)
- if (newItem.dependence && newItem.dependence.dependTaskList) {
- newItem.dependence.dependTaskList.forEach(dependTaskItem => {
- if (dependTaskItem.dependItemList) {
- dependTaskItem.dependItemList.forEach(dependItem => {
- Reflect.deleteProperty(dependItem, 'definitionList')
- })
- }
- })
- }
- newTasks.push(newItem)
- })
- return newTasks
-}
-
export default {
/**
* Task status acquisition
*/
getTaskState ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.get(`projects/${state.projectName}/instance/task-list-by-process-id`, {
+ io.get(`projects/${state.projectCode}/instance/task-list-by-process-id`, {
processInstanceId: payload
}, res => {
const arr = _.map(res.data.taskList, v => {
@@ -69,8 +50,9 @@ export default {
*/
editProcessState ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.post(`projects/${state.projectName}/process/release`, {
- processId: payload.processId,
+ io.post(`projects/${state.projectCode}/process/release`, {
+ code: payload.code,
+ name: payload.name,
releaseState: payload.releaseState
}, res => {
resolve(res)
@@ -85,7 +67,7 @@ export default {
*/
getProcessDefinitionVersionsPage ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.get(`projects/${state.projectName}/process/versions`, payload, res => {
+ io.get(`projects/${state.projectCode}/process/versions`, payload, res => {
resolve(res)
}).catch(e => {
reject(e)
@@ -98,7 +80,7 @@ export default {
*/
switchProcessDefinitionVersion ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.get(`projects/${state.projectName}/process/version/switch`, payload, res => {
+ io.get(`projects/${state.projectCode}/process/version/switch`, payload, res => {
resolve(res)
}).catch(e => {
reject(e)
@@ -111,7 +93,7 @@ export default {
*/
deleteProcessDefinitionVersion ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.get(`projects/${state.projectName}/process/version/delete`, payload, res => {
+ io.get(`projects/${state.projectCode}/process/version/delete`, payload, res => {
resolve(res)
}).catch(e => {
reject(e)
@@ -139,7 +121,7 @@ export default {
*/
verifDAGName ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.get(`projects/${state.projectName}/process/verify-name`, {
+ io.get(`projects/${state.projectCode}/process/verify-name`, {
name: payload
}, res => {
state.name = payload
@@ -155,36 +137,45 @@ export default {
*/
getProcessDetails ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.get(`projects/${state.projectName}/process/select-by-id`, {
- processId: payload
+ io.get(`projects/${state.projectCode}/process/select-by-code`, {
+ code: payload
}, res => {
// process definition code
- state.code = res.data.code
+ state.code = res.data.processDefinition.code
// version
- state.version = res.data.version
+ state.version = res.data.processDefinition.version
// name
- state.name = res.data.name
+ state.name = res.data.processDefinition.name
// description
- state.description = res.data.description
- // connects
- state.connects = JSON.parse(res.data.connects)
+ state.description = res.data.processDefinition.description
+ // taskRelationJson
+ state.connects = res.data.processTaskRelationList
// locations
- state.locations = JSON.parse(res.data.locations)
- // Process definition
- const processDefinitionJson = JSON.parse(res.data.processDefinitionJson)
- // tasks info
- state.tasks = processDefinitionJson.tasks
- // tasks cache
- state.cacheTasks = {}
- processDefinitionJson.tasks.forEach(v => {
- state.cacheTasks[v.id] = v
- })
+ state.locations = JSON.parse(res.data.processDefinition.locations)
// global params
- state.globalParams = processDefinitionJson.globalParams
+ state.globalParams = res.data.processDefinition.globalParamList
// timeout
- state.timeout = processDefinitionJson.timeout
-
- state.tenantId = processDefinitionJson.tenantId
+ state.timeout = res.data.processDefinition.timeout
+ // tenantId
+ state.tenantCode = res.data.processDefinition.tenantCode
+ // tasks info
+ state.tasks = res.data.taskDefinitionList.map(task => _.pick(task, [
+ 'code',
+ 'name',
+ 'version',
+ 'description',
+ 'delayTime',
+ 'taskType',
+ 'taskParams',
+ 'flag',
+ 'taskPriority',
+ 'workerGroup',
+ 'failRetryTimes',
+ 'failRetryInterval',
+ 'timeoutFlag',
+ 'timeoutNotifyStrategy',
+ 'timeout'
+ ]))
resolve(res.data)
}).catch(res => {
reject(res)
@@ -197,7 +188,7 @@ export default {
*/
copyProcess ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.post(`projects/${state.projectName}/process/copy`, {
+ io.post(`projects/${state.projectCode}/process/copy`, {
processDefinitionIds: payload.processDefinitionIds,
targetProjectId: payload.targetProjectId
}, res => {
@@ -213,7 +204,7 @@ export default {
*/
moveProcess ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.post(`projects/${state.projectName}/process/move`, {
+ io.post(`projects/${state.project}/process/move`, {
processDefinitionIds: payload.processDefinitionIds,
targetProjectId: payload.targetProjectId
}, res => {
@@ -242,37 +233,46 @@ export default {
*/
getInstancedetail ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.get(`projects/${state.projectName}/instance/select-by-id`, {
+ io.get(`projects/${state.projectCode}/instance/select-by-id`, {
processInstanceId: payload
}, res => {
+ const { processDefinition, processTaskRelationList, taskDefinitionList } = res.data.dagData
// code
- state.code = res.data.processDefinitionCode
+ state.code = processDefinition.code
// version
- state.version = res.data.processDefinitionVersion
+ state.version = processDefinition.version
// name
state.name = res.data.name
// desc
- state.description = res.data.description
+ state.description = processDefinition.description
// connects
- state.connects = JSON.parse(res.data.connects)
+ state.connects = processTaskRelationList
// locations
- state.locations = JSON.parse(res.data.locations)
- // process instance
- const processInstanceJson = JSON.parse(res.data.processInstanceJson)
- // tasks info
- state.tasks = processInstanceJson.tasks
- // tasks cache
- state.cacheTasks = {}
- processInstanceJson.tasks.forEach(v => {
- state.cacheTasks[v.id] = v
- })
+ state.locations = JSON.parse(processDefinition.locations)
// global params
- state.globalParams = processInstanceJson.globalParams
+ state.globalParams = processDefinition.globalParamList
// timeout
- state.timeout = processInstanceJson.timeout
-
- state.tenantId = processInstanceJson.tenantId
-
+ state.timeout = processDefinition.timeout
+ // tenantCode
+ state.tenantCode = res.data.tenantCode
+ // tasks info
+ state.tasks = taskDefinitionList.map(task => _.pick(task, [
+ 'code',
+ 'name',
+ 'version',
+ 'description',
+ 'delayTime',
+ 'taskType',
+ 'taskParams',
+ 'flag',
+ 'taskPriority',
+ 'workerGroup',
+ 'failRetryTimes',
+ 'failRetryInterval',
+ 'timeoutFlag',
+ 'timeoutNotifyStrategy',
+ 'timeout'
+ ]))
// startup parameters
state.startup = _.assign(state.startup, _.pick(res.data, ['commandType', 'failureStrategy', 'processInstancePriority', 'workerGroup', 'warningType', 'warningGroupId', 'receivers', 'receiversCc']))
state.startup.commandParam = JSON.parse(res.data.commandParam)
@@ -288,18 +288,15 @@ export default {
*/
saveDAGchart ({ state }, payload) {
return new Promise((resolve, reject) => {
- const data = {
- globalParams: state.globalParams,
- tasks: deleteDefinitionList(state.tasks),
- tenantId: state.tenantId,
- timeout: state.timeout
- }
- io.post(`projects/${state.projectName}/process/save`, {
- processDefinitionJson: JSON.stringify(data),
+ io.post(`projects/${state.projectCode}/process/save`, {
+ locations: JSON.stringify(state.locations),
name: _.trim(state.name),
+ taskDefinitionJson: JSON.stringify(state.tasks),
+ taskRelationJson: JSON.stringify(state.connects),
+ tenantCode: state.tenantCode,
description: _.trim(state.description),
- locations: JSON.stringify(state.locations),
- connects: JSON.stringify(state.connects)
+ globalParams: JSON.stringify(state.globalParams),
+ timeout: state.timeout
}, res => {
resolve(res)
}).catch(e => {
@@ -312,20 +309,17 @@ export default {
*/
updateDefinition ({ state }, payload) {
return new Promise((resolve, reject) => {
- const data = {
- globalParams: state.globalParams,
- tasks: deleteDefinitionList(state.tasks),
- tenantId: state.tenantId,
- timeout: state.timeout
- }
- io.post(`projects/${state.projectName}/process/update`, {
- processDefinitionJson: JSON.stringify(data),
+ io.post(`projects/${state.projectCode}/process/update`, {
locations: JSON.stringify(state.locations),
- connects: JSON.stringify(state.connects),
name: _.trim(state.name),
+ taskDefinitionJson: JSON.stringify(state.tasks),
+ taskRelationJson: JSON.stringify(state.connects),
+ tenantCode: state.tenantCode,
description: _.trim(state.description),
- id: payload,
- releaseState: state.releaseState
+ globalParams: JSON.stringify(state.globalParams),
+ timeout: state.timeout,
+ releaseState: state.releaseState,
+ code: payload
}, res => {
resolve(res)
state.isEditDag = false
@@ -345,7 +339,7 @@ export default {
tenantId: state.tenantId,
timeout: state.timeout
}
- io.post(`projects/${state.projectName}/instance/update`, {
+ io.post(`projects/${state.projectCode}/instance/update`, {
processInstanceJson: JSON.stringify(data),
locations: JSON.stringify(state.locations),
connects: JSON.stringify(state.connects),
@@ -368,7 +362,7 @@ export default {
resolve()
return
}
- io.get(`projects/${state.projectName}/process/list`, payload, res => {
+ io.get(`projects/${state.projectCode}/process/list`, payload, res => {
state.processListS = res.data
resolve(res.data)
}).catch(res => {
@@ -381,7 +375,7 @@ export default {
*/
getProcessListP ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.get(`projects/${state.projectName}/process/list-paging`, payload, res => {
+ io.get(`projects/${state.projectCode}/process/list-paging`, payload, res => {
resolve(res.data)
}).catch(res => {
reject(res)
@@ -410,7 +404,7 @@ export default {
*/
getProcessByProjectId ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.get(`projects/${state.projectName}/process/queryProcessDefinitionAllByProjectId`, payload, res => {
+ io.get(`projects/${state.projectCode}/process/queryProcessDefinitionAllByProjectId`, payload, res => {
resolve(res.data)
}).catch(res => {
reject(res)
@@ -474,7 +468,7 @@ export default {
*/
getProcessInstance ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.get(`projects/${state.projectName}/instance/list-paging`, payload, res => {
+ io.get(`projects/${state.projectCode}/instance/list-paging`, payload, res => {
state.instanceListS = res.data.totalList
resolve(res.data)
}).catch(res => {
@@ -531,7 +525,7 @@ export default {
*/
getSubProcessId ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.get(`projects/${state.projectName}/instance/select-sub-process`, payload, res => {
+ io.get(`projects/${state.projectCode}/instance/select-sub-process`, payload, res => {
resolve(res)
}).catch(e => {
reject(e)
@@ -628,7 +622,7 @@ export default {
*/
deleteInstance ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.get(`projects/${state.projectName}/instance/delete`, payload, res => {
+ io.get(`projects/${state.projectCode}/instance/delete`, payload, res => {
resolve(res)
}).catch(e => {
reject(e)
@@ -640,7 +634,7 @@ export default {
*/
batchDeleteInstance ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.get(`projects/${state.projectName}/instance/batch-delete`, payload, res => {
+ io.get(`projects/${state.projectCode}/instance/batch-delete`, payload, res => {
resolve(res)
}).catch(e => {
reject(e)
@@ -652,7 +646,7 @@ export default {
*/
deleteDefinition ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.get(`projects/${state.projectName}/process/delete`, payload, res => {
+ io.get(`projects/${state.projectCode}/process/delete`, payload, res => {
resolve(res)
}).catch(e => {
reject(e)
@@ -664,7 +658,7 @@ export default {
*/
batchDeleteDefinition ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.get(`projects/${state.projectName}/process/batch-delete`, payload, res => {
+ io.get(`projects/${state.projectCode}/process/batch-delete`, payload, res => {
resolve(res)
}).catch(e => {
reject(e)
@@ -696,7 +690,7 @@ export default {
}
}
- io.get(`projects/${state.projectName}/process/export`, { processDefinitionIds: payload.processDefinitionIds }, res => {
+ io.get(`projects/${state.projectCode}/process/export`, { processDefinitionIds: payload.processDefinitionIds }, res => {
downloadBlob(res, payload.fileName)
}, e => {
@@ -710,7 +704,7 @@ export default {
*/
getViewvariables ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.get(`projects/${state.projectName}/instance/view-variables`, payload, res => {
+ io.get(`projects/${state.projectCode}/instance/view-variables`, payload, res => {
resolve(res)
}).catch(e => {
reject(e)
@@ -734,7 +728,7 @@ export default {
*/
getTaskInstanceList ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.get(`projects/${state.projectName}/task-instance/list-paging`, payload, res => {
+ io.get(`projects/${state.projectCode}/task-instance/list-paging`, payload, res => {
resolve(res.data)
}).catch(e => {
reject(e)
@@ -746,7 +740,7 @@ export default {
*/
forceTaskSuccess ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.post(`projects/${state.projectName}/task-instance/force-success`, payload, res => {
+ io.post(`projects/${state.projectCode}/task-instance/force-success`, payload, res => {
resolve(res)
}).catch(e => {
reject(e)
@@ -782,7 +776,7 @@ export default {
*/
getViewTree ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.get(`projects/${state.projectName}/process/view-tree`, payload, res => {
+ io.get(`projects/${state.projectCode}/process/view-tree`, payload, res => {
resolve(res.data)
}).catch(e => {
reject(e)
@@ -794,7 +788,7 @@ export default {
*/
getViewGantt ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.get(`projects/${state.projectName}/instance/view-gantt`, payload, res => {
+ io.get(`projects/${state.projectCode}/instance/view-gantt`, payload, res => {
resolve(res.data)
}).catch(e => {
reject(e)
@@ -806,7 +800,7 @@ export default {
*/
getProcessTasksList ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.get(`projects/${state.projectName}/process/gen-task-list`, payload, res => {
+ io.get(`projects/${state.projectCode}/process/gen-task-list`, payload, res => {
resolve(res.data)
}).catch(e => {
reject(e)
@@ -815,7 +809,7 @@ export default {
},
getTaskListDefIdAll ({ state }, payload) {
return new Promise((resolve, reject) => {
- io.get(`projects/${state.projectName}/process/get-task-list`, payload, res => {
+ io.get(`projects/${state.projectCode}/process/get-task-list`, payload, res => {
resolve(res.data)
}).catch(e => {
reject(e)
@@ -842,5 +836,14 @@ export default {
reject(e)
})
})
+ },
+ genTaskCodeList ({ state }, payload) {
+ return new Promise((resolve, reject) => {
+ io.get(`projects/${state.projectCode}/task/gen-task-code-list`, payload, res => {
+ resolve(res.data)
+ }).catch(e => {
+ reject(e)
+ })
+ })
}
}
diff --git a/dolphinscheduler-ui/src/js/conf/home/store/dag/mutations.js b/dolphinscheduler-ui/src/js/conf/home/store/dag/mutations.js
index 010a860..b974fed 100755
--- a/dolphinscheduler-ui/src/js/conf/home/store/dag/mutations.js
+++ b/dolphinscheduler-ui/src/js/conf/home/store/dag/mutations.js
@@ -64,10 +64,10 @@ export default {
state.timeout = payload
},
/**
- * set tenantId
+ * set tenantCode
*/
- setTenantId (state, payload) {
- state.tenantId = payload
+ setTenantCode (state, payload) {
+ state.tenantCode = payload
},
/**
* set global params
@@ -108,13 +108,12 @@ export default {
* reset params
*/
resetParams (state, payload) {
- $('#canvas').html('')
state.globalParams = (payload && payload.globalParams) || []
state.tasks = (payload && payload.tasks) || []
state.name = (payload && payload.name) || ''
state.description = (payload && payload.description) || ''
state.timeout = (payload && payload.timeout) || 0
- state.tenantId = (payload && payload.tenantId) || -1
+ state.tenantCode = (payload && payload.tenantCode) || ''
state.processListS = (payload && payload.processListS) || []
state.resourcesListS = (payload && payload.resourcesListS) || []
state.resourcesListJar = (payload && payload.resourcesListJar) || []
@@ -126,48 +125,23 @@ export default {
},
/**
* add task
- * object {}
+ * @param {Task} task
*/
- addTasks (state, payload) {
- const i = _.findIndex(state.tasks, v => v.id === payload.id)
+ addTask (state, task) {
+ const i = _.findIndex(state.tasks, v => v.code === task.code)
if (i !== -1) {
- state.tasks[i] = Object.assign(state.tasks[i], {}, payload)
+ state.tasks[i] = Object.assign(state.tasks[i], {}, task)
} else {
- state.tasks.push(payload)
+ state.tasks.push(task)
}
- if (state.cacheTasks[payload.id]) {
- state.cacheTasks[payload.id] = Object.assign(state.cacheTasks[payload.id], {}, payload)
- } else {
- state.cacheTasks[payload.id] = payload
- }
- const dom = $(`#${payload.id}`)
- state.locations[payload.id] = _.assign(state.locations[payload.id], {
- name: dom.find('.name-p').text(),
- targetarr: dom.attr('data-targetarr'),
- nodenumber: dom.attr('data-nodenumber'),
- x: parseInt(dom.css('left'), 10),
- y: parseInt(dom.css('top'), 10)
- })
- },
- addConnects (state, payload) {
- state.connects = _.map(state.connects, v => {
- if (v.endPointSourceId === payload.sourceId && v.endPointTargetId === payload.targetId) {
- v.label = payload.labelName
- }
- return v
- })
},
/**
- * Cache the input
- * @param state
- * @param payload
+ * remove task
+ * @param {object} state
+ * @param {string} code
*/
- cacheTasks (state, payload) {
- if (state.cacheTasks[payload.id]) {
- state.cacheTasks[payload.id] = Object.assign(state.cacheTasks[payload.id], {}, payload)
- } else {
- state.cacheTasks[payload.id] = payload
- }
+ removeTask (state, code) {
+ state.tasks = state.tasks.filter(task => task.code !== code)
},
resetLocalParam (state, payload) {
const tasks = state.tasks
diff --git a/dolphinscheduler-ui/src/js/conf/home/store/dag/state.js b/dolphinscheduler-ui/src/js/conf/home/store/dag/state.js
index 4843ad9..b04c54f 100644
--- a/dolphinscheduler-ui/src/js/conf/home/store/dag/state.js
+++ b/dolphinscheduler-ui/src/js/conf/home/store/dag/state.js
@@ -39,11 +39,11 @@ export default {
cacheTasks: {},
// Timeout alarm
timeout: 0,
- // tenant id
- tenantId: -1,
+ // tenant code
+ tenantCode: '',
// Node location information
locations: {},
- // Node-to-node connection
+ // Node relations
connects: [],
// Running sign
runFlag: '',