TSK-190 Add workbasket information saving feature, spinner, modal and alert components.
This commit is contained in:
parent
bc5e0e9688
commit
e10cc3a0c9
|
@ -32,6 +32,7 @@ module.exports = function (config) {
|
|||
},
|
||||
angularCli: {
|
||||
environment: 'dev'
|
||||
//codeCoverage: true
|
||||
},
|
||||
reporters: config.angularCli && config.angularCli.codeCoverage
|
||||
? ['progress', 'coverage-istanbul']
|
||||
|
|
|
@ -36,20 +36,20 @@ describe('AppComponent', () => {
|
|||
document.body.removeChild(debugElement);
|
||||
}));
|
||||
|
||||
it('should create the app', async(() => {
|
||||
it('should create the app', (() => {
|
||||
expect(app).toBeTruthy();
|
||||
}));
|
||||
|
||||
it(`should have as title 'Taskana administration'`, async(() => {
|
||||
it(`should have as title 'Taskana administration'`, (() => {
|
||||
expect(app.title).toEqual('Taskana administration');
|
||||
}));
|
||||
|
||||
it('should render title in a <a> tag', async(() => {
|
||||
it('should render title in a <a> tag', (() => {
|
||||
fixture.detectChanges();
|
||||
expect(debugElement.querySelector('ul p a').textContent).toContain('Taskana administration');
|
||||
}));
|
||||
|
||||
it('should call Router.navigateByUrl("categories") and workbasketRoute should be false', async (inject([Router], (router: Router) => {
|
||||
it('should call Router.navigateByUrl("categories") and workbasketRoute should be false', (inject([Router], (router: Router) => {
|
||||
|
||||
expect(app.workbasketsRoute).toBe(true);
|
||||
fixture.detectChanges();
|
||||
|
|
|
@ -10,6 +10,7 @@ import { AlertModule } from 'ngx-bootstrap';
|
|||
import { AngularSvgIconModule } from 'angular-svg-icon';
|
||||
import { TabsModule } from 'ngx-bootstrap/tabs';
|
||||
import { TreeModule } from 'angular-tree-component';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
/**
|
||||
* Components
|
||||
|
@ -28,6 +29,8 @@ import { NoAccessComponent } from './workbasket/noAccess/no-access.component';
|
|||
import { SpinnerComponent } from './shared/spinner/spinner.component';
|
||||
import { FilterComponent } from './shared/filter/filter.component';
|
||||
import { IconTypeComponent } from './shared/type-icon/icon-type.component';
|
||||
import { AlertComponent } from './shared/alert/alert.component';
|
||||
import { GeneralMessageModalComponent } from './shared/general-message-modal/general-message-modal.component';
|
||||
|
||||
//Shared
|
||||
import { MasterAndDetailComponent} from './shared/masterAndDetail/master-and-detail.component';
|
||||
|
@ -35,11 +38,12 @@ import { MasterAndDetailComponent} from './shared/masterAndDetail/master-and-det
|
|||
/**
|
||||
* Services
|
||||
*/
|
||||
import { WorkbasketService } from './services/workbasketservice.service';
|
||||
import { WorkbasketService } from './services/workbasket.service';
|
||||
import { MasterAndDetailService } from './services/master-and-detail.service';
|
||||
import { HttpClientInterceptor } from './services/http-client-interceptor.service';
|
||||
import { PermissionService } from './services/permission.service';
|
||||
import { HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||
import { AlertService } from './services/alert.service';
|
||||
|
||||
/**
|
||||
* Pipes
|
||||
|
@ -55,7 +59,8 @@ const MODULES = [
|
|||
AppRoutingModule,
|
||||
AlertModule.forRoot(),
|
||||
AngularSvgIconModule,
|
||||
HttpClientModule
|
||||
HttpClientModule,
|
||||
BrowserAnimationsModule
|
||||
];
|
||||
|
||||
const DECLARATIONS = [
|
||||
|
@ -74,6 +79,8 @@ const DECLARATIONS = [
|
|||
SpinnerComponent,
|
||||
FilterComponent,
|
||||
IconTypeComponent,
|
||||
AlertComponent,
|
||||
GeneralMessageModalComponent,
|
||||
MapValuesPipe,
|
||||
RemoveNoneTypePipe
|
||||
];
|
||||
|
@ -90,7 +97,7 @@ const DECLARATIONS = [
|
|||
useClass: HttpClientInterceptor,
|
||||
multi: true
|
||||
},
|
||||
|
||||
AlertService
|
||||
],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
export class Links {
|
||||
constructor(
|
||||
public rel: string,
|
||||
public href: string,
|
||||
){}
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
import {WorkbasketSummary} from './workbasketSummary';
|
||||
import { WorkbasketSummary } from './workbasketSummary';
|
||||
import { Links } from './links';
|
||||
export class Workbasket {
|
||||
constructor(
|
||||
public id: string,
|
||||
public workbasketId: string,
|
||||
public created: string,
|
||||
public key: string,
|
||||
public domain: string,
|
||||
|
@ -18,5 +19,27 @@ export class Workbasket {
|
|||
public orgLevel2: string,
|
||||
public orgLevel3: string,
|
||||
public orgLevel4: string,
|
||||
public workbasketSummary: WorkbasketSummary){}
|
||||
public links: Array<Links>){}
|
||||
|
||||
public static equals(org: Workbasket, comp: Workbasket): boolean {
|
||||
if (org.workbasketId !== comp.workbasketId) { return false; }
|
||||
if (org.created !== comp.created) { return false; }
|
||||
if (org.key !== comp.key) { return false; }
|
||||
if (org.domain !== comp.domain) { return false; }
|
||||
if (org.type !== comp.type) { return false; }
|
||||
if (org.modified !== comp.modified) { return false; }
|
||||
if (org.name !== comp.name) { return false; }
|
||||
if (org.description !== comp.description) { return false; }
|
||||
if (org.owner !== comp.owner) { return false; }
|
||||
if (org.custom1 !== comp.custom1) { return false; }
|
||||
if (org.custom2 !== comp.custom2) { return false; }
|
||||
if (org.custom3 !== comp.custom3) { return false; }
|
||||
if (org.custom4 !== comp.custom4) { return false; }
|
||||
if (org.orgLevel1 !== comp.orgLevel1) { return false; }
|
||||
if (org.orgLevel2 !== comp.orgLevel2) { return false; }
|
||||
if (org.orgLevel3 !== comp.orgLevel3) { return false; }
|
||||
if (org.orgLevel4 !== comp.orgLevel4) { return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
import {Links} from './links';
|
||||
|
||||
export class WorkbasketSummary {
|
||||
constructor(
|
||||
public workbasketId: string,
|
||||
|
@ -11,5 +13,6 @@ export class WorkbasketSummary {
|
|||
public orgLevel1: string,
|
||||
public orgLevel2: string,
|
||||
public orgLevel3: string,
|
||||
public orgLevel4: string){}
|
||||
public orgLevel4: string,
|
||||
public links: Array<Links> = undefined){}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
import { TestBed, inject } from '@angular/core/testing';
|
||||
|
||||
import { AlertService } from './alert.service';
|
||||
|
||||
describe('AlertService', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [AlertService]
|
||||
});
|
||||
});
|
||||
|
||||
it('should be created', inject([AlertService], (service: AlertService) => {
|
||||
expect(service).toBeTruthy();
|
||||
}));
|
||||
});
|
|
@ -0,0 +1,34 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Subject, Observable } from 'rxjs';
|
||||
|
||||
export enum AlertType {
|
||||
SUCCESS = 'success',
|
||||
INFO = 'info',
|
||||
WARNING = 'warning',
|
||||
DANGER = 'danger',
|
||||
}
|
||||
|
||||
export class AlertModel {
|
||||
|
||||
constructor(public type: string = AlertType.SUCCESS,
|
||||
public text: string = 'Success',
|
||||
public autoClosing: boolean = true,
|
||||
public closingDelay: number = 2500){
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class AlertService {
|
||||
|
||||
public alertTriggered = new Subject<AlertModel>();
|
||||
|
||||
constructor() { }
|
||||
|
||||
triggerAlert(alert: AlertModel) {
|
||||
this.alertTriggered.next(alert);
|
||||
}
|
||||
|
||||
getAlert(): Observable<AlertModel> {
|
||||
return this.alertTriggered.asObservable();
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
import { TestBed, inject } from '@angular/core/testing';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { HttpModule } from '@angular/http';
|
||||
|
||||
import { HttpExtensionService } from './http-extension.service';
|
||||
import { PermissionService } from './permission.service';
|
||||
|
||||
describe('HttpExtensionService', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports:[HttpClientModule, HttpModule],
|
||||
providers: [HttpExtensionService, PermissionService]
|
||||
});
|
||||
});
|
||||
|
||||
it('should be created', inject([HttpExtensionService], (service: HttpExtensionService) => {
|
||||
expect(service).toBeTruthy();
|
||||
}));
|
||||
});
|
|
@ -1,28 +0,0 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Request, XHRBackend, RequestOptions, Response, Http, RequestOptionsArgs, Headers } from '@angular/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 HttpExtensionService extends Http {
|
||||
permissionService: PermissionService;
|
||||
constructor(backend: XHRBackend, defaultOptions: RequestOptions, permissionService: PermissionService) {
|
||||
super(backend, defaultOptions);
|
||||
this.permissionService = permissionService;
|
||||
}
|
||||
|
||||
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
|
||||
this.permissionService.setPermission(true);
|
||||
return super.request(url, options).catch((error: Response) => {
|
||||
if ((error.status === 401 || error.status === 403) && (window.location.href.match(/\?/g) || []).length < 2) {
|
||||
this.permissionService.setPermission(false);
|
||||
}
|
||||
return Observable.throw(error);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import { TestBed, inject, async } from '@angular/core/testing';
|
||||
import { WorkbasketService, Direction } from './workbasketservice.service';
|
||||
import { WorkbasketService, Direction } from './workbasket.service';
|
||||
import { HttpModule, Http } from '@angular/http';
|
||||
import { HttpClientModule, HttpClient } from '@angular/common/http';
|
||||
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
|
||||
|
@ -30,17 +30,17 @@ describe('WorkbasketService ', () => {
|
|||
});
|
||||
|
||||
it('should have a valid query parameter expression with sortBy=name and order=desc', () => {
|
||||
workbasketService.getWorkBasketsSummary('name', Direction.DESC);
|
||||
workbasketService.getWorkBasketsSummary(undefined, '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');
|
||||
workbasketService.getWorkBasketsSummary(undefined,'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');
|
||||
workbasketService.getWorkBasketsSummary(undefined,'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));
|
||||
});
|
||||
|
|
@ -0,0 +1,180 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { HttpClientModule, HttpClient, HttpHeaders, HttpResponse, HttpErrorResponse } from '@angular/common/http';
|
||||
import { WorkbasketSummary } from '../model/workbasketSummary';
|
||||
import { Workbasket } from '../model/workbasket';
|
||||
import { WorkbasketAuthorization } from '../model/workbasket-authorization';
|
||||
import { environment } from '../../environments/environment';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { Subject } from 'rxjs/Subject';
|
||||
import { Timestamp } from 'rxjs';
|
||||
|
||||
|
||||
//sort direction
|
||||
export enum Direction {
|
||||
ASC = 'asc',
|
||||
DESC = 'desc'
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class WorkbasketService {
|
||||
|
||||
public workBasketSelected = new Subject<string>();
|
||||
public workBasketSaved = new Subject<number>();
|
||||
|
||||
constructor(private httpClient: HttpClient) { }
|
||||
|
||||
//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';
|
||||
readonly KEYLIKE = 'keyLike';
|
||||
|
||||
//Access
|
||||
readonly REQUIREDPERMISSION = 'requiredPermission';
|
||||
|
||||
httpOptions = {
|
||||
headers: new HttpHeaders({
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Basic VEVBTUxFQURfMTpURUFNTEVBRF8x'
|
||||
})
|
||||
};
|
||||
|
||||
private workbasketSummaryRef: Observable<WorkbasketSummary[]>;
|
||||
|
||||
//#region "REST calls"
|
||||
// GET
|
||||
getWorkBasketsSummary( forceRequest: boolean = false,
|
||||
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,
|
||||
key: string = undefined,
|
||||
keyLike: string = undefined,
|
||||
requiredPermission: string = undefined): Observable<WorkbasketSummary[]> {
|
||||
if(this.workbasketSummaryRef && !forceRequest){
|
||||
return this.workbasketSummaryRef;
|
||||
}
|
||||
return this.httpClient.get<WorkbasketSummary[]>(`${environment.taskanaRestUrl}/v1/workbaskets/${this.getWorkbasketSummaryQueryParameters(sortBy, order, name,
|
||||
nameLike, descLike, owner, ownerLike, type, key, keyLike, requiredPermission)}`, this.httpOptions);
|
||||
|
||||
}
|
||||
|
||||
// GET
|
||||
getWorkBasket(url: string): Observable<Workbasket> {
|
||||
return this.httpClient.get<Workbasket>(url, this.httpOptions);
|
||||
}
|
||||
|
||||
getWorkBasket1(id: string): Observable<Workbasket> {
|
||||
return this.httpClient.get<Workbasket>(environment.taskanaRestUrl + '/v1/workbaskets/' + id, this.httpOptions);
|
||||
}
|
||||
// POST
|
||||
createWorkbasket(url: string, workbasket: Workbasket): Observable<Workbasket> {
|
||||
return this.httpClient
|
||||
.post<Workbasket>(url, this.httpOptions);
|
||||
}
|
||||
// PUT
|
||||
updateWorkbasket(url: string, workbasket: Workbasket): Observable<Workbasket> {
|
||||
return this.httpClient
|
||||
.put<Workbasket>(url, workbasket, this.httpOptions)
|
||||
.catch(this.handleError);
|
||||
}
|
||||
// DELETE
|
||||
deleteWorkbasket(id: string) {
|
||||
return this.httpClient.delete(environment.taskanaRestUrl + '/v1/workbaskets/' + id, this.httpOptions);
|
||||
}
|
||||
// GET
|
||||
getAllWorkBasketAuthorizations(id: String): Observable<WorkbasketAuthorization[]> {
|
||||
return this.httpClient.get<WorkbasketAuthorization[]>(environment.taskanaRestUrl + '/v1/workbaskets/' + id + '/authorizations', this.httpOptions);
|
||||
}
|
||||
// POST
|
||||
createWorkBasketAuthorization(workbasketAuthorization: WorkbasketAuthorization): Observable<WorkbasketAuthorization> {
|
||||
return this.httpClient.post<WorkbasketAuthorization>(environment.taskanaRestUrl + '/v1/workbaskets/authorizations', workbasketAuthorization, this.httpOptions);
|
||||
}
|
||||
// PUT
|
||||
updateWorkBasketAuthorization(workbasketAuthorization: WorkbasketAuthorization): Observable<WorkbasketAuthorization> {
|
||||
return this.httpClient.put<WorkbasketAuthorization>(environment.taskanaRestUrl + '/v1/workbaskets/authorizations/' + workbasketAuthorization.id, workbasketAuthorization, this.httpOptions)
|
||||
}
|
||||
// DELETE
|
||||
deleteWorkBasketAuthorization(workbasketAuthorization: WorkbasketAuthorization) {
|
||||
return this.httpClient.delete(environment.taskanaRestUrl + '/v1/workbaskets/authorizations/' + workbasketAuthorization.id, this.httpOptions);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region "Service extras"
|
||||
selectWorkBasket(id: string) {
|
||||
this.workBasketSelected.next(id);
|
||||
}
|
||||
|
||||
getSelectedWorkBasket(): Observable<string> {
|
||||
return this.workBasketSelected.asObservable();
|
||||
}
|
||||
|
||||
triggerWorkBasketSaved() {
|
||||
this.workBasketSaved.next(Date.now());
|
||||
}
|
||||
|
||||
workbasketSavedTriggered(): Observable<number> {
|
||||
return this.workBasketSaved.asObservable();
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region private
|
||||
private getWorkbasketSummaryQueryParameters(sortBy: string,
|
||||
order: string,
|
||||
name: string,
|
||||
nameLike: string,
|
||||
descLike: string,
|
||||
owner: string,
|
||||
ownerLike: string,
|
||||
type: string,
|
||||
key: string,
|
||||
keyLike: 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 += key ? `${this.KEY}=${key}&` : '';
|
||||
query += keyLike ? `${this.KEYLIKE}=${keyLike}&` : '';
|
||||
query += requiredPermission ? `${this.REQUIREDPERMISSION}=${requiredPermission}&` : '';
|
||||
|
||||
if (query.lastIndexOf('&') === query.length - 1) {
|
||||
query = query.slice(0, query.lastIndexOf('&'))
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
private handleError (error: Response | any) {
|
||||
// In a real world app, you might use a remote logging infrastructure
|
||||
let errMsg: string;
|
||||
if (error instanceof Response) {
|
||||
const body = error.json() || '';
|
||||
const err = JSON.stringify(body);
|
||||
errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
|
||||
} else {
|
||||
errMsg = error.message ? error.message : error.toString();
|
||||
}
|
||||
console.error(errMsg);
|
||||
return Observable.throw(errMsg);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
}
|
|
@ -1,136 +0,0 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { HttpClientModule, HttpClient, HttpHeaders, } from '@angular/common/http';
|
||||
import { WorkbasketSummary } from '../model/workbasketSummary';
|
||||
import { Workbasket } from '../model/workbasket';
|
||||
import { WorkbasketAuthorization } from '../model/workbasket-authorization';
|
||||
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<string>();
|
||||
|
||||
constructor(private httpClient: HttpClient) { }
|
||||
|
||||
//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';
|
||||
readonly KEYLIKE='keyLike';
|
||||
|
||||
//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,
|
||||
key:string = undefined,
|
||||
keyLike:string = undefined,
|
||||
requiredPermission: string = undefined): Observable<WorkbasketSummary[]> {
|
||||
|
||||
return this.httpClient.get<WorkbasketSummary[]>(`${environment.taskanaRestUrl}/v1/workbaskets/${this.getWorkbasketSummaryQueryParameters(sortBy, order, name,
|
||||
nameLike, descLike, owner, ownerLike, type, key, keyLike, requiredPermission)}`,this.httpOptions)
|
||||
|
||||
}
|
||||
|
||||
getWorkBasket(id: string): Observable<Workbasket> {
|
||||
return this.httpClient.get<Workbasket>(`${environment.taskanaRestUrl}/v1/workbaskets/${id}`, this.httpOptions);
|
||||
}
|
||||
|
||||
createWorkbasket(workbasket: WorkbasketSummary): Observable<WorkbasketSummary> {
|
||||
return this.httpClient.post<WorkbasketSummary>(environment.taskanaRestUrl + '/v1/workbaskets', workbasket, this.httpOptions);
|
||||
}
|
||||
|
||||
deleteWorkbasket(id: string) {
|
||||
return this.httpClient.delete(environment.taskanaRestUrl + '/v1/workbaskets/' + id, this.httpOptions);
|
||||
}
|
||||
|
||||
updateWorkbasket(workbasket: WorkbasketSummary): Observable<WorkbasketSummary> {
|
||||
return this.httpClient.put<WorkbasketSummary>(environment.taskanaRestUrl + '/v1/workbaskets/' + workbasket.workbasketId, workbasket, this.httpOptions);
|
||||
}
|
||||
|
||||
getAllWorkBasketAuthorizations(id: String): Observable<WorkbasketAuthorization[]> {
|
||||
return this.httpClient.get<WorkbasketAuthorization[]>(environment.taskanaRestUrl + '/v1/workbaskets/' + id + '/authorizations', this.httpOptions);
|
||||
}
|
||||
|
||||
createWorkBasketAuthorization(workbasketAuthorization: WorkbasketAuthorization): Observable<WorkbasketAuthorization> {
|
||||
return this.httpClient.post<WorkbasketAuthorization>(environment.taskanaRestUrl + '/v1/workbaskets/authorizations', workbasketAuthorization, this.httpOptions);
|
||||
}
|
||||
|
||||
updateWorkBasketAuthorization(workbasketAuthorization: WorkbasketAuthorization): Observable<WorkbasketAuthorization> {
|
||||
return this.httpClient.put<WorkbasketAuthorization>(environment.taskanaRestUrl + '/v1/workbaskets/authorizations/' + workbasketAuthorization.id, workbasketAuthorization, this.httpOptions)
|
||||
}
|
||||
|
||||
deleteWorkBasketAuthorization(workbasketAuthorization: WorkbasketAuthorization) {
|
||||
return this.httpClient.delete(environment.taskanaRestUrl + '/v1/workbaskets/authorizations/' + workbasketAuthorization.id, this.httpOptions);
|
||||
}
|
||||
|
||||
//Service extras
|
||||
selectWorkBasket(id: string){
|
||||
this.workBasketSelected.next(id);
|
||||
}
|
||||
|
||||
getSelectedWorkBasket(): Observable<string>{
|
||||
return this.workBasketSelected.asObservable();
|
||||
}
|
||||
|
||||
private getWorkbasketSummaryQueryParameters( sortBy: string,
|
||||
order: string,
|
||||
name: string,
|
||||
nameLike: string,
|
||||
descLike: string,
|
||||
owner: string,
|
||||
ownerLike: string,
|
||||
type: string,
|
||||
key: string,
|
||||
keyLike: 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 += key? `${this.KEY}=${key}&`:'';
|
||||
query += keyLike? `${this.KEYLIKE}=${keyLike}&`:'';
|
||||
query += requiredPermission? `${this.REQUIREDPERMISSION}=${requiredPermission}&`:'';
|
||||
|
||||
if(query.lastIndexOf('&') === query.length-1){
|
||||
query = query.slice(0, query.lastIndexOf('&'))
|
||||
}
|
||||
return query;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
<div *ngIf="alert" [@alertState]="alert" class="alert alert-{{alert.type}} {{alert.autoClosing? '':'alert-dismissible'}} footer"
|
||||
role="alert">
|
||||
<span class="glyphicon {{alert.type === 'success'? 'glyphicon-thumbs-up': 'glyphicon-exclamation-sign' }}" aria-hidden="true"></span>
|
||||
{{alert.text}}
|
||||
<button *ngIf="!alert.autoClosing" type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
.footer{
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
margin-bottom: 0px;
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { AlertService, AlertModel, AlertType } from '../../services/alert.service';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
import { AlertComponent } from './alert.component';
|
||||
|
||||
describe('AlertComponent', () => {
|
||||
let component: AlertComponent;
|
||||
let fixture: ComponentFixture<AlertComponent>;
|
||||
let debugElement,
|
||||
alertService;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports:[BrowserAnimationsModule],
|
||||
declarations: [AlertComponent],
|
||||
providers: [AlertService]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
alertService = TestBed.get(AlertService);
|
||||
fixture = TestBed.createComponent(AlertComponent);
|
||||
component = fixture.componentInstance;
|
||||
debugElement = fixture.debugElement.nativeElement;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
document.body.removeChild(debugElement);
|
||||
})
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should show alert message', () => {
|
||||
alertService.triggerAlert(new AlertModel(AlertType.SUCCESS,'some custom text',));
|
||||
fixture.detectChanges();
|
||||
expect(debugElement.querySelector('.alert.alert-success')).toBeDefined();
|
||||
expect(debugElement.querySelector('.alert.alert-success').innerText).toBe('some custom text');
|
||||
});
|
||||
|
||||
it('should have differents alert types', () => {
|
||||
alertService.triggerAlert(new AlertModel(AlertType.DANGER,'some custom text',));
|
||||
fixture.detectChanges();
|
||||
expect(debugElement.querySelector('.alert.alert-danger')).toBeDefined();
|
||||
|
||||
alertService.triggerAlert(new AlertModel(AlertType.WARNING,'some custom text',));
|
||||
fixture.detectChanges();
|
||||
expect(debugElement.querySelector('.alert.alert-warning')).toBeDefined();
|
||||
});
|
||||
|
||||
it('should define a closing timeout if alert has autoclosing property', (done) => {
|
||||
alertService.triggerAlert(new AlertModel(AlertType.SUCCESS,'some custom text',true, 5));
|
||||
fixture.detectChanges();
|
||||
expect(component.alert).toBeDefined();
|
||||
setTimeout(()=>{
|
||||
fixture.detectChanges();
|
||||
expect(component.alert).toBeUndefined();
|
||||
done();
|
||||
},6)
|
||||
});
|
||||
|
||||
it('should have defined a closing button if alert has no autoclosing property', () => {
|
||||
alertService.triggerAlert(new AlertModel(AlertType.DANGER,'some custom text',false));
|
||||
fixture.detectChanges();
|
||||
expect(debugElement.querySelector('.alert.alert-danger > button')).toBeDefined();
|
||||
});
|
||||
|
||||
});
|
|
@ -0,0 +1,41 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { AlertService, AlertModel } from '../../services/alert.service';
|
||||
import { trigger, state, style, animate, transition } from '@angular/animations';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-alert',
|
||||
templateUrl: './alert.component.html',
|
||||
styleUrls: ['./alert.component.scss'],
|
||||
animations: [
|
||||
trigger('alertState', [
|
||||
state('in', style({ transform: 'translateY(0)' })),
|
||||
transition('void => *', [
|
||||
style({ transform: 'translateY(100%)' }),
|
||||
animate(100)
|
||||
]),
|
||||
transition('* => void', [
|
||||
animate(100, style({ transform: 'translateY(100%)' }))
|
||||
])
|
||||
])
|
||||
]
|
||||
})
|
||||
|
||||
export class AlertComponent implements OnInit {
|
||||
alert: AlertModel;
|
||||
constructor(private alertService: AlertService) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.alertService.getAlert().subscribe((alert: AlertModel) => {
|
||||
this.alert = alert;
|
||||
if (alert.autoClosing) {
|
||||
this.setTimeOutForClosing(alert.closingDelay);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setTimeOutForClosing(time: number) {
|
||||
setTimeout(() => {
|
||||
this.alert = undefined;
|
||||
}, time);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
<div type="text" id="{{target}}" class="list-group-seach collapse">
|
||||
<div type="text" id="{{target}}" data-toogle="collapse" class="list-group-seach collapse">
|
||||
<div class="row">
|
||||
<div class="dropdown col-xs-2">
|
||||
<button class="btn btn-default" type="button" id="dropdownMenufilter" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<div class="modal fade" #generalModal tabindex="-1" data-backdrop="static" data-keyboard="false" role="dialog" aria-labelledby="generalModalLabel">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="generalModalLabel">{{title}}</h4>
|
||||
</div>
|
||||
<div *ngIf="error" class="modal-body">
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
|
||||
<span class="sr-only">Error:</span>
|
||||
{{message}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default btn-danger" data-dismiss="modal" (click)="removeMessage()">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,25 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { GeneralMessageModalComponent } from './general-message-modal.component';
|
||||
|
||||
describe('GeneralMessageModalComponent', () => {
|
||||
let component: GeneralMessageModalComponent;
|
||||
let fixture: ComponentFixture<GeneralMessageModalComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ GeneralMessageModalComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(GeneralMessageModalComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,35 @@
|
|||
import { Component, OnInit, Input, ViewChild, OnChanges, SimpleChanges } from '@angular/core';
|
||||
declare var $: any;
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-general-message-modal',
|
||||
templateUrl: './general-message-modal.component.html',
|
||||
styleUrls: ['./general-message-modal.component.scss']
|
||||
})
|
||||
export class GeneralMessageModalComponent implements OnChanges {
|
||||
|
||||
@Input()
|
||||
message: string = '';
|
||||
|
||||
@Input()
|
||||
title: string = '';
|
||||
|
||||
@Input()
|
||||
error: boolean = false;
|
||||
|
||||
@ViewChild('generalModal')
|
||||
private modal;
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (this.message) {
|
||||
$(this.modal.nativeElement).modal('toggle');
|
||||
}
|
||||
}
|
||||
|
||||
removeMessage() {
|
||||
this.message = undefined;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,14 +1,36 @@
|
|||
<div [hidden]="!isDelayedRunning" class="sk-circle">
|
||||
<div class="sk-circle1 sk-child"></div>
|
||||
<div class="sk-circle2 sk-child"></div>
|
||||
<div class="sk-circle3 sk-child"></div>
|
||||
<div class="sk-circle4 sk-child"></div>
|
||||
<div class="sk-circle5 sk-child"></div>
|
||||
<div class="sk-circle6 sk-child"></div>
|
||||
<div class="sk-circle7 sk-child"></div>
|
||||
<div class="sk-circle8 sk-child"></div>
|
||||
<div class="sk-circle9 sk-child"></div>
|
||||
<div class="sk-circle10 sk-child"></div>
|
||||
<div class="sk-circle11 sk-child"></div>
|
||||
<div class="sk-circle12 sk-child"></div>
|
||||
</div>
|
||||
<div [hidden]="!isDelayedRunning">
|
||||
<div class="sk-circle spinner-centered" [hidden]="this.isModal">
|
||||
<div class="sk-circle1 sk-child"></div>
|
||||
<div class="sk-circle2 sk-child"></div>
|
||||
<div class="sk-circle3 sk-child"></div>
|
||||
<div class="sk-circle4 sk-child"></div>
|
||||
<div class="sk-circle5 sk-child"></div>
|
||||
<div class="sk-circle6 sk-child"></div>
|
||||
<div class="sk-circle7 sk-child"></div>
|
||||
<div class="sk-circle8 sk-child"></div>
|
||||
<div class="sk-circle9 sk-child"></div>
|
||||
<div class="sk-circle10 sk-child"></div>
|
||||
<div class="sk-circle11 sk-child"></div>
|
||||
<div class="sk-circle12 sk-child"></div>
|
||||
</div>
|
||||
<div #spinnerModal class="modal fade" id="spinner-modal" data-backdrop="static" data-keyboard="false" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-dialog spinner-centered">
|
||||
<div class="sk-circle">
|
||||
<div class="sk-circle1 sk-child"></div>
|
||||
<div class="sk-circle2 sk-child"></div>
|
||||
<div class="sk-circle3 sk-child"></div>
|
||||
<div class="sk-circle4 sk-child"></div>
|
||||
<div class="sk-circle5 sk-child"></div>
|
||||
<div class="sk-circle6 sk-child"></div>
|
||||
<div class="sk-circle7 sk-child"></div>
|
||||
<div class="sk-circle8 sk-child"></div>
|
||||
<div class="sk-circle9 sk-child"></div>
|
||||
<div class="sk-circle10 sk-child"></div>
|
||||
<div class="sk-circle11 sk-child"></div>
|
||||
<div class="sk-circle12 sk-child"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -18,7 +18,7 @@
|
|||
margin: 0 auto;
|
||||
width: 15%;
|
||||
height: 15%;
|
||||
background-color: #337ab7;
|
||||
background-color: #33b784;
|
||||
border-radius: 100%;
|
||||
-webkit-animation: sk-circleBounceDelay 1.2s infinite ease-in-out both;
|
||||
animation: sk-circleBounceDelay 1.2s infinite ease-in-out both;
|
||||
|
@ -119,4 +119,14 @@
|
|||
-webkit-transform: scale(1);
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.floating {
|
||||
position: absolute;
|
||||
left: 45%;
|
||||
top: auto;
|
||||
z-index: 10;
|
||||
}
|
||||
.spinner-centered {
|
||||
margin-top: calc(50vh - 100px);
|
||||
}
|
|
@ -1,42 +1,62 @@
|
|||
import { Component, Input } from '@angular/core';
|
||||
import { Component, Input, ElementRef } from '@angular/core';
|
||||
import { ViewChild } from '@angular/core';
|
||||
declare var $: any;
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-spinner',
|
||||
templateUrl: './spinner.component.html',
|
||||
styleUrls: ['./spinner.component.scss']
|
||||
selector: 'taskana-spinner',
|
||||
templateUrl: './spinner.component.html',
|
||||
styleUrls: ['./spinner.component.scss']
|
||||
})
|
||||
export class SpinnerComponent {
|
||||
private currentTimeout: any;
|
||||
|
||||
isDelayedRunning: boolean = false;
|
||||
export class SpinnerComponent {
|
||||
private currentTimeout: any;
|
||||
|
||||
@Input()
|
||||
delay: number = 300;
|
||||
isDelayedRunning: boolean = false;
|
||||
|
||||
@Input()
|
||||
set isRunning(value: boolean) {
|
||||
if (!value) {
|
||||
this.cancelTimeout();
|
||||
this.isDelayedRunning = false;
|
||||
return;
|
||||
}
|
||||
@Input()
|
||||
delay: number = 300;
|
||||
|
||||
if (this.currentTimeout) {
|
||||
return;
|
||||
}
|
||||
@Input()
|
||||
set isRunning(value: boolean) {
|
||||
if (!value) {
|
||||
this.cancelTimeout();
|
||||
if (this.isModal) { this.closeModal(); }
|
||||
this.isDelayedRunning = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentTimeout = setTimeout(() => {
|
||||
this.isDelayedRunning = value;
|
||||
this.cancelTimeout();
|
||||
}, this.delay);
|
||||
}
|
||||
if (this.currentTimeout) {
|
||||
return;
|
||||
}
|
||||
this.runSpinner(value);
|
||||
|
||||
private cancelTimeout(): void {
|
||||
clearTimeout(this.currentTimeout);
|
||||
this.currentTimeout = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy(): any {
|
||||
this.cancelTimeout();
|
||||
}
|
||||
@Input()
|
||||
isModal: boolean = false;
|
||||
|
||||
@ViewChild('spinnerModal')
|
||||
private modal;
|
||||
|
||||
private runSpinner(value) {
|
||||
this.currentTimeout = setTimeout(() => {
|
||||
if (this.isModal) { $(this.modal.nativeElement).modal('toggle'); }
|
||||
this.isDelayedRunning = value;
|
||||
this.cancelTimeout();
|
||||
}, this.delay);
|
||||
}
|
||||
private closeModal() {
|
||||
if (this.isDelayedRunning) {
|
||||
$(this.modal.nativeElement).modal('toggle');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private cancelTimeout(): void {
|
||||
clearTimeout(this.currentTimeout);
|
||||
this.currentTimeout = undefined;
|
||||
}
|
||||
|
||||
ngOnDestroy(): any {
|
||||
this.cancelTimeout();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
import { Links} from '../../model/links';
|
||||
|
||||
export class Utils {
|
||||
static getSelfRef(links: Array<Links>) {
|
||||
return links.find(l => l.rel === 'self');
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { ActivatedRoute, Params } from '@angular/router';
|
||||
import { WorkbasketService } from '../services/workbasketservice.service';
|
||||
import { WorkbasketService } from '../services/workbasket.service';
|
||||
import { WorkbasketAuthorization } from '../model/workbasket-authorization';
|
||||
import { WorkbasketSummary } from '../model/workbasketSummary';
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { WorkbasketSummary } from '../model/workbasketSummary';
|
||||
import { WorkbasketService } from '../services/workbasketservice.service'
|
||||
import { WorkbasketService } from '../services/workbasket.service'
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
@Component({
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
<taskana-spinner [isRunning]="requestInProgress" [isModal]= "modalSpinner" class = "centered-horizontally floating"></taskana-spinner>
|
||||
<taskana-general-message-modal *ngIf="modalErrorMessage" [message]="modalErrorMessage" [title]="modalTitle" error = "true" ></taskana-general-message-modal>
|
||||
<div id = "wb-information" class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<div class="btn-group pull-right">
|
||||
<button type="button" class="btn btn-default btn-primary">Save</button>
|
||||
<button type="button" class="btn btn-default">Cancel</button>
|
||||
<button type="button" (click)="onSave()" class="btn btn-default btn-primary">Save</button>
|
||||
<button type="button" (click)="onClear()" class="btn btn-default">Undo changes</button>
|
||||
</div>
|
||||
<h4 class="panel-header">{{workbasket.name}}</h4>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { async, ComponentFixture, TestBed, fakeAsync } from '@angular/core/testing';
|
||||
import { WorkbasketService } from '../../../services/workbasketservice.service';
|
||||
import { async, ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
|
||||
import { WorkbasketService } from '../../../services/workbasket.service';
|
||||
import { WorkbasketInformationComponent } from './workbasket-information.component';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { AngularSvgIconModule } from 'angular-svg-icon';
|
||||
|
@ -7,56 +7,93 @@ import { HttpClientModule } from '@angular/common/http';
|
|||
import { HttpModule, JsonpModule } from '@angular/http';
|
||||
import { Workbasket } from 'app/model/workbasket';
|
||||
import { ICONTYPES, IconTypeComponent } from '../../../shared/type-icon/icon-type.component';
|
||||
import { SpinnerComponent } from '../../../shared/spinner/spinner.component';
|
||||
import { GeneralMessageModalComponent } from '../../../shared/general-message-modal/general-message-modal.component';
|
||||
import { MapValuesPipe } from '../../../pipes/map-values.pipe';
|
||||
import { RemoveNoneTypePipe } from '../../../pipes/remove-none-type';
|
||||
|
||||
|
||||
import { AlertService } from '../../../services/alert.service';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { Links } from '../../../model/links';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
describe('InformationComponent', () => {
|
||||
let component: WorkbasketInformationComponent;
|
||||
let fixture: ComponentFixture<WorkbasketInformationComponent>;
|
||||
let debugElement;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ WorkbasketInformationComponent, IconTypeComponent, MapValuesPipe, RemoveNoneTypePipe],
|
||||
imports:[FormsModule, AngularSvgIconModule, HttpClientModule, HttpModule],
|
||||
providers:[WorkbasketService]
|
||||
let component: WorkbasketInformationComponent;
|
||||
let fixture: ComponentFixture<WorkbasketInformationComponent>;
|
||||
let debugElement, workbasketService;
|
||||
|
||||
})
|
||||
.compileComponents();
|
||||
fixture = TestBed.createComponent(WorkbasketInformationComponent);
|
||||
component = fixture.componentInstance;
|
||||
debugElement = fixture.debugElement.nativeElement;
|
||||
}));
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [WorkbasketInformationComponent, IconTypeComponent, MapValuesPipe, RemoveNoneTypePipe, SpinnerComponent, GeneralMessageModalComponent],
|
||||
imports: [FormsModule, AngularSvgIconModule, HttpClientModule, HttpModule, RouterTestingModule],
|
||||
providers: [WorkbasketService, AlertService]
|
||||
|
||||
afterEach(() =>{
|
||||
document.body.removeChild(debugElement);
|
||||
});
|
||||
})
|
||||
.compileComponents();
|
||||
fixture = TestBed.createComponent(WorkbasketInformationComponent);
|
||||
component = fixture.componentInstance;
|
||||
debugElement = fixture.debugElement.nativeElement;
|
||||
workbasketService = TestBed.get(WorkbasketService);
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should create a panel with heading and form with all fields', async(() => {
|
||||
component.workbasket = new Workbasket('id','created','keyModified','domain','type','modified','name','description','owner','custom1','custom2','custom3','custom4','orgLevel1','orgLevel2','orgLevel3','orgLevel4',null);
|
||||
fixture.detectChanges();
|
||||
expect(debugElement.querySelector('#wb-information')).toBeDefined();
|
||||
expect(debugElement.querySelector('#wb-information > .panel-heading > h4').textContent).toBe('name');
|
||||
expect(debugElement.querySelectorAll('#wb-information > .panel-body > form').length).toBe(2);
|
||||
fixture.whenStable().then(() => {
|
||||
expect(debugElement.querySelector('#wb-information > .panel-body > form:first-child > div:first-child > input').value).toBe('keyModified');
|
||||
});
|
||||
|
||||
}));
|
||||
afterEach(() => {
|
||||
document.body.removeChild(debugElement);
|
||||
});
|
||||
|
||||
it('selectType should set workbasket.type to personal with 0 and group in other case', () => {
|
||||
component.workbasket = new Workbasket(null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null);
|
||||
expect(component.workbasket.type).toEqual(null);
|
||||
component.selectType(ICONTYPES.PERSONAL);
|
||||
expect(component.workbasket.type).toEqual('PERSONAL');
|
||||
component.selectType(ICONTYPES.GROUP);
|
||||
expect(component.workbasket.type).toEqual('GROUP');
|
||||
});
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should create a panel with heading and form with all fields', async(() => {
|
||||
component.workbasket = new Workbasket('id', 'created', 'keyModified', 'domain', 'type', 'modified', 'name', 'description', 'owner', 'custom1', 'custom2', 'custom3', 'custom4', 'orgLevel1', 'orgLevel2', 'orgLevel3', 'orgLevel4', null);
|
||||
fixture.detectChanges();
|
||||
expect(debugElement.querySelector('#wb-information')).toBeDefined();
|
||||
expect(debugElement.querySelector('#wb-information > .panel-heading > h4').textContent).toBe('name');
|
||||
expect(debugElement.querySelectorAll('#wb-information > .panel-body > form').length).toBe(2);
|
||||
fixture.whenStable().then(() => {
|
||||
expect(debugElement.querySelector('#wb-information > .panel-body > form:first-child > div:first-child > input').value).toBe('keyModified');
|
||||
});
|
||||
|
||||
}));
|
||||
|
||||
it('selectType should set workbasket.type to personal with 0 and group in other case', () => {
|
||||
component.workbasket = new Workbasket(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null);
|
||||
expect(component.workbasket.type).toEqual(null);
|
||||
component.selectType(ICONTYPES.PERSONAL);
|
||||
expect(component.workbasket.type).toEqual('PERSONAL');
|
||||
component.selectType(ICONTYPES.GROUP);
|
||||
expect(component.workbasket.type).toEqual('GROUP');
|
||||
});
|
||||
|
||||
|
||||
it('should create a copy of workbasket when workbasket is selected', () => {
|
||||
expect(component.workbasketClone).toBeUndefined();
|
||||
component.workbasket = new Workbasket('id', 'created', 'keyModified', 'domain', 'type', 'modified', 'name', 'description', 'owner', 'custom1', 'custom2', 'custom3', 'custom4', 'orgLevel1', 'orgLevel2', 'orgLevel3', 'orgLevel4', null);
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
expect(component.workbasket.workbasketId).toEqual(component.workbasketClone.workbasketId);
|
||||
});
|
||||
|
||||
it('should reset requestInProgress after saving request is done', fakeAsync(() => {
|
||||
component.workbasket = new Workbasket('id', 'created', 'keyModified', 'domain', 'type', 'modified', 'name', 'description',
|
||||
'owner', 'custom1', 'custom2', 'custom3', 'custom4', 'orgLevel1', 'orgLevel2',
|
||||
'orgLevel3', 'orgLevel4', new Array<Links>(new Links('self', 'someUrl')));
|
||||
spyOn(workbasketService, 'updateWorkbasket').and.returnValue(Observable.of(component.workbasket));
|
||||
spyOn(workbasketService, 'triggerWorkBasketSaved').and.returnValue(Observable.of(component.workbasket));
|
||||
component.onSave();
|
||||
expect(component.modalSpinner).toBeTruthy();
|
||||
expect(component.modalErrorMessage).toBeUndefined
|
||||
expect(component.requestInProgress).toBeFalsy();
|
||||
|
||||
}));
|
||||
|
||||
it('should trigger triggerWorkBasketSaved method after saving request is done', () => {
|
||||
component.workbasket = new Workbasket('id', 'created', 'keyModified', 'domain', 'type', 'modified', 'name', 'description',
|
||||
'owner', 'custom1', 'custom2', 'custom3', 'custom4', 'orgLevel1', 'orgLevel2',
|
||||
'orgLevel3', 'orgLevel4', new Array<Links>(new Links('self', 'someUrl')));
|
||||
spyOn(workbasketService, 'updateWorkbasket').and.returnValue(Observable.of(component.workbasket));
|
||||
spyOn(workbasketService, 'triggerWorkBasketSaved').and.returnValue(Observable.of(component.workbasket));
|
||||
component.onSave();
|
||||
expect(workbasketService.triggerWorkBasketSaved).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -1,26 +1,98 @@
|
|||
import { Component, OnInit, Input, Output } from '@angular/core';
|
||||
import { Workbasket } from '../../../model/workbasket';
|
||||
import { WorkbasketService } from '../../../services/workbasketservice.service';
|
||||
import { WorkbasketService } from '../../../services/workbasket.service';
|
||||
import { IconTypeComponent, ICONTYPES } from '../../../shared/type-icon/icon-type.component';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { Utils } from '../../../shared/utils/utils';
|
||||
import { AlertService, AlertModel, AlertType } from '../../../services/alert.service';
|
||||
import { ActivatedRoute, Params, Router, NavigationStart } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'workbasket-information',
|
||||
templateUrl: './workbasket-information.component.html',
|
||||
styleUrls: ['./workbasket-information.component.scss']
|
||||
selector: 'workbasket-information',
|
||||
templateUrl: './workbasket-information.component.html',
|
||||
styleUrls: ['./workbasket-information.component.scss']
|
||||
})
|
||||
export class WorkbasketInformationComponent implements OnInit {
|
||||
|
||||
@Input()
|
||||
workbasket: Workbasket;
|
||||
allTypes: Map<string, string>;
|
||||
constructor(private service: WorkbasketService) {
|
||||
this.allTypes = IconTypeComponent.allTypes;
|
||||
}
|
||||
@Input()
|
||||
workbasket: Workbasket;
|
||||
workbasketClone: Workbasket;
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
allTypes: Map<string, string>;
|
||||
requestInProgress: boolean = false;
|
||||
modalSpinner: boolean = false;
|
||||
modalErrorMessage: string;
|
||||
modalTitle: string = 'There was error while saving your workbasket';
|
||||
|
||||
private workbasketSubscription: Subscription;
|
||||
private routeSubscription: Subscription;
|
||||
|
||||
constructor(private workbasketService: WorkbasketService,
|
||||
private alertService: AlertService,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router, ) {
|
||||
this.allTypes = IconTypeComponent.allTypes;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.workbasketClone = { ...this.workbasket };
|
||||
this.routeSubscription = this.router.events.subscribe(event => {
|
||||
if (event instanceof NavigationStart) {
|
||||
this.checkForChanges();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
selectType(type: ICONTYPES) {
|
||||
this.workbasket.type = type;
|
||||
}
|
||||
|
||||
|
||||
onSave() {
|
||||
this.beforeRequest();
|
||||
this.workbasketSubscription = (this.workbasketService.updateWorkbasket((Utils.getSelfRef(this.workbasket.links).href), this.workbasket).subscribe(
|
||||
workbasketUpdated => {
|
||||
this.afterRequest();
|
||||
this.workbasket = workbasketUpdated;
|
||||
this.workbasketClone = {...this.workbasket};
|
||||
this.alertService.triggerAlert(new AlertModel(AlertType.SUCCESS, `Workbasket ${workbasketUpdated.key} was saved successfully`))
|
||||
},
|
||||
error => {
|
||||
this.afterRequest();
|
||||
this.modalErrorMessage = error;
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
onClear() {
|
||||
this.alertService.triggerAlert(new AlertModel(AlertType.INFO, 'Reset edited fields'))
|
||||
this.workbasket = { ...this.workbasketClone };
|
||||
}
|
||||
|
||||
private beforeRequest(){
|
||||
this.requestInProgress = true;
|
||||
this.modalSpinner = true;
|
||||
this.modalErrorMessage = undefined;
|
||||
}
|
||||
private afterRequest(){
|
||||
this.requestInProgress = false;
|
||||
this.workbasketService.triggerWorkBasketSaved();
|
||||
|
||||
}
|
||||
|
||||
private checkForChanges() {
|
||||
if (!Workbasket.equals(this.workbasket, this.workbasketClone)) {
|
||||
this.openDiscardChangesModal();
|
||||
}
|
||||
}
|
||||
|
||||
private openDiscardChangesModal() {
|
||||
|
||||
}
|
||||
|
||||
private ngOnDestroy() {
|
||||
if (this.workbasketSubscription) { this.workbasketSubscription.unsubscribe(); }
|
||||
if (this.routeSubscription) { this.routeSubscription.unsubscribe(); }
|
||||
}
|
||||
|
||||
selectType(type: ICONTYPES){
|
||||
this.workbasket.type = type;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<div class="container-scrollable" >
|
||||
<taskana-spinner [isRunning]="requestInProgress" class = "centered-horizontally"></taskana-spinner>
|
||||
<app-no-access *ngIf="!hasPermission || !workbasket && selectedId" ></app-no-access>
|
||||
<div id ="workbasket-details" class="workbasket-details" *ngIf="workbasket">
|
||||
<app-no-access *ngIf="!requestInProgress && (!hasPermission || !workbasket && selectedId)" ></app-no-access>
|
||||
<div id ="workbasket-details" class="workbasket-details" *ngIf="workbasket && !requestInProgress">
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li *ngIf="showDetail" class="visible-xs visible-sm hidden">
|
||||
<a (click) = "backClicked()"><span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>Back</a>
|
||||
</li>
|
||||
<li role="presentation" class="active">
|
||||
<a href="#work-baskets" aria-controls="work baskets" role="tab" data-toggle="tab" aria-expanded="true">Work baskets information</a>
|
||||
<a href="#work-baskets" aria-controls="work baskets" role="tab" data-toggle="tab" aria-expanded="true">Information</a>
|
||||
</li>
|
||||
<li role="presentation" class="inactive">
|
||||
<a href="#authorizations" aria-controls="Authorizations" role="tab" data-toggle="tab" aria-expanded="true">Authorizations</a>
|
||||
|
@ -28,4 +28,5 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<taskana-alert></taskana-alert>
|
||||
</div>
|
||||
|
|
|
@ -8,16 +8,21 @@ import { SpinnerComponent } from '../../shared/spinner/spinner.component';
|
|||
import { ICONTYPES, IconTypeComponent } from '../../shared/type-icon/icon-type.component';
|
||||
import { MapValuesPipe } from '../../pipes/map-values.pipe';
|
||||
import { RemoveNoneTypePipe } from '../../pipes/remove-none-type';
|
||||
import { AlertComponent } from '../../shared/alert/alert.component';
|
||||
import { GeneralMessageModalComponent } from '../../shared/general-message-modal/general-message-modal.component';
|
||||
import { Links } from 'app/model/links';
|
||||
|
||||
import { WorkbasketService } from '../../services/workbasketservice.service';
|
||||
import { WorkbasketService } from '../../services/workbasket.service';
|
||||
import { MasterAndDetailService } from '../../services/master-and-detail.service';
|
||||
import { PermissionService } from '../../services/permission.service';
|
||||
import { AlertService } from '../../services/alert.service';
|
||||
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { AngularSvgIconModule } from 'angular-svg-icon';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { HttpModule } from '@angular/http';
|
||||
import { WorkbasketSummary } from '../../model/workbasketSummary';
|
||||
|
||||
describe('WorkbasketDetailsComponent', () => {
|
||||
let component: WorkbasketDetailsComponent;
|
||||
|
@ -29,8 +34,8 @@ describe('WorkbasketDetailsComponent', () => {
|
|||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports:[RouterTestingModule, FormsModule, AngularSvgIconModule, HttpClientModule, HttpModule],
|
||||
declarations: [ WorkbasketDetailsComponent, NoAccessComponent, WorkbasketInformationComponent, SpinnerComponent, IconTypeComponent, MapValuesPipe, RemoveNoneTypePipe ],
|
||||
providers:[WorkbasketService, MasterAndDetailService, PermissionService]
|
||||
declarations: [ WorkbasketDetailsComponent, NoAccessComponent, WorkbasketInformationComponent, SpinnerComponent, IconTypeComponent, MapValuesPipe, RemoveNoneTypePipe, AlertComponent, GeneralMessageModalComponent ],
|
||||
providers:[WorkbasketService, MasterAndDetailService, PermissionService, AlertService]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
@ -44,6 +49,7 @@ describe('WorkbasketDetailsComponent', () => {
|
|||
workbasketService = TestBed.get(WorkbasketService);
|
||||
spyOn(masterAndDetailService, 'getShowDetail').and.returnValue(Observable.of(true));
|
||||
spyOn(workbasketService,'getSelectedWorkBasket').and.returnValue(Observable.of('id1'));
|
||||
spyOn(workbasketService,'getWorkBasketsSummary').and.returnValue(Observable.of(new Array<WorkbasketSummary>(new WorkbasketSummary('id1','','','','','','','','','','','',new Array<Links>( new Links('self', 'someurl'))))));
|
||||
spyOn(workbasketService,'getWorkBasket').and.returnValue(Observable.of(new Workbasket('id1',null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null)));
|
||||
});
|
||||
|
||||
|
@ -74,18 +80,11 @@ describe('WorkbasketDetailsComponent', () => {
|
|||
|
||||
it('should show back button with classes "visible-xs visible-sm hidden" when showDetail property is true', () => {
|
||||
|
||||
component.workbasket = new Workbasket(null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null);
|
||||
component.workbasket = new Workbasket('id1',null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null);
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
expect(debugElement.querySelector('.visible-xs.visible-sm.hidden > a').textContent).toBe('Back');
|
||||
|
||||
});
|
||||
|
||||
it('should create a copy of workbasket when workbasket is selected', () => {
|
||||
expect(component.workbasketClone).toBeUndefined();
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
expect(component.workbasket.id).toEqual(component.workbasketClone.id);
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -1,84 +1,95 @@
|
|||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { Workbasket } from '../../model/workbasket';
|
||||
import { WorkbasketService } from '../../services/workbasketservice.service'
|
||||
import { WorkbasketService } from '../../services/workbasket.service'
|
||||
import { MasterAndDetailService } from '../../services/master-and-detail.service'
|
||||
import { ActivatedRoute, Params, Router, NavigationStart } from '@angular/router';
|
||||
import { PermissionService } from '../../services/permission.service';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { WorkbasketSummary } from '../../model/workbasketSummary';
|
||||
import { Utils } from '../../shared/utils/utils';
|
||||
|
||||
@Component({
|
||||
selector: 'workbasket-details',
|
||||
templateUrl: './workbasket-details.component.html',
|
||||
styleUrls: ['./workbasket-details.component.scss']
|
||||
selector: 'workbasket-details',
|
||||
templateUrl: './workbasket-details.component.html',
|
||||
styleUrls: ['./workbasket-details.component.scss']
|
||||
})
|
||||
export class WorkbasketDetailsComponent implements OnInit {
|
||||
|
||||
selectedId: number = -1;
|
||||
workbasket: Workbasket;
|
||||
workbasketClone: Workbasket;
|
||||
showDetail: boolean = false;
|
||||
hasPermission: boolean = true;
|
||||
requestInProgress: boolean = false;
|
||||
|
||||
private workbasketSelectedSubscription: Subscription;
|
||||
private workbasketSubscription: Subscription;
|
||||
private routeSubscription: Subscription;
|
||||
private masterAndDetailSubscription: Subscription;
|
||||
private permissionSubscription: Subscription;
|
||||
selectedId: number = -1;
|
||||
workbasket: Workbasket;
|
||||
showDetail: boolean = false;
|
||||
hasPermission: boolean = true;
|
||||
requestInProgress: boolean = false;
|
||||
|
||||
constructor(private service: WorkbasketService,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private masterAndDetailService: MasterAndDetailService,
|
||||
private permissionService: PermissionService) { }
|
||||
private workbasketSelectedSubscription: Subscription;
|
||||
private workbasketSubscription: Subscription;
|
||||
private routeSubscription: Subscription;
|
||||
private masterAndDetailSubscription: Subscription;
|
||||
private permissionSubscription: Subscription;
|
||||
|
||||
|
||||
constructor(private service: WorkbasketService,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private masterAndDetailService: MasterAndDetailService,
|
||||
private permissionService: PermissionService) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.workbasketSelectedSubscription = this.service.getSelectedWorkBasket().subscribe( workbasketIdSelected => {
|
||||
this.workbasket = undefined;
|
||||
this.requestInProgress = true;
|
||||
this.workbasketSubscription = this.service.getWorkBasket(workbasketIdSelected).subscribe( workbasket => {
|
||||
this.workbasket = workbasket;
|
||||
this.workbasketClone = { ...this.workbasket };
|
||||
this.requestInProgress = false;
|
||||
});
|
||||
});
|
||||
|
||||
this.routeSubscription = this.route.params.subscribe(params => {
|
||||
let id = params['id'];
|
||||
if( id && id !== '') {
|
||||
this.selectedId = id;
|
||||
this.service.selectWorkBasket(id);
|
||||
}
|
||||
});
|
||||
|
||||
this.masterAndDetailSubscription = this.masterAndDetailService.getShowDetail().subscribe(showDetail => {
|
||||
this.showDetail = showDetail;
|
||||
});
|
||||
|
||||
this.permissionSubscription = this.permissionService.hasPermission().subscribe( permission => {
|
||||
this.hasPermission = permission;
|
||||
if(!this.hasPermission){
|
||||
this.requestInProgress = false;
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
ngOnInit() {
|
||||
this.workbasketSelectedSubscription = this.service.getSelectedWorkBasket().subscribe(workbasketIdSelected => {
|
||||
this.workbasket = undefined;
|
||||
this.requestInProgress = true;
|
||||
this.getWorkbasketInformation(workbasketIdSelected);
|
||||
});
|
||||
|
||||
onSave() {
|
||||
}
|
||||
|
||||
backClicked(): void {
|
||||
this.service.selectWorkBasket(undefined);
|
||||
this.router.navigate(['./'], { relativeTo: this.route.parent });
|
||||
}
|
||||
this.routeSubscription = this.route.params.subscribe(params => {
|
||||
let id = params['id'];
|
||||
if (id && id !== '') {
|
||||
this.selectedId = id;
|
||||
this.service.selectWorkBasket(id);
|
||||
}
|
||||
});
|
||||
|
||||
ngOnDestroy(){
|
||||
if(this.workbasketSelectedSubscription){this.workbasketSelectedSubscription.unsubscribe();}
|
||||
if(this.workbasketSubscription){this.workbasketSubscription.unsubscribe();}
|
||||
if(this.routeSubscription){this.routeSubscription.unsubscribe();}
|
||||
if(this.masterAndDetailSubscription){this.masterAndDetailSubscription.unsubscribe();}
|
||||
if(this.permissionSubscription){this.permissionSubscription.unsubscribe();}
|
||||
}
|
||||
this.masterAndDetailSubscription = this.masterAndDetailService.getShowDetail().subscribe(showDetail => {
|
||||
this.showDetail = showDetail;
|
||||
});
|
||||
|
||||
this.permissionSubscription = this.permissionService.hasPermission().subscribe(permission => {
|
||||
this.hasPermission = permission;
|
||||
if (!this.hasPermission) {
|
||||
this.requestInProgress = false;
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
backClicked(): void {
|
||||
this.service.selectWorkBasket(undefined);
|
||||
this.router.navigate(['./'], { relativeTo: this.route.parent });
|
||||
}
|
||||
|
||||
private getWorkbasketInformation(workbasketIdSelected: string) {
|
||||
this.service.getWorkBasketsSummary().subscribe((workbasketSummary: Array<WorkbasketSummary>) => {
|
||||
let workbasketSummarySelected = this.getWorkbasketSummaryById(workbasketSummary, workbasketIdSelected);
|
||||
if (workbasketSummarySelected && workbasketSummarySelected.links) {
|
||||
this.workbasketSubscription = this.service.getWorkBasket(Utils.getSelfRef(workbasketSummarySelected.links).href).subscribe(workbasket => {
|
||||
this.workbasket = workbasket;
|
||||
this.requestInProgress = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private getWorkbasketSummaryById(workbasketSummary: Array<WorkbasketSummary>, selectedId: string) {
|
||||
return workbasketSummary.find((summary => summary.workbasketId === selectedId));
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
if (this.workbasketSelectedSubscription) { this.workbasketSelectedSubscription.unsubscribe(); }
|
||||
if (this.workbasketSubscription) { this.workbasketSubscription.unsubscribe(); }
|
||||
if (this.routeSubscription) { this.routeSubscription.unsubscribe(); }
|
||||
if (this.masterAndDetailSubscription) { this.masterAndDetailSubscription.unsubscribe(); }
|
||||
if (this.permissionSubscription) { this.permissionSubscription.unsubscribe(); }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
<span class="glyphicon {{sortDirection === 'asc'? 'glyphicon-sort-by-attributes-alt' : 'glyphicon-sort-by-attributes' }} blue"
|
||||
data-toggle= "tooltip" title="{{sortDirection === 'asc'? 'A-Z' : 'Z-A' }}"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-right sortby-dropdown popup" aria-labelledby="sortingDropdown">
|
||||
<li>
|
||||
<div class="dropdown-menu dropdown-menu-right sortby-dropdown popup" aria-labelledby="sortingDropdown">
|
||||
<div>
|
||||
<div class="col-xs-6">
|
||||
<h5>Sort By</h5>
|
||||
</div>
|
||||
|
@ -36,8 +36,8 @@
|
|||
<button id= "sort-by-direction-desc" type="button" (click)="changeOrder('desc')" data-toggle="tooltip" title="Z-A" class="btn btn-default {{sortDirection === 'desc'? 'selected' : '' }}" >
|
||||
<span class="glyphicon glyphicon-sort-by-attributes blue" aria-hidden="true"></span>
|
||||
</button>
|
||||
</li>
|
||||
<li role="separator" class="divider"></li>
|
||||
</div>
|
||||
<div role="separator" class="divider"></div>
|
||||
<li id="sort-by-{{sortingField.key}}"(click)="changeSortBy(sortingField.key)" *ngFor="let sortingField of sortingFields | mapValues">
|
||||
<a>
|
||||
<label>
|
||||
|
@ -46,7 +46,7 @@
|
|||
</label>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix btn-group">
|
||||
<button class="btn btn-default collapsed" type="button" id="collapsedMenufilterWb" data-toggle="collapse" data-target="#wb-filter-bar" aria-expanded="false">
|
||||
|
@ -60,7 +60,7 @@
|
|||
</div>
|
||||
</li>
|
||||
<taskana-spinner [isRunning]="requestInProgress" class = "centered-horizontally"></taskana-spinner>
|
||||
<li class="list-group-item" *ngFor= "let workbasket of workbaskets" [class.active]="workbasket.workbasketId == selectedId" type="text" (click) ="selectWorkbasket(workbasket.workbasketId)" [routerLink]="[ {outlets: { detail: [workbasket.workbasketId] } }]">
|
||||
<li class="list-group-item" *ngFor= "let workbasket of workbaskets" [class.active]="workbasket.workbasketId == selectedId" type="text" (click) ="selectWorkbasket(workbasket.workbasketId)">
|
||||
<div class="row">
|
||||
<dl class="col-xs-1">
|
||||
<dt>
|
||||
|
|
|
@ -4,7 +4,7 @@ import { WorkbasketListComponent } from './workbasket-list.component';
|
|||
import { AngularSvgIconModule } from 'angular-svg-icon';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { WorkbasketSummary } from '../../model/workbasketSummary';
|
||||
import { WorkbasketService, Direction } from '../../services/workbasketservice.service';
|
||||
import { WorkbasketService, Direction } from '../../services/workbasket.service';
|
||||
import { HttpModule } from '@angular/http';
|
||||
import { Router, Routes } from '@angular/router';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
|
@ -17,113 +17,113 @@ import { MapValuesPipe } from '../../pipes/map-values.pipe';
|
|||
|
||||
|
||||
@Component({
|
||||
selector: 'dummy-detail',
|
||||
template: 'dummydetail'
|
||||
selector: 'dummy-detail',
|
||||
template: 'dummydetail'
|
||||
})
|
||||
export class DummyDetailComponent {
|
||||
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-filter',
|
||||
template: ''
|
||||
selector: 'taskana-filter',
|
||||
template: ''
|
||||
})
|
||||
export class FilterComponent {
|
||||
|
||||
}
|
||||
|
||||
const workbasketSummary: WorkbasketSummary[] = [ new WorkbasketSummary("1", "key1", "NAME1", "description 1", "owner 1", "", "", "PERSONAL", "", "", "", ""),
|
||||
new WorkbasketSummary("2", "key2", "NAME2", "description 2", "owner 2", "", "", "GROUP", "", "", "", "")
|
||||
];
|
||||
const workbasketSummary: WorkbasketSummary[] = [new WorkbasketSummary("1", "key1", "NAME1", "description 1", "owner 1", "", "", "PERSONAL", "", "", "", ""),
|
||||
new WorkbasketSummary("2", "key2", "NAME2", "description 2", "owner 2", "", "", "GROUP", "", "", "", "")
|
||||
];
|
||||
|
||||
|
||||
describe('WorkbasketListComponent', () => {
|
||||
let component: WorkbasketListComponent;
|
||||
let fixture: ComponentFixture<WorkbasketListComponent>;
|
||||
let debugElement: any = undefined;
|
||||
let workbasketService: WorkbasketService;
|
||||
let component: WorkbasketListComponent;
|
||||
let fixture: ComponentFixture<WorkbasketListComponent>;
|
||||
let debugElement: any = undefined;
|
||||
let workbasketService: WorkbasketService;
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: ':id', component: DummyDetailComponent, outlet: 'detail' }
|
||||
];
|
||||
const routes: Routes = [
|
||||
{ path: ':id', component: DummyDetailComponent, outlet: 'detail' }
|
||||
];
|
||||
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ WorkbasketListComponent, DummyDetailComponent, MapValuesPipe, SpinnerComponent, FilterComponent, RemoveNoneTypePipe, IconTypeComponent],
|
||||
imports:[
|
||||
AngularSvgIconModule,
|
||||
HttpModule,
|
||||
HttpClientModule,
|
||||
RouterTestingModule.withRoutes(routes)
|
||||
],
|
||||
providers:[WorkbasketService]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
|
||||
fixture = TestBed.createComponent(WorkbasketListComponent);
|
||||
component = fixture.componentInstance;
|
||||
debugElement = fixture.debugElement.nativeElement;
|
||||
workbasketService = TestBed.get(WorkbasketService);
|
||||
spyOn(workbasketService, 'getWorkBasketsSummary').and.returnValue(Observable.of(workbasketSummary));
|
||||
spyOn(workbasketService, 'getSelectedWorkBasket') .and.returnValue(Observable.of('2'));
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [WorkbasketListComponent, DummyDetailComponent, MapValuesPipe, SpinnerComponent, FilterComponent, RemoveNoneTypePipe, IconTypeComponent],
|
||||
imports: [
|
||||
AngularSvgIconModule,
|
||||
HttpModule,
|
||||
HttpClientModule,
|
||||
RouterTestingModule.withRoutes(routes)
|
||||
],
|
||||
providers: [WorkbasketService]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
afterEach(() =>{
|
||||
document.body.removeChild(debugElement);
|
||||
})
|
||||
fixture = TestBed.createComponent(WorkbasketListComponent);
|
||||
component = fixture.componentInstance;
|
||||
debugElement = fixture.debugElement.nativeElement;
|
||||
workbasketService = TestBed.get(WorkbasketService);
|
||||
spyOn(workbasketService, 'getWorkBasketsSummary').and.returnValue(Observable.of(workbasketSummary));
|
||||
spyOn(workbasketService, 'getSelectedWorkBasket').and.returnValue(Observable.of('2'));
|
||||
|
||||
it('should be created', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should call workbasketService.getWorkbasketsSummary method on init', () => {
|
||||
component.ngOnInit();
|
||||
expect(workbasketService.getWorkBasketsSummary).toHaveBeenCalled();
|
||||
workbasketService.getWorkBasketsSummary().subscribe(value => {
|
||||
expect(value).toBe(workbasketSummary);
|
||||
})
|
||||
});
|
||||
afterEach(() => {
|
||||
document.body.removeChild(debugElement);
|
||||
})
|
||||
|
||||
it('should have wb-action-toolbar, wb-search-bar, wb-list-container, wb-pagination, collapsedMenufilterWb and taskana-filter created in the html',() => {
|
||||
expect(debugElement.querySelector('#wb-action-toolbar')).toBeDefined();
|
||||
expect(debugElement.querySelector('#wb-search-bar')).toBeDefined();
|
||||
expect(debugElement.querySelector('#wb-pagination')).toBeDefined();
|
||||
expect(debugElement.querySelector('#wb-list-container')).toBeDefined();
|
||||
expect(debugElement.querySelector('#collapsedMenufilterWb')).toBeDefined();
|
||||
expect(debugElement.querySelector('taskana-filter')).toBeDefined();
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li').length).toBe(3);
|
||||
});
|
||||
it('should be created', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should have two workbasketsummary rows created with the second one selected.',() => {
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li').length).toBe(3);
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li')[1].getAttribute('class')).toBe('list-group-item');
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li')[2].getAttribute('class')).toBe('list-group-item active');
|
||||
});
|
||||
it('should call workbasketService.getWorkbasketsSummary method on init', () => {
|
||||
component.ngOnInit();
|
||||
expect(workbasketService.getWorkBasketsSummary).toHaveBeenCalled();
|
||||
workbasketService.getWorkBasketsSummary().subscribe(value => {
|
||||
expect(value).toBe(workbasketSummary);
|
||||
})
|
||||
});
|
||||
|
||||
it('should have two workbasketsummary rows created with two different icons: user and users',() => {
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li')[1].querySelector('svg-icon').getAttribute('ng-reflect-src')).toBe('./assets/icons/user.svg');
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li')[2].querySelector('svg-icon').getAttribute('ng-reflect-src')).toBe('./assets/icons/users.svg');
|
||||
});
|
||||
it('should have wb-action-toolbar, wb-search-bar, wb-list-container, wb-pagination, collapsedMenufilterWb and taskana-filter created in the html', () => {
|
||||
expect(debugElement.querySelector('#wb-action-toolbar')).toBeDefined();
|
||||
expect(debugElement.querySelector('#wb-search-bar')).toBeDefined();
|
||||
expect(debugElement.querySelector('#wb-pagination')).toBeDefined();
|
||||
expect(debugElement.querySelector('#wb-list-container')).toBeDefined();
|
||||
expect(debugElement.querySelector('#collapsedMenufilterWb')).toBeDefined();
|
||||
expect(debugElement.querySelector('taskana-filter')).toBeDefined();
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li').length).toBe(3);
|
||||
});
|
||||
|
||||
it('should have rendered sort by: name, id, description, owner and type', () => {
|
||||
expect(debugElement.querySelector('#sort-by-name')).toBeDefined();
|
||||
expect(debugElement.querySelector('#sort-by-key')).toBeDefined();
|
||||
expect(debugElement.querySelector('#sort-by-description')).toBeDefined();
|
||||
expect(debugElement.querySelector('#sort-by-owner')).toBeDefined();
|
||||
expect(debugElement.querySelector('#sort-by-type')).toBeDefined();
|
||||
|
||||
});
|
||||
it('should have two workbasketsummary rows created with the second one selected.', () => {
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li').length).toBe(3);
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li')[1].getAttribute('class')).toBe('list-group-item');
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li')[2].getAttribute('class')).toBe('list-group-item active');
|
||||
});
|
||||
|
||||
it('should have performRequest after performFilter is triggered', fakeAsync( () => {
|
||||
let type='PERSONAL', name = 'someName', description = 'someDescription', owner = 'someOwner', key = 'someKey';
|
||||
let filter = new FilterModel(type, name, description, owner, key );
|
||||
component.performFilter(filter);
|
||||
expect(workbasketService.getWorkBasketsSummary).toHaveBeenCalledWith('key', 'asc', undefined, name, description, undefined, owner, type, undefined, key );
|
||||
it('should have two workbasketsummary rows created with two different icons: user and users', () => {
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li')[1].querySelector('svg-icon').getAttribute('ng-reflect-src')).toBe('./assets/icons/user.svg');
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li')[2].querySelector('svg-icon').getAttribute('ng-reflect-src')).toBe('./assets/icons/users.svg');
|
||||
});
|
||||
|
||||
}));
|
||||
it('should have rendered sort by: name, id, description, owner and type', () => {
|
||||
expect(debugElement.querySelector('#sort-by-name')).toBeDefined();
|
||||
expect(debugElement.querySelector('#sort-by-key')).toBeDefined();
|
||||
expect(debugElement.querySelector('#sort-by-description')).toBeDefined();
|
||||
expect(debugElement.querySelector('#sort-by-owner')).toBeDefined();
|
||||
expect(debugElement.querySelector('#sort-by-type')).toBeDefined();
|
||||
|
||||
});
|
||||
|
||||
it('should have performRequest with forced = true after performFilter is triggered', (() => {
|
||||
let type = 'PERSONAL', name = 'someName', description = 'someDescription', owner = 'someOwner', key = 'someKey';
|
||||
let filter = new FilterModel(type, name, description, owner, key);
|
||||
component.performFilter(filter);
|
||||
expect(workbasketService.getWorkBasketsSummary).toHaveBeenCalledWith(true, 'key', 'asc', undefined, name, description, undefined, owner, type, undefined, key);
|
||||
|
||||
}));
|
||||
|
||||
});
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import { Component, OnInit, EventEmitter } from '@angular/core';
|
||||
import { WorkbasketSummary } from '../../model/workbasketSummary';
|
||||
import { WorkbasketService, Direction } from '../../services/workbasketservice.service'
|
||||
import { WorkbasketService, Direction } from '../../services/workbasket.service'
|
||||
import { Subscription } from 'rxjs/Subscription';
|
||||
import { FilterModel } from '../../shared/filter/filter.component'
|
||||
import { filter } from 'rxjs/operator/filter';
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'workbasket-list',
|
||||
|
@ -26,8 +27,9 @@ export class WorkbasketListComponent implements OnInit {
|
|||
|
||||
private workBasketSummarySubscription: Subscription;
|
||||
private workbasketServiceSubscription: Subscription;
|
||||
private workbasketServiceSavedSubscription: Subscription;
|
||||
|
||||
constructor(private workbasketService: WorkbasketService) { }
|
||||
constructor(private workbasketService: WorkbasketService, private router: Router, private route: ActivatedRoute) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.requestInProgress = true;
|
||||
|
@ -39,10 +41,20 @@ export class WorkbasketListComponent implements OnInit {
|
|||
this.workbasketServiceSubscription = this.workbasketService.getSelectedWorkBasket().subscribe(workbasketIdSelected => {
|
||||
this.selectedId = workbasketIdSelected;
|
||||
});
|
||||
|
||||
this.workbasketServiceSavedSubscription = this.workbasketService.workbasketSavedTriggered().subscribe(value => {
|
||||
this.performRequest();
|
||||
});
|
||||
}
|
||||
|
||||
selectWorkbasket(id: string) {
|
||||
this.selectedId = id;
|
||||
if(!this.selectedId) {
|
||||
this.router.navigate(['/workbaskets']);
|
||||
return
|
||||
}
|
||||
this.router.navigate([{outlets: { detail: [this.selectedId] } }], { relativeTo: this.route });
|
||||
|
||||
}
|
||||
|
||||
changeOrder(sortDirection: string) {
|
||||
|
@ -61,19 +73,11 @@ export class WorkbasketListComponent implements OnInit {
|
|||
}
|
||||
|
||||
onDelete(workbasket: WorkbasketSummary) {
|
||||
this.workbasketService.deleteWorkbasket(workbasket.workbasketId).subscribe(result => {
|
||||
var index = this.workbaskets.indexOf(workbasket);
|
||||
if (index > -1) {
|
||||
this.workbaskets.splice(index, 1);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
onAdd() {
|
||||
this.workbasketService.createWorkbasket(this.newWorkbasket).subscribe(result => {
|
||||
this.workbaskets.push(result);
|
||||
this.onClear();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
onClear() {
|
||||
|
@ -81,6 +85,7 @@ export class WorkbasketListComponent implements OnInit {
|
|||
this.newWorkbasket.name = "";
|
||||
this.newWorkbasket.description = "";
|
||||
this.newWorkbasket.owner = "";
|
||||
this.newWorkbasket.key = "";
|
||||
}
|
||||
|
||||
getEmptyObject() {
|
||||
|
@ -90,17 +95,27 @@ export class WorkbasketListComponent implements OnInit {
|
|||
private performRequest(): void {
|
||||
this.requestInProgress = true;
|
||||
this.workbaskets = undefined;
|
||||
this.workbasketServiceSubscription.add(this.workbasketService.getWorkBasketsSummary(this.sortBy, this.sortDirection, undefined,
|
||||
this.workbasketServiceSubscription.add(this.workbasketService.getWorkBasketsSummary(true, this.sortBy, this.sortDirection, undefined,
|
||||
this.filterBy.name, this.filterBy.description, undefined, this.filterBy.owner,
|
||||
this.filterBy.type, undefined, this.filterBy.key).subscribe(resultList => {
|
||||
this.workbaskets = resultList;
|
||||
this.requestInProgress = false;
|
||||
this.unSelectWorkbasket();
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
private unSelectWorkbasket() : void{
|
||||
if (!this.workbaskets.find( wb => wb.workbasketId === this.selectedId)){
|
||||
this.selectWorkbasket(undefined);
|
||||
}
|
||||
}
|
||||
|
||||
private ngOnDestroy() {
|
||||
this.workBasketSummarySubscription.unsubscribe();
|
||||
this.workbasketServiceSubscription.unsubscribe();
|
||||
this.workbasketServiceSavedSubscription.unsubscribe();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -109,8 +109,8 @@
|
|||
}
|
||||
|
||||
.footer-space {
|
||||
max-height: calc(100vh - 160px);
|
||||
height: calc(100vh - 160px);
|
||||
max-height: calc(100vh - 140px);
|
||||
height: calc(100vh - 140px);
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
@ -243,11 +243,6 @@ li > div.row > dl {
|
|||
-o-transition: opacity 300ms ease, visibility 300ms ease;
|
||||
transition: opacity 300ms ease, visibility 300ms ease;
|
||||
}
|
||||
|
||||
taskana-spinner.centered-horizontally > div {
|
||||
margin-top: calc(50vh - 250px);
|
||||
}
|
||||
|
||||
.vertical-align{
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M.157 15.852l-.128-.137v-4.892l.16-.3c.87-1.629 2.53-4.594 2.593-4.632.043-.026.189-.057.323-.068l.244-.021.018-2.632c.015-2.01.03-2.653.066-2.72.121-.227-.168-.214 4.614-.214 3.736 0 4.416.009 4.504.057.216.12.211.054.222 2.907l.01 2.622h.223c.25 0 .388.053.464.177.072.119 2.365 4.482 2.46 4.681.078.163.079.197.069 2.62l-.01 2.454-.123.117-.122.118H.284zm10.6-4.354c0-.601.036-.772.19-.912l.115-.103h1.854c1.166 0 1.854-.014 1.854-.038 0-.063-1.91-3.677-1.952-3.692-.023-.009-.036.378-.037 1.065 0 .593-.01 1.147-.024 1.231-.028.185-.188.369-.35.404-.139.03-.325-.046-.432-.174-.073-.088-.075-.161-.093-4.094l-.02-4.005-3.796-.01-3.797-.01-.01 3.996c-.01 3.985-.01 3.996-.089 4.109-.166.24-.497.253-.694.028l-.09-.102-.01-1.225c-.009-.87-.024-1.221-.053-1.21-.035.012-1.99 3.527-2.045 3.677-.015.04.368.05 1.839.05h1.857l.115.103c.155.14.19.31.191.912v.512h5.476v-.512zm-5.92-3.474c-.024-.027-.044-.104-.044-.173 0-.068.02-.146.045-.173.065-.07 6.296-.07 6.36 0 .059.063.059.284 0 .346-.064.07-6.295.07-6.36 0zm.04-1.461c-.11-.082-.117-.318-.012-.378.1-.058 6.206-.058 6.306 0 .106.06.1.296-.01.378-.127.095-6.158.095-6.285 0zm-.04-1.633c-.024-.027-.044-.105-.044-.173 0-.069.02-.146.045-.173.065-.07 6.296-.07 6.36 0 .059.062.059.283 0 .346-.064.07-6.295.07-6.36 0zm1.63-1.553c-.088-.104-.078-.27.022-.346.073-.055.36-.062 2.357-.062 2.155 0 2.277.004 2.336.073.082.097.079.26-.007.342-.062.06-.28.067-2.357.067-2.17 0-2.292-.004-2.35-.074zm-1.614-.742c-.1-.079-.068-.313.052-.378.125-.067 1.357-.072 1.475-.006.155.088.187.256.07.37-.06.057-.173.066-.8.066-.538 0-.748-.013-.797-.052z"/><path fill="none" d="M-.063.036h13.688v5.951H-.063zM14.125 4.633h2.25v.902h-2.25z"/><path fill="#fff" fill-rule="evenodd" d="M2.038.073h13.369v5.743H2.038z"/><path fill="#fff" fill-rule="evenodd" d="M11.071 4.173h.044v.219h-.044zM4.359 6.621H11.5v2.905H4.359z"/><path d="M5.16 7.084h5.733v.613H5.16zM5.164 8.042h5.733v.613H5.164zM5.159 8.954h5.733v.613H5.159zM3.605 2.452l1.277-1.125c.284-.25.284-.625 0-.875a.752.752 0 0 0-.994 0L2.611 1.577 1.334.452a.752.752 0 0 0-.993 0c-.284.25-.284.625 0 .875l1.277 1.125L.341 3.576c-.284.25-.284.625 0 .875a.75.75 0 0 0 .993 0l1.277-1.125 1.277 1.125a.75.75 0 0 0 .994 0c.284-.25.284-.625 0-.875zM4.05 5.812h7.914v.763H4.05z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16"><defs><clipPath id="b"/><clipPath id="c"/><clipPath id="d"><use xlink:href="#a" width="100%" height="100%"/></clipPath><clipPath id="e"/></defs><path d="M16.02 14.074v-1.51l-.072.068-.073.068-5.501-.008-5.502-.008 1.887-1.837 1.886-1.836 1.084-.001 1.083-.002.022-.488c.027-.624.035-.662.164-.81l.107-.125 1.844-.01c1.015-.005 1.856-.02 1.87-.034.014-.014-.03-.126-.096-.249-.293-.537-.807-1.451-1.152-2.05l-.374-.65.33-.326c.181-.18.335-.32.342-.313.006.008.39.684.852 1.503l1.07 1.893.228.403.009-3.738c.005-2.056.012-.294.016 3.916s0 7.654-.008 7.654c-.009 0-.016-.68-.016-1.51zM.976 15.414c-.334-.117-.523-.55-.4-.918.03-.087 1.574-1.608 7.023-6.917 3.842-3.744 7.03-6.831 7.085-6.86.186-.103.5-.051.673.11.181.166.26.479.187.742-.038.138-.378.476-6.21 6.153-3.393 3.303-6.55 6.38-7.015 6.837-.698.685-.868.836-.971.865a.494.494 0 0 1-.372-.011zm-.812-2.832l-.116-.118V7.875l.63-1.07c.743-1.26 1.803-3.011 1.974-3.262.066-.097.152-.199.19-.225.063-.043.52-.048 4.314-.047h4.245l-.36.34-.36.338-3.195.01-3.194.009-.019 1.163c-.02 1.345-.022 1.353-.259 1.442-.18.068-.332.043-.467-.076-.097-.086-.102-.101-.121-.394a22.726 22.726 0 0 1-.027-.941c-.004-.35-.016-.725-.027-.834-.019-.186-.023-.194-.07-.14-.093.106-1.747 2.864-1.92 3.2l-.078.154.191.02c.105.01.94.02 1.856.02h1.664l.099.1a.71.71 0 0 1 .133.193c.019.05.043.325.053.61l.02.52.078.01c.068.007-.177.257-1.805 1.847L1.71 12.699H.28zm5.027-6.14L5.2 6.17l1.612-.008 1.613-.008-.28.28-.282.279H5.182zm7.041.134c-.171-.061-.213-.148-.235-.5l-.02-.31.443-.434.443-.434-.012.684c-.013.762-.029.825-.243.968-.116.077-.214.084-.376.026zm-7.041-.972l.009-.272 2.03-.008c1.117-.004 2.026.003 2.02.016a4.483 4.483 0 0 1-.278.28l-.269.255H5.182zm0-.9l.009-.271 2.505-.008 2.505-.008-.28.28-.282.279H5.182z"/></svg>
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 1.8 KiB |
|
@ -50,20 +50,15 @@
|
|||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.modelmapper</groupId>
|
||||
<artifactId>modelmapper</artifactId>
|
||||
<version>1.1.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.hateoas</groupId>
|
||||
<artifactId>spring-hateoas</artifactId>
|
||||
<version>0.16.0.RELEASE</version>
|
||||
<version>0.24.0.RELEASE</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
|
Loading…
Reference in New Issue