Browse Source

Svg goodies, browswer compat

luis 7 years ago
parent
commit
3d6edbe73a

File diff suppressed because it is too large
+ 0 - 1
browser/vue-flow/src/assets/cog.svg


+ 0 - 6
browser/vue-flow/src/assets/ico/icons8-search.svg

@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 50 50" version="1.1" width="50px" height="50px">
-<g id="surface1">
-<path style=" " d="M 21 3 C 11.621094 3 4 10.621094 4 20 C 4 29.378906 11.621094 37 21 37 C 24.710938 37 28.140625 35.804688 30.9375 33.78125 L 44.09375 46.90625 L 46.90625 44.09375 L 33.90625 31.0625 C 36.460938 28.085938 38 24.222656 38 20 C 38 10.621094 30.378906 3 21 3 Z M 21 5 C 29.296875 5 36 11.703125 36 20 C 36 28.296875 29.296875 35 21 35 C 12.703125 35 6 28.296875 6 20 C 6 11.703125 12.703125 5 21 5 Z "/>
-</g>
-</svg>

File diff suppressed because it is too large
+ 0 - 4
browser/vue-flow/src/assets/ico/icons8-settings.svg


File diff suppressed because it is too large
+ 0 - 6
browser/vue-flow/src/assets/ico/icons8-user-male.svg


BIN
browser/vue-flow/src/assets/logo.png


+ 1 - 1
browser/vue-flow/src/assets/style.css

@@ -46,7 +46,7 @@ button::after,
 
 button:hover::after,
 .hover:hover::after {
-  opacity: 0.1;
+  opacity: 0.2;
 }
 
 ul {

+ 1 - 0
browser/vue-flow/src/components/flow/link.vue

@@ -55,6 +55,7 @@ export default {
 }
 .flow-link:hover .flow-link__visible {
   stroke: #F00;
+  filter: url(#highlight);
 }
 
 </style>

+ 101 - 105
browser/vue-flow/src/components/flow/manager.vue

@@ -1,78 +1,107 @@
 <template>
   <div class="flow-container">
+    <svg
+      xmlns="http://www.w3.org/2000/svg"
+      xmlns:xlink="http://www.w3.org/1999/xlink"
+      ref="svg"
+      class="view"
+      @dragover.prevent
+      @drop="managerDrop"
+      :width="width"
+      :height="height">
+      <defs>
+        <filter
+          id="highlight-border"
+          x="-100%"
+          y="-100%"
+          width="300%"
+          height="300%">
+          <feMorphology in="SourceGraphic" result="MORPH" operator="dilate" radius="1" />
+          <feColorMatrix in="MORPH" result="BORDER" type="matrix" values=".5 0 0 0 0, 0 .5 0 0 0, 0 0 .5 0 0, 0 0 0 1 0"/>
+          <feColorMatrix
+            result = "matrixOut"
+            in = "SourceGraphic"
+            type = "matrix"
+            values = ".2 0 0 0 0,  0 .2 0 0 0,  0 0 .2 0 0,  0 0 0 1 0"/>
+          <feGaussianBlur
+            result="blurOut"
+            in="matrixOut"
+            stdDeviation="2" />
+          <feMerge>
+            <feMergeNode in="blurOut"/>
+            <feMergeNode in="BORDER"/>
+            <feMergeNode in="SourceGraphic"/>
+          </feMerge>
 
-    <hx-split
-      dir="horizontal"
-      :resizeable="funcsResizeable"
-      :split="funcsActive?funcsSize:'0px'"
-      @onSplitResize="funcsSizeUpdate"
-    >
-      <flow-panel
-        :registry="registry"
-        @toggleResizeable="funcsResizeable=!funcsResizeable"
-      />
-      <div class="flow-svgcontainer">
-        <svg
-          xmlns="http://www.w3.org/2000/svg"
-          xmlns:xlink="http://www.w3.org/1999/xlink"
-          ref="svg"
-          class="view"
-          @dragover.prevent
-          @drop="managerDrop"
-          :width="width"
-          :height="height">
-          <flow-pan-zoom
-            ref="panzoom"
-            v-model="panzoom">
-            <flow-link
-              v-for="(link,i) in nodeData.links"
-              :key="i"
-              v-bind="linkProps(link)"
-              @click="linkRemove(link)"
-            />
-            <!-- mouse link-->
-            <flow-link
-              v-if="pointerLink.active"
-              v-bind="pointerLink.props"
-            />
-            <flow-node
-              ref="nodes"
-              v-for="(n,i) of nodeData.nodes"
-              v-bind="nodeProps(n)"
-              :key="'node' + n.id"
-              :id="n.id"
-              @nodePointerDown.prevent="nodeDragStart($event,i)"
-              @socketPointerDown="socketPointerDown(n.id,...arguments)"
-            />
-          </flow-pan-zoom>
-        </svg>
-        <div class="flow-svgcontainer__control">
-          <button
-            class="flow-funcs__toggle"
-            @click="funcsActive=!funcsActive">Panel</button>
-          <button
-          @click="panzoomReset">Reset view</button>
+        </filter>
+        <filter id="highlight" x="-100%" y="-100%" width="300%" height="300%">
+          <feColorMatrix
+            result = "matrixOut"
+            in = "SourceGraphic"
+            type = "matrix"
+            values = "2 0 0 0 0  0 2 0 0 0  0 0 2 0 0  0 0 0 1 0"/>
+          <feGaussianBlur
+            result="blurOut"
+            in="matrixOut"
+            stdDeviation="4" />
+          <feMerge>
+            <feMergeNode in="blurOut"/>
+            <feMergeNode in="WHITENED"/>
+            <feMergeNode in="SourceGraphic"/>
+          </feMerge>
 
-        </div>
-        <div class="flow-svgcontainer__info">
-          x:{{ panzoom.x.toFixed(2) }} y:{{ panzoom.y.toFixed(2) }} scale:{{ panzoom.zoom.toFixed(2) }}
-          nodes: {{ nodeData.nodes.length }}
-          links: {{ nodeData.links.length }}
-        </div>
-      </div> <!-- /svg-container-->
-    </hx-split>
+        </filter>
+
+        <filter id="drag-shadow" x="-100%" y="-100%" width="300%" height="300%">
+          <feDropShadow dx="0" dy="2" stdDeviation="3"/>
+        </filter>
+
+      </defs>
+      <flow-pan-zoom
+        ref="panzoom"
+        v-model="panzoom">
+        <flow-link
+          v-for="(link,i) in nodeData.links"
+          :key="i"
+          v-bind="linkProps(link)"
+          @click="linkRemove(link)"
+        />
+        <!-- mouse link-->
+        <flow-link
+          v-if="pointerLink.active"
+          v-bind="pointerLink.props"
+        />
+        <flow-node
+          ref="nodes"
+          v-for="(n,i) of nodeData.nodes"
+          v-bind="nodeProps(n)"
+          :key="'node' + n.id"
+          :id="n.id"
+          @nodePointerDown.prevent="nodeDragStart($event,i)"
+          @socketPointerDown="socketPointerDown(n.id,...arguments)"
+        />
+      </flow-pan-zoom>
+    </svg>
+    <div class="flow-container__control">
+      <button @click="$emit('funcsPanelToggle')">Panel</button>
+      <button @click="panzoomReset">Reset view</button>
+
+    </div>
+    <div class="flow-container__info">
+      x:{{ panzoom.x.toFixed(2) }} y:{{ panzoom.y.toFixed(2) }} scale:{{ panzoom.zoom.toFixed(2) }}
+      nodes: {{ nodeData.nodes.length }}
+      links: {{ nodeData.links.length }}
+    </div>
   </div>
 </template>
 <script>
-import FlowPanel from './panel'
 import FlowNode from './node'
 import FlowLink from './link'
 import FlowPanZoom from './panzoom'
-import HxSplit from '@/components/shared/hx-split'
 
 export default {
   name: 'FlowManager',
-  components: {FlowNode, FlowLink, FlowPanZoom, FlowPanel, HxSplit},
+  components: {FlowNode, FlowLink, FlowPanZoom},
   props: {
     'value': {type: Object, default: () => {}},
     'registry': {type: Object, default: () => {}},
@@ -82,9 +111,6 @@ export default {
   data () {
     // const cloned = JSON.parse(JSON.stringify(this.value)) // initial?
     return {
-      funcsSize: '200px',
-      funcsActive: true,
-      funcsResizeable: false,
       panzoom: { x: 0, y: 0, zoom: 1 },
       nodeData: { nodes: [], links: [] },
       dragging: null,
@@ -111,6 +137,7 @@ export default {
           inputs: nodeClass.inputs,
           output: nodeClass.output,
           match: match,
+          dragging: this.dragging === node,
           color: nodeClass.style && nodeClass.style.color,
           textColor: nodeClass.style && nodeClass.style.textColor
         }
@@ -169,9 +196,6 @@ export default {
     })
   },
   methods: {
-    funcsSizeUpdate (ev, size) {
-      this.funcsSize = size
-    },
     panzoomReset () {
       this.panzoom.x = 0
       this.panzoom.y = 0
@@ -390,26 +414,24 @@ function guid () {
 .flow-container {
   display:flex;
   flex-flow:row;
-}
-
-.flow-svgcontainer {
-  width:100%;
-  height:100%;
   position:relative;
 }
-.flow-svgcontainer__control {
+
+.flow-container__control {
   position:absolute;
-  top: 10px;
-  left: 10px;
+  top: 0px;
+  left: 0px;
   display:flex;
   justify-content: center;
   align-items: center;
 }
-.flow-svgcontainer__control button {
+.flow-container__control button {
   display:flex;
   justify-content: center;
+  margin:0;
+  padding:14px;
 }
-.flow-svgcontainer__info {
+.flow-container__info {
   position:absolute;
   bottom:10px;
   left:10px;
@@ -417,36 +439,10 @@ function guid () {
   font-size:8px;
   color: #777;
 }
-svg.view {
+.flow-container .svg.view {
   border:none;
   position:relative;
   fill:transparent;
 }
 
-.split .splitter{
-  flex-basis:0px;
-  position:relative;
-  background: rgba(208,208,208,0.9);
-}
-.split:not(.resizeable) .content:first-child {
-  transition: all .3s;
-}
-
-.split.resizeable.horizontal .splitter::after {
-  display:flex;
-  justify-content: center;
-  align-items: center;
-  z-index:100;
-  content:" ";
-  position:absolute;
-
-  top:20%;
-  bottom:20%;
-  left:0px;
-  width:20px;
-
-  background: rgba(0,0,0,0.4);
-  transition: all .3s;
-}
-
 </style>

+ 31 - 37
browser/vue-flow/src/components/flow/node.vue

@@ -7,8 +7,16 @@
     <rect
       ref="body"
       class="flow-node__body"
+      :class="{'flow-node__body--dragging':dragging}"
       v-bind="bodyProps"
     />
+    <text
+      ref="label"
+      class="flow-node__label"
+      v-bind="labelProps">
+      {{ label }}
+    </text>
+
     <!-- input -->
     <circle
       class="flow-node__socket flow-node__socket--inputs"
@@ -31,12 +39,6 @@
       v-bind="outputProps(0)"
       @mousedown.stop.prevent="socketPointerDown($event, {out:0})"
     />
-    <text
-      ref="label"
-      class="flow-node__label"
-      v-bind="labelProps">
-      {{ label }}
-    </text>
   </g>
 </template>
 
@@ -51,6 +53,7 @@ export default {
     'inputs': {type: Array, default: () => []},
     'output': {type: String, default: ''},
     'match': {type: Object, default: () => {}},
+    'dragging': {type: Boolean, default: false},
 
     'color': {type: String, default: '#777'},
     'textColor': {type: String, default: '#fff'}
@@ -59,7 +62,6 @@ export default {
   data () {
     return {
       // maintain reference here?
-      dragging: false,
       labelRect: {x: 0, y: 0, width: 0, height: 0},
       bodyRect: {x: 0, y: 0, width: 0, height: 0}
     }
@@ -104,17 +106,7 @@ export default {
           r: 6
         }
       }
-    },
-    outputPos () {
-      return (i) => {
-        const rect = this.bodyProps
-        return {
-          x: rect.x + rect.width,
-          y: 0
-        }
-      }
     }
-
   },
   watch: {
     // the only thing now that affects geometry
@@ -142,6 +134,13 @@ export default {
         y: this.bodyProps.y + d + (i * 2 * d)
       }
     },
+    outputPos (i) {
+      const rect = this.bodyProps
+      return {
+        x: rect.x + rect.width,
+        y: 0
+      }
+    },
     socketPointerDown (ev, socket) {
       this.$emit('socketPointerDown', ev, socket)
     }
@@ -151,43 +150,38 @@ export default {
 </script>
 <style lang="scss">
 .flow-node {
-  position:relative;
-}
-.flow-node__body {
-  // fill:#ddd;
-  stroke: rgba(190,0,0,0);
-  stroke-width:1;
-
-}
-.flow-node__body:hover,
-.flow-node.flow-node--dragging s-node__body {
   cursor:move;
-  stroke:rgba(190,0,0,1);
-  stroke-width:1;
-  transition: all .3s;
 }
-.flow-node.flow-node--dragging {
+.flow-node:hover {
+  filter: url(#highlight-border);
 }
 .flow-node__socket {
   fill: #AFAFAF;
   stroke: #AFAFAF;
-  stroke-width:2;
-
+  stroke-width:1;
   cursor:pointer;
   r:6;
+  transition:all .3s;
 }
 
 .flow-node__socket:hover {
-  stroke: #5F5FFF;
-  stroke-width:2;
+  stroke-width:5;
 }
 .flow-node__socket--match {
-  fill:green;
-  stroke:green;
+  stroke-width:5;
+  stroke:#2a2;
+  fill:#2a2;
+  filter: url(#highlight);
+}
+.flow-node__socket--match:hover {
+  stroke:#5F5;
+  fill:#5F5;
 }
 
 .flow-node__label {
+  stroke:none;
   pointer-events:none;
   user-select:none;
+  fill:white;
 }
 </style>

+ 62 - 12
browser/vue-flow/src/components/flowmain.vue

@@ -34,19 +34,33 @@
 
         <!--:value="nodeData"
         @input="documentUpdate"-->
-        <flow-manager
-          :registry="registry"
-          v-model="nodeData"
+        <hx-split
+          dir="horizontal"
+          :resizeable="funcsActive && funcsResizeable"
+          :split="funcsActive?funcsSize:'0px'"
+          @onSplitResize="funcsSizeUpdate"
 
-          @linkUpdate="sendFlowEvent('linkUpdate',$event)"
-          @linkRemove="sendFlowEvent('linkRemove',$event)"
+        >
+          <flow-panel
+            :registry="registry"
+            @toggleResizeable="funcsResizeable=!funcsResizeable"
+          />
 
-          @nodeUpdate="sendFlowEvent('nodeUpdate',$event)"
-          @nodeRemove="sendFlowEvent('nodeRemove',$event)"
-          @shouldPersist="sendDocumentUpdate"
+          <flow-manager
+            :registry="registry"
+            v-model="nodeData"
+            @funcsPanelToggle="funcsActive=!funcsActive"
 
-          width="100%"
-          height="100%"/>
+            @linkUpdate="sendFlowEvent('linkUpdate',$event)"
+            @linkRemove="sendFlowEvent('linkRemove',$event)"
+
+            @nodeUpdate="sendFlowEvent('nodeUpdate',$event)"
+            @nodeRemove="sendFlowEvent('nodeRemove',$event)"
+            @shouldPersist="sendDocumentUpdate"
+
+            width="100%"
+            height="100%"/>
+        </hx-split>
       </div>
       <div class="app-chat">
         <app-chat/>
@@ -57,12 +71,14 @@
 <script>
 import AppChat from '@/components/chat'
 import FlowManager from '@/components/flow/manager'
+import FlowPanel from './panel'
+import HxSplit from '@/components/shared/hx-split'
 import 'reset-css/reset.css'
 import '@/assets/style.css'
 // import nodeData from './nodedata'
 
 export default {
-  components: {FlowManager, AppChat},
+  components: {FlowManager, FlowPanel, HxSplit, AppChat},
   data () {
     return {
       registry: {
@@ -80,7 +96,12 @@ export default {
         'string': { group: 'Visualisation', inputs: ['string'], style: {'color': '#9a9'} },
         'lineGraph': { group: 'Visualisation', inputs: ['[]float32', '[]float32'], style: {'color': '#9a9'} }
       },
-      nodeData: {nodes: [], links: []}
+
+      nodeData: {nodes: [], links: []},
+      funcsSize: '200px',
+      funcsActive: true,
+      funcsResizeable: false
+
     }
   },
   mounted () {
@@ -119,6 +140,9 @@ export default {
     })
   },
   methods: {
+    funcsSizeUpdate (ev, size) {
+      this.funcsSize = size
+    },
     sendFlowEvent (type, param) {
       this.$flowService[type](param)
     },
@@ -174,6 +198,32 @@ export default {
   color: #f4f4f4;
   text-shadow: 1px 1px 1px rgba(255,255,255,0.5), -1px -1px 1px rgba(0,0,0,0.05);
 }
+.split .splitter{
+  flex-basis:0px;
+  position:relative;
+  background: rgba(208,208,208,0.9);
+}
+.split:not(.resizeable) .content:first-child {
+  transition: all .3s;
+}
+
+.split.resizeable.horizontal .splitter::after {
+  display:flex;
+  justify-content: center;
+  align-items: center;
+  z-index:100;
+  content:" ";
+  position:absolute;
+
+  top:20%;
+  bottom:20%;
+  left:0px;
+  width:10px;
+
+  background: rgba(0,0,0,0.4);
+  transition: all .3s;
+}
+
 .app-horizontal {
   height:100%;
   max-height:100%;

+ 0 - 59
browser/vue-flow/src/components/nodedata.js

@@ -1,59 +0,0 @@
-// Document shared state
-/* export default{
-  panzoom: { x: 0, y: 0, zoom: 1 },
-  defaults: { nodeHeight: 100 },
-  registry: {
-    'MatMul': { inputs: [ '[]float32', '[]float32' ], output: '[]float32', style: {color: '#789', textColor: '#fff'} },
-    'Weights': { inputs: [], output: '[]float32' },
-    'Input': { inputs: [], output: '[]float32', style: {color: '#686', textColor: '#fff'}},
-    'Activator': { inputs: [ '[]float32' ], output: '[]float32', type: 'circle', style: {color: '#a44', textColor: 'white'}},
-    'R': { inputs: [ '[]float32', 'string' ], output: 'string' },
-    'reverse': { inputs: [ 'string' ], output: 'string' }
-  },
-  nodes: [
-    { id: '1', x: 976, y: 163, label: 'Test input random', src: 'R' },
-    { id: '2', x: 702, y: 190, label: 'Sigmoid', src: 'Activator' },
-    { id: '3', x: 541, y: 195, label: 'MatMul', src: 'MatMul' },
-    { id: '4', x: 320, y: 249, label: 'Input', src: 'Input' },
-    { id: '5', x: 347, y: 90, label: 'Weights', src: 'Weights' },
-    { id: '6', x: 976, y: 263, label: 'reverse', src: 'reverse' }
-  ],
-  links: [
-    { from: '4', to: '3', in: 1 },
-    { from: '5', to: '3', in: 0 },
-    { from: '3', to: '2', in: 0 },
-    { from: '2', to: '1', in: 0 }
-  ]
-} /**/
-
-export default {
-  panzoom: { x: 0, y: 0, zoom: 1 },
-  defaults: { 'nodeHeight': 100 },
-  registry: {
-    'MatMul': { inputs: [ '[]float32', '[]float32' ], output: '[]float32', style: { 'color': '#789', 'textColor': '#fff' } },
-    'Weights': { inputs: [], output: '[]float32' },
-    'Input': { inputs: [], output: '[]float32', style: { 'color': '#686', 'textColor': '#fff' } },
-    'Activator': { inputs: [ '[]float32' ], output: '[]float32', 'type': 'circle', style: { 'color': '#a44', 'textColor': 'white' } },
-    'test': { inputs: [ '[]float32', 'string' ], output: 'string' },
-    'reverse': { inputs: [ 'string' ], output: 'string' }
-  },
-  nodes: [
-    { id: '4', x: 175, y: 85, label: 'Input', src: 'Input' },
-    { id: '3', x: 400, y: 111, label: 'MatMul', src: 'MatMul' },
-    { id: '1', x: 1041, y: 137, label: 'Testing', src: 'test' },
-    { id: '6', x: 735, y: 115, label: 'MatMul', src: 'MatMul' },
-    { id: '8', x: 908, y: 113, label: 'Activator', src: 'Activator' },
-    { id: '2', x: 556, y: 114, label: 'Sigmoid', src: 'Activator' },
-    { id: '7', x: 615, y: 283, label: 'Weights', src: 'Weights' },
-    { id: '5', x: 256, y: 269, label: 'Weights', src: 'Weights' }
-  ],
-  links: [
-    { from: '3', to: '2', in: 0 },
-    { from: '2', to: '6', in: 0 },
-    { from: '5', to: '3', in: 1 },
-    { from: '4', to: '3', in: 0 },
-    { from: '7', to: '6', in: 1 },
-    { from: '6', to: '8', in: 0 },
-    { from: '8', to: '1', in: 0 }
-  ]
-}

+ 25 - 10
browser/vue-flow/src/components/flow/panel.vue

@@ -11,20 +11,19 @@
       </button>
     </div>
     <div class="flow-funcs__inner">
-
       <hx-collapsible v-for="g in funcsGroups" :key="g">
         <div class="flow-funcs__header" slot="header">{{ g }}</div>
         <div class="flow-funcs__group" :class="{blocks:funcsViewBlocks}">
-          <button
+          <div
             :key="k"
-            class="flow-funcs__src hover-anim"
+            ref="src"
+            class="flow-funcs__src hover-anim hover"
             draggable="true"
             v-for="k in funcsGroup(g)"
-            @dragstart.stop="fnDrag($event,k)"
-
+            @dragstart="fnDrag($event,k)"
             :style="{'background':registry[k].style && registry[k].style.color}">
             {{ k }}
-          </button>
+          </div>
         </div>
       </hx-collapsible>
     </div>
@@ -59,10 +58,17 @@ export default {
         return ret
       }
     }
-
+  },
+  mounted () {
+    for (let n of this.$refs.src) {
+      n.addEventListener('dragstart', () => {
+        console.log('Dragging')
+      })
+    }
   },
   methods: {
     fnDrag (ev, src) {
+      console.log('Dragging started')
       ev.dataTransfer.setData('text/plain', src)
     }
   }
@@ -110,14 +116,24 @@ export default {
 }
 .flow-funcs__src {
   font-size:12px;
-  cursor: move;
   padding:11px 5px;
   background: #777;
   color:#eee;
+
   margin-top:1px;
   text-align:center;
   transition: all .3s;
   position:relative;
+
+  display:flex;
+  justify-content: center;
+  align-items: center;
+
+  cursor: move;
+  cursor: grab;
+  cursor: -moz-grab;
+  cursor: -webkit-grab;
+
 }
 .flow-funcs__group.blocks {
   flex-flow:row;
@@ -127,9 +143,8 @@ export default {
   align-content: center;
 }
 .flow-funcs__group.blocks .flow-funcs__src {
-/*Orientation*/
   text-overflow: ellipsis;
-  margin:2px;
+  margin:1px;
   width: 60px;
   height:60px;
   overflow:hidden;

+ 3 - 3
browser/vue-flow/src/services/flowservice.js

@@ -61,6 +61,8 @@ export default {
           service.send({op: ftyp, id: id, data: param})
           return
         }
+        if (ftyp !== 'documentUpdate') return // Do not persist other than documentUpdate on reconnection
+        // Schedule when is connected
         service.once('open', () => {
           service.send({op: ftyp, id: id, data: param})
         })
@@ -96,9 +98,7 @@ export default {
     }
 
     connect(options.location)
-    /// ////////////////////////////////////////
-    // Service methods here
-    /// /////
+
     Vue.prototype.$flowService = service
   }