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 listingMode$: Observable<ListingMode>;
|
||||||
readonly routerLinkFn?: (entity: T) => string | string[];
|
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 tableColumnConfigs: readonly TableColumnConfig<T>[];
|
||||||
abstract readonly tableHeaderLabel: string;
|
abstract readonly tableHeaderLabel: string;
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
[class.list-source]="isSource(column)"
|
[class.list-source]="isSource(column)"
|
||||||
[style.--color]="column.color"
|
[style.--color]="column.color"
|
||||||
class="column">
|
class="column">
|
||||||
<div class="heading">{{ column.label | translate }} ({{column.entities.length}})</div>
|
<div class="heading">{{ column.label | translate }} ({{column.entities?.length || 0}})</div>
|
||||||
<div
|
<div
|
||||||
(cdkDropListDropped)="move($event)"
|
(cdkDropListDropped)="move($event)"
|
||||||
[cdkDropListData]="column.entities"
|
[cdkDropListData]="column.entities"
|
||||||
@ -25,6 +25,9 @@
|
|||||||
<div *cdkDragPlaceholder [style.--height]="itemHeight"></div>
|
<div *cdkDragPlaceholder [style.--height]="itemHeight"></div>
|
||||||
<ng-container *ngTemplateOutlet="itemTemplate; context: { entity: entity }"></ng-container>
|
<ng-container *ngTemplateOutlet="itemTemplate; context: { entity: entity }"></ng-container>
|
||||||
</div>
|
</div>
|
||||||
|
<div (click)="addElement.emit()" *ngIf="column.key === addElementColumn" class="add-btn">
|
||||||
|
<mat-icon [svgIcon]="addElementIcon"></mat-icon>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -38,8 +38,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
> .heading {
|
> .heading {
|
||||||
margin-left: 18px;
|
margin: 0 18px 16px 18px;
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.dragging {
|
&.dragging {
|
||||||
@ -60,7 +59,7 @@
|
|||||||
var(--iqser-white) 8px
|
var(--iqser-white) 8px
|
||||||
);
|
);
|
||||||
|
|
||||||
> .heading, ::ng-deep.cdk-drag > * {
|
> .heading, .add-btn, ::ng-deep.cdk-drag > * {
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,11 +75,9 @@
|
|||||||
min-height: calc(100% - 36px);
|
min-height: calc(100% - 36px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.cdk-drag {
|
.cdk-drag {
|
||||||
background-color: var(--iqser-white);
|
background-color: var(--iqser-white);
|
||||||
transition: background-color 0.2s, box-shadow 0.2s;
|
|
||||||
border-radius: 8px;
|
|
||||||
margin: 0 8px 4px 8px;
|
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
@ -93,6 +90,31 @@
|
|||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: var(--iqser-grey-6);
|
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);
|
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 { ListingComponent } from '../listing-component.directive';
|
||||||
import { Listable, ListingModes } from '../models';
|
import { Listable, ListingModes } from '../models';
|
||||||
import { CdkDrag, CdkDragDrop, CdkDropList } from '@angular/cdk/drag-drop';
|
import { CdkDrag, CdkDragDrop, CdkDropList } from '@angular/cdk/drag-drop';
|
||||||
@ -16,6 +28,7 @@ interface WorkflowColumn<T, K> {
|
|||||||
|
|
||||||
export interface WorkflowConfig<T, K> {
|
export interface WorkflowConfig<T, K> {
|
||||||
key: string;
|
key: string;
|
||||||
|
itemVersionFn: (entity: T) => string;
|
||||||
columns: WorkflowColumn<T, K>[];
|
columns: WorkflowColumn<T, K>[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,23 +43,22 @@ export class WorkflowComponent<T extends Listable, K extends string> implements
|
|||||||
@Input() headerTemplate?: TemplateRef<unknown>;
|
@Input() headerTemplate?: TemplateRef<unknown>;
|
||||||
@Input() @Required() itemTemplate!: TemplateRef<T>;
|
@Input() @Required() itemTemplate!: TemplateRef<T>;
|
||||||
@Input() @Required() config!: WorkflowConfig<T, K>;
|
@Input() @Required() config!: WorkflowConfig<T, K>;
|
||||||
|
@Input() @Required() itemHeight!: string;
|
||||||
@Input() itemClasses?: { [key: string]: (e: T) => boolean };
|
@Input() itemClasses?: { [key: string]: (e: T) => boolean };
|
||||||
|
@Input() addElementIcon?: string;
|
||||||
|
@Input() addElementColumn?: K;
|
||||||
|
@Output() readonly addElement = new EventEmitter<void>();
|
||||||
|
|
||||||
dragging = false;
|
dragging = false;
|
||||||
sourceColumn?: WorkflowColumn<T, K>;
|
sourceColumn?: WorkflowColumn<T, K>;
|
||||||
@ViewChildren(CdkDropList) private readonly _dropLists!: QueryList<CdkDropList>;
|
@ViewChildren(CdkDropList) private readonly _dropLists!: QueryList<CdkDropList>;
|
||||||
|
private _existingEntities: { [key: string]: T } = {};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(forwardRef(() => ListingComponent)) private _parent: ListingComponent<T>,
|
@Inject(forwardRef(() => ListingComponent)) private _parent: ListingComponent<T>,
|
||||||
private readonly _loadingService: LoadingService
|
private readonly _loadingService: LoadingService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
_itemHeight = 0;
|
|
||||||
|
|
||||||
get itemHeight(): string {
|
|
||||||
return `${this._itemHeight}px`;
|
|
||||||
}
|
|
||||||
|
|
||||||
get listingComponent(): ListingComponent<T> {
|
get listingComponent(): ListingComponent<T> {
|
||||||
return this._parent;
|
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);
|
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[]) {
|
private _updateConfigItems(entities: T[]) {
|
||||||
// Disable updating while dragging
|
// Disable updating while dragging
|
||||||
if (this.dragging) {
|
if (this.dragging) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO ...
|
// Remove deleted entities
|
||||||
this.config.columns.forEach(column => {
|
const updatedIds = entities.map(entity => entity.id);
|
||||||
column.entities = [];
|
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 => {
|
entities.forEach(entity => {
|
||||||
const column = this._getColumnByKey(entity[this.config.key]);
|
const shouldAdd = this._shouldAdd(entity);
|
||||||
if (column) {
|
const shouldMove = this._shouldMove(entity);
|
||||||
column.entities?.push(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> {
|
private _getColumnByKey(key: K): WorkflowColumn<T, K> {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user