Skip to content

Commit

Permalink
filters fe revamp (#2725)
Browse files Browse the repository at this point in the history
  • Loading branch information
chitalian authored Oct 15, 2024
1 parent bf134c6 commit 1d3063b
Show file tree
Hide file tree
Showing 11 changed files with 816 additions and 274 deletions.
77 changes: 43 additions & 34 deletions web/components/shared/themed/FilterTreeEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from "react";
import { PlusIcon } from "@heroicons/react/24/outline";
import { Button } from "@tremor/react";

import { Result } from "../../../lib/result";
import { SingleFilterDef } from "../../../services/lib/filters/frontendFilterDefs";
import { AdvancedFilterRow, UIFilterRow } from "./themedAdvancedFilters";
Expand All @@ -10,6 +9,15 @@ import {
} from "../../../services/lib/filters/uiFilterRowTree";
import SaveFilterButton from "../../templates/dashboard/saveFilterButton";
import { OrganizationFilter } from "../../../services/lib/organization_layout/organization_layout";
import { Button } from "@/components/ui/button";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { PlusSquareIcon } from "lucide-react";

interface FilterTreeEditorProps {
uiFilterRowTree: UIFilterRowTree;
Expand Down Expand Up @@ -119,8 +127,8 @@ const FilterTreeEditor: React.FC<FilterTreeEditorProps> = ({
return null;
};

const handleOperatorToggle = (node: UIFilterRowNode) => {
node.operator = node.operator === "and" ? "or" : "and";
const handleOperatorChange = (node: UIFilterRowNode, value: string) => {
node.operator = value as "and" | "or";
onUpdate({ ...uiFilterRowTree });
};

Expand All @@ -133,40 +141,27 @@ const FilterTreeEditor: React.FC<FilterTreeEditorProps> = ({
const content = (
<>
{node.rows.length > 1 && (
<div
className={`flex items-center mb-4 ${
path.length === 1 && "ml-4"
}`}
<Select
value={node.operator}
onValueChange={(value) => handleOperatorChange(node, value)}
defaultValue="and"
>
<Button
onClick={() => handleOperatorToggle(node)}
variant="secondary"
size="xs"
className="mr-2 uppercase bg-[#E5F3F9] border-[#6BB9EF]"
>
{node.operator}
</Button>
</div>
<SelectTrigger className="self-start w-auto mb-1 bg-slate-50 hover:bg-slate-100 dark:bg-slate-900 dark:hover:bg-slate-800 focus:ring-0 focus:ring-offset-0 ">
<SelectValue placeholder="Operator" />
</SelectTrigger>
<SelectContent>
<SelectItem value="and">And</SelectItem>
<SelectItem value="or">Or</SelectItem>
</SelectContent>
</Select>
)}
{node.rows.map((childNode: UIFilterRowTree, childIndex: number) => (
<div key={childIndex} className="mb-2">
<div key={childIndex} className="mb-1">
{renderNode(childNode, [...path, childIndex], false)}
</div>
))}
{isRoot && (
<div className="flex flex-row w-full items-center justify-between my-4">
<button
onClick={() => handleAddFilter(node)}
className="bg-gray-100 dark:bg-[#17191d] border border-gray-300 dark:border-gray-700 rounded-lg px-2.5 py-1.5 hover:bg-sky-50 dark:hover:bg-sky-900 flex flex-row items-center gap-2"
>
<PlusIcon
className="mr-1 h-3.5 flex-none text-black dark:text-white hover:bg-sky-100 hover:text-sky-900 dark:hover:bg-sky-900 dark:hover:text-sky-100"
aria-hidden="true"
/>
<p className="text-sm font-medium text-gray-900 dark:text-gray-100 hidden sm:block">
Add Filter
</p>
</button>
<div className="flex flex-row w-full items-center mt-2">
{onSaveFilterCallback && (
<SaveFilterButton
filters={filters}
Expand All @@ -176,6 +171,20 @@ const FilterTreeEditor: React.FC<FilterTreeEditorProps> = ({
layoutPage={layoutPage}
/>
)}
<Button
variant={"outline"}
size="md_sleek"
onClick={() => handleAddFilter(node)}
className="flex-1 flex flex-row items-center gap-2.5"
>
<PlusSquareIcon
className="h-4 flex-none text-slate-500 dark:text-slate-400"
aria-hidden="true"
/>
<p className="font-medium text-xs text-slate-700 dark:text-slate-300 hidden sm:block">
Add Filter
</p>
</Button>
</div>
)}
</>
Expand All @@ -184,7 +193,7 @@ const FilterTreeEditor: React.FC<FilterTreeEditorProps> = ({
return isRoot ? (
<div className="mb-4">{content}</div>
) : (
<div className="mb-4 flex flex-col bg-gray-100 dark:bg-black py-4 rounded-lg border border-gray-300 dark:border-gray-700">
<div className="mb-1 flex flex-col bg-slate-50 dark:bg-slate-900 p-2 ml-4 border border-slate-200 dark:border-slate-800 rounded-lg">
{content}
</div>
);
Expand Down Expand Up @@ -230,7 +239,7 @@ const FilterTreeEditor: React.FC<FilterTreeEditorProps> = ({
);

return path.length === 1 ? (
<div className="flex flex-col bg-gray-100 dark:bg-[#17191d] py-4 rounded-lg border border-gray-300 dark:border-gray-700 ">
<div className="flex flex-col dark:bg-[#17191d] py-1 rounded-sm">
{filterRow}
</div>
) : (
Expand Down Expand Up @@ -267,7 +276,7 @@ const FilterTreeEditor: React.FC<FilterTreeEditorProps> = ({
};

return (
<div className="-mb-4 mt-4">{renderNode(uiFilterRowTree, [], true)}</div>
<div className="-mb-4 text-xs">{renderNode(uiFilterRowTree, [], true)}</div>
);
};

Expand Down
140 changes: 120 additions & 20 deletions web/components/shared/themed/table/themedTableHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ import FiltersButton from "./filtersButton";
import { DragColumnItem } from "./columns/DragList";
import { UIFilterRowTree } from "../../../../services/lib/filters/uiFilterRowTree";
import { Button } from "@/components/ui/button";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { PinIcon } from "lucide-react";
import { Input } from "@/components/ui/input";
import clsx from "clsx";

Expand Down Expand Up @@ -93,6 +99,11 @@ export default function ThemedTableHeader<T>(props: ThemedTableHeaderProps<T>) {
const [isSearchExpanded, setIsSearchExpanded] = useState(false);
const searchInputRef = useRef<HTMLInputElement>(null);

// Add state variables to manage the popover's open state and pin status
const [isFiltersPopoverOpen, setIsFiltersPopoverOpen] = useState(false);
const [isFiltersPinned, setIsFiltersPinned] = useState(false);
const popoverContentRef = useRef<HTMLDivElement>(null);

useEffect(() => {
const displayFilters = window.sessionStorage.getItem("showFilters") || null;
setShowFilters(displayFilters ? JSON.parse(displayFilters) : false);
Expand All @@ -119,6 +130,10 @@ export default function ThemedTableHeader<T>(props: ThemedTableHeaderProps<T>) {
}
};

const handlePopoverInteraction = (e: React.MouseEvent) => {
e.stopPropagation();
};

return (
<div className="flex flex-col">
<div className="flex flex-col gap-3 lg:flex-row justify-between ">
Expand All @@ -139,17 +154,87 @@ export default function ThemedTableHeader<T>(props: ThemedTableHeaderProps<T>) {
)}
<div className="flex flex-row">
{advancedFilters && (
<Button
onClick={showFilterHandler}
variant="ghostLinear"
className="gap-2"
size="sm_sleek"
<Popover
open={isFiltersPopoverOpen}
onOpenChange={setIsFiltersPopoverOpen}
>
<FunnelIcon className="h-[13px] w-[13px] " />
<span className="hidden sm:inline font-normal text-xs text-slate-700 dark:text-slate-400">
{showFilters ? "Hide" : ""} Filters
</span>
</Button>
{!isFiltersPinned ? (
<PopoverTrigger asChild>
<Button
variant="ghostLinear"
className="gap-2"
size="sm_sleek"
onClick={() => {
if (isFiltersPinned) {
setShowFilters(!showFilters);
setIsFiltersPopoverOpen(false);
} else {
setIsFiltersPopoverOpen(!isFiltersPopoverOpen);
setShowFilters(false);
}
}}
>
<FunnelIcon className="h-[13px] w-[13px]" />
<span className="hidden sm:inline font-normal text-[13px]">
Filters
</span>
</Button>
</PopoverTrigger>
) : (
<Button
variant="ghostLinear"
className="gap-2"
size="sm_sleek"
onClick={() => {
setShowFilters(!showFilters);
}}
>
<FunnelIcon className="h-[13px] w-[13px]" />
<span className="hidden sm:inline font-normal text-[13px]">
{isFiltersPinned
? showFilters
? "Hide Filters"
: "Show Filters"
: "Filters"}
</span>
</Button>
)}
<PopoverContent
className="min-w-[40rem] w-[40vw] flex items-start p-0 mx-2 rounded-lg"
ref={popoverContentRef}
onInteractOutside={(e) => {}}
onClick={handlePopoverInteraction}
>
<AdvancedFilters
filterMap={advancedFilters.filterMap}
filters={advancedFilters.filters}
setAdvancedFilters={advancedFilters.setAdvancedFilters}
searchPropertyFilters={
advancedFilters.searchPropertyFilters
}
savedFilters={savedFilters?.filters}
onSaveFilterCallback={savedFilters?.onSaveFilterCallback}
layoutPage={savedFilters?.layoutPage ?? "requests"}
/>
<div className="flex justify-end ml-4">
<Button
variant="ghostLinear"
onClick={() => {
setIsFiltersPinned(!isFiltersPinned);
setIsFiltersPopoverOpen(isFiltersPinned);
setShowFilters(!isFiltersPinned);
}}
className="text-gray-500 hover:text-gray-700 p-0 mt-4 mr-4 h-auto w-auto"
>
{isFiltersPinned ? (
<PinIcon className="h-5 w-5 text-primary" />
) : (
<PinIcon className="h-5 w-5 text-muted-foreground" />
)}
</Button>
</div>
</PopoverContent>
</Popover>
)}

{savedFilters && (
Expand Down Expand Up @@ -245,16 +330,31 @@ export default function ThemedTableHeader<T>(props: ThemedTableHeaderProps<T>) {
</div>
</div>

{advancedFilters && showFilters && (
<AdvancedFilters
filterMap={advancedFilters.filterMap}
filters={advancedFilters.filters}
setAdvancedFilters={advancedFilters.setAdvancedFilters}
searchPropertyFilters={advancedFilters.searchPropertyFilters}
savedFilters={savedFilters?.filters}
onSaveFilterCallback={savedFilters?.onSaveFilterCallback}
layoutPage={savedFilters?.layoutPage ?? "requests"}
/>
{advancedFilters && showFilters && isFiltersPinned && (
<div className="flex justify-start min-w-[50rem] w-full mt-1">
<div className="flex-1 rounded-lg">
<AdvancedFilters
filterMap={advancedFilters.filterMap}
filters={advancedFilters.filters}
setAdvancedFilters={advancedFilters.setAdvancedFilters}
searchPropertyFilters={advancedFilters.searchPropertyFilters}
savedFilters={savedFilters?.filters}
onSaveFilterCallback={savedFilters?.onSaveFilterCallback}
layoutPage={savedFilters?.layoutPage ?? "requests"}
/>
</div>
<Button
variant="ghost"
onClick={() => {
setIsFiltersPinned(false);
setShowFilters(false);
setIsFiltersPopoverOpen(true);
}}
className="text-gray-500 hover:text-gray-700"
>
<PinIcon className="h-5 w-5 text-primary rotate-45 fill-gray-500" />
</Button>
</div>
)}
</div>
);
Expand Down
Loading

0 comments on commit 1d3063b

Please sign in to comment.