"use client" import { useState, useEffect } from 'react' import { X, Edit3, Save, Settings, RefreshCw } from 'lucide-react' import { Button } from '@/components/ui/button' import { Card, CardContent, CardDescription, 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' 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() // 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 from API useEffect(() => { if (isPanelOpen) { loadAvailableFacets() } }, [isPanelOpen]) const loadAvailableFacets = async () => { console.log("[DEBUG] Loading available facets...") try { // Do a search to get facets (similar to search page) const response = await fetch("/api/search", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ query: "*", // Use wildcard like search page to get all documents/facets limit: 1, scoreThreshold: 0 // Omit filters entirely to get all available facets }), }) const result = await response.json() console.log("[DEBUG] Search API response:", result) if (response.ok && result.aggregations) { const facets = { data_sources: result.aggregations.data_sources?.buckets || [], document_types: result.aggregations.document_types?.buckets || [], owners: result.aggregations.owners?.buckets || [], connector_types: result.aggregations.connector_types?.buckets || [] } console.log("[DEBUG] Setting facets:", facets) setAvailableFacets(facets) } else { console.log("[DEBUG] No aggregations in response or response not ok") } } catch (error) { console.error("Failed to load available facets:", error) } } // 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 response = await fetch(`/api/knowledge-filter/${selectedFilter.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ name: editingName.trim(), description: editingDescription.trim(), }), }) const result = await response.json() if (response.ok && result.success) { const updatedFilter = { ...selectedFilter, name: editingName.trim(), description: editingDescription.trim(), updated_at: new Date().toISOString(), } setSelectedFilter(updatedFilter) 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 response = await fetch(`/api/knowledge-filter/${selectedFilter.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ queryData: JSON.stringify(filterData) }), }) const result = await response.json() if (response.ok && result.success) { // Update the filter in context const updatedFilter = { ...selectedFilter, query_data: JSON.stringify(filterData), updated_at: new Date().toISOString(), } setSelectedFilter(updatedFilter) } } 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 })) } return (
Knowledge Filter
Configure your knowledge filter settings
{/* Filter Name and Description */}
{isEditingMeta ? (
setEditingName(e.target.value)} placeholder="Filter name" />