Refresh items, add btn, some css fixes
This commit is contained in:
parent
5973631a1d
commit
5d0bb11c65
@ -23,7 +23,6 @@ export abstract class ListingComponent<T extends Listable> extends AutoUnsubscri
|
||||
readonly listingMode$: Observable<ListingMode>;
|
||||
readonly routerLinkFn?: (entity: T) => string | string[];
|
||||
|
||||
// TODO: These should be somewhere in table listing, not generic listing
|
||||
abstract readonly tableColumnConfigs: readonly TableColumnConfig<T>[];
|
||||
abstract readonly tableHeaderLabel: string;
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
[class.list-source]="isSource(column)"
|
||||
[style.--color]="column.color"
|
||||
class="column">
|
||||
<div class="heading">{{ column.label | translate }} ({{column.entities.length}})</div>
|
||||
<div class="heading">{{ column.label | translate }} ({{column.entities?.length || 0}})</div>
|
||||
<div
|
||||
(cdkDropListDropped)="move($event)"
|
||||
[cdkDropListData]="column.entities"
|
||||
@ -25,6 +25,9 @@
|
||||
<div *cdkDragPlaceholder [style.--height]="itemHeight"></div>
|
||||
<ng-container *ngTemplateOutlet="itemTemplate; context: { entity: entity }"></ng-container>
|
||||
</div>
|
||||
<div (click)="addElement.emit()" *ngIf="column.key === addElementColumn" class="add-btn">
|
||||
<mat-icon [svgIcon]="addElementIcon"></mat-icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -38,8 +38,7 @@
|
||||
}
|
||||
|
||||
> .heading {
|
||||
margin-left: 18px;
|
||||
margin-bottom: 16px;
|
||||
margin: 0 18px 16px 18px;
|
||||
}
|
||||
|
||||
&.dragging {
|
||||
@ -60,7 +59,7 @@
|
||||
var(--iqser-white) 8px
|
||||
);
|
||||
|
||||
> .heading, ::ng-deep.cdk-drag > * {
|
||||
> .heading, .add-btn, ::ng-deep.cdk-drag > * {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
@ -76,11 +75,9 @@
|
||||
min-height: calc(100% - 36px);
|
||||
}
|
||||
|
||||
|
||||
.cdk-drag {
|
||||
background-color: var(--iqser-white);
|
||||
transition: background-color 0.2s, box-shadow 0.2s;
|
||||
border-radius: 8px;
|
||||
margin: 0 8px 4px 8px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 8px;
|
||||
@ -93,6 +90,31 @@
|
||||
|
||||
&:hover {
|
||||
background-color: var(--iqser-grey-6);
|
||||
}
|
||||
}
|
||||
|
||||
.add-btn {
|
||||
background-color: var(--iqser-grey-6);
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
|
||||
mat-icon {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--iqser-grey-4);
|
||||
}
|
||||
}
|
||||
|
||||
.cdk-drag, .add-btn {
|
||||
transition: background-color 0.2s, box-shadow 0.2s;
|
||||
border-radius: 8px;
|
||||
margin: 0 8px 4px 8px;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,16 @@
|
||||
import { ChangeDetectionStrategy, Component, forwardRef, Inject, Input, OnInit, QueryList, TemplateRef, ViewChildren } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
EventEmitter,
|
||||
forwardRef,
|
||||
Inject,
|
||||
Input,
|
||||
OnInit,
|
||||
Output,
|
||||
QueryList,
|
||||
TemplateRef,
|
||||
ViewChildren
|
||||
} from '@angular/core';
|
||||
import { ListingComponent } from '../listing-component.directive';
|
||||
import { Listable, ListingModes } from '../models';
|
||||
import { CdkDrag, CdkDragDrop, CdkDropList } from '@angular/cdk/drag-drop';
|
||||
@ -16,6 +28,7 @@ interface WorkflowColumn<T, K> {
|
||||
|
||||
export interface WorkflowConfig<T, K> {
|
||||
key: string;
|
||||
itemVersionFn: (entity: T) => string;
|
||||
columns: WorkflowColumn<T, K>[];
|
||||
}
|
||||
|
||||
@ -30,23 +43,22 @@ export class WorkflowComponent<T extends Listable, K extends string> implements
|
||||
@Input() headerTemplate?: TemplateRef<unknown>;
|
||||
@Input() @Required() itemTemplate!: TemplateRef<T>;
|
||||
@Input() @Required() config!: WorkflowConfig<T, K>;
|
||||
@Input() @Required() itemHeight!: string;
|
||||
@Input() itemClasses?: { [key: string]: (e: T) => boolean };
|
||||
@Input() addElementIcon?: string;
|
||||
@Input() addElementColumn?: K;
|
||||
@Output() readonly addElement = new EventEmitter<void>();
|
||||
|
||||
dragging = false;
|
||||
sourceColumn?: WorkflowColumn<T, K>;
|
||||
@ViewChildren(CdkDropList) private readonly _dropLists!: QueryList<CdkDropList>;
|
||||
private _existingEntities: { [key: string]: T } = {};
|
||||
|
||||
constructor(
|
||||
@Inject(forwardRef(() => ListingComponent)) private _parent: ListingComponent<T>,
|
||||
private readonly _loadingService: LoadingService
|
||||
) {}
|
||||
|
||||
_itemHeight = 0;
|
||||
|
||||
get itemHeight(): string {
|
||||
return `${this._itemHeight}px`;
|
||||
}
|
||||
|
||||
get listingComponent(): ListingComponent<T> {
|
||||
return this._parent;
|
||||
}
|
||||
@ -106,31 +118,65 @@ export class WorkflowComponent<T extends Listable, K extends string> implements
|
||||
return this._dropLists?.find(list => list.id === id);
|
||||
}
|
||||
|
||||
private _computeItemHeight(): void {
|
||||
const items = document.getElementsByClassName('cdk-drag');
|
||||
if (items.length) {
|
||||
this._itemHeight = items[0].getBoundingClientRect().height;
|
||||
}
|
||||
}
|
||||
|
||||
private _updateConfigItems(entities: T[]) {
|
||||
// Disable updating while dragging
|
||||
if (this.dragging) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO ...
|
||||
this.config.columns.forEach(column => {
|
||||
column.entities = [];
|
||||
});
|
||||
// Remove deleted entities
|
||||
const updatedIds = entities.map(entity => entity.id);
|
||||
for (const id of Object.keys(this._existingEntities)) {
|
||||
if (!updatedIds.includes(id)) {
|
||||
this._removeEntity(this._existingEntities[id]);
|
||||
}
|
||||
}
|
||||
|
||||
// Add or move updated entities
|
||||
entities.forEach(entity => {
|
||||
const column = this._getColumnByKey(entity[this.config.key]);
|
||||
if (column) {
|
||||
column.entities?.push(entity);
|
||||
const shouldAdd = this._shouldAdd(entity);
|
||||
const shouldMove = this._shouldMove(entity);
|
||||
|
||||
if (shouldMove) {
|
||||
this._removeEntity(entity);
|
||||
}
|
||||
|
||||
if (shouldAdd || shouldMove) {
|
||||
this._addEntity(entity);
|
||||
}
|
||||
});
|
||||
|
||||
this._computeItemHeight();
|
||||
// this._computeItemHeight();
|
||||
}
|
||||
|
||||
private _addEntity(entity: T): void {
|
||||
this._existingEntities[entity.id] = entity;
|
||||
const column = this._getColumnByKey(entity[this.config.key] as K);
|
||||
if (column) {
|
||||
if (!column.entities) {
|
||||
column.entities = [];
|
||||
}
|
||||
column.entities.push(entity);
|
||||
}
|
||||
}
|
||||
|
||||
private _removeEntity(entity: T): void {
|
||||
const existingEntity = this._existingEntities[entity.id];
|
||||
const column = this._getColumnByKey(existingEntity[this.config.key] as K);
|
||||
if (column) {
|
||||
const idx = (column.entities as T[]).findIndex(item => item.id === entity.id);
|
||||
column.entities?.splice(idx, 1);
|
||||
}
|
||||
delete this._existingEntities[entity.id];
|
||||
}
|
||||
|
||||
private _shouldMove(entity: T): boolean {
|
||||
const existingEntity = this._existingEntities[entity.id];
|
||||
return existingEntity && this.config.itemVersionFn(entity) !== this.config.itemVersionFn(existingEntity);
|
||||
}
|
||||
|
||||
private _shouldAdd(entity: T): boolean {
|
||||
return !this._existingEntities[entity.id];
|
||||
}
|
||||
|
||||
private _getColumnByKey(key: K): WorkflowColumn<T, K> {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user