Skip to content

Commit 44e4c2d

Browse files
Thierry Habarthabarthierry-hue
authored andcommitted
Ticket #6 : Start to develop UI to display case instance
1 parent 2f770d8 commit 44e4c2d

24 files changed

Lines changed: 687 additions & 91 deletions

src/CaseManagement.CMMN/Apis/CaseInstancesController.cs

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public CaseInstancesController(ICreateCaseInstanceCommandHandler createCaseInsta
3636
public async Task<IActionResult> Search()
3737
{
3838
var query = HttpContext.Request.Query;
39-
var result = await _processFlowInstanceQueryRepository.Find(ExtractFindParameter(query));
39+
var result = await _processFlowInstanceQueryRepository.Find(ExtractFindWorkflowInstanceParameter(query));
4040
return new OkObjectResult(ToDto(result));
4141
}
4242

@@ -77,14 +77,40 @@ public async Task<IActionResult> Get(string id)
7777
return new OkObjectResult(ToDto(flowInstance));
7878
}
7979

80-
private static FindWorkflowInstanceParameter ExtractFindParameter(IQueryCollection query)
80+
[HttpGet("{id}/steps/.search")]
81+
public async Task<IActionResult> SearchExecutionSteps(string id)
82+
{
83+
var query = HttpContext.Request.Query;
84+
var parameter = ExtractFindExecutionStepsParameter(query);
85+
parameter.ProcessFlowInstanceId = id;
86+
var executionSteps = await _processFlowInstanceQueryRepository.FindExecutionSteps(parameter);
87+
return new OkObjectResult(ToDto(executionSteps));
88+
}
89+
90+
private static FindWorkflowInstanceParameter ExtractFindWorkflowInstanceParameter(IQueryCollection query)
8191
{
82-
int startIndex;
83-
int count;
84-
string orderBy;
8592
string templateId;
86-
FindOrders findOrder;
8793
var parameter = new FindWorkflowInstanceParameter();
94+
if (query.TryGet("template_id", out templateId))
95+
{
96+
parameter.ProcessFlowTemplateId = templateId;
97+
}
98+
ExtractFindParameter(query, parameter);
99+
return parameter;
100+
}
101+
102+
private static FindExecutionStepsParameter ExtractFindExecutionStepsParameter(IQueryCollection query)
103+
{
104+
var parameter = new FindExecutionStepsParameter();
105+
ExtractFindParameter(query, parameter);
106+
return parameter;
107+
}
108+
109+
private static void ExtractFindParameter(IQueryCollection query, BaseFindParameter parameter)
110+
{
111+
int startIndex, count;
112+
string orderBy;
113+
FindOrders findOrder;
88114
if (query.TryGet("start_index", out startIndex))
89115
{
90116
parameter.StartIndex = startIndex;
@@ -104,13 +130,23 @@ private static FindWorkflowInstanceParameter ExtractFindParameter(IQueryCollecti
104130
{
105131
parameter.Order = findOrder;
106132
}
133+
}
107134

108-
if (query.TryGet("template_id", out templateId))
135+
private static JObject ToDto(FindResponse<ProcessFlowInstanceExecutionStep> resp)
136+
{
137+
return new JObject
109138
{
110-
parameter.ProcessFlowTemplateId = templateId;
111-
}
112-
113-
return parameter;
139+
{ "start_index", resp.StartIndex },
140+
{ "total_length", resp.TotalLength },
141+
{ "count", resp.Count },
142+
{ "content", new JArray(resp.Content.Select(r => new JObject
143+
{
144+
{ "start_datetime", r.StartDateTime },
145+
{ "end_datetime", r.EndDateTime },
146+
{ "name", r.Element.Name },
147+
{ "id", r.Element.Id }
148+
})) }
149+
};
114150
}
115151

116152
private static JObject ToDto(FindResponse<ProcessFlowInstance> resp)
@@ -137,6 +173,8 @@ private static JObject ToDto(ProcessFlowInstance flowInstance)
137173
{
138174
{ "id", flowInstance.Id },
139175
{ "create_datetime", flowInstance.CreateDateTime },
176+
{ "template_id", flowInstance.ProcessFlowTemplateId },
177+
{ "name", flowInstance.ProcessFlowName },
140178
{ "status", Enum.GetName(typeof(ProcessFlowInstanceStatus), flowInstance.Status).ToLowerInvariant() }
141179
};
142180
var planItems = new JArray();

src/CaseManagement.Website/Startup.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,14 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env)
4747
{
4848
var angularRoutes = new[] {
4949
"/home",
50-
"/about"
50+
"/about",
51+
"/casedefinitions",
52+
"/caseinstances"
5153
};
5254

5355
app.Use(async (context, next) =>
5456
{
55-
if (context.Request.Path.HasValue && null != angularRoutes.FirstOrDefault(
56-
(ar) => context.Request.Path.Value.StartsWith(ar, StringComparison.OrdinalIgnoreCase)))
57+
if (context.Request.Path.HasValue && null != angularRoutes.FirstOrDefault((ar) => context.Request.Path.Value.StartsWith(ar, StringComparison.OrdinalIgnoreCase)))
5758
{
5859
context.Request.Path = new PathString("/");
5960
}

src/CaseManagement.Website/angularApp/app/casedefinitions/case-def/case-def.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,10 @@
107107
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
108108
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
109109
</table>
110-
<div *ngIf="isCaseInstancesLoading" class="center-spinner">
110+
<div *ngIf="isCaseExecutionStepsLoaded" class="center-spinner">
111111
<mat-spinner></mat-spinner>
112112
</div>
113-
<div *ngIf="isCaseInstancesErrorLoadOccured" class="error">
113+
<div *ngIf="isCaseExecutionStepsErrorLoadOccured" class="error">
114114
<p>{{ "ERROR_LOAD_CASE_INSTANCES" | translate }}</p>
115115
</div>
116116
<mat-paginator [length]="length" [pageSize]="5" [pageSizeOptions]="[5, 10, 25, 100]"></mat-paginator>

src/CaseManagement.Website/angularApp/app/casedefinitions/models/search-case-execution-steps-result.model.js

Lines changed: 34 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/CaseManagement.Website/angularApp/app/casedefinitions/models/search-case-execution-steps-result.model.js.map

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
export class SearchCaseExecutionStepItem {
2+
Id: string;
3+
Name: string;
4+
StartDateTime: Date;
5+
EndDateTime: Date;
6+
7+
public static fromJson(json: any): SearchCaseExecutionStepItem {
8+
let result = new SearchCaseExecutionStepItem();
9+
result.Id = json["id"];
10+
result.Name = json["name"];
11+
result.StartDateTime = json["start_datetime"];
12+
result.EndDateTime = json["end_datetime"];
13+
return result;
14+
}
15+
}
16+
17+
export class SearchCaseExecutionStepsResult {
18+
StartIndex: number;
19+
Count: number;
20+
TotalLength: number;
21+
Content: SearchCaseExecutionStepItem[];
22+
23+
public static fromJson(json: any): SearchCaseExecutionStepsResult
24+
{
25+
let result = new SearchCaseExecutionStepsResult();
26+
result.StartIndex = json["start_index"];
27+
result.Count = json["count"];
28+
result.TotalLength = json["total_length"];
29+
let content: SearchCaseExecutionStepItem[] = [];
30+
if (json["content"]) {
31+
json["content"].forEach(function (c: any) {
32+
content.push(SearchCaseExecutionStepItem.fromJson(c));
33+
});
34+
}
35+
36+
result.Content = content;
37+
return result;
38+
}
39+
}

src/CaseManagement.Website/angularApp/app/casedefinitions/models/search-case-instances-result.model.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,24 @@
1+
export class CaseInstancePlanItem {
2+
Id: string;
3+
Name: string;
4+
Status: string;
5+
6+
public static fromJson(json: any): CaseInstancePlanItem {
7+
let result = new CaseInstancePlanItem();
8+
result.Id = json["id"];
9+
result.Name = json["name"];
10+
result.Status = json["status"];
11+
return result;
12+
}
13+
}
14+
115
export class CaseInstance {
216
Id: string;
317
Name: string;
418
Status: string;
519
TemplateId: string;
620
CreateDateTime: Date;
21+
PlanItems: CaseInstancePlanItem[];
722

823
public static fromJson(json: any): CaseInstance {
924
let result = new CaseInstance();
@@ -12,6 +27,14 @@ export class CaseInstance {
1227
result.Status = json["status"];
1328
result.TemplateId = json["template_id"];
1429
result.CreateDateTime = json["create_datetime"];
30+
let items: CaseInstancePlanItem[] = [];
31+
if (json["items"]) {
32+
json["items"].forEach(function (i : any) {
33+
items.push(CaseInstancePlanItem.fromJson(i));
34+
});
35+
}
36+
37+
result.PlanItems = items;
1538
return result;
1639
}
1740
}

src/CaseManagement.Website/angularApp/app/casedefinitions/services/caseinstances.service.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,23 @@ import { Injectable } from '@angular/core';
33
import { Observable } from 'rxjs';
44
import { map } from 'rxjs/operators';
55
import { SearchCaseInstancesResult, CaseInstance } from '../models/search-case-instances-result.model';
6+
import { SearchCaseExecutionStepsResult } from '../models/search-case-execution-steps-result.model';
67

78
const url = "http://localhost:54942";
89

910
@Injectable()
1011
export class CaseInstancesService {
1112
constructor(private http: HttpClient) { }
1213

14+
get(caseInstanceId: string): Observable<CaseInstance> {
15+
let targetUrl = url + "/case-instances/" + caseInstanceId;
16+
let headers = new HttpHeaders();
17+
headers = headers.set('Accept', 'application/json');
18+
return this.http.get(targetUrl, { headers: headers }).pipe(map((res: any) => {
19+
return CaseInstance.fromJson(res);
20+
}));
21+
}
22+
1323
create(caseDefId: string, caseId: string) : Observable<CaseInstance> {
1424
const request = JSON.stringify({ case_definition_id: caseDefId, case_id: caseId });
1525
let targetUrl = url + "/case-instances";
@@ -44,4 +54,21 @@ export class CaseInstancesService {
4454
return SearchCaseInstancesResult.fromJson(res);
4555
}));
4656
}
57+
58+
searchExecutionSteps(startIndex: number, count: number, caseInstanceId: string, order: string, direction: string): Observable<SearchCaseExecutionStepsResult> {
59+
let headers = new HttpHeaders();
60+
headers = headers.set('Accept', 'application/json');
61+
let targetUrl = url + "/case-instances/" + caseInstanceId + "/steps/.search?start_index=" + startIndex + "&count=" + count;
62+
if (order) {
63+
targetUrl = targetUrl + "&order_by=" + order;
64+
}
65+
66+
if (direction) {
67+
targetUrl = targetUrl + "&order=" + direction;
68+
}
69+
70+
return this.http.get(targetUrl, { headers: headers }).pipe(map((res: any) => {
71+
return SearchCaseExecutionStepsResult.fromJson(res);
72+
}));
73+
}
4774
}
Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,25 @@
1+
import { Action } from '@ngrx/store';
2+
import { CaseDefinition } from '../../casedefinitions/models/case-def.model';
3+
import { CaseInstance } from '../../casedefinitions/models/search-case-instances-result.model';
4+
import { SearchCaseExecutionStepsResult } from '../../casedefinitions/models/search-case-execution-steps-result.model';
5+
16
export enum ActionTypes {
2-
}
7+
CASEINSTANCELOAD = "[CaseInstance] Load",
8+
CASEINSTANCELOADED = "[CaseInstance] Loaded",
9+
ERRORLOADCASEINSTANCE = "[CaseInstance] Error Load",
10+
CASEEXECUTIONSSTEPSLOAD = "[CaseExecutionSteps] Load",
11+
CASEEXECUTIONSTEPSLOADED = "[CaseExecutionSteps] Loaded",
12+
ERRORLOADCASEEXECUTIONSTEPS = "[CaseExecutionSteps] Error Load"
13+
}
14+
15+
export class CaseInstanceLoadedAction implements Action {
16+
type = ActionTypes.CASEINSTANCELOAD
17+
constructor(public caseInstance : CaseInstance, public caseDefinition : CaseDefinition) { }
18+
}
19+
20+
export class CaseExecutionStepsLoadedAction implements Action {
21+
type = ActionTypes.CASEEXECUTIONSTEPSLOADED
22+
constructor(public result: SearchCaseExecutionStepsResult) { }
23+
}
24+
25+
export type ActionsUnion = CaseInstanceLoadedAction | CaseExecutionStepsLoadedAction;
Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,50 @@
11
import { Injectable } from '@angular/core';
2-
// import { Actions } from '@ngrx/effects';
2+
import { Actions, Effect, ofType } from '@ngrx/effects';
3+
import { catchError, mergeMap, map } from 'rxjs/operators';
4+
import { ActionTypes } from './case-instance-actions';
5+
import { CaseDefinitionsService } from '../../casedefinitions/services/casedefinitions.service'
6+
import { CaseInstancesService } from '../../casedefinitions/services/caseinstances.service';
7+
import { CaseInstance } from '../../casedefinitions/models/search-case-instances-result.model';
8+
import { of } from 'rxjs';
39

410
@Injectable()
5-
export class CaseDefEffects {
11+
export class CaseInstanceEffects {
612
constructor(
7-
// private actions$: Actions
13+
private actions$: Actions,
14+
private caseDefinitionsService: CaseDefinitionsService,
15+
private caseInstancesService : CaseInstancesService
816
) { }
17+
18+
@Effect()
19+
loadCaseDef$ = this.actions$
20+
.pipe(
21+
ofType(ActionTypes.CASEINSTANCELOAD),
22+
mergeMap((evt: any) => {
23+
return this.caseInstancesService.get(evt.id)
24+
.pipe(
25+
mergeMap((caseInstance : CaseInstance) => {
26+
return this.caseDefinitionsService.get(caseInstance.TemplateId).pipe(
27+
map(caseDefinition => { return { type: ActionTypes.CASEINSTANCELOADED, caseInstance: caseInstance, caseDefinition: caseDefinition}; }),
28+
catchError(() => of({ type: ActionTypes.ERRORLOADCASEINSTANCE }))
29+
);
30+
}),
31+
catchError(() => of({ type: ActionTypes.ERRORLOADCASEINSTANCE }))
32+
);
33+
}
34+
)
35+
);
36+
37+
@Effect()
38+
loadExecutionSteps = this.actions$
39+
.pipe(
40+
ofType(ActionTypes.CASEEXECUTIONSSTEPSLOAD),
41+
mergeMap((evt: any) => {
42+
return this.caseInstancesService.searchExecutionSteps(evt.startIndex, evt.count, evt.id, evt.order, evt.direction)
43+
.pipe(
44+
map(r => { return { type: ActionTypes.CASEEXECUTIONSTEPSLOADED, result: r }; }),
45+
catchError(() => of({ type: ActionTypes.ERRORLOADCASEEXECUTIONSTEPS }))
46+
);
47+
}
48+
)
49+
);
950
}

0 commit comments

Comments
 (0)