From c8845027379e95db8106e9f4115de4da4dcd4a8a Mon Sep 17 00:00:00 2001 From: Utkarsh-Patel-13 Date: Sat, 2 Aug 2025 22:46:15 -0700 Subject: [PATCH] Added breadcrumbs --- .../[search_space_id]/client-layout.tsx | 8 +- .../dashboard/[search_space_id]/layout.tsx | 1 - .../app/dashboard/[search_space_id]/page.tsx | 15 ++ .../components/dashboard-breadcrumb.tsx | 169 ++++++++++++++++++ surfsense_web/components/ui/breadcrumb.tsx | 100 +++++++++++ 5 files changed, 290 insertions(+), 3 deletions(-) create mode 100644 surfsense_web/app/dashboard/[search_space_id]/page.tsx create mode 100644 surfsense_web/components/dashboard-breadcrumb.tsx create mode 100644 surfsense_web/components/ui/breadcrumb.tsx diff --git a/surfsense_web/app/dashboard/[search_space_id]/client-layout.tsx b/surfsense_web/app/dashboard/[search_space_id]/client-layout.tsx index d785bdf..8b28c8b 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/client-layout.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/client-layout.tsx @@ -1,6 +1,7 @@ "use client"; import type React from "react"; +import { DashboardBreadcrumb } from "@/components/dashboard-breadcrumb"; import { AppSidebarProvider } from "@/components/sidebar/AppSidebarProvider"; import { ThemeTogglerComponent } from "@/components/theme/theme-toggle"; import { Separator } from "@/components/ui/separator"; @@ -28,8 +29,11 @@ export function DashboardClientLayout({
- - +
+ + + +
diff --git a/surfsense_web/app/dashboard/[search_space_id]/layout.tsx b/surfsense_web/app/dashboard/[search_space_id]/layout.tsx index 9dc1862..d0e04fe 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/layout.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/layout.tsx @@ -31,7 +31,6 @@ export default function DashboardLayout({ title: "Researcher", url: `/dashboard/${search_space_id}/researcher`, icon: "SquareTerminal", - isActive: true, items: [], }, diff --git a/surfsense_web/app/dashboard/[search_space_id]/page.tsx b/surfsense_web/app/dashboard/[search_space_id]/page.tsx new file mode 100644 index 0000000..cd697db --- /dev/null +++ b/surfsense_web/app/dashboard/[search_space_id]/page.tsx @@ -0,0 +1,15 @@ +"use client"; + +import { useParams, useRouter } from "next/navigation"; +import { useEffect } from "react"; + +export default function SearchSpaceDashboardPage() { + const router = useRouter(); + const { search_space_id } = useParams(); + + useEffect(() => { + router.push(`/dashboard/${search_space_id}/chats`); + }, []); + + return <>; +} diff --git a/surfsense_web/components/dashboard-breadcrumb.tsx b/surfsense_web/components/dashboard-breadcrumb.tsx new file mode 100644 index 0000000..1bc7abd --- /dev/null +++ b/surfsense_web/components/dashboard-breadcrumb.tsx @@ -0,0 +1,169 @@ +"use client"; + +import { usePathname } from "next/navigation"; +import React from "react"; +import { + Breadcrumb, + BreadcrumbItem, + BreadcrumbLink, + BreadcrumbList, + BreadcrumbPage, + BreadcrumbSeparator, +} from "@/components/ui/breadcrumb"; + +interface BreadcrumbItemInterface { + label: string; + href?: string; +} + +export function DashboardBreadcrumb() { + const pathname = usePathname(); + + // Parse the pathname to create breadcrumb items + const generateBreadcrumbs = (path: string): BreadcrumbItemInterface[] => { + const segments = path.split("/").filter(Boolean); + const breadcrumbs: BreadcrumbItemInterface[] = []; + + // Always start with Dashboard + breadcrumbs.push({ label: "Dashboard", href: "/dashboard" }); + + // Handle search space + if (segments[0] === "dashboard" && segments[1]) { + breadcrumbs.push({ label: `Search Space ${segments[1]}`, href: `/dashboard/${segments[1]}` }); + + // Handle specific sections + if (segments[2]) { + const section = segments[2]; + let sectionLabel = section.charAt(0).toUpperCase() + section.slice(1); + + // Map section names to more readable labels + const sectionLabels: Record = { + researcher: "Researcher", + documents: "Documents", + connectors: "Connectors", + podcasts: "Podcasts", + logs: "Logs", + chats: "Chats", + }; + + sectionLabel = sectionLabels[section] || sectionLabel; + + // Handle sub-sections + if (segments[3]) { + const subSection = segments[3]; + let subSectionLabel = subSection.charAt(0).toUpperCase() + subSection.slice(1); + + // Handle documents sub-sections + if (section === "documents") { + const documentLabels: Record = { + upload: "Upload Documents", + youtube: "Add YouTube Videos", + webpage: "Add Webpages", + }; + + const documentLabel = documentLabels[subSection] || subSectionLabel; + breadcrumbs.push({ + label: "Documents", + href: `/dashboard/${segments[1]}/documents`, + }); + breadcrumbs.push({ label: documentLabel }); + return breadcrumbs; + } + + // Handle connector sub-sections + if (section === "connectors") { + // Handle specific connector types + if (subSection === "add" && segments[4]) { + const connectorType = segments[4]; + const connectorLabels: Record = { + "github-connector": "GitHub", + "jira-connector": "Jira", + "confluence-connector": "Confluence", + "discord-connector": "Discord", + "linear-connector": "Linear", + "clickup-connector": "ClickUp", + "slack-connector": "Slack", + "notion-connector": "Notion", + "tavily-api": "Tavily API", + "serper-api": "Serper API", + "linkup-api": "LinkUp API", + }; + + const connectorLabel = connectorLabels[connectorType] || connectorType; + breadcrumbs.push({ + label: "Connectors", + href: `/dashboard/${segments[1]}/connectors`, + }); + breadcrumbs.push({ + label: "Add Connector", + href: `/dashboard/${segments[1]}/connectors/add`, + }); + breadcrumbs.push({ label: connectorLabel }); + return breadcrumbs; + } + + const connectorLabels: Record = { + add: "Add Connector", + manage: "Manage Connectors", + }; + + const connectorLabel = connectorLabels[subSection] || subSectionLabel; + breadcrumbs.push({ + label: "Connectors", + href: `/dashboard/${segments[1]}/connectors`, + }); + breadcrumbs.push({ label: connectorLabel }); + return breadcrumbs; + } + + // Handle other sub-sections + const subSectionLabels: Record = { + upload: "Upload Documents", + youtube: "Add YouTube Videos", + webpage: "Add Webpages", + add: "Add Connector", + edit: "Edit Connector", + manage: "Manage", + }; + + subSectionLabel = subSectionLabels[subSection] || subSectionLabel; + + breadcrumbs.push({ + label: sectionLabel, + href: `/dashboard/${segments[1]}/${section}`, + }); + breadcrumbs.push({ label: subSectionLabel }); + } else { + breadcrumbs.push({ label: sectionLabel }); + } + } + } + + return breadcrumbs; + }; + + const breadcrumbs = generateBreadcrumbs(pathname); + + if (breadcrumbs.length <= 1) { + return null; // Don't show breadcrumbs for root dashboard + } + + return ( + + + {breadcrumbs.map((item, index) => ( + + + {index === breadcrumbs.length - 1 ? ( + {item.label} + ) : ( + {item.label} + )} + + {index < breadcrumbs.length - 1 && } + + ))} + + + ); +} diff --git a/surfsense_web/components/ui/breadcrumb.tsx b/surfsense_web/components/ui/breadcrumb.tsx new file mode 100644 index 0000000..e245157 --- /dev/null +++ b/surfsense_web/components/ui/breadcrumb.tsx @@ -0,0 +1,100 @@ +import { Slot } from "@radix-ui/react-slot"; +import { ChevronRight, MoreHorizontal } from "lucide-react"; + +import { cn } from "@/lib/utils"; + +function Breadcrumb({ ...props }: React.ComponentProps<"nav">) { + return