From 99bf3772b50131ddbdee9e8c09435bb900f0ff3b Mon Sep 17 00:00:00 2001 From: Brent O'Neill Date: Fri, 19 Sep 2025 12:16:20 -0600 Subject: [PATCH 01/12] updated header for chunks page --- frontend/src/app/knowledge/chunks/page.tsx | 67 ++++++++++++++++------ 1 file changed, 50 insertions(+), 17 deletions(-) diff --git a/frontend/src/app/knowledge/chunks/page.tsx b/frontend/src/app/knowledge/chunks/page.tsx index 9385c474..254eb511 100644 --- a/frontend/src/app/knowledge/chunks/page.tsx +++ b/frontend/src/app/knowledge/chunks/page.tsx @@ -1,8 +1,10 @@ "use client"; import { + ArrowLeft, Building2, Cloud, + File as FileIcon, FileText, HardDrive, Loader2, @@ -21,6 +23,9 @@ import { type File, useGetSearchQuery, } from "../../api/queries/useGetSearchQuery"; +import { Label } from "@/components/ui/label"; +import { Checkbox } from "@/components/ui/checkbox"; +import { Input } from "@/components/ui/input"; // Function to get the appropriate icon for a connector type function getSourceIcon(connectorType?: string) { @@ -47,9 +52,14 @@ function ChunksPageContent() { const filename = searchParams.get("filename"); const [chunks, setChunks] = useState([]); + const [selectAll, setSelectAll] = useState(false); + const [queryInputText, setQueryInputText] = useState( + parsedFilterData?.query ?? "" + ); + // Use the same search query as the knowledge page, but we'll filter for the specific file const { data = [], isFetching } = useGetSearchQuery("*", parsedFilterData); - + console.log({ data }); // Extract chunks for the specific file useEffect(() => { if (!filename || !(data as File[]).length) { @@ -98,30 +108,53 @@ function ChunksPageContent() { >
{/* Header */} -
-
- -
-

Document Chunks

-

- {decodeURIComponent(filename)} -

+
+
+
+ setSelectAll(checked === true)} + /> + +
+
+ setQueryInputText(e.target.value)} + placeholder="Search chunks..." + className="flex-1 bg-muted/20 rounded-lg border border-border/50 px-4 py-3 focus-visible:ring-1 focus-visible:ring-ring" + /> +
-
+ {/*
{!isFetching && chunks.length > 0 && ( {chunks.length} chunk{chunks.length !== 1 ? "s" : ""} found )} -
+
*/}
{/* Content Area - matches knowledge page structure */} From 9fdec36e9c5c6a7369738c53904a49ed358b6ed5 Mon Sep 17 00:00:00 2001 From: Brent O'Neill Date: Mon, 22 Sep 2025 13:06:19 -0600 Subject: [PATCH 02/12] make the search filter work --- frontend/src/app/knowledge/chunks/page.tsx | 107 +++++++++++---------- 1 file changed, 56 insertions(+), 51 deletions(-) diff --git a/frontend/src/app/knowledge/chunks/page.tsx b/frontend/src/app/knowledge/chunks/page.tsx index 254eb511..450032a8 100644 --- a/frontend/src/app/knowledge/chunks/page.tsx +++ b/frontend/src/app/knowledge/chunks/page.tsx @@ -2,18 +2,13 @@ import { ArrowLeft, - Building2, - Cloud, + Copy, File as FileIcon, - FileText, - HardDrive, Loader2, Search, } from "lucide-react"; import { Suspense, useCallback, useEffect, useState } from "react"; import { useRouter, useSearchParams } from "next/navigation"; -import { SiGoogledrive } from "react-icons/si"; -import { TbBrandOnedrive } from "react-icons/tb"; import { ProtectedRoute } from "@/components/protected-route"; import { Button } from "@/components/ui/button"; import { useKnowledgeFilter } from "@/contexts/knowledge-filter-context"; @@ -27,22 +22,6 @@ import { Label } from "@/components/ui/label"; import { Checkbox } from "@/components/ui/checkbox"; import { Input } from "@/components/ui/input"; -// Function to get the appropriate icon for a connector type -function getSourceIcon(connectorType?: string) { - switch (connectorType) { - case "google_drive": - return ; - case "onedrive": - return ; - case "sharepoint": - return ; - case "s3": - return ; - default: - return ; - } -} - function ChunksPageContent() { const router = useRouter(); const searchParams = useSearchParams(); @@ -51,12 +30,32 @@ function ChunksPageContent() { const filename = searchParams.get("filename"); const [chunks, setChunks] = useState([]); + const [chunksFilteredByQuery, setChunksFilteredByQuery] = useState< + ChunkResult[] + >([]); const [selectAll, setSelectAll] = useState(false); const [queryInputText, setQueryInputText] = useState( parsedFilterData?.query ?? "" ); + useEffect(() => { + if (queryInputText === "") { + setChunksFilteredByQuery(chunks); + } else { + setChunksFilteredByQuery((prevChunks) => + prevChunks.filter((chunk) => + chunk.text.toLowerCase().includes(queryInputText.toLowerCase()) + ) + ); + } + }, [queryInputText, chunks]); + + const handleCopy = useCallback((text: string) => { + console.log("copying text to clipboard:", text); + navigator.clipboard.writeText(text); + }, []); + // Use the same search query as the knowledge page, but we'll filter for the specific file const { data = [], isFetching } = useGetSearchQuery("*", parsedFilterData); console.log({ data }); @@ -118,7 +117,7 @@ function ChunksPageContent() {
-
+
- {/*
- {!isFetching && chunks.length > 0 && ( - - {chunks.length} chunk{chunks.length !== 1 ? "s" : ""} found - - )} -
*/}
{/* Content Area - matches knowledge page structure */} @@ -180,35 +172,48 @@ function ChunksPageContent() {
) : (
- {chunks.map((chunk, index) => ( + {chunksFilteredByQuery.map((chunk, index) => (
-
- - - {chunk.filename} +
+
+ +
+ + Chunk {chunk.page} - {chunk.connector_type && ( -
- {getSourceIcon(chunk.connector_type)} -
- )} + + {chunk.text.length} chars + +
+ +
- - {chunk.score.toFixed(2)} - + + {/* TODO: Update to use active toggle */} + {/* + + Active + */}
-
- {chunk.mimetype} - Page {chunk.page} - {chunk.owner_name && Owner: {chunk.owner_name}} +
+
+ {chunk.text} +
-

- {chunk.text} -

))}
From fc5f67e244f02f18523e95824bb7be13d006cdd9 Mon Sep 17 00:00:00 2001 From: Brent O'Neill Date: Mon, 22 Sep 2025 14:23:03 -0600 Subject: [PATCH 03/12] Added technical details section --- frontend/src/app/knowledge/chunks/page.tsx | 112 +++++++++++++++++++-- 1 file changed, 101 insertions(+), 11 deletions(-) diff --git a/frontend/src/app/knowledge/chunks/page.tsx b/frontend/src/app/knowledge/chunks/page.tsx index 450032a8..0a5a00a3 100644 --- a/frontend/src/app/knowledge/chunks/page.tsx +++ b/frontend/src/app/knowledge/chunks/page.tsx @@ -7,7 +7,7 @@ import { Loader2, Search, } from "lucide-react"; -import { Suspense, useCallback, useEffect, useState } from "react"; +import { Suspense, useCallback, useEffect, useMemo, useState } from "react"; import { useRouter, useSearchParams } from "next/navigation"; import { ProtectedRoute } from "@/components/protected-route"; import { Button } from "@/components/ui/button"; @@ -22,6 +22,12 @@ import { Label } from "@/components/ui/label"; import { Checkbox } from "@/components/ui/checkbox"; import { Input } from "@/components/ui/input"; +const getFileTypeLabel = (mimetype: string) => { + if (mimetype === "application/pdf") return "PDF"; + if (mimetype === "text/plain") return "Text"; + if (mimetype === "application/msword") return "Word Document"; +}; + function ChunksPageContent() { const router = useRouter(); const searchParams = useSearchParams(); @@ -33,12 +39,21 @@ function ChunksPageContent() { const [chunksFilteredByQuery, setChunksFilteredByQuery] = useState< ChunkResult[] >([]); + const averageChunkLength = useMemo( + () => + chunks.reduce((acc, chunk) => acc + chunk.text.length, 0) / + chunks.length || 0, + [chunks] + ); const [selectAll, setSelectAll] = useState(false); const [queryInputText, setQueryInputText] = useState( parsedFilterData?.query ?? "" ); + // Use the same search query as the knowledge page, but we'll filter for the specific file + const { data = [], isFetching } = useGetSearchQuery("*", parsedFilterData); + useEffect(() => { if (queryInputText === "") { setChunksFilteredByQuery(chunks); @@ -52,13 +67,14 @@ function ChunksPageContent() { }, [queryInputText, chunks]); const handleCopy = useCallback((text: string) => { - console.log("copying text to clipboard:", text); navigator.clipboard.writeText(text); }, []); - // Use the same search query as the knowledge page, but we'll filter for the specific file - const { data = [], isFetching } = useGetSearchQuery("*", parsedFilterData); - console.log({ data }); + const fileData = (data as File[]).find( + (file: File) => file.filename === filename + ); + + console.log({ fileData }); // Extract chunks for the specific file useEffect(() => { if (!filename || !(data as File[]).length) { @@ -66,11 +82,8 @@ function ChunksPageContent() { return; } - const fileData = (data as File[]).find( - (file: File) => file.filename === filename - ); setChunks(fileData?.chunks || []); - }, [data, filename]); + }, [data, filename, fileData?.chunks]); const handleBack = useCallback(() => { router.back(); @@ -90,9 +103,11 @@ function ChunksPageContent() { ); } + console.log({ data }); + return (
*/}
-
+
{chunk.text}
@@ -220,6 +235,81 @@ function ChunksPageContent() { )}
+ {/* Right panel - Summary (TODO), Technical details, */} +
+
+

Technical details

+
+
+
Total chunks
+
+ {chunks.length} +
+
+
+
Avg length
+
+ {averageChunkLength.toFixed(0)} chars +
+
+
+
Process time
+
+ {/* {averageChunkLength.toFixed(0)} chars */} +
+
+
+
Model
+
+ {/* {averageChunkLength.toFixed(0)} chars */} +
+
+
+
+
+

Original document

+
+
+
Name
+
+ {fileData?.filename} +
+
+
+
Type
+
+ {fileData ? getFileTypeLabel(fileData.mimetype) : "Unknown"} +
+
+
+
Size
+
+ {fileData?.size + ? `${Math.round(fileData.size / 1024)} KB` + : "Unknown"} +
+
+
+
Uploaded
+
+ {fileData?.uploaded || "Unknown"} +
+
+
+
Source
+
+ {/* {fileData?.uploaded || "Unknown"} */} +
+
+
+
Updated
+
+ N/A +
+
+
+
+
); } From 13f75411900eedb0dee46a960f72c6271ec0f102 Mon Sep 17 00:00:00 2001 From: Brent O'Neill Date: Mon, 22 Sep 2025 14:23:50 -0600 Subject: [PATCH 04/12] finish stubbing data --- frontend/src/app/knowledge/chunks/page.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/knowledge/chunks/page.tsx b/frontend/src/app/knowledge/chunks/page.tsx index 0a5a00a3..e9b66187 100644 --- a/frontend/src/app/knowledge/chunks/page.tsx +++ b/frontend/src/app/knowledge/chunks/page.tsx @@ -292,14 +292,12 @@ function ChunksPageContent() {
Uploaded
- {fileData?.uploaded || "Unknown"} + N/A
Source
-
- {/* {fileData?.uploaded || "Unknown"} */} -
+
Updated
From 8a17cccf3d7fc87e706bfb26ebaa9c7aecda3bd4 Mon Sep 17 00:00:00 2001 From: Brent O'Neill Date: Mon, 22 Sep 2025 14:29:13 -0600 Subject: [PATCH 05/12] remove console.logs --- frontend/src/app/knowledge/chunks/page.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/frontend/src/app/knowledge/chunks/page.tsx b/frontend/src/app/knowledge/chunks/page.tsx index e9b66187..b59a8760 100644 --- a/frontend/src/app/knowledge/chunks/page.tsx +++ b/frontend/src/app/knowledge/chunks/page.tsx @@ -74,7 +74,6 @@ function ChunksPageContent() { (file: File) => file.filename === filename ); - console.log({ fileData }); // Extract chunks for the specific file useEffect(() => { if (!filename || !(data as File[]).length) { @@ -103,8 +102,6 @@ function ChunksPageContent() { ); } - console.log({ data }); - return (
Date: Tue, 23 Sep 2025 11:53:58 -0600 Subject: [PATCH 06/12] commit and make select work --- frontend/src/app/knowledge/chunks/page.tsx | 60 ++++++++++++++++------ 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/frontend/src/app/knowledge/chunks/page.tsx b/frontend/src/app/knowledge/chunks/page.tsx index b59a8760..9a889dae 100644 --- a/frontend/src/app/knowledge/chunks/page.tsx +++ b/frontend/src/app/knowledge/chunks/page.tsx @@ -39,6 +39,9 @@ function ChunksPageContent() { const [chunksFilteredByQuery, setChunksFilteredByQuery] = useState< ChunkResult[] >([]); + const [selectedChunks, setSelectedChunks] = useState>(new Set()); + + // Calculate average chunk length const averageChunkLength = useMemo( () => chunks.reduce((acc, chunk) => acc + chunk.text.length, 0) / @@ -84,10 +87,34 @@ function ChunksPageContent() { setChunks(fileData?.chunks || []); }, [data, filename, fileData?.chunks]); + // Set selected state for all checkboxes when selectAll changes + useEffect(() => { + if (selectAll) { + setSelectedChunks(new Set(chunks.map((_, index) => index))); + } else { + setSelectedChunks(new Set()); + } + }, [selectAll, setSelectedChunks, chunks]); + const handleBack = useCallback(() => { - router.back(); + router.push("/knowledge"); }, [router]); + const handleChunkCardCheckboxChange = useCallback( + (index: number) => { + setSelectedChunks((prevSelected) => { + const newSelected = new Set(prevSelected); + if (newSelected.has(index)) { + newSelected.delete(index); + } else { + newSelected.add(index); + } + return newSelected; + }); + }, + [setSelectedChunks] + ); + if (!filename) { return (
@@ -134,11 +161,13 @@ function ChunksPageContent() { setSelectAll(checked === true)} + onCheckedChange={(handleSelectAll) => + setSelectAll(!!handleSelectAll) + } /> @@ -192,7 +221,10 @@ function ChunksPageContent() {
- + handleChunkCardCheckboxChange(index)} + />
Chunk {chunk.page} @@ -221,11 +253,9 @@ function ChunksPageContent() { Active */}
-
-
- {chunk.text} -
-
+
+ {chunk.text} +
))}
@@ -249,18 +279,17 @@ function ChunksPageContent() { {averageChunkLength.toFixed(0)} chars
-
+ {/* TODO: Uncomment after data is available */} + {/*
Process time
- {/* {averageChunkLength.toFixed(0)} chars */}
Model
- {/* {averageChunkLength.toFixed(0)} chars */}
-
+
*/}
@@ -292,10 +321,11 @@ function ChunksPageContent() { N/A
-
+ {/* TODO: Uncomment after data is available */} + {/*
Source
-
+
*/}
Updated
From a425ba62fbcc34bb3b10281a44ba48edc466fe3e Mon Sep 17 00:00:00 2001 From: boneill-ds Date: Tue, 23 Sep 2025 13:24:25 -0600 Subject: [PATCH 07/12] Update frontend/src/app/knowledge/chunks/page.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- frontend/src/app/knowledge/chunks/page.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/app/knowledge/chunks/page.tsx b/frontend/src/app/knowledge/chunks/page.tsx index 9a889dae..c55690c5 100644 --- a/frontend/src/app/knowledge/chunks/page.tsx +++ b/frontend/src/app/knowledge/chunks/page.tsx @@ -26,6 +26,7 @@ const getFileTypeLabel = (mimetype: string) => { if (mimetype === "application/pdf") return "PDF"; if (mimetype === "text/plain") return "Text"; if (mimetype === "application/msword") return "Word Document"; + return "Unknown"; }; function ChunksPageContent() { From 3cb33526dbf1fd9f28a89e2d8895911c027b4a2d Mon Sep 17 00:00:00 2001 From: boneill-ds Date: Tue, 23 Sep 2025 13:24:41 -0600 Subject: [PATCH 08/12] Update frontend/src/app/knowledge/chunks/page.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- frontend/src/app/knowledge/chunks/page.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/knowledge/chunks/page.tsx b/frontend/src/app/knowledge/chunks/page.tsx index c55690c5..d538ce36 100644 --- a/frontend/src/app/knowledge/chunks/page.tsx +++ b/frontend/src/app/knowledge/chunks/page.tsx @@ -62,8 +62,8 @@ function ChunksPageContent() { if (queryInputText === "") { setChunksFilteredByQuery(chunks); } else { - setChunksFilteredByQuery((prevChunks) => - prevChunks.filter((chunk) => + setChunksFilteredByQuery( + chunks.filter((chunk) => chunk.text.toLowerCase().includes(queryInputText.toLowerCase()) ) ); From c33b5bcd4ed265c3e3d57d9b1436fdd2121a1e77 Mon Sep 17 00:00:00 2001 From: boneill-ds Date: Tue, 23 Sep 2025 13:24:49 -0600 Subject: [PATCH 09/12] Update frontend/src/app/knowledge/chunks/page.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- frontend/src/app/knowledge/chunks/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/knowledge/chunks/page.tsx b/frontend/src/app/knowledge/chunks/page.tsx index d538ce36..52b4bcfd 100644 --- a/frontend/src/app/knowledge/chunks/page.tsx +++ b/frontend/src/app/knowledge/chunks/page.tsx @@ -86,7 +86,7 @@ function ChunksPageContent() { } setChunks(fileData?.chunks || []); - }, [data, filename, fileData?.chunks]); + }, [data, filename]); // Set selected state for all checkboxes when selectAll changes useEffect(() => { From 9caebae22e03b2c795d85dde3f0326c99280ab7b Mon Sep 17 00:00:00 2001 From: boneill-ds Date: Tue, 23 Sep 2025 13:24:57 -0600 Subject: [PATCH 10/12] Update frontend/src/app/knowledge/chunks/page.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- frontend/src/app/knowledge/chunks/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/knowledge/chunks/page.tsx b/frontend/src/app/knowledge/chunks/page.tsx index 52b4bcfd..73a687b1 100644 --- a/frontend/src/app/knowledge/chunks/page.tsx +++ b/frontend/src/app/knowledge/chunks/page.tsx @@ -227,7 +227,7 @@ function ChunksPageContent() { onClick={() => handleChunkCardCheckboxChange(index)} />
- + Chunk {chunk.page} From 5a473541ad0ce934af4c879156745d30c608133f Mon Sep 17 00:00:00 2001 From: boneill-ds Date: Tue, 23 Sep 2025 13:25:40 -0600 Subject: [PATCH 11/12] Update frontend/src/app/knowledge/chunks/page.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- frontend/src/app/knowledge/chunks/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/knowledge/chunks/page.tsx b/frontend/src/app/knowledge/chunks/page.tsx index 73a687b1..7de98830 100644 --- a/frontend/src/app/knowledge/chunks/page.tsx +++ b/frontend/src/app/knowledge/chunks/page.tsx @@ -224,7 +224,7 @@ function ChunksPageContent() {
handleChunkCardCheckboxChange(index)} + onCheckedChange={(checked) => handleChunkCardCheckboxChange(checked, index)} />
From 1808ccc149c3dccc490e630b10d10d55d935bf6a Mon Sep 17 00:00:00 2001 From: Brent O'Neill Date: Tue, 23 Sep 2025 13:59:35 -0600 Subject: [PATCH 12/12] fix selection --- frontend/src/app/knowledge/chunks/page.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/knowledge/chunks/page.tsx b/frontend/src/app/knowledge/chunks/page.tsx index 7de98830..cdc9fcc3 100644 --- a/frontend/src/app/knowledge/chunks/page.tsx +++ b/frontend/src/app/knowledge/chunks/page.tsx @@ -224,7 +224,9 @@ function ChunksPageContent() {
handleChunkCardCheckboxChange(checked, index)} + onCheckedChange={() => + handleChunkCardCheckboxChange(index) + } />