|
@@ -2,27 +2,22 @@ import {mapGetters, mapActions} from 'vuex'
|
|
import FlowNode from './node'
|
|
import FlowNode from './node'
|
|
import FlowLink from './link'
|
|
import FlowLink from './link'
|
|
import FlowTriggerLink from './link-trigger'
|
|
import FlowTriggerLink from './link-trigger'
|
|
-
|
|
|
|
import FlowPanZoom from './panzoom'
|
|
import FlowPanZoom from './panzoom'
|
|
|
|
+import FlowModalData from './modal-data' // NEW 15/02/2018
|
|
import HxContextMenu from '@/components/shared/hx-contextmenu'
|
|
import HxContextMenu from '@/components/shared/hx-contextmenu'
|
|
import SvgDefs from './svgdefswrapper'
|
|
import SvgDefs from './svgdefswrapper'
|
|
import utils from '@/utils/utils'
|
|
import utils from '@/utils/utils'
|
|
|
|
|
|
export default {
|
|
export default {
|
|
name: 'FlowManager',
|
|
name: 'FlowManager',
|
|
- components: {FlowNode, FlowLink, FlowTriggerLink, FlowPanZoom, HxContextMenu, SvgDefs},
|
|
|
|
|
|
+ components: {FlowNode, FlowLink, FlowTriggerLink, FlowPanZoom, FlowModalData, HxContextMenu, SvgDefs},
|
|
props: {
|
|
props: {
|
|
'width': {type: String, default: '800px'},
|
|
'width': {type: String, default: '800px'},
|
|
'height': {type: String, default: '600px'}
|
|
'height': {type: String, default: '600px'}
|
|
},
|
|
},
|
|
data () {
|
|
data () {
|
|
- // const cloned = JSON.parse(JSON.stringify(this.value)) // initial?
|
|
|
|
return {
|
|
return {
|
|
panzoom: { x: 0, y: 0, zoom: 1 },
|
|
panzoom: { x: 0, y: 0, zoom: 1 },
|
|
-
|
|
|
|
- // Shared state
|
|
|
|
- // nodeData: { nodes: [], links: [], triggers: [] },
|
|
|
|
-
|
|
|
|
dragging: null,
|
|
dragging: null,
|
|
linking: false,
|
|
linking: false,
|
|
triggerLinking: false,
|
|
triggerLinking: false,
|
|
@@ -31,7 +26,6 @@ export default {
|
|
pointerTriggerLink: {active: false, props: {}, src: {}},
|
|
pointerTriggerLink: {active: false, props: {}, src: {}},
|
|
|
|
|
|
selector: null,
|
|
selector: null,
|
|
- nodeSelection: {}, // map of true false
|
|
|
|
|
|
|
|
stickySockets: false,
|
|
stickySockets: false,
|
|
stickyTriggers: false,
|
|
stickyTriggers: false,
|
|
@@ -39,7 +33,7 @@ export default {
|
|
}
|
|
}
|
|
},
|
|
},
|
|
computed: {
|
|
computed: {
|
|
- ...mapGetters('flow', ['registry', 'activity', 'nodeData', 'nodeById']),
|
|
|
|
|
|
+ ...mapGetters('flow', ['registry', 'activity', 'nodeData', 'nodeById', 'nodeSelection']),
|
|
outputNode () {
|
|
outputNode () {
|
|
const n = this.nodeData.nodes.find(n => n.src === 'Output')
|
|
const n = this.nodeData.nodes.find(n => n.src === 'Output')
|
|
|
|
|
|
@@ -157,6 +151,7 @@ export default {
|
|
'NOTIFICATION_ADD',
|
|
'NOTIFICATION_ADD',
|
|
'DOCUMENT_SYNC',
|
|
'DOCUMENT_SYNC',
|
|
'NODE_RAISE', 'NODE_UPDATE', 'NODE_ADD', 'NODE_REMOVE', 'NODE_INSPECT', 'NODE_PROCESS', 'NODE_TRAIN',
|
|
'NODE_RAISE', 'NODE_UPDATE', 'NODE_ADD', 'NODE_REMOVE', 'NODE_INSPECT', 'NODE_PROCESS', 'NODE_TRAIN',
|
|
|
|
+ 'NODE_SELECTION_ADD', 'NODE_SELECTION_CLEAR',
|
|
'LINK_ADD', 'LINK_REMOVE',
|
|
'LINK_ADD', 'LINK_REMOVE',
|
|
'TRIGGER_ADD', 'TRIGGER_REMOVE' ]),
|
|
'TRIGGER_ADD', 'TRIGGER_REMOVE' ]),
|
|
|
|
|
|
@@ -168,32 +163,23 @@ export default {
|
|
}
|
|
}
|
|
|
|
|
|
let single = null
|
|
let single = null
|
|
- const selectionIds = Object.keys(this.nodeSelection)
|
|
|
|
- if (selectionIds.length === 1) { single = this.nodeSelection[selectionIds[0]] }
|
|
|
|
|
|
+ if (Object.keys(this.nodeSelection).length === 1) { single = this.nodeSelection[Object.keys(this.nodeSelection)[0]] }
|
|
switch (ev.key) {
|
|
switch (ev.key) {
|
|
case 'Enter':
|
|
case 'Enter':
|
|
if (!single) { return }
|
|
if (!single) { return }
|
|
this.nodeInspect(single, true)
|
|
this.nodeInspect(single, true)
|
|
break
|
|
break
|
|
case 'Delete':
|
|
case 'Delete':
|
|
- if (!this.nodeSelection) { return }
|
|
|
|
|
|
+ if (Object.keys(this.nodeSelection).length === 0) { return }
|
|
console.log('Removing nodes:', this.nodeSelection)
|
|
console.log('Removing nodes:', this.nodeSelection)
|
|
this.NODE_REMOVE(this.nodeSelection)
|
|
this.NODE_REMOVE(this.nodeSelection)
|
|
- // for (let k in this.nodeSelection) {
|
|
|
|
- // this.nodeRemove(this.nodeSelection[k])
|
|
|
|
- // }
|
|
|
|
break
|
|
break
|
|
case 'a':
|
|
case 'a':
|
|
if (ev.ctrlKey) {
|
|
if (ev.ctrlKey) {
|
|
ev.preventDefault()
|
|
ev.preventDefault()
|
|
ev.stopPropagation()
|
|
ev.stopPropagation()
|
|
-
|
|
|
|
- this.nodeSelection = {}
|
|
|
|
- for (let n of this.nodeData.nodes) {
|
|
|
|
- this.nodeSelection[n.id] = n
|
|
|
|
- }
|
|
|
|
|
|
+ this.NODE_SELECTION_ADD(this.nodeData.nodes)
|
|
}
|
|
}
|
|
-
|
|
|
|
break
|
|
break
|
|
}
|
|
}
|
|
},
|
|
},
|
|
@@ -409,24 +395,63 @@ export default {
|
|
this.nodeInspect(tnode)
|
|
this.nodeInspect(tnode)
|
|
|
|
|
|
// Switch selection
|
|
// Switch selection
|
|
- if (!this.nodeSelection[tnode.id] && !ev.ctrlKey) this.nodeSelection = {}
|
|
|
|
- this.nodeSelection[tnode.id] = tnode
|
|
|
|
- // we can handle with nodeId and a search
|
|
|
|
-
|
|
|
|
|
|
+ if (!this.nodeSelection[tnode.id] && !ev.ctrlKey) {
|
|
|
|
+ this.NODE_SELECTION_CLEAR()
|
|
|
|
+ }
|
|
|
|
+ this.NODE_SELECTION_ADD([tnode])
|
|
this.NODE_RAISE(this.nodeSelection)
|
|
this.NODE_RAISE(this.nodeSelection)
|
|
|
|
|
|
let curP = this.transformedPoint(ev.x, ev.y)
|
|
let curP = this.transformedPoint(ev.x, ev.y)
|
|
-
|
|
|
|
- this.dragging = this.nodeSelection
|
|
|
|
|
|
+ let clone = false
|
|
|
|
+ if (ev.ctrlKey && Object.keys(this.nodeSelection).length > 0) clone = true
|
|
utils.createDrag({
|
|
utils.createDrag({
|
|
drag: (ev) => {
|
|
drag: (ev) => {
|
|
- if (this.nodeSelection === undefined) {
|
|
|
|
- console.error('Well something went wrong')
|
|
|
|
|
|
+ /// /////////// IMPORTANT NEW ////////////////
|
|
|
|
+ // logic: we analyse selection, create new nodes based on same src
|
|
|
|
+ // with same things, and checkout the inner links, nodes between our nodes
|
|
|
|
+ // if all ok we link the new nodes aswell
|
|
|
|
+ // XXX: add a sub function for this, cloneSelection
|
|
|
|
+
|
|
|
|
+ if (clone && this.nodeSelection) {
|
|
|
|
+ clone = false
|
|
|
|
+ const nodeMap = {}
|
|
|
|
+ const newNodes = []
|
|
|
|
+ for (let k in this.nodeSelection) {
|
|
|
|
+ const n = this.nodeById(k)
|
|
|
|
+ if (n.src === 'Output') { // Do not clone output
|
|
|
|
+ continue
|
|
|
|
+ }
|
|
|
|
+ const newNode = JSON.parse(JSON.stringify(n))
|
|
|
|
+ newNode.id = utils.guid()
|
|
|
|
+ nodeMap[n.id] = newNode.id
|
|
|
|
+ newNodes.push(newNode)
|
|
|
|
+ }
|
|
|
|
+ this.NODE_ADD(newNodes)
|
|
|
|
+ // Clone links if inside the selection
|
|
|
|
+ for (let k in this.nodeSelection) {
|
|
|
|
+ const links = this.nodeData.links.filter(l => l.from === k)
|
|
|
|
+ if (!links) break
|
|
|
|
+ for (let l of links) {
|
|
|
|
+ if (this.nodeSelection[l.to]) { // Link is inside
|
|
|
|
+ const link = {
|
|
|
|
+ from: nodeMap[k],
|
|
|
|
+ to: nodeMap[l.to],
|
|
|
|
+ in: l.in
|
|
|
|
+ }
|
|
|
|
+ this.LINK_ADD(link)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Check inner links
|
|
|
|
+
|
|
|
|
+ this.NODE_SELECTION_CLEAR()
|
|
|
|
+ this.NODE_SELECTION_ADD(newNodes)
|
|
}
|
|
}
|
|
|
|
+ this.dragging = this.nodeSelection
|
|
const dragP = this.transformedPoint(ev.x, ev.y)
|
|
const dragP = this.transformedPoint(ev.x, ev.y)
|
|
const nodeUpdate = []
|
|
const nodeUpdate = []
|
|
for (let k in this.nodeSelection) {
|
|
for (let k in this.nodeSelection) {
|
|
- // const n = this.nodeData.nodes.find(n => n.id === k)
|
|
|
|
const n = this.nodeById(k)
|
|
const n = this.nodeById(k)
|
|
// create new nodes
|
|
// create new nodes
|
|
nodeUpdate.push({
|
|
nodeUpdate.push({
|
|
@@ -436,30 +461,32 @@ export default {
|
|
})
|
|
})
|
|
}
|
|
}
|
|
this.NODE_UPDATE(nodeUpdate)
|
|
this.NODE_UPDATE(nodeUpdate)
|
|
- // this.sendFlowEvent('nodeUpdate', this.nodeSelection)
|
|
|
|
curP = dragP
|
|
curP = dragP
|
|
},
|
|
},
|
|
drop: (ev) => {
|
|
drop: (ev) => {
|
|
- // snap?
|
|
|
|
this.dragging = null
|
|
this.dragging = null
|
|
|
|
+ // snap?
|
|
// Snapping
|
|
// Snapping
|
|
const dragP = this.transformedPoint(ev.x, ev.y)
|
|
const dragP = this.transformedPoint(ev.x, ev.y)
|
|
const nodeUpdate = []
|
|
const nodeUpdate = []
|
|
for (let k in this.nodeSelection) {
|
|
for (let k in this.nodeSelection) {
|
|
- // const n = this.nodeData.nodes.find(n => n.id === k)
|
|
|
|
const n = this.nodeById(k)
|
|
const n = this.nodeById(k)
|
|
// create new nodes
|
|
// create new nodes
|
|
nodeUpdate.push({
|
|
nodeUpdate.push({
|
|
...n,
|
|
...n,
|
|
x: n.x + dragP.x - curP.x,
|
|
x: n.x + dragP.x - curP.x,
|
|
y: n.y + dragP.y - curP.y
|
|
y: n.y + dragP.y - curP.y
|
|
- // x: Math.round((n.x + dragP.x - curP.x) / 10) * 10, // snapping
|
|
|
|
- // y: Math.round((n.y + dragP.y - curP.y) / 10) * 10 // snapping
|
|
|
|
|
|
+ // snapping
|
|
|
|
+ // x: Math.round((n.x + dragP.x - curP.x) / 10) * 10,
|
|
|
|
+ // y: Math.round((n.y + dragP.y - curP.y) / 10) * 10
|
|
})
|
|
})
|
|
}
|
|
}
|
|
// Updating nodes
|
|
// Updating nodes
|
|
this.NODE_UPDATE(nodeUpdate)
|
|
this.NODE_UPDATE(nodeUpdate)
|
|
this.DOCUMENT_SYNC()
|
|
this.DOCUMENT_SYNC()
|
|
|
|
+ },
|
|
|
|
+ noDrag: (ev) => {
|
|
|
|
+ this.dragging = null
|
|
}
|
|
}
|
|
})
|
|
})
|
|
},
|
|
},
|
|
@@ -491,7 +518,7 @@ export default {
|
|
newNode.prop[k] = ''
|
|
newNode.prop[k] = ''
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- this.NODE_ADD(newNode)
|
|
|
|
|
|
+ this.NODE_ADD([newNode])
|
|
},
|
|
},
|
|
|
|
|
|
managerDrop (ev) {
|
|
managerDrop (ev) {
|
|
@@ -524,17 +551,24 @@ export default {
|
|
}
|
|
}
|
|
},
|
|
},
|
|
drop: (ev) => {
|
|
drop: (ev) => {
|
|
- if (!ev.shiftKey) this.nodeSelection = {}
|
|
|
|
|
|
+ if (!ev.shiftKey) this.NODE_SELECTION_CLEAR()
|
|
|
|
+ const nodesToSelect = []
|
|
for (let n in this.nodeData.nodes) {
|
|
for (let n in this.nodeData.nodes) {
|
|
const node = this.nodeData.nodes[n]
|
|
const node = this.nodeData.nodes[n]
|
|
if (node.x > this.selector.x && node.x < (this.selector.x + this.selector.width) &&
|
|
if (node.x > this.selector.x && node.x < (this.selector.x + this.selector.width) &&
|
|
node.y > this.selector.y && node.y < (this.selector.y + this.selector.height)
|
|
node.y > this.selector.y && node.y < (this.selector.y + this.selector.height)
|
|
) {
|
|
) {
|
|
- this.nodeSelection[node.id] = node
|
|
|
|
|
|
+ nodesToSelect.push(node)
|
|
|
|
+ // Add to selection
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ this.NODE_SELECTION_ADD(nodesToSelect)
|
|
this.selector = null
|
|
this.selector = null
|
|
- }})
|
|
|
|
|
|
+ },
|
|
|
|
+ noDrag: (ev) => {
|
|
|
|
+ if (!ev.shiftKey) this.NODE_SELECTION_CLEAR()
|
|
|
|
+ }
|
|
|
|
+ })
|
|
},
|
|
},
|
|
documentProcess () {
|
|
documentProcess () {
|
|
const n = this.nodeData.nodes.find(n => n.src === 'Output')
|
|
const n = this.nodeData.nodes.find(n => n.src === 'Output')
|
|
@@ -568,7 +602,7 @@ export default {
|
|
src: 'Portal From'
|
|
src: 'Portal From'
|
|
}
|
|
}
|
|
|
|
|
|
- this.NODE_ADD(portalNode)
|
|
|
|
|
|
+ this.NODE_ADD([portalNode])
|
|
},
|
|
},
|
|
// HELPERS depending on svg ref
|
|
// HELPERS depending on svg ref
|
|
createSVGPoint (x, y) {
|
|
createSVGPoint (x, y) {
|