From 3a1bde1bb5a6260ab0ade4a5e2ffb713f0ac6d46 Mon Sep 17 00:00:00 2001 From: Cole Goldsmith Date: Thu, 2 Oct 2025 17:17:09 -0500 Subject: [PATCH] refactor page layout styles to use grid --- frontend/components/knowledge-dropdown.tsx | 110 +++++------------- .../components/knowledge-filter-panel.tsx | 4 +- frontend/src/app/globals.css | 25 ++++ frontend/src/app/knowledge/page.tsx | 49 +++----- frontend/src/app/settings/page.tsx | 50 ++++---- frontend/src/components/layout-wrapper.tsx | 69 ++++++----- .../src/components/task-notification-menu.tsx | 4 +- 7 files changed, 145 insertions(+), 166 deletions(-) diff --git a/frontend/components/knowledge-dropdown.tsx b/frontend/components/knowledge-dropdown.tsx index ee49fc3a..c70fb234 100644 --- a/frontend/components/knowledge-dropdown.tsx +++ b/frontend/components/knowledge-dropdown.tsx @@ -6,7 +6,6 @@ import { FolderOpen, Loader2, PlugZap, - Plus, Upload, } from "lucide-react"; import { useRouter } from "next/navigation"; @@ -25,15 +24,7 @@ import { Label } from "@/components/ui/label"; import { useTask } from "@/contexts/task-context"; import { cn } from "@/lib/utils"; -interface KnowledgeDropdownProps { - active?: boolean; - variant?: "navigation" | "button"; -} - -export function KnowledgeDropdown({ - active, - variant = "navigation", -}: KnowledgeDropdownProps) { +export function KnowledgeDropdown() { const { addTask } = useTask(); const router = useRouter(); const [isOpen, setIsOpen] = useState(false); @@ -437,77 +428,35 @@ export function KnowledgeDropdown({ return ( <>
- + /> + )} + + {isOpen && !isLoading && (
@@ -519,12 +468,13 @@ export function KnowledgeDropdown({ disabled={"disabled" in item ? item.disabled : false} title={"tooltip" in item ? item.tooltip : undefined} className={cn( - "w-full px-3 py-2 text-left text-sm hover:bg-accent hover:text-accent-foreground", + "w-full flex flex-nowrap items-center px-3 py-2 text-left text-sm hover:bg-accent hover:text-accent-foreground", "disabled" in item && item.disabled && "opacity-50 cursor-not-allowed hover:bg-transparent hover:text-current" )} > + {item.icon && } {item.label} ))} @@ -561,7 +511,7 @@ export function KnowledgeDropdown({ type="text" placeholder="/path/to/documents" value={folderPath} - onChange={e => setFolderPath(e.target.value)} + onChange={(e) => setFolderPath(e.target.value)} />
@@ -603,7 +553,7 @@ export function KnowledgeDropdown({ type="text" placeholder="s3://bucket/path" value={bucketUrl} - onChange={e => setBucketUrl(e.target.value)} + onChange={(e) => setBucketUrl(e.target.value)} />
diff --git a/frontend/components/knowledge-filter-panel.tsx b/frontend/components/knowledge-filter-panel.tsx index 6bf9285b..a45304e9 100644 --- a/frontend/components/knowledge-filter-panel.tsx +++ b/frontend/components/knowledge-filter-panel.tsx @@ -231,8 +231,8 @@ export function KnowledgeFilterPanel() { }; return ( -
- +
+
diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css index 150d1c56..22601457 100644 --- a/frontend/src/app/globals.css +++ b/frontend/src/app/globals.css @@ -53,6 +53,8 @@ --flow-icon: #2f67d0; --radius: 0.5rem; + + --app-header-height: 53px; } .dark { @@ -108,6 +110,29 @@ } @layer components { + .app-grid-cols-arrangement { + --sidebar-width: 0px; + --notifications-width: 0px; + --filters-width: 0px; + + @media (width >= 48rem) { + --sidebar-width: 288px; + } + + &.notifications-open { + --notifications-width: 320px; + } + &.filters-open { + --filters-width: 320px; + } + display: grid; + height: calc(100% - var(--app-header-height)); + grid-template-columns: var(--sidebar-width) 1fr var(--notifications-width) var( + --filters-width + ); + transition: grid-template-columns 0.3s ease-in-out; + } + .header-arrangement { @apply flex w-full h-[53px] items-center justify-between border-b border-border; } diff --git a/frontend/src/app/knowledge/page.tsx b/frontend/src/app/knowledge/page.tsx index 1b8b60ef..34595eb2 100644 --- a/frontend/src/app/knowledge/page.tsx +++ b/frontend/src/app/knowledge/page.tsx @@ -1,8 +1,8 @@ "use client"; -import type { ColDef } from "ag-grid-community"; +import { themeQuartz, type ColDef } from "ag-grid-community"; import { AgGridReact, type CustomCellRendererProps } from "ag-grid-react"; -import { Building2, Cloud, HardDrive, Search, Trash2, X } from "lucide-react"; +import { Building2, Cloud, HardDrive, Search, X } from "lucide-react"; import { useRouter } from "next/navigation"; import { type ChangeEvent, useCallback, useRef, useState } from "react"; import { SiGoogledrive } from "react-icons/si"; @@ -46,8 +46,8 @@ function getSourceIcon(connectorType?: string) { function SearchPage() { const router = useRouter(); - const { isMenuOpen, files: taskFiles } = useTask(); - const { selectedFilter, setSelectedFilter, parsedFilterData, isPanelOpen } = + const { files: taskFiles } = useTask(); + const { selectedFilter, setSelectedFilter, parsedFilterData } = useKnowledgeFilter(); const [selectedRows, setSelectedRows] = useState([]); const [showBulkDeleteDialog, setShowBulkDeleteDialog] = useState(false); @@ -144,7 +144,6 @@ function SearchPage() { { field: "avgScore", headerName: "Avg score", - initialFlex: 0.5, cellRenderer: ({ value }: CustomCellRendererProps) => { return ( @@ -229,32 +228,19 @@ function SearchPage() { }; return ( -
-
+ <> +
-

Project Knowledge

- +

Knowledge

{/* Search Input Area */} -
-
-
+
+ +
{selectedFilter?.name && (
setShowBulkDeleteDialog(true)} > - Delete + Delete )} +
+ +
params.data.filename} domLayout="normal" + theme={themeQuartz.withParams({ browserColorScheme: "inherit" })} onSelectionChanged={onSelectionChanged} noRowsOverlayComponent={() => (
@@ -347,15 +337,12 @@ function SearchPage() { selectedRows.length } document${ selectedRows.length > 1 ? "s" : "" - }? This will remove all chunks and data associated with these documents. This action cannot be undone. - -Documents to be deleted: -${selectedRows.map((row) => `• ${row.filename}`).join("\n")}`} + }? This will remove all chunks and data associated with these documents. This action cannot be undone.`} confirmText="Delete All" onConfirm={handleBulkDelete} isLoading={deleteDocumentMutation.isPending} /> -
+ ); } diff --git a/frontend/src/app/settings/page.tsx b/frontend/src/app/settings/page.tsx index 7530bcbb..587d3946 100644 --- a/frontend/src/app/settings/page.tsx +++ b/frontend/src/app/settings/page.tsx @@ -114,7 +114,8 @@ function KnowledgeSourcesPage() { const [chunkOverlap, setChunkOverlap] = useState(50); const [tableStructure, setTableStructure] = useState(false); const [ocr, setOcr] = useState(false); - const [pictureDescriptions, setPictureDescriptions] = useState(false); + const [pictureDescriptions, setPictureDescriptions] = + useState(false); // Fetch settings using React Query const { data: settings = {} } = useGetSettingsQuery({ @@ -164,7 +165,7 @@ function KnowledgeSourcesPage() { onSuccess: () => { console.log("Setting updated successfully"); }, - onError: error => { + onError: (error) => { console.error("Failed to update setting:", error.message); }, }); @@ -303,8 +304,8 @@ function KnowledgeSourcesPage() { // Initialize connectors list with metadata from backend const initialConnectors = connectorTypes - .filter(type => connectorsResult.connectors[type].available) // Only show available connectors - .map(type => ({ + .filter((type) => connectorsResult.connectors[type].available) // Only show available connectors + .map((type) => ({ id: type, name: connectorsResult.connectors[type].name, description: connectorsResult.connectors[type].description, @@ -327,8 +328,8 @@ function KnowledgeSourcesPage() { ); const isConnected = activeConnection !== undefined; - setConnectors(prev => - prev.map(c => + setConnectors((prev) => + prev.map((c) => c.type === connectorType ? { ...c, @@ -347,7 +348,7 @@ function KnowledgeSourcesPage() { const handleConnect = async (connector: Connector) => { setIsConnecting(connector.id); - setSyncResults(prev => ({ ...prev, [connector.id]: null })); + setSyncResults((prev) => ({ ...prev, [connector.id]: null })); try { // Use the shared auth callback URL, same as connectors page @@ -508,9 +509,9 @@ function KnowledgeSourcesPage() { // Watch for task completions and refresh stats useEffect(() => { // Find newly completed tasks by comparing with previous state - const newlyCompletedTasks = tasks.filter(task => { + const newlyCompletedTasks = tasks.filter((task) => { const wasCompleted = - prevTasks.find(prev => prev.task_id === task.task_id)?.status === + prevTasks.find((prev) => prev.task_id === task.task_id)?.status === "completed"; return task.status === "completed" && !wasCompleted; }); @@ -564,7 +565,7 @@ function KnowledgeSourcesPage() { fetch(`/api/reset-flow/retrieval`, { method: "POST", }) - .then(response => { + .then((response) => { if (response.ok) { return response.json(); } @@ -577,7 +578,7 @@ function KnowledgeSourcesPage() { handleModelChange(DEFAULT_AGENT_SETTINGS.llm_model); closeDialog(); // Close after successful completion }) - .catch(error => { + .catch((error) => { console.error("Error restoring retrieval flow:", error); closeDialog(); // Close even on error (could show error toast instead) }); @@ -587,7 +588,7 @@ function KnowledgeSourcesPage() { fetch(`/api/reset-flow/ingest`, { method: "POST", }) - .then(response => { + .then((response) => { if (response.ok) { return response.json(); } @@ -602,14 +603,14 @@ function KnowledgeSourcesPage() { setPictureDescriptions(false); closeDialog(); // Close after successful completion }) - .catch(error => { + .catch((error) => { console.error("Error restoring ingest flow:", error); closeDialog(); // Close even on error (could show error toast instead) }); }; return ( -
+
{/* Connectors Section */}
@@ -700,7 +701,7 @@ function KnowledgeSourcesPage() { {/* Connectors Grid */}
- {connectors.map(connector => ( + {connectors.map((connector) => (
@@ -834,7 +835,7 @@ function KnowledgeSourcesPage() { } confirmText="Proceed" confirmIcon={} - onConfirm={closeDialog => + onConfirm={(closeDialog) => handleEditInLangflow("chat", closeDialog) } variant="warning" @@ -854,7 +855,8 @@ function KnowledgeSourcesPage() {