support filtering by document ID (#668)

This commit is contained in:
Sidney Alcantara
2022-06-08 17:34:18 +10:00
parent 2a1209f8cb
commit 456676d10c
8 changed files with 82 additions and 30 deletions

View File

@@ -29,16 +29,17 @@ export default function ColumnSelect({
...props
}: IColumnSelectProps & Omit<MultiSelectProps<string>, "options">) {
const [tableColumnsOrdered] = useAtom(tableColumnsOrderedAtom, tableScope);
const options = (
filterColumns
const options =
props.options ||
(filterColumns
? tableColumnsOrdered.filter(filterColumns)
: tableColumnsOrdered
).map(({ key, name, type, index }) => ({
value: key,
label: name,
type,
index,
}));
).map(({ key, name, type, index }) => ({
value: key,
label: name,
type,
index,
}));
return (
<MultiSelect

View File

@@ -10,6 +10,7 @@ import {
} from "@mui/material";
import ColumnSelect from "@src/components/Table/ColumnSelect";
import FieldSkeleton from "@src/components/SideDrawer/FieldSkeleton";
import IdFilterInput from "./IdFilterInput";
import type { useFilterInputs } from "./useFilterInputs";
import { getFieldType, getFieldProp } from "@src/components/fields";
@@ -97,15 +98,21 @@ export default function FilterInputs({
<Suspense fallback={<FieldSkeleton />}>
{columnType &&
createElement(getFieldProp("SideDrawerField", columnType), {
column: selectedColumn,
_rowy_ref: {},
value: query.value,
onChange: (value: any) => {
setQuery((query) => ({ ...query, value }));
},
disabled,
})}
createElement(
query.key === "_rowy_ref.id"
? IdFilterInput
: getFieldProp("filter.customInput" as any, columnType) ||
getFieldProp("SideDrawerField", columnType),
{
column: selectedColumn,
_rowy_ref: {},
value: query.value,
onChange: (value: any) => {
setQuery((query) => ({ ...query, value }));
},
disabled,
}
)}
</Suspense>
</>
)}

View File

@@ -65,6 +65,7 @@ export default function FiltersPopover({
</ButtonWithStatus>
{appliedFilters.map((filter) => {
const fieldName = filter.key === "_rowy_ref.id" ? "ID" : filter.key;
const operator = (availableFilters?.operators ?? []).find(
(f) => f.value === filter.operator
);
@@ -78,8 +79,8 @@ export default function FiltersPopover({
<Chip
key={filter.key}
label={
<Typography variant="inherit">
{filter.key}{" "}
<Typography variant="inherit" component="span">
{fieldName}{" "}
<Typography
variant="inherit"
display="inline"

View File

@@ -0,0 +1,26 @@
import { TextField } from "@mui/material";
export interface IIdFilterInputProps {
value: string;
onChange: (value: string) => void;
}
export default function IdFilterInput({
value,
onChange,
}: IIdFilterInputProps) {
return (
<TextField
aria-label="Filter by this ID"
onChange={(e) => onChange(e.target.value)}
value={value}
fullWidth
sx={{
"& .MuiFilledInput-input": {
typography: "caption",
fontFamily: "mono",
},
}}
/>
);
}

View File

@@ -2,6 +2,7 @@ import { useState } from "react";
import { find } from "lodash-es";
import { getFieldType, getFieldProp } from "@src/components/fields";
import { FieldType } from "@src/constants/fields";
import type { ColumnConfig, TableFilter } from "@src/types/table";
import type { IFieldConfig } from "@src/components/fields/types";
@@ -22,6 +23,15 @@ export const useFilterInputs = (
index: c.index,
}));
// Always allow IDs to be filterable
filterColumns.push({
value: "_rowy_ref.id",
label: "Document ID",
type: FieldType.id,
key: "_rowy_ref.id",
index: filterColumns.length,
});
// State for filter inputs
const [query, setQuery] = useState<TableFilter | typeof INITIAL_QUERY>(
defaultQuery || INITIAL_QUERY
@@ -30,6 +40,11 @@ export const useFilterInputs = (
// When the user sets a new column, automatically set the operator and value
const handleChangeColumn = (value: string | null) => {
if (value === "_rowy_ref.id") {
setQuery({ key: "_rowy_ref.id", operator: "id-equal", value: "" });
return;
}
const column = find(filterColumns, ["key", value]);
if (column) {
@@ -47,9 +62,12 @@ export const useFilterInputs = (
// Get the column config
const selectedColumn = find(filterColumns, ["key", query?.key]);
// Get available filters from selected column type
const availableFilters: IFieldConfig["filter"] = selectedColumn
? getFieldProp("filter", getFieldType(selectedColumn))
: undefined;
const availableFilters: IFieldConfig["filter"] =
query?.key === "_rowy_ref.id"
? { operators: [{ value: "id-equal", label: "is" }] }
: selectedColumn
? getFieldProp("filter", getFieldType(selectedColumn))
: undefined;
return {
filterColumns,

View File

@@ -36,7 +36,7 @@ export interface IFieldConfig {
settingsValidator?: (config: Record<string, any>) => Record<string, string>;
filter?: {
operators: IFilterOperator[];
customInput?: React.ComponentType<IFiltersProps>;
customInput?: React.ComponentType<{ onChange: (value: any) => void }>;
defaultValue?: any;
valueFormatter?: (value: any) => string;
};
@@ -101,12 +101,6 @@ export interface ISettingsProps {
errors: Record<string, any>;
}
// TODO: WRITE TYPES
export interface IFiltersProps {
onChange: (key: string) => (value: any) => void;
[key: string]: any;
}
export interface IFilterOperator {
value: TableFilter["operator"];
label: string;

View File

@@ -22,6 +22,7 @@ import {
Query,
QueryConstraint,
WhereFilterOp,
documentId,
} from "firebase/firestore";
import { useErrorHandler } from "react-error-boundary";
@@ -358,6 +359,9 @@ export const tableFiltersToFirestoreFilters = (filters: TableFilter[]) => {
firestoreFilters.push(where(filter.key, ">=", startDate));
firestoreFilters.push(where(filter.key, "<=", endDate));
continue;
} else if (filter.operator === "id-equal") {
firestoreFilters.push(where(documentId(), "==", filter.value));
continue;
}
firestoreFilters.push(

View File

@@ -152,7 +152,8 @@ export type TableFilter = {
| "date-after"
| "date-before-equal"
| "date-after-equal"
| "time-minute-equal";
| "time-minute-equal"
| "id-equal";
value: any;
};