diff options
Diffstat (limited to 'Timeline/ClientApp/src/app')
7 files changed, 53 insertions, 43 deletions
diff --git a/Timeline/ClientApp/src/app/todo-item/todo-item.component.html b/Timeline/ClientApp/src/app/todo-item/todo-item.component.html index 624586cb..bf080e83 100644 --- a/Timeline/ClientApp/src/app/todo-item/todo-item.component.html +++ b/Timeline/ClientApp/src/app/todo-item/todo-item.component.html @@ -1,5 +1,5 @@ <mat-card class="mat-elevation-z2 item-card"> - <span class="item-color-block" [class.color-block-closed]="item.closed" [class.color-block-open]="!item.closed"></span> + <span class="item-color-block" [class.color-block-completed]="item.isCompleted" [class.color-block-resolving]="!item.isCompleted"></span> <!-- Do not move the margin style to class because there is some preset classes on mat-card children making it invalid. --> <div class="mat-h3 item-body-box" style="margin: 5px;"> <img class="item-icon" [src]="item.iconUrl" /> diff --git a/Timeline/ClientApp/src/app/todo-item/todo-item.component.spec.ts b/Timeline/ClientApp/src/app/todo-item/todo-item.component.spec.ts index 245f9141..277eca23 100644 --- a/Timeline/ClientApp/src/app/todo-item/todo-item.component.spec.ts +++ b/Timeline/ClientApp/src/app/todo-item/todo-item.component.spec.ts @@ -22,7 +22,7 @@ describe('TodoItemComponent', () => { mockWorkItem = { id: 0, title: 'Title', - closed: true, + isCompleted: true, detailUrl: '/detail', iconUrl: '/icon' }; diff --git a/Timeline/ClientApp/src/app/todo-list-page/todo-list-color-block.css b/Timeline/ClientApp/src/app/todo-list-page/todo-list-color-block.css index 5e0d4ba9..456e477f 100644 --- a/Timeline/ClientApp/src/app/todo-list-page/todo-list-color-block.css +++ b/Timeline/ClientApp/src/app/todo-list-page/todo-list-color-block.css @@ -1,7 +1,7 @@ -.color-block-open { +.color-block-resolving { background: red; } -.color-block-closed { +.color-block-completed { background: green; } diff --git a/Timeline/ClientApp/src/app/todo-list-page/todo-list-page.component.html b/Timeline/ClientApp/src/app/todo-list-page/todo-list-page.component.html index 3b4809ae..505032a6 100644 --- a/Timeline/ClientApp/src/app/todo-list-page/todo-list-page.component.html +++ b/Timeline/ClientApp/src/app/todo-list-page/todo-list-page.component.html @@ -7,11 +7,11 @@ <div class="space"></div> <div class="sample-box" *ngIf="i === 0"> <div class="mat-caption sample-item"> - <span class="sample-color-block color-block-open"></span> + <span class="sample-color-block color-block-resolving"></span> <span> means working now.</span> </div> <div class="mat-caption sample-item"> - <span class="sample-color-block color-block-closed"></span> + <span class="sample-color-block color-block-completed"></span> <span> means completed.</span> </div> <div class="mat-caption">click on item to see details.</div> diff --git a/Timeline/ClientApp/src/app/todo-list-page/todo-list-page.component.spec.ts b/Timeline/ClientApp/src/app/todo-list-page/todo-list-page.component.spec.ts index 590c5ef0..aed32c9a 100644 --- a/Timeline/ClientApp/src/app/todo-list-page/todo-list-page.component.spec.ts +++ b/Timeline/ClientApp/src/app/todo-list-page/todo-list-page.component.spec.ts @@ -30,9 +30,9 @@ describe('TodoListPageComponent', () => { const todoListService: jasmine.SpyObj<TodoListService> = jasmine.createSpyObj('TodoListService', ['getWorkItemList']); mockWorkItems = [{ - id: 0, title: 'Test title 1', closed: true, detailUrl: 'https://test.org/workitems/0', iconUrl: 'https://test.org/icon/0' + id: 0, title: 'Test title 1', isCompleted: true, detailUrl: 'https://test.org/workitems/0', iconUrl: 'https://test.org/icon/0' }, { - id: 1, title: 'Test title 2', closed: false, detailUrl: 'https://test.org/workitems/1', iconUrl: 'https://test.org/icon/1' + id: 1, title: 'Test title 2', isCompleted: false, detailUrl: 'https://test.org/workitems/1', iconUrl: 'https://test.org/icon/1' }]; todoListService.getWorkItemList.and.returnValue(asyncData(mockWorkItems)); diff --git a/Timeline/ClientApp/src/app/todo-list-page/todo-list.service.spec.ts b/Timeline/ClientApp/src/app/todo-list-page/todo-list.service.spec.ts index 13bae5be..70922623 100644 --- a/Timeline/ClientApp/src/app/todo-list-page/todo-list.service.spec.ts +++ b/Timeline/ClientApp/src/app/todo-list-page/todo-list.service.spec.ts @@ -34,7 +34,7 @@ describe('TodoListServiceService', () => { const mockWorkItems: WorkItem[] = Array.from({ length: 2 }, (_, i) => <WorkItem>{ id: i, title: 'Test work item ' + i, - closed: i === 0, + isCompleted: i === 0, detailUrl: `${baseUrl}_workitems/edit/${i}/`, iconUrl: `${baseUrl}_api/wit/icon/${i}`, }); @@ -66,7 +66,7 @@ describe('TodoListServiceService', () => { id: mockWorkItem.id, fields: { [TodoListService.titleFieldName]: mockWorkItem.title, - [TodoListService.stateFieldName]: (mockWorkItem.closed ? 'Closed' : 'Active'), + [TodoListService.stateFieldName]: (mockWorkItem.isCompleted ? 'Closed' : 'Active'), [TodoListService.typeFieldName]: workItemTypeMap.get(mockWorkItem) } }; diff --git a/Timeline/ClientApp/src/app/todo-list-page/todo-list.service.ts b/Timeline/ClientApp/src/app/todo-list-page/todo-list.service.ts index 17ded67b..af3617fe 100644 --- a/Timeline/ClientApp/src/app/todo-list-page/todo-list.service.ts +++ b/Timeline/ClientApp/src/app/todo-list-page/todo-list.service.ts @@ -26,14 +26,14 @@ export interface WorkItemResult { export interface WorkItemTypeResult { icon: { - url: string + url: string; }; } export interface WorkItem { id: number; title: string; - closed: boolean; + isCompleted: boolean; detailUrl: string; iconUrl: string; } @@ -42,52 +42,62 @@ export interface WorkItem { providedIn: 'root' }) export class TodoListService { - public static titleFieldName = 'System.Title'; public static stateFieldName = 'System.State'; public static typeFieldName = 'System.WorkItemType'; - constructor(private client: HttpClient) { } + constructor(private client: HttpClient) {} private getAzureDevOpsAccessInfo(): Observable<AzureDevOpsAccessInfo> { return this.client.get<AzureDevOpsAccessInfo>('/api/TodoPage/AzureDevOpsAccessInfo'); } private getItemIconUrl(baseUrl: string, headers: HttpHeaders, type: string): Observable<string> { - return this.client.get<WorkItemTypeResult>(`${baseUrl}_apis/wit/workitemtypes/${encodeURIComponent(type)}?api-version=5.0`, { - headers: headers - }).pipe( - map(result => result.icon.url) - ); + return this.client + .get<WorkItemTypeResult>(`${baseUrl}_apis/wit/workitemtypes/${encodeURIComponent(type)}?api-version=5.0`, { + headers: headers + }) + .pipe(map(result => result.icon.url)); } getWorkItemList(): Observable<WorkItem[]> { return this.getAzureDevOpsAccessInfo().pipe( - switchMap( - accessInfo => { - const baseUrl = `https://dev.azure.com/${accessInfo.organization}/${accessInfo.project}/`; - const headers = new HttpHeaders({ - 'Accept': 'application/json', - 'Authorization': `Basic ${btoa(accessInfo.username + ':' + accessInfo.personalAccessToken)}` - }); - return this.client.post<WiqlResult>( - `${baseUrl}_apis/wit/wiql?api-version=5.0`, { + switchMap(accessInfo => { + const baseUrl = `https://dev.azure.com/${accessInfo.organization}/${accessInfo.project}/`; + const headers = new HttpHeaders({ + Accept: 'application/json', + Authorization: `Basic ${btoa(accessInfo.username + ':' + accessInfo.personalAccessToken)}` + }); + return this.client + .post<WiqlResult>( + `${baseUrl}_apis/wit/wiql?api-version=5.0`, + { query: 'SELECT [System.Id] FROM workitems WHERE [System.TeamProject] = @project' - }, { headers: headers }).pipe( - switchMap(result => result.workItems), - concatMap(result => this.client.get<WorkItemResult>(result.url, { headers: headers })), - concatMap(result => this.getItemIconUrl(baseUrl, headers, result.fields[TodoListService.typeFieldName]).pipe( - map(iconResult => <WorkItem>{ - id: result.id, - title: <string>result.fields[TodoListService.titleFieldName], - closed: ((<string>result.fields[TodoListService.stateFieldName]).toLowerCase() === 'closed'), - detailUrl: `${baseUrl}_workitems/edit/${result.id}/`, - iconUrl: iconResult - }))), - toArray() - ); - } - ) + }, + { headers: headers } + ) + .pipe( + switchMap(result => result.workItems), + concatMap(result => this.client.get<WorkItemResult>(result.url, { headers: headers })), + concatMap(result => + this.getItemIconUrl(baseUrl, headers, result.fields[TodoListService.typeFieldName]).pipe( + map( + iconResult => + <WorkItem>{ + id: result.id, + title: <string>result.fields[TodoListService.titleFieldName], + isCompleted: (function(stateErasedCase: string): Boolean { + return stateErasedCase === 'closed' || stateErasedCase === 'resolved'; + })((result.fields[TodoListService.stateFieldName] as string).toLowerCase()), + detailUrl: `${baseUrl}_workitems/edit/${result.id}/`, + iconUrl: iconResult + } + ) + ) + ), + toArray() + ); + }) ); } } |