11using UvA . Workflow . Api . Submissions . Dtos ;
22using UvA . Workflow . Api . Users . Dtos ;
33using UvA . Workflow . Api . WorkflowDefinitions . Dtos ;
4+ using UvA . Workflow . Events ;
45using UvA . Workflow . Submissions ;
56using UvA . Workflow . Versioning ;
67using UvA . Workflow . WorkflowModel ;
@@ -26,8 +27,6 @@ public async Task<WorkflowInstanceDto> Create(WorkflowInstance instance, Cancell
2627 {
2728 var actions = await instanceService . GetAllowedActions ( instance , ct ) ;
2829 var submissions = await instanceService . GetAllowedSubmissions ( instance , ct ) ;
29- var allowedForms = ( await rightsService . GetAllowedActions ( instance , RoleAction . View ) )
30- . SelectMany ( a => a . AllForms ) . ToArray ( ) ;
3130 var workflowDefinition = modelService . WorkflowDefinitions [ instance . WorkflowDefinition ] ;
3231 var permissions = await rightsService . GetAllowedActions ( instance , RoleAction . ViewAdminTools , RoleAction . Edit ) ;
3332 // Both admin-tool and impersonation visibility are evaluated against the real user (ignoring any
@@ -50,7 +49,11 @@ await instanceService.Enrich(workflowDefinition, [context],
5049 workflowDefinition . Steps . SelectMany ( f => f . Lookups ) . Concat ( relatedUserLookups ) . Concat ( resourceLookups ) , ct ) ;
5150
5251 // Fetch versions for all steps
53- var stepVersionsMap = await GetStepVersionsMap ( instance , workflowDefinition . AllSteps , ct ) ;
52+ var instanceHistory = await workflowInstanceService . GetInstanceHistory ( instance . Id , ct ) ;
53+ var stepVersionsMap = GetStepVersionsMap ( instance , workflowDefinition . AllSteps , instanceHistory . EventLogs ) ;
54+ var steps = await Task . WhenAll ( workflowDefinition . Steps
55+ . Where ( s => s . Condition . IsMet ( context ) )
56+ . Select ( s => CreateStepDto ( s , instance , stepVersionsMap , instanceHistory , context , ct ) ) ) ;
5457
5558 var editActions = permissions . Where ( a => a . Type == RoleAction . Edit ) . ToArray ( ) ;
5659 var canEditByProperty = rightsService . CanEditProperties (
@@ -72,10 +75,7 @@ await instanceService.Enrich(workflowDefinition, [context],
7275 instance . ParentId ,
7376 actions . Select ( ActionDto . Create ) . ToArray ( ) ,
7477 CreateFields ( workflowDefinition , instance . Id , ct ) . Result ?? [ ] ,
75- workflowDefinition . Steps
76- . Where ( s => s . Condition . IsMet ( context ) )
77- . Select ( s => CreateStepDto ( s , instance , stepVersionsMap , context , allowedForms ) )
78- . ToArray ( ) ,
78+ steps ,
7979 submissions
8080 . Select ( s => submissionDtoFactory . Create ( instance , s . Form , s . SubmissionState , s . QuestionStatus ,
8181 permissions . Where ( p => p . MatchesForm ( s . Form . Name ) ) . Select ( p => p . Type ) . ToArray ( ) ) )
@@ -115,20 +115,21 @@ await instanceService.Enrich(workflowDefinition, [context],
115115 }
116116
117117 /// <summary>
118- /// Fetches versions for all steps and returns a dictionary keyed by step name
118+ /// Creates versions for all steps from a preloaded instance-wide event log.
119119 /// </summary>
120- private async Task < Dictionary < string , List < StepVersion > > > GetStepVersionsMap (
120+ private Dictionary < string , List < StepVersion > > GetStepVersionsMap (
121121 WorkflowInstance instance ,
122122 IEnumerable < Step > steps ,
123- CancellationToken ct )
123+ IEnumerable < InstanceEventLogEntry > eventLogs )
124124 {
125+ var eventLogList = eventLogs . ToList ( ) ;
125126 var stepVersionsMap = new Dictionary < string , List < StepVersion > > ( ) ;
126127
127128 foreach ( var step in steps )
128129 {
129130 try
130131 {
131- var versions = await stepVersionService . GetStepVersions ( instance , step . Name , ct ) ;
132+ var versions = stepVersionService . GetStepVersions ( instance , step , eventLogList ) ;
132133 if ( versions . Any ( ) )
133134 {
134135 stepVersionsMap [ step . Name ] = versions ;
@@ -147,15 +148,31 @@ private async Task<Dictionary<string, List<StepVersion>>> GetStepVersionsMap(
147148 /// <summary>
148149 /// Creates a StepDto with versions from the map, recursively handling child steps
149150 /// </summary>
150- private StepDto CreateStepDto (
151+ private async Task < StepDto > CreateStepDto (
151152 Step step ,
152153 WorkflowInstance instance ,
153154 Dictionary < string , List < StepVersion > > stepVersionsMap ,
155+ WorkflowInstanceHistory instanceHistory ,
154156 ObjectContext context ,
155- string [ ] allowedForms )
157+ CancellationToken ct )
156158 {
157159 var workflowDef = modelService . WorkflowDefinitions [ instance . WorkflowDefinition ] ;
158- var versions = stepVersionsMap . GetValueOrDefault ( step . Name ) ;
160+
161+ // The newest version is the step's live state, already rendered as the current submission.
162+ var versions = stepVersionsMap . GetValueOrDefault ( step . Name )
163+ ? . OrderByDescending ( version => version . SubmittedAt )
164+ . Skip ( step . HasEnded ( context ) ? 1 : 0 ) ;
165+
166+ var children = step . Children . Length != 0
167+ ? await Task . WhenAll ( step . Children
168+ . Where ( s => s . Condition . IsMet ( context ) )
169+ . Select ( s => CreateStepDto ( s , instance , stepVersionsMap , instanceHistory , context , ct ) ) )
170+ : null ;
171+ var versionDtos = versions != null
172+ ? await Task . WhenAll ( versions
173+ . OrderByDescending ( version => version . SubmittedAt )
174+ . Select ( version => CreateStepVersionDto ( version , instance , instanceHistory , ct ) ) )
175+ : null ;
159176
160177 return new StepDto (
161178 step . Name ,
@@ -164,32 +181,31 @@ private StepDto CreateStepDto(
164181 step . EndEvent ,
165182 step . GetEndDate ( instance , workflowDef ) ,
166183 step . GetDeadline ( instance , modelService ) ,
167- step . Children . Length != 0
168- ? step . Children
169- . Where ( s => s . Condition . IsMet ( context ) )
170- . Select ( s => CreateStepDto ( s , instance , stepVersionsMap , context , allowedForms ) )
171- . ToArray ( )
172- : null ,
184+ children ,
173185 stepHeaderStatusResolver . Resolve ( step , instance ) ,
174186 step . ResultsType ,
175187 step . HierarchyMode ,
176- versions ? . Select ( v => CreateStepVersionDto ( v , instance , allowedForms ) ) . ToList ( )
188+ versionDtos ? . ToList ( )
177189 ) ;
178190 }
179191
180192 /// <summary>
181193 /// Creates a StepVersionDto with properly constructed SubmissionDtos for all events in the version
182194 /// </summary>
183- private StepVersionDto CreateStepVersionDto ( StepVersion stepVersion , WorkflowInstance instance ,
184- string [ ] allowedForms )
195+ private async Task < StepVersionDto > CreateStepVersionDto (
196+ StepVersion stepVersion ,
197+ WorkflowInstance instance ,
198+ WorkflowInstanceHistory instanceHistory ,
199+ CancellationToken ct )
185200 {
186201 try
187202 {
188203 var submissions = new List < SubmissionDto > ( ) ;
189204
190205 // Get the instance at the version timestamp
191206 var instanceAtVersion = workflowInstanceService
192- . GetAsOfTimestamp ( instance . Id , stepVersion . SubmittedAt , CancellationToken . None ) . Result ;
207+ . GetAsOfTimestamp ( instance , stepVersion . SubmittedAt , instanceHistory ) ;
208+ var allowedViewActions = await rightsService . GetAllowedActions ( instanceAtVersion , RoleAction . View ) ;
193209
194210 // Create a submission for each event in the version
195211 foreach ( var eventId in stepVersion . EventIds )
@@ -202,7 +218,7 @@ private StepVersionDto CreateStepVersionDto(StepVersion stepVersion, WorkflowIns
202218 continue ;
203219 }
204220
205- if ( ! allowedForms . Contains ( form . Name ) )
221+ if ( ! allowedViewActions . Any ( action => action . MatchesForm ( form . Name ) ) )
206222 continue ;
207223
208224 // Get question status with all fields visible (historical view)
0 commit comments