diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/embed/embed-setup.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/embed/embed-setup.tsx index d21b2d46eb9..8977053ce5d 100644 --- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/embed/embed-setup.tsx +++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/embed/embed-setup.tsx @@ -313,6 +313,7 @@ export const EmbedSetup: React.FC = ({ }); apiKeys.refetch(); }} + enableNebulaServiceByDefault={false} /> diff --git a/apps/dashboard/src/app/account/components/AccountHeader.tsx b/apps/dashboard/src/app/account/components/AccountHeader.tsx index b5bde823acc..ffd984832cf 100644 --- a/apps/dashboard/src/app/account/components/AccountHeader.tsx +++ b/apps/dashboard/src/app/account/components/AccountHeader.tsx @@ -21,8 +21,10 @@ export function AccountHeader(props: { }) { const myAccountQuery = useAccount(); const router = useDashboardRouter(); - const [isCreateProjectDialogOpen, setIsCreateProjectDialogOpen] = - useState(false); + const [createProjectDialogState, setCreateProjectDialogState] = useState< + { team: Team; isOpen: true } | { isOpen: false } + >({ isOpen: false }); + const client = useThirdwebClient(); const wallet = useActiveWallet(); const { disconnect } = useDisconnect(); @@ -43,7 +45,11 @@ export function AccountHeader(props: { teamsAndProjects: props.teamsAndProjects, logout: logout, connectButton: , - createProject: () => setIsCreateProjectDialogOpen(true), + createProject: (team: Team) => + setCreateProjectDialogState({ + team, + isOpen: true, + }), account: myAccountQuery.data, client, }; @@ -54,12 +60,20 @@ export function AccountHeader(props: { + setCreateProjectDialogState({ + isOpen: false, + }) + } onCreateAndComplete={() => { // refresh projects router.refresh(); }} + enableNebulaServiceByDefault={ + createProjectDialogState.isOpen && + createProjectDialogState.team.enabledScopes.includes("nebula") + } /> ); diff --git a/apps/dashboard/src/app/account/components/AccountHeaderUI.tsx b/apps/dashboard/src/app/account/components/AccountHeaderUI.tsx index efafb18793d..e193826c3de 100644 --- a/apps/dashboard/src/app/account/components/AccountHeaderUI.tsx +++ b/apps/dashboard/src/app/account/components/AccountHeaderUI.tsx @@ -16,7 +16,7 @@ export type AccountHeaderCompProps = { logout: () => void; connectButton: React.ReactNode; teamsAndProjects: Array<{ team: Team; projects: Project[] }>; - createProject: () => void; + createProject: (team: Team) => void; account: Pick | undefined; client: ThirdwebClient; }; diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/projects/TeamProjectsPage.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/projects/TeamProjectsPage.tsx index b6b2abc60cc..c5423ccd137 100644 --- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/projects/TeamProjectsPage.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/projects/TeamProjectsPage.tsx @@ -1,6 +1,9 @@ "use client"; import type { Project } from "@/api/projects"; +import type { Team } from "@/api/team"; +import { ProjectAvatar } from "@/components/blocks/Avatars/ProjectAvatar"; +import { CopyButton } from "@/components/ui/CopyButton"; import { Button } from "@/components/ui/button"; import { DropdownMenu, @@ -8,13 +11,6 @@ import { DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Input } from "@/components/ui/input"; -import { format } from "date-fns"; -import { ChevronDownIcon, SearchIcon } from "lucide-react"; -import Link from "next/link"; -import { useState } from "react"; - -import { ProjectAvatar } from "@/components/blocks/Avatars/ProjectAvatar"; -import { CopyButton } from "@/components/ui/CopyButton"; import { Select, SelectContent, @@ -23,12 +19,16 @@ import { } from "@/components/ui/select"; import { useDashboardRouter } from "@/lib/DashboardRouter"; import { LazyCreateAPIKeyDialog } from "components/settings/ApiKeys/Create/LazyCreateAPIKeyDialog"; +import { format } from "date-fns"; +import { ChevronDownIcon, SearchIcon } from "lucide-react"; +import Link from "next/link"; +import { useState } from "react"; type SortyById = "name" | "createdAt"; export function TeamProjectsPage(props: { projects: Project[]; - team_slug: string; + team: Team; }) { const { projects } = props; const [searchTerm, setSearchTerm] = useState(""); @@ -69,7 +69,7 @@ export function TeamProjectsPage(props: { setIsCreateProjectDialogOpen(true)} - teamMembersSettingsPath={`/team/${props.team_slug}/~/settings/members`} + teamMembersSettingsPath={`/team/${props.team.slug}/~/settings/members`} /> @@ -88,7 +88,7 @@ export function TeamProjectsPage(props: { ); })} @@ -104,6 +104,9 @@ export function TeamProjectsPage(props: { // refresh projects router.refresh(); }} + enableNebulaServiceByDefault={props.team.enabledScopes.includes( + "nebula", + )} /> ); diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/projects/page.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/projects/page.tsx index 27f7a75f4e1..d160e4cc8ca 100644 --- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/projects/page.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/projects/page.tsx @@ -1,15 +1,19 @@ import { getProjects } from "@/api/projects"; +import { getTeamBySlug } from "@/api/team"; +import { redirect } from "next/navigation"; import { TeamProjectsPage } from "./TeamProjectsPage"; export default async function Page(props: { params: Promise<{ team_slug: string }>; }) { - const projects = await getProjects((await props.params).team_slug); - - return ( - - ); + const params = await props.params; + const team = await getTeamBySlug(params.team_slug); + + if (!team) { + redirect("/team"); + } + + const projects = await getProjects(params.team_slug); + + return ; } diff --git a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/ProjectGeneralSettingsPage.stories.tsx b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/ProjectGeneralSettingsPage.stories.tsx index 316b7b3aae9..b75798bdd91 100644 --- a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/ProjectGeneralSettingsPage.stories.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/ProjectGeneralSettingsPage.stories.tsx @@ -60,6 +60,7 @@ function Story() { payConfig: "/payConfig", }} onKeyUpdated={undefined} + showNebulaSettings={false} /> diff --git a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/ProjectGeneralSettingsPage.tsx b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/ProjectGeneralSettingsPage.tsx index 34e8c48d343..55211eb2fb0 100644 --- a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/ProjectGeneralSettingsPage.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/ProjectGeneralSettingsPage.tsx @@ -51,6 +51,7 @@ export function ProjectGeneralSettingsPage(props: { apiKey: ApiKey; paths: EditProjectUIPaths; onKeyUpdated: (() => void) | undefined; + showNebulaSettings: boolean; }) { const updateMutation = useUpdateApiKey(); const deleteMutation = useRevokeApiKey(); @@ -62,6 +63,7 @@ export function ProjectGeneralSettingsPage(props: { deleteMutation={deleteMutation} paths={props.paths} onKeyUpdated={props.onKeyUpdated} + showNebulaSettings={props.showNebulaSettings} /> ); } @@ -81,6 +83,7 @@ interface EditApiKeyProps { deleteMutation: DeleteMutation; paths: EditProjectUIPaths; onKeyUpdated: (() => void) | undefined; + showNebulaSettings: boolean; } type UpdateAPIForm = UseFormReturn; @@ -233,6 +236,7 @@ export const ProjectGeneralSettingsPageUI: React.FC = ( updateMutation={updateMutation} handleSubmit={handleSubmit} paths={props.paths} + showNebulaSettings={props.showNebulaSettings} /> void; apiKey: ApiKey; paths: EditApiKeyProps["paths"]; + showNebulaSettings: boolean; }) { const { form, handleSubmit, updateMutation } = props; @@ -512,7 +517,10 @@ function EnabledServicesSetting(props: {
{fields.map((srv, idx) => { const service = getServiceByName(srv.name as ServiceName); - const hidden = HIDDEN_SERVICES.includes(service.name); + const hidden = + (service.name === "nebula" && !props.showNebulaSettings) || + HIDDEN_SERVICES.includes(service.name); + const serviceName = getServiceByName(service.name as ServiceName); const shouldShow = !hidden && serviceName; diff --git a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/ProjectGeneralSettingsPageForTeams.tsx b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/ProjectGeneralSettingsPageForTeams.tsx index 104005b5a9c..ea4636e8718 100644 --- a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/ProjectGeneralSettingsPageForTeams.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/ProjectGeneralSettingsPageForTeams.tsx @@ -1,17 +1,18 @@ "use client"; +import type { Team } from "@/api/team"; import { useDashboardRouter } from "@/lib/DashboardRouter"; import type { ApiKey } from "@3rdweb-sdk/react/hooks/useApi"; import { ProjectGeneralSettingsPage } from "./ProjectGeneralSettingsPage"; export function ProjectGeneralSettingsPageForTeams(props: { - team_slug: string; + team: Team; project_slug: string; apiKey: ApiKey; }) { const router = useDashboardRouter(); - const { team_slug, project_slug, apiKey } = props; - const projectSettingsLayout = `/team/${team_slug}/${project_slug}/settings`; + const { team, project_slug, apiKey } = props; + const projectSettingsLayout = `/team/${team.slug}/${project_slug}/settings`; // TODO - add a Project Image form field on this page @@ -22,11 +23,12 @@ export function ProjectGeneralSettingsPageForTeams(props: { aaConfig: `${projectSettingsLayout}/account-abstraction`, inAppConfig: `${projectSettingsLayout}/in-app-wallets`, payConfig: `${projectSettingsLayout}/pay`, - afterDeleteRedirectTo: `/team/${team_slug}`, + afterDeleteRedirectTo: `/team/${team.slug}`, }} onKeyUpdated={() => { router.refresh(); }} + showNebulaSettings={team.enabledScopes.includes("nebula")} /> ); } diff --git a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/page.tsx b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/page.tsx index 664617af1de..da57dfe8e6f 100644 --- a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/page.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/page.tsx @@ -1,5 +1,6 @@ import { getProject } from "@/api/projects"; -import { notFound } from "next/navigation"; +import { getTeamBySlug } from "@/api/team"; +import { notFound, redirect } from "next/navigation"; import { getAPIKeyForProjectId } from "../../../../api/lib/getAPIKeys"; import { ProjectGeneralSettingsPageForTeams } from "./ProjectGeneralSettingsPageForTeams"; @@ -7,6 +8,13 @@ export default async function Page(props: { params: Promise<{ team_slug: string; project_slug: string }>; }) { const { team_slug, project_slug } = await props.params; + + const team = await getTeamBySlug(team_slug); + + if (!team) { + redirect("/team"); + } + const project = await getProject(team_slug, project_slug); if (!project) { @@ -23,7 +31,7 @@ export default async function Page(props: { ); } diff --git a/apps/dashboard/src/app/team/components/TeamHeader/ProjectSelectorMobileMenuButton.tsx b/apps/dashboard/src/app/team/components/TeamHeader/ProjectSelectorMobileMenuButton.tsx index c382da42bde..bf130e3c10a 100644 --- a/apps/dashboard/src/app/team/components/TeamHeader/ProjectSelectorMobileMenuButton.tsx +++ b/apps/dashboard/src/app/team/components/TeamHeader/ProjectSelectorMobileMenuButton.tsx @@ -13,7 +13,7 @@ type ProjectSelectorMobileMenuButtonProps = { currentProject: Project; projects: Project[]; team: Team; - createProject: () => void; + createProject: (team: Team) => void; }; export function ProjectSelectorMobileMenuButton( @@ -49,7 +49,7 @@ export function ProjectSelectorMobileMenuButton( projects={props.projects} team={props.team} createProject={() => { - props.createProject(); + props.createProject(props.team); setOpen(false); }} /> diff --git a/apps/dashboard/src/app/team/components/TeamHeader/TeamAndProjectSelectorPopoverButton.tsx b/apps/dashboard/src/app/team/components/TeamHeader/TeamAndProjectSelectorPopoverButton.tsx index 45f2ed8a094..0916585dc12 100644 --- a/apps/dashboard/src/app/team/components/TeamHeader/TeamAndProjectSelectorPopoverButton.tsx +++ b/apps/dashboard/src/app/team/components/TeamHeader/TeamAndProjectSelectorPopoverButton.tsx @@ -21,7 +21,7 @@ type TeamSwitcherProps = { currentProject: Project | undefined; teamsAndProjects: Array<{ team: Team; projects: Project[] }>; focus: "project-selection" | "team-selection"; - createProject: () => void; + createProject: (team: Team) => void; account: Pick | undefined; }; @@ -104,7 +104,7 @@ export function TeamAndProjectSelectorPopoverButton(props: TeamSwitcherProps) { team={projectsToShowOfTeam} createProject={() => { setOpen(false); - props.createProject(); + props.createProject(projectsToShowOfTeam); }} /> )} diff --git a/apps/dashboard/src/app/team/components/TeamHeader/TeamHeaderUI.tsx b/apps/dashboard/src/app/team/components/TeamHeader/TeamHeaderUI.tsx index 77296d2cf2f..a39e592a53e 100644 --- a/apps/dashboard/src/app/team/components/TeamHeader/TeamHeaderUI.tsx +++ b/apps/dashboard/src/app/team/components/TeamHeader/TeamHeaderUI.tsx @@ -23,7 +23,7 @@ export type TeamHeaderCompProps = { account: Pick | undefined; logout: () => void; connectButton: React.ReactNode; - createProject: () => void; + createProject: (team: Team) => void; client: ThirdwebClient; }; diff --git a/apps/dashboard/src/app/team/components/TeamHeader/team-header-logged-in.client.tsx b/apps/dashboard/src/app/team/components/TeamHeader/team-header-logged-in.client.tsx index e2d06acfddf..b00167004df 100644 --- a/apps/dashboard/src/app/team/components/TeamHeader/team-header-logged-in.client.tsx +++ b/apps/dashboard/src/app/team/components/TeamHeader/team-header-logged-in.client.tsx @@ -22,8 +22,9 @@ export function TeamHeaderLoggedIn(props: { currentProject: Project | undefined; account: Pick; }) { - const [isCreateProjectDialogOpen, setIsCreateProjectDialogOpen] = - useState(false); + const [createProjectDialogState, setCreateProjectDialogState] = useState< + { team: Team; isOpen: true } | { isOpen: false } + >({ isOpen: false }); const activeWallet = useActiveWallet(); const { disconnect } = useDisconnect(); const router = useDashboardRouter(); @@ -48,7 +49,12 @@ export function TeamHeaderLoggedIn(props: { account: props.account, logout: logout, connectButton: , - createProject: () => setIsCreateProjectDialogOpen(true), + createProject: (team: Team) => { + setCreateProjectDialogState({ + isOpen: true, + team, + }); + }, client: getThirdwebClient(), }; @@ -58,12 +64,20 @@ export function TeamHeaderLoggedIn(props: { + setCreateProjectDialogState({ + isOpen: false, + }) + } onCreateAndComplete={() => { // refresh projects router.refresh(); }} + enableNebulaServiceByDefault={ + createProjectDialogState.isOpen && + createProjectDialogState.team.enabledScopes.includes("nebula") + } />
); diff --git a/apps/dashboard/src/components/settings/ApiKeys/Create/CreateApiKeyModal.stories.tsx b/apps/dashboard/src/components/settings/ApiKeys/Create/CreateApiKeyModal.stories.tsx index a28810c62e7..9fac70b8c3b 100644 --- a/apps/dashboard/src/components/settings/ApiKeys/Create/CreateApiKeyModal.stories.tsx +++ b/apps/dashboard/src/components/settings/ApiKeys/Create/CreateApiKeyModal.stories.tsx @@ -52,6 +52,7 @@ function Story(props: { onOpenChange={setIsOpen} createKeyMutation={mutation} prefill={props.prefill} + enableNebulaServiceByDefault={false} />