luis 7 rokov pred
rodič
commit
1de06f49a1

+ 3 - 10
browser/vue-flow/src/components/flow/manager.vue

@@ -83,6 +83,7 @@ export default {
   name: 'FlowManager',
   components: {FlowNode, FlowLink, FlowPanZoom, SvgDefs},
   props: {
+    'activity': {type: Object, default: () => {}},
     'registry': {type: Object, default: () => {}},
     'width': {type: String, default: '800px'},
     'height': {type: String, default: '600px'}
@@ -99,9 +100,7 @@ export default {
       detailed: false,
       pointerLink: {active: false, props: {}, src: {}},
       selector: null,
-
-      nodeSelection: {},
-      nodeStatus: {}
+      nodeSelection: {}
     }
   },
   computed: {
@@ -124,6 +123,7 @@ export default {
           output: nodeClass.output,
           match: match,
           dragging: this.dragging && !!this.dragging[node.id],
+          activity: this.activity[node.id],
           nodeStyle: nodeClass.style
         }
       }
@@ -195,13 +195,6 @@ export default {
         // }
       }
     })
-    this.$flowService.on('nodeStart', (v) => {
-      this.nodeStatus[v.id] = 'started'
-    })
-    this.$flowService.on('nodeFinish', (v) => {
-      this.nodeStatus[v.id] = ''
-    })
-
     this.$nextTick(() => {
       this.$forceUpdate()
     })

+ 20 - 2
browser/vue-flow/src/components/flow/node.vue

@@ -6,6 +6,7 @@
       'flow-node--dragging':dragging,
       'flow-node--selected': selected
     }"
+    :status="status"
     @mousedown.stop.prevent="$emit('nodePointerDown',$event)"
     @dblclick="$emit('nodeDoubleClick',$event)"
   >
@@ -86,6 +87,7 @@
     />
 
     <text
+      :key="'inp' +i"
       class="flow-node__socket-detail"
       v-for="(inp,i) in inputs"
       text-anchor="end"
@@ -123,7 +125,7 @@ export default {
     'match': {type: Object, default: () => {}},
     'dragging': {type: Boolean, default: false},
     'selected': {type: Boolean, default: false},
-    'status': {type: String, default: ''},
+    'activity': {type: Object, default: () => {}},
 
     'nodeStyle': {type: Object, default: () => {}}
   },
@@ -138,8 +140,11 @@ export default {
     style () {
       return this.nodeStyle || {}
     },
+    status () {
+      return this.activity && this.activity.status
+    },
     labelWrap () {
-      let wrapThreshold = 10 // initial wrap threshold
+      let wrapThreshold = 8 // initial wrap threshold
       const opt = shapeOpts[this.style.shape] || shapeOpts.default
       return utils.textWrap(this.label, wrapThreshold, opt.textWrap)
     },
@@ -232,6 +237,19 @@ export default {
 }
 </script>
 <style>
+
+.flow-node[status=running] .flow-node__body{
+  stroke: yellow !important;
+  fill: yellow !important;
+  stroke-width:30;
+}
+
+.flow-node[status=error] .flow-node__body{
+  stroke: red !important;
+  fill: red !important;
+  stroke-width:30;
+}
+
 .flow-view:not(.activity) .flow-node:hover,
 .flow-node--dragging {
   cursor:move;

+ 27 - 20
browser/vue-flow/src/components/main.vue

@@ -55,9 +55,10 @@
 
           <flow-manager
             ref="flowManager"
+            :activity="activity"
             :registry="registry"
             @funcsPanelToggle="funcsActive=!funcsActive"
-            @nodeInspect="nodeInspect(...arguments)"
+            @nodeInspect="nodeInspectStart(...arguments)"
 
             width="100%"
             height="100%"/>
@@ -69,7 +70,7 @@
       <!-- Node inspector -->
       <!-- Move this to a different place -->
       <!-- And rename it to inspector -->
-      <hx-modal class="flow-modal" v-if="nodeInspectTarget" @close="nodeInspectTarget=null">
+      <hx-modal class="flow-modal" v-if="nodeInspect" @close="nodeInspect=null">
         <div slot="header">Node inspector:</div>
         <div slot="body" class="flow-modal__body">
           <div class="flow-modal__info">
@@ -79,12 +80,13 @@
                   style="pointer-events:none"
                   ref="modalPreviewNode"
                   transform="translate(150,100)"
-                  :id="nodeInspectTarget.id"
+                  :id="nodeInspect.id"
                   :match="{}"
-                  :label="nodeInspectTarget.label"
-                  :inputs= "registry[nodeInspectTarget.src].inputs"
-                  :output= "registry[nodeInspectTarget.src].output"
-                  :nodeStyle= "registry[nodeInspectTarget.src].style"
+                  :label="nodeInspect.label"
+                  :inputs= "registry[nodeInspect.src].inputs"
+                  :output= "registry[nodeInspect.src].output"
+                  :activity: "activity[node.id]"
+                  :nodeStyle= "registry[nodeInspect.src].style"
               /></flow-panzoom>
             </svg>
             <div class="flow-modal__sockets-properties">
@@ -92,10 +94,10 @@
               <div class="property">Bogus description</div>
               <label>Help</label>
               <div class="property">Connect to input a thing and goes to output another thing</div>
-              <div class="flow-modal__params" v-if="nodeInspectTarget.prop" @keydown.enter="nodeInspectTarget=null">
-                <div class="flow-modal__param" v-for="(v,k) in nodeInspectTarget.prop">
+              <div class="flow-modal__params" v-if="nodeInspect.prop" @keydown.enter="nodeInspect=null">
+                <div class="flow-modal__param" v-for="(v,k) in nodeInspect.prop">
                   <label>{{ k }}</label>
-                  <input type="text" v-model="nodeInspectTarget.prop[k]">
+                  <input type="text" v-model="nodeInspect.prop[k]">
                 </div>
               </div>
             </div>
@@ -104,14 +106,14 @@
           <input
             ref="modalInput"
             type="text"
-            v-model="nodeInspectTarget.label"
-            @keydown.esc="nodeInspectTarget=null"
-            @keydown.enter="nodeInspectTarget=null"
+            v-model="nodeInspect.label"
+            @keydown.esc="nodeInspect=null"
+            @keydown.enter="nodeInspect=null"
           >
         </div>
         <div slot="footer">
-          <button class="primary-invert" @click="nodeProcess(nodeInspectTarget)">Run</button>
-          <button @click="nodeInspectTarget=false">OK</button>
+          <button class="primary-invert" @click="nodeProcess(nodeInspect)">Run</button>
+          <button @click="nodeInspect=false">OK</button>
         </div>
       </hx-modal>
 
@@ -162,6 +164,7 @@ export default {
   data () {
     return {
       registry: JSON.parse(JSON.stringify(defRegistry)),
+      activity: {},
 
       /* {
         // Fixed default stuff
@@ -186,7 +189,7 @@ export default {
         'lineGraph': { group: 'Visualization', inputs: ['[]float32', '[]float32'], style: {'color': '#9a9'} }
       }, */
 
-      nodeInspectTarget: false,
+      nodeInspect: false,
 
       funcsSize: '250px',
       funcsActive: true,
@@ -196,14 +199,14 @@ export default {
     }
   },
   watch: {
-    nodeInspectTarget: {
+    nodeInspect: {
       handler (val, oldVal) {
         if (!val === null && !oldVal) { return }
         if (!val) {
           this.$refs.flowManager.sendDocumentUpdate()
           return
         }
-        this.$refs.flowManager.sendFlowEvent('nodeUpdate', [this.nodeInspectTarget])
+        this.$refs.flowManager.sendFlowEvent('nodeUpdate', [this.nodeInspect])
       },
       deep: true
     }
@@ -219,6 +222,10 @@ export default {
     this.$flowService.on('registry', (v) => {
       this.registry = Object.assign({}, defRegistry, v.data)
     })
+    this.$flowService.on('nodeActivity', (v) => {
+      this.activity = v.data || {}
+    })
+
     // Connected
     this.$flowService.connected(() => {
       // Make this in a service
@@ -230,8 +237,8 @@ export default {
     })
   },
   methods: {
-    nodeInspect (node) { // node
-      this.nodeInspectTarget = node
+    nodeInspectStart (node) { // node
+      this.nodeInspect = node
       this.$nextTick(() => {
         if (!this.$refs.modalInput) return
         this.$refs.modalInput.setSelectionRange(0, this.$refs.modalInput.value.length)

+ 8 - 9
browser/vue-flow/src/components/panel.vue

@@ -27,13 +27,15 @@
           class="flow-funcs__group"
           :class="{blocks:funcsViewBlocks}">
           <div
-            :key="k"
             ref="src"
-            class="flow-funcs__src hover-anim hover"
+            :key="k"
+            class="flow-funcs__src hover"
             draggable="true"
             v-for="k in funcsGroup(g)"
             @dragstart="fnDrag($event,k)"
-            :style="{ 'background': registry[k].style && registry[k].style.color, }">
+            :style="{ 'background': registry[k].style && registry[k].style.color, }"
+            :title="k"
+          >
             {{ k }}
           </div>
         </div>
@@ -133,9 +135,8 @@ export default {
 
 .flow-funcs__src {
   font-size:12px;
-  padding:4px;
+  padding:12px 4px;
   margin-top:1px;
-  height:35px;
   text-align:center;
   transition: all 0.3s;
   position:relative;
@@ -146,7 +147,6 @@ export default {
   cursor: grab;
   cursor: -moz-grab;
   cursor: -webkit-grab;
-
 }
 
 .flow-funcs__group.blocks {
@@ -156,11 +156,10 @@ export default {
 }
 
 .flow-funcs__group.blocks .flow-funcs__src {
-  width: calc(50% - 2px);
   display:block;
-  padding:15px 4px;
+  width: calc(25% - 2px);
+  padding:22px 4px;
   text-overflow: ellipsis;
-  height:40px;
   margin:1px;
   word-wrap: break-all;
   overflow:hidden;

+ 1 - 13
browser/vue-flow/src/services/flowservice.js

@@ -1,6 +1,6 @@
 // FlowWSService
 
-const debug = 1
+const debug = 0
 let log = () => {}
 if (debug) {
   log = console.log.bind(console.log, '%cSVC:', 'color:#0a0')
@@ -16,18 +16,6 @@ export default {
     const eventBus = new Vue()
 
     let service = {
-      /* documentUpdate (nodeData, id) { // Specific
-        log('documentUpdate -- ', nodeData)
-        if (connected === false) {
-          log('Saving failed, rescheduling')
-          failed = {
-            DocumentUpdate: JSON.parse(JSON.stringify(nodeData)),
-            sessId: id
-          }
-          return
-        }
-        this.send({op: 'documentUpdate', id: id, data: nodeData})
-      }, */
       send (msg) { // Raw message
         ws.send(JSON.stringify(msg))
       },

+ 11 - 1
go/src/flowserver/cmd/flowserver/main.go

@@ -26,6 +26,7 @@ func main() {
 	flow.Register("delay.reverse", delayReverse)
 	flow.Register("delay.split", delaySplit)
 	flow.Register("delay.join", delayJoin)
+	flow.Register("longduration", longduration)
 	flow.Register("duration", duration)
 
 	f := flowserver.FlowServer{}
@@ -66,9 +67,18 @@ func delayJoin(s []string, join string) string {
 	return strings.Join(s, join)
 }
 
+func longduration() string {
+	mark := time.Now()
+	time.Sleep(25 * time.Second) // Simulate
+	now := time.Now()
+
+	return " took: " + fmt.Sprint(now.Sub(mark))
+
+}
 func duration(s string) string {
+
 	mark := time.Now()
-	time.Sleep(time.Duration(2+rand.Intn(10)) * time.Second) // Simulate
+	time.Sleep(7 * time.Second) // Simulate
 	now := time.Now()
 
 	return s + " took: " + fmt.Sprint(now.Sub(mark))

+ 1 - 1
go/src/flowserver/flowmsg/flowmessage.go

@@ -9,7 +9,7 @@ type RecvMessage struct {
 	Data json.RawMessage `json:"data"`
 }
 
-// SendMessage sendMessage structure
+// SendMessage
 type SendMessage struct {
 	OP   string      `json:"op"`
 	ID   string      `json:"id"`

+ 32 - 6
go/src/flowserver/session.go

@@ -11,6 +11,11 @@ import (
 	"github.com/gorilla/websocket"
 )
 
+type NodeActivity struct {
+	Status string    `json:"status"` // nodeStatus, Running, error, result
+	Result flow.Data `json:"result"`
+}
+
 // FlowSession Create a session and link clients
 type FlowSession struct {
 	sync.Mutex
@@ -19,14 +24,23 @@ type FlowSession struct {
 	clients []*websocket.Conn
 	Chat    ChatRoom
 
-	RawDoc []byte // Just share data
+	RawDoc       []byte // Just share data
+	nodeActivity map[string]NodeActivity
 
 	flow *flow.Flow
 }
 
 //NewSession creates and initializes a NewSession
 func NewSession(ID string) *FlowSession {
-	s := &FlowSession{sync.Mutex{}, ID, []*websocket.Conn{}, ChatRoom{}, []byte{}, nil}
+	s := &FlowSession{
+		sync.Mutex{},
+		ID,
+		[]*websocket.Conn{},
+		ChatRoom{},
+		[]byte{},
+		map[string]NodeActivity{},
+		nil,
+	}
 	return s
 }
 
@@ -48,10 +62,15 @@ func (s *FlowSession) ClientAdd(c *websocket.Conn) error {
 	}
 	s.clients = append(s.clients, c)
 
-	if len(s.RawDoc) > 0 {
-		return c.WriteJSON(flowmsg.SendMessage{OP: "document", Data: json.RawMessage(s.RawDoc)})
+	if len(s.RawDoc) == 0 {
+		return nil
 	}
-	return nil
+	err = c.WriteJSON(flowmsg.SendMessage{OP: "document", Data: json.RawMessage(s.RawDoc)})
+	if err != nil {
+		return err
+	}
+
+	return c.WriteJSON(flowmsg.SendMessage{OP: "nodeActivity", Data: s.nodeActivity})
 
 	// Send registry
 }
@@ -116,9 +135,16 @@ func (s *FlowSession) NodeRun(c *websocket.Conn, data []byte) error {
 
 	log.Println("Attaching hooks")
 	s.flow.Handle(func(name string, payload map[string]flow.Data) {
+
+		switch name {
+		case "nodeStart":
+			s.nodeActivity[payload["id"].(string)] = NodeActivity{Status: "running"}
+		case "nodeFinish":
+			s.nodeActivity[payload["id"].(string)] = NodeActivity{Status: "finish", Result: payload["result"]}
+		}
 		// Add to executing nodes
 		log.Println("Exec doc", name)
-		s.Broadcast(nil, flowmsg.SendMessage{OP: name, ID: payload["id"].(string), Data: payload})
+		s.Broadcast(nil, flowmsg.SendMessage{OP: "nodeActivity", Data: s.nodeActivity})
 	})
 
 	log.Println("Fetch result")