From 229f5560a67e1aa61585fac03b8d7c779930b394 Mon Sep 17 00:00:00 2001 From: Charis <26616127+charislam@users.noreply.github.com> Date: Fri, 12 Sep 2025 01:50:02 -0400 Subject: [PATCH] fix: prevent crash on _ page when user has no organizations (#38640) * fix: prevent crash on _ page when user has no organizations * Nit refactors to make wild card pages consistent + fix loading state of org wildcard route * Smol fix --------- Co-authored-by: Joshen Lim --- .../Home/ProjectList/EmptyStates.tsx | 36 +++++ apps/studio/next-env.d.ts | 1 - apps/studio/pages/org/_/[[...routeSlug]].tsx | 135 +++++++----------- .../pages/project/_/[[...routeSlug]].tsx | 99 +++++-------- 4 files changed, 123 insertions(+), 148 deletions(-) diff --git a/apps/studio/components/interfaces/Home/ProjectList/EmptyStates.tsx b/apps/studio/components/interfaces/Home/ProjectList/EmptyStates.tsx index d0957524562..f2dabecd8bb 100644 --- a/apps/studio/components/interfaces/Home/ProjectList/EmptyStates.tsx +++ b/apps/studio/components/interfaces/Home/ProjectList/EmptyStates.tsx @@ -2,6 +2,7 @@ import { Plus } from 'lucide-react' import Link from 'next/link' import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' +import { BASE_PATH } from 'lib/constants' import { Button, Card, @@ -16,6 +17,23 @@ import { } from 'ui' import { ShimmeringCard } from './ShimmeringCard' +export const Header = () => { + return ( +
+
+ + Supabase + +
+
+ ) +} + export const NoFilterResults = ({ filterStatus, resetFilterStatus, @@ -122,3 +140,21 @@ export const NoProjectsState = ({ slug }: { slug: string }) => { ) } + +export const NoOrganizationsState = () => { + return ( +
+
+

You are not part of any organizations yet

+

+ Create your first organization to get started with Supabase +

+
+
+ +
+
+ ) +} diff --git a/apps/studio/next-env.d.ts b/apps/studio/next-env.d.ts index 254b73c165d..52e831b4342 100644 --- a/apps/studio/next-env.d.ts +++ b/apps/studio/next-env.d.ts @@ -1,6 +1,5 @@ /// /// -/// // NOTE: This file should not be edited // see https://nextjs.org/docs/pages/api-reference/config/typescript for more information. diff --git a/apps/studio/pages/org/_/[[...routeSlug]].tsx b/apps/studio/pages/org/_/[[...routeSlug]].tsx index db3226c6804..c89df6107e7 100644 --- a/apps/studio/pages/org/_/[[...routeSlug]].tsx +++ b/apps/studio/pages/org/_/[[...routeSlug]].tsx @@ -1,31 +1,17 @@ -import { Plus } from 'lucide-react' import { NextPage } from 'next' -import Link from 'next/link' import { useRouter } from 'next/router' -import { ShimmeringCard } from 'components/interfaces/Home/ProjectList/ShimmeringCard' +import { + Header, + LoadingCardView, + NoOrganizationsState, +} from 'components/interfaces/Home/ProjectList/EmptyStates' +import { PageLayout } from 'components/layouts/PageLayout/PageLayout' +import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold' import CardButton from 'components/ui/CardButton' import { useOrganizationsQuery } from 'data/organizations/organizations-query' import { withAuth } from 'hooks/misc/withAuth' -import { BASE_PATH } from 'lib/constants' -import { Button, cn } from 'ui' - -const Header = () => { - return ( -
-
- - Supabase - -
-
- ) -} +import { cn } from 'ui' // [Joshen] Thinking we can deprecate this page in favor of /organizations const GenericOrganizationPage: NextPage = () => { @@ -52,70 +38,51 @@ const GenericOrganizationPage: NextPage = () => { return ( <>
-
-

- Select an organization to continue -

-
-
- {isLoading ? ( -
    + + +
    +
    + {isLoading ? ( + + ) : organizations?.length === 0 ? ( + + ) : ( +
      + {organizations?.map((organization) => ( +
    • + + {organization.name} +
    + } + footer={ +
    + + {organization.slug} + +
    + } + /> + + ))} +
)} - > - - - - ) : organizations?.length === 0 ? ( -
-
-

You are not part of any organizations yet

-

- Get started by creating a new organization. -

-
-
- -
- ) : ( -
    - {organizations?.map((organization) => ( -
  • - - {organization.name} -
- } - footer={ -
- - {organization.slug} - -
- } - /> - - ))} - - )} -
-
- + + + + ) } diff --git a/apps/studio/pages/project/_/[[...routeSlug]].tsx b/apps/studio/pages/project/_/[[...routeSlug]].tsx index b4c1e96940a..30bdfef0c6e 100644 --- a/apps/studio/pages/project/_/[[...routeSlug]].tsx +++ b/apps/studio/pages/project/_/[[...routeSlug]].tsx @@ -1,10 +1,14 @@ import { AlertTriangleIcon } from 'lucide-react' import { NextPage } from 'next' -import Link from 'next/link' import { useRouter } from 'next/router' import { useEffect, useState } from 'react' import { IS_PLATFORM, LOCAL_STORAGE_KEYS } from 'common' +import { + Header, + LoadingCardView, + NoOrganizationsState, +} from 'components/interfaces/Home/ProjectList/EmptyStates' import { ProjectList } from 'components/interfaces/Home/ProjectList/ProjectList' import { HomePageActions } from 'components/interfaces/HomePageActions' import { PageLayout } from 'components/layouts/PageLayout/PageLayout' @@ -12,7 +16,6 @@ import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold' import { useOrganizationsQuery } from 'data/organizations/organizations-query' import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage' import { withAuth } from 'hooks/misc/withAuth' -import { BASE_PATH } from 'lib/constants' import { Alert_Shadcn_, AlertDescription_Shadcn_, @@ -23,44 +26,6 @@ import { SelectTrigger_Shadcn_, SelectValue_Shadcn_, } from 'ui' -import ShimmeringLoader from 'ui-patterns/ShimmeringLoader' - -const Header = () => { - return ( -
-
- - Supabase - -
-
- ) -} - -const OrganizationLoadingState = () => { - return ( - <> - - - - - ) -} - -const OrganizationErrorState = () => { - return ( - - - Failed to load your Supabase organizations - Try refreshing the page - - ) -} // [Joshen] I'd say we don't do route validation here, this page will act more // like a proxy to the project specific pages, and we let those pages handle @@ -108,7 +73,7 @@ const GenericProjectPage: NextPage = () => { if (!!lastVisitedOrgSlug) { setSlug(lastVisitedOrgSlug) } else if (isSuccessOrganizations) { - setSlug(organizations[0].slug) + setSlug(organizations[0]?.slug) } // eslint-disable-next-line react-hooks/exhaustive-deps }, [lastVisitedOrgSlug, isSuccessOrganizations]) @@ -118,31 +83,39 @@ const GenericProjectPage: NextPage = () => {
- -
- - -
-

Organization:

- -
-
- - {organizations.map((org) => ( - - {org.name} - - ))} - -
- -
-
+ {organizations.length > 0 && ( + +
+ + +
+

Organization:

+ +
+
+ + {organizations.map((org) => ( + + {org.name} + + ))} + +
+ +
+
+ )} {isLoadingOrganizations ? ( - + ) : isErrorOrganizations ? ( - + + + Failed to load your Supabase organizations + Try refreshing the page + + ) : organizations.length === 0 ? ( + ) : !!selectedOrganization ? (