From bb8c03e6ea165b76c39bfe8f0b8c8534847985d8 Mon Sep 17 00:00:00 2001 From: dextmorgn Date: Sun, 30 Mar 2025 23:46:42 +0200 Subject: [PATCH] feat: new layout --- flowsint-web/src/app/dashboard/keys/page.tsx | 2 - flowsint-web/src/app/dashboard/layout.tsx | 29 +++++++- flowsint-web/src/app/dashboard/page.tsx | 8 +- .../individuals/[individual_id]/client.tsx | 37 ---------- .../[investigation_id]/client.tsx | 8 +- .../dashboard/projects/[project_id]/page.tsx | 17 ++--- .../src/app/dashboard/settings/layout.tsx | 30 ++++---- .../src/components/dashboard/main-nav.tsx | 47 ++++++++++++ .../src/components/dashboard/sub-nav.tsx | 73 +++++++++++++++++++ .../investigations/case-selector.tsx | 1 + .../investigations/individual-modal.tsx | 60 +++++++-------- .../investigation-navigation.tsx | 62 ++++++++++++++++ .../src/components/investigations/layout.tsx | 61 +--------------- .../investigations/project-navigation.tsx | 65 +++++++++++++++++ .../investigations/sketch/graph.tsx | 17 +---- flowsint-web/src/components/nav-user.tsx | 8 +- 16 files changed, 340 insertions(+), 185 deletions(-) delete mode 100644 flowsint-web/src/app/dashboard/projects/[project_id]/individuals/[individual_id]/client.tsx create mode 100644 flowsint-web/src/components/dashboard/main-nav.tsx create mode 100644 flowsint-web/src/components/dashboard/sub-nav.tsx create mode 100644 flowsint-web/src/components/investigations/investigation-navigation.tsx create mode 100644 flowsint-web/src/components/investigations/project-navigation.tsx diff --git a/flowsint-web/src/app/dashboard/keys/page.tsx b/flowsint-web/src/app/dashboard/keys/page.tsx index bfd6329..47ebd27 100644 --- a/flowsint-web/src/app/dashboard/keys/page.tsx +++ b/flowsint-web/src/app/dashboard/keys/page.tsx @@ -18,7 +18,6 @@ export default function TokensPage() { ]) return ( -
@@ -146,7 +145,6 @@ export default function TokensPage() {
- ) } diff --git a/flowsint-web/src/app/dashboard/layout.tsx b/flowsint-web/src/app/dashboard/layout.tsx index a556bc4..3ba635e 100644 --- a/flowsint-web/src/app/dashboard/layout.tsx +++ b/flowsint-web/src/app/dashboard/layout.tsx @@ -1,10 +1,16 @@ -import { AppSidebar } from "@/components/app-sidebar" import { createClient } from "@/lib/supabase/server"; import { SidebarInset, SidebarProvider, } from "@/components/ui/sidebar" import { redirect } from "next/navigation"; +import { Radar, Settings } from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { MainNav } from "@/components/dashboard/main-nav"; +import { NavUser } from "@/components/nav-user"; +import { SubNav } from "@/components/dashboard/sub-nav"; +import Feedback from "@/components/dashboard/feedback"; +import Link from "next/link"; const DashboardLayout = async ({ children, @@ -18,11 +24,28 @@ const DashboardLayout = async ({ if (userError || !data?.user) { redirect('/login') } + return ( - -
+
+
+
+ + +

flowsint

+ + +
+
+ + + +
+ +
+
+
{children}
diff --git a/flowsint-web/src/app/dashboard/page.tsx b/flowsint-web/src/app/dashboard/page.tsx index 332f634..fee75b9 100644 --- a/flowsint-web/src/app/dashboard/page.tsx +++ b/flowsint-web/src/app/dashboard/page.tsx @@ -17,6 +17,7 @@ import NewProject from "@/components/dashboard/new-project" import { AvatarList } from "@/components/avatar-list" import { cn } from "@/lib/utils" import DashboardLayout from "@/components/dashboard/layout" +import { SubNav } from "@/components/dashboard/sub-nav" const DashboardPage = () => { const [searchQuery, setSearchQuery] = useState("") @@ -38,7 +39,10 @@ const DashboardPage = () => { ) return ( - + <> +
+ +

Welcome back, Eliott

@@ -160,7 +164,7 @@ const DashboardPage = () => {
)}
-
+ ) } diff --git a/flowsint-web/src/app/dashboard/projects/[project_id]/individuals/[individual_id]/client.tsx b/flowsint-web/src/app/dashboard/projects/[project_id]/individuals/[individual_id]/client.tsx deleted file mode 100644 index 6681ad5..0000000 --- a/flowsint-web/src/app/dashboard/projects/[project_id]/individuals/[individual_id]/client.tsx +++ /dev/null @@ -1,37 +0,0 @@ -"use client" -import { useQuery } from "@tanstack/react-query" -import InvestigationGraph from "@/components/investigations/sketch/graph" -import LargeInvestigationGraph from '@/components/investigations/sketch/large-data-graph' -import IndividualModal from "@/components/investigations/individual-modal" -import { notFound } from "next/navigation" -import { useQueryState } from "nuqs" -interface ProfileProps { - projectId: string - individualId: string -} -export default function DashboardClient({ projectId, individualId }: ProfileProps) { - // Use the initial data from the server, but enable background updates - const [view, _] = useQueryState("view", { defaultValue: "flow-graph" }) - const graphQuery = useQuery({ - queryKey: ["project", individualId, "individuals", individualId], - queryFn: async () => { - const res = await fetch(`/api/projects/${projectId}/individuals/${individualId}`) - if (!res.ok) { - notFound() - } - return res.json() - }, - refetchOnWindowFocus: true, - }) - return ( -
- {view === "flow-graph" ? - - : - - } - -
- ) -} - diff --git a/flowsint-web/src/app/dashboard/projects/[project_id]/investigations/[investigation_id]/client.tsx b/flowsint-web/src/app/dashboard/projects/[project_id]/investigations/[investigation_id]/client.tsx index 5fa0313..140c7a8 100644 --- a/flowsint-web/src/app/dashboard/projects/[project_id]/investigations/[investigation_id]/client.tsx +++ b/flowsint-web/src/app/dashboard/projects/[project_id]/investigations/[investigation_id]/client.tsx @@ -5,6 +5,7 @@ import LargeInvestigationGraph from '@/components/investigations/sketch/large-da import IndividualModal from "@/components/investigations/individual-modal" import { notFound } from "next/navigation" import { useQueryState } from "nuqs" +import { InvestigationtNavigation } from "@/components/investigations/investigation-navigation" interface DashboardClientProps { projectId: string investigationId: string @@ -24,14 +25,17 @@ export default function DashboardClient({ projectId, investigationId }: Dashboar refetchOnWindowFocus: true, }) return ( -
+ <> +
+ +
{view === "flow-graph" ? : } -
+ ) } diff --git a/flowsint-web/src/app/dashboard/projects/[project_id]/page.tsx b/flowsint-web/src/app/dashboard/projects/[project_id]/page.tsx index f359d41..30bbd68 100644 --- a/flowsint-web/src/app/dashboard/projects/[project_id]/page.tsx +++ b/flowsint-web/src/app/dashboard/projects/[project_id]/page.tsx @@ -11,19 +11,11 @@ import Loader from "@/components/loader" import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu" import { format, formatDistanceToNow } from "date-fns" import Link from "next/link" -import { - Breadcrumb, - BreadcrumbItem, - BreadcrumbLink, - BreadcrumbList, - BreadcrumbPage, - BreadcrumbSeparator, -} from "@/components/ui/breadcrumb" import { Investigation } from "@/types/investigation" import NewCase from "@/components/dashboard/new-sketch" import { DocumentList } from "@/components/projects/documents-list" import { cn } from "@/lib/utils" -import DashboardLayout from "@/components/dashboard/layout" +import { ProjectNavigation } from "@/components/investigations/project-navigation" const DashboardPage = () => { const { project_id } = useParams() @@ -64,7 +56,10 @@ const DashboardPage = () => { const isRefetching = isRefetchingDocs || isRefetchingSketches return ( - + <> +
+ +
@@ -180,7 +175,7 @@ const DashboardPage = () => {
)}
- + ) } diff --git a/flowsint-web/src/app/dashboard/settings/layout.tsx b/flowsint-web/src/app/dashboard/settings/layout.tsx index d1563bb..18a1fcc 100644 --- a/flowsint-web/src/app/dashboard/settings/layout.tsx +++ b/flowsint-web/src/app/dashboard/settings/layout.tsx @@ -39,22 +39,20 @@ interface SettingsLayoutProps { export default function SettingsLayout({ children }: SettingsLayoutProps) { return ( - -
-
-

Settings

-

- Manage your account settings and set e-mail preferences. -

-
- -
- -
{children}
-
+
+
+

Settings

+

+ Manage your account settings and set e-mail preferences. +

- + +
+ +
{children}
+
+
) } diff --git a/flowsint-web/src/components/dashboard/main-nav.tsx b/flowsint-web/src/components/dashboard/main-nav.tsx new file mode 100644 index 0000000..5184782 --- /dev/null +++ b/flowsint-web/src/components/dashboard/main-nav.tsx @@ -0,0 +1,47 @@ +"use client" +import type React from "react" +import Link from "next/link" +import { cn } from "@/lib/utils" +import ProjectSelector from "../investigations/project-selector" +import CaseSelector from "../investigations/case-selector" +import { useParams } from "next/navigation" + +export function MainNav({ className, ...props }: React.HTMLAttributes) { + const { investigation_id, project_id } = useParams() + + if (project_id) return ( +
+ {investigation_id && <>/} +
+ ) + + return ( + + ) +} + diff --git a/flowsint-web/src/components/dashboard/sub-nav.tsx b/flowsint-web/src/components/dashboard/sub-nav.tsx new file mode 100644 index 0000000..94afb99 --- /dev/null +++ b/flowsint-web/src/components/dashboard/sub-nav.tsx @@ -0,0 +1,73 @@ +"use client" + +import { cn } from "@/lib/utils" +import { Eye, Users, Camera, Database, Settings } from "lucide-react" +import Link from "next/link" +import { usePathname } from "next/navigation" +import { useState } from "react" + + +export function SubNav() { + const pathname = usePathname() + const sections = [ + { + id: "overview", + name: "Overview", + href: "/dashboard", + icon: Eye, + count: 18, + }, + { + id: "investigations", + name: "Investigations", + href: "/dashboard/investigations", + icon: Users, + count: 24, + }, + { + id: "surveillance", + name: "Surveillance", + href: "/dashboard/surveillance", + icon: Camera, + count: 6, + }, + { + id: "intelligence", + name: "Intelligence", + href: "/dashboard/intelligence", + icon: Database, + count: 16, + }, + { + id: "configurations", + name: "Configurations", + href: "/dashboard/settings", + icon: Settings, + count: null, + }, + ] + + return ( +
+ {sections.map((section) => ( + + + {section.name} + {section.count !== null && ( + {section.count} + )} + + ))} +
+ ) +} + diff --git a/flowsint-web/src/components/investigations/case-selector.tsx b/flowsint-web/src/components/investigations/case-selector.tsx index 10892d8..e665da3 100644 --- a/flowsint-web/src/components/investigations/case-selector.tsx +++ b/flowsint-web/src/components/investigations/case-selector.tsx @@ -1,3 +1,4 @@ +"use client" import { useInvestigations } from "@/lib/hooks/investigation/investigation"; import { useInvestigationStore } from '@/store/investigation-store'; import { useParams, useRouter } from "next/navigation"; diff --git a/flowsint-web/src/components/investigations/individual-modal.tsx b/flowsint-web/src/components/investigations/individual-modal.tsx index e63b154..4e6dee8 100644 --- a/flowsint-web/src/components/investigations/individual-modal.tsx +++ b/flowsint-web/src/components/investigations/individual-modal.tsx @@ -89,9 +89,9 @@ const IndividualModal = () => { return ( - +
-
+
{individual?.full_name || "User Profile"}
@@ -469,7 +469,7 @@ const IndividualModal = () => { className={ email.breaches.length > 0 ? "bg-red-950/50 border-red-900 text-red-200" - : "bg-zinc-800 border-zinc-700" + : "bg-zinc-800" } > @@ -496,7 +496,7 @@ const IndividualModal = () => { {phones.map((phone, index) => (
-
+
{editMode ? ( { @@ -546,7 +546,7 @@ const IndividualModal = () => { {ips.map((ip, index) => (
-
+
{ @@ -624,13 +624,13 @@ const IndividualModal = () => { {relations.map((relation) => ( setIndividualId(relation.id)} > - + - + {relation.full_name?.[0] || "?"} @@ -652,7 +652,7 @@ const IndividualModal = () => { diff --git a/flowsint-web/src/components/investigations/investigation-navigation.tsx b/flowsint-web/src/components/investigations/investigation-navigation.tsx new file mode 100644 index 0000000..49fa076 --- /dev/null +++ b/flowsint-web/src/components/investigations/investigation-navigation.tsx @@ -0,0 +1,62 @@ +"use client" + +import { cn } from "@/lib/utils" +import { Users, TimerIcon, MapIcon, WaypointsIcon } from "lucide-react" +import Link from "next/link" +import { usePathname } from "next/navigation" + + +export function InvestigationtNavigation({ project_id, investigation_id }: { project_id: string, investigation_id: string }) { + const pathname = usePathname() + const sections = [ + { + id: "sketch", + name: "Sketch", + href: `/dashboard/projects/${project_id}/investigations/${investigation_id}`, + icon: WaypointsIcon + }, + { + id: "individuals", + name: "Individuals", + href: `/dashboard/projects/${project_id}/investigations/${investigation_id}/individuals`, + icon: Users, + count: 24, + }, + { + id: "timeline", + name: "Timeline", + href: `/dashboard/projects/${project_id}/investigations/${investigation_id}/timeline`, + icon: TimerIcon, + }, + { + id: "map", + name: "Map", + href: `/dashboard/projects/${project_id}/investigations/${investigation_id}/map`, + icon: MapIcon, + }, + ] + + return ( +
+ {sections.map((section) => ( + + + {section.name} + {section.count && ( + {section.count} + )} + + ))} +
+ ) +} + diff --git a/flowsint-web/src/components/investigations/layout.tsx b/flowsint-web/src/components/investigations/layout.tsx index 42b027f..77dda94 100644 --- a/flowsint-web/src/components/investigations/layout.tsx +++ b/flowsint-web/src/components/investigations/layout.tsx @@ -1,75 +1,16 @@ "use client" -import React from 'react' -import MoreMenu from './more-menu'; -import CaseSelector from './case-selector'; -import NewCase from '@/components/dashboard/new-sketch'; -import SearchModal from '@/components/dashboard/search-palette'; -import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels'; -import { PanelRightIcon, PlusIcon, RotateCwIcon } from 'lucide-react'; -import Logo from '@/components/logo'; -import { useInvestigationStore } from '@/store/investigation-store'; -import { Button } from '../ui/button'; -import { ScrollArea } from '../ui/scroll-area'; -import Assistant from '../assistant'; -import { AppSidebar } from '../app-sidebar'; -import { SidebarProvider } from '../ui/sidebar'; import { ScanDrawer } from './scan-drawer'; -import { ScanButton } from './scans-drawer/scan-button'; -import ProjectSelector from './project-selector'; - const InvestigationLayout = ({ children, - left, - investigation_id, - user }: { children: React.ReactNode; left: React.ReactNode; investigation_id: string user: any }) => { - const { panelOpen, setPanelOpen } = useInvestigationStore() return ( <> - {/* */} - {/* {panelOpen && -
-
-
- - - - -
-
- -
- {left} -
-
-
-
} - */} - {/* */} -
-
-
-
- / -
- -
-
- -
-
- {children} -
- {/*
-
- */} + {children} ) diff --git a/flowsint-web/src/components/investigations/project-navigation.tsx b/flowsint-web/src/components/investigations/project-navigation.tsx new file mode 100644 index 0000000..5e01e8d --- /dev/null +++ b/flowsint-web/src/components/investigations/project-navigation.tsx @@ -0,0 +1,65 @@ +"use client" + +import { cn } from "@/lib/utils" +import { Eye, Users, Camera, Settings } from "lucide-react" +import Link from "next/link" +import { usePathname } from "next/navigation" + + +export function ProjectNavigation({ project_id }: { project_id: string }) { + const pathname = usePathname() + const sections = [ + { + id: "overview", + name: "Overview", + href: `/dashboard/projects/${project_id}`, + icon: Eye, + count: 18, + }, + { + id: "sketches", + name: "Sketches", + href: `/dashboard/projects/${project_id}?filter=sketch`, + icon: Users, + count: 24, + }, + { + id: "documents", + name: "Documents", + href: `/dashboard/projects/${project_id}?filter=document`, + icon: Camera, + count: 6, + }, + { + id: "configurations", + name: "Configurations", + href: `/dashboard/projects/${project_id}/settings`, + icon: Settings, + count: null, + }, + ] + + return ( +
+ {sections.map((section) => ( + + + {section.name} + {section.count !== null && ( + {section.count} + )} + + ))} +
+ ) +} + diff --git a/flowsint-web/src/components/investigations/sketch/graph.tsx b/flowsint-web/src/components/investigations/sketch/graph.tsx index 105482b..da120ab 100644 --- a/flowsint-web/src/components/investigations/sketch/graph.tsx +++ b/flowsint-web/src/components/investigations/sketch/graph.tsx @@ -170,19 +170,6 @@ const FlowControls = memo( Zoom out - - - - Sketch - Map - Timeline - - - - {/* {currentNode && ( - - - )} */} ) }, @@ -292,7 +279,7 @@ const LayoutFlow = ({ refetch, theme }: LayoutFlowProps) => { ) return ( -
+
@@ -379,7 +366,7 @@ function Graph({ graphQuery }: { graphQuery: any }) { if (!mounted || isLoading) { return ( -
+
Loading...
) diff --git a/flowsint-web/src/components/nav-user.tsx b/flowsint-web/src/components/nav-user.tsx index e539c95..5a1542d 100644 --- a/flowsint-web/src/components/nav-user.tsx +++ b/flowsint-web/src/components/nav-user.tsx @@ -47,17 +47,11 @@ export function NavUser({ {user.email[0]} -
- {user.name} - {user.email} -
-
- CN + {user.email[0]}
{user.name}