UNPKG

gp-crm-ui

Version:

Модуль компонентов UI Имя модуля: `gp-crm-ui`

215 lines (174 loc) 6.15 kB
import { Component, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core'; // Сенсор import { ResizeSensor } from 'css-element-queries'; // Интерфейсы import { IColumn, IRowCache, ISize, ITableOptions } from '../../interfaces'; // Контент таблицы @Component({ selector: 'crm-table-content', templateUrl: './crm-table-content.component.html', styleUrls: ['./crm-table-content.component.scss'] }) export class CrmTableContentComponent implements OnChanges, OnInit, OnDestroy { // Строки @Input() public rows: any[]; // Конфигурация таблицы @Input() public options: ITableOptions; // Закрепленные столбцы @Input() public pinnedColumns: IColumn[]; // Ширина области контента закрепленных столбцов @Input() public pinnedCanvasWidth: number; // Обычные столбцы @Input() public defaultColumns: IColumn[]; // Ширина области контента обычных столбцов @Input() public defaultCanvasWidth: number; // Смещение области контента в области отображения @Input() public offsetLeft: number; // Смещение области контента в области отображения @Input() public offsetTop: number; // Событие изменения размера defaultView @Output() public resizedView = new EventEmitter<ISize>(); // Событие изменения размера defaultCanvas @Output() public resizedCanvas = new EventEmitter<ISize>(); // Ссылка на область отображения закрепленных столбцов @ViewChild('pinnedView') public pinnedView: ElementRef; // Ссылка на область отображения обычных столбцов @ViewChild('defaultView') public defaultView: ElementRef; // Ссылка на область контента обычных столбцов @ViewChild('defaultCanvas') public defaultCanvas: ElementRef; // Сенсор изменения размера defaultView private resizeSensorView: any; // Сенсор изменения размера defaultCanvas private resizeSensorCanvas: any; // Высота строки по умолчанию private readonly DEFAULT_ROW_HEIGHT: number = 32; private get defaultRowHeight(): number { return (this.options && this.options.defaultRowHeight) || this.DEFAULT_ROW_HEIGHT; } // Кеш высот строк private readonly _rowsCache: WeakMap<object, IRowCache> = new WeakMap<object, IRowCache>(); public readonly rowsCache: WeakMap<object, number> = new WeakMap<object, number>(); // Событие изменения высоты ячейки public readonly emitterChangeHeight: EventEmitter<any> = new EventEmitter<any>(); // -------------------------------------------------------------------------- // Обновить смещения private updateOffset(): void { const defaultView = this.defaultView && this.defaultView.nativeElement; const pinnedView = this.pinnedView && this.pinnedView.nativeElement; if (defaultView) { defaultView.scrollLeft = this.offsetLeft; defaultView.scrollTop = this.offsetTop; } if (pinnedView) { pinnedView.scrollTop = this.offsetTop; } } // Обновить кеш строк private updateRowsCache(): void { const rows = this.rows || []; rows.forEach((row: any): void => { if (!this.rowsCache.has(row)) { this.rowsCache.set(row, this.defaultRowHeight); } }); } // Расчет высоты строки private calcRowHeight(row: any): void { const rowCache = this._rowsCache.get(row); if (rowCache) { const heightCells = Object.keys(rowCache) .map((key: string): number => rowCache[key].height); const height = Math.max(...heightCells); this.rowsCache.set(row, height); } } // Обработчик изменения размера ячейки private onChangeHeight(event: any): void { const row = event.row; const field = event.column.field; const height = event.height || this.defaultRowHeight; if (!this._rowsCache.has(row)) { this._rowsCache.set(row, {}); } const rowCache = this._rowsCache.get(row); rowCache[field] = { field, height }; this.calcRowHeight(row); } // Обработчик изменения размера defaultView public onResizedView(): void { const el = this.defaultView.nativeElement; this.resizedView.emit({ width: el.offsetWidth, height: el.offsetHeight }); } // Обработчик изменения размера defaultCanvas public onResizedCanvas(): void { const el = this.defaultCanvas.nativeElement; this.resizedCanvas.emit({ width: el.offsetWidth, height: el.offsetHeight }); } // Добавить сенсоры private addSensors(): void { this.resizeSensorView = new ResizeSensor( this.defaultView.nativeElement, this.onResizedView.bind(this) ); this.resizeSensorCanvas = new ResizeSensor( this.defaultCanvas.nativeElement, this.onResizedCanvas.bind(this) ); } // Удалить сенсоры private removeSensors(): void { if (this.resizeSensorView) { this.resizeSensorView.detach(); } if (this.resizeSensorCanvas) { this.resizeSensorCanvas.detach(); } } // -------------------------------------------------------------------------- // HOOKS // Инициализация public ngOnInit(): void { this.emitterChangeHeight.subscribe({ next: this.onChangeHeight.bind(this) }); // Добавить сенсоры this.addSensors(); // Пропуск кадра setTimeout((): void => { this.onResizedView(); this.onResizedCanvas(); }); } // Уничтожение public ngOnDestroy(): void { this.removeSensors(); } // Изменение входных параметров public ngOnChanges(changes: SimpleChanges): void { if (changes.offsetLeft || changes.offsetTop) { this.updateOffset(); } if (changes.rows) { this.updateRowsCache(); } } }