diff --git a/src/api/Synapse.Api.Http/Synapse.Api.Http.csproj b/src/api/Synapse.Api.Http/Synapse.Api.Http.csproj
index e6afd741c..ef8f1a9b6 100644
--- a/src/api/Synapse.Api.Http/Synapse.Api.Http.csproj
+++ b/src/api/Synapse.Api.Http/Synapse.Api.Http.csproj
@@ -10,8 +10,8 @@
-
-
+
+
diff --git a/src/core/Synapse.Core.Infrastructure/Synapse.Core.Infrastructure.csproj b/src/core/Synapse.Core.Infrastructure/Synapse.Core.Infrastructure.csproj
index f601d3c5a..8a87a4cdd 100644
--- a/src/core/Synapse.Core.Infrastructure/Synapse.Core.Infrastructure.csproj
+++ b/src/core/Synapse.Core.Infrastructure/Synapse.Core.Infrastructure.csproj
@@ -10,11 +10,11 @@
-
-
-
-
-
+
+
+
+
+
diff --git a/src/core/Synapse.Core/Synapse.Core.csproj b/src/core/Synapse.Core/Synapse.Core.csproj
index 5b4a51042..557bfb1d6 100644
--- a/src/core/Synapse.Core/Synapse.Core.csproj
+++ b/src/core/Synapse.Core/Synapse.Core.csproj
@@ -32,8 +32,8 @@
-
-
+
+
diff --git a/src/correlator/Synapse.Correlator/Synapse.Correlator.csproj b/src/correlator/Synapse.Correlator/Synapse.Correlator.csproj
index e1b46019e..e2de0e553 100644
--- a/src/correlator/Synapse.Correlator/Synapse.Correlator.csproj
+++ b/src/correlator/Synapse.Correlator/Synapse.Correlator.csproj
@@ -16,12 +16,12 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/CallTaskNodeViewModel.cs b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/CallTaskNodeViewModel.cs
index 14e5cd834..0965e8d92 100644
--- a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/CallTaskNodeViewModel.cs
+++ b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/CallTaskNodeViewModel.cs
@@ -22,11 +22,12 @@ public class CallTaskNodeViewModel
///
/// Initializes a new
///
+ /// The node task reference
/// The node name
/// The node content
/// The type of call
- public CallTaskNodeViewModel(string name, string content, string callType = "")
- : base(new() { Label = name, CssClass = "call-task-node" })
+ public CallTaskNodeViewModel(string taskReference, string name, string content, string callType = "")
+ : base(taskReference, new() { Label = name, CssClass = "call-task-node" })
{
Content = content;
Symbol = !string.IsNullOrEmpty(callType) ? $"{callType.ToLower()}-symbol" : "call-symbol";
diff --git a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/DoTaskNodeViewModel.cs b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/DoTaskNodeViewModel.cs
index c9fbda422..c9f2a92db 100644
--- a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/DoTaskNodeViewModel.cs
+++ b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/DoTaskNodeViewModel.cs
@@ -22,10 +22,11 @@ public class DoTaskNodeViewModel
///
/// Initializes a new
///
+ /// The node task reference
/// The node name
/// The node content
- public DoTaskNodeViewModel(string name, string content)
- : base(new() { Label = name, CssClass = "do-task-node" })
+ public DoTaskNodeViewModel(string taskReference, string name, string content)
+ : base(taskReference, new() { Label = name, CssClass = "do-task-node" })
{
Content = content;
Symbol = "do-symbol";
diff --git a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/EmitTaskNodeViewModel.cs b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/EmitTaskNodeViewModel.cs
index 4cecee45f..a11684014 100644
--- a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/EmitTaskNodeViewModel.cs
+++ b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/EmitTaskNodeViewModel.cs
@@ -22,10 +22,11 @@ public class EmitTaskNodeViewModel
///
/// Initializes a new
///
+ /// The node task reference
/// The node name
/// The node content
- public EmitTaskNodeViewModel(string name, string content)
- : base(new() { Label = name, CssClass = "emit-task-node" })
+ public EmitTaskNodeViewModel(string taskReference, string name, string content)
+ : base(taskReference, new() { Label = name, CssClass = "emit-task-node" })
{
Content = content;
Symbol = "emit-symbol";
diff --git a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/EndNodeViewModel.cs b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/EndNodeViewModel.cs
index 765b756ec..5ff3fe779 100644
--- a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/EndNodeViewModel.cs
+++ b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/EndNodeViewModel.cs
@@ -19,6 +19,6 @@ namespace Synapse.Dashboard.Components;
/// Represents the object that holds the data required to render the view of a workflow's end node
///
public class EndNodeViewModel()
- : WorkflowNodeViewModel(new() { CssClass = "end-node", Shape = NodeShape.Circle, Width = WorkflowGraphBuilder.StartEndNodeRadius, Height = WorkflowGraphBuilder.StartEndNodeRadius })
+ : WorkflowNodeViewModel("end-node", new() { CssClass = "end-node", Shape = NodeShape.Circle, Width = WorkflowGraphBuilder.StartEndNodeRadius, Height = WorkflowGraphBuilder.StartEndNodeRadius })
{
}
diff --git a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/ExtensionTaskNodeViewModel.cs b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/ExtensionTaskNodeViewModel.cs
index 7cda60da5..228754c0c 100644
--- a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/ExtensionTaskNodeViewModel.cs
+++ b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/ExtensionTaskNodeViewModel.cs
@@ -22,9 +22,10 @@ public class ExtensionTaskNodeViewModel
///
/// Initializes a new
///
+ /// The node task reference
/// The node name
- public ExtensionTaskNodeViewModel(string name)
- : base(new() { Label = name, CssClass = "extension-task-node" })
+ public ExtensionTaskNodeViewModel(string taskReference, string name)
+ : base(taskReference, new() { Label = name, CssClass = "extension-task-node" })
{
Symbol = "extension-symbol";
Type = "EXTENSION";
diff --git a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/ForTaskNodeViewModel.cs b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/ForTaskNodeViewModel.cs
index f99f5abfe..b171ac0cb 100644
--- a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/ForTaskNodeViewModel.cs
+++ b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/ForTaskNodeViewModel.cs
@@ -22,10 +22,11 @@ public class ForTaskNodeViewModel
///
/// Initializes a new
///
+ /// The node task reference
/// The node name
/// The node content
- public ForTaskNodeViewModel(string name, string content)
- : base(new() { Label = name, CssClass = "for-task-node" })
+ public ForTaskNodeViewModel(string taskReference, string name, string content)
+ : base(taskReference, new() { Label = name, CssClass = "for-task-node" })
{
Content = content;
Symbol = "for-symbol";
diff --git a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/ListenTaskNodeViewModel.cs b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/ListenTaskNodeViewModel.cs
index e0cb9fb6f..ce5f96201 100644
--- a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/ListenTaskNodeViewModel.cs
+++ b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/ListenTaskNodeViewModel.cs
@@ -22,10 +22,11 @@ public class ListenTaskNodeViewModel
///
/// Initializes a new
///
+ /// The node task reference
/// The node name
/// The node content
- public ListenTaskNodeViewModel(string name, string content)
- : base(new() { Label = name, CssClass = "listen-task-node" })
+ public ListenTaskNodeViewModel(string taskReference, string name, string content)
+ : base(taskReference, new() { Label = name, CssClass = "listen-task-node" })
{
Content = content;
Symbol = "listen-symbol";
diff --git a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/NodeViewModelConfig.cs b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/NodeViewModelConfig.cs
index e0af8cc3b..9b634c2b3 100644
--- a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/NodeViewModelConfig.cs
+++ b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/NodeViewModelConfig.cs
@@ -73,7 +73,7 @@ public class NodeViewModelConfig
///
/// Gets/sets parent node id
///
- public Guid? ParentId { get; set; }
+ public string? ParentId { get; set; }
///
/// Gets/sets the shape the node
diff --git a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/RaiseTaskNodeViewModel.cs b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/RaiseTaskNodeViewModel.cs
index f62bb7432..4640d52f9 100644
--- a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/RaiseTaskNodeViewModel.cs
+++ b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/RaiseTaskNodeViewModel.cs
@@ -22,10 +22,11 @@ public class RaiseTaskNodeViewModel
///
/// Initializes a new
///
+ /// The node task reference
/// The node name
/// The node content
- public RaiseTaskNodeViewModel(string name, string content)
- : base(new() { Label = name, CssClass = "raise-task-node" })
+ public RaiseTaskNodeViewModel(string taskReference, string name, string content)
+ : base(taskReference, new() { Label = name, CssClass = "raise-task-node" })
{
Content = content;
Symbol = "raise-symbol";
diff --git a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/RunTaskNodeViewModel.cs b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/RunTaskNodeViewModel.cs
index 583095a75..83fe4469d 100644
--- a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/RunTaskNodeViewModel.cs
+++ b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/RunTaskNodeViewModel.cs
@@ -24,11 +24,12 @@ public class RunTaskNodeViewModel
///
/// Initializes a new
///
+ /// The node task reference
/// The node name
/// The node content
/// The type of run
- public RunTaskNodeViewModel(string name, string content, string runType = "")
- : base(new() { Label = name, CssClass = "run-task-node" })
+ public RunTaskNodeViewModel(string taskReference, string name, string content, string runType = "")
+ : base(taskReference, new() { Label = name, CssClass = "run-task-node" })
{
Content = content;
Symbol = !string.IsNullOrEmpty(runType) ? $"{runType.ToLower()}-symbol" : "run-symbol";
diff --git a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/SetTaskNodeViewModel.cs b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/SetTaskNodeViewModel.cs
index 45c3e1f68..5a5407eec 100644
--- a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/SetTaskNodeViewModel.cs
+++ b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/SetTaskNodeViewModel.cs
@@ -22,10 +22,11 @@ public class SetTaskNodeViewModel
///
/// Initializes a new
///
+ /// The node task reference
/// The node name
/// The node content
- public SetTaskNodeViewModel(string name, string content)
- : base(new() { Label = name, CssClass = "set-task-node" })
+ public SetTaskNodeViewModel(string taskReference, string name, string content)
+ : base(taskReference, new() { Label = name, CssClass = "set-task-node" })
{
Content = content;
Symbol = "set-symbol";
diff --git a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/StartNodeViewModel.cs b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/StartNodeViewModel.cs
index a1f4aec3b..87a05e66e 100644
--- a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/StartNodeViewModel.cs
+++ b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/StartNodeViewModel.cs
@@ -20,7 +20,7 @@ namespace Synapse.Dashboard.Components;
/// Represents the object that holds the data required to render the view of a workflow's start node
///
public class StartNodeViewModel(bool hasSuccessor = false)
- : WorkflowNodeViewModel(new() { CssClass = "start-node", Shape = NodeShape.Circle, Width = WorkflowGraphBuilder.StartEndNodeRadius, Height = WorkflowGraphBuilder.StartEndNodeRadius })
+ : WorkflowNodeViewModel("start-node", new() { CssClass = "start-node", Shape = NodeShape.Circle, Width = WorkflowGraphBuilder.StartEndNodeRadius, Height = WorkflowGraphBuilder.StartEndNodeRadius })
{
///
diff --git a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/SwitchTaskNodeViewModel.cs b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/SwitchTaskNodeViewModel.cs
index 15d09e730..96beb1e65 100644
--- a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/SwitchTaskNodeViewModel.cs
+++ b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/SwitchTaskNodeViewModel.cs
@@ -22,10 +22,11 @@ public class SwitchTaskNodeViewModel
///
/// Initializes a new
///
+ /// The node task reference
/// The node name
/// The node content
- public SwitchTaskNodeViewModel(string name, string content)
- : base(new() { Label = name, CssClass = "switch-task-node" })
+ public SwitchTaskNodeViewModel(string taskReference, string name, string content)
+ : base(taskReference, new() { Label = name, CssClass = "switch-task-node" })
{
Content = content;
Symbol = "switch-symbol";
diff --git a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/TaskNodeViewModel.cs b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/TaskNodeViewModel.cs
index fa54dd026..36f8bd20c 100644
--- a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/TaskNodeViewModel.cs
+++ b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/TaskNodeViewModel.cs
@@ -30,12 +30,14 @@ public class TaskNodeViewModel
///
/// Initializes a new
///
+ /// The node task reference
/// The name of the the represents
/// The the represents
/// Indicates whether or not the task to create the for is the first task of the workflow it belongs to
- public TaskNodeViewModel(string name, TaskDefinition definition, bool isFirst = false)
+ public TaskNodeViewModel(string taskReference, string name, TaskDefinition definition, bool isFirst = false)
: base(null, name)
{
+ this.Id = taskReference;
this.Name = name;
this.Definition = definition;
this.IsFirst = isFirst;
diff --git a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/Templates/NodeLabelTemplate.razor b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/Templates/NodeLabelTemplate.razor
index 2e79de05d..67b5b8d16 100644
--- a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/Templates/NodeLabelTemplate.razor
+++ b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/Templates/NodeLabelTemplate.razor
@@ -18,11 +18,11 @@ else if (!string.IsNullOrWhiteSpace(Node.Label) )
@code {
- IBoundingBox bbox => Node.BBox!;
- string x => bbox.X.ToInvariantString() ?? string.Empty;
- string y => bbox.Y.ToInvariantString() ?? string.Empty;
- string width => bbox.Width.ToInvariantString() ?? string.Empty;
- string height => bbox.Height.ToInvariantString() ?? Neuroglia.Blazor.Dagre.Constants.LabelHeight.ToInvariantString();
+ BoundingBox bounds => Node.Bounds!;
+ string x => bounds.X.ToInvariantString() ?? string.Empty;
+ string y => bounds.Y.ToInvariantString() ?? string.Empty;
+ string width => bounds.Width.ToInvariantString() ?? string.Empty;
+ string height => bounds.Height.ToInvariantString() ?? Neuroglia.Blazor.Dagre.Constants.LabelHeight.ToInvariantString();
[CascadingParameter(Name = "Node")] public INodeViewModel Node { get; set; } = null!;
[CascadingParameter(Name = "LabelTemplate")] public RenderFragment? LabelTemplate { get; set; } = null!;
diff --git a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/Templates/NodeShapeTemplate.razor b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/Templates/NodeShapeTemplate.razor
index cea246a44..cc09064e6 100644
--- a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/Templates/NodeShapeTemplate.razor
+++ b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/Templates/NodeShapeTemplate.razor
@@ -3,31 +3,31 @@
@if (Node.Shape == NodeShape.Circle)
{
-
+
}
else if (Node.Shape == NodeShape.Ellipse)
{
-
+
}
else if (Node.Shape == SynapseNodeShape.Cartouche)
{
-
-
+
+
}
else
{
-
+
}
@code {
- IBoundingBox bbox => Node.BBox!;
+ BoundingBox bounds => Node.Bounds!;
[CascadingParameter(Name = "Node")] public INodeViewModel Node { get; set; } = null!;
}
\ No newline at end of file
diff --git a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/Templates/NodeSymbolTemplate.razor b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/Templates/NodeSymbolTemplate.razor
index bf519b36b..9a0498770 100644
--- a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/Templates/NodeSymbolTemplate.razor
+++ b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/Templates/NodeSymbolTemplate.razor
@@ -12,18 +12,18 @@
@code {
Double _symbolSize = 30;
- IBoundingBox bbox => Node.BBox!;
+ BoundingBox bounds => Node.Bounds!;
string? width => Node.Shape != SynapseNodeShape.Cartouche ?
- (bbox.Width / 2).ToInvariantString() :
+ (bounds.Width / 2).ToInvariantString() :
_symbolSize.ToInvariantString();
string? height => Node.Shape != SynapseNodeShape.Cartouche ?
- (bbox.Height / 2).ToInvariantString() :
+ (bounds.Height / 2).ToInvariantString() :
_symbolSize.ToInvariantString();
string? x => Node.Shape != SynapseNodeShape.Cartouche ?
- (0 - bbox.Width / 4).ToInvariantString() :
- (0 - (bbox.Width - _symbolSize) / 2).ToInvariantString();
+ (0 - bounds.Width / 4).ToInvariantString() :
+ (0 - (bounds.Width - _symbolSize) / 2).ToInvariantString();
string? y => Node.Shape != SynapseNodeShape.Cartouche ?
- (0 - bbox.Height / 4).ToInvariantString() :
+ (0 - bounds.Height / 4).ToInvariantString() :
(0 - _symbolSize / 2).ToInvariantString();
[CascadingParameter(Name = "Node")] public INodeViewModel Node { get; set; } = null!;
diff --git a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/Templates/WorkflowNodeTemplate.razor b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/Templates/WorkflowNodeTemplate.razor
index ee03f16e4..b67b8beee 100644
--- a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/Templates/WorkflowNodeTemplate.razor
+++ b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/Templates/WorkflowNodeTemplate.razor
@@ -1,7 +1,7 @@
@namespace Synapse.Dashboard
@inherits NodeTemplate
-
+
@@ -24,15 +24,15 @@
@code {
protected virtual IWorkflowNodeViewModel WorkflowNode => (IWorkflowNodeViewModel)this.Node;
- IBoundingBox bbox => Node.BBox!;
+ BoundingBox bounds => Node.Bounds!;
RenderFragment? LabelTemplate => !string.IsNullOrWhiteSpace(WorkflowNode.Type) || !string.IsNullOrWhiteSpace(WorkflowNode.Content) ? (__builder) =>
{
-
+
@if (!string.IsNullOrWhiteSpace(Node.Label))
diff --git a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/TryTaskNodeViewModel.cs b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/TryTaskNodeViewModel.cs
index 34ff04476..fa7499721 100644
--- a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/TryTaskNodeViewModel.cs
+++ b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/TryTaskNodeViewModel.cs
@@ -22,10 +22,11 @@ public class TryTaskNodeViewModel
///
/// Initializes a new
///
+ /// The node task reference
/// The node name
/// The node content
- public TryTaskNodeViewModel(string name, string content)
- : base(new() { Label = name, CssClass = "try-task-node" })
+ public TryTaskNodeViewModel(string taskReference, string name, string content)
+ : base(taskReference, new() { Label = name, CssClass = "try-task-node" })
{
Content = content;
Symbol = "try-symbol";
diff --git a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/WaitTaskNodeViewModel.cs b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/WaitTaskNodeViewModel.cs
index 29624e055..490f73a64 100644
--- a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/WaitTaskNodeViewModel.cs
+++ b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/WaitTaskNodeViewModel.cs
@@ -22,10 +22,11 @@ public class WaitTaskNodeViewModel
///
/// Initializes a new
///
+ /// The node task reference
/// The node name
/// The node content
- public WaitTaskNodeViewModel(string name, string content)
- : base(new() { Label = name, CssClass = "wait-task-node" })
+ public WaitTaskNodeViewModel(string taskReference, string name, string content)
+ : base(taskReference, new() { Label = name, CssClass = "wait-task-node" })
{
Content = content;
Symbol = "wait-symbol";
diff --git a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/WorkflowDiagram.razor b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/WorkflowDiagram.razor
index 3435b8d7f..c881fca85 100644
--- a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/WorkflowDiagram.razor
+++ b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/WorkflowDiagram.razor
@@ -22,9 +22,9 @@
[Parameter] public EventCallback> OnMouseUp { get; set; }
- protected override async Task OnParametersSetAsync()
+ protected override void OnParametersSet()
{
- await base.OnParametersSetAsync();
+ base.OnParametersSet();
if (this.WorkflowDefinition != null && this.WorkflowDefinition != this.workflowDefinition)
{
this.workflowDefinition = this.WorkflowDefinition;
@@ -32,7 +32,7 @@
{
Direction = this.Orientation == WorkflowDiagramOrientation.LeftToRight ? DagreGraphDirection.LeftToRight : DagreGraphDirection.TopToBottom
};
- this.graph = await this.WorkflowGraphBuilder.Build(this.workflowDefinition);
+ this.graph = this.WorkflowGraphBuilder.Build(this.workflowDefinition);
this.isDirty = true;
}
}
diff --git a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/WorkflowNodeViewModel.cs b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/WorkflowNodeViewModel.cs
index 730c3d950..e58636b13 100644
--- a/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/WorkflowNodeViewModel.cs
+++ b/src/dashboard/Synapse.Dashboard/Components/WorkflowDiagram/WorkflowNodeViewModel.cs
@@ -18,12 +18,8 @@ namespace Synapse.Dashboard.Components;
///
/// Represents the base class for all workflow-related node models
///
-///
-/// Initialiazes a new
-///
-///
-public abstract class WorkflowNodeViewModel(NodeViewModelConfig? config = null)
- : NodeViewModel(config?.Label, config?.CssClass, config?.Shape, config?.Width, config?.Height, config?.RadiusX, config?.RadiusY, config?.X, config?.Y, config?.ComponentType, config?.ParentId), IWorkflowNodeViewModel
+public abstract class WorkflowNodeViewModel
+ : NodeViewModel, IWorkflowNodeViewModel
{
int _operativeInstances = 0;
@@ -60,6 +56,17 @@ public int FaultedInstancesCount
}
}
+ ///
+ /// Initialiazes a new
+ ///
+ /// The node task reference
+ /// The for the node
+ public WorkflowNodeViewModel(string taskReference, NodeViewModelConfig? config = null)
+ : base(config?.Label, config?.CssClass, config?.Shape, config?.Width ?? 0, config?.Height ?? 0, config?.RadiusX ?? 0, config?.RadiusY ?? 0, config?.X ?? 0, config?.Y ?? 0, config?.ComponentType, config?.ParentId)
+ {
+ this.Id = taskReference;
+ }
+
///
public void ResetInstancesCount()
{
diff --git a/src/dashboard/Synapse.Dashboard/Services/Interfaces/IWorkflowGraphBuilder.cs b/src/dashboard/Synapse.Dashboard/Services/Interfaces/IWorkflowGraphBuilder.cs
index a9c26b9b8..cee013aad 100644
--- a/src/dashboard/Synapse.Dashboard/Services/Interfaces/IWorkflowGraphBuilder.cs
+++ b/src/dashboard/Synapse.Dashboard/Services/Interfaces/IWorkflowGraphBuilder.cs
@@ -27,6 +27,6 @@ public interface IWorkflowGraphBuilder
///
/// The to build a new for
/// A new
- Task Build(WorkflowDefinition workflow);
+ IGraphViewModel Build(WorkflowDefinition workflow);
}
diff --git a/src/dashboard/Synapse.Dashboard/Services/WorkflowGraphBuilder.cs b/src/dashboard/Synapse.Dashboard/Services/WorkflowGraphBuilder.cs
index a5231daa3..0131ba7fb 100644
--- a/src/dashboard/Synapse.Dashboard/Services/WorkflowGraphBuilder.cs
+++ b/src/dashboard/Synapse.Dashboard/Services/WorkflowGraphBuilder.cs
@@ -19,6 +19,7 @@
using ServerlessWorkflow.Sdk.Models.Calls;
using ServerlessWorkflow.Sdk.Models.Tasks;
using System.Diagnostics;
+using System.Xml.Linq;
namespace Synapse.Dashboard.Services;
@@ -47,7 +48,7 @@ public class WorkflowGraphBuilder(IYamlSerializer yamlSerializer, IJsonSerialize
protected IJsonSerializer JsonSerializer { get; } = jsonSerializer;
///
- public async Task Build(WorkflowDefinition workflow)
+ public IGraphViewModel Build(WorkflowDefinition workflow)
{
ArgumentNullException.ThrowIfNull(workflow);
Stopwatch sw = Stopwatch.StartNew();
@@ -55,10 +56,14 @@ public async Task Build(WorkflowDefinition workflow)
var graph = new GraphViewModel();
var startNode = this.BuildStartNode(!isEmpty);
var endNode = this.BuildEndNode();
- await graph.AddElementAsync(startNode);
- await graph.AddElementAsync(endNode);
- if (isEmpty) await this.BuildEdgeAsync(graph, startNode, endNode);
- else await this.BuildTaskNodesAsync(new(workflow, graph, 0, workflow.Do.First().Key, workflow.Do.First().Value, null, "/do", endNode, startNode));
+ graph.AddNode(startNode);
+ graph.AddNode(endNode);
+ var nextNode = endNode;
+ if (!isEmpty)
+ {
+ nextNode = this.BuildTaskNode(new(workflow, graph, 0, workflow.Do.First().Key, workflow.Do.First().Value, null, "/do", endNode, startNode));
+ }
+ this.BuildEdge(graph, startNode, nextNode);
sw.Stop();
Console.WriteLine($"WorkflowGraphBuilder.Build took {sw.ElapsedMilliseconds} ms");
return graph;
@@ -72,30 +77,29 @@ public async Task Build(WorkflowDefinition workflow)
protected virtual NodeViewModel BuildStartNode(bool hasSuccessor = false) => new StartNodeViewModel(hasSuccessor);
///
- /// Recursively builds task nodes and their edges
+ /// Gets the next in the graph
///
/// The rendering context for the task nodes
- /// The last built task
- protected async Task BuildTaskNodesAsync(TaskNodeRenderingContext context)
+ /// The current task node
+ /// A transition, if different from the context task definition's
+ /// The next task
+ ///
+ protected NodeViewModel GetNextNode(TaskNodeRenderingContext context, NodeViewModel currentNode, string? transition = null)
{
- var lastNode = await this.BuildTaskNodeAsync(context);
- if (context.TaskDefinition.Then == FlowDirective.End || context.TaskDefinition.Then == FlowDirective.Exit) await this.BuildEdgeAsync(context.Graph, lastNode, context.EndNode);
- else
- {
- var nextTaskName = string.IsNullOrWhiteSpace(context.TaskDefinition.Then) || context.TaskDefinition.Then == FlowDirective.Continue
+ transition = !string.IsNullOrWhiteSpace(transition) ? transition : context.TaskDefinition.Then;
+ if (transition == FlowDirective.End || transition == FlowDirective.Exit) return context.EndNode;
+ var nextTaskName = string.IsNullOrWhiteSpace(transition) || transition == FlowDirective.Continue
? context.Workflow.GetTaskAfter(new(context.TaskName, context.TaskDefinition), context.ParentReference)?.Key
- : context.TaskDefinition.Then;
- if (string.IsNullOrWhiteSpace(nextTaskName)) await this.BuildEdgeAsync(context.Graph, lastNode, context.EndNode);
- else
- {
- var nextTaskIndex = context.Workflow.IndexOf(nextTaskName, context.ParentReference);
- var nextTaskReference = $"{context.ParentReference}/{nextTaskIndex}/{nextTaskName}";
- var nextTask = context.Workflow.GetComponent(nextTaskReference) ?? throw new Exception($"Failed to find the task at '{nextTaskReference}' in workflow '{context.Workflow.Document.Name}.{context.Workflow.Document.Namespace}:{context.Workflow.Document.Version}'");
- var nextTaskNode = await this.BuildTaskNodesAsync(new(context.Workflow, context.Graph, nextTaskIndex, nextTaskName, nextTask, context.TaskGroup, context.ParentReference, context.EndNode, lastNode));
- await this.BuildEdgeAsync(context.Graph, lastNode, nextTaskNode);
- }
+ : transition;
+ if (string.IsNullOrWhiteSpace(nextTaskName)) return context.EndNode;
+ var nextTaskIndex = context.Workflow.IndexOf(nextTaskName, context.ParentReference);
+ var nextTaskReference = $"{context.ParentReference}/{nextTaskIndex}/{nextTaskName}";
+ var nextTask = context.Workflow.GetComponent(nextTaskReference) ?? throw new Exception($"Failed to find the task at '{nextTaskReference}' in workflow '{context.Workflow.Document.Name}.{context.Workflow.Document.Namespace}:{context.Workflow.Document.Version}'");
+ if (!context.Graph.AllNodes.ContainsKey(nextTaskReference))
+ {
+ this.BuildTaskNode(new(context.Workflow, context.Graph, nextTaskIndex, nextTaskName, nextTask, context.TaskGroup, context.ParentReference, context.EndNode, currentNode));
}
- return lastNode;
+ return (NodeViewModel)context.Graph.AllNodes[nextTaskReference];
}
///
@@ -103,23 +107,23 @@ protected async Task BuildTaskNodesAsync(TaskNodeRenderingContext
///
/// The rendering context for the task node
/// A new
- protected async Task BuildTaskNodeAsync(TaskNodeRenderingContext context)
+ protected NodeViewModel BuildTaskNode(TaskNodeRenderingContext context)
{
ArgumentNullException.ThrowIfNull(context);
return context.TaskDefinition switch
{
- CallTaskDefinition => await this.BuildCallTaskNodeAsync(context.OfType()),
- DoTaskDefinition => await this.BuildDoTaskNodeAsync(context.OfType()),
- EmitTaskDefinition => await this.BuildEmitTaskNodeAsync(context.OfType()),
- ExtensionTaskDefinition => await this.BuildExtensionTaskNodeAsync(context.OfType()),
- ForTaskDefinition => await this.BuildForTaskNodeAsync(context.OfType()),
- ListenTaskDefinition => await this.BuildListenTaskNodeAsync(context.OfType()),
- RaiseTaskDefinition => await this.BuildRaiseTaskNodeAsync(context.OfType()),
- RunTaskDefinition => await this.BuildRunTaskNodeAsync(context.OfType()),
- SetTaskDefinition => await this.BuildSetTaskNodeAsync(context.OfType()),
- SwitchTaskDefinition => await this.BuildSwitchTaskNodeAsync(context.OfType()),
- TryTaskDefinition => await this.BuildTryTaskNodeAsync(context.OfType()),
- WaitTaskDefinition => await this.BuildWaitTaskNodeAsync(context.OfType()),
+ CallTaskDefinition => this.BuildCallTaskNode(context.OfType()),
+ DoTaskDefinition => this.BuildDoTaskNode(context.OfType()),
+ EmitTaskDefinition => this.BuildEmitTaskNode(context.OfType()),
+ ExtensionTaskDefinition => this.BuildExtensionTaskNode(context.OfType()),
+ ForTaskDefinition => this.BuildForTaskNode(context.OfType()),
+ ListenTaskDefinition => this.BuildListenTaskNode(context.OfType()),
+ RaiseTaskDefinition => this.BuildRaiseTaskNode(context.OfType()),
+ RunTaskDefinition => this.BuildRunTaskNode(context.OfType()),
+ SetTaskDefinition => this.BuildSetTaskNode(context.OfType()),
+ SwitchTaskDefinition => this.BuildSwitchTaskNode(context.OfType()),
+ TryTaskDefinition => this.BuildTryTaskNode(context.OfType()),
+ WaitTaskDefinition => this.BuildWaitTaskNode(context.OfType()),
_ => throw new NotSupportedException($"The specified task type '{context.TaskDefinition.GetType()}' is not supported")
} ?? throw new Exception($"Unable to define a last node for task '{context.TaskName}'");
}
@@ -129,7 +133,7 @@ protected async Task BuildTaskNodeAsync(TaskNodeRenderingContext
///
/// The rendering context for the call task node
/// A new
- protected virtual async Task BuildCallTaskNodeAsync(TaskNodeRenderingContext context)
+ protected virtual NodeViewModel BuildCallTaskNode(TaskNodeRenderingContext context)
{
ArgumentNullException.ThrowIfNull(context);
var content = string.Empty;
@@ -169,11 +173,11 @@ protected virtual async Task BuildCallTaskNodeAsync(TaskNodeRende
callType = string.Empty;
break;
}
- var lastNode = new CallTaskNodeViewModel(context.TaskName, content, callType);
- if (context.TaskGroup == null) await context.Graph.AddElementAsync(lastNode);
- else await context.TaskGroup.AddChildAsync(lastNode);
- await this.BuildEdgeAsync(context.Graph, context.PreviousNode, lastNode);
- return lastNode;
+ var node = new CallTaskNodeViewModel(context.TaskReference, context.TaskName, content, callType);
+ if (context.TaskGroup == null) context.Graph.AddNode(node);
+ else context.TaskGroup.AddChild(node);
+ this.BuildEdge(context.Graph, node, this.GetNextNode(context, node));
+ return node;
}
///
@@ -181,15 +185,15 @@ protected virtual async Task BuildCallTaskNodeAsync(TaskNodeRende
///
/// The rendering context for the do task node
/// A new
- protected virtual async Task BuildDoTaskNodeAsync(TaskNodeRenderingContext context)
+ protected virtual NodeViewModel BuildDoTaskNode(TaskNodeRenderingContext context)
{
ArgumentNullException.ThrowIfNull(context);
var taskCount = context.TaskDefinition.Do.Count;
- var lastNode = new DoTaskNodeViewModel(context.TaskName, $"{taskCount} task{(taskCount > 1 ? "s": "")}");
- if (context.TaskGroup == null) await context.Graph.AddElementAsync(lastNode);
- else await context.TaskGroup.AddChildAsync(lastNode);
- await this.BuildEdgeAsync(context.Graph, context.PreviousNode, lastNode);
- return lastNode;
+ var node = new DoTaskNodeViewModel(context.TaskReference, context.TaskName, $"{taskCount} task{(taskCount > 1 ? "s": "")}");
+ if (context.TaskGroup == null) context.Graph.AddNode(node);
+ else context.TaskGroup.AddChild(node);
+ this.BuildEdge(context.Graph, node, this.GetNextNode(context, node));
+ return node;
}
///
@@ -197,14 +201,14 @@ protected virtual async Task BuildDoTaskNodeAsync(TaskNodeRenderi
///
/// The rendering context for the emit task node
/// A new
- protected virtual async Task BuildEmitTaskNodeAsync(TaskNodeRenderingContext context)
+ protected virtual NodeViewModel BuildEmitTaskNode(TaskNodeRenderingContext context)
{
ArgumentNullException.ThrowIfNull(context);
- var lastNode = new EmitTaskNodeViewModel(context.TaskName, this.YamlSerializer.SerializeToText(context.TaskDefinition.Emit.Event.With));
- if (context.TaskGroup == null) await context.Graph.AddElementAsync(lastNode);
- else await context.TaskGroup.AddChildAsync(lastNode);
- await this.BuildEdgeAsync(context.Graph, context.PreviousNode, lastNode);
- return lastNode;
+ var node = new EmitTaskNodeViewModel(context.TaskReference, context.TaskName, this.YamlSerializer.SerializeToText(context.TaskDefinition.Emit.Event.With));
+ if (context.TaskGroup == null) context.Graph.AddNode(node);
+ else context.TaskGroup.AddChild(node);
+ this.BuildEdge(context.Graph, node, this.GetNextNode(context, node));
+ return node;
}
///
@@ -212,14 +216,14 @@ protected virtual async Task BuildEmitTaskNodeAsync(TaskNodeRende
///
/// The rendering context for the extension task node
/// A new
- protected virtual async Task BuildExtensionTaskNodeAsync(TaskNodeRenderingContext context)
+ protected virtual NodeViewModel BuildExtensionTaskNode(TaskNodeRenderingContext context)
{
ArgumentNullException.ThrowIfNull(context);
- var lastNode = new ExtensionTaskNodeViewModel(context.TaskName);
- if (context.TaskGroup == null) await context.Graph.AddElementAsync(lastNode);
- else await context.TaskGroup.AddChildAsync(lastNode);
- await this.BuildEdgeAsync(context.Graph, context.PreviousNode, lastNode);
- return lastNode;
+ var node = new ExtensionTaskNodeViewModel(context.TaskReference, context.TaskName);
+ if (context.TaskGroup == null) context.Graph.AddNode(node);
+ else context.TaskGroup.AddChild(node);
+ this.BuildEdge(context.Graph, node, this.GetNextNode(context, node));
+ return node;
}
///
@@ -227,14 +231,14 @@ protected virtual async Task BuildExtensionTaskNodeAsync(TaskNode
///
/// The rendering context for the for task node
/// A new
- protected virtual async Task BuildForTaskNodeAsync(TaskNodeRenderingContext context)
+ protected virtual NodeViewModel BuildForTaskNode(TaskNodeRenderingContext context)
{
ArgumentNullException.ThrowIfNull(context);
- var lastNode = new ForTaskNodeViewModel(context.TaskName, this.YamlSerializer.SerializeToText(context.TaskDefinition.For));
- if (context.TaskGroup == null) await context.Graph.AddElementAsync(lastNode);
- else await context.TaskGroup.AddChildAsync(lastNode);
- await this.BuildEdgeAsync(context.Graph, context.PreviousNode, lastNode);
- return lastNode;
+ var node = new ForTaskNodeViewModel(context.TaskReference, context.TaskName, this.YamlSerializer.SerializeToText(context.TaskDefinition.For));
+ if (context.TaskGroup == null) context.Graph.AddNode(node);
+ else context.TaskGroup.AddChild(node);
+ this.BuildEdge(context.Graph, node, this.GetNextNode(context, node));
+ return node;
}
///
@@ -242,14 +246,14 @@ protected virtual async Task BuildForTaskNodeAsync(TaskNodeRender
///
/// The rendering context for the listen task node
/// A new
- protected virtual async Task BuildListenTaskNodeAsync(TaskNodeRenderingContext context)
+ protected virtual NodeViewModel BuildListenTaskNode(TaskNodeRenderingContext context)
{
ArgumentNullException.ThrowIfNull(context);
- var lastNode = new ListenTaskNodeViewModel(context.TaskName, this.YamlSerializer.SerializeToText(context.TaskDefinition.Listen));
- if (context.TaskGroup == null) await context.Graph.AddElementAsync(lastNode);
- else await context.TaskGroup.AddChildAsync(lastNode);
- await this.BuildEdgeAsync(context.Graph, context.PreviousNode, lastNode);
- return lastNode;
+ var node = new ListenTaskNodeViewModel(context.TaskReference, context.TaskName, this.YamlSerializer.SerializeToText(context.TaskDefinition.Listen));
+ if (context.TaskGroup == null) context.Graph.AddNode(node);
+ else context.TaskGroup.AddChild(node);
+ this.BuildEdge(context.Graph, node, this.GetNextNode(context, node));
+ return node;
}
///
@@ -257,14 +261,14 @@ protected virtual async Task BuildListenTaskNodeAsync(TaskNodeRen
///
/// The rendering context for the raise task node
/// A new
- protected virtual async Task BuildRaiseTaskNodeAsync(TaskNodeRenderingContext context)
+ protected virtual NodeViewModel BuildRaiseTaskNode(TaskNodeRenderingContext context)
{
ArgumentNullException.ThrowIfNull(context);
- var lastNode = new RaiseTaskNodeViewModel(context.TaskName, this.YamlSerializer.SerializeToText(context.TaskDefinition.Raise.Error));
- if (context.TaskGroup == null) await context.Graph.AddElementAsync(lastNode);
- else await context.TaskGroup.AddChildAsync(lastNode);
- await this.BuildEdgeAsync(context.Graph, context.PreviousNode, lastNode);
- return lastNode;
+ var node = new RaiseTaskNodeViewModel(context.TaskReference, context.TaskName, this.YamlSerializer.SerializeToText(context.TaskDefinition.Raise.Error));
+ if (context.TaskGroup == null) context.Graph.AddNode(node);
+ else context.TaskGroup.AddChild(node);
+ this.BuildEdge(context.Graph, node, this.GetNextNode(context, node));
+ return node;
}
///
@@ -272,7 +276,7 @@ protected virtual async Task BuildRaiseTaskNodeAsync(TaskNodeRend
///
/// The rendering context for the run task node
/// A new
- protected virtual async Task BuildRunTaskNodeAsync(TaskNodeRenderingContext context)
+ protected virtual NodeViewModel BuildRunTaskNode(TaskNodeRenderingContext context)
{
ArgumentNullException.ThrowIfNull(context);
string content = string.Empty;
@@ -307,11 +311,11 @@ protected virtual async Task BuildRunTaskNodeAsync(TaskNodeRender
runType = string.Empty;
break;
}
- var lastNode = new RunTaskNodeViewModel(context.TaskName, content, runType);
- if (context.TaskGroup == null) await context.Graph.AddElementAsync(lastNode);
- else await context.TaskGroup.AddChildAsync(lastNode);
- await this.BuildEdgeAsync(context.Graph, context.PreviousNode, lastNode);
- return lastNode;
+ var node = new RunTaskNodeViewModel(context.TaskReference, context.TaskName, content, runType);
+ if (context.TaskGroup == null) context.Graph.AddNode(node);
+ else context.TaskGroup.AddChild(node);
+ this.BuildEdge(context.Graph, node, this.GetNextNode(context, node));
+ return node;
}
///
@@ -319,14 +323,14 @@ protected virtual async Task BuildRunTaskNodeAsync(TaskNodeRender
///
/// The rendering context for the set task node
/// A new
- protected virtual async Task BuildSetTaskNodeAsync(TaskNodeRenderingContext context)
+ protected virtual NodeViewModel BuildSetTaskNode(TaskNodeRenderingContext context)
{
ArgumentNullException.ThrowIfNull(context);
- var lastNode = new SetTaskNodeViewModel(context.TaskName, this.YamlSerializer.SerializeToText(context.TaskDefinition.Set));
- if (context.TaskGroup == null) await context.Graph.AddElementAsync(lastNode);
- else await context.TaskGroup.AddChildAsync(lastNode);
- await this.BuildEdgeAsync(context.Graph, context.PreviousNode, lastNode);
- return lastNode;
+ var node = new SetTaskNodeViewModel(context.TaskReference, context.TaskName, this.YamlSerializer.SerializeToText(context.TaskDefinition.Set));
+ if (context.TaskGroup == null) context.Graph.AddNode(node);
+ else context.TaskGroup.AddChild(node);
+ this.BuildEdge(context.Graph, node, this.GetNextNode(context, node));
+ return node;
}
///
@@ -334,14 +338,23 @@ protected virtual async Task BuildSetTaskNodeAsync(TaskNodeRender
///
/// The rendering context for the switch task node
/// A new
- protected virtual async Task BuildSwitchTaskNodeAsync(TaskNodeRenderingContext context)
+ protected virtual NodeViewModel BuildSwitchTaskNode(TaskNodeRenderingContext context)
{
ArgumentNullException.ThrowIfNull(context);
- var lastNode = new SwitchTaskNodeViewModel(context.TaskName, this.YamlSerializer.SerializeToText(context.TaskDefinition.Switch));
- if (context.TaskGroup == null) await context.Graph.AddElementAsync(lastNode);
- else await context.TaskGroup.AddChildAsync(lastNode);
- await this.BuildEdgeAsync(context.Graph, context.PreviousNode, lastNode);
- return lastNode;
+ var node = new SwitchTaskNodeViewModel(context.TaskReference, context.TaskName, this.YamlSerializer.SerializeToText(context.TaskDefinition.Switch));
+ if (context.TaskGroup == null) context.Graph.AddNode(node);
+ else context.TaskGroup.AddChild(node);
+ foreach (var switchCase in context.TaskDefinition.Switch)
+ {
+ var nextTaskNode = this.GetNextNode(context, node, switchCase.Value.Then);
+ this.BuildEdge(context.Graph, node, nextTaskNode, switchCase.Key);
+ //node = nextTaskNode;
+ }
+ if (!context.TaskDefinition.Switch.Any(switchCase => string.IsNullOrEmpty(switchCase.Value.When)))
+ {
+ this.BuildEdge(context.Graph, node, this.GetNextNode(context, node));
+ }
+ return node;
}
///
@@ -349,15 +362,15 @@ protected virtual async Task BuildSwitchTaskNodeAsync(TaskNodeRen
///
/// The rendering context for the try task node
/// A new
- protected virtual async Task BuildTryTaskNodeAsync(TaskNodeRenderingContext context)
+ protected virtual NodeViewModel BuildTryTaskNode(TaskNodeRenderingContext context)
{
ArgumentNullException.ThrowIfNull(context);
var taskCount = context.TaskDefinition.Try.Count;
- var lastNode = new TryTaskNodeViewModel(context.TaskName, $"{taskCount} task{(taskCount > 1 ? "s" : "")}");
- if (context.TaskGroup == null) await context.Graph.AddElementAsync(lastNode);
- else await context.TaskGroup.AddChildAsync(lastNode);
- await this.BuildEdgeAsync(context.Graph, context.PreviousNode, lastNode);
- return lastNode;
+ var node = new TryTaskNodeViewModel(context.TaskReference, context.TaskName, $"{taskCount} task{(taskCount > 1 ? "s" : "")}");
+ if (context.TaskGroup == null) context.Graph.AddNode(node);
+ else context.TaskGroup.AddChild(node);
+ this.BuildEdge(context.Graph, node, this.GetNextNode(context, node));
+ return node;
}
///
@@ -365,14 +378,14 @@ protected virtual async Task BuildTryTaskNodeAsync(TaskNodeRender
///
/// The rendering context for the wait task node
/// A new
- protected virtual async Task BuildWaitTaskNodeAsync(TaskNodeRenderingContext context)
+ protected virtual NodeViewModel BuildWaitTaskNode(TaskNodeRenderingContext context)
{
ArgumentNullException.ThrowIfNull(context);
- var lastNode = new WaitTaskNodeViewModel(context.TaskName, context.TaskDefinition.Wait.ToTimeSpan().ToString("hh\\:mm\\:ss\\.fff"));
- if (context.TaskGroup == null) await context.Graph.AddElementAsync(lastNode);
- else await context.TaskGroup.AddChildAsync(lastNode);
- await this.BuildEdgeAsync(context.Graph, context.PreviousNode, lastNode);
- return lastNode;
+ var node = new WaitTaskNodeViewModel(context.TaskReference, context.TaskName, context.TaskDefinition.Wait.ToTimeSpan().ToString("hh\\:mm\\:ss\\.fff"));
+ if (context.TaskGroup == null) context.Graph.AddNode(node);
+ else context.TaskGroup.AddChild(node);
+ this.BuildEdge(context.Graph, node, this.GetNextNode(context, node));
+ return node;
}
///
@@ -387,8 +400,21 @@ protected virtual async Task BuildWaitTaskNodeAsync(TaskNodeRende
/// The current
/// The node to draw the edge from
/// The node to draw the edge to
+ /// The edge label, if any
/// A new awaitable
- protected virtual Task BuildEdgeAsync(GraphViewModel graph, NodeViewModel source, NodeViewModel target) => graph.AddElementAsync(new EdgeViewModel(source.Id, target.Id, null));
+ protected virtual void BuildEdge(GraphViewModel graph, NodeViewModel source, NodeViewModel target, string? label = null)
+ {
+ var existingEdge = graph.Edges.Select(keyValuePair => keyValuePair.Value).FirstOrDefault(edge => edge.SourceId == source.Id && edge.TargetId == target.Id);
+ if (existingEdge != null)
+ {
+ if (!string.IsNullOrEmpty(label)) {
+ existingEdge.Label = existingEdge.Label + " / " + label;
+ }
+ return;
+ }
+ if (graph.Edges.Select(keyValuePair => keyValuePair.Value).Any(edge => edge.SourceId == source.Id && edge.TargetId == target.Id && edge.Label == label)) return;
+ graph.AddEdge(new EdgeViewModel(source.Id, target.Id, label));
+ }
///
/// Represents the context for rendering a task node within a workflow.
diff --git a/src/dashboard/Synapse.Dashboard/Synapse.Dashboard.csproj b/src/dashboard/Synapse.Dashboard/Synapse.Dashboard.csproj
index 23519f509..9431650cb 100644
--- a/src/dashboard/Synapse.Dashboard/Synapse.Dashboard.csproj
+++ b/src/dashboard/Synapse.Dashboard/Synapse.Dashboard.csproj
@@ -34,7 +34,8 @@
-
+
+
diff --git a/src/runner/Synapse.Runner/Synapse.Runner.csproj b/src/runner/Synapse.Runner/Synapse.Runner.csproj
index 1c5f70b4a..c8bc88f38 100644
--- a/src/runner/Synapse.Runner/Synapse.Runner.csproj
+++ b/src/runner/Synapse.Runner/Synapse.Runner.csproj
@@ -40,11 +40,11 @@
-
-
-
-
-
+
+
+
+
+
diff --git a/tests/Synapse.UnitTests/Synapse.UnitTests.csproj b/tests/Synapse.UnitTests/Synapse.UnitTests.csproj
index fea3207f3..4606f124a 100644
--- a/tests/Synapse.UnitTests/Synapse.UnitTests.csproj
+++ b/tests/Synapse.UnitTests/Synapse.UnitTests.csproj
@@ -19,9 +19,9 @@
-
-
-
+
+
+