update date & time filter operators for clarity

This commit is contained in:
Sidney Alcantara
2022-06-29 15:03:30 +10:00
parent 28c1d678f2
commit c856211cfa
7 changed files with 96 additions and 25 deletions

View File

@@ -1,16 +1,21 @@
import { Suspense, createElement } from "react";
import { ErrorBoundary } from "react-error-boundary";
import {
Grid,
MenuItem,
ListItemText,
Divider,
ListSubheader,
Typography,
TextField,
InputLabel,
} from "@mui/material";
import ColumnSelect from "@src/components/Table/ColumnSelect";
import FieldSkeleton from "@src/components/SideDrawer/FieldSkeleton";
import IdFilterInput from "./IdFilterInput";
import { InlineErrorFallback } from "@src/components/ErrorFallback";
import type { useFilterInputs } from "./useFilterInputs";
import { getFieldType, getFieldProp } from "@src/components/fields";
@@ -30,6 +35,45 @@ export default function FilterInputs({
}: IFilterInputsProps) {
const columnType = selectedColumn ? getFieldType(selectedColumn) : null;
const operators = availableFilters?.operators ?? [];
const renderedOperatorItems = operators.map((operator) => (
<MenuItem key={operator.value} value={operator.value}>
<ListItemText style={{ flexShrink: 0 }}>{operator.label}</ListItemText>
{operator.secondaryLabel && (
<Typography
variant="inherit"
color="text.disabled"
sx={{ overflow: "hidden", textOverflow: "ellipsis", ml: 1 }}
>
&nbsp;{operator.secondaryLabel}
</Typography>
)}
</MenuItem>
));
// Insert ListSubheader components in between groups of operators
for (let i = 0; i < operators.length; i++) {
if (!operators[i].group) continue;
if (i === 0 || operators[i - 1].group !== operators[i].group) {
renderedOperatorItems.splice(
i === 0 ? 0 : i + 1,
0,
<ListSubheader key={operators[i].group}>
{operators[i].group}
</ListSubheader>
);
if (i > 0)
renderedOperatorItems.splice(
i + 1,
0,
<Divider key={`divider-${operators[i].group}`} variant="middle" />
);
}
}
return (
<Grid container spacing={2} sx={{ mb: 3 }}>
<Grid item xs={4}>
@@ -65,29 +109,13 @@ export default function FilterInputs({
<MenuItem disabled value="" style={{ display: "none" }}>
Select operator
</MenuItem>
{availableFilters?.operators.map((operator) => (
<MenuItem key={operator.value} value={operator.value}>
<ListItemText style={{ flexShrink: 0 }}>
{operator.label}
</ListItemText>
{operator.secondaryLabel && (
<Typography
variant="inherit"
color="text.disabled"
style={{ overflow: "hidden", textOverflow: "ellipsis" }}
>
&nbsp;{operator.secondaryLabel}
</Typography>
)}
</MenuItem>
))}
{renderedOperatorItems}
</TextField>
</Grid>
<Grid item xs={4}>
<Grid item xs={4} key={query.key + query.operator}>
{query.key && query.operator && (
<>
<ErrorBoundary FallbackComponent={InlineErrorFallback}>
<InputLabel
variant="filled"
id={`filters-label-${query.key}`}
@@ -111,10 +139,11 @@ export default function FilterInputs({
setQuery((query) => ({ ...query, value }));
},
disabled,
operator: query.operator,
}
)}
</Suspense>
</>
</ErrorBoundary>
)}
</Grid>
</Grid>

View File

@@ -76,7 +76,7 @@ export default function FiltersPopover({
const formattedValue = availableFilters?.valueFormatter
? availableFilters.valueFormatter(filter.value)
: filter.value;
: filter.value.toString();
return (
<Chip

View File

@@ -0,0 +1,14 @@
import { IFilterCustomInputProps } from "@src/components/fields/types";
import DateTimeInput from "./SideDrawerField";
import DateInput from "@src/components/fields/Date/SideDrawerField";
export default function FilterCustomInput({
onChange,
operator,
...props
}: IFilterCustomInputProps) {
if (operator && operator.startsWith("date-"))
return <DateInput {...(props as any)} onChange={onChange} />;
return <DateTimeInput {...(props as any)} onChange={onChange} />;
}

View File

@@ -14,7 +14,7 @@ import { getFieldId } from "@src/components/SideDrawer/utils";
export interface IDateProps extends ISideDrawerFieldProps {}
export default function Date_({
export default function DateTime({
column,
value,
onChange,

View File

@@ -7,56 +7,67 @@ export const filterOperators: IFilterOperator[] = [
label: "equals",
secondaryLabel: "==",
value: "time-minute-equal",
group: "Date & Time",
},
{
label: "not equal to",
secondaryLabel: "!=",
value: "!=",
group: "Date & Time",
},
{
label: "before",
secondaryLabel: "<",
value: "<",
group: "Date & Time",
},
{
label: "after",
secondaryLabel: ">",
value: ">",
group: "Date & Time",
},
{
label: "before or at",
secondaryLabel: "<=",
value: "<=",
group: "Date & Time",
},
{
label: "at or after",
secondaryLabel: ">=",
value: ">=",
group: "Date & Time",
},
{
label: "where date is is",
label: "where date is",
secondaryLabel: "date ==",
value: "date-equal",
group: "Date",
},
{
label: "where date is before",
secondaryLabel: "date <",
value: "date-before",
group: "Date",
},
{
label: "where date is after",
secondaryLabel: "date >",
value: "date-after",
group: "Date",
},
{
label: "where date is before or on",
secondaryLabel: "date <=",
value: "date-before-equal",
group: "Date",
},
{
label: "where date is on or after",
secondaryLabel: "date >=",
value: "date-after-equal",
group: "Date",
},
];

View File

@@ -21,6 +21,12 @@ const SideDrawerField = lazy(
const Settings = lazy(
() => import("./Settings" /* webpackChunkName: "Settings-DateTime" */)
);
const FilterCustomInput = lazy(
() =>
import(
"./FilterCustomInput" /* webpackChunkName: "FilterCustomInput-DateTime" */
)
);
export const config: IFieldConfig = {
type: FieldType.dateTime,
@@ -34,7 +40,11 @@ export const config: IFieldConfig = {
TableCell: withHeavyCell(BasicCell, TableCell),
TableEditor: NullEditor as any,
SideDrawerField,
filter: { operators: filterOperators, valueFormatter },
filter: {
operators: filterOperators,
valueFormatter,
customInput: FilterCustomInput,
},
settings: Settings,
csvImportParser: (value) => parseJSON(value).getTime(),
csvExportFormatter: (value: any, config?: any) =>

View File

@@ -35,7 +35,7 @@ export interface IFieldConfig {
settingsValidator?: (config: Record<string, any>) => Record<string, string>;
filter?: {
operators: IFilterOperator[];
customInput?: React.ComponentType<{ onChange: (value: any) => void }>;
customInput?: React.ComponentType<IFilterCustomInputProps>;
defaultValue?: any;
valueFormatter?: (value: any) => string;
};
@@ -104,4 +104,11 @@ export interface IFilterOperator {
value: TableFilter["operator"];
label: string;
secondaryLabel?: React.ReactNode;
group?: string;
}
export interface IFilterCustomInputProps {
onChange: (value: any) => void;
operator: TableFilter["operator"];
[key: string]: any;
}