TSK-294 Create spinner component
This commit is contained in:
parent
a214851289
commit
11c12422be
|
@ -25,6 +25,7 @@ import { WorkbasketDistributiontargetsComponent } from './workbasket-distributio
|
|||
import { WorkbasketDetailsComponent } from './workbasket/details/workbasket-details.component';
|
||||
import { WorkbasketInformationComponent } from './workbasket/details/information/workbasket-information.component';
|
||||
import { NoAccessComponent } from './workbasket/noAccess/no-access.component';
|
||||
import { SpinnerComponent } from './shared/spinner/spinner.component';
|
||||
|
||||
//Shared
|
||||
import { MasterAndDetailComponent} from './shared/masterAndDetail/master-and-detail.component';
|
||||
|
@ -68,6 +69,7 @@ const COMPONENTS = [
|
|||
MasterAndDetailComponent,
|
||||
WorkbasketInformationComponent,
|
||||
NoAccessComponent,
|
||||
SpinnerComponent,
|
||||
MapValuesPipe
|
||||
];
|
||||
@NgModule({
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<div [hidden]="!isDelayedRunning" class="sk-circle">
|
||||
<div class="sk-circle1 sk-child"></div>
|
||||
<div class="sk-circle2 sk-child"></div>
|
||||
<div class="sk-circle3 sk-child"></div>
|
||||
<div class="sk-circle4 sk-child"></div>
|
||||
<div class="sk-circle5 sk-child"></div>
|
||||
<div class="sk-circle6 sk-child"></div>
|
||||
<div class="sk-circle7 sk-child"></div>
|
||||
<div class="sk-circle8 sk-child"></div>
|
||||
<div class="sk-circle9 sk-child"></div>
|
||||
<div class="sk-circle10 sk-child"></div>
|
||||
<div class="sk-circle11 sk-child"></div>
|
||||
<div class="sk-circle12 sk-child"></div>
|
||||
</div>
|
|
@ -0,0 +1,122 @@
|
|||
.sk-circle {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
position: relative;
|
||||
}
|
||||
.sk-circle .sk-child {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.sk-circle .sk-child:before {
|
||||
content: '';
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
width: 15%;
|
||||
height: 15%;
|
||||
background-color: #337ab7;
|
||||
border-radius: 100%;
|
||||
-webkit-animation: sk-circleBounceDelay 1.2s infinite ease-in-out both;
|
||||
animation: sk-circleBounceDelay 1.2s infinite ease-in-out both;
|
||||
}
|
||||
.sk-circle .sk-circle2 {
|
||||
-webkit-transform: rotate(30deg);
|
||||
-ms-transform: rotate(30deg);
|
||||
transform: rotate(30deg); }
|
||||
.sk-circle .sk-circle3 {
|
||||
-webkit-transform: rotate(60deg);
|
||||
-ms-transform: rotate(60deg);
|
||||
transform: rotate(60deg); }
|
||||
.sk-circle .sk-circle4 {
|
||||
-webkit-transform: rotate(90deg);
|
||||
-ms-transform: rotate(90deg);
|
||||
transform: rotate(90deg); }
|
||||
.sk-circle .sk-circle5 {
|
||||
-webkit-transform: rotate(120deg);
|
||||
-ms-transform: rotate(120deg);
|
||||
transform: rotate(120deg); }
|
||||
.sk-circle .sk-circle6 {
|
||||
-webkit-transform: rotate(150deg);
|
||||
-ms-transform: rotate(150deg);
|
||||
transform: rotate(150deg); }
|
||||
.sk-circle .sk-circle7 {
|
||||
-webkit-transform: rotate(180deg);
|
||||
-ms-transform: rotate(180deg);
|
||||
transform: rotate(180deg); }
|
||||
.sk-circle .sk-circle8 {
|
||||
-webkit-transform: rotate(210deg);
|
||||
-ms-transform: rotate(210deg);
|
||||
transform: rotate(210deg); }
|
||||
.sk-circle .sk-circle9 {
|
||||
-webkit-transform: rotate(240deg);
|
||||
-ms-transform: rotate(240deg);
|
||||
transform: rotate(240deg); }
|
||||
.sk-circle .sk-circle10 {
|
||||
-webkit-transform: rotate(270deg);
|
||||
-ms-transform: rotate(270deg);
|
||||
transform: rotate(270deg); }
|
||||
.sk-circle .sk-circle11 {
|
||||
-webkit-transform: rotate(300deg);
|
||||
-ms-transform: rotate(300deg);
|
||||
transform: rotate(300deg); }
|
||||
.sk-circle .sk-circle12 {
|
||||
-webkit-transform: rotate(330deg);
|
||||
-ms-transform: rotate(330deg);
|
||||
transform: rotate(330deg); }
|
||||
.sk-circle .sk-circle2:before {
|
||||
-webkit-animation-delay: -1.1s;
|
||||
animation-delay: -1.1s; }
|
||||
.sk-circle .sk-circle3:before {
|
||||
-webkit-animation-delay: -1s;
|
||||
animation-delay: -1s; }
|
||||
.sk-circle .sk-circle4:before {
|
||||
-webkit-animation-delay: -0.9s;
|
||||
animation-delay: -0.9s; }
|
||||
.sk-circle .sk-circle5:before {
|
||||
-webkit-animation-delay: -0.8s;
|
||||
animation-delay: -0.8s; }
|
||||
.sk-circle .sk-circle6:before {
|
||||
-webkit-animation-delay: -0.7s;
|
||||
animation-delay: -0.7s; }
|
||||
.sk-circle .sk-circle7:before {
|
||||
-webkit-animation-delay: -0.6s;
|
||||
animation-delay: -0.6s; }
|
||||
.sk-circle .sk-circle8:before {
|
||||
-webkit-animation-delay: -0.5s;
|
||||
animation-delay: -0.5s; }
|
||||
.sk-circle .sk-circle9:before {
|
||||
-webkit-animation-delay: -0.4s;
|
||||
animation-delay: -0.4s; }
|
||||
.sk-circle .sk-circle10:before {
|
||||
-webkit-animation-delay: -0.3s;
|
||||
animation-delay: -0.3s; }
|
||||
.sk-circle .sk-circle11:before {
|
||||
-webkit-animation-delay: -0.2s;
|
||||
animation-delay: -0.2s; }
|
||||
.sk-circle .sk-circle12:before {
|
||||
-webkit-animation-delay: -0.1s;
|
||||
animation-delay: -0.1s; }
|
||||
|
||||
@-webkit-keyframes sk-circleBounceDelay {
|
||||
0%, 80%, 100% {
|
||||
-webkit-transform: scale(0);
|
||||
transform: scale(0);
|
||||
} 40% {
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes sk-circleBounceDelay {
|
||||
0%, 80%, 100% {
|
||||
-webkit-transform: scale(0);
|
||||
transform: scale(0);
|
||||
} 40% {
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { SpinnerComponent } from './spinner.component';
|
||||
|
||||
describe('SpinnerComponent', () => {
|
||||
let component: SpinnerComponent;
|
||||
let fixture: ComponentFixture<SpinnerComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ SpinnerComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SpinnerComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,42 @@
|
|||
import { Component, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-spinner',
|
||||
templateUrl: './spinner.component.html',
|
||||
styleUrls: ['./spinner.component.scss']
|
||||
})
|
||||
export class SpinnerComponent {
|
||||
private currentTimeout: any;
|
||||
|
||||
isDelayedRunning: boolean = false;
|
||||
|
||||
@Input()
|
||||
delay: number = 300;
|
||||
|
||||
@Input()
|
||||
set isRunning(value: boolean) {
|
||||
if (!value) {
|
||||
this.cancelTimeout();
|
||||
this.isDelayedRunning = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.currentTimeout) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentTimeout = setTimeout(() => {
|
||||
this.isDelayedRunning = value;
|
||||
this.cancelTimeout();
|
||||
}, this.delay);
|
||||
}
|
||||
|
||||
private cancelTimeout(): void {
|
||||
clearTimeout(this.currentTimeout);
|
||||
this.currentTimeout = undefined;
|
||||
}
|
||||
|
||||
ngOnDestroy(): any {
|
||||
this.cancelTimeout();
|
||||
}
|
||||
}
|
|
@ -1,30 +1,31 @@
|
|||
<div class="container-scrollable" >
|
||||
<app-no-access *ngIf="!hasPermission" ></app-no-access>
|
||||
<div id ="workbasket-details" class="workbasket-details" *ngIf="workbasket">
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li *ngIf="showDetail" class="visible-xs visible-sm hidden">
|
||||
<a (click) = "backClicked()"><span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>Back</a>
|
||||
</li>
|
||||
<li role="presentation" class="active">
|
||||
<a href="#work-baskets" aria-controls="work baskets" role="tab" data-toggle="tab" aria-expanded="true">Work baskets information</a>
|
||||
</li>
|
||||
<li role="presentation" class="inactive">
|
||||
<a href="#authorizations" aria-controls="Authorizations" role="tab" data-toggle="tab" aria-expanded="true">Authorizations</a>
|
||||
</li>
|
||||
<li role="presentation" class="inactive">
|
||||
<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 detail-tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="work-baskets">
|
||||
<workbasket-information [workbasket]="workbasket"></workbasket-information>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane inactive" id="authorizations">
|
||||
<!-- <app-workbasket-authorization [workbasket]="workbasket"></app-workbasket-authorization> -->
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane inactive" id="distribution-targets">
|
||||
<!-- <app-workbasket-distributiontargets [workbasket]="workbasket"></app-workbasket-distributiontargets>-->
|
||||
<taskana-spinner [isRunning]="requestInProgress" class = "centered-horizontally"></taskana-spinner>
|
||||
<app-no-access *ngIf="!hasPermission" ></app-no-access>
|
||||
<div id ="workbasket-details" class="workbasket-details" *ngIf="workbasket">
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li *ngIf="showDetail" class="visible-xs visible-sm hidden">
|
||||
<a (click) = "backClicked()"><span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>Back</a>
|
||||
</li>
|
||||
<li role="presentation" class="active">
|
||||
<a href="#work-baskets" aria-controls="work baskets" role="tab" data-toggle="tab" aria-expanded="true">Work baskets information</a>
|
||||
</li>
|
||||
<li role="presentation" class="inactive">
|
||||
<a href="#authorizations" aria-controls="Authorizations" role="tab" data-toggle="tab" aria-expanded="true">Authorizations</a>
|
||||
</li>
|
||||
<li role="presentation" class="inactive">
|
||||
<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 detail-tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="work-baskets">
|
||||
<workbasket-information [workbasket]="workbasket"></workbasket-information>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane inactive" id="authorizations">
|
||||
<!-- <app-workbasket-authorization [workbasket]="workbasket"></app-workbasket-authorization> -->
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane inactive" id="distribution-targets">
|
||||
<!-- <app-workbasket-distributiontargets [workbasket]="workbasket"></app-workbasket-distributiontargets>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -4,6 +4,7 @@ import { NoAccessComponent } from '../noAccess/no-access.component';
|
|||
import { WorkbasketInformationComponent } from './information/workbasket-information.component';
|
||||
import { Workbasket } from 'app/model/workbasket';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { SpinnerComponent } from '../../shared/spinner/spinner.component';
|
||||
|
||||
import { WorkbasketService } from '../../services/workbasketservice.service';
|
||||
import { MasterAndDetailService } from '../../services/master-and-detail.service';
|
||||
|
@ -25,7 +26,7 @@ describe('WorkbasketDetailsComponent', () => {
|
|||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports:[RouterTestingModule, FormsModule, AngularSvgIconModule, HttpClientModule, HttpModule],
|
||||
declarations: [ WorkbasketDetailsComponent, NoAccessComponent, WorkbasketInformationComponent ],
|
||||
declarations: [ WorkbasketDetailsComponent, NoAccessComponent, WorkbasketInformationComponent, SpinnerComponent ],
|
||||
providers:[WorkbasketService, MasterAndDetailService, PermissionService]
|
||||
})
|
||||
.compileComponents();
|
||||
|
|
|
@ -18,12 +18,13 @@ export class WorkbasketDetailsComponent implements OnInit {
|
|||
workbasketClone: Workbasket;
|
||||
showDetail: boolean = false;
|
||||
hasPermission: boolean = true;
|
||||
requestInProgress: boolean = false;
|
||||
|
||||
workbasketSelectedSubscription: Subscription;
|
||||
workbasketSubscription: Subscription;
|
||||
routeSubscription: Subscription;
|
||||
masterAndDetailSubscription: Subscription;
|
||||
permissionSubscription: Subscription;
|
||||
private workbasketSelectedSubscription: Subscription;
|
||||
private workbasketSubscription: Subscription;
|
||||
private routeSubscription: Subscription;
|
||||
private masterAndDetailSubscription: Subscription;
|
||||
private permissionSubscription: Subscription;
|
||||
|
||||
constructor(private service: WorkbasketService,
|
||||
private route: ActivatedRoute,
|
||||
|
@ -31,12 +32,16 @@ export class WorkbasketDetailsComponent implements OnInit {
|
|||
private masterAndDetailService: MasterAndDetailService,
|
||||
private permissionService: PermissionService) { }
|
||||
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
this.workbasketSelectedSubscription = this.service.getSelectedWorkBasket().subscribe( workbasketIdSelected => {
|
||||
this.workbasket = undefined;
|
||||
this.requestInProgress = true;
|
||||
this.workbasketSubscription = this.service.getWorkBasket(workbasketIdSelected).subscribe( workbasket => {
|
||||
this.workbasket = workbasket;
|
||||
this.workbasketClone = { ...this.workbasket };
|
||||
this.requestInProgress = false;
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -52,6 +57,9 @@ export class WorkbasketDetailsComponent implements OnInit {
|
|||
|
||||
this.permissionSubscription = this.permissionService.hasPermission().subscribe( permission => {
|
||||
this.hasPermission = permission;
|
||||
if(!this.hasPermission){
|
||||
this.requestInProgress = false;
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
|
|
@ -5,16 +5,16 @@
|
|||
<div class="col-xs-9 mod-col-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>
|
||||
<button type="button" data-toggle="tooltip" title="Edit" class="btn btn-default">
|
||||
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
|
||||
</button>
|
||||
</button>
|
||||
<button type="button" data-toggle="tooltip" title="copy" class="btn btn-default">
|
||||
<span class="glyphicon glyphicon-copy" aria-hidden="true"></span>
|
||||
</button>
|
||||
</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>
|
||||
<button type="button" data-toggle="tooltip" title="Remove" class="btn btn-default remove">
|
||||
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
|
||||
</button>
|
||||
|
@ -54,6 +54,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<taskana-spinner [isRunning]="requestInProgress" class = "centered-horizontally"></taskana-spinner>
|
||||
<li type="text" id="wb-search-bar" class="list-group-seach collapse">
|
||||
<div class="row">
|
||||
<dl class="pull-left padding-left-5">
|
||||
|
@ -68,7 +69,7 @@
|
|||
<li>
|
||||
<button type="button" placeholder="multiple" data-toggle="tooltip" title="multiple" class="btn btn-default btn-users-list">
|
||||
<svg-icon class="small blue" src="./assets/icons/users.svg"></svg-icon>
|
||||
</button>
|
||||
</button>
|
||||
</li>
|
||||
</ul></dt>
|
||||
</dl>
|
||||
|
@ -90,7 +91,7 @@
|
|||
<dd>{{workbasket.owner}} </dd>
|
||||
</dl>
|
||||
</div>
|
||||
</li>
|
||||
</li>
|
||||
</ul>
|
||||
<ul id= "wb-pagination" class="pagination vertical-center">
|
||||
<li>
|
||||
|
|
|
@ -9,6 +9,7 @@ import { HttpModule } from '@angular/http';
|
|||
import { Router, Routes } from '@angular/router';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { SpinnerComponent } from '../../shared/spinner/spinner.component';
|
||||
import { MapValuesPipe } from '../../pipes/map-values.pipe';
|
||||
|
||||
@Component({
|
||||
|
@ -37,8 +38,7 @@ describe('WorkbasketListComponent', () => {
|
|||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ WorkbasketListComponent, DummyDetailComponent, MapValuesPipe],
|
||||
|
||||
declarations: [ WorkbasketListComponent, DummyDetailComponent, MapValuesPipe, SpinnerComponent],
|
||||
imports:[
|
||||
AngularSvgIconModule,
|
||||
HttpModule,
|
||||
|
|
|
@ -15,6 +15,7 @@ export class WorkbasketListComponent implements OnInit {
|
|||
newWorkbasket: WorkbasketSummary;
|
||||
selectedId: string = undefined;
|
||||
workbaskets : Array<WorkbasketSummary> = [];
|
||||
requestInProgress: boolean = false;
|
||||
|
||||
sortBy: string = 'key';
|
||||
sortDirection: Direction = Direction.ASC;
|
||||
|
@ -26,8 +27,10 @@ export class WorkbasketListComponent implements OnInit {
|
|||
constructor(private workbasketService: WorkbasketService) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.requestInProgress = true;
|
||||
this.workBasketSummarySubscription = this.workbasketService.getWorkBasketsSummary().subscribe(resultList => {
|
||||
this.workbaskets = resultList;
|
||||
this.requestInProgress = false;
|
||||
});
|
||||
|
||||
this.workbasketServiceSubscription = this.workbasketService.getSelectedWorkBasket().subscribe( workbasketIdSelected => {
|
||||
|
@ -77,8 +80,11 @@ export class WorkbasketListComponent implements OnInit {
|
|||
}
|
||||
|
||||
private performRequest(): void{
|
||||
this.requestInProgress = true;
|
||||
this.workbaskets = undefined;
|
||||
this.workbasketServiceSubscription.add(this.workbasketService.getWorkBasketsSummary(this.sortBy,this.sortDirection).subscribe(resultList => {
|
||||
this.workbaskets = resultList;
|
||||
this.requestInProgress = false;
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
|
@ -242,4 +242,8 @@ li > div.row > dl {
|
|||
-moz-transition: opacity 300ms ease, visibility 300ms ease;
|
||||
-o-transition: opacity 300ms ease, visibility 300ms ease;
|
||||
transition: opacity 300ms ease, visibility 300ms ease;
|
||||
}
|
||||
}
|
||||
|
||||
taskana-spinner.centered-horizontally > div {
|
||||
margin-top: calc(50vh - 250px);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue