Forráskód Böngészése

Quick optimizations and last corrections

luis 7 éve
szülő
commit
665df4a79f

+ 3 - 1
TODO.md

@@ -1,12 +1,14 @@
 # TODO
 
+## Deprecated
+
 ## Ideas
 
 * Make editor importable to any vue UI
 * Consider adding f.Err again
 
 * [ ] FlowServer: Maintain flow to keep variables
-* [ ] Create a special operator "var" to handle local data
+* [x] Create a special operator "var" to handle local data
 * [x] triggers, vertical slots in nodes, handling events giving the possibility
       to trigger execution of subsequent nodes based on links
 * [ ] handle Trigger activity to show highlighted trigger

+ 0 - 1
browser/vue-flow/src/assets/default-theme.css

@@ -309,7 +309,6 @@ input::placeholder {
 .flow-node__socket-detail {
   font-size: 12px;
   font-weight: 100;
-  transition: all var(--transition-speed);
   fill: var(--normal);
 }
 

+ 44 - 41
browser/vue-flow/src/assets/doc/readme.md

@@ -185,47 +185,6 @@ node
 
 > WIP
 
-## TODO
-
-### Readme
-
-> this is a simple markdown which is rendered to html during compile time with
-> webpack using markdown-loader and highlight-loader, the left menu is generated by analysing
-> the html h1,h2,h3,h4 tags
-
-* Fix any typos bad English etc...
-* Create an explanation of the project inspiration/goals
-* describe milestones
-
-### UX/UI
-
-* UX/UI: Create Undo behaviour, Possibly easy since this is using vuex (centralized state management)
-* UX/UI: Special visualisers/nodes to display information (images, datatables, graphs);
-* UX/UI: Ability to group nodes into a single box exposing inputs and outputs;
-* UX/UI: Implement touch;
-* UX/UI: Drop link in node to link to the next compatible input;
-* UX/UI: Find a way to highlight/linked portals for easy user reference
-* UX/UI: Multiple selection inspecting [idea](#multiple-node-editing)
-* UX/UI: Dynamic Context menu
-* ~~UX/UI: Portals to clean graph crossing~~ (testing);
-* ~~UX/UI: `Shift` key to merge group selections~~;
-
-### Packages
-
-* FlowPkg: Create training mechanism;
-* FlowPkg: Machine learning examples;
-* FlowPkg: Generate go code to maximize call performance;
-
-### Backend
-
-* Backend: Export/Deploy a model to a training cluster;
-* Backend: Expose the model possibly via an Rest API for easy function access;
-
-### Other
-
-* Collaboration: Better concurrent editing/message passing;
-* Flow: Proper documentation;
-
 ## Ideas
 
 ### Matching types
@@ -287,6 +246,50 @@ would be good to have the same by right clicking in other subjects:
   * toggle Show Triggers
   * Reset view
 
+## TODO
+
+### Readme
+
+> this is a simple markdown which is rendered to html during compile time with
+> webpack using markdown-loader and highlight-loader, the left menu is generated by analysing
+> the html h1,h2,h3,h4 tags
+
+* Fix any typos bad English etc...
+* Create an explanation of the project inspiration/goals
+* describe milestones
+
+### UX/UI
+
+* UX/UI: Create Undo behaviour, Possibly easy since this is using vuex (centralized state management)
+* UX/UI: Special visualisers/nodes to display information (images, datatables, graphs);
+* UX/UI: Ability to group nodes into a single box exposing inputs and outputs;
+* UX/UI: Implement touch;
+* UX/UI: Drop link in node to link to the next compatible input;
+* UX/UI: Find a way to highlight/linked portals for easy user reference
+* UX/UI: Multiple selection inspecting [idea](#multiple-node-editing)
+* UX/UI: Dynamic Context menu
+* UX/UI: link/node animation synchronization on collaborative environment
+* ~~UX/UI: Portals to clean graph crossing~~ (testing);
+* ~~UX/UI: `Shift` key to merge group selections~~;
+
+### Packages
+
+* FlowPkg: Create training mechanism;
+* FlowPkg: Machine learning examples;
+* FlowPkg: Generate go code to maximize call performance;
+
+### Backend
+
+* Backend: Export/Deploy a model to a training cluster;
+* Backend: Expose the model possibly via an Rest API for easy function access;
+
+### Other
+
+* Collaboration: Better concurrent editing/message passing;
+* Flow: Proper documentation;
+
+---
+
 ## Changelog
 
 18/02/2018

+ 2 - 2
browser/vue-flow/src/assets/lines-theme.css

@@ -82,11 +82,11 @@
 }
 
 .lines .flow-node__label {
-  fill: black;
+  fill: var(--normal);
 }
 
 .lines .flow-node--selected .flow-node__label {
-  fill: var(--normal) !important;
+  fill: var(--normal);
 }
 
 .lines .flow-panel__selector {

+ 5 - 45
browser/vue-flow/src/components/flow/editor.js

@@ -64,49 +64,9 @@ export default {
         }
       }
       return highlight
-    },
-    triggerProps () {
-      return (trigger) => {
-        if (!this.$refs.nodes) return
-        // For size .x .y
-        const nodeFrom = this.nodeById(trigger.from)
-        const nodeTo = this.nodeById(trigger.to)
-
-        const refFrom = this.$refs.nodes.find(n => n.id === trigger.from)
-        const refTo = this.$refs.nodes.find(n => n.id === trigger.to)
-        if (!refFrom || !refTo) { // delete trigger
-          return {}
-        }
-
-        const fromOutput = {
-          x: 0,
-          y: refFrom.bodyProps.height / 2
-        }
-        const toInput = {
-          x: 0,
-          y: -refTo.bodyProps.height / 2
-        }
-
-        return {
-          x1: nodeFrom.x + fromOutput.x,
-          y1: nodeFrom.y + fromOutput.y,
-          x2: nodeTo.x + toInput.x,
-          y2: nodeTo.y + toInput.y,
-          status: this.activity.nodes[nodeFrom.id] && this.activity.nodes[nodeFrom.id].status
-        }
-      }
-    }
-  },
-  watch: {
-    'activity' () {
-      this.activityUpdate()
     }
   },
   mounted () {
-    console.log('Mounted')
-    this.$nextTick(() => {
-      this.$forceUpdate()
-    })
     document.addEventListener('keydown', this.keyDown)
     document.addEventListener('keyup', this.keyUp)
   },
@@ -123,10 +83,6 @@ export default {
       'LINK_ADD', 'LINK_REMOVE',
       'TRIGGER_ADD', 'TRIGGER_REMOVE' ]),
 
-    activityUpdate: _debounce(function () {
-      console.log('Activity updated')
-    }, 1500),
-
     keyDown (ev) {
       if (document.activeElement && document.activeElement.matches('input,textarea')) { return }
       if (ev.shiftKey) {
@@ -144,6 +100,7 @@ export default {
         case 'Delete':
           if (Object.keys(this.nodeSelection).length === 0) { return }
           this.NODE_REMOVE(this.nodeSelection)
+          this.NODE_SELECTION_CLEAR()
           break
         case 'a':
           if (ev.ctrlKey) {
@@ -173,10 +130,12 @@ export default {
       const p = this.transformedPoint(ev.clientX, ev.clientY)
       this.pointerLink.pointer = p
       if (isInput) {
+        this.pointerLink.from = null
         this.pointerLink.to = nodeId
         this.pointerLink.in = socket.in
       } else {
         this.pointerLink.from = nodeId
+        this.pointerLink.to = null
       }
       if (isInput) {
         this.pointerLink.src = {nodeId: nodeId, type: this.registry[node.src].inputs[socket.in].type, in: socket.in}
@@ -269,9 +228,11 @@ export default {
       const isInput = (dir === 'in')
 
       if (isInput) {
+        this.pointerTriggerLink.from = null
         this.pointerTriggerLink.to = nodeId
       } else {
         this.pointerTriggerLink.from = nodeId
+        this.pointerTriggerLink.to = null
       }
       this.pointerTriggerLink.src = {nodeId: nodeId, dir: dir}
       this.pointerTriggerLink.pointer = this.transformedPoint(ev.clientX, ev.clientY)
@@ -327,7 +288,6 @@ export default {
       this.$emit('nodeInspect', nodeId, force)
     },
 
-    // HERE
     nodePointerDown (ev, nodeId) {
       document.activeElement && document.activeElement.blur()
       const tnode = this.nodeById(nodeId)

+ 1 - 1
browser/vue-flow/src/components/flow/editor.vue

@@ -19,7 +19,7 @@
         v-model="panzoom">
 
         <flow-link
-          v-for="(l,i) in nodeData.links"
+          v-for="l of nodeData.links"
           :key="'link' + l.to + l.in"
           :link="l"
           @mousedown.middle="LINK_REMOVE(l)"

+ 9 - 4
browser/vue-flow/src/components/flow/link.vue

@@ -19,6 +19,7 @@
 <script>
 import {mapGetters, mapActions} from 'vuex'
 
+const zeroPos = {x: 0, y: 0}
 const curve = 100
 export default {
   name: 'FlowLink',
@@ -43,8 +44,12 @@ export default {
         }
       }
       const nodeFrom = this.nodeById(this.link.from)
+      if (!this.link.from || !nodeFrom) {
+        console.log('Unexpected BROKEN LINK', this.link)
+        this.LINK_REMOVE(this.link)
+        return zeroPos
+      }
       const fromOutput = this.nodeOutputPos(nodeFrom, 0)
-
       return {
         x: nodeFrom.x + fromOutput.x + 7,
         y: nodeFrom.y + fromOutput.y
@@ -58,10 +63,10 @@ export default {
         }
       }
       const nodeTo = this.nodeById(this.link.to)
-      if (this.link.to === undefined) {
+      if (!this.link.to === undefined || !nodeTo) {
         console.log('Unexpected BROKEN LINK', this.link)
         this.LINK_REMOVE(this.link)
-        return {x: 0, y: 0}
+        return zeroPos
       }
       const toInput = this.nodeInputPos(nodeTo, this.link.in)
       return {
@@ -141,7 +146,7 @@ export default {
 
 .flow-view:not(.activity)
 .flow-link *{
-  transition: all var(--transition-speed-fast);
+  transition: all var(--transition-speed);
 }
 
 .flow-link__area {

+ 0 - 1
browser/vue-flow/src/components/flow/node-activity.vue

@@ -101,7 +101,6 @@ export default {
   },
   watch: {
     nodeActivity (val, oldVal) {
-      console.log('Activity updated')
       this.recalcStartTime()
     }
   },

+ 2 - 1
browser/vue-flow/src/components/flow/node-size.js

@@ -1,3 +1,4 @@
+
 import store from '@/store'
 import utils from '@/utils/utils'
 
@@ -11,7 +12,7 @@ export default {
     },
     'portal': {
       textWrap: 'white-space',
-      eDim: {x: 0, y: 0, width: 40, height: 40}
+      eDim: {x: -20, y: -20, width: 40, height: 40}
     },
     default: {
       textWrap: 'white-space'

+ 21 - 47
browser/vue-flow/src/components/flow/node.vue

@@ -6,7 +6,7 @@
       'flow-node--selected': !!nodeSelection[node.id]
     }"
     :status="status"
-    :transform="'translate(' + node.x + ',' + node.y +')'"
+    :transform="nodePos"
     @mousedown.stop.prevent="nodePointerDown"
     @contextmenu.capture.prevent="nodeRightClick"
     @dblclick="nodeDoubleClick"
@@ -54,7 +54,8 @@
       ref="label"
       class="flow-node__label"
       v-bind="labelProps"
-      text-anchor="middle">
+      text-anchor="middle"
+      dominant-baseline="middle">
       <tspan
         :key="'label-wrap' + i"
         x="0"
@@ -100,10 +101,10 @@
       class="flow-node__socket flow-node__socket--outputs"
     >
       <circle r="5" />
-      <!--<rect
+      <rect
         v-bind="outputLabelBGProps(0)"
         class="flow-node__socket-detail--background"
-        />-->
+      />
       <text
         ref="outputLabel"
         class="flow-node__socket-detail"
@@ -120,7 +121,7 @@
       :data-nodeid="node.id"
       data-dir="in"
       :x="-5"
-      :y="-bodyProps.height/2-5"
+      :y="-bodyProps.height/2-2"
       width="10"
       height="10"
       @mousedown.stop.prevent="triggerPointerDown($event, 'in')"
@@ -131,7 +132,7 @@
       :data-nodeid="node.id"
       data-dir="out"
       :x="-5"
-      :y="bodyProps.height/2 -5"
+      :y="bodyProps.height/2 -7"
       width="10"
       height="10"
       @mousedown.stop.prevent="triggerPointerDown($event, 'out')"
@@ -167,21 +168,13 @@ export default {
     'pointerLink': {type: Object, default: null},
     'pointerTriggerLink': {type: Object, default: null},
     'dragging': {type: Object, default: null}
-    // 'activity': {type: Object, default: () => {}},
-    // 'nodeStyle': {type: Object, default: () => {}}
-  },
-  data () {
-    return {
-      // maintain reference here?
-      inputLabelRect: [],
-      outputLabelRect: [],
-      labelRect: {x: 0, y: 0, width: 0, height: 0}
-      // bodyRect: {x: 0, y: 0, width: 0, height: 0}
-    }
   },
   computed: {
     ...mapGetters('flow', ['nodeCache', 'nodeData', 'registry', 'activity', 'nodeById', 'nodeSelection', 'nodeInputPos', 'nodeOutputPos']),
 
+    nodePos () {
+      return `translate(${this.node.x}, ${this.node.y})`
+    },
     nodeDim () {
       return this.nodeCache[this.node.id].dim
     },
@@ -211,12 +204,12 @@ export default {
       return utils.textWrap(this.node.label, wrapThreshold, opt.textWrap)
     },
     labelProps () {
+      const ldim = nodeSize.labelDim(this.node)
       return {
         x: 0,
         y: 0,
         fill: this.textColor,
-        // transform: `translate(${-this.labelRect.width / 2},${-this.labelRect.height / 2})`
-        transform: `translate(0,${-this.labelRect.height / 2})`
+        transform: `translate(0,${-ldim.height / 2 - 5})`
       }
     },
     bodyProps () {
@@ -336,26 +329,6 @@ export default {
       }
     }
   },
-  watch: {
-    // the only thing now that affects geometry
-    'node.label' (val, oldVal) {
-      if (val === oldVal) { return }
-      this.$nextTick(() => {
-        this.labelRect = this.$refs.label.getBBox()
-      })
-    }
-  },
-  mounted () {
-    // After render
-    this.$nextTick(() => { // after mount we reupdate with new values
-      if (!this.$refs.label) return
-      this.labelRect = this.$refs.label.getBBox()
-      this.$forceUpdate()
-    })
-  },
-  udpated () {
-    console.log('Node update')
-  },
   methods: {
     nodePointerDown (ev) {
       this.$emit('nodePointerDown', ev)
@@ -387,12 +360,12 @@ export default {
 }
 
 .flow-view:not(.activity) .flow-node {
-  transition: all var(--transition-speed-fast);
+  transition: all var(--transition-speed);
 }
 
 .flow-node__body {
   opacity:0.9;
-  transition: all var(--transition-speed-fast);
+  transition: all var(--transition-speed);
 }
 
 .flow-node[status=running] .flow-node__body{
@@ -414,7 +387,7 @@ export default {
   font-size:15px;
   opacity:0;
   fill: var(--normal);
-  transition: all var(--transition-speed-fast);
+  transition: all var(--transition-speed);
 }
 
 .flow-linking .flow-node__src-detail {
@@ -426,7 +399,7 @@ export default {
   pointer-events: none;
   stroke-width:1;
   opacity:0;
-  transition: all var(--transition-speed-fast);
+  transition: all var(--transition-speed);
 }
 
 .flow-view:not(.activity) .flow-node__socket:hover {
@@ -438,12 +411,13 @@ export default {
   opacity:1;
   stroke-width:0 !important;
   fill: #fff !default;
-  transition: all var(--transition-speed-fast);
+  transition: all var(--transition-speed);
 }
 
 .flow-node__socket-detail--background {
   stroke-width:0;
-  transition:all var(--transition-speed-fast);
+
+  /*transition: all var(--transition-speed);*/
 }
 
 .flow-node__socket--match {
@@ -470,7 +444,7 @@ export default {
 .flow-node__trigger {
   pointer-events:none;
   opacity:0;
-  transition: all var(--transition-speed-fast);
+  transition: all var(--transition-speed);
 }
 
 .flow-triggers .flow-node__trigger {
@@ -507,8 +481,8 @@ for hidden
   stroke: var(--node-selection);
   stroke-dasharray:2,2;
   pointer-events:none;
-  transition: all var(--transition-speed-fast);
   fill: var(--node-selection);
+  transition: all var(--transition-speed);
 }
 
 .flow-node--selected .flow-node__selection {

+ 3 - 3
browser/vue-flow/src/components/flow/panzoom.vue

@@ -124,9 +124,9 @@ export default {
   fill:transparent;
 }
 
-/*.flow-pan-zoom__transformed {
-  transition: transform 0.15s ease;
-}*/
+.flow-pan-zoom__transformed {
+  /*transition: transform 0.45s ease;*/
+}
 
 .flow-pan-zoom__grid {
   fill:transparent;

+ 4 - 0
browser/vue-flow/src/store/flow/actions.js

@@ -26,6 +26,7 @@ export default {
   },
   [m.NODE_REMOVE] (ctx, nodes) {
     ctx.commit(m.NODE_REMOVE, nodes)
+    // ctx.commit(m.NODE_SELECTION_REMOVE, nodes)
     flowService.nodeRemove(nodes)
     ctx.dispatch(m.DOCUMENT_SYNC)
   },
@@ -38,6 +39,9 @@ export default {
   [m.NODE_SELECTION_CLEAR] (ctx) {
     ctx.commit(m.NODE_SELECTION_CLEAR)
   },
+  [m.NODE_SELECTION_REMOVE] (ctx, nodes) {
+    ctx.commit(m.NODE_SELECTION_REMOVED, nodes)
+  },
   [m.NODE_SELECTION_ADD] (ctx, nodes) {
     ctx.commit(m.NODE_SELECTION_ADD, nodes)
   },

+ 1 - 1
browser/vue-flow/src/store/flow/mutation-types.js

@@ -4,7 +4,7 @@ var actions = [
   'DOCUMENT_UPDATE', 'DOCUMENT_SYNC',
   'ACTIVITY_UPDATE',
   'NODE_RAISE', 'NODE_UPDATE', 'NODE_ADD', 'NODE_REMOVE', 'NODE_INSPECT', 'NODE_PROCESS', 'NODE_TRAIN',
-  'NODE_SELECTION_CLEAR', 'NODE_SELECTION_ADD',
+  'NODE_SELECTION_CLEAR', 'NODE_SELECTION_REMOVE', 'NODE_SELECTION_ADD',
   'LINK_ADD', 'LINK_REMOVE',
   'TRIGGER_ADD', 'TRIGGER_REMOVE',
   'NOTIFICATION_ADD', 'NOTIFICATION_CLEAR'

+ 17 - 7
browser/vue-flow/src/store/flow/mutations.js

@@ -10,12 +10,12 @@ function updateNodeCache (state, nodes) {
       if (state.nodeCache[node.id].label === node.label) {
         continue
       }
-
       state.nodeCache[node.id].dim = nodeSize.nodeDim(node)
     }
     return
   }
   // Rebuild Full cache
+  state.nodeCache = {}
   for (let k in state.nodeData.nodes) {
     const node = state.nodeData.nodes[k]
     Vue.set(state.nodeCache, node.id, {
@@ -39,6 +39,12 @@ export default {
     // new ones will be added
     state.nodeData = nodeData
     updateNodeCache(state)
+    // Delete selected unexistent nodes
+    for (let k in state.nodeSelection) {
+      if (!state.nodeCache[k]) {
+        Vue.delete(state.nodeSelection, k)
+      }
+    }
   },
   [m.ACTIVITY_UPDATE] (state, activity) {
     state.activity = activity
@@ -58,12 +64,10 @@ export default {
     // If array
     for (let k in nodes) {
       const node = nodes[k]
-      const ni = state.nodeCache[node.id]
-      if (ni === null) continue
-
+      const cached = state.nodeCache[node.id]
+      if (cached === null) continue
       // Object.assign(state.nodeData.nodes[ni], node)
-      Object.assign(ni.node, node)
-
+      Object.assign(cached.node, node)
       // Vue.set(state.nodeData.nodes, ni, node)
       if (node.id === state.nodeInspect.id) {
         // Update node inspect
@@ -84,7 +88,7 @@ export default {
       state.nodeData.links = state.nodeData.links
         .filter(l => l.from !== node.id && l.to !== node.id)
       state.nodeData.triggers = state.nodeData.triggers
-        .filter(l => l.from !== node.id && l.to !== node.id)
+        .filter(t => t.from !== node.id && t.to !== node.id)
       state.nodeData.nodes.splice(ni, 1)
     }
     updateNodeCache(state)
@@ -96,6 +100,12 @@ export default {
   [m.NODE_SELECTION_CLEAR] (state) {
     state.nodeSelection = {}
   },
+  [m.NODE_SELECTION_REMOVE] (state, nodes) {
+    for (let k in nodes) {
+      const n = nodes[k]
+      Vue.delete(state.nodeSelection, n.id)
+    }
+  },
   [m.NODE_SELECTION_ADD] (state, nodes) {
     for (let k in nodes) {
       const n = nodes[k]