TSK-1517: Fix distribution targets moving and filtering
This commit is contained in:
parent
4d279c4871
commit
abfa4e09fc
|
@ -1,7 +1,8 @@
|
|||
<div id="dual-list-Left" class="distribution-targets-list">
|
||||
<mat-toolbar>
|
||||
<span class="distribution-targets-list__header">{{header}}</span>
|
||||
<span class="distribution-targets-list__header" matTooltip="{{header}}">{{header}}</span>
|
||||
|
||||
<!-- FILTER BUTTON -->
|
||||
<button mat-flat-button class="distribution-targets-list__action-button" (click)="changeToolbarState(!toolbarState)"
|
||||
>
|
||||
<span *ngIf="!toolbarState">
|
||||
|
@ -16,29 +17,35 @@
|
|||
|
||||
<span style="flex: 1 1 auto"> </span>
|
||||
|
||||
<!-- SELECT ALL BUTTON -->
|
||||
<button mat-flat-button class="distribution-targets-list__action-button" (click)="selectAll(allSelected);">
|
||||
<mat-icon class="button-icon" *ngIf="!allSelected" matTooltip="Deselect all items">check_box</mat-icon>
|
||||
<mat-icon class="button-icon" *ngIf="allSelected" matTooltip="Select all items">check_box_outline_blank</mat-icon>
|
||||
</button>
|
||||
</mat-toolbar>
|
||||
|
||||
<!-- FILTER COMPONENT -->
|
||||
<taskana-shared-workbasket-filter *ngIf="toolbarState" (performFilter)="performAvailableFilter($event)"
|
||||
isExpanded="true" component="distribution-target"></taskana-shared-workbasket-filter>
|
||||
|
||||
<!-- WORKBASKET LIST -->
|
||||
<div class="distribution-targets-list__list" infiniteScroll [infiniteScrollDistance]="1" [infiniteScrollThrottle]="50" (scrolled)="onScroll()"
|
||||
<div class="{{toolbarState? 'distribution-targets-list__list--with-filter' : 'distribution-targets-list__list--no-filter'}}"
|
||||
infiniteScroll [infiniteScrollDistance]="1" [infiniteScrollThrottle]="50"
|
||||
[scrollWindow]="false" *ngIf="distributionTargets?.length > 0">
|
||||
<mat-selection-list #workbasket [multiple]="true">
|
||||
<mat-list-option class="workbasket-distribution-targets__workbaskets-item"
|
||||
*ngFor="let workbasket of distributionTargets | selectWorkbaskets: distributionTargetsSelected: side"
|
||||
*ngFor="let workbasket of distributionTargets"
|
||||
[selected]="workbasket.selected"
|
||||
(click)="workbasket.selected = !workbasket.selected"
|
||||
[value]="workbasket.workbasketId">
|
||||
<div class="distribution-targets-list__item-wrapper">
|
||||
|
||||
<!-- ICON -->
|
||||
<div class="distribution-targets-list__item-icon">
|
||||
<taskana-administration-icon-type [type]="workbasket.type" size="large" tooltip="true"></taskana-administration-icon-type>
|
||||
</div>
|
||||
|
||||
<!-- INFO -->
|
||||
<div class="distribution-targets-list__item-info">
|
||||
<p>
|
||||
<b>{{workbasket.name}}</b>, <i>{{workbasket.key}} </i>
|
||||
|
@ -47,6 +54,7 @@
|
|||
<p>{{workbasket.owner}} </p>
|
||||
</div>
|
||||
|
||||
<!-- MARKED FOR DELETION -->
|
||||
<div class="workbaskets-item__marked" *ngIf="workbasket.markedForDeletion">
|
||||
<span title="Marked for deletion" matTooltip="Marked for deletion"
|
||||
class="material-icons md-20 {{workbasket.workbasketId === selectedId ? 'white': 'red' }} ">error</span>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
&__list {
|
||||
&__list--no-filter {
|
||||
min-width: 100%;
|
||||
background-color: white;
|
||||
border-radius: 10px;
|
||||
|
@ -24,6 +24,18 @@
|
|||
min-height: 83px;
|
||||
}
|
||||
}
|
||||
&__list--with-filter {
|
||||
min-width: 100%;
|
||||
background-color: white;
|
||||
border-radius: 10px;
|
||||
|
||||
overflow-y: scroll;
|
||||
height: calc(100vh - 360px - 187px) !important;
|
||||
@media screen and (max-width: 991px) {
|
||||
height: calc((100vh - 315px - 187px));
|
||||
min-height: 83px;
|
||||
}
|
||||
}
|
||||
&__item-wrapper {
|
||||
display: flex;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ import { Component, DebugElement, EventEmitter, Input, Output } from '@angular/c
|
|||
import { WorkbasketDistributionTargetsListComponent } from './workbasket-distribution-targets-list.component';
|
||||
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
|
||||
import { WorkbasketType } from '../../../shared/models/workbasket-type';
|
||||
import { SelectWorkBasketPipe } from '../../../shared/pipes/select-workbaskets.pipe';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { workbasketReadStateMock } from '../../../shared/store/mock-data/mock-store';
|
||||
import { Side } from '../workbasket-distribution-targets/workbasket-distribution-targets.component';
|
||||
|
@ -11,6 +10,7 @@ import { MatIconModule } from '@angular/material/icon';
|
|||
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||
import { MatListModule } from '@angular/material/list';
|
||||
import { WorkbasketQueryFilterParameter } from '../../../shared/models/workbasket-query-filter-parameter';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
|
||||
@Component({ selector: 'taskana-shared-workbasket-filter', template: '' })
|
||||
class FilterStub {
|
||||
|
@ -35,14 +35,15 @@ describe('WorkbasketDistributionTargetsListComponent', () => {
|
|||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [MatIconModule, MatToolbarModule, MatListModule, InfiniteScrollModule, BrowserAnimationsModule],
|
||||
declarations: [
|
||||
WorkbasketDistributionTargetsListComponent,
|
||||
FilterStub,
|
||||
SpinnerStub,
|
||||
IconTypeStub,
|
||||
SelectWorkBasketPipe
|
||||
imports: [
|
||||
MatIconModule,
|
||||
MatToolbarModule,
|
||||
MatListModule,
|
||||
MatTooltipModule,
|
||||
InfiniteScrollModule,
|
||||
BrowserAnimationsModule
|
||||
],
|
||||
declarations: [WorkbasketDistributionTargetsListComponent, FilterStub, SpinnerStub, IconTypeStub],
|
||||
providers: []
|
||||
}).compileComponents();
|
||||
|
||||
|
@ -50,7 +51,6 @@ describe('WorkbasketDistributionTargetsListComponent', () => {
|
|||
debugElement = fixture.debugElement;
|
||||
component = fixture.componentInstance;
|
||||
component.distributionTargets = workbasketReadStateMock.paginatedWorkbasketsSummary.workbaskets;
|
||||
component.distributionTargetsSelected = [];
|
||||
component.side = Side.AVAILABLE;
|
||||
}));
|
||||
|
||||
|
@ -70,12 +70,6 @@ describe('WorkbasketDistributionTargetsListComponent', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('should emit side when scrolling', () => {
|
||||
const scrollingEmitSpy = jest.spyOn(component.scrolling, 'emit');
|
||||
component.onScroll();
|
||||
expect(scrollingEmitSpy).toHaveBeenCalledWith(component.side);
|
||||
});
|
||||
|
||||
it('should change toolbar state', () => {
|
||||
expect(component.toolbarState).toBe(false);
|
||||
component.changeToolbarState(true);
|
||||
|
|
|
@ -23,15 +23,10 @@ import { WorkbasketQueryFilterParameter } from '../../../shared/models/workbaske
|
|||
})
|
||||
export class WorkbasketDistributionTargetsListComponent implements OnInit, AfterContentChecked {
|
||||
@Input() distributionTargets: WorkbasketSummary[];
|
||||
@Input() distributionTargetsSelected: WorkbasketSummary[];
|
||||
@Output() performDualListFilter = new EventEmitter<Pair<Side, WorkbasketQueryFilterParameter>>();
|
||||
@Input() requestInProgress = false;
|
||||
@Input() loadingItems? = false;
|
||||
@Input() side: Side;
|
||||
@Input() header: string;
|
||||
@Output() scrolling = new EventEmitter<Side>();
|
||||
@Input() allSelected;
|
||||
@Output() allSelectedChange = new EventEmitter<boolean>();
|
||||
@Output() performDualListFilter = new EventEmitter<Pair<Side, WorkbasketQueryFilterParameter>>();
|
||||
|
||||
toolbarState = false;
|
||||
@ViewChild('workbasket') distributionTargetsList: MatSelectionList;
|
||||
|
@ -52,11 +47,6 @@ export class WorkbasketDistributionTargetsListComponent implements OnInit, After
|
|||
this.distributionTargetsList.options.map((item) => (item['selected'] = selected));
|
||||
}
|
||||
this.distributionTargets.map((item) => (item['selected'] = selected));
|
||||
this.allSelectedChange.emit(this.allSelected);
|
||||
}
|
||||
|
||||
onScroll() {
|
||||
this.scrolling.emit(this.side);
|
||||
}
|
||||
|
||||
performAvailableFilter(pair: Pair<string, WorkbasketQueryFilterParameter>) {
|
||||
|
|
|
@ -82,13 +82,10 @@
|
|||
<taskana-administration-workbasket-distribution-targets-list
|
||||
[ngClass]="sideBySide ? 'distribution-targets-list__lists--left-side' : ''"
|
||||
header="Selected distribution targets"
|
||||
[distributionTargets]="distributionTargetsLeft"
|
||||
[distributionTargetsSelected]="distributionTargetsSelected"
|
||||
[distributionTargets]="selectedDistributionTargets"
|
||||
(performDualListFilter)="performFilter($event)"
|
||||
[side]="side.SELECTED"
|
||||
(scrolling)="onScroll()"
|
||||
[loadingItems]="loadingItems"
|
||||
[(allSelected)]="selectAllLeft"
|
||||
[allSelected]="selectAllLeft"
|
||||
[hidden]="displayingDistributionTargetsPicker && !sideBySide"
|
||||
>
|
||||
|
||||
|
@ -98,11 +95,8 @@
|
|||
header="Available distribution targets"
|
||||
[distributionTargets]="availableDistributionTargets"
|
||||
[side]="side.AVAILABLE"
|
||||
[distributionTargetsSelected]="distributionTargetsSelected"
|
||||
(performDualListFilter)="performFilter($event)"
|
||||
(scrolling)="onScroll()"
|
||||
[loadingItems]="loadingItems"
|
||||
[(allSelected)]="selectAllRight"
|
||||
[allSelected]="selectAllRight"
|
||||
*ngIf="displayingDistributionTargetsPicker"
|
||||
>
|
||||
|
||||
|
|
|
@ -127,37 +127,62 @@ describe('WorkbasketDistributionTargetsComponent', () => {
|
|||
});
|
||||
|
||||
it('should get available and selected distribution targets', () => {
|
||||
component.getWorkbaskets();
|
||||
expect(component.availableDistributionTargets).toHaveLength(8); //mock-data has 8 entries
|
||||
expect(component.distributionTargetsSelected).toHaveLength(3); //mock-data has 3 entries
|
||||
});
|
||||
// mock-data has 8 entries, array should be filtered by selected distribution targets
|
||||
expect(component.availableDistributionTargets).toHaveLength(5);
|
||||
expect(component.availableDistributionTargetsUndoClone).toHaveLength(5);
|
||||
expect(component.availableDistributionTargetsFilterClone).toHaveLength(5);
|
||||
|
||||
// TODO: was ist das für ein test?
|
||||
it('should emit filter model and side when performing filter', () => {
|
||||
const performDualListFilterSpy = jest.spyOn(component, 'performFilter');
|
||||
const filterModelMock: WorkbasketQueryFilterParameter = { domain: ['DOMAIN_A'] };
|
||||
|
||||
component.performFilter({ left: Side.AVAILABLE, right: filterModelMock });
|
||||
|
||||
expect(performDualListFilterSpy).toHaveBeenCalledWith({ right: filterModelMock, left: Side.AVAILABLE });
|
||||
// mock-data has 3 entries
|
||||
expect(component.selectedDistributionTargets).toHaveLength(3);
|
||||
expect(component.selectedDistributionTargetsUndoClone).toHaveLength(3);
|
||||
expect(component.selectedDistributionTargetsFilterClone).toHaveLength(3);
|
||||
});
|
||||
|
||||
it('should move distribution targets to selected list', () => {
|
||||
component.availableDistributionTargets[0]['selected'] = true; // select first item in available array
|
||||
component.distributionTargetsLeft = component.distributionTargetsSelected;
|
||||
const removeSelectedItems = jest.spyOn(component, 'removeSelectedItems');
|
||||
component.moveDistributionTargets(Side.AVAILABLE);
|
||||
expect(component.distributionTargetsSelected).toHaveLength(4); // mock-data only has 3
|
||||
|
||||
expect(component.selectedDistributionTargets).toHaveLength(4); // mock-data only has 3
|
||||
expect(component.selectedDistributionTargetsFilterClone).toHaveLength(4);
|
||||
expect(removeSelectedItems).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should move distribution targets to available list', () => {
|
||||
component.selectedDistributionTargets[0]['selected'] = true; // select first item in available array
|
||||
const removeSelectedItems = jest.spyOn(component, 'removeSelectedItems');
|
||||
component.moveDistributionTargets(Side.SELECTED);
|
||||
|
||||
expect(component.availableDistributionTargets).toHaveLength(6); // mock-data has 5
|
||||
expect(component.availableDistributionTargetsFilterClone).toHaveLength(6);
|
||||
expect(removeSelectedItems).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should set selectAll checkboxes to true when moving a workbasket', () => {
|
||||
[Side.SELECTED, Side.AVAILABLE].forEach((side) => {
|
||||
component.moveDistributionTargets(side);
|
||||
expect(component.selectAllLeft).toBeTruthy();
|
||||
expect(component.selectAllRight).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
it('should call unselectItems() when moving a workbasket', () => {
|
||||
const unselectItems = jest.spyOn(component, 'unselectItems');
|
||||
|
||||
[Side.SELECTED, Side.AVAILABLE].forEach((side) => {
|
||||
component.moveDistributionTargets(side);
|
||||
expect(unselectItems).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('should reset distribution targets to last state when undo is called', () => {
|
||||
component.distributionTargetsClone = component.availableDistributionTargets;
|
||||
component.distributionTargetsSelectedClone = component.distributionTargetsSelected;
|
||||
component.availableDistributionTargets[0]['selected'] = true; // select first item in available array
|
||||
component.distributionTargetsLeft = component.distributionTargetsSelected;
|
||||
|
||||
component.moveDistributionTargets(Side.AVAILABLE);
|
||||
expect(component.distributionTargetsSelected).toHaveLength(4); // mock-data only has 3
|
||||
expect(component.selectedDistributionTargets).toHaveLength(4); // mock-data only has 3
|
||||
|
||||
component.onClear();
|
||||
expect(component.distributionTargetsSelected).toHaveLength(3);
|
||||
expect(component.selectedDistributionTargets).toHaveLength(3);
|
||||
expect(component.selectedDistributionTargetsFilterClone).toHaveLength(3);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Component, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import { Component, Input, OnDestroy, OnInit, SimpleChanges } from '@angular/core';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
|
||||
import { Workbasket } from 'app/shared/models/workbasket';
|
||||
|
@ -6,7 +6,6 @@ import { WorkbasketSummary } from 'app/shared/models/workbasket-summary';
|
|||
import { WorkbasketSummaryRepresentation } from 'app/shared/models/workbasket-summary-representation';
|
||||
import { WorkbasketDistributionTargets } from 'app/shared/models/workbasket-distribution-targets';
|
||||
import { WorkbasketService } from 'app/shared/services/workbasket/workbasket.service';
|
||||
import { Page } from 'app/shared/models/page';
|
||||
import { Actions, ofActionCompleted, Select, Store } from '@ngxs/store';
|
||||
import { filter, take, takeUntil } from 'rxjs/operators';
|
||||
import { NOTIFICATION_TYPES } from '../../../shared/models/notifications';
|
||||
|
@ -22,7 +21,6 @@ import { WorkbasketSelectors } from '../../../shared/store/workbasket-store/work
|
|||
import { ButtonAction } from '../../models/button-action';
|
||||
import { Pair } from '../../../shared/models/pair';
|
||||
import { WorkbasketQueryFilterParameter } from '../../../shared/models/workbasket-query-filter-parameter';
|
||||
import { QueryPagingParameter } from '../../../shared/models/query-paging-parameter';
|
||||
|
||||
export enum Side {
|
||||
AVAILABLE,
|
||||
|
@ -41,26 +39,19 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
|||
sideBySide = true;
|
||||
displayingDistributionTargetsPicker = true;
|
||||
|
||||
distributionTargetsSelectedResource: WorkbasketDistributionTargets;
|
||||
availableDistributionTargets: WorkbasketSummary[] = [];
|
||||
distributionTargetsClone: WorkbasketSummary[];
|
||||
|
||||
distributionTargetsLeft: WorkbasketSummary[] = [];
|
||||
distributionTargetsSelected: WorkbasketSummary[];
|
||||
distributionTargetsSelectedClone: WorkbasketSummary[];
|
||||
|
||||
loadingItems = false;
|
||||
side = Side;
|
||||
private initialized = false;
|
||||
currentPage: Page;
|
||||
pageParameter: QueryPagingParameter = {
|
||||
page: 1,
|
||||
'page-size': 9
|
||||
};
|
||||
cards: number;
|
||||
selectAllLeft = false;
|
||||
selectAllRight = false;
|
||||
|
||||
availableDistributionTargets: WorkbasketSummary[] = [];
|
||||
availableDistributionTargetsUndoClone: WorkbasketSummary[];
|
||||
availableDistributionTargetsFilterClone: WorkbasketSummary[];
|
||||
|
||||
selectedDistributionTargets: WorkbasketSummary[];
|
||||
selectedDistributionTargetsUndoClone: WorkbasketSummary[];
|
||||
selectedDistributionTargetsFilterClone: WorkbasketSummary[];
|
||||
selectedDistributionTargetsResource: WorkbasketDistributionTargets;
|
||||
|
||||
@Select(WorkbasketSelectors.workbasketDistributionTargets)
|
||||
workbasketDistributionTargets$: Observable<WorkbasketDistributionTargets>;
|
||||
|
||||
|
@ -88,7 +79,10 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
|||
*/
|
||||
ngOnInit() {
|
||||
this.selectedWorkbasket$
|
||||
.pipe(filter((selectedWorkbasket) => typeof selectedWorkbasket !== 'undefined'))
|
||||
.pipe(
|
||||
filter((selectedWorkbasket) => typeof selectedWorkbasket !== 'undefined'),
|
||||
takeUntil(this.destroy$)
|
||||
)
|
||||
.subscribe((selectedWorkbasket) => {
|
||||
this.workbasket = selectedWorkbasket;
|
||||
});
|
||||
|
@ -98,20 +92,23 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
|||
this.store.dispatch(new GetAvailableDistributionTargets());
|
||||
}
|
||||
|
||||
this.availableDistributionTargets$
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.pipe(filter((availableDistributionTargets) => typeof availableDistributionTargets !== 'undefined'))
|
||||
.subscribe((availableDistributionTargets) => {
|
||||
this.availableDistributionTargets = availableDistributionTargets.map((wb) => ({ ...wb }));
|
||||
});
|
||||
|
||||
this.workbasketDistributionTargets$.subscribe((workbasketDistributionTargets) => {
|
||||
this.workbasketDistributionTargets$.pipe(takeUntil(this.destroy$)).subscribe((workbasketDistributionTargets) => {
|
||||
if (typeof workbasketDistributionTargets !== 'undefined') {
|
||||
this.distributionTargetsSelectedResource = { ...workbasketDistributionTargets };
|
||||
this.distributionTargetsSelected = this.distributionTargetsSelectedResource.distributionTargets;
|
||||
this.distributionTargetsSelectedClone = { ...this.distributionTargetsSelected };
|
||||
this.pageParameter.page = 1;
|
||||
this.getWorkbaskets();
|
||||
this.selectedDistributionTargetsResource = { ...workbasketDistributionTargets };
|
||||
|
||||
this.selectedDistributionTargets = [];
|
||||
workbasketDistributionTargets.distributionTargets.forEach((distributionTarget) => {
|
||||
const target = {};
|
||||
Object.keys(distributionTarget).forEach((key) => {
|
||||
target[key] = distributionTarget[key];
|
||||
});
|
||||
this.selectedDistributionTargets.push(target);
|
||||
});
|
||||
|
||||
this.selectedDistributionTargetsFilterClone = [...this.selectedDistributionTargets];
|
||||
this.selectedDistributionTargetsUndoClone = [...this.selectedDistributionTargets];
|
||||
|
||||
this.getAvailableDistributionTargets();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -123,7 +120,7 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
|||
// saving workbasket distributions targets when workbasket was copied or created
|
||||
this.ngxsActions$.pipe(ofActionCompleted(SaveNewWorkbasket), takeUntil(this.destroy$)).subscribe(() => {
|
||||
this.selectedWorkbasket$.pipe(take(1)).subscribe((workbasket) => {
|
||||
this.distributionTargetsSelectedResource._links = {
|
||||
this.selectedDistributionTargetsResource._links = {
|
||||
self: { href: workbasket._links.distributionTargets.href }
|
||||
};
|
||||
this.onSave();
|
||||
|
@ -144,13 +141,38 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
|||
});
|
||||
}
|
||||
|
||||
onScroll() {
|
||||
if (this.currentPage && this.currentPage.totalPages > this.pageParameter.page) {
|
||||
this.loadingItems = true;
|
||||
this.getNextPage();
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (changes.workbasket.currentValue !== changes.workbasket.previousValue) {
|
||||
this.getAvailableDistributionTargets();
|
||||
}
|
||||
}
|
||||
|
||||
filterWorkbasketsByWorkbasketIDs(workbaskets: WorkbasketSummary[], IDs: WorkbasketSummary[]): WorkbasketSummary[] {
|
||||
const workbasketIds: string[] = IDs.map((workbasket) => workbasket.workbasketId);
|
||||
return workbaskets.filter((workbasket) => !workbasketIds.includes(workbasket.workbasketId));
|
||||
}
|
||||
|
||||
getAvailableDistributionTargets() {
|
||||
this.availableDistributionTargets$
|
||||
.pipe(
|
||||
take(1),
|
||||
filter((availableDistributionTargets) => typeof availableDistributionTargets !== 'undefined')
|
||||
)
|
||||
.subscribe((availableDistributionTargets) => {
|
||||
this.availableDistributionTargets = availableDistributionTargets.map((wb) => ({ ...wb }));
|
||||
|
||||
if (this.selectedDistributionTargets && this.selectedDistributionTargets.length !== 0) {
|
||||
this.availableDistributionTargets = this.filterWorkbasketsByWorkbasketIDs(
|
||||
this.availableDistributionTargets,
|
||||
this.selectedDistributionTargets
|
||||
);
|
||||
}
|
||||
|
||||
this.availableDistributionTargetsUndoClone = [...this.availableDistributionTargets];
|
||||
this.availableDistributionTargetsFilterClone = [...this.availableDistributionTargets];
|
||||
});
|
||||
}
|
||||
|
||||
changeToolbarState(state: boolean) {
|
||||
this.toolbarState = state;
|
||||
}
|
||||
|
@ -159,56 +181,42 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
|||
this.displayingDistributionTargetsPicker = !this.displayingDistributionTargetsPicker;
|
||||
}
|
||||
|
||||
getWorkbaskets(side?: Side) {
|
||||
if (this.distributionTargetsSelected && !this.initialized) {
|
||||
this.initialized = true;
|
||||
this.pageParameter['page-size'] = this.cards + this.distributionTargetsSelected.length;
|
||||
}
|
||||
|
||||
this.workbasketService
|
||||
.getWorkBasketsSummary(true, undefined, undefined, this.pageParameter)
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((distributionTargetsAvailable: WorkbasketSummaryRepresentation) => {
|
||||
if (this.pageParameter === 1) {
|
||||
this.availableDistributionTargets = [];
|
||||
this.currentPage = distributionTargetsAvailable.page;
|
||||
}
|
||||
if (side === Side.AVAILABLE) {
|
||||
this.availableDistributionTargets.push(...distributionTargetsAvailable.workbaskets);
|
||||
} else if (side === Side.SELECTED) {
|
||||
this.distributionTargetsLeft = Object.assign([], distributionTargetsAvailable.workbaskets);
|
||||
} else {
|
||||
this.availableDistributionTargets.push(...distributionTargetsAvailable.workbaskets);
|
||||
this.distributionTargetsLeft = Object.assign([], distributionTargetsAvailable.workbaskets);
|
||||
this.distributionTargetsClone = Object.assign([], distributionTargetsAvailable.workbaskets);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getNextPage(side?: Side) {
|
||||
this.pageParameter.page += 1;
|
||||
this.getWorkbaskets(side);
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// an own filter would save a lot of work here because the workbasketService filter
|
||||
// returns all available distribution targets and must be filtered again
|
||||
performFilter({ left: side, right: filter }: Pair<Side, WorkbasketQueryFilterParameter>) {
|
||||
this.workbasketService
|
||||
.getWorkBasketsSummary(true, filter)
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((distributionTargetsAvailable: WorkbasketSummaryRepresentation) => {
|
||||
this.fillDistributionTargets(side, []);
|
||||
const isFilterEmpty =
|
||||
filter['name-like'].length === 0 &&
|
||||
filter['key-like'].length === 0 &&
|
||||
filter['description-like'].length === 0 &&
|
||||
filter['owner-like'].length === 0 &&
|
||||
filter['type'].length === 0;
|
||||
|
||||
if (this.pageParameter === 1) {
|
||||
this.availableDistributionTargets = [];
|
||||
this.currentPage = distributionTargetsAvailable.page;
|
||||
}
|
||||
// filter available side
|
||||
if (side === Side.AVAILABLE) {
|
||||
this.availableDistributionTargets.push(...distributionTargetsAvailable.workbaskets);
|
||||
} else if (side === Side.SELECTED) {
|
||||
this.distributionTargetsLeft = Object.assign([], distributionTargetsAvailable.workbaskets);
|
||||
} else {
|
||||
this.availableDistributionTargets.push(...distributionTargetsAvailable.workbaskets);
|
||||
this.distributionTargetsLeft = Object.assign([], distributionTargetsAvailable.workbaskets);
|
||||
this.distributionTargetsClone = Object.assign([], distributionTargetsAvailable.workbaskets);
|
||||
if (isFilterEmpty) {
|
||||
this.availableDistributionTargets = this.availableDistributionTargetsFilterClone;
|
||||
} else {
|
||||
this.availableDistributionTargets = this.filterWorkbasketsByWorkbasketIDs(
|
||||
distributionTargetsAvailable.workbaskets,
|
||||
this.selectedDistributionTargetsFilterClone
|
||||
);
|
||||
}
|
||||
}
|
||||
// filter selected side
|
||||
else if (side === Side.SELECTED) {
|
||||
if (isFilterEmpty) {
|
||||
this.selectedDistributionTargets = this.selectedDistributionTargetsFilterClone;
|
||||
} else {
|
||||
const ids = distributionTargetsAvailable.workbaskets.map((workbasket) => workbasket.workbasketId);
|
||||
this.selectedDistributionTargets = this.selectedDistributionTargetsFilterClone.filter((workbasket) =>
|
||||
ids.includes(workbasket.workbasketId)
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -216,7 +224,7 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
|||
onSave() {
|
||||
this.store.dispatch(
|
||||
new UpdateWorkbasketDistributionTargets(
|
||||
this.distributionTargetsSelectedResource._links.self.href,
|
||||
this.selectedDistributionTargetsResource._links.self.href,
|
||||
this.getSelectedIds()
|
||||
)
|
||||
);
|
||||
|
@ -224,44 +232,55 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
|||
}
|
||||
|
||||
moveDistributionTargets(side: number) {
|
||||
// get all workbaskets without applied filter and without overwriting the selected property
|
||||
this.selectedDistributionTargets = this.selectedDistributionTargets.concat(
|
||||
this.filterWorkbasketsByWorkbasketIDs(
|
||||
this.selectedDistributionTargetsFilterClone,
|
||||
this.selectedDistributionTargets
|
||||
)
|
||||
);
|
||||
this.availableDistributionTargets = this.availableDistributionTargets.concat(
|
||||
this.filterWorkbasketsByWorkbasketIDs(
|
||||
this.availableDistributionTargetsFilterClone,
|
||||
this.availableDistributionTargets
|
||||
)
|
||||
);
|
||||
|
||||
if (side === Side.AVAILABLE) {
|
||||
const itemsLeft = this.availableDistributionTargets.length;
|
||||
const itemsRight = this.distributionTargetsLeft.length;
|
||||
// moving available items to selected side
|
||||
const itemsSelected = this.getSelectedItems(this.availableDistributionTargets);
|
||||
this.distributionTargetsSelected = [...this.distributionTargetsSelected, ...itemsSelected];
|
||||
this.distributionTargetsLeft = this.distributionTargetsLeft.concat(itemsSelected);
|
||||
if (
|
||||
itemsLeft - itemsSelected.length <= this.pageParameter['page-size'] &&
|
||||
itemsLeft + itemsRight < this.currentPage.totalElements
|
||||
) {
|
||||
this.getNextPage(side);
|
||||
}
|
||||
this.unselectItems(this.distributionTargetsSelected);
|
||||
this.selectedDistributionTargets = this.selectedDistributionTargets.concat(itemsSelected);
|
||||
this.availableDistributionTargets = this.removeSelectedItems(this.availableDistributionTargets, itemsSelected);
|
||||
this.unselectItems(itemsSelected);
|
||||
} else {
|
||||
const itemsSelected = this.getSelectedItems(this.distributionTargetsLeft);
|
||||
this.distributionTargetsSelected = this.removeSelectedItems(this.distributionTargetsSelected, itemsSelected);
|
||||
this.distributionTargetsLeft = this.removeSelectedItems(this.distributionTargetsLeft, itemsSelected);
|
||||
// moving selected items to available side
|
||||
const itemsSelected = this.getSelectedItems(this.selectedDistributionTargets);
|
||||
this.selectedDistributionTargets = this.removeSelectedItems(this.selectedDistributionTargets, itemsSelected);
|
||||
this.availableDistributionTargets = this.availableDistributionTargets.concat(itemsSelected);
|
||||
this.unselectItems(itemsSelected);
|
||||
}
|
||||
this.selectedDistributionTargetsFilterClone = this.selectedDistributionTargets;
|
||||
this.availableDistributionTargetsFilterClone = this.availableDistributionTargets;
|
||||
this.selectAllRight = true;
|
||||
this.selectAllLeft = true;
|
||||
}
|
||||
|
||||
onClear() {
|
||||
this.notificationsService.showToast(NOTIFICATION_TYPES.INFO_ALERT);
|
||||
this.availableDistributionTargets = Object.assign([], this.distributionTargetsClone);
|
||||
this.distributionTargetsLeft = Object.assign([], this.distributionTargetsSelectedClone);
|
||||
this.distributionTargetsSelected = Object.assign([], this.distributionTargetsSelectedClone);
|
||||
}
|
||||
|
||||
fillDistributionTargets(side: Side, workbaskets: WorkbasketSummary[]) {
|
||||
this.availableDistributionTargets = side === Side.AVAILABLE ? workbaskets : this.availableDistributionTargets;
|
||||
this.distributionTargetsLeft = side === Side.SELECTED ? workbaskets : this.distributionTargetsLeft;
|
||||
this.availableDistributionTargets = Object.assign([], this.availableDistributionTargetsUndoClone);
|
||||
this.availableDistributionTargetsFilterClone = Object.assign([], this.availableDistributionTargetsUndoClone);
|
||||
this.selectedDistributionTargets = Object.assign([], this.selectedDistributionTargetsUndoClone);
|
||||
this.selectedDistributionTargetsFilterClone = Object.assign([], this.selectedDistributionTargetsUndoClone);
|
||||
}
|
||||
|
||||
getSelectedItems(originList: any): any[] {
|
||||
return originList.filter((item: any) => item.selected === true);
|
||||
}
|
||||
|
||||
getSelectedIds(): string[] {
|
||||
return this.selectedDistributionTargets.map((distributionTarget) => distributionTarget.workbasketId);
|
||||
}
|
||||
|
||||
unselectItems(originList: any[]): any[] {
|
||||
return originList
|
||||
.filter((item) => item.selected)
|
||||
|
@ -280,10 +299,6 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
|||
return copyList;
|
||||
}
|
||||
|
||||
getSelectedIds(): string[] {
|
||||
return this.distributionTargetsSelected.map((distributionTarget) => distributionTarget.workbasketId);
|
||||
}
|
||||
|
||||
toggleSideBySideView() {
|
||||
this.sideBySide = !this.sideBySide;
|
||||
this.displayingDistributionTargetsPicker = true; //always display picker when toggle from side-by-side to single
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import { WorkbasketSummary } from '../models/workbasket-summary';
|
||||
import { Side } from '../../administration/components/workbasket-distribution-targets/workbasket-distribution-targets.component';
|
||||
|
||||
@Pipe({ name: 'selectWorkbaskets' })
|
||||
export class SelectWorkBasketPipe implements PipeTransform {
|
||||
transform(
|
||||
allWorkbaskets: WorkbasketSummary[],
|
||||
selectedWorkbaskets: WorkbasketSummary[],
|
||||
side: Side
|
||||
): WorkbasketSummary[] {
|
||||
if (!allWorkbaskets || !selectedWorkbaskets) {
|
||||
return [];
|
||||
}
|
||||
if (side === Side.SELECTED) {
|
||||
return selectedWorkbaskets;
|
||||
}
|
||||
const selectedWorkbasketIds: string[] = selectedWorkbaskets.map((wb) => wb.workbasketId);
|
||||
const isNotASelectedWorkbasket = (wb: WorkbasketSummary) => !selectedWorkbasketIds.includes(wb.workbasketId);
|
||||
return allWorkbaskets.filter(isNotASelectedWorkbasket);
|
||||
}
|
||||
}
|
|
@ -37,7 +37,6 @@ import { DropdownComponent } from './components/dropdown/dropdown.component';
|
|||
*/
|
||||
import { MapValuesPipe } from './pipes/map-values.pipe';
|
||||
import { RemoveNoneTypePipe } from './pipes/remove-empty-type.pipe';
|
||||
import { SelectWorkBasketPipe } from './pipes/select-workbaskets.pipe';
|
||||
import { SpreadNumberPipe } from './pipes/spread-number.pipe';
|
||||
import { OrderBy } from './pipes/order-by.pipe';
|
||||
import { MapToIterable } from './pipes/map-to-iterable.pipe';
|
||||
|
@ -87,7 +86,6 @@ const DECLARATIONS = [
|
|||
TypeAheadComponent,
|
||||
MapValuesPipe,
|
||||
RemoveNoneTypePipe,
|
||||
SelectWorkBasketPipe,
|
||||
SpreadNumberPipe,
|
||||
DateTimeZonePipe,
|
||||
NumberToArray,
|
||||
|
|
Loading…
Reference in New Issue