From f2b407b4c80afdab192c4ceb228c39557d42f35f Mon Sep 17 00:00:00 2001 From: phact Date: Wed, 20 Aug 2025 11:16:55 -0400 Subject: [PATCH] rename pages, improve knowledge and chat --- frontend/components/navigation.tsx | 12 +- frontend/src/app/chat/page.tsx | 105 +++++-------- .../src/app/{search => knowledge}/page.tsx | 27 ++-- .../{knowledge-sources => settings}/page.tsx | 141 +----------------- 4 files changed, 64 insertions(+), 221 deletions(-) rename frontend/src/app/{search => knowledge}/page.tsx (96%) rename frontend/src/app/{knowledge-sources => settings}/page.tsx (81%) diff --git a/frontend/components/navigation.tsx b/frontend/components/navigation.tsx index 1311a550..1d540e97 100644 --- a/frontend/components/navigation.tsx +++ b/frontend/components/navigation.tsx @@ -2,7 +2,7 @@ import Link from "next/link" import { usePathname } from "next/navigation" -import { Library, Database, MessageSquare, Settings2 } from "lucide-react" +import { Library, MessageSquare, Settings2 } from "lucide-react" import { cn } from "@/lib/utils" export function Navigation() { @@ -18,14 +18,14 @@ export function Navigation() { { label: "Knowledge", icon: Library, - href: "/search", - active: pathname === "/search", + href: "/knowledge", + active: pathname === "/knowledge", }, { label: "Settings", icon: Settings2, - href: "/knowledge-sources", - active: pathname === "/knowledge-sources", + href: "/settings", + active: pathname === "/settings", }, ] @@ -33,7 +33,7 @@ export function Navigation() {
- {routes.map((route, index) => ( + {routes.map((route) => (
(null) - const inputRef = useRef(null) + const inputRef = useRef(null) const { addTask } = useTask() const { selectedFilter, parsedFilterData } = useKnowledgeFilter() @@ -1125,44 +1123,29 @@ function ChatPage() { ) : ( <> {messages.map((message, index) => ( -
+
{message.role === "user" && ( -
-
- - - - {user?.name ? user.name.charAt(0).toUpperCase() : } - - - {user?.name || "User"} -
-
+
+ + + + {user?.name ? user.name.charAt(0).toUpperCase() : } + + +

{message.content}

)} {message.role === "assistant" && ( -
-
-
- -
- AI +
+
+
-
-
-
-
- Finished - - {message.timestamp.toLocaleTimeString()} - -
- {renderFunctionCalls(message.functionCalls || [], index)} -

{message.content}

-
+
+ {renderFunctionCalls(message.functionCalls || [], index)} +

{message.content}

)} @@ -1171,46 +1154,30 @@ function ChatPage() { {/* Streaming Message Display */} {streamingMessage && ( -
-
-
- -
- AI +
+
+
-
-
-
- - Streaming... - - {streamingMessage.timestamp.toLocaleTimeString()} - -
- {renderFunctionCalls(streamingMessage.functionCalls, messages.length)} -

- {streamingMessage.content} - -

-
+
+ {renderFunctionCalls(streamingMessage.functionCalls, messages.length)} +

+ {streamingMessage.content} + +

)} - {loading && !asyncMode && ( -
-
-
- -
- AI + {/* Loading animation - shows immediately after user submits */} + {loading && ( +
+
+
-
-
-
- - Thinking... -
+
+
+ + Thinking...
@@ -1266,7 +1233,7 @@ function ChatPage() { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault() if (input.trim() && !loading) { - handleSubmit(e as any) + handleSubmit(e as React.FormEvent) } } }} diff --git a/frontend/src/app/search/page.tsx b/frontend/src/app/knowledge/page.tsx similarity index 96% rename from frontend/src/app/search/page.tsx rename to frontend/src/app/knowledge/page.tsx index 0c93a734..25db537b 100644 --- a/frontend/src/app/search/page.tsx +++ b/frontend/src/app/knowledge/page.tsx @@ -3,11 +3,9 @@ import { useState, useEffect, useCallback, useRef } from "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 { Badge } from "@/components/ui/badge" -import { Search, Loader2, FileText, Zap, RefreshCw } from "lucide-react" +import { Search, Loader2, FileText } from "lucide-react" import { ProtectedRoute } from "@/components/protected-route" import { useKnowledgeFilter } from "@/contexts/knowledge-filter-context" @@ -30,7 +28,7 @@ interface SearchResponse { function SearchPage() { - const { selectedFilter, parsedFilterData } = useKnowledgeFilter() + const { parsedFilterData } = useKnowledgeFilter() const [query, setQuery] = useState("") const [loading, setLoading] = useState(false) const [results, setResults] = useState([]) @@ -161,12 +159,23 @@ function SearchPage() { }, [parsedFilterData, searchPerformed, query, handleSearch]) // Fetch stats with current knowledge filter applied - const fetchStats = async () => { + const fetchStats = useCallback(async () => { try { setStatsLoading(true) // Build search payload with current filter data - const searchPayload: any = { + interface SearchPayload { + query: string; + limit: number; + scoreThreshold: number; + filters?: { + data_sources?: string[]; + document_types?: string[]; + owners?: string[]; + }; + } + + const searchPayload: SearchPayload = { query: '*', limit: 0, scoreThreshold: parsedFilterData?.scoreThreshold || 0 @@ -183,7 +192,7 @@ function SearchPage() { !filters.owners.includes("*") if (hasSpecificFilters) { - const processedFilters: any = {} + const processedFilters: SearchPayload['filters'] = {} // Only add filter arrays that don't contain wildcards if (!filters.data_sources.includes("*")) { @@ -227,12 +236,12 @@ function SearchPage() { } finally { setStatsLoading(false) } - } + }, [parsedFilterData]) // Initial stats fetch and refresh when filter changes useEffect(() => { fetchStats() - }, [parsedFilterData]) + }, [fetchStats]) diff --git a/frontend/src/app/knowledge-sources/page.tsx b/frontend/src/app/settings/page.tsx similarity index 81% rename from frontend/src/app/knowledge-sources/page.tsx rename to frontend/src/app/settings/page.tsx index 460fa244..3dfd583b 100644 --- a/frontend/src/app/knowledge-sources/page.tsx +++ b/frontend/src/app/settings/page.tsx @@ -62,11 +62,6 @@ function KnowledgeSourcesPage() { const [syncResults, setSyncResults] = useState<{[key: string]: SyncResult | null}>({}) const [maxFiles, setMaxFiles] = useState(10) - // Stats state (from wildcard search aggregations) - const [statsLoading, setStatsLoading] = useState(false) - const [totalDocs, setTotalDocs] = useState(0) - const [totalChunks, setTotalChunks] = useState(0) - const [facetStats, setFacetStats] = useState<{ data_sources: FacetBucket[]; document_types: FacetBucket[]; owners: FacetBucket[] } | null>(null) // File upload handlers const handleDirectFileUpload = async (file: File) => { @@ -87,8 +82,6 @@ function KnowledgeSourcesPage() { if (response.ok) { setUploadStatus(`File processed successfully! ID: ${result.id}`) - // Refresh stats after successful file upload - fetchStats() } else { setUploadStatus(`Error: ${result.error || "Processing failed"}`) } @@ -176,9 +169,6 @@ function KnowledgeSourcesPage() { addTask(taskId) setUploadStatus(`🔄 Processing started for ${totalFiles} files. Check the task notification panel for real-time progress. (Task ID: ${taskId})`) setBucketUrl("s3://") - - // Refresh stats after successful bucket upload - fetchStats() } else { setUploadStatus(`Error: ${result.error || "Bucket processing failed"}`) } @@ -389,37 +379,6 @@ function KnowledgeSourcesPage() { } }, [searchParams, isAuthenticated, checkConnectorStatuses]) - // Fetch global stats using match-all wildcard - const fetchStats = async () => { - try { - setStatsLoading(true) - const response = await fetch('/api/search', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ query: '*', limit: 0 }) - }) - const result = await response.json() - if (response.ok) { - const aggs = result.aggregations || {} - const toBuckets = (agg: { buckets?: Array<{ key: string | number; doc_count: number }> }): FacetBucket[] => - (agg?.buckets || []).map(b => ({ key: String(b.key), count: b.doc_count })) - const dataSourceBuckets = toBuckets(aggs.data_sources) - setFacetStats({ - data_sources: dataSourceBuckets.slice(0, 10), - document_types: toBuckets(aggs.document_types).slice(0, 10), - owners: toBuckets(aggs.owners).slice(0, 10) - }) - // Frontend-only doc count: number of distinct filenames (data_sources buckets) - setTotalDocs(dataSourceBuckets.length) - // Chunk count from hits.total (match_all over chunks) - setTotalChunks(Number(result.total || 0)) - } - } catch { - // non-fatal – keep page functional without stats - } finally { - setStatsLoading(false) - } - } // Check AWS availability useEffect(() => { @@ -437,10 +396,6 @@ function KnowledgeSourcesPage() { checkAws() }, []) - // Initial stats fetch - useEffect(() => { - fetchStats() - }, []) // Track previous tasks to detect new completions const [prevTasks, setPrevTasks] = useState([]) @@ -454,9 +409,9 @@ function KnowledgeSourcesPage() { }) if (newlyCompletedTasks.length > 0) { - // Refresh stats when any task newly completes + // Task completed - could refresh data here if needed const timeoutId = setTimeout(() => { - fetchStats() + // Stats refresh removed }, 1000) // Update previous tasks state @@ -471,95 +426,10 @@ function KnowledgeSourcesPage() { return (
- {/* Hero Section */} -
-
-

- Knowledge Sources -

-
-

- Add documents to your knowledge base -

-

- Import files and folders directly, or connect external services like Google Drive to automatically sync and index your documents. -

-
- - {/* Knowledge Overview Stats */} - - - -
Knowledge Overview
- -
- Snapshot of indexed content -
- - {/* Documents row */} -
-
-
Total documents
-
{statsLoading ? '—' : totalDocs}
-
-
- - {/* Separator */} -
- - {/* Chunks row */} -
-
-
Total chunks
-
{statsLoading ? '—' : totalChunks}
-
-
-
Top types
-
- {(facetStats?.document_types || []).slice(0,5).map((b) => ( - {b.key} · {b.count} - ))} -
-
-
-
Top owners
-
- {(facetStats?.owners || []).slice(0,5).map((b) => ( - {b.key || 'unknown'} · {b.count} - ))} -
-
-
-
Top files
-
- {(facetStats?.data_sources || []).slice(0,5).map((b) => ( - {b.key} · {b.count} - ))} -
-
-
- - - {/* Upload Section */}
-

Direct Import

-

- Add individual files or process entire folders from your local system -

+

Import

@@ -686,10 +556,7 @@ function KnowledgeSourcesPage() { {/* Connectors Section */}
-

Connectors

-

- Connect external services to automatically sync and index your documents -

+

Cloud Connectors

{/* Sync Settings */}