refactor: enhance DocumentsFilters and FolderTreeView components for improved filter handling and search functionality

This commit is contained in:
Anish Sarkar 2026-04-06 14:41:53 +05:30
parent 3251f0e98d
commit be7e73e615
5 changed files with 20 additions and 28 deletions

View file

@ -65,7 +65,7 @@ export function DocumentsFilters({
<div className="flex select-none"> <div className="flex select-none">
<div className="flex items-center gap-2 w-full"> <div className="flex items-center gap-2 w-full">
{/* Filter + New Folder Toggle Group */} {/* Filter + New Folder Toggle Group */}
<ToggleGroup type="multiple" variant="outline" value={[]}> <ToggleGroup type="multiple" variant="outline" value={[]} className="overflow-visible">
{onCreateFolder && ( {onCreateFolder && (
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>
@ -90,11 +90,11 @@ export function DocumentsFilters({
<PopoverTrigger asChild> <PopoverTrigger asChild>
<ToggleGroupItem <ToggleGroupItem
value="filter" value="filter"
className="relative h-9 w-9 shrink-0 border-sidebar-border text-sidebar-foreground/60 hover:text-sidebar-foreground hover:border-sidebar-border bg-sidebar" className="relative h-9 w-9 shrink-0 border-sidebar-border text-sidebar-foreground/60 hover:text-sidebar-foreground hover:border-sidebar-border bg-sidebar overflow-visible"
> >
<ListFilter size={14} /> <ListFilter size={14} />
{activeTypes.length > 0 && ( {activeTypes.length > 0 && (
<span className="absolute -top-1 -right-1 flex h-4 w-4 items-center justify-center rounded-full bg-primary text-[9px] font-medium text-primary-foreground"> <span className="absolute -top-1 -right-1 flex h-4 w-4 items-center justify-center rounded-full bg-sidebar-border text-[9px] font-medium text-sidebar-foreground">
{activeTypes.length} {activeTypes.length}
</span> </span>
)} )}
@ -167,22 +167,6 @@ export function DocumentsFilters({
)) ))
)} )}
</div> </div>
{activeTypes.length > 0 && (
<div className="px-3 pt-1.5 pb-1.5 border-t border-border dark:border-neutral-700">
<Button
variant="ghost"
size="sm"
className="w-full h-7 text-[11px] text-muted-foreground hover:text-foreground hover:bg-neutral-200 dark:hover:bg-neutral-700"
onClick={() => {
activeTypes.forEach((t) => {
onToggleType(t, false);
});
}}
>
Clear filters
</Button>
</div>
)}
</div> </div>
</PopoverContent> </PopoverContent>
</Popover> </Popover>

View file

@ -96,14 +96,21 @@ export function FolderTreeView({
); );
const handleCancelRename = useCallback(() => setRenamingFolderId(null), [setRenamingFolderId]); const handleCancelRename = useCallback(() => setRenamingFolderId(null), [setRenamingFolderId]);
const effectiveActiveTypes = useMemo(() => {
if (activeTypes.includes("FILE" as DocumentTypeEnum) && !activeTypes.includes("LOCAL_FOLDER_FILE" as DocumentTypeEnum)) {
return [...activeTypes, "LOCAL_FOLDER_FILE" as DocumentTypeEnum];
}
return activeTypes;
}, [activeTypes]);
const hasDescendantMatch = useMemo(() => { const hasDescendantMatch = useMemo(() => {
if (activeTypes.length === 0 && !searchQuery) return null; if (effectiveActiveTypes.length === 0 && !searchQuery) return null;
const match: Record<number, boolean> = {}; const match: Record<number, boolean> = {};
function check(folderId: number): boolean { function check(folderId: number): boolean {
if (match[folderId] !== undefined) return match[folderId]; if (match[folderId] !== undefined) return match[folderId];
const childDocs = (docsByFolder[folderId] ?? []).some( const childDocs = (docsByFolder[folderId] ?? []).some(
(d) => activeTypes.length === 0 || activeTypes.includes(d.document_type as DocumentTypeEnum) (d) => effectiveActiveTypes.length === 0 || effectiveActiveTypes.includes(d.document_type as DocumentTypeEnum)
); );
if (childDocs) { if (childDocs) {
match[folderId] = true; match[folderId] = true;
@ -124,7 +131,7 @@ export function FolderTreeView({
check(f.id); check(f.id);
} }
return match; return match;
}, [folders, docsByFolder, foldersByParent, activeTypes, searchQuery]); }, [folders, docsByFolder, foldersByParent, effectiveActiveTypes, searchQuery]);
const folderSelectionStates = useMemo(() => { const folderSelectionStates = useMemo(() => {
const states: Record<number, FolderSelectionState> = {}; const states: Record<number, FolderSelectionState> = {};
@ -194,7 +201,7 @@ export function FolderTreeView({
? childFolders.filter((f) => hasDescendantMatch[f.id]) ? childFolders.filter((f) => hasDescendantMatch[f.id])
: childFolders; : childFolders;
const childDocs = (docsByFolder[key] ?? []).filter( const childDocs = (docsByFolder[key] ?? []).filter(
(d) => activeTypes.length === 0 || activeTypes.includes(d.document_type as DocumentTypeEnum) (d) => effectiveActiveTypes.length === 0 || effectiveActiveTypes.includes(d.document_type as DocumentTypeEnum)
); );
const nodes: React.ReactNode[] = []; const nodes: React.ReactNode[] = [];
@ -278,7 +285,7 @@ export function FolderTreeView({
); );
} }
if (treeNodes.length === 0 && (activeTypes.length > 0 || searchQuery)) { if (treeNodes.length === 0 && (effectiveActiveTypes.length > 0 || searchQuery)) {
return ( return (
<div className="flex flex-1 flex-col items-center justify-center gap-3 px-4 py-12 text-muted-foreground"> <div className="flex flex-1 flex-col items-center justify-center gap-3 px-4 py-12 text-muted-foreground">
<Search className="h-10 w-10" /> <Search className="h-10 w-10" />

View file

@ -84,7 +84,7 @@ export function RightPanelExpandButton() {
variant="ghost" variant="ghost"
size="icon" size="icon"
onClick={() => startTransition(() => setCollapsed(false))} onClick={() => startTransition(() => setCollapsed(false))}
className="h-7 w-7 shrink-0" className="h-8 w-8 shrink-0 -m-0.5"
> >
<PanelRight className="h-4 w-4" /> <PanelRight className="h-4 w-4" />
<span className="sr-only">Expand panel</span> <span className="sr-only">Expand panel</span>

View file

@ -531,7 +531,8 @@ export function DocumentsSidebar({
const typeCounts = useMemo(() => { const typeCounts = useMemo(() => {
const counts: Partial<Record<string, number>> = {}; const counts: Partial<Record<string, number>> = {};
for (const d of treeDocuments) { for (const d of treeDocuments) {
counts[d.document_type] = (counts[d.document_type] || 0) + 1; const displayType = d.document_type === "LOCAL_FOLDER_FILE" ? "FILE" : d.document_type;
counts[displayType] = (counts[displayType] || 0) + 1;
} }
return counts; return counts;
}, [treeDocuments]); }, [treeDocuments]);
@ -746,7 +747,7 @@ export function DocumentsSidebar({
</button> </button>
</div> </div>
<div className="flex-1 min-h-0 overflow-x-hidden pt-0 flex flex-col"> <div className="flex-1 min-h-0 pt-0 flex flex-col">
<div className="px-4 pb-2"> <div className="px-4 pb-2">
<DocumentsFilters <DocumentsFilters
typeCounts={typeCounts} typeCounts={typeCounts}

View file

@ -127,7 +127,7 @@ export const getConnectorIcon = (connectorType: EnumConnectorName | string, clas
case "DEEPEST": case "DEEPEST":
return <Telescope {...iconProps} />; return <Telescope {...iconProps} />;
case "LOCAL_FOLDER_FILE": case "LOCAL_FOLDER_FILE":
return null; return <File {...iconProps} />;
default: default:
return <Search {...iconProps} />; return <Search {...iconProps} />;
} }