"use client"; import { useState, useEffect } from "react"; import { X, Edit3, Save, RefreshCw } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { MultiSelect } from "@/components/ui/multi-select"; import { Slider } from "@/components/ui/slider"; import { useKnowledgeFilter } from "@/contexts/knowledge-filter-context"; import { useDeleteFilter } from "@/app/api/mutations/useDeleteFilter"; import { useUpdateFilter } from "@/app/api/mutations/useUpdateFilter"; import { useGetSearchAggregations } from "@/src/app/api/queries/useGetSearchAggregations"; interface FacetBucket { key: string; count: number; } interface AvailableFacets { data_sources: FacetBucket[]; document_types: FacetBucket[]; owners: FacetBucket[]; connector_types: FacetBucket[]; } export function KnowledgeFilterPanel() { const { selectedFilter, parsedFilterData, setSelectedFilter, isPanelOpen, closePanelOnly, } = useKnowledgeFilter(); const deleteFilterMutation = useDeleteFilter(); const updateFilterMutation = useUpdateFilter(); // Edit mode states const [isEditingMeta, setIsEditingMeta] = useState(false); const [editingName, setEditingName] = useState(""); const [editingDescription, setEditingDescription] = useState(""); const [isSaving, setIsSaving] = useState(false); // Filter configuration states (mirror search page exactly) const [query, setQuery] = useState(""); const [selectedFilters, setSelectedFilters] = useState({ data_sources: ["*"] as string[], // Default to wildcard document_types: ["*"] as string[], // Default to wildcard owners: ["*"] as string[], // Default to wildcard connector_types: ["*"] as string[], // Default to wildcard }); const [resultLimit, setResultLimit] = useState(10); const [scoreThreshold, setScoreThreshold] = useState(0); // Available facets (loaded from API) const [availableFacets, setAvailableFacets] = useState({ data_sources: [], document_types: [], owners: [], connector_types: [], }); // Load current filter data into controls useEffect(() => { if (selectedFilter && parsedFilterData) { setQuery(parsedFilterData.query || ""); // Set the actual filter selections from the saved knowledge filter const filters = parsedFilterData.filters; // Use the exact selections from the saved filter // Empty arrays mean "none selected" not "all selected" const processedFilters = { data_sources: filters.data_sources, document_types: filters.document_types, owners: filters.owners, connector_types: filters.connector_types || ["*"], }; console.log("[DEBUG] Loading filter selections:", processedFilters); setSelectedFilters(processedFilters); setResultLimit(parsedFilterData.limit || 10); setScoreThreshold(parsedFilterData.scoreThreshold || 0); setEditingName(selectedFilter.name); setEditingDescription(selectedFilter.description || ""); } }, [selectedFilter, parsedFilterData]); // Load available facets using search aggregations hook const { data: aggregations } = useGetSearchAggregations("*", 1, 0, { enabled: isPanelOpen, placeholderData: (prev) => prev, staleTime: 60_000, gcTime: 5 * 60_000, }); useEffect(() => { if (!aggregations) return; const facets = { data_sources: aggregations.data_sources?.buckets || [], document_types: aggregations.document_types?.buckets || [], owners: aggregations.owners?.buckets || [], connector_types: aggregations.connector_types?.buckets || [], }; setAvailableFacets(facets); }, [aggregations]); // Don't render if panel is closed or no filter selected if (!isPanelOpen || !selectedFilter || !parsedFilterData) return null; const selectAllFilters = () => { // Use wildcards instead of listing all specific items setSelectedFilters({ data_sources: ["*"], document_types: ["*"], owners: ["*"], connector_types: ["*"], }); }; const clearAllFilters = () => { setSelectedFilters({ data_sources: [], document_types: [], owners: [], connector_types: [], }); }; const handleEditMeta = () => { setIsEditingMeta(true); }; const handleCancelEdit = () => { setIsEditingMeta(false); setEditingName(selectedFilter.name); setEditingDescription(selectedFilter.description || ""); }; const handleSaveMeta = async () => { if (!editingName.trim()) return; setIsSaving(true); try { const result = await updateFilterMutation.mutateAsync({ id: selectedFilter.id, name: editingName.trim(), description: editingDescription.trim(), }); if (result.success && result.filter) { setSelectedFilter(result.filter); setIsEditingMeta(false); } } catch (error) { console.error("Error updating filter:", error); } finally { setIsSaving(false); } }; const handleSaveConfiguration = async () => { const filterData = { query, filters: selectedFilters, limit: resultLimit, scoreThreshold, }; setIsSaving(true); try { const result = await updateFilterMutation.mutateAsync({ id: selectedFilter.id, queryData: JSON.stringify(filterData), }); if (result.success && result.filter) { setSelectedFilter(result.filter); } } catch (error) { console.error("Error updating filter configuration:", error); } finally { setIsSaving(false); } }; const formatDate = (dateString: string) => { return new Date(dateString).toLocaleDateString("en-US", { year: "numeric", month: "short", day: "numeric", hour: "2-digit", minute: "2-digit", }); }; const handleFilterChange = ( facetType: keyof typeof selectedFilters, newValues: string[] ) => { setSelectedFilters((prev) => ({ ...prev, [facetType]: newValues, })); }; const handleDeleteFilter = async () => { const result = await deleteFilterMutation.mutateAsync({ id: selectedFilter.id, }); if (result.success) { setSelectedFilter(null); closePanelOnly(); } }; return (
Knowledge Filter
{/* Filter Name and Description */}
{isEditingMeta ? (
setEditingName(e.target.value)} placeholder="Filter name" />