Skip to content

Commit 447a519

Browse files
committed
[TOOL-3768] Dashboard: Move Nebula from team to project layout (#6608)
<!-- start pr-codex --> ## PR-Codex overview This PR focuses on enhancing the `Nebula` components in the dashboard application by improving layout styles, adding project ID handling in analytics, and adjusting waitlist checks. ### Detailed summary - Updated class names for better styling in `nebula-analytics-filter.tsx` and `nebula-waitlist-page.tsx`. - Added `projectId` parameter to `fetchNebulaAnalytics`. - Modified `NebulaWaitListPageUI` layout. - Integrated `showNebula` prop in `ProjectSidebarLayout`. - Adjusted project layout and waitlist checks in `layout.tsx`. - Enhanced `NebulaAnalyticsPage` to pass `projectId`. - Updated page handling in `page.tsx` to include project fetching and redirects. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex -->
1 parent a9b7633 commit 447a519

File tree

9 files changed

+56
-30
lines changed

9 files changed

+56
-30
lines changed

apps/dashboard/src/app/team/[team_slug]/(team)/layout.tsx

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { getProjects } from "@/api/projects";
2-
import { getTeamNebulaWaitList, getTeams } from "@/api/team";
2+
import { getTeams } from "@/api/team";
33
import { AppFooter } from "@/components/blocks/app-footer";
44
import { TabPathLinks } from "@/components/ui/tabs";
55
import { redirect } from "next/navigation";
@@ -39,9 +39,6 @@ export default async function TeamLayout(props: {
3939
})),
4040
);
4141

42-
const isOnNebulaWaitList = (await getTeamNebulaWaitList(team.slug))
43-
?.onWaitlist;
44-
4542
return (
4643
<div className="flex h-full grow flex-col">
4744
<AnnouncementBanner />
@@ -74,14 +71,6 @@ export default async function TeamLayout(props: {
7471
path: `/team/${params.team_slug}/~/ecosystem`,
7572
name: "Ecosystems",
7673
},
77-
...(isOnNebulaWaitList
78-
? [
79-
{
80-
path: `/team/${params.team_slug}/~/nebula`,
81-
name: "Nebula",
82-
},
83-
]
84-
: []),
8574
{
8675
path: `/team/${params.team_slug}/~/usage`,
8776
name: "Usage",

apps/dashboard/src/app/team/[team_slug]/[project_slug]/components/ProjectSidebarLayout.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ import { ContractIcon } from "../../../../(dashboard)/(chain)/components/server/
1212
import { InsightIcon } from "../../../../(dashboard)/(chain)/components/server/icons/InsightIcon";
1313
import { PayIcon } from "../../../../(dashboard)/(chain)/components/server/icons/PayIcon";
1414
import { SmartAccountIcon } from "../../../../(dashboard)/(chain)/components/server/icons/SmartAccountIcon";
15+
import { NebulaIcon } from "../../../../nebula-app/(app)/icons/NebulaIcon";
1516

1617
export function ProjectSidebarLayout(props: {
1718
layoutPath: string;
1819
children: React.ReactNode;
20+
showNebula: boolean;
1921
}) {
20-
const { layoutPath, children } = props;
22+
const { layoutPath, children, showNebula } = props;
2123

2224
const tracking = (label: string) => ({
2325
category: "project-sidebar",
@@ -60,6 +62,16 @@ export function ProjectSidebarLayout(props: {
6062
icon: ContractIcon,
6163
tracking: tracking("contracts"),
6264
},
65+
...(showNebula
66+
? [
67+
{
68+
href: `${layoutPath}/nebula`,
69+
label: "Nebula",
70+
icon: NebulaIcon,
71+
tracking: tracking("nebula"),
72+
},
73+
]
74+
: []),
6375
{
6476
href: `${layoutPath}/insight`,
6577
label: "Insight",

apps/dashboard/src/app/team/[team_slug]/[project_slug]/layout.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { getProjects } from "@/api/projects";
2-
import { getTeams } from "@/api/team";
2+
import { getTeamNebulaWaitList, getTeams } from "@/api/team";
33
import { SidebarProvider } from "@/components/ui/sidebar";
44
import { redirect } from "next/navigation";
55
import { AnnouncementBanner } from "../../../../components/notices/AnnouncementBanner";
@@ -9,7 +9,7 @@ import { TeamHeaderLoggedIn } from "../../components/TeamHeader/team-header-logg
99
import { ProjectSidebarLayout } from "./components/ProjectSidebarLayout";
1010
import { SaveLastUsedProject } from "./components/SaveLastUsedProject";
1111

12-
export default async function TeamLayout(props: {
12+
export default async function ProjectLayout(props: {
1313
children: React.ReactNode;
1414
breadcrumbNav: React.ReactNode;
1515
params: Promise<{ team_slug: string; project_slug: string }>;
@@ -49,6 +49,9 @@ export default async function TeamLayout(props: {
4949
redirect(`/team/${params.team_slug}`);
5050
}
5151

52+
const isOnNebulaWaitList = (await getTeamNebulaWaitList(team.slug))
53+
?.onWaitlist;
54+
5255
const layoutPath = `/team/${params.team_slug}/${params.project_slug}`;
5356

5457
return (
@@ -64,7 +67,10 @@ export default async function TeamLayout(props: {
6467
accountAddress={accountAddress}
6568
/>
6669
</div>
67-
<ProjectSidebarLayout layoutPath={layoutPath}>
70+
<ProjectSidebarLayout
71+
layoutPath={layoutPath}
72+
showNebula={!!isOnNebulaWaitList}
73+
>
6874
{props.children}
6975
</ProjectSidebarLayout>
7076
</div>

apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/components/analytics/fetch-nebula-analytics.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export type NebulaAnalyticsDataItem = {
1212
export const fetchNebulaAnalytics = unstable_cache(
1313
async (params: {
1414
teamId: string;
15+
projectId: string;
1516
authToken: string;
1617
from: string;
1718
to: string;
@@ -20,6 +21,7 @@ export const fetchNebulaAnalytics = unstable_cache(
2021
const analyticsEndpoint = process.env.ANALYTICS_SERVICE_URL as string;
2122
const url = new URL(`${analyticsEndpoint}/v2/nebula/usage`);
2223
url.searchParams.set("teamId", params.teamId);
24+
url.searchParams.set("projectId", params.projectId);
2325
url.searchParams.set("from", params.from);
2426
url.searchParams.set("to", params.to);
2527
url.searchParams.set("period", params.period);

apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/components/analytics/nebula-analytics-filter.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export function NebulaAnalyticsFilter() {
2222
});
2323

2424
return (
25-
<div className="flex items-center gap-3">
25+
<div className="no-scrollbar flex items-center gap-3 overflow-auto">
2626
<DateRangeSelector
2727
range={range}
2828
popoverAlign="end"

apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/components/analytics/nebula-analytics-page.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@ export function NebulaAnalyticsPage(props: {
1919
};
2020
teamId: string;
2121
authToken: string;
22+
projectId: string;
2223
}) {
2324
return (
2425
<ResponsiveSearchParamsProvider value={props.searchParams}>
2526
<header className="border-b">
26-
<div className="container flex flex-col items-start gap-4 py-10 md:flex-row md:items-center md:justify-between">
27+
<div className="flex flex-col items-start gap-4 pt-2 pb-6 md:flex-row md:items-center md:justify-between lg:pt-4 lg:pb-10">
2728
<h1 className="font-semibold text-3xl tracking-tight">Nebula</h1>
2829

2930
<div className="flex gap-3">
@@ -44,7 +45,7 @@ export function NebulaAnalyticsPage(props: {
4445
</div>
4546
</header>
4647

47-
<div className="container pt-8 pb-20">
48+
<div className="pt-8">
4849
<div className="mb-4 flex flex-col justify-between gap-3 md:flex-row md:items-end">
4950
<h2 className="font-semibold text-2xl tracking-tight">Analytics</h2>
5051
<NebulaAnalyticsFilter />
@@ -56,6 +57,7 @@ export function NebulaAnalyticsPage(props: {
5657
<NebulaAnalyticDashboard
5758
searchParams={props.searchParams}
5859
teamId={props.teamId}
60+
projectId={props.projectId}
5961
authToken={props.authToken}
6062
/>
6163
</ResponsiveSuspense>
@@ -67,6 +69,7 @@ export function NebulaAnalyticsPage(props: {
6769
async function NebulaAnalyticDashboard(props: {
6870
teamId: string;
6971
authToken: string;
72+
projectId: string;
7073
searchParams: {
7174
from: string | undefined | string[];
7275
to: string | undefined | string[];
@@ -80,6 +83,7 @@ async function NebulaAnalyticDashboard(props: {
8083
const res = await fetchNebulaAnalytics({
8184
teamId: props.teamId,
8285
authToken: props.authToken,
86+
projectId: props.projectId,
8387
from: normalizeTimeISOString(range.from),
8488
to: normalizeTimeISOString(range.to),
8589
// internally renamed

apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/components/nebula-waitlist-page-ui.client.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ export function NebulaWaitListPageUI(props: {
1313
<div className={cn("flex grow flex-col", props.className)}>
1414
{/* Header */}
1515
{!props.hideHeader && (
16-
<div className="border-b py-10">
17-
<div className="container flex items-center justify-between">
16+
<div className="border-b pt-4 pb-10">
17+
<div className="flex items-center justify-between">
1818
<h1 className="font-semibold text-3xl tracking-tight"> Nebula </h1>
1919
<Button asChild variant="outline">
2020
<Link href="/contact-us" target="_blank">
@@ -25,7 +25,7 @@ export function NebulaWaitListPageUI(props: {
2525
</div>
2626
)}
2727

28-
<div className="container flex grow flex-col overflow-hidden py-32">
28+
<div className="flex grow flex-col overflow-hidden py-32">
2929
<CenteredCard
3030
title="You're on the waitlist"
3131
description="You should receive access to Nebula soon!"

apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/components/nebula-waitlist-page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ function UnexpectedErrorPage(props: {
4646
message: string;
4747
}) {
4848
return (
49-
<div className="container flex grow flex-col py-10">
49+
<div className="flex grow flex-col py-10">
5050
<div className="flex min-h-[300px] grow flex-col items-center justify-center rounded-lg border">
5151
<div className="flex flex-col items-center gap-4">
5252
<span className="text-destructive-text">{props.message}</span>

apps/dashboard/src/app/team/[team_slug]/(team)/~/nebula/page.tsx renamed to apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/page.tsx

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
1+
import { getProject } from "@/api/projects";
12
import { getTeamBySlug } from "@/api/team";
2-
import { getAuthToken } from "../../../../../api/lib/getAuthToken";
3-
import { loginRedirect } from "../../../../../login/loginRedirect";
4-
import { NebulaAnalyticsPage } from "../../../[project_slug]/nebula/components/analytics/nebula-analytics-page";
5-
import { NebulaWaitListPage } from "../../../[project_slug]/nebula/components/nebula-waitlist-page";
3+
import { redirect } from "next/navigation";
4+
import { getAuthToken } from "../../../../api/lib/getAuthToken";
5+
import { loginRedirect } from "../../../../login/loginRedirect";
6+
import { NebulaAnalyticsPage } from "./components/analytics/nebula-analytics-page";
7+
import { NebulaWaitListPage } from "./components/nebula-waitlist-page";
68

79
export default async function Page(props: {
810
params: Promise<{
911
team_slug: string;
12+
project_slug: string;
1013
}>;
1114
searchParams: Promise<{
1215
from: string | undefined | string[];
@@ -19,13 +22,22 @@ export default async function Page(props: {
1922
props.searchParams,
2023
]);
2124

22-
const [authToken, team] = await Promise.all([
25+
const [authToken, team, project] = await Promise.all([
2326
getAuthToken(),
2427
getTeamBySlug(params.team_slug),
28+
getProject(params.team_slug, params.project_slug),
2529
]);
2630

27-
if (!team || !authToken) {
28-
loginRedirect(`/team/${params.team_slug}/~/nebula`);
31+
if (!team) {
32+
redirect("/team");
33+
}
34+
35+
if (!project) {
36+
redirect(`/team/${params.team_slug}`);
37+
}
38+
39+
if (!authToken) {
40+
loginRedirect(`/team/${params.team_slug}/${params.project_slug}/nebula`);
2941
}
3042

3143
const hasNebulaAccess = team.enabledScopes.includes("nebula");
@@ -36,6 +48,7 @@ export default async function Page(props: {
3648
teamId={team.id}
3749
authToken={authToken}
3850
searchParams={searchParams}
51+
projectId={project.id}
3952
/>
4053
);
4154
}

0 commit comments

Comments
 (0)