import { Column, GridOption, OnKeyDownEventArgs, SlickDataView, SlickEventData, SlickGrid, } from "slickgrid"; import { elementNotVisible } from "shared/lib/dom"; import { localStore } from "shared/lib/localStrore"; import { IColumnPicker, IDownloadManager, IEditedRow, IFilter, IGrouping, IHotKeysBehavior, IObserver, IPrinter, ISlickRow, ISlickTable, ITotalCalculator, } from "shared/model/types"; import { getOnKeyDownCallback } from "../../../lib"; import { DownloadManager } from "../csvDownloadManager"; import { WithoutFilter } from "../filters"; import { WithoutHotKeys } from "../hotKeys"; import { DefaultPrinter } from "../printer"; export class SlickTable implements ISlickTable { public columnPicker: IColumnPicker | null = null; public copiedRows: (ISlickRow & IEditedRow)[] = []; public downloadManager: IDownloadManager = new DownloadManager(); public filter: IFilter = new WithoutFilter(); public readonly hotKeysBehavior: IHotKeysBehavior = new WithoutHotKeys(); public readonly id: string; public readonly name: string; public totalCalculator?: ITotalCalculator; public readonly summaryColumnIds: string[] = []; private _grid: SlickGrid | null = null; private _grouping: IGrouping = {}; private _isActive = false; private _isEdited = false; private _lastActiveCell = { row: 0, cell: 0 }; // to return to the last active cell after saving private readonly _observers: IObserver[] = []; private _printer: IPrinter = new DefaultPrinter(); constructor(args: { columnPicker?: IColumnPicker; downloadManager?: IDownloadManager; filter?: IFilter; hotKeys?: IHotKeysBehavior; id: string; name?: string; printer?: IPrinter; summaryColumnIds?: string[]; totalCalculator?: ITotalCalculator; }) { const { columnPicker, downloadManager, filter, hotKeys, id, name, printer, summaryColumnIds, totalCalculator, } = args; this.id = id; this.name = name || ""; if (columnPicker) this.columnPicker = columnPicker; if (downloadManager) this.downloadManager = downloadManager; if (filter) { this.filter = filter; this.filter.tableId = id; this.filter.args = { columnFilters: localStore.columnFilters.get(this.id), }; } if (hotKeys) this.hotKeysBehavior = hotKeys; if (printer) this.printer = printer; if (summaryColumnIds) this.summaryColumnIds = summaryColumnIds; if (totalCalculator) this.totalCalculator = totalCalculator; } public createGrid( dataView: SlickDataView, columns: Column[], options: GridOption, ): SlickGrid { this.reset(); const grid = new SlickGrid(`#${this.id}`, dataView, columns, options); this.grid = grid; grid.onKeyDown.subscribe(getOnKeyDownCallback(grid)); this.filter.register(grid, this.id); return this.grid; } public handleKeyboardEvent(event: SlickEventData): void { if (elementNotVisible(`#${this.id}`)) return; this.hotKeysBehavior.handleKeyboardEvent(event, this); } public get grid(): SlickGrid | null { return this._grid; } public get grouping(): IGrouping { return this._grouping; } public get isEdited(): boolean { return this._isEdited; } private set grid(grid: SlickGrid | null) { this._grid = grid; } public set grouping(grouping: IGrouping) { this._grouping = { ...this._grouping, ...grouping }; if (!this.grid) return; const dataView = this.grid.getData(); if (this.grouping.isGrouped) { dataView.setGrouping(this.grouping.groups || []); } else { dataView.setGrouping([]); } } public set isEdited(isEdited: boolean) { this._isEdited = isEdited; this.notifyObservers(); } public set printer(printer: IPrinter) { this._printer = printer; } public get printer(): IPrinter { return this._printer; } public get isActive(): boolean { return this._isActive; } public set isActive(isActive: boolean) { this._isActive = isActive; } public get lastActiveSell() { return this._lastActiveCell; } public set lastActiveSell(cell: { row: number; cell: number }) { this._lastActiveCell = cell; } public resizeCanvas(): void { console.log(""); // doesn't resize without this code line O_o this.grid?.resizeCanvas(); } public registerObservers(observer: IObserver): void { if (!~this._observers.indexOf(observer)) { this._observers.push(observer); } } public notifyObservers(): void { for (const observer of this._observers) { observer(this); } } public deleteObserver(observer: IObserver): void { const index = this._observers.indexOf(observer); this._observers.splice(index, 1); } public reset(): void { this.grid?.onKeyDown.unsubscribe(getOnKeyDownCallback(this.grid)); if (this.grid?.getSelectionModel()) { this.grid.setSelectedRows([]); } this.hotKeysBehavior.resetQueue(); this.isEdited = false; this.isActive = false; this.grid = null; } }