TSK-1448: Expand workbasket path with selected tab (#1333)

This commit is contained in:
Sofie Hofmann 2020-11-16 12:59:58 +01:00 committed by GitHub
parent ea38c7ddba
commit b8156d75ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 76 additions and 52 deletions

View File

@ -51,9 +51,6 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
@Input()
action: ACTION;
@Input()
active: string;
@ViewChildren('htmlInputElement')
inputs: QueryList<ElementRef>;
@ -142,14 +139,6 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
}
ngOnChanges(changes?: SimpleChanges) {
if (!this.initialized && changes.active && changes.active.currentValue === 'accessItems') {
this.init();
}
if (this.initialized && typeof changes.workbasket !== 'undefined') {
if (changes.workbasket.currentValue.workbasketId !== changes.workbasket.previousValue.workbasketId) {
this.init();
}
}
if (changes.action) {
this.setBadge();
}

View File

@ -37,15 +37,15 @@
</button>
</mat-menu>
</mat-toolbar>
<mat-tab-group animationDuration="0ms" (selectedIndexChange)="selectComponent($event)">
<mat-tab-group animationDuration="0ms" (selectedIndexChange)="selectComponent($event)" [selectedIndex]="selectedTab$ | async">
<mat-tab label="Information">
<taskana-administration-workbasket-information [workbasket]="workbasket" [action]="action"></taskana-administration-workbasket-information>
</mat-tab>
<mat-tab label="Access">
<taskana-administration-workbasket-access-items [workbasket]="workbasket" [action]="action" [active]="tabSelected"></taskana-administration-workbasket-access-items>
<taskana-administration-workbasket-access-items [workbasket]="workbasket" [action]="action"></taskana-administration-workbasket-access-items>
</mat-tab>
<mat-tab label="Distribution Targets">
<taskana-administration-workbasket-distribution-targets [workbasket]="workbasket" [action]="action" [active]="tabSelected"></taskana-administration-workbasket-distribution-targets>
<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>

View File

@ -15,11 +15,7 @@ import { RequestInProgressService } from '../../../shared/services/request-in-pr
import { SelectedRouteService } from '../../../shared/services/selected-route/selected-route';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatDialogModule } from '@angular/material/dialog';
import {
engineConfigurationMock,
selectedWorkbasketMock,
workbasketReadStateMock
} from '../../../shared/store/mock-data/mock-store';
import { selectedWorkbasketMock, workbasketReadStateMock } from '../../../shared/store/mock-data/mock-store';
import { StartupService } from '../../../shared/services/startup/startup.service';
import { TaskanaEngineService } from '../../../shared/services/taskana-engine/taskana-engine.service';
import { WindowRefService } from '../../../shared/services/window/window.service';
@ -29,6 +25,8 @@ import { MatTabsModule } from '@angular/material/tabs';
import { MatMenuModule } from '@angular/material/menu';
import { MatToolbarModule } from '@angular/material/toolbar';
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 {
@ -140,7 +138,6 @@ describe('WorkbasketDetailsComponent', () => {
workbasket: workbasketCreateState
});
fixture.detectChanges();
expect(component.tabSelected).toMatch('information');
expect(component.selectedId).toBeUndefined();
});
@ -165,9 +162,13 @@ describe('WorkbasketDetailsComponent', () => {
expect(component.workbasket).toEqual(selectedWorkbasketMock);
});
it('should select information tab when action is CREATE', () => {
component.action = ACTION.CREATE;
component.selectTab('workbasket');
expect(component.tabSelected).toEqual('information');
it('should select information tab when action is CREATE', (done) => {
component.selectComponent(1);
store.dispatch(new CreateWorkbasket());
fixture.detectChanges();
component.selectedTab$.pipe(take(1)).subscribe((tab) => {
expect(tab).toEqual(0);
done();
});
});
});

View File

@ -9,6 +9,7 @@ import { Select, Store } from '@ngxs/store';
import { takeUntil } from 'rxjs/operators';
import { WorkbasketAndAction, WorkbasketSelectors } from '../../../shared/store/workbasket-store/workbasket.selectors';
import { TaskanaDate } from '../../../shared/util/taskana.date';
import { Location } from '@angular/common';
import { ICONTYPES } from '../../../shared/models/icon-types';
import {
DeselectWorkbasket,
@ -16,6 +17,7 @@ import {
SelectComponent
} from '../../../shared/store/workbasket-store/workbasket.actions';
import { ButtonAction } from '../../models/button-action';
import { WorkbasketComponent } from '../../models/workbasket-component';
@Component({
selector: 'taskana-administration-workbasket-details',
@ -28,12 +30,14 @@ export class WorkbasketDetailsComponent implements OnInit, OnDestroy, OnChanges
selectedId: string;
requestInProgress = false;
action: ACTION;
tabSelected = 'information';
badgeMessage = '';
@Select(WorkbasketSelectors.selectedWorkbasket)
selectedWorkbasket$: Observable<Workbasket>;
@Select(WorkbasketSelectors.selectedComponent)
selectedTab$: Observable<number>;
@Select(WorkbasketSelectors.workbasketActiveAction)
activeAction$: Observable<ACTION>;
@ -43,6 +47,7 @@ export class WorkbasketDetailsComponent implements OnInit, OnDestroy, OnChanges
destroy$ = new Subject<void>();
constructor(
private location: Location,
private route: ActivatedRoute,
private router: Router,
private domainService: DomainService,
@ -54,7 +59,6 @@ export class WorkbasketDetailsComponent implements OnInit, OnDestroy, OnChanges
this.selectedWorkbasketAndAction$.pipe(takeUntil(this.destroy$)).subscribe((selectedWorkbasketAndAction) => {
this.action = selectedWorkbasketAndAction.action;
if (this.action === ACTION.CREATE) {
this.tabSelected = 'information';
this.selectedId = undefined;
this.badgeMessage = 'Creating new workbasket';
this.initWorkbasket();
@ -99,10 +103,6 @@ export class WorkbasketDetailsComponent implements OnInit, OnDestroy, OnChanges
this.router.navigate(['./'], { relativeTo: this.route.parent });
}
selectTab(tab) {
this.tabSelected = this.action === ACTION.CREATE ? 'information' : tab;
}
getWorkbasketInformation(selectedWorkbasket?: Workbasket) {
let workbasketIdSelected: string;
if (selectedWorkbasket) {
@ -145,19 +145,6 @@ export class WorkbasketDetailsComponent implements OnInit, OnDestroy, OnChanges
selectComponent(index) {
this.store.dispatch(new SelectComponent(index));
switch (index) {
case 0:
this.selectTab('information');
break;
case 1:
this.selectTab('access-items');
break;
case 2:
this.selectTab('distribution-targets');
break;
default:
break;
}
}
onSubmit() {

View File

@ -42,9 +42,6 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnChanges
@Input()
action: ACTION;
@Input()
active: string;
badgeMessage = '';
distributionTargetsSelectedResource: WorkbasketDistributionTargets;
@ -95,9 +92,6 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnChanges
}
ngOnChanges(changes: SimpleChanges) {
if (!this.initialized && changes.active && changes.active.currentValue === 'distributionTargets') {
this.init();
}
if (changes.action) {
this.setBadge();
}

View File

@ -74,7 +74,6 @@ export class WorkbasketInformationComponent implements OnInit, OnChanges, OnDest
) {}
ngOnInit() {
this.store.dispatch(new SelectComponent(WorkbasketComponent.INFORMATION));
this.allTypes = new Map([
['PERSONAL', 'Personal'],
['GROUP', 'Group'],

View File

@ -16,6 +16,7 @@ import { TaskanaType } from '../../../shared/models/taskana-type';
import { MatIconModule } from '@angular/material/icon';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatDialogModule } from '@angular/material/dialog';
import { RouterTestingModule } from '@angular/router/testing';
const getDomainFn = jest.fn().mockReturnValue(true);
const domainServiceMock = jest.fn().mockImplementation(
@ -53,6 +54,7 @@ describe('WorkbasketListToolbarComponent', () => {
TestBed.configureTestingModule({
imports: [
HttpClientTestingModule,
RouterTestingModule,
NgxsModule.forRoot([WorkbasketState]),
BrowserAnimationsModule,
MatIconModule,

View File

@ -22,6 +22,7 @@ import { MatSelectModule } from '@angular/material/select';
import { FormsModule } from '@angular/forms';
import { MatListModule, MatSelectionList } from '@angular/material/list';
import { DomainService } from '../../../shared/services/domain/domain.service';
import { RouterTestingModule } from '@angular/router/testing';
const workbasketSavedTriggeredFn = jest.fn().mockReturnValue(of(1));
const workbasketSummaryFn = jest.fn().mockReturnValue(of({}));
@ -99,6 +100,7 @@ describe('WorkbasketListComponent', () => {
TestBed.configureTestingModule({
imports: [
NgxsModule.forRoot([WorkbasketState]),
RouterTestingModule,
MatSnackBarModule,
MatDialogModule,
FormsModule,

View File

@ -31,6 +31,7 @@ import { WorkbasketDistributionTargets } from '../../models/workbasket-distribut
import { WorkbasketSummary } from '../../models/workbasket-summary';
import { WorkbasketComponent } from '../../../administration/models/workbasket-component';
import { ButtonAction } from '../../../administration/models/button-action';
import { ActivatedRoute } from '@angular/router';
class InitializeStore {
static readonly type = '[Workbasket] Initializing state';
@ -41,9 +42,36 @@ export class WorkbasketState implements NgxsAfterBootstrap {
constructor(
private workbasketService: WorkbasketService,
private location: Location,
private notificationService: NotificationService
private notificationService: NotificationService,
private route: ActivatedRoute
) {}
@Action(InitializeStore)
initializeStore(ctx: StateContext<WorkbasketStateModel>): Observable<any> {
// read the selected tab from the route
this.route.queryParams.pipe(take(2)).subscribe((params) => {
let tabName: string = params.tab;
let tab: number;
switch (tabName) {
case 'information':
tab = WorkbasketComponent.INFORMATION;
break;
case 'access-items':
tab = WorkbasketComponent.ACCESS_ITEMS;
break;
case 'distribution-targets':
tab = WorkbasketComponent.DISTRIBUTION_TARGETS;
break;
default:
tab = WorkbasketComponent.INFORMATION;
}
ctx.dispatch(new SelectComponent(tab));
});
return of();
}
@Action(GetWorkbasketsSummary)
getWorkbasketsSummary(ctx: StateContext<WorkbasketStateModel>, action: GetWorkbasketsSummary): Observable<any> {
ctx.patchState({
@ -75,7 +103,25 @@ export class WorkbasketState implements NgxsAfterBootstrap {
@Action(SelectWorkbasket)
selectWorkbasket(ctx: StateContext<WorkbasketStateModel>, action: SelectWorkbasket): Observable<any> {
this.location.go(this.location.path().replace(/(workbaskets).*/g, `workbaskets/(detail:${action.workbasketId})`));
let selectedComponent;
switch (ctx.getState().selectedComponent) {
case WorkbasketComponent.INFORMATION:
selectedComponent = 'information';
break;
case WorkbasketComponent.ACCESS_ITEMS:
selectedComponent = 'access-items';
break;
case WorkbasketComponent.DISTRIBUTION_TARGETS:
selectedComponent = 'distribution-targets';
break;
}
this.location.go(
this.location
.path()
.replace(/(workbaskets).*/g, `workbaskets/(detail:${action.workbasketId})?tab=${selectedComponent}`)
);
const id = action.workbasketId;
if (typeof id !== 'undefined') {
return this.workbasketService.getWorkBasket(id).pipe(
@ -106,6 +152,7 @@ export class WorkbasketState implements NgxsAfterBootstrap {
this.location.go(this.location.path().replace(/(workbaskets).*/g, 'workbaskets/(detail:new-workbasket)'));
ctx.patchState({
selectedWorkbasket: undefined,
selectedComponent: WorkbasketComponent.INFORMATION,
action: ACTION.CREATE
});
return of(null);
@ -122,12 +169,15 @@ export class WorkbasketState implements NgxsAfterBootstrap {
switch (action.component) {
case WorkbasketComponent.INFORMATION:
ctx.patchState({ selectedComponent: WorkbasketComponent.INFORMATION });
this.location.go(this.location.path().replace(/(tab).*/g, 'tab=information'));
break;
case WorkbasketComponent.ACCESS_ITEMS:
ctx.patchState({ selectedComponent: WorkbasketComponent.ACCESS_ITEMS });
this.location.go(this.location.path().replace(/(tab).*/g, 'tab=access-items'));
break;
case WorkbasketComponent.DISTRIBUTION_TARGETS:
ctx.patchState({ selectedComponent: WorkbasketComponent.DISTRIBUTION_TARGETS });
this.location.go(this.location.path().replace(/(tab).*/g, 'tab=distribution-targets'));
break;
}
return of(null);