Pull request #7: Workflow virtualscroll
Merge in SL/common-ui from workflow-virtualscroll to master * commit '3616ccaf42f0e50a440d040805cc1c2200f9d8fe': use ng-template for drop preview and placeholder fix show add button when multi select active fix virtual scroll drag&drop preview and placeholder add virtual scroll in workflow
This commit is contained in:
commit
e6779d8a2b
@ -15,3 +15,7 @@ export * from './listing-component.directive';
|
|||||||
|
|
||||||
export * from './page-header/page-header.component';
|
export * from './page-header/page-header.component';
|
||||||
export * from './page-header/models';
|
export * from './page-header/models';
|
||||||
|
|
||||||
|
export * from './workflow/models/entity-wrapper.model';
|
||||||
|
export * from './workflow/models/workflow-config.model';
|
||||||
|
export * from './workflow/models/workflow-column.model';
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { AfterViewInit, ChangeDetectionStrategy, Component, forwardRef, Inject, Input, OnDestroy, ViewChild } from '@angular/core';
|
import { AfterViewInit, ChangeDetectionStrategy, Component, forwardRef, Inject, Input, OnDestroy, ViewChild } from '@angular/core';
|
||||||
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
||||||
import { delay, tap } from 'rxjs/operators';
|
import { delay, tap } from 'rxjs/operators';
|
||||||
import { AutoUnsubscribe, trackBy } from '../../utils';
|
import { AutoUnsubscribe, trackByFactory } from '../../utils';
|
||||||
import { IListable } from '../models';
|
import { IListable } from '../models';
|
||||||
import { ListingComponent, ListingService } from '../index';
|
import { ListingComponent, ListingService } from '../index';
|
||||||
import { HasScrollbarDirective } from '../../scrollbar';
|
import { HasScrollbarDirective } from '../../scrollbar';
|
||||||
@ -20,7 +20,7 @@ export class TableContentComponent<T extends IListable> extends AutoUnsubscribe
|
|||||||
@Input() tableItemClasses?: Record<string, (e: T) => boolean>;
|
@Input() tableItemClasses?: Record<string, (e: T) => boolean>;
|
||||||
@Input() selectionEnabled!: boolean;
|
@Input() selectionEnabled!: boolean;
|
||||||
@Input() helpModeKey?: 'dossier-list' | 'document-list';
|
@Input() helpModeKey?: 'dossier-list' | 'document-list';
|
||||||
readonly trackBy = trackBy<T>();
|
readonly trackBy = trackByFactory<T>();
|
||||||
|
|
||||||
@ViewChild(CdkVirtualScrollViewport, { static: true }) readonly scrollViewport!: CdkVirtualScrollViewport;
|
@ViewChild(CdkVirtualScrollViewport, { static: true }) readonly scrollViewport!: CdkVirtualScrollViewport;
|
||||||
@ViewChild(HasScrollbarDirective, { static: true }) readonly hasScrollbarDirective!: HasScrollbarDirective;
|
@ViewChild(HasScrollbarDirective, { static: true }) readonly hasScrollbarDirective!: HasScrollbarDirective;
|
||||||
|
|||||||
@ -15,8 +15,8 @@ import { filter, map, tap } from 'rxjs/operators';
|
|||||||
import { CircleButtonTypes } from '../../../buttons';
|
import { CircleButtonTypes } from '../../../buttons';
|
||||||
import { IListable } from '../../models';
|
import { IListable } from '../../models';
|
||||||
import { AutoUnsubscribe, Debounce } from '../../../utils';
|
import { AutoUnsubscribe, Debounce } from '../../../utils';
|
||||||
import { WorkflowColumn } from '../workflow.component';
|
|
||||||
import { ListingService } from '../../services';
|
import { ListingService } from '../../services';
|
||||||
|
import { WorkflowColumn } from '../models/workflow-column.model';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'iqser-column-header [column] [selectionColumn]',
|
selector: 'iqser-column-header [column] [selectionColumn]',
|
||||||
@ -105,6 +105,6 @@ export class ColumnHeaderComponent<T extends IListable, K extends string> extend
|
|||||||
this._updateBulkActionsContainerWidth(entries[0]);
|
this._updateBulkActionsContainerWidth(entries[0]);
|
||||||
});
|
});
|
||||||
|
|
||||||
observer.observe(this.bulkActionsContainer?.nativeElement);
|
observer.observe(this.bulkActionsContainer?.nativeElement as Element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
25
src/lib/listing/workflow/models/entity-wrapper.model.ts
Normal file
25
src/lib/listing/workflow/models/entity-wrapper.model.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { IListable } from '@iqser/common-ui';
|
||||||
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
|
|
||||||
|
export class EntityWrapper<T extends IListable> {
|
||||||
|
readonly classes$: BehaviorSubject<Record<string, boolean>>;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
readonly entity: T,
|
||||||
|
private readonly _itemClasses: Record<string, (e: T) => boolean>,
|
||||||
|
readonly isSelected$: Observable<boolean>,
|
||||||
|
) {
|
||||||
|
this.classes$ = new BehaviorSubject<Record<string, boolean>>(this._getItemClasses(entity));
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getItemClasses(entity: T): Record<string, boolean> {
|
||||||
|
const classes: { [key: string]: boolean } = {};
|
||||||
|
for (const key in this._itemClasses) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(this._itemClasses, key)) {
|
||||||
|
classes[key] = this._itemClasses[key](entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
classes.item = true;
|
||||||
|
return classes;
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/lib/listing/workflow/models/workflow-column.model.ts
Normal file
11
src/lib/listing/workflow/models/workflow-column.model.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { IListable } from '@iqser/common-ui';
|
||||||
|
import { BehaviorSubject } from 'rxjs';
|
||||||
|
|
||||||
|
export interface WorkflowColumn<T extends IListable, K> {
|
||||||
|
key: K;
|
||||||
|
label: string;
|
||||||
|
color: string;
|
||||||
|
enterFn: (entities: T[]) => Promise<void> | void;
|
||||||
|
enterPredicate: (entities: T[]) => boolean;
|
||||||
|
entities: BehaviorSubject<T[]>;
|
||||||
|
}
|
||||||
8
src/lib/listing/workflow/models/workflow-config.model.ts
Normal file
8
src/lib/listing/workflow/models/workflow-config.model.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { IListable } from '@iqser/common-ui';
|
||||||
|
import { WorkflowColumn } from './workflow-column.model';
|
||||||
|
|
||||||
|
export interface WorkflowConfig<T extends IListable, K> {
|
||||||
|
columnIdentifierFn: (entity: T) => K;
|
||||||
|
itemVersionFn: (entity: T) => string;
|
||||||
|
columns: WorkflowColumn<T, K>[];
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
<iqser-table-header [tableHeaderLabel]="tableHeaderLabel" listingMode="workflow">
|
<iqser-table-header [tableHeaderLabel]="listingComponent.tableHeaderLabel" listingMode="workflow">
|
||||||
<ng-container *ngTemplateOutlet="headerTemplate"></ng-container>
|
<ng-container *ngTemplateOutlet="headerTemplate"></ng-container>
|
||||||
</iqser-table-header>
|
</iqser-table-header>
|
||||||
|
|
||||||
@ -27,49 +27,53 @@
|
|||||||
class="column"
|
class="column"
|
||||||
>
|
>
|
||||||
<iqser-column-header [(selectionColumn)]="selectionColumn" [bulkActions]="bulkActions" [column]="column"></iqser-column-header>
|
<iqser-column-header [(selectionColumn)]="selectionColumn" [bulkActions]="bulkActions" [column]="column"></iqser-column-header>
|
||||||
<div
|
<cdk-virtual-scroll-viewport [itemSize]="itemHeight">
|
||||||
(cdkDropListDropped)="move($event)"
|
|
||||||
*ngIf="column.entities | async as entities"
|
|
||||||
[cdkDropListData]="entities"
|
|
||||||
[cdkDropListEnterPredicate]="canMoveTo(column)"
|
|
||||||
[id]="column.key"
|
|
||||||
cdkDropList
|
|
||||||
cdkDropListSortingDisabled
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
(cdkDragEnded)="stopDragging()"
|
(cdkDropListDropped)="move($event)"
|
||||||
(cdkDragStarted)="startDragging(column, $event)"
|
*ngIf="column.entities | async as entities"
|
||||||
(click)="selectionColumn === column && listingService.select(entity)"
|
[cdkDropListData]="entities"
|
||||||
*ngFor="let entity of entities"
|
[cdkDropListEnterPredicate]="canMoveTo(column)"
|
||||||
[cdkDragData]="entity"
|
[class.multi-select-active]="selectionColumn === column"
|
||||||
[class.no-border]="dragging && draggingEntities.includes(entity)"
|
[id]="column.key"
|
||||||
[class.selected]="all[entity.id].isSelected$ | async"
|
cdkDropList
|
||||||
[ngClass]="all[entity.id].classes$ | async"
|
cdkDropListSortingDisabled
|
||||||
cdkDrag
|
|
||||||
>
|
>
|
||||||
<ng-container *ngIf="!draggingEntities.includes(entity)">
|
<div
|
||||||
<ng-container *ngTemplateOutlet="itemTemplate; context: { entity: entity }"></ng-container>
|
(cdkDragEnded)="stopDragging()"
|
||||||
</ng-container>
|
(cdkDragStarted)="startDragging(column, $event)"
|
||||||
|
(click)="selectionColumn === column && listingService.select(entity)"
|
||||||
<div *cdkDragPlaceholder>
|
*cdkVirtualFor="let entity of column.entities; trackBy: trackBy"
|
||||||
<div *ngFor="let e of draggingEntities" [style.min-height]="itemHeight + 'px'" class="placeholder"></div>
|
[cdkDragData]="entity"
|
||||||
</div>
|
[class.no-border]="dragging && draggingEntities.includes(entity)"
|
||||||
|
[class.selected]="all[entity.id].isSelected$ | async"
|
||||||
<div *cdkDragPreview>
|
[ngClass]="all[entity.id].classes$ | async"
|
||||||
<ng-container *ngFor="let e of draggingEntities">
|
cdkDrag
|
||||||
<div
|
>
|
||||||
[class.selected]="all[e.id].isSelected$ | async"
|
<ng-container *ngIf="!draggingEntities.includes(entity)">
|
||||||
[ngClass]="all[e.id].classes$ | async"
|
<ng-container *ngTemplateOutlet="itemTemplate; context: { entity: entity }"></ng-container>
|
||||||
[style.width]="itemWidth + 'px'"
|
|
||||||
>
|
|
||||||
<ng-container *ngTemplateOutlet="itemTemplate; context: { entity: e }"></ng-container>
|
|
||||||
</div>
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-template cdkDragPlaceholder>
|
||||||
|
<div *ngFor="let e of draggingEntities" [style.min-height]="itemHeight + 'px'" class="placeholder"></div>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template cdkDragPreview>
|
||||||
|
<ng-container *ngFor="let e of draggingEntities">
|
||||||
|
<div
|
||||||
|
[class.selected]="all[e.id].isSelected$ | async"
|
||||||
|
[ngClass]="all[e.id].classes$ | async"
|
||||||
|
[style.width]="itemWidth + 'px'"
|
||||||
|
>
|
||||||
|
<ng-container *ngTemplateOutlet="itemTemplate; context: { entity: e }"></ng-container>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
</ng-template>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div (click)="addElement.emit()" *ngIf="column.key === addElementColumn" class="add-btn">
|
||||||
|
<mat-icon [svgIcon]="addElementIcon"></mat-icon>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div (click)="addElement.emit()" *ngIf="column.key === addElementColumn" class="add-btn">
|
</cdk-virtual-scroll-viewport>
|
||||||
<mat-icon [svgIcon]="addElementIcon"></mat-icon>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -58,7 +58,6 @@
|
|||||||
> .heading, .add-btn, ::ng-deep.item > * > * {
|
> .heading, .add-btn, ::ng-deep.item > * > * {
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,6 +67,10 @@
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
@include no-scroll-bar;
|
@include no-scroll-bar;
|
||||||
min-height: calc(100% - 36px);
|
min-height: calc(100% - 36px);
|
||||||
|
|
||||||
|
&.multi-select-active {
|
||||||
|
min-height: calc(100% - 86px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
@ -124,3 +127,8 @@
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
margin: 0 8px 4px 8px;
|
margin: 0 8px 4px 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cdk-virtual-scroll-viewport {
|
||||||
|
height: 100%;
|
||||||
|
@include no-scroll-bar;
|
||||||
|
}
|
||||||
|
|||||||
@ -15,61 +15,25 @@ import {
|
|||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { ListingComponent } from '../listing-component.directive';
|
import { ListingComponent } from '../listing-component.directive';
|
||||||
import { CdkDragDrop, CdkDragStart, CdkDropList } from '@angular/cdk/drag-drop';
|
import { CdkDragDrop, CdkDragStart, CdkDropList } from '@angular/cdk/drag-drop';
|
||||||
import { AutoUnsubscribe, Debounce, Required } from '../../utils';
|
import { AutoUnsubscribe, Debounce, trackByFactory } from '../../utils';
|
||||||
import { LoadingService } from '../../loading';
|
|
||||||
import { IListable } from '../models';
|
import { IListable } from '../models';
|
||||||
import { EntitiesService, ListingService } from '../services';
|
import { EntitiesService, ListingService } from '../services';
|
||||||
import { BehaviorSubject, Observable } from 'rxjs';
|
import { BehaviorSubject } from 'rxjs';
|
||||||
import { filter, tap } from 'rxjs/operators';
|
import { filter, tap } from 'rxjs/operators';
|
||||||
|
import { WorkflowConfig } from './models/workflow-config.model';
|
||||||
export interface WorkflowColumn<T extends IListable, K> {
|
import { WorkflowColumn } from './models/workflow-column.model';
|
||||||
key: K;
|
import { EntityWrapper } from './models/entity-wrapper.model';
|
||||||
label: string;
|
|
||||||
color: string;
|
|
||||||
enterFn: (entities: T[]) => Promise<void> | void;
|
|
||||||
enterPredicate: (entities: T[]) => boolean;
|
|
||||||
entities: BehaviorSubject<T[]>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WorkflowConfig<T extends IListable, K> {
|
|
||||||
columnIdentifierFn: (entity: T) => K;
|
|
||||||
itemVersionFn: (entity: T) => string;
|
|
||||||
columns: WorkflowColumn<T, K>[];
|
|
||||||
}
|
|
||||||
|
|
||||||
class EntityWrapper<T extends IListable> {
|
|
||||||
readonly classes$: BehaviorSubject<Record<string, boolean>>;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
readonly entity: T,
|
|
||||||
private readonly _itemClasses: Record<string, (e: T) => boolean>,
|
|
||||||
readonly isSelected$: Observable<boolean>,
|
|
||||||
) {
|
|
||||||
this.classes$ = new BehaviorSubject<Record<string, boolean>>(this._getItemClasses(entity));
|
|
||||||
}
|
|
||||||
|
|
||||||
private _getItemClasses(entity: T): Record<string, boolean> {
|
|
||||||
const classes: { [key: string]: boolean } = {};
|
|
||||||
for (const key in this._itemClasses) {
|
|
||||||
if (Object.prototype.hasOwnProperty.call(this._itemClasses, key)) {
|
|
||||||
classes[key] = this._itemClasses[key](entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
classes.item = true;
|
|
||||||
return classes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'iqser-workflow',
|
selector: 'iqser-workflow [itemTemplate] [config]',
|
||||||
templateUrl: './workflow.component.html',
|
templateUrl: './workflow.component.html',
|
||||||
styleUrls: ['./workflow.component.scss'],
|
styleUrls: ['./workflow.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class WorkflowComponent<T extends IListable, K extends string> extends AutoUnsubscribe implements OnInit {
|
export class WorkflowComponent<T extends IListable, K extends string> extends AutoUnsubscribe implements OnInit {
|
||||||
@Input() headerTemplate?: TemplateRef<unknown>;
|
@Input() headerTemplate?: TemplateRef<unknown>;
|
||||||
@Input() @Required() itemTemplate!: TemplateRef<T>;
|
@Input() itemTemplate!: TemplateRef<T>;
|
||||||
@Input() @Required() config!: WorkflowConfig<T, K>;
|
@Input() config!: WorkflowConfig<T, K>;
|
||||||
@Input() itemClasses!: Record<string, (e: T) => boolean>;
|
@Input() itemClasses!: Record<string, (e: T) => boolean>;
|
||||||
@Input() addElementIcon?: string;
|
@Input() addElementIcon?: string;
|
||||||
@Input() addElementColumn?: K;
|
@Input() addElementColumn?: K;
|
||||||
@ -82,6 +46,7 @@ export class WorkflowComponent<T extends IListable, K extends string> extends Au
|
|||||||
@Output() readonly noDataAction = new EventEmitter<void>();
|
@Output() readonly noDataAction = new EventEmitter<void>();
|
||||||
@Output() readonly addElement = new EventEmitter<void>();
|
@Output() readonly addElement = new EventEmitter<void>();
|
||||||
|
|
||||||
|
readonly trackBy = trackByFactory<T>();
|
||||||
itemHeight?: number;
|
itemHeight?: number;
|
||||||
itemWidth?: number;
|
itemWidth?: number;
|
||||||
dragging = false;
|
dragging = false;
|
||||||
@ -90,13 +55,12 @@ export class WorkflowComponent<T extends IListable, K extends string> extends Au
|
|||||||
readonly draggingEntities$ = new BehaviorSubject<T[]>([]);
|
readonly draggingEntities$ = new BehaviorSubject<T[]>([]);
|
||||||
all: { [key: string]: EntityWrapper<T> } = {};
|
all: { [key: string]: EntityWrapper<T> } = {};
|
||||||
@ViewChildren(CdkDropList) private readonly _dropLists!: QueryList<CdkDropList>;
|
@ViewChildren(CdkDropList) private readonly _dropLists!: QueryList<CdkDropList>;
|
||||||
private _observer = new ResizeObserver((entries: ResizeObserverEntry[]) => {
|
private readonly _observer = new ResizeObserver((entries: ResizeObserverEntry[]) => {
|
||||||
this._updateItemSize(entries[0]);
|
this._updateItemSize(entries[0]);
|
||||||
});
|
});
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(forwardRef(() => ListingComponent)) readonly listingComponent: ListingComponent<T>,
|
@Inject(forwardRef(() => ListingComponent)) readonly listingComponent: ListingComponent<T>,
|
||||||
private readonly _loadingService: LoadingService,
|
|
||||||
private readonly _changeRef: ChangeDetectorRef,
|
private readonly _changeRef: ChangeDetectorRef,
|
||||||
private readonly _elementRef: ElementRef,
|
private readonly _elementRef: ElementRef,
|
||||||
readonly listingService: ListingService<T>,
|
readonly listingService: ListingService<T>,
|
||||||
@ -105,10 +69,6 @@ export class WorkflowComponent<T extends IListable, K extends string> extends Au
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
get tableHeaderLabel(): string | undefined {
|
|
||||||
return this.listingComponent.tableHeaderLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
async move(event: CdkDragDrop<T[]>): Promise<void> {
|
async move(event: CdkDragDrop<T[]>): Promise<void> {
|
||||||
if (event.previousContainer !== event.container) {
|
if (event.previousContainer !== event.container) {
|
||||||
const column = this._getColumnByKey((<unknown>event.container.id) as K);
|
const column = this._getColumnByKey((<unknown>event.container.id) as K);
|
||||||
@ -135,9 +95,9 @@ export class WorkflowComponent<T extends IListable, K extends string> extends Au
|
|||||||
return () => column.enterPredicate(this.draggingEntities$.value);
|
return () => column.enterPredicate(this.draggingEntities$.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
startDragging(column: WorkflowColumn<T, K>, $event: CdkDragStart): void {
|
startDragging(column: WorkflowColumn<T, K>, $event: CdkDragStart<T>): void {
|
||||||
const entity: T = $event.source.data as T;
|
const entity = $event.source.data;
|
||||||
if (this.listingService.selected.includes(entity)) {
|
if (this.listingService.selectedIds.includes(entity.id)) {
|
||||||
this.draggingEntities$.next(this.listingService.selected);
|
this.draggingEntities$.next(this.listingService.selected);
|
||||||
} else {
|
} else {
|
||||||
this.draggingEntities$.next([entity]);
|
this.draggingEntities$.next([entity]);
|
||||||
@ -165,8 +125,9 @@ export class WorkflowComponent<T extends IListable, K extends string> extends Au
|
|||||||
return !!this._getListById(column.key)?._dropListRef.isReceiving();
|
return !!this._getListById(column.key)?._dropListRef.isReceiving();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Debounce(30)
|
||||||
private _setupResizeObserver(): void {
|
private _setupResizeObserver(): void {
|
||||||
const cdkDragElement: Element = this._elementRef.nativeElement.querySelector('.cdk-drag') as Element;
|
const cdkDragElement = this._elementRef.nativeElement.querySelector('.cdk-drag') as Element;
|
||||||
if (cdkDragElement) {
|
if (cdkDragElement) {
|
||||||
this._observer.observe(cdkDragElement);
|
this._observer.observe(cdkDragElement);
|
||||||
}
|
}
|
||||||
@ -214,7 +175,7 @@ export class WorkflowComponent<T extends IListable, K extends string> extends Au
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this._changeRef.detectChanges();
|
this._changeRef.markForCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
private _addEntity(entity: T): void {
|
private _addEntity(entity: T): void {
|
||||||
@ -246,12 +207,14 @@ export class WorkflowComponent<T extends IListable, K extends string> extends Au
|
|||||||
private _removeEntity(entity: T): void {
|
private _removeEntity(entity: T): void {
|
||||||
const existingEntity = this.all[entity.id];
|
const existingEntity = this.all[entity.id];
|
||||||
const column = this._getColumnByKey(this.config.columnIdentifierFn(existingEntity.entity));
|
const column = this._getColumnByKey(this.config.columnIdentifierFn(existingEntity.entity));
|
||||||
|
|
||||||
if (column) {
|
if (column) {
|
||||||
const entities = column.entities.value;
|
const entities = column.entities.value;
|
||||||
const idx = entities.findIndex(item => item.id === entity.id);
|
const idx = entities.findIndex(item => item.id === entity.id);
|
||||||
entities.splice(idx, 1);
|
entities.splice(idx, 1);
|
||||||
column.entities.next(entities);
|
column.entities.next(entities);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete this.all[entity.id];
|
delete this.all[entity.id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -31,6 +31,6 @@ export function toNumber(str: string): number {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trackBy<T extends ITrackable>() {
|
export function trackByFactory<T extends ITrackable>() {
|
||||||
return (index: number, item: T): string => item.id;
|
return (index: number, item: T): string => item.id;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user