mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-20 09:04:08 +00:00
7a0cd6c2b4
Summary: Makes filter counts take other column filters into account. - Changes the summaries rows to reflect hidden rows: - hidden rows are added to the `Other Values` summary - show the unique number of other values as `Other Values (12)` - Also, adds a sort button to the column filter menu Test Plan: Adds browser test. Reviewers: paulfitz, jarek Reviewed By: jarek Differential Revision: https://phab.getgrist.com/D2861
67 lines
2.4 KiB
TypeScript
67 lines
2.4 KiB
TypeScript
import { ColumnFilter } from "app/client/models/ColumnFilter";
|
|
import { localeCompare, nativeCompare } from "app/common/gutil";
|
|
import { CellValue } from "app/plugin/GristData";
|
|
import { Computed, Disposable, Observable } from "grainjs";
|
|
import escapeRegExp = require("lodash/escapeRegExp");
|
|
|
|
const MAXIMUM_SHOWN_FILTER_ITEMS = 500;
|
|
|
|
export interface IFilterCount {
|
|
label: string;
|
|
count: number;
|
|
}
|
|
|
|
type ICompare<T> = (a: T, b: T) => number
|
|
|
|
export class ColumnFilterMenuModel extends Disposable {
|
|
|
|
public readonly searchValue = Observable.create(this, '');
|
|
|
|
public readonly isSortedByCount = Observable.create(this, false);
|
|
|
|
// computes a set of all keys that matches the search text.
|
|
public readonly filterSet = Computed.create(this, this.searchValue, (_use, searchValue) => {
|
|
const searchRegex = new RegExp(escapeRegExp(searchValue), 'i');
|
|
return new Set(
|
|
this._valueCount
|
|
.filter(([_, {count}]) => count)
|
|
.filter(([_, {label}]) => searchRegex.test(label))
|
|
.map(([key]) => key)
|
|
);
|
|
});
|
|
|
|
// computes the sorted array of all values (ie: pair of key and IFilterCount) that matches the search text.
|
|
public readonly filteredValues = Computed.create(
|
|
this, this.filterSet, this.isSortedByCount,
|
|
(_use, filter, isSortedByCount) => {
|
|
const comparator: ICompare<[CellValue, IFilterCount]> = isSortedByCount ?
|
|
(a, b) => nativeCompare(b[1].count, a[1].count) :
|
|
(a, b) => localeCompare(a[1].label, b[1].label);
|
|
return this._valueCount
|
|
.filter(([key]) => filter.has(key))
|
|
.sort(comparator);
|
|
}
|
|
);
|
|
|
|
// computes the array of all values that does NOT matches the search text
|
|
public readonly otherValues = Computed.create(this, this.filterSet, (_use, filter) => {
|
|
return this._valueCount.filter(([key]) => !filter.has(key));
|
|
});
|
|
|
|
// computes the array of keys that matches the search text
|
|
public readonly filteredKeys = Computed.create(this, this.filterSet, (_use, filter) => {
|
|
return this._valueCount
|
|
.filter(([key]) => filter.has(key))
|
|
.map(([key]) => key);
|
|
});
|
|
|
|
public readonly valuesBeyondLimit = Computed.create(this, this.filteredValues, (_use, filteredValues) => {
|
|
return filteredValues.slice(this.limitShown);
|
|
});
|
|
|
|
constructor(public columnFilter: ColumnFilter, private _valueCount: Array<[CellValue, IFilterCount]>,
|
|
public limitShown: number = MAXIMUM_SHOWN_FILTER_ITEMS) {
|
|
super();
|
|
}
|
|
}
|