mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
3112433a58
Summary: Dropdown conditions let you specify a predicate formula that's used to filter choices and references in their respective autocomplete dropdown menus. Test Plan: Python and browser tests (WIP). Reviewers: jarek, paulfitz Reviewed By: jarek Subscribers: dsagal, paulfitz Differential Revision: https://phab.getgrist.com/D4235
66 lines
2.4 KiB
TypeScript
66 lines
2.4 KiB
TypeScript
/**
|
|
* 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.
|
|
*
|
|
* It is currently used for auto-complete in the ReferenceEditor and ReferenceListEditor widgets.
|
|
*/
|
|
import {ACIndex, ACIndexImpl, normalizeText} from 'app/client/lib/ACIndex';
|
|
import {ColumnCache} from 'app/client/models/ColumnCache';
|
|
import {UserError} from 'app/client/models/errors';
|
|
import {TableData} from 'app/client/models/TableData';
|
|
import {localeCompare, nativeCompare} from 'app/common/gutil';
|
|
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 {
|
|
private _columnCache = new ColumnCache<ACIndex<ICellItem>>(this._tableData);
|
|
|
|
constructor(private _tableData: TableData) {}
|
|
|
|
/**
|
|
* Returns the column index for the given column, using a cached one if available.
|
|
* The formatter should be created using field.visibleColFormatter(). It's assumed that
|
|
* getColACIndex() is called for the same column with the the same formatter.
|
|
*/
|
|
public getColACIndex(colId: string, formatter: BaseFormatter): ACIndex<ICellItem> {
|
|
return this._columnCache.getValue(colId, () => this.buildColACIndex(colId, formatter));
|
|
}
|
|
|
|
public buildColACIndex(
|
|
colId: string,
|
|
formatter: BaseFormatter,
|
|
filter?: (item: ICellItem) => boolean
|
|
): 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 = normalizeText(text);
|
|
return {rowId, text, cleanText};
|
|
})
|
|
.filter((item) => filter?.(item) ?? true)
|
|
.sort(itemCompare);
|
|
return new ACIndexImpl(items);
|
|
}
|
|
}
|
|
|
|
function itemCompare(a: ICellItem, b: ICellItem) {
|
|
return localeCompare(a.cleanText, b.cleanText) ||
|
|
localeCompare(a.text, b.text) ||
|
|
nativeCompare(a.rowId, b.rowId);
|
|
}
|