|
[<AutoOpen>] |
|
module Workflow = |
|
type State = Initial | Draft | PendingApproval | Approved | Cancelled | Completed |
|
type Action = Create | Cancel | SendForApproval | Approve | Reject | Complete |
|
type Role = Creator | Approver | Completor |
|
type Transition = { Action:Action; From:State; To:State; Roles:Role list } |
|
module Transitions = |
|
let create = { Action=Create; From=Initial; To=Draft; Roles=[ Creator ] } |
|
let cancel = { Action=Cancel; From=Draft; To=Cancelled; Roles=[ Creator ] } |
|
let sendForAppr = { Action=SendForApproval; From=Draft; To=PendingApproval; Roles=[ Creator ] } |
|
let approve = { Action=Approve; From=PendingApproval; To=Approved; Roles=[ Approver ] } |
|
let reject = { Action=Reject; From=PendingApproval; To=Draft; Roles=[ Approver ] } |
|
let complete = { Action=Complete; From=Approved; To=Completed; Roles=[ Completor ] } |
|
let all = [ create; sendForAppr; approve; reject; complete; cancel; ] |
|
|
|
|
|
#r "System.Xml.Linq" |
|
|
|
[<AutoOpen>] |
|
module Dgml = |
|
open System.Xml.Linq |
|
let xn name = XName.Get(name, "") |
|
let xns name ns = XName.Get(name, ns) |
|
let xnd name = xns name "http://schemas.microsoft.com/vs/2009/dgml" |
|
let attr name value = XAttribute(xn name, value) :> XObject |
|
let elem name (children:XObject list) = XElement(xnd name, children) :> XObject |
|
|
|
type Link = { Source:string; Target:string; Label:string; } |
|
type Node = { Id:string; } |
|
|
|
let nodeToElement (node:Node) = elem "Node" [ attr "Id" node.Id ] |
|
let linkToElement (link:Link) = elem "Link" [ attr "Source" link.Source |
|
attr "Target" link.Target |
|
attr "Label" link.Label ] |
|
|
|
let create (nodes: Node list) (links: Link list) = |
|
XDocument(elem "DirectedGraph" [ elem "Nodes" (nodes |> List.map nodeToElement) |
|
elem "Links" (links |> List.map linkToElement) ]) |
|
|
|
let stateToString (state:State) = sprintf "%A" state |
|
let actionToString (action:Action) = sprintf "%A" action |
|
let transitionToNodes (t:Transition) = [ { Id=stateToString t.From}; { Id=stateToString t.To } ] |
|
let transitionsToNodes = Seq.collect transitionToNodes >> Seq.distinct >> Seq.toList |
|
let transitionToLink t = { Source=stateToString t.From; Target=stateToString t.To; Label=actionToString t.Action } |
|
let transitionsToLinks = Seq.map transitionToLink >> Seq.toList |
|
|
|
Dgml.create (transitionsToNodes Transitions.all) (transitionsToLinks Transitions.all) |