better cache usage, make filters blue

This commit is contained in:
Cole Goldsmith 2025-09-23 11:04:27 -05:00
parent 744a799c11
commit 0b39baa5ec
6 changed files with 43 additions and 23 deletions

View file

@ -12,6 +12,7 @@ import { Button } from "./ui/button";
import { DeleteConfirmationDialog } from "./confirmation-dialog";
import { useDeleteDocument } from "@/app/api/mutations/useDeleteDocument";
import { toast } from "sonner";
import { useRouter } from "next/navigation";
interface KnowledgeActionsDropdownProps {
filename: string;
@ -22,6 +23,7 @@ export const KnowledgeActionsDropdown = ({
}: KnowledgeActionsDropdownProps) => {
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
const deleteDocumentMutation = useDeleteDocument();
const router = useRouter();
const handleDelete = async () => {
try {
@ -43,7 +45,17 @@ export const KnowledgeActionsDropdown = ({
<EllipsisVertical className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent side="right" sideOffset={-10}>
<DropdownMenuContent side="right" align="start" sideOffset={-10}>
<DropdownMenuItem
className="text-primary focus:text-primary"
onClick={() => {
router.push(
`/knowledge/chunks?filename=${encodeURIComponent(filename)}`
);
}}
>
View chunks
</DropdownMenuItem>
{/* //TODO: Implement rename and sync */}
{/* <DropdownMenuItem
className="text-primary focus:text-primary"

View file

@ -6,7 +6,7 @@ import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { Filter, Loader2, Plus, Save } from "lucide-react";
import { Filter, Loader2, Plus, Save, X } from "lucide-react";
import { cn } from "@/lib/utils";
import {
useGetFiltersSearchQuery,
@ -123,7 +123,7 @@ export function KnowledgeFilterList({
size="sm"
onClick={handleCreateNew}
title="Create New Filter"
className="h-8 px-3"
className="h-8 px-3 text-muted-foreground"
>
<Plus className="h-3 w-3" />
</Button>
@ -152,7 +152,9 @@ export function KnowledgeFilterList({
>
<div className="flex flex-col gap-1 flex-1 min-w-0">
<div className="flex items-center gap-2">
<Filter className="h-4 w-4" />
<div className="flex items-center justify-center bg-blue-500/20 w-5 h-5 rounded">
<Filter className="h-3 w-3 text-blue-400" />
</div>
<div className="text-sm font-medium truncate group-hover:text-accent-foreground">
{filter.name}
</div>
@ -172,8 +174,8 @@ export function KnowledgeFilterList({
</div>
<span className="text-xs bg-muted text-muted-foreground px-1 py-0.5 rounded-sm">
{(() => {
const dataSources =
parseQueryData(filter.query_data).filters.data_sources;
const dataSources = parseQueryData(filter.query_data)
.filters.data_sources;
if (dataSources[0] === "*") return "All sources";
const count = dataSources.length;
return `${count} ${count === 1 ? "source" : "sources"}`;
@ -181,6 +183,19 @@ export function KnowledgeFilterList({
</span>
</div>
</div>
{selectedFilter?.id === filter.id && (
<Button
variant="ghost"
size="sm"
className="px-0"
onClick={(e) => {
e.stopPropagation();
onFilterSelect(null);
}}
>
<X className="h-4 w-4 flex-shrink-0 opacity-0 group-hover:opacity-100 text-muted-foreground" />
</Button>
)}
</div>
))
)}
@ -189,7 +204,7 @@ export function KnowledgeFilterList({
<Dialog open={showCreateModal} onOpenChange={setShowCreateModal}>
<DialogContent>
<DialogHeader>
<DialogTitle>Create New Knowledge Filter</DialogTitle>
<DialogTitle>Create a new knowledge filter</DialogTitle>
<DialogDescription>
Save a reusable filter to quickly scope searches across your
knowledge base.

View file

@ -44,7 +44,7 @@ export const useCreateFilter = () => {
return useMutation({
mutationFn: createFilter,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["knowledge-filters"], exact: false });
queryClient.invalidateQueries({ queryKey: ["knowledge-filters"]});
},
});
};

View file

@ -33,7 +33,7 @@ export const useDeleteFilter = () => {
mutationFn: deleteFilter,
onSuccess: () => {
// Invalidate filters queries so UI refreshes automatically
queryClient.invalidateQueries({ queryKey: ["knowledge-filters"], exact: false });
queryClient.invalidateQueries({ queryKey: ["knowledge-filters"] });
},
});
};

View file

@ -46,7 +46,7 @@ export const useUpdateFilter = () => {
mutationFn: updateFilter,
onSuccess: () => {
// Refresh any knowledge filter lists/searches
queryClient.invalidateQueries({ queryKey: ["knowledge-filters"], exact: false });
queryClient.invalidateQueries({ queryKey: ["knowledge-filters"] });
},
});
};

View file

@ -3,14 +3,13 @@
import {
Building2,
Cloud,
Filter,
HardDrive,
Search,
Trash2,
X,
} from "lucide-react";
import { AgGridReact, CustomCellRendererProps } from "ag-grid-react";
import { useCallback, useEffect, useState, useRef, ChangeEvent } from "react";
import { useCallback, useState, useRef, ChangeEvent } from "react";
import { useRouter } from "next/navigation";
import { SiGoogledrive } from "react-icons/si";
import { TbBrandOnedrive } from "react-icons/tb";
@ -60,11 +59,10 @@ function SearchPage() {
const deleteDocumentMutation = useDeleteDocument();
const {
data = [],
isFetching,
refetch: refetchSearch,
} = useGetSearchQuery(parsedFilterData?.query || "", parsedFilterData);
const { data = [], isFetching } = useGetSearchQuery(
parsedFilterData?.query || "*",
parsedFilterData
);
const handleTableSearch = (e: ChangeEvent<HTMLInputElement>) => {
gridRef.current?.api.setGridOption("quickFilterText", e.target.value);
@ -200,10 +198,6 @@ function SearchPage() {
}
};
useEffect(() => {
refetchSearch();
}, [selectedFilter, refetchSearch]);
return (
<div
className={`fixed inset-0 md:left-72 top-[53px] flex flex-col transition-all duration-300 ${
@ -230,8 +224,7 @@ function SearchPage() {
<form className="flex gap-3">
<div className="primary-input min-h-10 !flex items-center flex-nowrap gap-2 focus-within:border-foreground transition-colors !py-0">
{selectedFilter?.name && (
<div className="flex items-center gap-2 bg-accent text-accent-foreground px-1 py-0.5 rounded max-w-[300px]">
<Filter className="h-3 w-3 flex-shrink-0 ml-1" />
<div className="flex items-center gap-1 bg-blue-500/20 text-blue-400 px-1.5 py-0.5 rounded max-w-[300px]">
<span className="truncate">{selectedFilter?.name}</span>
<X
aria-label="Remove filter"