@@ -88,10 +88,10 @@ public IGraphViewModel Build(WorkflowDefinition workflow)
88
88
/// Returns the name, index and reference of the next node
89
89
/// </summary>
90
90
/// <param name="context">The rendering context for the task nodes</param>
91
- /// <param name="currentNode">The current task node </param>
91
+ /// <param name="ignoreConditionalTasks">If true, skips <see cref="TaskDefinition"/> with an if clause </param>
92
92
/// <param name="transition">A transition, if different from the context task definition's</param>
93
93
/// <returns>The next task <see cref="TaskIdentity"/></returns>
94
- protected TaskIdentity ? GetNextTaskIdentity ( TaskNodeRenderingContext context , NodeViewModel currentNode , string ? transition = null )
94
+ protected TaskIdentity ? GetNextTaskIdentity ( TaskNodeRenderingContext context , bool ignoreConditionalTasks , string ? transition = null )
95
95
{
96
96
transition = ! string . IsNullOrWhiteSpace ( transition ) ? transition : context . TaskDefinition . Then ;
97
97
if ( transition == FlowDirective . End ) return null ;
@@ -101,35 +101,55 @@ public IGraphViewModel Build(WorkflowDefinition workflow)
101
101
{
102
102
return null ;
103
103
}
104
- return this . GetNextTaskIdentity ( context . ParentContext , currentNode ) ;
104
+ return this . GetNextTaskIdentity ( context . ParentContext , ignoreConditionalTasks ) ;
105
105
}
106
106
var nextTaskName = string . IsNullOrWhiteSpace ( transition ) || transition == FlowDirective . Continue
107
- ? context . Workflow . GetTaskAfter ( new ( context . TaskName , context . TaskDefinition ) , context . ParentReference ) ? . Key
107
+ ? context . Workflow . GetTaskAfter ( new ( context . TaskName , context . TaskDefinition ) , context . ParentReference , ignoreConditionalTasks ) ? . Key
108
108
: transition ;
109
109
if ( string . IsNullOrWhiteSpace ( nextTaskName ) )
110
110
{
111
111
if ( context . ParentContext == null )
112
112
{
113
113
return null ;
114
114
}
115
- return this . GetNextTaskIdentity ( context . ParentContext , currentNode ) ;
115
+ return this . GetNextTaskIdentity ( context . ParentContext , ignoreConditionalTasks ) ;
116
116
}
117
117
var nextTaskIndex = context . Workflow . IndexOf ( nextTaskName , context . ParentReference ) ;
118
118
var nextTaskReference = $ "{ context . ParentReference } /{ nextTaskIndex } /{ nextTaskName } ";
119
119
return new ( nextTaskName , nextTaskIndex , nextTaskReference , context ) ;
120
120
}
121
121
122
+ /// <summary>
123
+ /// Gets a <see cref="NodeViewModel"/> by reference in the provided <see cref="TaskNodeRenderingContext"/>
124
+ /// </summary>
125
+ /// <param name="context">The source <see cref="TaskNodeRenderingContext"/></param>
126
+ /// <param name="reference">The reference to look for</param>
127
+ /// <returns></returns>
128
+ protected NodeViewModel GetNodeByReference ( TaskNodeRenderingContext context , string reference )
129
+ {
130
+ if ( context . Graph . AllClusters . ContainsKey ( reference ) )
131
+ {
132
+ return ( NodeViewModel ) context . Graph . AllClusters [ reference ] . AllNodes . First ( ) . Value ;
133
+ }
134
+ if ( context . Graph . AllNodes . ContainsKey ( reference ) )
135
+ {
136
+ return ( NodeViewModel ) context . Graph . AllNodes [ reference ] ;
137
+ }
138
+ throw new IndexOutOfRangeException ( $ "Unabled to find the task with reference '{ reference } ' in the provided context.") ;
139
+ }
140
+
122
141
/// <summary>
123
142
/// Gets the next <see cref="NodeViewModel"/> in the graph
124
143
/// </summary>
125
144
/// <param name="context">The rendering context for the task nodes</param>
126
145
/// <param name="currentNode">The current task node</param>
146
+ /// <param name="ignoreConditionalTasks">If true, skips <see cref="TaskDefinition"/> with an if clause</param>
127
147
/// <param name="transition">A transition, if different from the context task definition's</param>
128
148
/// <returns>The next task <see cref="NodeViewModel"/></returns>
129
149
/// <exception cref="Exception"></exception>
130
- protected NodeViewModel GetNextNode ( TaskNodeRenderingContext context , NodeViewModel currentNode , string ? transition = null )
150
+ protected NodeViewModel GetNextNode ( TaskNodeRenderingContext context , NodeViewModel currentNode , bool ignoreConditionalTasks = false , string ? transition = null )
131
151
{
132
- var nextTaskIdentity = this . GetNextTaskIdentity ( context , currentNode , transition ) ;
152
+ var nextTaskIdentity = this . GetNextTaskIdentity ( context , ignoreConditionalTasks , transition ) ;
133
153
if ( nextTaskIdentity == null )
134
154
{
135
155
return context . EndNode ;
@@ -139,11 +159,13 @@ protected NodeViewModel GetNextNode(TaskNodeRenderingContext context, NodeViewMo
139
159
{
140
160
this . BuildTaskNode ( new ( nextTaskIdentity . Context . Workflow , nextTaskIdentity . Context . Graph , nextTaskIdentity . Index , nextTaskIdentity . Name , nextTask , nextTaskIdentity . Context . TaskGroup , nextTaskIdentity . Context . ParentReference , nextTaskIdentity . Context . ParentContext , nextTaskIdentity . Context . EndNode , currentNode ) ) ;
141
161
}
142
- if ( context . Graph . AllClusters . ContainsKey ( nextTaskIdentity . Reference ) )
162
+ if ( string . IsNullOrEmpty ( nextTask . If ) )
143
163
{
144
- return ( NodeViewModel ) context . Graph . AllClusters [ nextTaskIdentity . Reference ] . AllNodes . First ( ) . Value ;
164
+ return this . GetNodeByReference ( context , nextTaskIdentity . Reference ) ;
145
165
}
146
- return ( NodeViewModel ) context . Graph . AllNodes [ nextTaskIdentity . Reference ] ;
166
+ var nextNode = this . GetNodeByReference ( context , nextTaskIdentity . Reference ) ;
167
+ this . BuildEdge ( context . Graph , currentNode , nextNode ) ;
168
+ return this . GetNextNode ( context , currentNode , true , transition ) ;
147
169
}
148
170
149
171
/// <summary>
@@ -239,10 +261,16 @@ protected virtual NodeViewModel BuildDoTaskNode(TaskNodeRenderingContext<DoTaskD
239
261
cluster . AddChild ( port ) ;
240
262
if ( context . TaskGroup == null ) context . Graph . AddCluster ( cluster ) ;
241
263
else context . TaskGroup . AddChild ( cluster ) ;
242
- this . BuildTaskNode ( new ( context . Workflow , context . Graph , 0 , context . TaskDefinition . Do . First ( ) . Key , context . TaskDefinition . Do . First ( ) . Value , cluster , context . TaskReference + "/do" , context , context . EndNode , context . PreviousNode ) ) ;
264
+ var innerContext = new TaskNodeRenderingContext ( context . Workflow , context . Graph , 0 , context . TaskDefinition . Do . First ( ) . Key , context . TaskDefinition . Do . First ( ) . Value , cluster , context . TaskReference + "/do" , context , context . EndNode , context . PreviousNode ) ;
265
+ this . BuildTaskNode ( innerContext ) ;
243
266
if ( taskCount > 0 )
244
267
{
245
- this . BuildEdge ( context . Graph , port , ( NodeViewModel ) cluster . AllNodes . Skip ( 1 ) . First ( ) . Value ) ;
268
+ var firstDoNode = ( NodeViewModel ) cluster . AllNodes . Skip ( 1 ) . First ( ) . Value ;
269
+ this . BuildEdge ( context . Graph , port , firstDoNode ) ;
270
+ if ( taskCount > 1 && ! string . IsNullOrWhiteSpace ( context . TaskDefinition . Do . First ( ) . Value . If ) )
271
+ {
272
+ this . BuildEdge ( context . Graph , port , this . GetNextNode ( innerContext , firstDoNode ) ) ;
273
+ }
246
274
}
247
275
else
248
276
{
@@ -445,7 +473,7 @@ protected virtual NodeViewModel BuildSwitchTaskNode(TaskNodeRenderingContext<Swi
445
473
else context . TaskGroup . AddChild ( node ) ;
446
474
foreach ( var switchCase in context . TaskDefinition . Switch )
447
475
{
448
- var switchCaseNode = this . GetNextNode ( context , node , switchCase . Value . Then ) ;
476
+ var switchCaseNode = this . GetNextNode ( context , node , false , switchCase . Value . Then ) ;
449
477
this . BuildEdge ( context . Graph , node , switchCaseNode , switchCase . Key ) ;
450
478
}
451
479
if ( ! context . TaskDefinition . Switch . Any ( switchCase => string . IsNullOrEmpty ( switchCase . Value . When ) ) )
@@ -475,10 +503,16 @@ protected virtual NodeViewModel BuildTryTaskNode(TaskNodeRenderingContext<TryTas
475
503
tryCluster . AddChild ( tryPort ) ;
476
504
containerCluster . AddChild ( tryCluster ) ;
477
505
this . BuildEdge ( context . Graph , containerPort , tryPort ) ;
478
- this . BuildTaskNode ( new ( context . Workflow , context . Graph , 0 , context . TaskDefinition . Try . First ( ) . Key , context . TaskDefinition . Try . First ( ) . Value , tryCluster , context . TaskReference + "/try" , context , context . EndNode , context . PreviousNode ) ) ;
506
+ var innerContext = new TaskNodeRenderingContext ( context . Workflow , context . Graph , 0 , context . TaskDefinition . Try . First ( ) . Key , context . TaskDefinition . Try . First ( ) . Value , tryCluster , context . TaskReference + "/try" , context , context . EndNode , context . PreviousNode ) ;
507
+ this . BuildTaskNode ( innerContext ) ;
479
508
if ( taskCount > 0 )
480
509
{
481
- this . BuildEdge ( context . Graph , tryPort , tryCluster . AllNodes . Values . Skip ( 1 ) . First ( ) ) ;
510
+ var firstNode = ( NodeViewModel ) tryCluster . AllNodes . Skip ( 1 ) . First ( ) . Value ;
511
+ this . BuildEdge ( context . Graph , tryPort , firstNode ) ;
512
+ if ( taskCount > 1 && ! string . IsNullOrWhiteSpace ( context . TaskDefinition . Try . First ( ) . Value . If ) )
513
+ {
514
+ this . BuildEdge ( context . Graph , tryPort , this . GetNextNode ( innerContext , firstNode ) ) ;
515
+ }
482
516
}
483
517
var catchContent = this . YamlSerializer . SerializeToText ( context . TaskDefinition . Catch ) ;
484
518
if ( context . TaskDefinition . Catch . Do == null || context . TaskDefinition . Catch . Do . Count == 0 )
0 commit comments