Skip to content

Commit

Permalink
feat: better filter ux
Browse files Browse the repository at this point in the history
Makes it easier to see whether a filter is applied or not and how to apply it.
  • Loading branch information
Loxeris committed Aug 27, 2024
1 parent f7f6ab7 commit e9c1599
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,8 @@ export function DataTable(props: DataTableProps) {
const { getAllParam, getParam, setParam } = useSearchParamsUtils();
const appId = getParam("appId");

const [appliedFilters, setAppliedFilters] = React.useState<Filter[]>(filters);

const updateFiltersAndUrl = React.useCallback(
(newFilters: Filter[]) => {
// Update the filters in the URL using the setParam function
Expand Down Expand Up @@ -364,6 +366,7 @@ export function DataTable(props: DataTableProps) {
}));
setSearchBody({ search: jsonFilters });
setPage(0);
setAppliedFilters(filters);

// Update the filters in the URL
updateFiltersAndUrl(filters);
Expand Down Expand Up @@ -498,6 +501,7 @@ export function DataTable(props: DataTableProps) {
columns={columns}
filters={filters}
setFilters={setFilters}
appliedFilters={appliedFilters}
handleApplyFilters={handleApplyFilters}
/>
<Box sx={{ width: "100%", p: 1 }} data-testid="skeleton">
Expand All @@ -520,6 +524,7 @@ export function DataTable(props: DataTableProps) {
columns={columns}
filters={filters}
setFilters={setFilters}
appliedFilters={appliedFilters}
handleApplyFilters={handleApplyFilters}
/>
<Box sx={{ width: "100%", marginTop: 2 }}>
Expand All @@ -539,6 +544,7 @@ export function DataTable(props: DataTableProps) {
columns={columns}
filters={filters}
setFilters={setFilters}
appliedFilters={appliedFilters}
handleApplyFilters={handleApplyFilters}
/>
<Box sx={{ width: "100%", marginTop: 2 }}>
Expand All @@ -556,6 +562,7 @@ export function DataTable(props: DataTableProps) {
columns={columns}
filters={filters}
setFilters={setFilters}
appliedFilters={appliedFilters}
handleApplyFilters={handleApplyFilters}
/>

Expand Down
89 changes: 62 additions & 27 deletions packages/diracx-web-components/components/shared/FilterToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from "react";
import { FilterList, Delete, Send } from "@mui/icons-material";
import Chip from "@mui/material/Chip";
import Button from "@mui/material/Button";
import { Popover, Stack, Tooltip } from "@mui/material";
import { Alert, Popover, Stack, Tooltip } from "@mui/material";
import { Filter } from "@/types/Filter";
import { Column } from "@/types/Column";
import { FilterForm } from "./FilterForm";
Expand All @@ -18,6 +18,8 @@ interface FilterToolbarProps {
filters: Filter[];
/** The function to set the filters */
setFilters: React.Dispatch<React.SetStateAction<Filter[]>>;
/** The applied filters */
appliedFilters: Filter[];
/** The function to apply the filters */
handleApplyFilters: () => void;
}
Expand All @@ -28,7 +30,8 @@ interface FilterToolbarProps {
* @returns a FilterToolbar component
*/
export function FilterToolbar(props: FilterToolbarProps) {
const { columns, filters, setFilters, handleApplyFilters } = props;
const { columns, filters, setFilters, appliedFilters, handleApplyFilters } =
props;
const [anchorEl, setAnchorEl] = React.useState<HTMLElement | null>(null);
const [selectedFilter, setSelectedFilter] = React.useState<Filter | null>(
null,
Expand Down Expand Up @@ -82,6 +85,17 @@ export function FilterToolbar(props: FilterToolbarProps) {
setFilters(filters.filter((_, i) => i !== index));
};

const changesUnapplied = React.useCallback(() => {
return JSON.stringify(filters) !== JSON.stringify(appliedFilters);
}, [filters, appliedFilters]);

const isApplied = React.useCallback(
(filter: Filter) => {
return appliedFilters.some((f) => f.id == filter.id);
},
[appliedFilters],
);

// Keyboard shortcuts
React.useEffect(() => {
function debounce(func: (...args: any[]) => void, wait: number) {
Expand Down Expand Up @@ -142,37 +156,51 @@ export function FilterToolbar(props: FilterToolbarProps) {

return (
<>
<Stack direction="row" spacing={1} sx={{ m: 1 }}>
<Stack direction="row" spacing={1} sx={{ m: 1 }} alignItems={"center"}>
<Tooltip title="Alt+Shift+a" placement="top">
<Button
variant="text"
startIcon={<FilterList />}
onClick={handleAddFilter}
ref={addFilterButtonRef}
>
<span>Add filter</span>
</Button>
<span>
<Button
variant="text"
startIcon={<FilterList />}
onClick={handleAddFilter}
ref={addFilterButtonRef}
>
<span>Add filter</span>
</Button>
</span>
</Tooltip>
<Tooltip title="Alt+Shift+p" placement="top">
<Button
variant="text"
startIcon={<Send />}
onClick={() => handleApplyFilters()}
>
<span>Apply filters</span>
</Button>
<span>
<Button
variant="text"
startIcon={<Send />}
onClick={() => handleApplyFilters()}
disabled={!changesUnapplied()}
>
<span>Apply filters</span>
</Button>
</span>
</Tooltip>
<Tooltip title="Alt+Shift+c" placement="top">
<Button
variant="text"
startIcon={<Delete />}
onClick={handleRemoveAllFilters}
>
<span>Clear all filters</span>
</Button>
<span>
<Button
variant="text"
startIcon={<Delete />}
onClick={handleRemoveAllFilters}
disabled={filters.length === 0}
>
<span>Clear all filters</span>
</Button>
</span>
</Tooltip>
</Stack>
<Stack direction="row" spacing={1} sx={{ m: 1, flexWrap: "wrap" }}>
<Stack
direction="row"
spacing={1}
flexWrap="wrap"
useFlexGap
sx={{ m: 1 }}
>
{filters.map((filter: Filter, index: number) => (
<Chip
key={index}
Expand All @@ -184,10 +212,11 @@ export function FilterToolbar(props: FilterToolbarProps) {
onDelete={() => {
handleRemoveFilter(index);
}}
color="primary"
color={isApplied(filter) ? "chipColor" : "default"}
sx={{ m: 0.5 }}
/>
))}

<Popover
open={open}
onClose={handleFilterMenuClose}
Expand All @@ -207,6 +236,12 @@ export function FilterToolbar(props: FilterToolbarProps) {
/>
</Popover>
</Stack>
{changesUnapplied() && (
<Alert severity="info">
Some filter changes have not been applied. Please click on &quot;Apply
filters&quot; to update your results.
</Alert>
)}
</>
);
}
46 changes: 34 additions & 12 deletions packages/diracx-web-components/hooks/theme.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,30 @@
import { PaletteMode } from "@mui/material";
import { grey, lightGreen, cyan } from "@mui/material/colors";
import { createTheme, darken, lighten } from "@mui/material/styles";
import { cyan, grey, lightGreen } from "@mui/material/colors";
import {
createTheme,
darken,
lighten,
getContrastRatio,
} from "@mui/material/styles";
import { useContext } from "react";
import { ThemeContext } from "@/contexts/ThemeProvider";

declare module "@mui/material/styles" {
interface Palette {
chipColor: Palette["primary"];
}

interface PaletteOptions {
chipColor?: PaletteOptions["primary"];
}
}

declare module "@mui/material/Chip" {
interface ChipPropsColorOverrides {
chipColor: true;
}
}

/**
* Custom hook to access the theme context
* @returns the theme context
Expand All @@ -26,19 +47,27 @@ export const useTheme = () => {
export const useMUITheme = () => {
const { theme } = useTheme();

const primary = lightGreen[700];
const secondary = cyan[500];

const chipColor =
theme === "light" ? lighten(primary, 0.5) : darken(primary, 0.5);

// Create a Material-UI theme based on the current mode
const muiTheme = createTheme({
palette: {
mode: theme as PaletteMode,
primary: {
main: "#ffffff",
},
chipColor: {
main: chipColor,
contrastText:
getContrastRatio(chipColor, "#fff") > 4.5 ? "#fff" : "#111",
},
},
});

const primary = lightGreen[700];
const secondary = cyan[500];

const scrollbarBackground = theme === "dark" ? "#333" : "#f1f1f1";
const scrollbarThumbBackground = theme === "dark" ? "#888" : "#ccc";
const scrollbarThumbHoverBackground = theme === "dark" ? "#555" : "#999";
Expand Down Expand Up @@ -101,13 +130,6 @@ export const useMUITheme = () => {
},
},
},
MuiChip: {
styleOverrides: {
root: {
backgroundColor: lighten(primary, 0.75),
},
},
},
MuiInputLabel: {
styleOverrides: {
root: {
Expand Down

0 comments on commit e9c1599

Please sign in to comment.