diff --git a/frontend/components/knowledge-actions-dropdown.tsx b/frontend/components/knowledge-actions-dropdown.tsx index a7cf1337..eddc8a1f 100644 --- a/frontend/components/knowledge-actions-dropdown.tsx +++ b/frontend/components/knowledge-actions-dropdown.tsx @@ -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 = ({ - + + { + router.push( + `/knowledge/chunks?filename=${encodeURIComponent(filename)}` + ); + }} + > + View chunks + {/* //TODO: Implement rename and sync */} {/* void; +} + +export function KnowledgeFilterList({ + selectedFilter, + onFilterSelect, +}: KnowledgeFilterListProps) { + const [searchQuery] = useState(""); + const [showCreateModal, setShowCreateModal] = useState(false); + const [createName, setCreateName] = useState(""); + const [createDescription, setCreateDescription] = useState(""); + const [creating, setCreating] = useState(false); + + const { data, isFetching: loading } = useGetFiltersSearchQuery( + searchQuery, + 20 + ); + + const filters = data || []; + + const createFilterMutation = useCreateFilter(); + + const handleFilterSelect = (filter: KnowledgeFilter) => { + onFilterSelect(filter); + }; + + const handleCreateNew = () => { + setShowCreateModal(true); + }; + + const handleCreateFilter = async () => { + if (!createName.trim()) return; + + setCreating(true); + try { + // Create a basic filter with wildcards (match everything by default) + const defaultFilterData = { + query: "", + filters: { + data_sources: ["*"], + document_types: ["*"], + owners: ["*"], + }, + limit: 10, + scoreThreshold: 0, + }; + + const result = await createFilterMutation.mutateAsync({ + name: createName.trim(), + description: createDescription.trim(), + queryData: JSON.stringify(defaultFilterData), + }); + + // Select the new filter from API response + onFilterSelect(result.filter); + + // Close modal and reset form + setShowCreateModal(false); + setCreateName(""); + setCreateDescription(""); + } catch (error) { + console.error("Error creating knowledge filter:", error); + } finally { + setCreating(false); + } + }; + + const handleCancelCreate = () => { + setShowCreateModal(false); + setCreateName(""); + setCreateDescription(""); + }; + + const parseQueryData = (queryData: string): ParsedQueryData => { + return JSON.parse(queryData) as ParsedQueryData; + }; + + return ( + <> +
+
+
+ Knowledge Filters +
+ +
+ {loading ? ( +
+ + + Loading... + +
+ ) : filters.length === 0 ? ( +
+ {searchQuery ? "No filters found" : "No saved filters"} +
+ ) : ( + filters.map((filter) => ( +
handleFilterSelect(filter)} + className={cn( + "flex items-center gap-3 px-3 py-2 w-full rounded-lg hover:bg-accent hover:text-accent-foreground cursor-pointer group transition-colors", + selectedFilter?.id === filter.id && + "bg-accent text-accent-foreground" + )} + > +
+
+
+ +
+
+ {filter.name} +
+
+ {filter.description && ( +
+ {filter.description} +
+ )} +
+
+ {new Date(filter.created_at).toLocaleDateString(undefined, { + month: "short", + day: "numeric", + year: "numeric", + })} +
+ + {(() => { + 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"}`; + })()} + +
+
+ {selectedFilter?.id === filter.id && ( + + )} +
+ )) + )} +
+ {/* Create Filter Dialog */} + + + + Create a new knowledge filter + + Save a reusable filter to quickly scope searches across your + knowledge base. + + +
+
+ + setCreateName(e.target.value)} + className="mt-1" + /> +
+
+ +