2020-10-02 15:10:00 +00:00
|
|
|
/**
|
|
|
|
* Implements a cache of ACIndex objects for columns in Grist table.
|
|
|
|
*
|
|
|
|
* The getColACIndex() function returns the corresponding ACIndex, building it if needed and
|
|
|
|
* caching for subsequent calls. Any change to the column or a value in it invalidates the cache.
|
|
|
|
*
|
|
|
|
* It is available as tableData.columnACIndexes.
|
|
|
|
*
|
2021-08-12 18:06:40 +00:00
|
|
|
* It is currently used for auto-complete in the ReferenceEditor and ReferenceListEditor widgets.
|
2020-10-02 15:10:00 +00:00
|
|
|
*/
|
|
|
|
import {ACIndex, ACIndexImpl} from 'app/client/lib/ACIndex';
|
2021-04-20 21:57:45 +00:00
|
|
|
import {ColumnCache} from 'app/client/models/ColumnCache';
|
2020-10-02 15:10:00 +00:00
|
|
|
import {UserError} from 'app/client/models/errors';
|
|
|
|
import {TableData} from 'app/client/models/TableData';
|
2021-04-20 21:57:45 +00:00
|
|
|
import {localeCompare, nativeCompare} from 'app/common/gutil';
|
2020-10-02 15:10:00 +00:00
|
|
|
import {BaseFormatter} from 'app/common/ValueFormatter';
|
|
|
|
|
|
|
|
export interface ICellItem {
|
|
|
|
rowId: number|'new';
|
|
|
|
text: string; // Formatted cell text.
|
|
|
|
cleanText: string; // Trimmed lowercase text for searching.
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export class ColumnACIndexes {
|
2021-04-20 21:57:45 +00:00
|
|
|
private _columnCache = new ColumnCache<ACIndex<ICellItem>>(this._tableData);
|
2020-10-02 15:10:00 +00:00
|
|
|
|
2021-04-20 21:57:45 +00:00
|
|
|
constructor(private _tableData: TableData) {}
|
2020-10-02 15:10:00 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the column index for the given column, using a cached one if available.
|
|
|
|
* The formatter should be created using field.createVisibleColFormatter(). It's assumed that
|
|
|
|
* getColACIndex() is called for the same column with the the same formatter.
|
|
|
|
*/
|
|
|
|
public getColACIndex(colId: string, formatter: BaseFormatter): ACIndex<ICellItem> {
|
2021-04-20 21:57:45 +00:00
|
|
|
return this._columnCache.getValue(colId, () => this._buildColACIndex(colId, formatter));
|
2020-10-02 15:10:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private _buildColACIndex(colId: string, formatter: BaseFormatter): ACIndex<ICellItem> {
|
|
|
|
const rowIds = this._tableData.getRowIds();
|
|
|
|
const valColumn = this._tableData.getColValues(colId);
|
|
|
|
if (!valColumn) {
|
|
|
|
throw new UserError(`Invalid column ${this._tableData.tableId}.${colId}`);
|
|
|
|
}
|
|
|
|
const items: ICellItem[] = valColumn.map((val, i) => {
|
|
|
|
const rowId = rowIds[i];
|
|
|
|
const text = formatter.formatAny(val);
|
|
|
|
const cleanText = text.trim().toLowerCase();
|
|
|
|
return {rowId, text, cleanText};
|
|
|
|
});
|
|
|
|
items.sort(itemCompare);
|
|
|
|
return new ACIndexImpl(items);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function itemCompare(a: ICellItem, b: ICellItem) {
|
2021-03-13 02:25:44 +00:00
|
|
|
return localeCompare(a.cleanText, b.cleanText) ||
|
|
|
|
localeCompare(a.text, b.text) ||
|
2020-10-02 15:10:00 +00:00
|
|
|
nativeCompare(a.rowId, b.rowId);
|
|
|
|
}
|