Refresh items, add btn, some css fixes

This commit is contained in:
Adina Țeudan 2021-09-28 00:39:03 +03:00
parent 5973631a1d
commit 5d0bb11c65
4 changed files with 100 additions and 30 deletions

View File

@ -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;

View File

@ -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>

View File

@ -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);
}
}

View File

@ -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> {