diff --git a/src/app/(authenticated)/layout.tsx b/src/app/(authenticated)/layout.tsx index 85d4baa062..7cec7963c2 100644 --- a/src/app/(authenticated)/layout.tsx +++ b/src/app/(authenticated)/layout.tsx @@ -11,7 +11,7 @@ export default async function AuthenticatedLayout({ const { orgId } = await auth(); if (!orgId) { - redirect('/onboarding/select-org'); + redirect('/select-org'); } return ( diff --git a/src/app/(authenticated)/org/[[...organization-profile]]/Org.tsx b/src/app/(authenticated)/org/[[...organization-profile]]/Org.tsx index 5490d1b0f7..a1d93e38dd 100644 --- a/src/app/(authenticated)/org/[[...organization-profile]]/Org.tsx +++ b/src/app/(authenticated)/org/[[...organization-profile]]/Org.tsx @@ -15,7 +15,7 @@ export const Org = () => { ; + +export const CursorLogo = ({ + width = '36', + height = '36', + ...props +}: CursorLogoProps) => ( + + + + + + + + + +); diff --git a/src/app/(centered)/extension/sign-in/DeepLink.tsx b/src/app/(centered)/extension/sign-in/DeepLink.tsx new file mode 100644 index 0000000000..a4ea28d998 --- /dev/null +++ b/src/app/(centered)/extension/sign-in/DeepLink.tsx @@ -0,0 +1,45 @@ +'use client'; + +import { useEffect, useState } from 'react'; +import Link from 'next/link'; + +import { Card, CardContent, CardFooter } from '@/components/ui'; +import { VSCodeLogo } from './VSCodeLogo'; +import { CursorLogo } from './CursorLogo'; + +interface DeepLinkProps { + vsCodeUrl: string; + cursorUrl: string; +} + +export const DeepLink = ({ vsCodeUrl, cursorUrl }: DeepLinkProps) => { + const [redirectAttempted, setRedirectAttempted] = useState(false); + + useEffect(() => { + window.location.href = vsCodeUrl; + const timer = setTimeout(() => setRedirectAttempted(true), 2000); + return () => clearTimeout(timer); + }, [vsCodeUrl]); + + return ( + + +
You've successfully authenticated.
+
+
Open in your IDE:
+ + + + + + +
+
+ + {redirectAttempted + ? 'You can close this window after your IDE opens.' + : 'Redirecting automatically...'} + +
+ ); +}; diff --git a/src/app/(centered)/extension/sign-in/VSCodeLogo.tsx b/src/app/(centered)/extension/sign-in/VSCodeLogo.tsx new file mode 100644 index 0000000000..eef1117a01 --- /dev/null +++ b/src/app/(centered)/extension/sign-in/VSCodeLogo.tsx @@ -0,0 +1,140 @@ +import type { SVGProps } from 'react'; + +type VSCodeLogoProps = SVGProps; + +export const VSCodeLogo = ({ + width = '36', + height = '36', + ...props +}: VSCodeLogoProps) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +); diff --git a/src/app/extension/sign-in/page.tsx b/src/app/(centered)/extension/sign-in/page.tsx similarity index 89% rename from src/app/extension/sign-in/page.tsx rename to src/app/(centered)/extension/sign-in/page.tsx index efb00dd705..11008d8f88 100644 --- a/src/app/extension/sign-in/page.tsx +++ b/src/app/(centered)/extension/sign-in/page.tsx @@ -17,13 +17,17 @@ export default async function Page(props: Props) { redirect(`/sign-in`); } - const { userId } = await auth(); + const { userId, orgId } = await auth(); const code = userId ? await getSignInToken(userId) : undefined; if (!code) { redirect(`/sign-in?state=${state}`); } + if (!orgId) { + redirect(`/select-org?state=${state}`); + } + const searchParams = new URLSearchParams({ state, code }); const path = `/auth/clerk/callback?${searchParams.toString()}`; const vsCodeUrl = new URL(path, Env.VSCODE_EXTENSION_BASE_URL); diff --git a/src/app/(profile)/layout.tsx b/src/app/(centered)/layout.tsx similarity index 100% rename from src/app/(profile)/layout.tsx rename to src/app/(centered)/layout.tsx diff --git a/src/app/(centered)/select-org/SelectOrg.tsx b/src/app/(centered)/select-org/SelectOrg.tsx new file mode 100644 index 0000000000..150f155adf --- /dev/null +++ b/src/app/(centered)/select-org/SelectOrg.tsx @@ -0,0 +1,22 @@ +'use client'; + +import { useMemo } from 'react'; +import { useSearchParams } from 'next/navigation'; +import { OrganizationList } from '@clerk/nextjs'; + +export const SelectOrg = () => { + const searchParams = useSearchParams(); + + const afterSelectOrganizationUrl = useMemo(() => { + const state = searchParams.get('state'); + return state ? `/extension/sign-in?state=${state}` : '/dashboard'; + }, [searchParams]); + + return ( + + ); +}; diff --git a/src/app/(centered)/select-org/page.tsx b/src/app/(centered)/select-org/page.tsx new file mode 100644 index 0000000000..99a5c1bf89 --- /dev/null +++ b/src/app/(centered)/select-org/page.tsx @@ -0,0 +1,5 @@ +import { SelectOrg } from './SelectOrg'; + +export default async function Page() { + return ; +} diff --git a/src/app/sign-in/[[...sign-in]]/SignIn.tsx b/src/app/(centered)/sign-in/[[...sign-in]]/SignIn.tsx similarity index 57% rename from src/app/sign-in/[[...sign-in]]/SignIn.tsx rename to src/app/(centered)/sign-in/[[...sign-in]]/SignIn.tsx index 38eb63904f..a68805e3a3 100644 --- a/src/app/sign-in/[[...sign-in]]/SignIn.tsx +++ b/src/app/(centered)/sign-in/[[...sign-in]]/SignIn.tsx @@ -2,11 +2,8 @@ import { useMemo } from 'react'; import { useSearchParams } from 'next/navigation'; -import Link from 'next/link'; import { SignIn as ClerkSignIn } from '@clerk/nextjs'; -import { Logo } from '@/components/layout'; - export const SignIn = () => { const searchParams = useSearchParams(); @@ -15,12 +12,5 @@ export const SignIn = () => { return state ? `/extension/sign-in?state=${state}` : undefined; }, [searchParams]); - return ( -
- - - - -
- ); + return ; }; diff --git a/src/app/sign-in/[[...sign-in]]/page.tsx b/src/app/(centered)/sign-in/[[...sign-in]]/page.tsx similarity index 100% rename from src/app/sign-in/[[...sign-in]]/page.tsx rename to src/app/(centered)/sign-in/[[...sign-in]]/page.tsx diff --git a/src/app/sign-up/[[...sign-up]]/SignUp.tsx b/src/app/(centered)/sign-up/[[...sign-up]]/SignUp.tsx similarity index 57% rename from src/app/sign-up/[[...sign-up]]/SignUp.tsx rename to src/app/(centered)/sign-up/[[...sign-up]]/SignUp.tsx index a62539fc9b..472baee990 100644 --- a/src/app/sign-up/[[...sign-up]]/SignUp.tsx +++ b/src/app/(centered)/sign-up/[[...sign-up]]/SignUp.tsx @@ -2,11 +2,8 @@ import { useMemo } from 'react'; import { useSearchParams } from 'next/navigation'; -import Link from 'next/link'; import { SignUp as ClerkSignUp } from '@clerk/nextjs'; -import { Logo } from '@/components/layout'; - export const SignUp = () => { const searchParams = useSearchParams(); @@ -15,12 +12,5 @@ export const SignUp = () => { return state ? `/extension/sign-in?state=${state}` : undefined; }, [searchParams]); - return ( -
- - - - -
- ); + return ; }; diff --git a/src/app/sign-up/[[...sign-up]]/page.tsx b/src/app/(centered)/sign-up/[[...sign-up]]/page.tsx similarity index 100% rename from src/app/sign-up/[[...sign-up]]/page.tsx rename to src/app/(centered)/sign-up/[[...sign-up]]/page.tsx diff --git a/src/app/(profile)/onboarding/create-org/page.tsx b/src/app/(profile)/onboarding/create-org/page.tsx deleted file mode 100644 index 8dcba18d26..0000000000 --- a/src/app/(profile)/onboarding/create-org/page.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { CreateOrganization } from '@clerk/nextjs'; - -export default async function Page() { - return ; -} diff --git a/src/app/(profile)/onboarding/select-org/page.tsx b/src/app/(profile)/onboarding/select-org/page.tsx deleted file mode 100644 index cc56f83a41..0000000000 --- a/src/app/(profile)/onboarding/select-org/page.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { OrganizationList } from '@clerk/nextjs'; - -export default async function Page() { - return ( - - ); -} diff --git a/src/app/(profile)/user/[[...user-profile]]/page.tsx b/src/app/(profile)/user/[[...user-profile]]/page.tsx deleted file mode 100644 index a374ef585c..0000000000 --- a/src/app/(profile)/user/[[...user-profile]]/page.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { UserProfile } from '@clerk/nextjs'; - -export default function Page() { - return ; -} diff --git a/src/app/extension/sign-in/DeepLink.tsx b/src/app/extension/sign-in/DeepLink.tsx deleted file mode 100644 index 998b5b8804..0000000000 --- a/src/app/extension/sign-in/DeepLink.tsx +++ /dev/null @@ -1,51 +0,0 @@ -'use client'; - -import { useEffect, useState } from 'react'; -import Link from 'next/link'; - -import { Button, Card, CardContent, CardFooter } from '@/components/ui'; -import { Logo } from '@/components/layout'; - -interface DeepLinkProps { - vsCodeUrl: string; - cursorUrl: string; -} - -export const DeepLink = ({ vsCodeUrl, cursorUrl }: DeepLinkProps) => { - const [redirectAttempted, setRedirectAttempted] = useState(false); - - useEffect(() => { - window.location.href = vsCodeUrl; - const timer = setTimeout(() => setRedirectAttempted(true), 2000); - return () => clearTimeout(timer); - }, [vsCodeUrl]); - - return ( -
- - - - - -
- You've successfully authenticated. We're attempting to - open VSCode with your credentials. -
-
- - -
-
- - {redirectAttempted - ? 'You can close this window after VSCode opens.' - : 'Redirecting automatically...'} - -
-
- ); -}; diff --git a/src/middleware.ts b/src/middleware.ts index 3e2eeea616..8f2316f7d3 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -3,6 +3,7 @@ import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'; const isUnprotectedRoute = createRouteMatcher([ '/sign-in(.*)', '/sign-up(.*)', + '/extension/sign-in(.*)', '/', ]);