mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Download as CSV button on sections
Summary: Adding "Download as CSV" button that exports filtred section data to csv Test Plan: Browser tests Reviewers: paulfitz, dsagal Reviewed By: paulfitz Differential Revision: https://phab.getgrist.com/D2830
This commit is contained in:
18
app/common/ColumnFilterFunc.ts
Normal file
18
app/common/ColumnFilterFunc.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { CellValue } from "app/common/DocActions";
|
||||
import { FilterState, makeFilterState } from "app/common/FilterState";
|
||||
|
||||
export type ColumnFilterFunc = (value: CellValue) => boolean;
|
||||
|
||||
// Returns a filter function for a particular column: the function takes a cell value and returns
|
||||
// whether it's accepted according to the given FilterState.
|
||||
export function makeFilterFunc({ include, values }: FilterState): ColumnFilterFunc {
|
||||
// NOTE: This logic results in complex values and their stringified JSON representations as equivalent.
|
||||
// For example, a TypeError in the formula column and the string '["E","TypeError"]' would be seen as the same.
|
||||
// TODO: This narrow corner case seems acceptable for now, but may be worth revisiting.
|
||||
return (val: CellValue) => (values.has(Array.isArray(val) ? JSON.stringify(val) : val) === include);
|
||||
}
|
||||
|
||||
// Given a JSON string, returns a ColumnFilterFunc
|
||||
export function buildColFilter(filterJson: string | undefined): ColumnFilterFunc | null {
|
||||
return filterJson ? makeFilterFunc(makeFilterState(filterJson)) : null;
|
||||
}
|
||||
33
app/common/FilterState.ts
Normal file
33
app/common/FilterState.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { CellValue } from "app/common/DocActions";
|
||||
|
||||
// Filter object as stored in the db
|
||||
export interface FilterSpec {
|
||||
included?: CellValue[];
|
||||
excluded?: CellValue[];
|
||||
}
|
||||
|
||||
// A more efficient representation of filter state for a column than FilterSpec.
|
||||
export interface FilterState {
|
||||
include: boolean;
|
||||
values: Set<CellValue>;
|
||||
}
|
||||
|
||||
// Creates a FilterState. Accepts spec as a json string or a FilterSpec.
|
||||
export function makeFilterState(spec: string | FilterSpec): FilterState {
|
||||
if (typeof (spec) === 'string') {
|
||||
return makeFilterState((spec && JSON.parse(spec)) || {});
|
||||
}
|
||||
return {
|
||||
include: Boolean(spec.included),
|
||||
values: new Set(spec.included || spec.excluded || []),
|
||||
};
|
||||
}
|
||||
|
||||
// Returns true if state and spec are equivalent, false otherwise.
|
||||
export function isEquivalentFilter(state: FilterState, spec: FilterSpec): boolean {
|
||||
const other = makeFilterState(spec);
|
||||
if (state.include !== other.include) { return false; }
|
||||
if (state.values.size !== other.values.size) { return false; }
|
||||
for (const val of other.values) { if (!state.values.has(val)) { return false; } }
|
||||
return true;
|
||||
}
|
||||
16
app/common/RowFilterFunc.ts
Normal file
16
app/common/RowFilterFunc.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { CellValue } from "app/common/DocActions";
|
||||
import { ColumnFilterFunc } from "app/common/ColumnFilterFunc";
|
||||
|
||||
export type RowFilterFunc<T> = (row: T) => boolean;
|
||||
|
||||
// Builds RowFilter for a single column
|
||||
export function buildRowFilter<T>(
|
||||
getter: RowValueFunc<T> | null,
|
||||
filterFunc: ColumnFilterFunc | null): RowFilterFunc<T> {
|
||||
if (!getter || !filterFunc) {
|
||||
return () => true;
|
||||
}
|
||||
return (rowId: T) => filterFunc(getter(rowId));
|
||||
}
|
||||
|
||||
export type RowValueFunc<T> = (rowId: T) => CellValue;
|
||||
Reference in New Issue
Block a user