import {ColumnGetter, ColumnGetters, ColumnGettersByColId} from 'app/common/ColumnGetters'; import * as gristTypes from 'app/common/gristTypes'; import {safeJsonParse} from 'app/common/gutil'; import {choiceGetter} from 'app/common/SortFunc'; import {Sort} from 'app/common/SortSpec'; import {BulkColValues} from 'app/plugin/GristData'; /** * * An implementation of ColumnGetters for the server, currently * drawing on the data and metadata prepared for CSV export. * */ export class ServerColumnGetters implements ColumnGetters, ColumnGettersByColId { private _rowIndices: Map; private _colIndices: Map; constructor(rowIds: number[], private _dataByColId: BulkColValues, private _columns: any[]) { this._rowIndices = new Map(rowIds.map((rowId, index) => [rowId, index] as [number, number])); this._colIndices = new Map(_columns.map(col => [col.id, col.colId] as [number, string])); } public getColGetter(colSpec: Sort.ColSpec): ColumnGetter | null { const colRef = Sort.getColRef(colSpec); if (typeof colRef !== 'number') { // colRef might be string for virtual tables, but we don't support them here. throw new Error(`Unsupported colRef type: ${typeof colRef}`); } const colId = this._colIndices.get(colRef); if (colId === undefined) { return null; } let getter = this.getColGetterByColId(colId); if (!getter) { return null; } const details = Sort.specToDetails(colSpec); if (details.orderByChoice) { const rowModel = this._columns.find(c => c.id == colRef); if (rowModel?.type === 'Choice') { const choices: string[] = safeJsonParse(rowModel.widgetOptions, {}).choices || []; getter = choiceGetter(getter, choices); } } return getter; } public getManualSortGetter(): ((rowId: number) => any) | null { const manualSortCol = this._columns.find(c => c.colId === gristTypes.MANUALSORT); if (!manualSortCol) { return null; } return this.getColGetter(manualSortCol.id); } public getColGetterByColId(colId: string): ColumnGetter | null { if (colId === "id") { return (rowId: number) => rowId; } const col = this._dataByColId[colId]; if (!col) { return null; } return (rowId: number) => { const idx = this._rowIndices.get(rowId); if (idx === undefined) { return null; } return col[idx]; }; } }