From 8d7b3905455c01a6a34b9b0b3bd00be782d64ead Mon Sep 17 00:00:00 2001 From: Martin Rojas Miguel Angel Date: Thu, 15 Feb 2018 16:46:35 +0100 Subject: [PATCH] Add Sorting feature to workbasketsummary and changed HTTP client to latest version --- admin/karma.conf.js | 2 +- admin/src/app/app.module.ts | 21 ++-- admin/src/app/pipes/map-values.pipe.ts | 17 +++ .../http-client-interceptor.service.spec.ts | 19 ++++ .../http-client-interceptor.service.ts | 29 +++++ .../workbasketservice.service.spec.ts | 52 +++++++-- .../app/services/workbasketservice.service.ts | 101 +++++++++++++----- .../list/workbasket-list.component.html | 66 ++++-------- .../list/workbasket-list.component.scss | 9 ++ .../list/workbasket-list.component.spec.ts | 52 +++++++-- .../list/workbasket-list.component.ts | 25 ++++- admin/src/assets/_site.scss | 4 - admin/src/assets/icons/noaccess.svg | 11 +- 13 files changed, 293 insertions(+), 115 deletions(-) create mode 100644 admin/src/app/pipes/map-values.pipe.ts create mode 100644 admin/src/app/services/http-client-interceptor.service.spec.ts create mode 100644 admin/src/app/services/http-client-interceptor.service.ts diff --git a/admin/karma.conf.js b/admin/karma.conf.js index a7fc81756..115ab19ec 100644 --- a/admin/karma.conf.js +++ b/admin/karma.conf.js @@ -39,7 +39,7 @@ module.exports = function (config) { colors: true, logLevel: config.LOG_INFO, autoWatch: true, - browsers: ['Chrome', 'Firefox'], + browsers: ['Chrome'], singleRun: false }); }; diff --git a/admin/src/app/app.module.ts b/admin/src/app/app.module.ts index 06c764598..bf324262e 100644 --- a/admin/src/app/app.module.ts +++ b/admin/src/app/app.module.ts @@ -4,7 +4,6 @@ import { BrowserModule } from '@angular/platform-browser'; import { NgModule, } from '@angular/core'; import { FormsModule } from '@angular/forms'; -import { HttpModule, JsonpModule, Http } from '@angular/http'; import { HttpClientModule } from '@angular/common/http'; import { AppRoutingModule } from './app-routing.module'; import { AlertModule } from 'ngx-bootstrap'; @@ -35,15 +34,19 @@ import { MasterAndDetailComponent} from './shared/masterAndDetail/master-and-det */ import { WorkbasketService } from './services/workbasketservice.service'; import { MasterAndDetailService } from './services/master-and-detail.service'; -import { HttpExtensionService } from './services/http-extension.service'; +import { HttpClientInterceptor } from './services/http-client-interceptor.service'; import { PermissionService } from './services/permission.service'; +import { HTTP_INTERCEPTORS } from '@angular/common/http'; + +/** + * Pipes + */ +import { MapValuesPipe } from './pipes/map-values.pipe'; const MODULES = [ BrowserModule, FormsModule, - HttpModule, - JsonpModule, TabsModule.forRoot(), TreeModule, AppRoutingModule, @@ -64,7 +67,8 @@ const COMPONENTS = [ WorkbasketDistributiontargetsComponent, MasterAndDetailComponent, WorkbasketInformationComponent, - NoAccessComponent + NoAccessComponent, + MapValuesPipe ]; @NgModule({ declarations: COMPONENTS, @@ -73,7 +77,12 @@ const COMPONENTS = [ WorkbasketService, MasterAndDetailService, PermissionService, - { provide: Http, useClass: HttpExtensionService } + { + provide: HTTP_INTERCEPTORS, + useClass: HttpClientInterceptor, + multi: true + }, + ], bootstrap: [AppComponent] }) diff --git a/admin/src/app/pipes/map-values.pipe.ts b/admin/src/app/pipes/map-values.pipe.ts new file mode 100644 index 000000000..ea249167a --- /dev/null +++ b/admin/src/app/pipes/map-values.pipe.ts @@ -0,0 +1,17 @@ +import {Pipe, PipeTransform} from '@angular/core'; + +@Pipe({name: 'mapValues'}) +export class MapValuesPipe implements PipeTransform { + transform(value: any, args?: any[]): Object[] { + let returnArray = []; + + value.forEach((entryVal, entryKey) => { + returnArray.push({ + key: entryKey, + value: entryVal + }); + }); + + return returnArray; + } +} \ No newline at end of file diff --git a/admin/src/app/services/http-client-interceptor.service.spec.ts b/admin/src/app/services/http-client-interceptor.service.spec.ts new file mode 100644 index 000000000..deaef7835 --- /dev/null +++ b/admin/src/app/services/http-client-interceptor.service.spec.ts @@ -0,0 +1,19 @@ +import { TestBed, inject } from '@angular/core/testing'; +import { HttpClientModule } from '@angular/common/http'; +import { HttpModule } from '@angular/http'; + +import { HttpClientInterceptor } from './http-client-interceptor.service'; +import { PermissionService } from './permission.service'; + +describe('HttpExtensionService', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + imports:[HttpClientModule, HttpModule], + providers: [HttpClientInterceptor, PermissionService] + }); + }); + + it('should be created', inject([HttpClientInterceptor], (service: HttpClientInterceptor) => { + expect(service).toBeTruthy(); + })); +}); diff --git a/admin/src/app/services/http-client-interceptor.service.ts b/admin/src/app/services/http-client-interceptor.service.ts new file mode 100644 index 000000000..ebc01796e --- /dev/null +++ b/admin/src/app/services/http-client-interceptor.service.ts @@ -0,0 +1,29 @@ +import { Injectable } from '@angular/core'; +import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpErrorResponse } from '@angular/common/http'; +import { Observable } from 'rxjs/Observable'; +import 'rxjs/add/operator/catch'; +import 'rxjs/add/observable/throw'; +import { BehaviorSubject } from 'rxjs/BehaviorSubject'; +import { PermissionService } from './permission.service'; + + + +@Injectable() +export class HttpClientInterceptor implements HttpInterceptor { + permissionService: PermissionService; + + constructor(permissionService: PermissionService) { + this.permissionService = permissionService; + } + + intercept (req: HttpRequest, next: HttpHandler): Observable> { + return next.handle(req).do(event => { + setTimeout(() => {this.permissionService.setPermission(true);},1) + + }, err => { + if (err instanceof HttpErrorResponse && (err.status === 401 || err.status ===403 )) { + setTimeout(() => {this.permissionService.setPermission(false);},1) + } + }); + } +} \ No newline at end of file diff --git a/admin/src/app/services/workbasketservice.service.spec.ts b/admin/src/app/services/workbasketservice.service.spec.ts index db0f65940..7f1d494ac 100644 --- a/admin/src/app/services/workbasketservice.service.spec.ts +++ b/admin/src/app/services/workbasketservice.service.spec.ts @@ -1,15 +1,51 @@ -import { TestBed, inject } from '@angular/core/testing'; +import { TestBed, inject, async } from '@angular/core/testing'; +import { WorkbasketService, Direction } from './workbasketservice.service'; +import { HttpModule, Http } from '@angular/http'; +import { HttpClientModule, HttpClient } from '@angular/common/http'; +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; -import { WorkbasketService } from './workbasketservice.service'; - -describe('WorkbasketService', () => { +describe('WorkbasketService ', () => { + + var workbasketService, httpClient; beforeEach(() => { TestBed.configureTestingModule({ - providers: [WorkbasketService] + imports: [HttpClientModule, HttpClientTestingModule], + providers: [WorkbasketService, HttpClient, HttpTestingController] }); + + httpClient = TestBed.get(HttpClient); + workbasketService = TestBed.get(WorkbasketService); + }); - xit('should be created', inject([WorkbasketService], (service: WorkbasketService) => { - expect(service).toBeTruthy(); - })); + describe(' WorkbasketSummary GET method ',() => { + + beforeEach(() => { + spyOn(httpClient, 'get').and.returnValue(''); + }); + + it('should have a valid query parameter expression sortBy=key, order=asc as default', () => { + workbasketService.getWorkBasketsSummary(); + expect(httpClient.get).toHaveBeenCalledWith('http://localhost:8080/v1/workbaskets/?sortBy=key&order=asc&', jasmine.any(Object)); + }); + + it('should have a valid query parameter expression with sortBy=name and order=desc', () => { + workbasketService.getWorkBasketsSummary('name', Direction.DESC); + expect(httpClient.get).toHaveBeenCalledWith('http://localhost:8080/v1/workbaskets/?sortBy=name&order=desc&', jasmine.any(Object)); + }); + + it('should have a valid query parameter expression with sortBy=name and order=desc and descLike=some description ',() => { + workbasketService.getWorkBasketsSummary('name', Direction.DESC, undefined, undefined, 'some description'); + expect(httpClient.get).toHaveBeenCalledWith('http://localhost:8080/v1/workbaskets/?sortBy=name&order=desc&descLike=some description&', jasmine.any(Object)); + }); + + it('should have a valid query parameter expression with sortBy=key, order=asc, descLike=some description and type=group ',() => { + workbasketService.getWorkBasketsSummary('name', Direction.DESC, undefined, undefined, 'some description', undefined, undefined, 'group'); + expect(httpClient.get).toHaveBeenCalledWith('http://localhost:8080/v1/workbaskets/?sortBy=name&order=desc&descLike=some description&type=group&', jasmine.any(Object)); + }); + + + }); + + }); diff --git a/admin/src/app/services/workbasketservice.service.ts b/admin/src/app/services/workbasketservice.service.ts index 6d432c0d9..b62e60b6c 100644 --- a/admin/src/app/services/workbasketservice.service.ts +++ b/admin/src/app/services/workbasketservice.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { RequestOptions, Headers, Http, Response } from '@angular/http'; +import { HttpClientModule, HttpClient, HttpHeaders, } from '@angular/common/http'; import { WorkbasketSummary } from '../model/workbasketSummary'; import { Workbasket } from '../model/workbasket'; import { WorkbasketAuthorization } from '../model/workbasket-authorization'; @@ -7,57 +7,92 @@ import { environment } from '../../environments/environment'; import { Observable } from 'rxjs/Observable'; import { Subject } from 'rxjs/Subject'; + +//sort direction +export enum Direction{ + ASC = "asc", + DESC = "desc" +}; + @Injectable() export class WorkbasketService { public workBasketSelected = new Subject(); - constructor(private http: Http) { } + constructor(private httpClient: HttpClient) { } - getWorkBasketsSummary(): Observable { - return this.http.get(environment.taskanaRestUrl + "/v1/workbaskets", this.createAuthorizationHeader()) - .map(res => res.json()); + //Sorting + readonly SORTBY="sortBy"; + readonly ORDER="order"; + + //Filtering + readonly NAME="name"; + readonly NAMELIKE="nameLike"; + readonly DESCLIKE="descLike"; + readonly OWNER="owner"; + readonly OWNERLIKE="ownerLike"; + readonly TYPE="type"; + readonly KEY="key"; + + //Access + readonly REQUIREDPERMISSION="requiredPermission"; + + httpOptions = { + headers: new HttpHeaders({ + 'Content-Type': 'application/json', + 'Authorization': 'Basic VEVBTUxFQURfMTpURUFNTEVBRF8x' + }) + }; + + //REST calls + getWorkBasketsSummary(sortBy: string = this.KEY, + order: string = Direction.ASC, + name: string = undefined, + nameLike: string = undefined, + descLike: string = undefined, + owner:string = undefined, + ownerLike:string = undefined, + type:string = undefined, + requiredPermission: string = undefined): Observable { + + return this.httpClient.get(`${environment.taskanaRestUrl}/v1/workbaskets/${this.getWorkbasketSummaryQueryParameters(sortBy, order, name, + nameLike, descLike, owner, ownerLike, type, requiredPermission)}`,this.httpOptions) + } getWorkBasket(id: string): Observable { - return this.http.get(`${environment.taskanaRestUrl}/v1/workbaskets/${id}`, this.createAuthorizationHeader()) - .map(res => res.json()); + return this.httpClient.get(`${environment.taskanaRestUrl}/v1/workbaskets/${id}`, this.httpOptions); } createWorkbasket(workbasket: WorkbasketSummary): Observable { - return this.http.post(environment.taskanaRestUrl + "/v1/workbaskets", workbasket, this.createAuthorizationHeader()) - .map(res => res.json()); + return this.httpClient.post(environment.taskanaRestUrl + "/v1/workbaskets", workbasket, this.httpOptions); } deleteWorkbasket(id: string) { - return this.http.delete(environment.taskanaRestUrl + "/v1/workbaskets/" + id, this.createAuthorizationHeader()) - .map(res => res.json()); + return this.httpClient.delete(environment.taskanaRestUrl + "/v1/workbaskets/" + id, this.httpOptions); } updateWorkbasket(workbasket: WorkbasketSummary): Observable { - return this.http.put(environment.taskanaRestUrl + "/v1/workbaskets/" + workbasket.workbasketId, workbasket, this.createAuthorizationHeader()) - .map(res => res.json()); + return this.httpClient.put(environment.taskanaRestUrl + "/v1/workbaskets/" + workbasket.workbasketId, workbasket, this.httpOptions); } getAllWorkBasketAuthorizations(id: String): Observable { - return this.http.get(environment.taskanaRestUrl + "/v1/workbaskets/" + id + "/authorizations", this.createAuthorizationHeader()) - .map(res => res.json()); + return this.httpClient.get(environment.taskanaRestUrl + "/v1/workbaskets/" + id + "/authorizations", this.httpOptions); } createWorkBasketAuthorization(workbasketAuthorization: WorkbasketAuthorization): Observable { - return this.http.post(environment.taskanaRestUrl + "/v1/workbaskets/authorizations", workbasketAuthorization, this.createAuthorizationHeader()) - .map(res => res.json()); + return this.httpClient.post(environment.taskanaRestUrl + "/v1/workbaskets/authorizations", workbasketAuthorization, this.httpOptions); } updateWorkBasketAuthorization(workbasketAuthorization: WorkbasketAuthorization): Observable { - return this.http.put(environment.taskanaRestUrl + "/v1/workbaskets/authorizations/" + workbasketAuthorization.id, workbasketAuthorization, this.createAuthorizationHeader()) - .map(res => res.json()); + return this.httpClient.put(environment.taskanaRestUrl + "/v1/workbaskets/authorizations/" + workbasketAuthorization.id, workbasketAuthorization, this.httpOptions) } deleteWorkBasketAuthorization(workbasketAuthorization: WorkbasketAuthorization) { - return this.http.delete(environment.taskanaRestUrl + "/v1/workbaskets/authorizations/" + workbasketAuthorization.id, this.createAuthorizationHeader()); + return this.httpClient.delete(environment.taskanaRestUrl + "/v1/workbaskets/authorizations/" + workbasketAuthorization.id, this.httpOptions); } + //Service extras selectWorkBasket(id: string){ this.workBasketSelected.next(id); } @@ -66,11 +101,27 @@ export class WorkbasketService { return this.workBasketSelected.asObservable(); } - private createAuthorizationHeader() { - let headers: Headers = new Headers(); - headers.append("Authorization", "Basic VEVBTUxFQURfMTpURUFNTEVBRF8x"); - headers.append("content-type", "application/json"); + private getWorkbasketSummaryQueryParameters( sortBy: string, + order: string, + name: string, + nameLike: string, + descLike: string, + owner:string, + ownerLike:string, + type:string, + requiredPermission: string): string{ + let query: string = "?"; + query += sortBy? `${this.SORTBY}=${sortBy}&`:''; + query += order? `${this.ORDER}=${order}&`:''; + query += name? `${this.NAME}=${name}&`:''; + query += nameLike? `${this.NAMELIKE}=${nameLike}&`:''; + query += descLike? `${this.DESCLIKE}=${descLike}&`:''; + query += owner? `${this.OWNER}=${owner}&`:''; + query += ownerLike? `${this.OWNERLIKE}=${ownerLike}&`:''; + query += type? `${this.TYPE}=${type}&`:''; + query += requiredPermission? `${this.REQUIREDPERMISSION}=${requiredPermission}&`:''; - return new RequestOptions({ headers: headers }); + + return query; } } diff --git a/admin/src/app/workbasket/list/workbasket-list.component.html b/admin/src/app/workbasket/list/workbasket-list.component.html index 63da9260e..2c8d81d50 100644 --- a/admin/src/app/workbasket/list/workbasket-list.component.html +++ b/admin/src/app/workbasket/list/workbasket-list.component.html @@ -25,63 +25,35 @@ - - +