TSK-1316: Replaced local progress bars by global one

TSK-1316: Replaced local progress bars by global one in workplace
TSK-1316: Rework of progress-bar component


TSK-1316: Renamed progress-bar component


TSK-1316: Changed progress-bar mode
TSK-1316: Updated tests
This commit is contained in:
Sofie Hofmann 2020-11-23 11:56:14 +01:00
parent 4ffeacdfe8
commit 4dd426e060
36 changed files with 241 additions and 241 deletions

View File

@ -60,11 +60,6 @@ describe('AccessItemsManagementComponent', () => {
let store: Store;
let actions$: Observable<any>;
@Component({ selector: 'taskana-shared-spinner', template: '' })
class TaskanaSharedSpinnerStub {
@Input() isRunning: boolean;
}
@Component({ selector: 'taskana-shared-sort', template: '' })
class TaskanaSharedSortStub {
@Input() sortingFields: Map<string, string>;
@ -95,12 +90,7 @@ describe('AccessItemsManagementComponent', () => {
MatListModule,
MatExpansionModule
],
declarations: [
AccessItemsManagementComponent,
TypeAheadComponent,
TaskanaSharedSortStub,
TaskanaSharedSpinnerStub
],
declarations: [AccessItemsManagementComponent, TypeAheadComponent, TaskanaSharedSortStub],
providers: [
{ provide: FormsValidatorService, useClass: formValidatorServiceSpy },
{ provide: NotificationService, useClass: notificationServiceSpy },

View File

@ -1,7 +1,6 @@
<div class="classification-details">
<mat-progress-bar mode="query" *ngIf="requestInProgress"></mat-progress-bar>
<div class="classification-details__wrapper" id="classification-details" *ngIf="classification && !spinnerIsRunning">
<div class="classification-details__wrapper" id="classification-details" *ngIf="classification && !requestInProgress">
<!-- TITLE + ACTION BUTTONS -->
<section class="classification-details__action-toolbar">

View File

@ -32,11 +32,6 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { By } from '@angular/platform-browser';
import { MatProgressBarModule } from '@angular/material/progress-bar';
@Component({ selector: 'taskana-shared-spinner', template: '' })
class SpinnerStub {
@Input() isRunning;
}
@Component({ selector: 'taskana-shared-field-error-display', template: '' })
class FieldErrorDisplayStub {
@Input() displayError;
@ -87,7 +82,8 @@ const importExportServiceSpy = jest.fn().mockImplementation(
const requestInProgressServiceSpy = jest.fn().mockImplementation(
(): Partial<RequestInProgressService> => ({
setRequestInProgress: jest.fn().mockReturnValue(of())
setRequestInProgress: jest.fn().mockReturnValue(of()),
getRequestInProgress: jest.fn().mockReturnValue(of(false))
})
);
@ -133,14 +129,7 @@ describe('ClassificationDetailsComponent', () => {
MatMenuModule,
BrowserAnimationsModule
],
declarations: [
ClassificationDetailsComponent,
SpinnerStub,
InputStub,
FieldErrorDisplayStub,
SvgIconStub,
TextareaStub
],
declarations: [ClassificationDetailsComponent, InputStub, FieldErrorDisplayStub, SvgIconStub, TextareaStub],
providers: [
{ provide: ClassificationsService, useClass: classificationServiceSpy },
{ provide: ClassificationCategoriesService, useClass: classificationCategoriesServiceSpy },
@ -254,7 +243,7 @@ describe('ClassificationDetailsComponent', () => {
/* HTML */
it('should not show details when spinner is running', () => {
component.spinnerIsRunning = true;
component.requestInProgress = true;
component.classification = {};
fixture.detectChanges();
expect(debugElement.nativeElement.querySelector('.classification-details__action-toolbar')).toBeFalsy();
@ -262,7 +251,7 @@ describe('ClassificationDetailsComponent', () => {
});
it('should not show details when classification does not exist', () => {
component.spinnerIsRunning = false;
component.requestInProgress = false;
component.classification = null;
fixture.detectChanges();
expect(debugElement.nativeElement.querySelector('.classification-details__action-toolbar')).toBeFalsy();

View File

@ -20,7 +20,6 @@ import { NotificationService } from '../../../shared/services/notifications/noti
import { ClassificationCategoryImages, CustomField, getCustomFields } from '../../../shared/models/customisation';
import { Classification } from '../../../shared/models/classification';
import { customFieldCount } from '../../../shared/models/classification-summary';
import { CategoriesResponse } from '../../../shared/services/classification-categories/classification-categories.service';
import {
SaveCreatedClassification,
@ -40,19 +39,18 @@ import {
})
export class ClassificationDetailsComponent implements OnInit, OnDestroy {
classification: Classification;
requestInProgress = false;
@Select(ClassificationSelectors.selectCategories) categories$: Observable<string[]>;
@Select(EngineConfigurationSelectors.selectCategoryIcons) categoryIcons$: Observable<ClassificationCategoryImages>;
@Select(ClassificationSelectors.selectedClassificationType) selectedClassificationType$: Observable<string>;
@Select(ClassificationSelectors.selectedClassification) selectedClassification$: Observable<Classification>;
@Select(ClassificationSelectors.getBadgeMessage) badgeMessage$: Observable<string>;
spinnerIsRunning = false;
customFields$: Observable<CustomField[]>;
isCreatingNewClassification: boolean = false;
readonly lengthError = 'You have reached the maximum length for this field';
inputOverflowMap = new Map<string, boolean>();
validateInputOverflow: Function;
requestInProgress: boolean;
@ViewChild('ClassificationForm') classificationForm: NgForm;
toggleValidationMap = new Map<string, boolean>();
@ -86,6 +84,13 @@ export class ClassificationDetailsComponent implements OnInit, OnDestroy {
this.store.dispatch(new SelectClassification(this.classification.classificationId));
});
this.requestInProgressService
.getRequestInProgress()
.pipe(takeUntil(this.destroy$))
.subscribe((value) => {
this.requestInProgress = value;
});
this.formsValidatorService.inputOverflowObservable.pipe(takeUntil(this.destroy$)).subscribe((inputOverflowMap) => {
this.inputOverflowMap = inputOverflowMap;
});
@ -141,10 +146,6 @@ export class ClassificationDetailsComponent implements OnInit, OnDestroy {
);
}
spinnerRunning(value) {
this.spinnerIsRunning = value;
}
validChanged(): void {
this.classification.isValidInDomain = !this.classification.isValidInDomain;
}

View File

@ -61,11 +61,9 @@
<!-- CLASSIFICATION TREE -->
<mat-progress-bar mode="query" *ngIf="requestInProgress"></mat-progress-bar>
<taskana-administration-tree *ngIf="(classifications && classifications.length) else empty_classifications"
[filterText]="inputValue" [filterIcon]="selectedCategory"
(switchTaskanaSpinnerEmit)="requestInProgress=$event"></taskana-administration-tree>
(switchTaskanaSpinnerEmit)="setRequestInProgress($event)"></taskana-administration-tree>
<ng-template #empty_classifications>
<div *ngIf="!requestInProgress" class="classification-list__no-items">
<h3 class="grey">There are no classifications</h3>

View File

@ -19,6 +19,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatInputModule } from '@angular/material/input';
import { By } from '@angular/platform-browser';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { RequestInProgressService } from '../../../shared/services/request-in-progress/request-in-progress.service';
@Component({ selector: 'taskana-administration-import-export', template: '' })
class ImportExportStub {
@ -29,11 +30,6 @@ class ImportExportStub {
@Component({ selector: 'taskana-administration-classification-types-selector', template: '' })
class ClassificationTypesSelectorStub {}
@Component({ selector: 'taskana-shared-spinner', template: '' })
class SpinnerStub {
@Input() isRunning;
}
@Component({ selector: 'taskana-administration-tree', template: '' })
class TreeStub {
@Input() filterText;
@ -75,6 +71,13 @@ const importExportServiceSpy = jest.fn().mockImplementation(
})
);
const requestInProgressServiceSpy = jest.fn().mockImplementation(
(): Partial<RequestInProgressService> => ({
setRequestInProgress: jest.fn().mockReturnValue(of()),
getRequestInProgress: jest.fn().mockReturnValue(of(false))
})
);
describe('ClassificationListComponent', () => {
let fixture: ComponentFixture<ClassificationListComponent>;
let debugElement: DebugElement;
@ -96,7 +99,6 @@ describe('ClassificationListComponent', () => {
declarations: [
ClassificationListComponent,
ClassificationTypesSelectorStub,
SpinnerStub,
TreeStub,
SvgIconStub,
ImportExportStub,
@ -106,7 +108,8 @@ describe('ClassificationListComponent', () => {
{ provide: ClassificationsService, useClass: classificationServiceSpy },
{ provide: ClassificationCategoriesService, useClass: classificationCategoriesServiceSpy },
{ provide: DomainService, useClass: domainServiceSpy },
{ provide: ImportExportService, useClass: importExportServiceSpy }
{ provide: ImportExportService, useClass: importExportServiceSpy },
{ provide: RequestInProgressService, useClass: requestInProgressServiceSpy }
]
}).compileComponents();

View File

@ -18,6 +18,7 @@ import {
} from '../../../shared/store/classification-store/classification.actions';
import { DomainService } from '../../../shared/services/domain/domain.service';
import { ClassificationSummary } from '../../../shared/models/classification-summary';
import { RequestInProgressService } from '../../../shared/services/request-in-progress/request-in-progress.service';
@Component({
selector: 'taskana-administration-classification-list',
@ -43,15 +44,16 @@ export class ClassificationListComponent implements OnInit, OnDestroy {
constructor(
private location: Location,
private importExportService: ImportExportService,
private domainService: DomainService,
private requestInProgressService: RequestInProgressService,
private store: Store,
private ngxsActions$: Actions,
private domainService: DomainService
private ngxsActions$: Actions
) {
this.ngxsActions$.pipe(ofActionDispatched(GetClassifications), takeUntil(this.destroy$)).subscribe(() => {
this.requestInProgress = true;
this.requestInProgressService.setRequestInProgress(true);
});
this.ngxsActions$.pipe(ofActionCompleted(GetClassifications), takeUntil(this.destroy$)).subscribe(() => {
this.requestInProgress = false;
this.requestInProgressService.setRequestInProgress(false);
});
}
@ -79,6 +81,13 @@ export class ClassificationListComponent implements OnInit, OnDestroy {
.subscribe((domain) => {
this.store.dispatch(GetClassifications);
});
this.requestInProgressService
.getRequestInProgress()
.pipe(takeUntil(this.destroy$))
.subscribe((value) => {
this.requestInProgress = value;
});
}
addClassification() {
@ -107,6 +116,10 @@ export class ClassificationListComponent implements OnInit, OnDestroy {
this.showFilter = !this.showFilter;
}
setRequestInProgress(value: boolean) {
this.requestInProgressService.setRequestInProgress(value);
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();

View File

@ -1,4 +1,3 @@
<mat-progress-bar mode="query" *ngIf="requestInProgress"></mat-progress-bar>
<div *ngIf="workbasket" id="wb-information">
<!-- ACCESS ITEMS -->

View File

@ -1,6 +1,6 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { WorkbasketAccessItemsComponent } from './workbasket-access-items.component';
import { Component, DebugElement, Input } from '@angular/core';
import { DebugElement } from '@angular/core';
import { Actions, NgxsModule, ofActionDispatched, Store } from '@ngxs/store';
import { Observable, of } from 'rxjs';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
@ -32,19 +32,12 @@ import {
} from '../../../shared/store/workbasket-store/workbasket.actions';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ACTION } from '../../../shared/models/action';
import { WorkbasketAccessItems } from '../../../shared/models/workbasket-access-items';
import { MatSelectModule } from '@angular/material/select';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatProgressBarModule } from '@angular/material/progress-bar';
@Component({ selector: 'taskana-shared-spinner', template: '' })
class SpinnerStub {
@Input() isRunning: boolean;
@Input() positionClass: string;
}
const savingWorkbasketServiceSpy = jest.fn().mockImplementation(
(): Partial<SavingWorkbasketService> => ({
triggeredAccessItemsSaving: jest.fn().mockReturnValue(of(true))
@ -100,7 +93,7 @@ describe('WorkbasketAccessItemsComponent', () => {
MatAutocompleteModule,
MatProgressBarModule
],
declarations: [WorkbasketAccessItemsComponent, TypeAheadComponent, SpinnerStub],
declarations: [WorkbasketAccessItemsComponent, TypeAheadComponent],
providers: [
{ provide: SavingWorkbasketService, useClass: savingWorkbasketServiceSpy },
{ provide: RequestInProgressService, useClass: requestInProgressServiceSpy },

View File

@ -61,7 +61,6 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
accessItemsRepresentation: WorkbasketAccessItemsRepresentation;
accessItemsClone: Array<WorkbasketAccessItems>;
accessItemsResetClone: Array<WorkbasketAccessItems>;
requestInProgress = false;
AccessItemsForm = this.formBuilder.group({
accessItemsGroups: this.formBuilder.array([])
});
@ -148,9 +147,9 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
if (!this.workbasket._links.accessItems) {
return;
}
this.requestInProgress = true;
this.requestInProgressService.setRequestInProgress(true);
this.store.dispatch(new GetWorkbasketAccessItems(this.workbasket._links.accessItems.href)).subscribe(() => {
this.requestInProgress = false;
this.requestInProgressService.setRequestInProgress(false);
});
this.savingWorkbaskets

View File

@ -48,6 +48,5 @@
<taskana-administration-workbasket-distribution-targets [workbasket]="workbasket" [action]="action"></taskana-administration-workbasket-distribution-targets>
</mat-tab>
</mat-tab-group>
<mat-progress-bar mode="query" *ngIf="requestInProgress"></mat-progress-bar>
</div>

View File

@ -28,11 +28,6 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { CreateWorkbasket } from '../../../shared/store/workbasket-store/workbasket.actions';
import { take } from 'rxjs/operators';
@Component({ selector: 'taskana-shared-spinner', template: '' })
class SpinnerStub {
@Input() isRunning: boolean;
}
@Component({ selector: 'taskana-administration-workbasket-information', template: '<div>i</div>' })
class WorkbasketInformationStub {
@Input() workbasket: Workbasket;
@ -91,7 +86,6 @@ describe('WorkbasketDetailsComponent', () => {
],
declarations: [
WorkbasketDetailsComponent,
SpinnerStub,
WorkbasketAccessItemsStub,
WorkbasketDistributionTargetsStub,
WorkbasketInformationStub
@ -126,7 +120,6 @@ describe('WorkbasketDetailsComponent', () => {
it('should render information component when workbasket details is opened', () => {
component.workbasket = { workbasketId: '1' };
component.requestInProgress = false;
fixture.detectChanges();
const information = debugElement.nativeElement.querySelector('taskana-administration-workbasket-information');
expect(information).toBeTruthy();

View File

@ -17,6 +17,7 @@ import {
SelectComponent
} from '../../../shared/store/workbasket-store/workbasket.actions';
import { ButtonAction } from '../../models/button-action';
import { RequestInProgressService } from '../../../shared/services/request-in-progress/request-in-progress.service';
import { WorkbasketComponent } from '../../models/workbasket-component';
@Component({
@ -28,7 +29,6 @@ export class WorkbasketDetailsComponent implements OnInit, OnDestroy, OnChanges
workbasket: Workbasket;
workbasketCopy: Workbasket;
selectedId: string;
requestInProgress = false;
action: ACTION;
badgeMessage = '';
@ -52,6 +52,7 @@ export class WorkbasketDetailsComponent implements OnInit, OnDestroy, OnChanges
private router: Router,
private domainService: DomainService,
private importExportService: ImportExportService,
private requestInProgressService: RequestInProgressService,
private store: Store
) {}
@ -108,7 +109,7 @@ export class WorkbasketDetailsComponent implements OnInit, OnDestroy, OnChanges
if (selectedWorkbasket) {
workbasketIdSelected = selectedWorkbasket.workbasketId;
}
this.requestInProgress = true;
this.requestInProgressService.setRequestInProgress(true);
if (!workbasketIdSelected && this.action === ACTION.CREATE) {
// CREATE
this.workbasket = {};
@ -118,16 +119,16 @@ export class WorkbasketDetailsComponent implements OnInit, OnDestroy, OnChanges
.subscribe((domain) => {
this.workbasket.domain = domain;
});
this.requestInProgress = false;
this.requestInProgressService.setRequestInProgress(false);
} else if (!workbasketIdSelected && this.action === ACTION.COPY) {
// COPY
this.workbasket = { ...this.workbasketCopy };
delete this.workbasket.workbasketId;
this.requestInProgress = false;
this.requestInProgressService.setRequestInProgress(false);
}
if (workbasketIdSelected) {
this.workbasket = selectedWorkbasket;
this.requestInProgress = false;
this.requestInProgressService.setRequestInProgress(false);
this.checkDomainAndRedirect();
}
}

View File

@ -1,4 +1,3 @@
<mat-progress-bar mode="query" *ngIf="requestInProgress"></mat-progress-bar>
<div *ngIf="workbasket" id="wb-information">
<!--
<div class="panel-heading">

View File

@ -41,11 +41,6 @@ import { MatSelectModule } from '@angular/material/select';
import { MatInputModule } from '@angular/material/input';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
@Component({ selector: 'taskana-shared-spinner', template: '' })
class SpinnerStub {
@Input() isRunning: boolean;
}
@Component({ selector: 'taskana-shared-field-error-display', template: '' })
class FieldErrorDisplayStub {
@Input() displayError: boolean;
@ -120,7 +115,6 @@ describe('WorkbasketInformationComponent', () => {
],
declarations: [
WorkbasketInformationComponent,
SpinnerStub,
FieldErrorDisplayStub,
IconTypeStub,
TypeAheadComponent,

View File

@ -43,7 +43,6 @@ export class WorkbasketInformationComponent implements OnInit, OnChanges, OnDest
workbasketClone: Workbasket;
allTypes: Map<string, string>;
requestInProgress = false;
badgeMessage = '';
toggleValidationMap = new Map<string, boolean>();
lookupField = false;

View File

@ -4,7 +4,6 @@
<taskana-administration-workbasket-list-toolbar [workbaskets]="workbasketsSummary$ | async" (performFilter)="performFilter($event)"
(performSorting)="performSorting($event)" [workbasketDefaultSortBy]="workbasketDefaultSortBy">
</taskana-administration-workbasket-list-toolbar>
<mat-progress-bar mode="query" *ngIf="requestInProgress"></mat-progress-bar>
</section>
<!-- WORKBASKET LIST -->
@ -43,7 +42,7 @@
<!-- SPINNER and EMPTY WORKBASKET LIST -->
<ng-template #empty_workbaskets>
<div *ngIf="!requestInProgress" class="workbasket-list__no-items">
<div *ngIf="!requestInProgress && !requestInProgressLocal" class="workbasket-list__no-items">
<h3 class="grey">There are no workbaskets</h3>
</div>
</ng-template>

View File

@ -17,12 +17,12 @@ import { Filter } from '../../../shared/models/filter';
import { ICONTYPES } from '../../../shared/models/icon-types';
import { Page } from '../../../shared/models/page';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
import { FormsModule } from '@angular/forms';
import { MatListModule, MatSelectionList } from '@angular/material/list';
import { MatListModule } from '@angular/material/list';
import { DomainService } from '../../../shared/services/domain/domain.service';
import { RouterTestingModule } from '@angular/router/testing';
import { RequestInProgressService } from '../../../shared/services/request-in-progress/request-in-progress.service';
const workbasketSavedTriggeredFn = jest.fn().mockReturnValue(of(1));
const workbasketSummaryFn = jest.fn().mockReturnValue(of({}));
@ -59,6 +59,13 @@ const domainServiceSpy = jest.fn().mockImplementation(
})
);
const requestInProgressServiceSpy = jest.fn().mockImplementation(
(): Partial<RequestInProgressService> => ({
setRequestInProgress: jest.fn().mockReturnValue(of()),
getRequestInProgress: jest.fn().mockReturnValue(of(false))
})
);
@Component({ selector: 'taskana-administration-workbasket-list-toolbar', template: '' })
class WorkbasketListToolbarStub {
@Input() workbaskets: Array<WorkbasketSummary>;
@ -73,11 +80,6 @@ class IconTypeStub {
@Input() selected = false;
}
@Component({ selector: 'taskana-shared-spinner', template: '' })
class SpinnerStub {
@Input() isRunning: boolean;
}
@Component({ selector: 'taskana-shared-pagination', template: '' })
class PaginationStub {
@Input() page: Page;
@ -108,19 +110,13 @@ describe('WorkbasketListComponent', () => {
MatSelectModule,
MatListModule
],
declarations: [
WorkbasketListComponent,
WorkbasketListToolbarStub,
IconTypeStub,
SpinnerStub,
PaginationStub,
SvgIconStub
],
declarations: [WorkbasketListComponent, WorkbasketListToolbarStub, IconTypeStub, PaginationStub, SvgIconStub],
providers: [
{ provide: WorkbasketService, useClass: workbasketServiceMock },
{ provide: OrientationService, useClass: orientationServiceMock },
{ provide: ImportExportService, useClass: importExportServiceMock },
{ provide: DomainService, useClass: domainServiceSpy }
{ provide: DomainService, useClass: domainServiceSpy },
{ provide: RequestInProgressService, useClass: requestInProgressServiceSpy }
]
}).compileComponents();

View File

@ -22,6 +22,7 @@ import { WorkbasketSelectors } from '../../../shared/store/workbasket-store/work
import { Workbasket } from '../../../shared/models/workbasket';
import { MatSelectionList } from '@angular/material/list';
import { DomainService } from '../../../shared/services/domain/domain.service';
import { RequestInProgressService } from '../../../shared/services/request-in-progress/request-in-progress.service';
@Component({
selector: 'taskana-administration-workbasket-list',
@ -30,7 +31,6 @@ import { DomainService } from '../../../shared/services/domain/domain.service';
})
export class WorkbasketListComponent implements OnInit, OnDestroy {
selectedId = '';
requestInProgress = false;
pageSelected = 1;
pageSize = 9;
type = 'workbaskets';
@ -38,6 +38,8 @@ export class WorkbasketListComponent implements OnInit, OnDestroy {
workbasketDefaultSortBy: string = 'name';
sort: Sorting = new Sorting(this.workbasketDefaultSortBy);
filterBy: Filter = new Filter({ name: '', owner: '', type: '', description: '', key: '' });
requestInProgress: boolean;
requestInProgressLocal = false;
@ViewChild('wbToolbar', { static: true })
private toolbarElement: ElementRef;
@ -61,18 +63,21 @@ export class WorkbasketListComponent implements OnInit, OnDestroy {
private orientationService: OrientationService,
private importExportService: ImportExportService,
private domainService: DomainService,
private requestInProgressService: RequestInProgressService,
private ngxsActions$: Actions
) {
this.ngxsActions$.pipe(ofActionDispatched(GetWorkbasketsSummary), takeUntil(this.destroy$)).subscribe(() => {
this.requestInProgress = true;
this.requestInProgressService.setRequestInProgress(true);
this.requestInProgressLocal = true;
});
this.ngxsActions$.pipe(ofActionCompleted(GetWorkbasketsSummary), takeUntil(this.destroy$)).subscribe(() => {
this.requestInProgress = false;
this.requestInProgressService.setRequestInProgress(false);
this.requestInProgressLocal = false;
});
}
ngOnInit() {
this.requestInProgress = true;
this.requestInProgressService.setRequestInProgress(true);
this.selectedWorkbasket$.pipe(takeUntil(this.destroy$)).subscribe((selectedWorkbasket) => {
if (typeof selectedWorkbasket !== 'undefined') {
@ -117,11 +122,18 @@ export class WorkbasketListComponent implements OnInit, OnDestroy {
.getWorkbasketActionToolbarExpansion()
.pipe(takeUntil(this.destroy$))
.subscribe((value) => {
this.requestInProgress = true;
this.requestInProgressService.setRequestInProgress(true);
setTimeout(() => {
this.refreshWorkbasketList();
}, 1);
});
this.requestInProgressService
.getRequestInProgress()
.pipe(takeUntil(this.destroy$))
.subscribe((value) => {
this.requestInProgress = value;
});
}
selectWorkbasket(id: string) {
@ -176,7 +188,7 @@ export class WorkbasketListComponent implements OnInit, OnDestroy {
)
)
.subscribe(() => {
this.requestInProgress = false;
this.requestInProgressService.setRequestInProgress(false);
});
TaskanaQueryParameters.pageSize = this.cards;
}

View File

@ -21,12 +21,15 @@
</mat-sidenav>
<mat-sidenav-content>
<taskana-shared-nav-bar></taskana-shared-nav-bar>
<mat-progress-bar mode="query" *ngIf="requestInProgress"></mat-progress-bar>
<div (window:resize)="onResize()">
<div class="taskana-main">
<div class="taskana-main__progress-bar">
<mat-progress-bar [hidden]="!requestInProgress" mode="indeterminate"></mat-progress-bar>
</div>
<router-outlet></router-outlet>
<taskana-shared-progress-bar [hidden]="currentProgressValue === 0" currentValue={{currentProgressValue}}>
</taskana-shared-progress-bar>
<taskana-shared-progress-spinner
[hidden]="currentProgressValue === 0" currentValue={{currentProgressValue}}>
</taskana-shared-progress-spinner>
</div>
</div>
</mat-sidenav-content>

View File

@ -1,4 +1,5 @@
@import '../theme/variables';
@import 'src/theme/_colors.scss';
.sidenav {
position: absolute;
@ -6,7 +7,7 @@
bottom: 0;
left: 0;
right: 0;
margin-top: 0px;
margin-top: 0;
}
.sidenav__drawer {
@ -56,9 +57,11 @@
outline: none;
}
mat-sidenav-content {
height: unset;
.taskana-main__progress-bar {
height: 4px;
background-color: $light-grey;
}
::ng-deep .mat-drawer-inner-container {
overflow: visible !important;
}

View File

@ -1,6 +1,6 @@
import { Component, HostListener, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { NavigationStart, Router } from '@angular/router';
import { Subscription } from 'rxjs';
import { Subject } from 'rxjs';
import { FormsValidatorService } from 'app/shared/services/forms-validator/forms-validator.service';
import { SidenavService } from './shared/services/sidenav/sidenav.service';
import { RequestInProgressService } from './shared/services/request-in-progress/request-in-progress.service';
@ -12,6 +12,7 @@ import { TaskanaEngineService } from './shared/services/taskana-engine/taskana-e
import { WindowRefService } from 'app/shared/services/window/window.service';
import { environment } from 'environments/environment';
import { MatSidenav } from '@angular/material/sidenav';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'taskana-root',
@ -25,14 +26,12 @@ export class AppComponent implements OnInit, OnDestroy {
requestInProgress = false;
currentProgressValue = 0;
requestInProgressSubscription: Subscription;
selectedRouteSubscription: Subscription;
routerSubscription: Subscription;
uploadingFileSubscription: Subscription;
error: ErrorModel;
version: string;
toggle: boolean = false;
destroy$ = new Subject<void>();
constructor(
private router: Router,
private requestInProgressService: RequestInProgressService,
@ -53,31 +52,41 @@ export class AppComponent implements OnInit, OnDestroy {
@ViewChild('sidenav') public sidenav: MatSidenav;
ngOnInit() {
this.routerSubscription = this.router.events.subscribe((event) => {
this.router.events.pipe(takeUntil(this.destroy$)).subscribe((event) => {
if (event instanceof NavigationStart) {
this.selectedRouteService.selectRoute(event);
this.formsValidatorService.formSubmitAttempt = false;
}
});
this.requestInProgressSubscription = this.requestInProgressService
this.requestInProgressService
.getRequestInProgress()
.pipe(takeUntil(this.destroy$))
.subscribe((value: boolean) => {
this.requestInProgress = value;
});
this.selectedRouteSubscription = this.selectedRouteService.getSelectedRoute().subscribe((value: string) => {
this.selectedRouteService
.getSelectedRoute()
.pipe(takeUntil(this.destroy$))
.subscribe((value: string) => {
if (value.indexOf('classifications') !== -1) {
this.workbasketsRoute = false;
}
this.selectedRoute = value;
});
this.uploadingFileSubscription = this.uploadService.getCurrentProgressObservable().subscribe((value) => {
this.uploadService
.getCurrentProgressObservable()
.pipe(takeUntil(this.destroy$))
.subscribe((value) => {
this.currentProgressValue = value;
});
this.taskanaEngineService.getVersion().subscribe((restVersion) => {
this.taskanaEngineService
.getVersion()
.pipe(takeUntil(this.destroy$))
.subscribe((restVersion) => {
this.version = restVersion.version;
});
}
@ -97,17 +106,7 @@ export class AppComponent implements OnInit, OnDestroy {
}
ngOnDestroy() {
if (this.routerSubscription) {
this.routerSubscription.unsubscribe();
}
if (this.requestInProgressSubscription) {
this.requestInProgressSubscription.unsubscribe();
}
if (this.selectedRouteSubscription) {
this.selectedRouteSubscription.unsubscribe();
}
if (this.uploadingFileSubscription) {
this.uploadingFileSubscription.unsubscribe();
}
this.destroy$.next();
this.destroy$.complete();
}
}

View File

@ -60,6 +60,7 @@ import { MatButtonModule } from '@angular/material/button';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatSelectModule } from '@angular/material/select';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
const MODULES = [
TabsModule.forRoot(),
@ -92,7 +93,7 @@ export function startupServiceFactory(startupService: StartupService): () => Pro
@NgModule({
declarations: DECLARATIONS,
imports: [MODULES, MatSidenavModule, MatIconModule, MatToolbarModule, MatProgressBarModule],
imports: [MODULES, MatSidenavModule, MatIconModule, MatToolbarModule, MatProgressBarModule, MatProgressSpinnerModule],
providers: [
WindowRefService,
DomainService,

View File

@ -1,7 +0,0 @@
<div class="upload-file-container col-xs-12 col-md-4">
<div class="item progress-{{currentValue}}">
<div class="radial-inner-bg"><h1 class="blue"> {{currentValue}}%</h1></div>
</div>
<h4 class="blue">Uploading file</h4>
</div>
<div *ngIf="currentValue" class="mask"></div>

View File

@ -1,11 +0,0 @@
.upload-file-container {
z-index: 3000;
width: 170px;
position: absolute;
left: 50%;
top: 33%;
margin-left: -85px;
> .item {
margin-left: 10px;
}
}

View File

@ -1,24 +0,0 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ProgressBarComponent } from './progress-bar.component';
describe('ProgressBarComponent', () => {
let component: ProgressBarComponent;
let fixture: ComponentFixture<ProgressBarComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ProgressBarComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ProgressBarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,29 +0,0 @@
import { Component, OnInit, Input, SimpleChanges, OnChanges } from '@angular/core';
@Component({
selector: 'taskana-shared-progress-bar',
templateUrl: './progress-bar.component.html',
styleUrls: ['./progress-bar.component.scss']
})
export class ProgressBarComponent implements OnInit, OnChanges {
@Input()
currentValue = 0;
@Input()
min = 0;
@Input()
max = 100;
inProgress = false;
ngOnInit() {}
ngOnChanges(changes: SimpleChanges) {
if (!this.inProgress && changes.currentValue.currentValue > this.min) {
this.inProgress = true;
}
if (this.inProgress && changes.currentValue.currentValue >= this.max) {
this.inProgress = false;
}
}
}

View File

@ -0,0 +1,7 @@
<div class="progress-spinner-component">
<div class="progress-spinner-component__spinner-wrapper">
<mat-progress-spinner [value]="currentValue"></mat-progress-spinner>
</div>
<h4 class="progress-spinner-component__text">Uploading file</h4>
</div>
<div *ngIf="currentValue" class="mask"></div>

View File

@ -0,0 +1,30 @@
@import 'src/theme/_colors.scss';
.progress-spinner-component {
z-index: 3000;
width: 170px;
height: 160px;
position: absolute;
left: 50%;
top: 33%;
margin-left: -85px;
> .item {
margin-left: 10px;
}
display: flex;
flex-direction: column;
justify-content: space-between;
}
.progress-spinner-component__spinner-wrapper {
display: flex;
justify-content: center;
}
.progress-spinner-component__text {
color: $aquamarine;
text-align: center;
}
//TODO: Change color of spinner

View File

@ -0,0 +1,26 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ProgressSpinnerComponent } from './progress-spinner.component';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
describe('ProgressSpinnerComponent', () => {
let component: ProgressSpinnerComponent;
let fixture: ComponentFixture<ProgressSpinnerComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ProgressSpinnerComponent],
imports: [MatProgressSpinnerModule]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ProgressSpinnerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create component', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,11 @@
import { Component, Input } from '@angular/core';
@Component({
selector: 'taskana-shared-progress-spinner',
templateUrl: './progress-spinner.component.html',
styleUrls: ['./progress-spinner.component.scss']
})
export class ProgressSpinnerComponent {
@Input()
currentValue = 0;
}

View File

@ -29,7 +29,7 @@ import { MatRadioModule } from '@angular/material/radio';
import { SortComponent } from './components/sort/sort.component';
import { PaginationComponent } from './components/pagination/pagination.component';
import { NumberPickerComponent } from './components/number-picker/number-picker.component';
import { ProgressBarComponent } from './components/progress-bar/progress-bar.component';
import { ProgressSpinnerComponent } from './components/progress-spinner/progress-spinner.component';
import { DatePickerComponent } from './components/date-picker/date-picker.component';
import { DropdownComponent } from './components/dropdown/dropdown.component';
@ -60,6 +60,7 @@ import { MatTooltipModule } from '@angular/material/tooltip';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatSelectModule } from '@angular/material/select';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
const MODULES = [
CommonModule,
@ -97,7 +98,7 @@ const DECLARATIONS = [
FieldErrorDisplayComponent,
PaginationComponent,
NumberPickerComponent,
ProgressBarComponent,
ProgressSpinnerComponent,
DatePickerComponent,
DropdownComponent,
ToastComponent,
@ -116,7 +117,8 @@ const DECLARATIONS = [
MatTooltipModule,
MatPaginatorModule,
MatSelectModule,
ReactiveFormsModule
ReactiveFormsModule,
MatProgressSpinnerModule
],
exports: DECLARATIONS,
providers: [

View File

@ -1,4 +1,3 @@
<taskana-shared-spinner [isRunning]="requestInProgress"></taskana-shared-spinner>
<div class="panel panel-default">
<div class="panel-heading">
<div class="pull-right">

View File

@ -8,6 +8,7 @@ import { WorkbasketService } from 'app/shared/services/workbasket/workbasket.ser
import { Subscription } from 'rxjs';
import { ClassificationsService } from 'app/shared/services/classifications/classifications.service';
import { take } from 'rxjs/operators';
import { RequestInProgressService } from '../../../shared/services/request-in-progress/request-in-progress.service';
@Component({
selector: 'taskana-task',
@ -16,7 +17,6 @@ import { take } from 'rxjs/operators';
})
export class TaskComponent implements OnInit, OnDestroy {
routeSubscription: Subscription;
requestInProgress = false;
regex = /\${(.*?)}/g;
address = 'https://bing.com/';
@ -29,6 +29,7 @@ export class TaskComponent implements OnInit, OnDestroy {
private taskService: TaskService,
private workbasketService: WorkbasketService,
private classificationService: ClassificationsService,
private requestInProgressService: RequestInProgressService,
private route: ActivatedRoute,
private router: Router,
private sanitizer: DomSanitizer
@ -39,20 +40,20 @@ export class TaskComponent implements OnInit, OnDestroy {
const { id } = params;
this.getTask(id);
this.requestInProgress = true;
this.requestInProgressService.setRequestInProgress(true);
this.taskService
.claimTask(id)
.pipe(take(1))
.subscribe((task) => {
this.task = task;
this.taskService.publishUpdatedTask(task);
this.requestInProgress = false;
this.requestInProgressService.setRequestInProgress(false);
});
});
}
async getTask(id: string) {
this.requestInProgress = true;
this.requestInProgressService.setRequestInProgress(true);
this.task = await this.taskService.getTask(id).toPromise();
this.taskService.selectTask(this.task);
const classification = await this.classificationService
@ -61,13 +62,13 @@ export class TaskComponent implements OnInit, OnDestroy {
this.address = this.extractUrl(classification.applicationEntryPoint) || `${this.address}/?q=${this.task.name}`;
this.link = this.sanitizer.bypassSecurityTrustResourceUrl(this.address);
this.getWorkbaskets();
this.requestInProgress = false;
this.requestInProgressService.setRequestInProgress(false);
}
getWorkbaskets() {
this.requestInProgress = true;
this.requestInProgressService.setRequestInProgress(true);
this.workbasketService.getAllWorkBaskets().subscribe((workbaskets) => {
this.requestInProgress = false;
this.requestInProgressService.setRequestInProgress(false);
this.workbaskets = workbaskets.workbaskets;
const index = this.workbaskets.findIndex((workbasket) => workbasket.name === this.task.workbasketSummary.name);
@ -78,18 +79,18 @@ export class TaskComponent implements OnInit, OnDestroy {
}
transferTask(workbasket: Workbasket) {
this.requestInProgress = true;
this.requestInProgressService.setRequestInProgress(true);
this.taskService.transferTask(this.task.taskId, workbasket.workbasketId).subscribe((task) => {
this.requestInProgress = false;
this.requestInProgressService.setRequestInProgress(false);
this.task = task;
});
this.navigateBack();
}
completeTask() {
this.requestInProgress = true;
this.requestInProgressService.setRequestInProgress(true);
this.taskService.completeTask(this.task.taskId).subscribe((task) => {
this.requestInProgress = false;
this.requestInProgressService.setRequestInProgress(false);
this.task = task;
this.taskService.publishUpdatedTask(task);
this.navigateBack();
@ -97,14 +98,14 @@ export class TaskComponent implements OnInit, OnDestroy {
}
cancelClaimTask() {
this.requestInProgress = true;
this.requestInProgressService.setRequestInProgress(true);
this.taskService
.cancelClaimTask(this.task.taskId)
.pipe(take(1))
.subscribe((task) => {
this.task = task;
this.taskService.publishUpdatedTask(task);
this.requestInProgress = false;
this.requestInProgressService.setRequestInProgress(false);
});
this.navigateBack();
}

View File

@ -1,4 +1,3 @@
<taskana-shared-spinner [isRunning]="requestInProgress"></taskana-shared-spinner>
<div class="panel panel-default" *ngIf="task && !requestInProgress">
<!--Buttonbar-->
<div class="panel-heading">

View File

@ -1,5 +1,5 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { Subject, Subscription } from 'rxjs';
import { ActivatedRoute, Router } from '@angular/router';
import { TaskService } from 'app/workplace/services/task.service';
@ -12,6 +12,7 @@ import { WorkplaceService } from 'app/workplace/services/workplace.service';
import { MasterAndDetailService } from 'app/shared/services/master-and-detail/master-and-detail.service';
import { NOTIFICATION_TYPES } from '../../../shared/models/notifications';
import { NotificationService } from '../../../shared/services/notifications/notification.service';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'taskana-task-details',
@ -26,6 +27,7 @@ export class TaskdetailsComponent implements OnInit, OnDestroy {
currentWorkbasket: Workbasket;
currentId: string;
showDetail = false;
destroy$ = new Subject<void>();
private routeSubscription: Subscription;
private workbasketSubscription: Subscription;
@ -47,6 +49,7 @@ export class TaskdetailsComponent implements OnInit, OnDestroy {
this.workbasketSubscription = this.workplaceService.getSelectedWorkbasket().subscribe((workbasket) => {
this.currentWorkbasket = workbasket;
});
this.routeSubscription = this.route.params.subscribe((params) => {
this.currentId = params.id;
// redirect if user enters through a deep-link
@ -55,9 +58,17 @@ export class TaskdetailsComponent implements OnInit, OnDestroy {
}
this.getTask();
});
this.masterAndDetailSubscription = this.masterAndDetailService.getShowDetail().subscribe((showDetail) => {
this.showDetail = showDetail;
});
this.requestInProgressService
.getRequestInProgress()
.pipe(takeUntil(this.destroy$))
.subscribe((value) => {
this.requestInProgress = value;
});
}
resetTask(): void {
@ -69,14 +80,14 @@ export class TaskdetailsComponent implements OnInit, OnDestroy {
}
getTask(): void {
this.requestInProgress = true;
this.requestInProgressService.setRequestInProgress(true);
if (this.currentId === 'new-task') {
this.requestInProgress = false;
this.requestInProgressService.setRequestInProgress(false);
this.task = new Task('', new ObjectReference(), this.currentWorkbasket);
} else {
this.taskService.getTask(this.currentId).subscribe(
(task) => {
this.requestInProgress = false;
this.requestInProgressService.setRequestInProgress(false);
this.task = task;
this.cloneTask();
this.taskService.selectTask(task);
@ -139,6 +150,9 @@ export class TaskdetailsComponent implements OnInit, OnDestroy {
if (this.deleteTaskSubscription) {
this.deleteTaskSubscription.unsubscribe();
}
this.destroy$.next();
this.destroy$.complete();
}
private onSave() {