TSK-185 Add create, copy and delete workbasket item.
This commit is contained in:
parent
32449a4d52
commit
40c670991f
|
@ -7,7 +7,8 @@ import { MasterAndDetailComponent } from './shared/masterAndDetail/master-and-de
|
|||
import { NoAccessComponent } from './workbasket/noAccess/no-access.component';
|
||||
|
||||
const appRoutes: Routes = [
|
||||
{ path: 'workbaskets',
|
||||
{
|
||||
path: 'workbaskets',
|
||||
component: MasterAndDetailComponent,
|
||||
children: [
|
||||
{
|
||||
|
@ -27,7 +28,8 @@ const appRoutes: Routes = [
|
|||
}
|
||||
]
|
||||
},
|
||||
{ path: 'clasifications',
|
||||
{
|
||||
path: 'clasifications',
|
||||
component: MasterAndDetailComponent,
|
||||
children: [
|
||||
{
|
||||
|
|
|
@ -1,37 +1,51 @@
|
|||
<nav class="navbar navbar-fixed-top">
|
||||
<div class="navbar show no-border-radius navbar-inverse no-gutter">
|
||||
<div class="col-xs-3 col-md-4">
|
||||
<svg-icon class="logo hidden visible-xs visible-sm" src="./assets/icons/logo.svg"></svg-icon>
|
||||
<ul class="nav logo">
|
||||
<svg-icon class="logo hidden-xs hidden-sm" src="./assets/icons/logo.svg"></svg-icon>
|
||||
<p class="navbar-brand no-margin hidden-xs hidden-sm" > <a [href]="adminUrl">{{title}}</a></p>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-8 col-md-7 logo-container">
|
||||
<ul class="nav nav-tabs no-border-bottom" id="myTabs" role="tablist">
|
||||
<li role="presentation" class="{{workbasketsRoute? 'active' : 'inactive'}}" role="tab" data-toggle="tab" ><a routerLink="/workbaskets" aria-controls="Work baskets" routerLinkActive="active">Workbaskets</a></li>
|
||||
<li role="presentation" class="{{workbasketsRoute? 'inactive' : 'active'}}" role="tab" data-toggle="tab" ><a routerLink="/clasifications" aria-controls="Clasifications" routerLinkActive="active">Clasifications</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-1">
|
||||
<button type="button" class="navbar-toggle collapsed show" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="navbar" class="collapse pull-right navbar-inverse" data-html="false">
|
||||
<ul class="nav navbar-nav navbar-right content-margin">
|
||||
<li><a [href]="monitorUrl">Monitor</a></li>
|
||||
<li><a [href]="workplaceUrl">Workplace</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="navbar show no-border-radius navbar-inverse no-gutter">
|
||||
<div class="col-xs-3 col-md-4">
|
||||
<svg-icon class="logo hidden visible-xs visible-sm" src="./assets/icons/logo.svg"></svg-icon>
|
||||
<ul class="nav logo">
|
||||
<svg-icon class="logo hidden-xs hidden-sm" src="./assets/icons/logo.svg"></svg-icon>
|
||||
<p class="navbar-brand no-margin hidden-xs hidden-sm">
|
||||
<a [href]="adminUrl">{{title}}</a>
|
||||
</p>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-8 col-md-7 logo-container">
|
||||
<ul class="nav nav-tabs no-border-bottom" id="myTabs" role="tablist">
|
||||
<li role="presentation" class="{{workbasketsRoute? 'active' : 'inactive'}}" role="tab" data-toggle="tab">
|
||||
<a routerLink="/workbaskets" aria-controls="Work baskets" routerLinkActive="active">Workbaskets</a>
|
||||
</li>
|
||||
<li role="presentation" class="{{workbasketsRoute? 'inactive' : 'active'}}" role="tab" data-toggle="tab">
|
||||
<a routerLink="/clasifications" aria-controls="Clasifications" routerLinkActive="active">Clasifications</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-1">
|
||||
<button type="button" class="navbar-toggle collapsed show" data-toggle="collapse" data-target="#navbar" aria-expanded="false"
|
||||
aria-controls="navbar">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="navbar" class="collapse pull-right navbar-inverse" data-html="false">
|
||||
<ul class="nav navbar-nav navbar-right content-margin">
|
||||
<li>
|
||||
<a [href]="monitorUrl">Monitor</a>
|
||||
</li>
|
||||
<li>
|
||||
<a [href]="workplaceUrl">Workplace</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container-fluid container-main">
|
||||
<div class ="row ">
|
||||
<div class="row ">
|
||||
<router-outlet></router-outlet>
|
||||
<taskana-general-message-modal *ngIf="modalErrorMessage" [(message)]="modalErrorMessage" [title]="modalTitle" error="true"></taskana-general-message-modal>
|
||||
<taskana-spinner [isRunning]="requestInProgress" isModal="true"></taskana-spinner>
|
||||
<taskana-alert></taskana-alert>
|
||||
</div>
|
||||
</div>
|
|
@ -5,6 +5,12 @@ import { AngularSvgIconModule } from 'angular-svg-icon';
|
|||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { Router, Routes } from '@angular/router';
|
||||
import { GeneralMessageModalComponent } from './shared/general-message-modal/general-message-modal.component'
|
||||
import { SpinnerComponent } from './shared/spinner/spinner.component'
|
||||
import { ErrorModalService } from './services/error-modal.service';
|
||||
import { RequestInProgressService } from './services/request-in-progress.service';
|
||||
import { AlertComponent } from './shared/alert/alert.component';
|
||||
import { AlertService } from './services/alert.service';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
|
||||
|
@ -17,13 +23,14 @@ describe('AppComponent', () => {
|
|||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
AppComponent, GeneralMessageModalComponent, SpinnerComponent, AlertComponent
|
||||
],
|
||||
imports: [
|
||||
AngularSvgIconModule,
|
||||
RouterTestingModule.withRoutes(routes),
|
||||
HttpClientModule
|
||||
]
|
||||
],
|
||||
providers: [ErrorModalService, RequestInProgressService, AlertService]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(AppComponent);
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { environment } from '../environments/environment';
|
||||
import { Router, ActivatedRoute, NavigationStart } from '@angular/router';
|
||||
import { Router, NavigationStart } from '@angular/router';
|
||||
import { ErrorModalService } from './services/error-modal.service';
|
||||
import { ErrorModel } from './model/modal-error';
|
||||
import { RequestInProgressService } from './services/request-in-progress.service';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-root',
|
||||
|
@ -15,7 +18,15 @@ export class AppComponent implements OnInit {
|
|||
workplaceUrl: string = environment.taskanaWorkplaceUrl;
|
||||
workbasketsRoute = true;
|
||||
|
||||
constructor(private route: ActivatedRoute, private router: Router) {
|
||||
modalErrorMessage = '';
|
||||
modalTitle = '';
|
||||
|
||||
requestInProgress = false;
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private errorModalService: ErrorModalService,
|
||||
private requestInProgressService: RequestInProgressService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
@ -26,5 +37,14 @@ export class AppComponent implements OnInit {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.errorModalService.getError().subscribe((error: ErrorModel) => {
|
||||
this.modalErrorMessage = error.message;
|
||||
this.modalTitle = error.title;
|
||||
})
|
||||
|
||||
this.requestInProgressService.getRequestInProgress().subscribe((value: boolean) => {
|
||||
this.requestInProgress = value;
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
|||
*/
|
||||
import { AppComponent } from './app.component';
|
||||
import { WorkbasketListComponent } from './workbasket/list/workbasket-list.component';
|
||||
import { WorkbasketListToolbarComponent } from './workbasket/list/workbasket-list-toolbar/workbasket-list-toolbar.component'
|
||||
import { WorkbasketDetailsComponent } from './workbasket/details/workbasket-details.component';
|
||||
import { WorkbasketInformationComponent } from './workbasket/details/information/workbasket-information.component';
|
||||
import { DistributionTargetsComponent } from './workbasket/details/distribution-targets/distribution-targets.component';
|
||||
|
@ -42,6 +43,11 @@ import { HttpClientInterceptor } from './services/http-client-interceptor.servic
|
|||
import { PermissionService } from './services/permission.service';
|
||||
import { HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||
import { AlertService } from './services/alert.service';
|
||||
import { ErrorModalService } from './services/error-modal.service';
|
||||
import { RequestInProgressService } from './services/request-in-progress.service';
|
||||
import { SavingWorkbasketService } from './services/saving-workbaskets/saving-workbaskets.service';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Pipes
|
||||
|
@ -66,6 +72,7 @@ const MODULES = [
|
|||
const DECLARATIONS = [
|
||||
AppComponent,
|
||||
WorkbasketListComponent,
|
||||
WorkbasketListToolbarComponent,
|
||||
AccessItemsComponent,
|
||||
WorkbasketDetailsComponent,
|
||||
MasterAndDetailComponent,
|
||||
|
@ -96,7 +103,10 @@ const DECLARATIONS = [
|
|||
useClass: HttpClientInterceptor,
|
||||
multi: true
|
||||
},
|
||||
AlertService
|
||||
AlertService,
|
||||
ErrorModalService,
|
||||
RequestInProgressService,
|
||||
SavingWorkbasketService
|
||||
],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
export enum ACTION {
|
||||
CREATE = 'CREATE',
|
||||
COPY = 'COPY'
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
export class Links {
|
||||
constructor(
|
||||
public self: { 'href': string },
|
||||
public self: { 'href': string } = undefined,
|
||||
public distributionTargets: { 'href': string } = undefined,
|
||||
public accessItems: { 'href': string } = undefined
|
||||
) { }
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
export class ErrorModel {
|
||||
constructor(
|
||||
public title: string = undefined,
|
||||
public message: string = undefined
|
||||
) { }
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
|
||||
export enum ICONTYPES {
|
||||
NONE = '',
|
||||
PERSONAL = 'PERSONAL',
|
||||
GROUP = 'GROUP',
|
||||
CLEARANCE = 'CLEARANCE',
|
||||
TOPIC = 'TOPIC'
|
||||
}
|
|
@ -1,19 +1,20 @@
|
|||
import { Links } from './links';
|
||||
import { ICONTYPES } from './type';
|
||||
|
||||
export class WorkbasketSummary {
|
||||
constructor(
|
||||
public workbasketId: string,
|
||||
public key: string,
|
||||
public name: string,
|
||||
public description: string,
|
||||
public owner: string,
|
||||
public modified: string,
|
||||
public domain: string,
|
||||
public type: string,
|
||||
public orgLevel1: string,
|
||||
public orgLevel2: string,
|
||||
public orgLevel3: string,
|
||||
public orgLevel4: string,
|
||||
public workbasketId: string = undefined,
|
||||
public key: string = undefined,
|
||||
public name: string = undefined,
|
||||
public description: string = undefined,
|
||||
public owner: string = undefined,
|
||||
public modified: string = undefined,
|
||||
public domain: string = undefined,
|
||||
public type: string = ICONTYPES.PERSONAL,
|
||||
public orgLevel1: string = undefined,
|
||||
public orgLevel2: string = undefined,
|
||||
public orgLevel3: string = undefined,
|
||||
public orgLevel4: string = undefined,
|
||||
public _links: Links = undefined) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Links } from './links';
|
||||
import { ICONTYPES } from './type';
|
||||
export class Workbasket {
|
||||
|
||||
public static equals(org: Workbasket, comp: Workbasket): boolean {
|
||||
|
@ -28,7 +29,7 @@ export class Workbasket {
|
|||
public created: string = undefined,
|
||||
public key: string = undefined,
|
||||
public domain: string = undefined,
|
||||
public type: string = undefined,
|
||||
public type: ICONTYPES = ICONTYPES.PERSONAL,
|
||||
public modified: string = undefined,
|
||||
public name: string = undefined,
|
||||
public description: string = undefined,
|
||||
|
@ -41,6 +42,6 @@ export class Workbasket {
|
|||
public orgLevel2: string = undefined,
|
||||
public orgLevel3: string = undefined,
|
||||
public orgLevel4: string = undefined,
|
||||
public _links: Links = undefined) {
|
||||
public _links: Links = new Links()) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Subject } from 'rxjs/Subject';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { ErrorModel } from '../model/modal-error';
|
||||
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class ErrorModalService {
|
||||
|
||||
public errorTriggered = new Subject<ErrorModel>();
|
||||
|
||||
constructor() { }
|
||||
|
||||
triggerError(error: ErrorModel) {
|
||||
this.errorTriggered.next(error);
|
||||
}
|
||||
|
||||
getError(): Observable<ErrorModel> {
|
||||
return this.errorTriggered.asObservable();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Subject } from 'rxjs/Subject';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class RequestInProgressService {
|
||||
|
||||
public requestInProgressTriggered = new Subject<boolean>();
|
||||
|
||||
constructor() { }
|
||||
|
||||
setRequestInProgress(value: boolean) {
|
||||
this.requestInProgressTriggered.next(value);
|
||||
}
|
||||
|
||||
getRequestInProgress(): Observable<boolean> {
|
||||
return this.requestInProgressTriggered.asObservable();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
import { TestBed, inject } from '@angular/core/testing';
|
||||
|
||||
import { SavingWorkbasketService } from './saving-workbaskets.service';
|
||||
|
||||
describe('SavingWorkbasketsService', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [SavingWorkbasketService]
|
||||
});
|
||||
});
|
||||
|
||||
it('should be created', inject([SavingWorkbasketService], (service: SavingWorkbasketService) => {
|
||||
expect(service).toBeTruthy();
|
||||
}));
|
||||
});
|
|
@ -0,0 +1,33 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Subject } from 'rxjs/Subject';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
export class SavingInformation {
|
||||
|
||||
constructor(public url: string,
|
||||
public workbasketId: string) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class SavingWorkbasketService {
|
||||
|
||||
public distributionTargetsSavingInformation = new Subject<SavingInformation>();
|
||||
public accessItemsSavingInformation = new Subject<SavingInformation>();
|
||||
|
||||
constructor() { }
|
||||
|
||||
triggerDistributionTargetSaving(distributionTargetInformation: SavingInformation) {
|
||||
this.distributionTargetsSavingInformation.next(distributionTargetInformation);
|
||||
}
|
||||
triggerAccessItemsSaving(accessItemsInformation: SavingInformation) {
|
||||
this.accessItemsSavingInformation.next(accessItemsInformation);
|
||||
}
|
||||
triggeredDistributionTargetsSaving(): Observable<SavingInformation> {
|
||||
return this.distributionTargetsSavingInformation.asObservable();
|
||||
}
|
||||
triggeredAccessItemsSaving(): Observable<SavingInformation> {
|
||||
return this.accessItemsSavingInformation.asObservable();
|
||||
}
|
||||
}
|
|
@ -75,7 +75,7 @@ export class WorkbasketService {
|
|||
// POST
|
||||
createWorkbasket(url: string, workbasket: Workbasket): Observable<Workbasket> {
|
||||
return this.httpClient
|
||||
.post<Workbasket>(url, this.httpOptions);
|
||||
.post<Workbasket>(url, workbasket, this.httpOptions);
|
||||
}
|
||||
// PUT
|
||||
updateWorkbasket(url: string, workbasket: Workbasket): Observable<Workbasket> {
|
||||
|
|
|
@ -4,4 +4,5 @@
|
|||
bottom: 0;
|
||||
width: 100%;
|
||||
margin-bottom: 0px;
|
||||
text-align: center;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
.list-group-search {
|
||||
padding: 10px 15px;
|
||||
margin-top: 12px;
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
.list-group-search {
|
||||
border-top: none;
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core';
|
||||
import { IconTypeComponent, ICONTYPES } from '../type-icon/icon-type.component'
|
||||
import { IconTypeComponent } from '../type-icon/icon-type.component'
|
||||
import { ICONTYPES } from '../../model/type';
|
||||
|
||||
export class FilterModel {
|
||||
type: string;
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<div class="no-gutter">
|
||||
<div class="{{showDetail? 'col-md-4 hidden-xs hidden-sm':'col-xs-12 col-md-4'}} vertical-right-divider" >
|
||||
<div class="{{showDetail? 'col-md-4 hidden-xs hidden-sm':'col-xs-12 col-md-4'}} vertical-right-divider">
|
||||
<router-outlet name="master"></router-outlet>
|
||||
</div>
|
||||
<div class="{{showDetail? 'col-xs-12 col-md-8': 'hidden'}}" >
|
||||
<div class="{{showDetail? 'col-xs-12 col-md-8': 'hidden'}}">
|
||||
<router-outlet name="detail">
|
||||
</router-outlet>
|
||||
</div>
|
||||
<div class="{{showDetail? 'hidden': 'hidden-xs hidden-sm col-md-8 container-no-detail'}}">
|
||||
<div class = "center-block no-detail" >
|
||||
<h3 class = "grey">Select a worbasket</h3>
|
||||
<div class="center-block no-detail">
|
||||
<h3 class="grey">Select a worbasket</h3>
|
||||
<svg-icon class="img-responsive no-detail-icon" src="./assets/icons/wb-empty.svg"></svg-icon>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
.container-no-detail{
|
||||
top:30vh;
|
||||
height: 65vh;
|
||||
}
|
||||
|
||||
.center-block.no-detail {
|
||||
|
|
|
@ -8,17 +8,18 @@ import { AngularSvgIconModule } from 'angular-svg-icon';
|
|||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { MasterAndDetailService } from '../../services/master-and-detail.service'
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-dummy-master',
|
||||
template: 'dummymaster'
|
||||
selector: 'taskana-dummy-master',
|
||||
template: 'dummymaster'
|
||||
})
|
||||
export class DummyMasterComponent {
|
||||
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-dummy-detail',
|
||||
template: 'dummydetail'
|
||||
selector: 'taskana-dummy-detail',
|
||||
template: 'dummydetail'
|
||||
})
|
||||
export class DummyDetailComponent {
|
||||
|
||||
|
@ -26,83 +27,86 @@ export class DummyDetailComponent {
|
|||
|
||||
describe('MasterAndDetailComponent ', () => {
|
||||
|
||||
let component, fixture, debugElement, location, router;
|
||||
let component, fixture, debugElement, location, router;
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: 'workbaskets',
|
||||
component: MasterAndDetailComponent,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: DummyMasterComponent,
|
||||
outlet: 'master'
|
||||
},
|
||||
{
|
||||
path: ':id',
|
||||
component: DummyDetailComponent,
|
||||
outlet: 'detail'
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: 'workbaskets',
|
||||
component: MasterAndDetailComponent,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: DummyMasterComponent,
|
||||
outlet: 'master'
|
||||
},
|
||||
{
|
||||
path: ':id',
|
||||
component: DummyDetailComponent,
|
||||
outlet: 'detail'
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [MasterAndDetailComponent, DummyMasterComponent, DummyDetailComponent],
|
||||
imports: [
|
||||
RouterTestingModule.withRoutes(routes),
|
||||
AngularSvgIconModule,
|
||||
HttpClientModule
|
||||
],
|
||||
providers: [MasterAndDetailService]
|
||||
})
|
||||
.compileComponents();
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
MasterAndDetailComponent,
|
||||
DummyMasterComponent,
|
||||
DummyDetailComponent],
|
||||
imports: [
|
||||
RouterTestingModule.withRoutes(routes),
|
||||
AngularSvgIconModule,
|
||||
HttpClientModule
|
||||
],
|
||||
providers: [MasterAndDetailService]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(MasterAndDetailComponent);
|
||||
component = fixture.debugElement.componentInstance;
|
||||
debugElement = fixture.debugElement.nativeElement;
|
||||
location = TestBed.get(Location);
|
||||
router = TestBed.get(Router);
|
||||
router.initialNavigation();
|
||||
fixture = TestBed.createComponent(MasterAndDetailComponent);
|
||||
component = fixture.debugElement.componentInstance;
|
||||
debugElement = fixture.debugElement.nativeElement;
|
||||
location = TestBed.get(Location);
|
||||
router = TestBed.get(Router);
|
||||
router.initialNavigation();
|
||||
|
||||
}));
|
||||
}));
|
||||
|
||||
afterEach(async(() => {
|
||||
document.body.removeChild(debugElement);
|
||||
}));
|
||||
afterEach(async(() => {
|
||||
document.body.removeChild(debugElement);
|
||||
}));
|
||||
|
||||
it('should be created', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
it('should be created', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should call Router.navigateByUrl("/wokbaskets") and showDetail property should be false', async(() => {
|
||||
it('should call Router.navigateByUrl("/wokbaskets") and showDetail property should be false', async(() => {
|
||||
|
||||
expect(component.showDetail).toBe(false);
|
||||
fixture.detectChanges();
|
||||
router.navigateByUrl('/workbaskets');
|
||||
expect(component.showDetail).toBe(false);
|
||||
expect(component.showDetail).toBe(false);
|
||||
fixture.detectChanges();
|
||||
router.navigateByUrl('/workbaskets');
|
||||
expect(component.showDetail).toBe(false);
|
||||
|
||||
}));
|
||||
}));
|
||||
|
||||
it('should call Router.navigateByUrl("/wokbaskets/(detail:Id)") and showDetail property should be true', async(() => {
|
||||
it('should call Router.navigateByUrl("/wokbaskets/(detail:Id)") and showDetail property should be true', async(() => {
|
||||
|
||||
expect(component.showDetail).toBe(false);
|
||||
fixture.detectChanges();
|
||||
router.navigateByUrl('/workbaskets/(detail:2)');
|
||||
expect(component.showDetail).toBe(true);
|
||||
expect(component.showDetail).toBe(false);
|
||||
fixture.detectChanges();
|
||||
router.navigateByUrl('/workbaskets/(detail:2)');
|
||||
expect(component.showDetail).toBe(true);
|
||||
|
||||
}));
|
||||
}));
|
||||
|
||||
it('should navigate to parent state when backIsClicked', async(() => {
|
||||
it('should navigate to parent state when backIsClicked', async(() => {
|
||||
|
||||
const spy = spyOn(router, 'navigateByUrl');
|
||||
router.navigateByUrl('/workbaskets/(detail:2)');
|
||||
fixture.detectChanges();
|
||||
expect(spy.calls.first().args[0]).toBe('/workbaskets/(detail:2)');
|
||||
component.backClicked();
|
||||
expect(spy.calls.mostRecent().args.length).toBe(2);
|
||||
const spy = spyOn(router, 'navigateByUrl');
|
||||
router.navigateByUrl('/workbaskets/(detail:2)');
|
||||
fixture.detectChanges();
|
||||
expect(spy.calls.first().args[0]).toBe('/workbaskets/(detail:2)');
|
||||
component.backClicked();
|
||||
expect(spy.calls.mostRecent().args.length).toBe(2);
|
||||
|
||||
}));
|
||||
}));
|
||||
|
||||
});
|
||||
|
|
|
@ -1,14 +1,5 @@
|
|||
import { Component, OnInit, Input } from '@angular/core';
|
||||
|
||||
|
||||
export enum ICONTYPES {
|
||||
NONE = '',
|
||||
PERSONAL = 'PERSONAL',
|
||||
GROUP = 'GROUP',
|
||||
CLEARANCE = 'CLEARANCE',
|
||||
TOPIC = 'TOPIC'
|
||||
}
|
||||
|
||||
import { ICONTYPES } from '../../model/type';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-icon-type',
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
<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 *ngIf="workbasket && accessItems" id="wb-information" class="panel panel-default">
|
||||
<div *ngIf="workbasket" id="wb-information" class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<div class="btn-group pull-right">
|
||||
<button type="button" (click)="onSave()" [disabled]="!AccessItemsForm.form.valid" class="btn btn-default btn-primary">Save</button>
|
||||
<button type="button" (click)="onSave()" [disabled]="!AccessItemsForm.form.valid || action === 'COPY'" class="btn btn-default btn-primary">Save</button>
|
||||
<button type="button" (click)="clear()" class="btn btn-default">Undo changes</button>
|
||||
</div>
|
||||
<h4 class="panel-header">{{workbasket.name}}</h4>
|
||||
<h4 class="panel-header">{{workbasket.name}}
|
||||
<span *ngIf="!workbasket.workbasketId" class="badge warning"> {{badgeMessage}}</span>
|
||||
</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form #AccessItemsForm="ngForm">
|
||||
|
|
|
@ -13,6 +13,9 @@ import { Observable } from 'rxjs/Observable';
|
|||
import { AccessItemsComponent } from './access-items.component';
|
||||
import { WorkbasketAccessItems } from '../../../model/workbasket-access-items';
|
||||
import { WorkbasketAccessItemsResource } from '../../../model/workbasket-access-items-resource';
|
||||
import { ICONTYPES } from '../../../model/type';
|
||||
import { ErrorModalService } from '../../../services/error-modal.service';
|
||||
import { SavingWorkbasketService, SavingInformation } from '../../../services/saving-workbaskets/saving-workbaskets.service';
|
||||
|
||||
describe('AccessItemsComponent', () => {
|
||||
let component: AccessItemsComponent;
|
||||
|
@ -23,7 +26,7 @@ describe('AccessItemsComponent', () => {
|
|||
TestBed.configureTestingModule({
|
||||
declarations: [SpinnerComponent, AccessItemsComponent, GeneralMessageModalComponent],
|
||||
imports: [FormsModule, AngularSvgIconModule, HttpClientModule, HttpModule, ReactiveFormsModule],
|
||||
providers: [WorkbasketService, AlertService]
|
||||
providers: [WorkbasketService, AlertService, ErrorModalService, SavingWorkbasketService]
|
||||
|
||||
})
|
||||
.compileComponents();
|
||||
|
@ -32,7 +35,7 @@ describe('AccessItemsComponent', () => {
|
|||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(AccessItemsComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.workbasket = new Workbasket('1', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
||||
component.workbasket = new Workbasket('1', '', '', '', ICONTYPES.TOPIC, '', '', '', '', '', '', '', '', '', '', '', '',
|
||||
new Links(undefined, undefined, { 'href': 'someurl' }));
|
||||
workbasketService = TestBed.get(WorkbasketService);
|
||||
alertService = TestBed.get(AlertService);
|
||||
|
|
|
@ -7,6 +7,10 @@ import { WorkbasketAccessItems } from '../../../model/workbasket-access-items';
|
|||
import { WorkbasketService } from '../../../services/workbasket.service';
|
||||
import { AlertService, AlertModel, AlertType } from '../../../services/alert.service';
|
||||
import { WorkbasketAccessItemsResource } from '../../../model/workbasket-access-items-resource';
|
||||
import { ErrorModalService } from '../../../services/error-modal.service';
|
||||
import { ErrorModel } from '../../../model/modal-error';
|
||||
import { SavingWorkbasketService, SavingInformation } from '../../../services/saving-workbaskets/saving-workbaskets.service';
|
||||
import { ACTION } from '../../../model/action';
|
||||
|
||||
declare var $: any;
|
||||
|
||||
|
@ -19,6 +23,9 @@ export class AccessItemsComponent implements OnInit, OnDestroy {
|
|||
|
||||
@Input()
|
||||
workbasket: Workbasket;
|
||||
@Input()
|
||||
action: string;
|
||||
badgeMessage = '';
|
||||
|
||||
accessItemsResource: WorkbasketAccessItemsResource;
|
||||
accessItems: Array<WorkbasketAccessItems>;
|
||||
|
@ -29,11 +36,19 @@ export class AccessItemsComponent implements OnInit, OnDestroy {
|
|||
modalTitle: string;
|
||||
modalErrorMessage: string;
|
||||
accessItemsubscription: Subscription;
|
||||
savingAccessItemsSubscription: Subscription;
|
||||
|
||||
|
||||
constructor(private workbasketService: WorkbasketService, private alertService: AlertService) { }
|
||||
constructor(
|
||||
private workbasketService: WorkbasketService,
|
||||
private alertService: AlertService,
|
||||
private errorModalService: ErrorModalService,
|
||||
private savingWorkbaskets: SavingWorkbasketService) { }
|
||||
|
||||
ngOnInit() {
|
||||
if (!this.workbasket._links.accessItems) {
|
||||
return;
|
||||
}
|
||||
this.accessItemsubscription = this.workbasketService.getWorkBasketAccessItems(this.workbasket._links.accessItems.href)
|
||||
.subscribe((accessItemsResource: WorkbasketAccessItemsResource) => {
|
||||
this.accessItemsResource = accessItemsResource;
|
||||
|
@ -41,7 +56,17 @@ export class AccessItemsComponent implements OnInit, OnDestroy {
|
|||
this.accessItemsClone = this.cloneAccessItems(this.accessItems);
|
||||
this.accessItemsResetClone = this.cloneAccessItems(this.accessItems);
|
||||
})
|
||||
|
||||
this.savingAccessItemsSubscription = this.savingWorkbaskets.triggeredAccessItemsSaving()
|
||||
.subscribe((savingInformation: SavingInformation) => {
|
||||
if (this.action === ACTION.COPY) {
|
||||
this.accessItemsResource._links.self.href = savingInformation.url;
|
||||
this.setWorkbasketIdForCopy(savingInformation.workbasketId);
|
||||
this.onSave();
|
||||
}
|
||||
})
|
||||
if (this.action === ACTION.COPY) {
|
||||
this.badgeMessage = `Copying workbasket: ${this.workbasket.key}`;
|
||||
}
|
||||
}
|
||||
|
||||
addAccessItem() {
|
||||
|
@ -70,12 +95,11 @@ export class AccessItemsComponent implements OnInit, OnDestroy {
|
|||
AlertType.SUCCESS, `Workbasket ${this.workbasket.name} Access items were saved successfully`));
|
||||
this.requestInProgress = false;
|
||||
return true;
|
||||
},
|
||||
error => {
|
||||
this.modalErrorMessage = error.message;
|
||||
this.requestInProgress = false;
|
||||
return false;
|
||||
})
|
||||
}, error => {
|
||||
this.errorModalService.triggerError(new ErrorModel(`There was error while saving your workbasket's access items`, error))
|
||||
this.requestInProgress = false;
|
||||
return false;
|
||||
})
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -86,8 +110,15 @@ export class AccessItemsComponent implements OnInit, OnDestroy {
|
|||
});
|
||||
return accessItemClone;
|
||||
}
|
||||
private setWorkbasketIdForCopy(workbasketId: string) {
|
||||
this.accessItems.forEach(element => {
|
||||
element.accessItemId = undefined;
|
||||
element.workbasketId = workbasketId;
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
if (this.accessItemsubscription) { this.accessItemsubscription.unsubscribe(); }
|
||||
if (this.savingAccessItemsSubscription) { this.savingAccessItemsSubscription.unsubscribe(); }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
<taskana-spinner [isRunning]="requestInProgress" isModal="true" (requestTimeoutExceeded)="requestTimeoutExceeded($event)"
|
||||
class="centered-horizontally floating"></taskana-spinner>
|
||||
<taskana-general-message-modal *ngIf="modalErrorMessage" [(message)]="modalErrorMessage" [title]="modalTitle" error="true"></taskana-general-message-modal>
|
||||
<div *ngIf="workbasket" id="wb-information" class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<div class="btn-group pull-right">
|
||||
<button type="button" (click)="onSave()" class="btn btn-default btn-primary">Save</button>
|
||||
<button type="button" (click)="onSave()" [disabled]="action === 'COPY'" 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>
|
||||
<h4 class="panel-header">{{workbasket.name}}
|
||||
<span *ngIf="!workbasket.workbasketId" class="badge warning"> {{badgeMessage}}</span>
|
||||
</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<taskana-dual-list id="dual-list-Left" [(distributionTargets)]="distributionTargetsLeft" [distributionTargetsSelected]="distributionTargetsSelected"
|
||||
|
|
|
@ -20,6 +20,9 @@ import { Workbasket } from '../../../model/workbasket';
|
|||
import { WorkbasketDistributionTargetsResource } from '../../../model/workbasket-distribution-targets-resource';
|
||||
import { FilterModel } from '../../../shared/filter/filter.component';
|
||||
import { DualListComponent } from './dual-list/dual-list.component';
|
||||
import { ICONTYPES } from '../../../model/type';
|
||||
import { ErrorModalService } from '../../../services/error-modal.service';
|
||||
import { SavingWorkbasketService, SavingInformation } from '../../../services/saving-workbaskets/saving-workbaskets.service';
|
||||
|
||||
const workbasketSummaryResource: WorkbasketSummaryResource = new WorkbasketSummaryResource({
|
||||
'workbaskets': new Array<WorkbasketSummary>(
|
||||
|
@ -43,7 +46,7 @@ describe('DistributionTargetsComponent', () => {
|
|||
let component: DistributionTargetsComponent;
|
||||
let fixture: ComponentFixture<DistributionTargetsComponent>;
|
||||
let workbasketService;
|
||||
const workbasket = new Workbasket('1', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
||||
const workbasket = new Workbasket('1', '', '', '', ICONTYPES.TOPIC, '', '', '', '', '', '', '', '', '', '', '', '',
|
||||
new Links({ 'href': 'someurl' }, { 'href': 'someurl' }, { 'href': 'someurl' }));
|
||||
|
||||
beforeEach(async(() => {
|
||||
|
@ -51,7 +54,7 @@ describe('DistributionTargetsComponent', () => {
|
|||
imports: [AngularSvgIconModule, HttpClientModule, HttpModule, JsonpModule],
|
||||
declarations: [DistributionTargetsComponent, SpinnerComponent, GeneralMessageModalComponent,
|
||||
FilterComponent, SelectWorkBasketPipe, IconTypeComponent, DualListComponent],
|
||||
providers: [WorkbasketService, AlertService]
|
||||
providers: [WorkbasketService, AlertService, SavingWorkbasketService, ErrorModalService]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
|
|
@ -12,6 +12,10 @@ import { Subscription } from 'rxjs/Subscription';
|
|||
import { element } from 'protractor';
|
||||
import { WorkbasketSummaryResource } from '../../../model/workbasket-summary-resource';
|
||||
import { WorkbasketDistributionTargetsResource } from '../../../model/workbasket-distribution-targets-resource';
|
||||
import { SavingWorkbasketService, SavingInformation } from '../../../services/saving-workbaskets/saving-workbaskets.service';
|
||||
import { ErrorModalService } from '../../../services/error-modal.service';
|
||||
import { ErrorModel } from '../../../model/modal-error';
|
||||
import { ACTION } from '../../../model/action';
|
||||
|
||||
export enum Side {
|
||||
LEFT,
|
||||
|
@ -26,10 +30,14 @@ export class DistributionTargetsComponent implements OnInit, OnDestroy {
|
|||
|
||||
@Input()
|
||||
workbasket: Workbasket;
|
||||
@Input()
|
||||
action: string;
|
||||
badgeMessage = '';
|
||||
|
||||
distributionTargetsSubscription: Subscription;
|
||||
workbasketSubscription: Subscription;
|
||||
workbasketFilterSubscription: Subscription;
|
||||
savingDistributionTargetsSubscription: Subscription;
|
||||
|
||||
distributionTargetsSelectedResource: WorkbasketDistributionTargetsResource;
|
||||
distributionTargetsLeft: Array<WorkbasketSummary>;
|
||||
|
@ -45,10 +53,17 @@ export class DistributionTargetsComponent implements OnInit, OnDestroy {
|
|||
modalErrorMessage: string;
|
||||
side = Side;
|
||||
|
||||
constructor(private workbasketService: WorkbasketService, private alertService: AlertService) { }
|
||||
constructor(
|
||||
private workbasketService: WorkbasketService,
|
||||
private alertService: AlertService,
|
||||
private savingWorkbaskets: SavingWorkbasketService,
|
||||
private errorModalService: ErrorModalService) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.onRequest(undefined);
|
||||
if (!this.workbasket._links.distributionTargets) {
|
||||
return;
|
||||
}
|
||||
this.distributionTargetsSubscription = this.workbasketService.getWorkBasketsDistributionTargets(
|
||||
this.workbasket._links.distributionTargets.href).subscribe(
|
||||
(distributionTargetsSelectedResource: WorkbasketDistributionTargetsResource) => {
|
||||
|
@ -64,6 +79,18 @@ export class DistributionTargetsComponent implements OnInit, OnDestroy {
|
|||
this.onRequest(undefined, true);
|
||||
});
|
||||
});
|
||||
|
||||
this.savingDistributionTargetsSubscription = this.savingWorkbaskets.triggeredDistributionTargetsSaving()
|
||||
.subscribe((savingInformation: SavingInformation) => {
|
||||
if (this.action === ACTION.COPY) {
|
||||
this.distributionTargetsSelectedResource._links.self.href = savingInformation.url;
|
||||
this.onSave();
|
||||
}
|
||||
});
|
||||
|
||||
if (this.action === ACTION.COPY) {
|
||||
this.badgeMessage = `Copying workbasket: ${this.workbasket.key}`;
|
||||
}
|
||||
}
|
||||
|
||||
moveDistributionTargets(side: number) {
|
||||
|
@ -92,7 +119,7 @@ export class DistributionTargetsComponent implements OnInit, OnDestroy {
|
|||
return true;
|
||||
},
|
||||
error => {
|
||||
this.modalErrorMessage = error.message;
|
||||
this.errorModalService.triggerError(new ErrorModel(`There was error while saving your workbasket's distribution targets`, error))
|
||||
this.requestInProgress = false;
|
||||
return false;
|
||||
}
|
||||
|
@ -161,6 +188,8 @@ export class DistributionTargetsComponent implements OnInit, OnDestroy {
|
|||
if (this.distributionTargetsSubscription) { this.distributionTargetsSubscription.unsubscribe(); }
|
||||
if (this.workbasketSubscription) { this.workbasketSubscription.unsubscribe(); }
|
||||
if (this.workbasketFilterSubscription) { this.workbasketFilterSubscription.unsubscribe(); }
|
||||
if (this.savingDistributionTargetsSubscription) { this.savingDistributionTargetsSubscription.unsubscribe(); }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
<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 *ngIf="workbasket" id="wb-information" class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<div class="btn-group pull-right">
|
||||
<button type="button" [disabled]="!WorkbasketForm.form.valid" (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>
|
||||
<h4 class="panel-header">{{workbasket.name}}
|
||||
<span *ngIf="!workbasket.workbasketId" class="badge warning"> {{badgeMessage}}</span>
|
||||
</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form #WorkbasketForm="ngForm">
|
||||
|
@ -24,7 +25,7 @@
|
|||
<input type="text" required #name="ngModel" class="form-control" id="wb-name" placeholder="Name" [(ngModel)]="workbasket.name"
|
||||
name="workbasket.name">
|
||||
<div [hidden]="name.valid" class="required-text">
|
||||
* Name is required
|
||||
* Name is required
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group required">
|
||||
|
@ -32,7 +33,15 @@
|
|||
<input type="text" required #owner="ngModel" class="form-control" id="wb-owner" placeholder="Owner" [(ngModel)]="workbasket.owner"
|
||||
name="workbasket.owner">
|
||||
<div [hidden]="owner.valid" class="required-text">
|
||||
* Owner is required
|
||||
* Owner is required
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group required">
|
||||
<label for="wb-domain" class="control-label">Domain</label>
|
||||
<input type="text" required #domain="ngModel" class="form-control" id="wb-domain" placeholder="Domain" [(ngModel)]="workbasket.domain"
|
||||
name="workbasket.domain">
|
||||
<div [hidden]="domain.valid" class="required-text">
|
||||
* Domain is required
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -43,7 +52,7 @@
|
|||
{{allTypes.get(workbasket.type)}}
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu" aria-labelledby="dropdownMenu1">
|
||||
<ul class="dropdown-menu dropdown-menu" aria-labelledby="dropdownMenu">
|
||||
<li>
|
||||
<a *ngFor="let type of allTypes | mapValues | removeEmptyType" (click)="selectType(type.key)">
|
||||
<taskana-icon-type class="vertical-align" [type]='type.key'></taskana-icon-type>
|
||||
|
@ -53,11 +62,6 @@
|
|||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="wb-domain" class="control-label">Domain</label>
|
||||
<input type="text" class="form-control" id="wb-domain" placeholder="Domain" [(ngModel)]="workbasket.domain" name="workbasket.domain"
|
||||
disabled="">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="wb-description" class="control-label">Description</label>
|
||||
<textarea class="form-control" rows="5" id="wb-description" placeholder="Description" [(ngModel)]="workbasket.description"
|
||||
|
|
|
@ -6,7 +6,7 @@ import { AngularSvgIconModule } from 'angular-svg-icon';
|
|||
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 { 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';
|
||||
|
@ -15,18 +15,22 @@ import { AlertService } from '../../../services/alert.service';
|
|||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { Links } from '../../../model/links';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { ICONTYPES } from '../../../model/type';
|
||||
import { ErrorModalService } from '../../../services/error-modal.service';
|
||||
import { SavingWorkbasketService, SavingInformation } from '../../../services/saving-workbaskets/saving-workbaskets.service';
|
||||
import { ACTION } from '../../../model/action';
|
||||
|
||||
describe('InformationComponent', () => {
|
||||
let component: WorkbasketInformationComponent;
|
||||
let fixture: ComponentFixture<WorkbasketInformationComponent>;
|
||||
let debugElement, workbasketService;
|
||||
let debugElement, workbasketService, alertService, savingWorkbasketService;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [WorkbasketInformationComponent, IconTypeComponent, MapValuesPipe,
|
||||
RemoveNoneTypePipe, SpinnerComponent, GeneralMessageModalComponent],
|
||||
imports: [FormsModule, AngularSvgIconModule, HttpClientModule, HttpModule, RouterTestingModule],
|
||||
providers: [WorkbasketService, AlertService]
|
||||
providers: [WorkbasketService, AlertService, SavingWorkbasketService, ErrorModalService]
|
||||
|
||||
})
|
||||
.compileComponents();
|
||||
|
@ -34,6 +38,9 @@ describe('InformationComponent', () => {
|
|||
component = fixture.componentInstance;
|
||||
debugElement = fixture.debugElement.nativeElement;
|
||||
workbasketService = TestBed.get(WorkbasketService);
|
||||
alertService = TestBed.get(AlertService);
|
||||
savingWorkbasketService = TestBed.get(SavingWorkbasketService);
|
||||
spyOn(alertService, 'triggerAlert');
|
||||
}));
|
||||
|
||||
afterEach(() => {
|
||||
|
@ -45,12 +52,12 @@ describe('InformationComponent', () => {
|
|||
});
|
||||
|
||||
it('should create a panel with heading and form with all fields', async(() => {
|
||||
component.workbasket = new Workbasket('id', 'created', 'keyModified', 'domain', 'type',
|
||||
component.workbasket = new Workbasket('id', 'created', 'keyModified', 'domain', ICONTYPES.TOPIC,
|
||||
'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.querySelector('#wb-information > .panel-heading > h4').textContent.trim()).toBe('name');
|
||||
expect(debugElement.querySelectorAll('#wb-information > .panel-body > form').length).toBe(1);
|
||||
fixture.whenStable().then(() => {
|
||||
expect(debugElement.querySelector('#wb-information > .panel-body > form > div > div > input ').value).toBe('keyModified');
|
||||
|
@ -60,8 +67,6 @@ describe('InformationComponent', () => {
|
|||
|
||||
it('selectType should set workbasket.type to personal with 0 and group in other case', () => {
|
||||
component.workbasket = new Workbasket('id1');
|
||||
expect(component.workbasket.type).toEqual(undefined);
|
||||
component.selectType(ICONTYPES.PERSONAL);
|
||||
expect(component.workbasket.type).toEqual('PERSONAL');
|
||||
component.selectType(ICONTYPES.GROUP);
|
||||
expect(component.workbasket.type).toEqual('GROUP');
|
||||
|
@ -70,7 +75,7 @@ describe('InformationComponent', () => {
|
|||
|
||||
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',
|
||||
component.workbasket = new Workbasket('id', 'created', 'keyModified', 'domain', ICONTYPES.TOPIC, 'modified', 'name', 'description',
|
||||
'owner', 'custom1', 'custom2', 'custom3', 'custom4', 'orgLevel1', 'orgLevel2', 'orgLevel3', 'orgLevel4', null);
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
|
@ -78,20 +83,19 @@ describe('InformationComponent', () => {
|
|||
});
|
||||
|
||||
it('should reset requestInProgress after saving request is done', fakeAsync(() => {
|
||||
component.workbasket = new Workbasket('id', 'created', 'keyModified', 'domain', 'type', 'modified', 'name', 'description',
|
||||
component.workbasket = new Workbasket('id', 'created', 'keyModified', 'domain', ICONTYPES.TOPIC, 'modified', 'name', 'description',
|
||||
'owner', 'custom1', 'custom2', 'custom3', 'custom4', 'orgLevel1', 'orgLevel2',
|
||||
'orgLevel3', 'orgLevel4', new Links({ 'href': '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',
|
||||
component.workbasket = new Workbasket('id', 'created', 'keyModified', 'domain', ICONTYPES.TOPIC, 'modified', 'name', 'description',
|
||||
'owner', 'custom1', 'custom2', 'custom3', 'custom4', 'orgLevel1', 'orgLevel2',
|
||||
'orgLevel3', 'orgLevel4', new Links({ 'href': 'someUrl' }));
|
||||
spyOn(workbasketService, 'updateWorkbasket').and.returnValue(Observable.of(component.workbasket));
|
||||
|
@ -100,4 +104,43 @@ describe('InformationComponent', () => {
|
|||
expect(workbasketService.triggerWorkBasketSaved).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should post a new workbasket when no workbasketId is defined and update workbasket', () => {
|
||||
const workbasket = new Workbasket(undefined, 'created', 'keyModified', 'domain', ICONTYPES.TOPIC, 'modified', 'name', 'description',
|
||||
'owner', 'custom1', 'custom2', 'custom3', 'custom4', 'orgLevel1', 'orgLevel2',
|
||||
'orgLevel3', 'orgLevel4', new Links({ 'href': 'someUrl' }));
|
||||
component.workbasket = workbasket
|
||||
spyOn(workbasketService, 'createWorkbasket').and.returnValue(Observable.of(
|
||||
new Workbasket('someNewId', 'created', 'keyModified', 'domain', ICONTYPES.TOPIC, 'modified', 'name', 'description',
|
||||
'owner', 'custom1', 'custom2', 'custom3', 'custom4', 'orgLevel1', 'orgLevel2',
|
||||
'orgLevel3', 'orgLevel4', new Links({ 'href': 'someUrl' }))));
|
||||
|
||||
component.onSave();
|
||||
expect(alertService.triggerAlert).toHaveBeenCalled();
|
||||
expect(component.workbasket.workbasketId).toBe('someNewId');
|
||||
});
|
||||
|
||||
it('should post a new workbasket, new distribution targets and new access ' +
|
||||
'items when no workbasketId is defined and action is copy', () => {
|
||||
const workbasket = new Workbasket(undefined, 'created', 'keyModified', 'domain', ICONTYPES.TOPIC,
|
||||
'modified', 'name', 'description', 'owner', 'custom1', 'custom2',
|
||||
'custom3', 'custom4', 'orgLevel1', 'orgLevel2',
|
||||
'orgLevel3', 'orgLevel4', new Links({ 'href': 'someUrl' }));
|
||||
component.workbasket = workbasket
|
||||
component.action = ACTION.COPY;
|
||||
|
||||
spyOn(workbasketService, 'createWorkbasket').and.returnValue(Observable.of(
|
||||
new Workbasket('someNewId', 'created', 'keyModified', 'domain', ICONTYPES.TOPIC, 'modified', 'name', 'description',
|
||||
'owner', 'custom1', 'custom2', 'custom3', 'custom4', 'orgLevel1', 'orgLevel2',
|
||||
'orgLevel3', 'orgLevel4', new Links({ 'href': 'someUrl' }, { 'href': 'someUrl' }, { 'href': 'someUrl' }))));
|
||||
|
||||
spyOn(savingWorkbasketService, 'triggerDistributionTargetSaving');
|
||||
spyOn(savingWorkbasketService, 'triggerAccessItemsSaving');
|
||||
|
||||
component.onSave();
|
||||
expect(alertService.triggerAlert).toHaveBeenCalled();
|
||||
expect(component.workbasket.workbasketId).toBe('someNewId');
|
||||
expect(savingWorkbasketService.triggerDistributionTargetSaving).toHaveBeenCalled();
|
||||
expect(savingWorkbasketService.triggerAccessItemsSaving).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -1,11 +1,20 @@
|
|||
import { Component, OnInit, Input, Output, OnDestroy } from '@angular/core';
|
||||
import { Workbasket } from '../../../model/workbasket';
|
||||
import { WorkbasketService } from '../../../services/workbasket.service';
|
||||
import { IconTypeComponent, ICONTYPES } from '../../../shared/type-icon/icon-type.component';
|
||||
import { IconTypeComponent } from '../../../shared/type-icon/icon-type.component';
|
||||
import { Subscription } from 'rxjs/Subscription';
|
||||
import { AlertService, AlertModel, AlertType } from '../../../services/alert.service';
|
||||
import { ActivatedRoute, Params, Router, NavigationStart } from '@angular/router';
|
||||
import { ICONTYPES } from '../../../model/type';
|
||||
import { ErrorModalService } from '../../../services/error-modal.service';
|
||||
import { ErrorModel } from '../../../model/modal-error';
|
||||
import { DatePipe } from '@angular/common';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
import { ACTION } from '../../../model/action';
|
||||
import { SavingWorkbasketService, SavingInformation } from '../../../services/saving-workbaskets/saving-workbaskets.service';
|
||||
|
||||
const dateFormat = 'yyyy-MM-ddTHH:mm:ss';
|
||||
const dateLocale = 'en-US';
|
||||
@Component({
|
||||
selector: 'taskana-workbasket-information',
|
||||
templateUrl: './workbasket-information.component.html',
|
||||
|
@ -16,12 +25,15 @@ export class WorkbasketInformationComponent implements OnInit, OnDestroy {
|
|||
@Input()
|
||||
workbasket: Workbasket;
|
||||
workbasketClone: Workbasket;
|
||||
@Input()
|
||||
action: string;
|
||||
|
||||
allTypes: Map<string, string>;
|
||||
requestInProgress = false;
|
||||
modalSpinner = false;
|
||||
modalErrorMessage: string;
|
||||
modalTitle = 'There was error while saving your workbasket';
|
||||
hasChanges = false;
|
||||
badgeMessage = '';
|
||||
|
||||
|
||||
private workbasketSubscription: Subscription;
|
||||
private routeSubscription: Subscription;
|
||||
|
@ -29,17 +41,20 @@ export class WorkbasketInformationComponent implements OnInit, OnDestroy {
|
|||
constructor(private workbasketService: WorkbasketService,
|
||||
private alertService: AlertService,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router, ) {
|
||||
private router: Router,
|
||||
private errorModalService: ErrorModalService,
|
||||
private savingWorkbasket: SavingWorkbasketService) {
|
||||
this.allTypes = IconTypeComponent.allTypes;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.workbasketClone = { ...this.workbasket };
|
||||
this.routeSubscription = this.router.events.subscribe(event => {
|
||||
if (event instanceof NavigationStart) {
|
||||
this.checkForChanges();
|
||||
}
|
||||
});
|
||||
if (this.action === ACTION.CREATE) {
|
||||
this.badgeMessage = 'Creating new workbasket';
|
||||
} else if (this.action === ACTION.COPY) {
|
||||
this.badgeMessage = `Copying workbasket: ${this.workbasket.key}`;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
selectType(type: ICONTYPES) {
|
||||
|
@ -48,6 +63,11 @@ export class WorkbasketInformationComponent implements OnInit, OnDestroy {
|
|||
|
||||
onSave() {
|
||||
this.beforeRequest();
|
||||
if (!this.workbasket.workbasketId) {
|
||||
this.postNewWorkbasket();
|
||||
return true;
|
||||
}
|
||||
|
||||
this.workbasketSubscription = (this.workbasketService.updateWorkbasket(this.workbasket._links.self.href, this.workbasket).subscribe(
|
||||
workbasketUpdated => {
|
||||
this.afterRequest();
|
||||
|
@ -57,7 +77,7 @@ export class WorkbasketInformationComponent implements OnInit, OnDestroy {
|
|||
},
|
||||
error => {
|
||||
this.afterRequest();
|
||||
this.modalErrorMessage = error;
|
||||
this.errorModalService.triggerError(new ErrorModel('There was error while saving your workbasket', error))
|
||||
}
|
||||
));
|
||||
}
|
||||
|
@ -65,12 +85,12 @@ export class WorkbasketInformationComponent implements OnInit, OnDestroy {
|
|||
onClear() {
|
||||
this.alertService.triggerAlert(new AlertModel(AlertType.INFO, 'Reset edited fields'))
|
||||
this.workbasket = { ...this.workbasketClone };
|
||||
this.hasChanges = false;
|
||||
}
|
||||
|
||||
private beforeRequest() {
|
||||
this.requestInProgress = true;
|
||||
this.modalSpinner = true;
|
||||
this.modalErrorMessage = undefined;
|
||||
}
|
||||
|
||||
private afterRequest() {
|
||||
|
@ -79,13 +99,34 @@ export class WorkbasketInformationComponent implements OnInit, OnDestroy {
|
|||
|
||||
}
|
||||
|
||||
private checkForChanges() {
|
||||
if (!Workbasket.equals(this.workbasket, this.workbasketClone)) {
|
||||
this.openDiscardChangesModal();
|
||||
}
|
||||
private postNewWorkbasket() {
|
||||
this.addDateToWorkbasket();
|
||||
this.workbasketService.createWorkbasket(this.workbasket._links.self.href,
|
||||
this.workbasket)
|
||||
.subscribe((workbasketUpdated: Workbasket) => {
|
||||
this.alertService.triggerAlert(new AlertModel(AlertType.SUCCESS, `Workbasket ${workbasketUpdated.key} was created successfully`))
|
||||
this.workbasket = workbasketUpdated;
|
||||
this.afterRequest();
|
||||
this.workbasketService.triggerWorkBasketSaved();
|
||||
this.workbasketService.selectWorkBasket(this.workbasket.workbasketId);
|
||||
this.router.navigate(['../' + this.workbasket.workbasketId], { relativeTo: this.route });
|
||||
if (this.action === ACTION.COPY) {
|
||||
this.savingWorkbasket.triggerDistributionTargetSaving(
|
||||
new SavingInformation(this.workbasket._links.distributionTargets.href, this.workbasket.workbasketId));
|
||||
this.savingWorkbasket.triggerAccessItemsSaving(
|
||||
new SavingInformation(this.workbasket._links.accessItems.href, this.workbasket.workbasketId));
|
||||
}
|
||||
}, error => {
|
||||
this.errorModalService.triggerError(new ErrorModel('There was an error creating a workbasket', error.error.message))
|
||||
this.requestInProgress = false;
|
||||
});
|
||||
}
|
||||
|
||||
private openDiscardChangesModal() {
|
||||
private addDateToWorkbasket() {
|
||||
const datePipe = new DatePipe(dateLocale);
|
||||
const date = datePipe.transform(Date.now(), dateFormat) + 'Z';
|
||||
this.workbasket.created = date;
|
||||
this.workbasket.modified = date;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
<div class="container-scrollable" >
|
||||
<taskana-spinner [isRunning]="requestInProgress" class = "centered-horizontally"></taskana-spinner>
|
||||
<taskana-no-access *ngIf="!requestInProgress && (!hasPermission || !workbasket && selectedId)" ></taskana-no-access>
|
||||
<div id ="workbasket-details" *ngIf="workbasket && !requestInProgress">
|
||||
<div class="container-scrollable">
|
||||
<taskana-spinner [isRunning]="requestInProgress" class="centered-horizontally"></taskana-spinner>
|
||||
<taskana-no-access *ngIf="!requestInProgress && (!hasPermission && !workbasket || !workbasket && selectedId)"></taskana-no-access>
|
||||
<div id="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>
|
||||
<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">Information</a>
|
||||
</li>
|
||||
<li role="presentation" class="">
|
||||
<li role="presentation" [ngClass]="{'disabled': !workbasket._links?.accessItems}">
|
||||
<a href="#access-items" aria-controls="Acccess" role="tab" data-toggle="tab" aria-expanded="true">Access</a>
|
||||
</li>
|
||||
<li role="presentation" class="">
|
||||
<li role="presentation" [ngClass]="{'disabled': !workbasket._links?.distributionTargets}">
|
||||
<a href="#distribution-targets" aria-controls="distribution targets" role="tab" data-toggle="tab" aria-expanded="true">Distribution targets</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="work-baskets">
|
||||
<taskana-workbasket-information [workbasket]="workbasket"></taskana-workbasket-information>
|
||||
<div role="tabpanel" class="tab-pane fade in active" id="work-baskets">
|
||||
<taskana-workbasket-information [workbasket]="workbasket" [action]="action"></taskana-workbasket-information>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane inactive" id="access-items">
|
||||
<taskana-workbasket-access-items [workbasket]="workbasket"></taskana-workbasket-access-items>
|
||||
<div role="tabpanel" class="tab-pane fade" id="access-items">
|
||||
<taskana-workbasket-access-items [workbasket]="workbasket" [action]="action"></taskana-workbasket-access-items>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane inactive" id="distribution-targets">
|
||||
<taskana-workbaskets-distribution-targets [workbasket]="workbasket"></taskana-workbaskets-distribution-targets>
|
||||
<div role="tabpanel" class="tab-pane fade" id="distribution-targets">
|
||||
<taskana-workbaskets-distribution-targets [workbasket]="workbasket" [action]="action"></taskana-workbaskets-distribution-targets>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<taskana-alert></taskana-alert>
|
||||
</div>
|
|
@ -21,4 +21,11 @@
|
|||
& > p{
|
||||
margin: 0px;
|
||||
}
|
||||
& > li.disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
& > li.disabled > a {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import { DualListComponent } from './distribution-targets//dual-list/dual-list.c
|
|||
import { Workbasket } from 'app/model/workbasket';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { SpinnerComponent } from '../../shared/spinner/spinner.component';
|
||||
import { ICONTYPES, IconTypeComponent } from '../../shared/type-icon/icon-type.component';
|
||||
import { IconTypeComponent } from '../../shared/type-icon/icon-type.component';
|
||||
import { MapValuesPipe } from '../../pipes/map-values.pipe';
|
||||
import { RemoveNoneTypePipe } from '../../pipes/remove-none-type';
|
||||
import { SelectWorkBasketPipe } from '../../pipes/seleted-workbasket.pipe';
|
||||
|
@ -22,6 +22,8 @@ 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 { ErrorModalService } from '../../services/error-modal.service';
|
||||
import { SavingWorkbasketService } from '../../services/saving-workbaskets/saving-workbaskets.service';
|
||||
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
@ -31,101 +33,116 @@ import { HttpModule } from '@angular/http';
|
|||
import { WorkbasketSummary } from '../../model/workbasket-summary';
|
||||
import { WorkbasketSummaryResource } from '../../model/workbasket-summary-resource';
|
||||
import { WorkbasketAccessItemsResource } from '../../model/workbasket-access-items-resource';
|
||||
import { ICONTYPES } from '../../model/type';
|
||||
import { Router, Routes } from '@angular/router';
|
||||
import { ACTION } from '../../model/action';
|
||||
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-filter',
|
||||
template: ''
|
||||
selector: 'taskana-filter',
|
||||
template: ''
|
||||
})
|
||||
export class FilterComponent {
|
||||
|
||||
@Input()
|
||||
target: string;
|
||||
@Input()
|
||||
target: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-dummy-detail',
|
||||
template: 'dummydetail'
|
||||
})
|
||||
export class DummyDetailComponent {
|
||||
|
||||
}
|
||||
|
||||
|
||||
describe('WorkbasketDetailsComponent', () => {
|
||||
let component: WorkbasketDetailsComponent;
|
||||
let fixture: ComponentFixture<WorkbasketDetailsComponent>;
|
||||
let debugElement;
|
||||
let masterAndDetailService;
|
||||
let workbasketService;
|
||||
const workbasket = new Workbasket('1', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
||||
new Links({ 'href': 'someurl' }, { 'href': 'someurl' }, { 'href': 'someurl' }));
|
||||
let component: WorkbasketDetailsComponent;
|
||||
let fixture: ComponentFixture<WorkbasketDetailsComponent>;
|
||||
let debugElement;
|
||||
let masterAndDetailService;
|
||||
let workbasketService;
|
||||
let router;
|
||||
const workbasket = new Workbasket('1', '', '', '', ICONTYPES.TOPIC, '', '', '', '', '', '', '', '', '', '', '', '',
|
||||
new Links({ 'href': 'someurl' }, { 'href': 'someurl' }, { 'href': 'someurl' }));
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: ':id', component: DummyDetailComponent, outlet: 'detail' }
|
||||
];
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [RouterTestingModule, FormsModule, AngularSvgIconModule, HttpClientModule, HttpModule],
|
||||
declarations: [WorkbasketDetailsComponent, NoAccessComponent, WorkbasketInformationComponent, SpinnerComponent,
|
||||
IconTypeComponent, MapValuesPipe, RemoveNoneTypePipe, AlertComponent, GeneralMessageModalComponent, AccessItemsComponent,
|
||||
DistributionTargetsComponent, FilterComponent, DualListComponent, SelectWorkBasketPipe],
|
||||
providers: [WorkbasketService, MasterAndDetailService, PermissionService, AlertService]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [RouterTestingModule.withRoutes(routes), FormsModule, AngularSvgIconModule, HttpClientModule, HttpModule],
|
||||
declarations: [WorkbasketDetailsComponent, NoAccessComponent, WorkbasketInformationComponent, SpinnerComponent,
|
||||
IconTypeComponent, MapValuesPipe, RemoveNoneTypePipe, AlertComponent, GeneralMessageModalComponent, AccessItemsComponent,
|
||||
DistributionTargetsComponent, FilterComponent, DualListComponent, DummyDetailComponent, SelectWorkBasketPipe],
|
||||
providers: [WorkbasketService, MasterAndDetailService, PermissionService,
|
||||
AlertService, ErrorModalService, SavingWorkbasketService]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(WorkbasketDetailsComponent);
|
||||
component = fixture.componentInstance;
|
||||
debugElement = fixture.debugElement.nativeElement;
|
||||
fixture.detectChanges();
|
||||
masterAndDetailService = TestBed.get(MasterAndDetailService);
|
||||
workbasketService = TestBed.get(WorkbasketService);
|
||||
spyOn(masterAndDetailService, 'getShowDetail').and.callFake(() => { return Observable.of(true) })
|
||||
spyOn(workbasketService, 'getSelectedWorkBasket').and.callFake(() => { return Observable.of('id1') })
|
||||
spyOn(workbasketService, 'getWorkBasketsSummary').and.callFake(() => {
|
||||
return Observable.of(new WorkbasketSummaryResource(
|
||||
{
|
||||
'workbaskets': new Array<WorkbasketSummary>(
|
||||
new WorkbasketSummary('id1', '', '', '', '', '', '', '', '', '', '', '',
|
||||
new Links({ 'href': 'someurl' })))
|
||||
}, new Links({ 'href': 'someurl' })))
|
||||
})
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(WorkbasketDetailsComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.hasPermission = false;
|
||||
debugElement = fixture.debugElement.nativeElement;
|
||||
router = TestBed.get(Router)
|
||||
fixture.detectChanges();
|
||||
masterAndDetailService = TestBed.get(MasterAndDetailService);
|
||||
workbasketService = TestBed.get(WorkbasketService);
|
||||
spyOn(masterAndDetailService, 'getShowDetail').and.callFake(() => { return Observable.of(true) })
|
||||
spyOn(workbasketService, 'getSelectedWorkBasket').and.callFake(() => { return Observable.of('id1') })
|
||||
spyOn(workbasketService, 'getWorkBasketsSummary').and.callFake(() => {
|
||||
return Observable.of(new WorkbasketSummaryResource(
|
||||
{
|
||||
'workbaskets': new Array<WorkbasketSummary>(
|
||||
new WorkbasketSummary('id1', '', '', '', '', '', '', '', '', '', '', '',
|
||||
new Links({ 'href': 'someurl' })))
|
||||
}, new Links({ 'href': 'someurl' })))
|
||||
})
|
||||
|
||||
spyOn(workbasketService, 'getWorkBasket').and.callFake(() => { return Observable.of(workbasket) })
|
||||
spyOn(workbasketService, 'getWorkBasketAccessItems').and.callFake(() => {
|
||||
return Observable.of(new WorkbasketAccessItemsResource(
|
||||
{ 'accessItems': new Array<WorkbasketAccessItems>() }, new Links({ 'href': 'url' })))
|
||||
})
|
||||
spyOn(workbasketService, 'getWorkBasketsDistributionTargets').and.callFake(() => {
|
||||
return Observable.of(new WorkbasketSummaryResource(
|
||||
{ 'workbaskets': new Array<WorkbasketSummary>() }, new Links({ 'href': 'url' })))
|
||||
})
|
||||
spyOn(workbasketService, 'getWorkBasket').and.callFake(() => { return Observable.of(workbasket) })
|
||||
spyOn(workbasketService, 'getWorkBasketAccessItems').and.callFake(() => {
|
||||
return Observable.of(new WorkbasketAccessItemsResource(
|
||||
{ 'accessItems': new Array<WorkbasketAccessItems>() }, new Links({ 'href': 'url' })))
|
||||
})
|
||||
spyOn(workbasketService, 'getWorkBasketsDistributionTargets').and.callFake(() => {
|
||||
return Observable.of(new WorkbasketSummaryResource(
|
||||
{ 'workbaskets': new Array<WorkbasketSummary>() }, new Links({ 'href': 'url' })))
|
||||
})
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
document.body.removeChild(debugElement);
|
||||
});
|
||||
afterEach(() => {
|
||||
document.body.removeChild(debugElement);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
it('should be created', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should has created taskana-no-access if workbasket is not defined', () => {
|
||||
expect(component.workbasket).toBeUndefined();
|
||||
expect(debugElement.querySelector('taskana-no-access')).toBeTruthy();
|
||||
});
|
||||
it('should has created taskana-no-access if workbasket is not defined and hasPermission is false', () => {
|
||||
expect(component.workbasket).toBeUndefined();
|
||||
component.hasPermission = false;
|
||||
fixture.detectChanges();
|
||||
expect(debugElement.querySelector('taskana-no-access')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should has created taskana-workbasket-details if workbasket is defined and taskana-no-access should dissapear', () => {
|
||||
expect(component.workbasket).toBeUndefined();
|
||||
expect(debugElement.querySelector('taskana-no-access')).toBeTruthy();
|
||||
it('should has created taskana-workbasket-details if workbasket is defined and taskana-no-access should dissapear', () => {
|
||||
expect(component.workbasket).toBeUndefined();
|
||||
component.hasPermission = false;
|
||||
fixture.detectChanges();
|
||||
expect(debugElement.querySelector('taskana-no-access')).toBeTruthy();
|
||||
|
||||
component.workbasket = workbasket;
|
||||
fixture.detectChanges();
|
||||
component.workbasket = workbasket;
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(debugElement.querySelector('taskana-no-access')).toBeFalsy();
|
||||
expect(debugElement.querySelector('taskana-workbasket-information')).toBeTruthy();
|
||||
expect(debugElement.querySelector('taskana-no-access')).toBeFalsy();
|
||||
expect(debugElement.querySelector('taskana-workbasket-information')).toBeTruthy();
|
||||
|
||||
});
|
||||
|
||||
it('should show back button with classes "visible-xs visible-sm hidden" when showDetail property is true', () => {
|
||||
|
||||
component.workbasket = workbasket;
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
expect(debugElement.querySelector('.visible-xs.visible-sm.hidden > a').textContent).toBe('Back');
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -7,6 +7,10 @@ import { PermissionService } from '../../services/permission.service';
|
|||
import { Subscription } from 'rxjs/Subscription';
|
||||
import { WorkbasketSummary } from '../../model/workbasket-summary';
|
||||
import { WorkbasketSummaryResource } from '../../model/workbasket-summary-resource';
|
||||
import { ICONTYPES } from '../../model/type';
|
||||
import { ErrorModel } from '../../model/modal-error';
|
||||
import { ErrorModalService } from '../../services/error-modal.service';
|
||||
import { ACTION } from '../../model/action';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-workbasket-details',
|
||||
|
@ -17,10 +21,12 @@ export class WorkbasketDetailsComponent implements OnInit, OnDestroy {
|
|||
|
||||
|
||||
workbasket: Workbasket;
|
||||
selectedId = -1;
|
||||
workbasketCopy: Workbasket;
|
||||
selectedId: string = undefined;
|
||||
showDetail = false;
|
||||
hasPermission = true;
|
||||
requestInProgress = false;
|
||||
action: string;
|
||||
|
||||
private workbasketSelectedSubscription: Subscription;
|
||||
private workbasketSubscription: Subscription;
|
||||
|
@ -32,22 +38,37 @@ export class WorkbasketDetailsComponent implements OnInit, OnDestroy {
|
|||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private masterAndDetailService: MasterAndDetailService,
|
||||
private permissionService: PermissionService) { }
|
||||
private permissionService: PermissionService,
|
||||
private errorModalService: ErrorModalService) { }
|
||||
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
this.workbasketSelectedSubscription = this.service.getSelectedWorkBasket().subscribe(workbasketIdSelected => {
|
||||
this.workbasket = undefined;
|
||||
this.requestInProgress = true;
|
||||
this.getWorkbasketInformation(workbasketIdSelected);
|
||||
});
|
||||
|
||||
this.routeSubscription = this.route.params.subscribe(params => {
|
||||
const id = params['id'];
|
||||
let id = params['id'];
|
||||
this.action = undefined;
|
||||
if (id && id.indexOf('new-workbasket') !== -1) {
|
||||
this.action = ACTION.CREATE;
|
||||
id = undefined;
|
||||
this.getWorkbasketInformation(id);
|
||||
} else if (id && id.indexOf('copy-workbasket') !== -1) {
|
||||
if (!this.selectedId) {
|
||||
this.router.navigate(['./'], { relativeTo: this.route.parent });
|
||||
return;
|
||||
}
|
||||
this.action = ACTION.COPY;
|
||||
this.workbasketCopy = this.workbasket;
|
||||
id = undefined
|
||||
this.getWorkbasketInformation(id, this.selectedId);
|
||||
}
|
||||
|
||||
if (id && id !== '') {
|
||||
this.selectedId = id;
|
||||
this.service.selectWorkBasket(id);
|
||||
this.selectWorkbasket(id);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -69,8 +90,25 @@ export class WorkbasketDetailsComponent implements OnInit, OnDestroy {
|
|||
this.router.navigate(['./'], { relativeTo: this.route.parent });
|
||||
}
|
||||
|
||||
private getWorkbasketInformation(workbasketIdSelected: string) {
|
||||
this.service.getWorkBasketsSummary().subscribe((workbasketSummary: WorkbasketSummaryResource) => {
|
||||
private selectWorkbasket(id: string) {
|
||||
this.selectedId = id;
|
||||
this.service.selectWorkBasket(id);
|
||||
}
|
||||
|
||||
private getWorkbasketInformation(workbasketIdSelected: string, copyId: string = undefined) {
|
||||
this.requestInProgress = true;
|
||||
this.service.getWorkBasketsSummary(true).subscribe((workbasketSummary: WorkbasketSummaryResource) => {
|
||||
if (!workbasketIdSelected && this.action === ACTION.CREATE) { // CREATE
|
||||
this.workbasket = new Workbasket(undefined);
|
||||
this.workbasket._links.self = workbasketSummary._links.self;
|
||||
this.requestInProgress = false;
|
||||
} else if (!workbasketIdSelected && this.action === ACTION.COPY) { // COPY
|
||||
this.workbasket = { ...this.workbasketCopy };
|
||||
this.workbasket._links.self = workbasketSummary._links.self;
|
||||
this.workbasket.workbasketId = undefined;
|
||||
this.requestInProgress = false;
|
||||
}
|
||||
|
||||
const workbasketSummarySelected = this.getWorkbasketSummaryById(workbasketSummary._embedded.workbaskets, workbasketIdSelected);
|
||||
if (workbasketSummarySelected && workbasketSummarySelected._links) {
|
||||
this.workbasketSubscription = this.service.getWorkBasket(workbasketSummarySelected._links.self.href).subscribe(workbasket => {
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<li id="wb-action-toolbar" class="list-group-item tab-align">
|
||||
<div class="row">
|
||||
<div class="col-xs-9">
|
||||
<button type="button" (click)="addWorkbasket()" data-toggle="tooltip" title="Add" class="btn btn-default">
|
||||
<span class="glyphicon glyphicon-plus green" aria-hidden="true"></span>
|
||||
</button>
|
||||
<button type="button" data-toggle="tooltip" title="Edit" class="btn btn-default">
|
||||
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
|
||||
</button>
|
||||
<button *ngIf="workbasketIdSelected" type="button" (click)="copyWorkbasket()" data-toggle="tooltip" title="copy" class="btn btn-default">
|
||||
<span class="glyphicon glyphicon-copy" aria-hidden="true"></span>
|
||||
</button>
|
||||
<button *ngIf="workbasketIdSelected" type="button" data-toggle="tooltip" title="Remove distibution target" class="btn btn-default">
|
||||
<span class="glyphicon glyphicon-erase" aria-hidden="true"></span>
|
||||
</button>
|
||||
<button *ngIf="workbasketIdSelected" type="button" (click)="removeWorkbasket()" data-toggle="tooltip" title="Remove" class="btn btn-default remove">
|
||||
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="pull-right margin-right">
|
||||
<taskana-sort (performSorting)="sorting($event)"></taskana-sort>
|
||||
<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">
|
||||
<span class="glyphicon glyphicon-filter blue"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<taskana-filter target="wb-filter-bar" (performFilter)="filtering($event)"></taskana-filter>
|
||||
</div>
|
||||
</li>
|
|
@ -0,0 +1,12 @@
|
|||
.list-group-item {
|
||||
padding: 0px 15px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.tab-align{
|
||||
margin-bottom: 0px;
|
||||
padding: 0px;
|
||||
&>div{
|
||||
margin: 6px 0px;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { AngularSvgIconModule } from 'angular-svg-icon';
|
||||
import { HttpModule } from '@angular/http';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { Router, Routes } from '@angular/router';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { ErrorModalService } from '../../../services/error-modal.service';
|
||||
import { WorkbasketService } from '../../../services/workbasket.service';
|
||||
import { RequestInProgressService } from '../../../services/request-in-progress.service';
|
||||
import { AlertService } from '../../../services/alert.service';
|
||||
import { SortComponent, SortingModel } from '../../../shared/sort/sort.component';
|
||||
import { FilterComponent, FilterModel } from '../../../shared/filter/filter.component';
|
||||
import { IconTypeComponent } from '../../../shared/type-icon/icon-type.component';
|
||||
import { MapValuesPipe } from '../../../pipes/map-values.pipe';
|
||||
import { WorkbasketListToolbarComponent } from './workbasket-list-toolbar.component';
|
||||
import { Component } from '@angular/core';
|
||||
import { WorkbasketSummary } from '../../../model/workbasket-summary';
|
||||
import { Links } from '../../../model/links';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-dummy-detail',
|
||||
template: 'dummydetail'
|
||||
})
|
||||
export class DummyDetailComponent {
|
||||
|
||||
}
|
||||
|
||||
describe('WorkbasketListToolbarComponent', () => {
|
||||
let component: WorkbasketListToolbarComponent;
|
||||
let fixture: ComponentFixture<WorkbasketListToolbarComponent>;
|
||||
let debugElement, workbasketService, requestInProgressService, router;
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: ':id', component: DummyDetailComponent, outlet: 'detail' }
|
||||
];
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [FormsModule, ReactiveFormsModule, AngularSvgIconModule, HttpModule,
|
||||
HttpClientModule, RouterTestingModule.withRoutes(routes)],
|
||||
declarations: [WorkbasketListToolbarComponent, SortComponent,
|
||||
FilterComponent, IconTypeComponent, DummyDetailComponent, MapValuesPipe],
|
||||
providers: [ErrorModalService, WorkbasketService, RequestInProgressService, AlertService]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(WorkbasketListToolbarComponent);
|
||||
workbasketService = TestBed.get(WorkbasketService);
|
||||
requestInProgressService = TestBed.get(RequestInProgressService);
|
||||
router = TestBed.get(Router);
|
||||
spyOn(workbasketService, 'deleteWorkbasket').and.returnValue(Observable.of(''));
|
||||
spyOn(workbasketService, 'triggerWorkBasketSaved');
|
||||
spyOn(requestInProgressService, 'setRequestInProgress');
|
||||
|
||||
debugElement = fixture.debugElement.nativeElement;
|
||||
component = fixture.componentInstance;
|
||||
component.workbaskets = new Array<WorkbasketSummary>(
|
||||
new WorkbasketSummary('1', 'key1', 'NAME1', 'description 1', 'owner 1',
|
||||
undefined, undefined, undefined, undefined, undefined, undefined, undefined, new Links({ 'href': 'selfLink' })));
|
||||
component.workbasketIdSelected = '1';
|
||||
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
document.body.removeChild(debugElement);
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should navigate to new-workbasket when click on add new workbasket', () => {
|
||||
const spy = spyOn(router, 'navigate');
|
||||
component.addWorkbasket();
|
||||
expect(spy.calls.first().args[0][0].outlets.detail[0]).toBe('new-workbasket');
|
||||
});
|
||||
|
||||
|
||||
it('should navigate to copy-workbasket when click on add copy workbasket', () => {
|
||||
const spy = spyOn(router, 'navigate');
|
||||
component.copyWorkbasket();
|
||||
expect(spy.calls.first().args[0][0].outlets.detail[0]).toBe('copy-workbasket');
|
||||
});
|
||||
|
||||
|
||||
it('should call to workbasket service to remove workbasket after click on remove workbasket', () => {
|
||||
const spy = spyOn(router, 'navigate');
|
||||
component.removeWorkbasket();
|
||||
expect(requestInProgressService.setRequestInProgress).toHaveBeenCalledWith(true);
|
||||
expect(workbasketService.deleteWorkbasket).toHaveBeenCalledWith('selfLink');
|
||||
expect(requestInProgressService.setRequestInProgress).toHaveBeenCalledWith(false);
|
||||
expect(workbasketService.triggerWorkBasketSaved).toHaveBeenCalled();
|
||||
expect(spy.calls.first().args[0][0]).toBe('/workbaskets');
|
||||
});
|
||||
|
||||
it('should emit performSorting when sorting is triggered', () => {
|
||||
let sort: SortingModel;
|
||||
const compareSort = new SortingModel();
|
||||
|
||||
component.performSorting.subscribe((value) => { sort = value })
|
||||
component.sorting(compareSort);
|
||||
expect(sort).toBe(compareSort);
|
||||
|
||||
});
|
||||
|
||||
it('should emit performFilter when filter is triggered', () => {
|
||||
let filter: FilterModel;
|
||||
const compareFilter = new FilterModel();
|
||||
|
||||
component.performFilter.subscribe((value) => { filter = value })
|
||||
component.filtering(compareFilter);
|
||||
expect(filter).toBe(compareFilter);
|
||||
});
|
||||
|
||||
});
|
|
@ -0,0 +1,73 @@
|
|||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { SortingModel } from '../../../shared/sort/sort.component';
|
||||
import { FilterModel } from '../../../shared/filter/filter.component';
|
||||
import { WorkbasketService } from '../../../services/workbasket.service';
|
||||
import { Subscription } from 'rxjs/Subscription';
|
||||
import { WorkbasketSummary } from '../../../model/workbasket-summary';
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
import { ErrorModel } from '../../../model/modal-error';
|
||||
import { ErrorModalService } from '../../../services/error-modal.service';
|
||||
import { RequestInProgressService } from '../../../services/request-in-progress.service';
|
||||
import { AlertService, AlertModel, AlertType } from '../../../services/alert.service';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-workbasket-list-toolbar',
|
||||
templateUrl: './workbasket-list-toolbar.component.html',
|
||||
styleUrls: ['./workbasket-list-toolbar.component.scss']
|
||||
})
|
||||
export class WorkbasketListToolbarComponent implements OnInit {
|
||||
|
||||
|
||||
@Input() workbaskets: Array<WorkbasketSummary>;
|
||||
@Input() workbasketIdSelected: string;
|
||||
@Input() workbasketIdSelectedChanged: string;
|
||||
@Output() performSorting = new EventEmitter<SortingModel>();
|
||||
@Output() performFilter = new EventEmitter<FilterModel>();
|
||||
workbasketServiceSubscription: Subscription;
|
||||
|
||||
constructor(
|
||||
private workbasketService: WorkbasketService,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private errorModalService: ErrorModalService,
|
||||
private requestInProgressService: RequestInProgressService,
|
||||
private alertService: AlertService) { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
sorting(sort: SortingModel) {
|
||||
this.performSorting.emit(sort);
|
||||
}
|
||||
|
||||
filtering(filterBy: FilterModel) {
|
||||
this.performFilter.emit(filterBy);
|
||||
}
|
||||
|
||||
addWorkbasket() {
|
||||
this.router.navigate([{ outlets: { detail: ['new-workbasket'] } }], { relativeTo: this.route });
|
||||
}
|
||||
|
||||
removeWorkbasket() {
|
||||
this.requestInProgressService.setRequestInProgress(true);
|
||||
this.workbasketService.deleteWorkbasket(this.findWorkbasketSelectedObject()._links.self.href).subscribe(response => {
|
||||
this.requestInProgressService.setRequestInProgress(false);
|
||||
this.workbasketService.triggerWorkBasketSaved();
|
||||
this.alertService.triggerAlert(new AlertModel(AlertType.SUCCESS,
|
||||
`Workbasket ${this.workbasketIdSelected} was removed successfully`))
|
||||
this.router.navigate(['/workbaskets']);
|
||||
}, error => {
|
||||
this.requestInProgressService.setRequestInProgress(false);
|
||||
this.errorModalService.triggerError(new ErrorModel(
|
||||
`There was an error deleting workbasket ${this.workbasketIdSelected}`, error.error.message))
|
||||
});
|
||||
}
|
||||
|
||||
copyWorkbasket() {
|
||||
this.router.navigate([{ outlets: { detail: ['copy-workbasket'] } }], { relativeTo: this.route });
|
||||
}
|
||||
|
||||
private findWorkbasketSelectedObject() {
|
||||
return this.workbaskets.find(element => element.workbasketId === this.workbasketIdSelected);
|
||||
}
|
||||
}
|
|
@ -1,40 +1,8 @@
|
|||
<div class="workbasket-list-full-height">
|
||||
<ul id="wb-list-container" class="list-group footer-space">
|
||||
<li id="wb-action-toolbar" class="list-group-item tab-align">
|
||||
<div class="row">
|
||||
<div class="col-xs-9">
|
||||
<button type="button" data-toggle="tooltip" title="Add" class="btn btn-default">
|
||||
<span class="glyphicon glyphicon-plus green" aria-hidden="true"></span>
|
||||
</button>
|
||||
<button type="button" data-toggle="tooltip" title="Edit" class="btn btn-default">
|
||||
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
|
||||
</button>
|
||||
<button type="button" data-toggle="tooltip" title="copy" class="btn btn-default">
|
||||
<span class="glyphicon glyphicon-copy" aria-hidden="true"></span>
|
||||
</button>
|
||||
<button type="button" data-toggle="tooltip" title="Remove distibution target" class="btn btn-default">
|
||||
<span class="glyphicon glyphicon-erase" aria-hidden="true"></span>
|
||||
</button>
|
||||
<button type="button" data-toggle="tooltip" title="Remove" class="btn btn-default remove">
|
||||
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="pull-right margin-right">
|
||||
<taskana-sort (performSorting)="performSorting($event)"></taskana-sort>
|
||||
<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">
|
||||
<span class="glyphicon glyphicon-filter blue"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<taskana-filter target="wb-filter-bar" (performFilter)="performFilter($event)"></taskana-filter>
|
||||
</div>
|
||||
</li>
|
||||
<taskana-workbasket-list-toolbar [workbaskets]="workbaskets" (performFilter)="performFilter($event)" (performSorting)="performSorting ($event)"
|
||||
[(workbasketIdSelected)]="selectedId"></taskana-workbasket-list-toolbar>
|
||||
<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)">
|
||||
<div class="row">
|
||||
|
@ -44,8 +12,10 @@
|
|||
</dt>
|
||||
</dl>
|
||||
<dl class="col-xs-10">
|
||||
<dt>{{workbasket.name}} ({{workbasket.key}}) </dt>
|
||||
<dd>{{workbasket.description}}</dd>
|
||||
<dt>{{workbasket.name}},
|
||||
<i>{{workbasket.key}} </i>
|
||||
</dt>
|
||||
<dd>{{workbasket.description}} </dd>
|
||||
<dd>{{workbasket.owner}} </dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
|
|
@ -16,7 +16,13 @@ a > label{
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.tab-align{
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding-bottom: 12px;
|
||||
dt > i {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
li > div.row > dl {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
li > div.row > dl:first-child {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { async, ComponentFixture, TestBed, tick, fakeAsync } from '@angular/core/testing';
|
||||
import { WorkbasketListComponent } from './workbasket-list.component';
|
||||
import { WorkbasketListToolbarComponent } from './workbasket-list-toolbar/workbasket-list-toolbar.component';
|
||||
import { AngularSvgIconModule } from 'angular-svg-icon';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { WorkbasketSummary } from '../../model/workbasket-summary';
|
||||
|
@ -17,7 +18,9 @@ import { RemoveNoneTypePipe } from '../../pipes/remove-none-type';
|
|||
import { MapValuesPipe } from '../../pipes/map-values.pipe';
|
||||
import { WorkbasketSummaryResource } from '../../model/workbasket-summary-resource';
|
||||
import { Links } from '../../model/links';
|
||||
|
||||
import { ErrorModalService } from '../../services/error-modal.service';
|
||||
import { RequestInProgressService } from '../../services/request-in-progress.service';
|
||||
import { AlertService } from '../../services/alert.service';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-dummy-detail',
|
||||
|
@ -55,7 +58,7 @@ describe('WorkbasketListComponent', () => {
|
|||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [WorkbasketListComponent, DummyDetailComponent, SpinnerComponent, FilterComponent,
|
||||
declarations: [WorkbasketListComponent, DummyDetailComponent, SpinnerComponent, FilterComponent, WorkbasketListToolbarComponent,
|
||||
RemoveNoneTypePipe, IconTypeComponent, SortComponent, MapValuesPipe],
|
||||
imports: [
|
||||
AngularSvgIconModule,
|
||||
|
@ -63,7 +66,7 @@ describe('WorkbasketListComponent', () => {
|
|||
HttpClientModule,
|
||||
RouterTestingModule.withRoutes(routes)
|
||||
],
|
||||
providers: [WorkbasketService]
|
||||
providers: [WorkbasketService, ErrorModalService, RequestInProgressService, AlertService]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
|
@ -102,19 +105,19 @@ describe('WorkbasketListComponent', () => {
|
|||
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);
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li').length).toBe(2);
|
||||
});
|
||||
|
||||
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');
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li').length).toBe(2);
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li')[0].getAttribute('class')).toBe('list-group-item');
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li')[1].getAttribute('class')).toBe('list-group-item active');
|
||||
});
|
||||
|
||||
it('should have two workbasketsummary rows created with two different icons: user and users', () => {
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li')[1]
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li')[0]
|
||||
.querySelector('svg-icon').getAttribute('ng-reflect-src')).toBe('./assets/icons/user.svg');
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li')[2]
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li')[1]
|
||||
.querySelector('svg-icon').getAttribute('ng-reflect-src')).toBe('./assets/icons/users.svg');
|
||||
});
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Component, OnInit, EventEmitter, OnDestroy } from '@angular/core';
|
||||
import { Component, OnInit, EventEmitter, OnDestroy, ChangeDetectorRef } from '@angular/core';
|
||||
import { WorkbasketSummaryResource } from '../../model/workbasket-summary-resource';
|
||||
import { WorkbasketSummary } from '../../model/workbasket-summary';
|
||||
import { WorkbasketService } from '../../services/workbasket.service'
|
||||
|
@ -14,8 +14,7 @@ import { Router, ActivatedRoute } from '@angular/router';
|
|||
})
|
||||
export class WorkbasketListComponent implements OnInit, OnDestroy {
|
||||
|
||||
newWorkbasket: WorkbasketSummary;
|
||||
selectedId: string = undefined;
|
||||
selectedId = '';
|
||||
workbaskets: Array<WorkbasketSummary> = [];
|
||||
requestInProgress = false;
|
||||
|
||||
|
@ -26,7 +25,11 @@ export class WorkbasketListComponent implements OnInit, OnDestroy {
|
|||
private workbasketServiceSubscription: Subscription;
|
||||
private workbasketServiceSavedSubscription: Subscription;
|
||||
|
||||
constructor(private workbasketService: WorkbasketService, private router: Router, private route: ActivatedRoute) { }
|
||||
constructor(
|
||||
private workbasketService: WorkbasketService,
|
||||
private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
private cdRef: ChangeDetectorRef) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.requestInProgress = true;
|
||||
|
@ -37,6 +40,7 @@ export class WorkbasketListComponent implements OnInit, OnDestroy {
|
|||
|
||||
this.workbasketServiceSubscription = this.workbasketService.getSelectedWorkBasket().subscribe(workbasketIdSelected => {
|
||||
this.selectedId = workbasketIdSelected;
|
||||
this.cdRef.detectChanges();
|
||||
});
|
||||
|
||||
this.workbasketServiceSavedSubscription = this.workbasketService.workbasketSavedTriggered().subscribe(value => {
|
||||
|
@ -51,13 +55,11 @@ export class WorkbasketListComponent implements OnInit, OnDestroy {
|
|||
return
|
||||
}
|
||||
this.router.navigate([{ outlets: { detail: [this.selectedId] } }], { relativeTo: this.route });
|
||||
|
||||
}
|
||||
|
||||
performSorting(sort: SortingModel) {
|
||||
this.sort = sort;
|
||||
this.performRequest();
|
||||
|
||||
}
|
||||
|
||||
performFilter(filterBy: FilterModel) {
|
||||
|
@ -65,17 +67,6 @@ export class WorkbasketListComponent implements OnInit, OnDestroy {
|
|||
this.performRequest();
|
||||
}
|
||||
|
||||
onDelete(workbasket: WorkbasketSummary) {
|
||||
|
||||
}
|
||||
|
||||
onAdd() {
|
||||
|
||||
}
|
||||
|
||||
onClear() {
|
||||
}
|
||||
|
||||
private performRequest(): void {
|
||||
this.requestInProgress = true;
|
||||
this.workbaskets = [];
|
||||
|
|
|
@ -34,8 +34,7 @@
|
|||
.container-scrollable {
|
||||
max-height: calc(100vh - 55px);
|
||||
height: calc(100vh - 55px);
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.vertical-center {
|
||||
|
@ -99,6 +98,12 @@
|
|||
}
|
||||
|
||||
|
||||
.panel-default > .panel-heading .badge.warning {
|
||||
background-color: #f0ad4e;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*Remove bootstrap cols padding for master and detail component
|
||||
*/
|
||||
|
@ -131,10 +136,6 @@
|
|||
border-bottom: none;
|
||||
}
|
||||
|
||||
li > div.row > dl {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.selected {
|
||||
z-index: 2;
|
||||
background-color: #f5f5f5;
|
||||
|
|
Loading…
Reference in New Issue