visual/react/server.go (84 lines of code) (raw):

package react import ( "encoding/json" "log/slog" "net/http" flow "github.com/Azure/go-workflow" "github.com/Azure/go-workflow/visual/react/out" "github.com/google/uuid" ) var UI = out.UI type StaticHandler struct { Workflow *flow.Workflow } func (sh StaticHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) { // resp.Header().Set("Access-Control-Allow-Origin", "http://localhost:3000") root := &Node{ID: "root"} nodes := map[flow.Steper]*Node{sh.Workflow: root} getNode := func(s flow.Steper) *Node { node, ok := nodes[s] if !ok { node = &Node{ID: uuid.NewString()} nodes[s] = node } return node } flow.Traverse(sh.Workflow, func(s flow.Steper, walked []flow.Steper) flow.TraverseDecision { if w, ok := s.(interface { Unwrap() []flow.Steper UpstreamOf(flow.Steper) map[flow.Steper]flow.StepResult }); ok { for _, r := range w.Unwrap() { n := getNode(r) n.Labels = append(n.Labels, Label{flow.String(r)}) parent := s for i := len(walked) - 1; i >= 0; i-- { if _, ok := walked[i].(interface{ Unwrap() []flow.Steper }); ok { if i < len(walked)-1 { parent = walked[i+1] break } } } getNode(parent).Children = append(getNode(parent).Children, n) for up := range w.UpstreamOf(r) { eid := uuid.NewString() getNode(parent).Edges = append(getNode(parent).Edges, &Edge{ ID: eid, Sources: []string{getNode(up).ID}, Targets: []string{getNode(r).ID}, }) } } } return flow.TraverseContinue }) b, err := json.Marshal(root) if err != nil { resp.WriteHeader(http.StatusInternalServerError) slog.Error("failed to marshal flow", "error", err) return } resp.WriteHeader(http.StatusOK) if _, err := resp.Write(b); err != nil { slog.Error("failed to write response", "error", err) return } } type Node struct { ID string `json:"id"` Children []*Node `json:"children,omitempty"` Edges []*Edge `json:"edges,omitempty"` X int `json:"x,omitempty"` Y int `json:"y,omitempty"` Width int `json:"width,omitempty"` Height int `json:"height,omitempty"` Labels []Label `json:"labels,omitempty"` } type Label struct { Text string `json:"text,omitempty"` } type Edge struct { ID string `json:"id"` Sources []string `json:"sources"` Targets []string `json:"targets"` }