diff --git a/apps/studio/components/layouts/NavigationV2/AppSidebar.tsx b/apps/studio/components/layouts/NavigationV2/AppSidebar.tsx index c3a81b36145..7024d3418c9 100644 --- a/apps/studio/components/layouts/NavigationV2/AppSidebar.tsx +++ b/apps/studio/components/layouts/NavigationV2/AppSidebar.tsx @@ -1,15 +1,20 @@ import { useParams } from 'common' import { Plug } from 'lucide-react' +import { useRouter } from 'next/router' import { parseAsBoolean, useQueryState } from 'nuqs' import { Button, cn, Sidebar, SidebarContent, SidebarHeader } from 'ui' +import { ShimmeringLoader } from 'ui-patterns' import { NavGroup } from './NavGroup' import { useAppSidebarNavItems, type AppSidebarScope } from './useAppSidebarNavItems' import { ConnectSheet } from '@/components/interfaces/ConnectSheet/ConnectSheet' import { OrgSelector } from '@/components/layouts/Navigation/NavigationBar/OrgSelector' import { ProjectBranchSelector } from '@/components/layouts/Navigation/NavigationBar/ProjectBranchSelector' +import { useOrganizationsQuery } from '@/data/organizations/organizations-query' +import { useProjectDetailQuery } from '@/data/projects/project-detail-query' import { useHideSidebar } from '@/hooks/misc/useHideSidebar' import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject' import { IS_PLATFORM } from '@/lib/constants' export type { AppSidebarScope } @@ -28,6 +33,8 @@ function AppSidebarNavBody({ scope, variant = 'desktop' }: AppSidebarNavBodyProp const [, setShowConnect] = useQueryState('showConnect', parseAsBoolean.withDefault(false)) const { slug: orgRouteSlug } = useParams() const { data: selectedOrganization } = useSelectedOrganizationQuery() + const { isPending: isLoadingOrganizations } = useOrganizationsQuery() + const { data: project, isPending: isLoadingProject } = useSelectedProjectQuery() const { isProjectScope, @@ -40,31 +47,57 @@ function AppSidebarNavBody({ scope, variant = 'desktop' }: AppSidebarNavBodyProp organizationItems, } = useAppSidebarNavItems({ scope }) - const isMobileSheet = variant === 'mobile-sheet' - const selectorHeaderClass = cn('flex-col gap-2', isMobileSheet ? 'flex' : 'hidden md:flex') + const isBranch = project != null && project.parentRef !== project.ref + const { data: parentProject, isPending: isLoadingParentProject } = useProjectDetailQuery( + { ref: project?.parent_project_ref }, + { enabled: Boolean(isProjectScope && isBranch && project?.parent_project_ref) } + ) + const selectedProject = parentProject ?? project + + const isOrgSelectorLoading = isLoadingOrganizations + const isProjectSelectorLoading = + isLoadingProject || (isBranch && isLoadingParentProject) || !selectedProject const shouldShowOrgSelector = !isProjectScope && IS_PLATFORM && (Boolean(orgRouteSlug) || Boolean(selectedOrganization)) + const isHeaderLoading = + (shouldShowOrgSelector && isOrgSelectorLoading) || (isProjectScope && isProjectSelectorLoading) + + const isMobileSheet = variant === 'mobile-sheet' + const selectorHeaderClass = cn('flex-col gap-2', isMobileSheet ? 'flex' : 'hidden md:flex') + return ( <> - {shouldShowOrgSelector && } - {isProjectScope && ( + {isHeaderLoading ? ( + + ) : ( <> - -
- -
+ {shouldShowOrgSelector && } + {isProjectScope && ( + <> + +
+ +
+ + )} )}
@@ -125,12 +158,17 @@ export function AppSidebarV2({ scope }: AppSidebarV2Props = {}) { /** * Full-height V2 navigation for `StudioMobileSheetNav`, opened via `registerOpenMenu` from - * {@link ProjectLayoutV2}. Mirrors desktop {@link AppSidebarV2} structure. + * {@link ProjectLayoutV2}. Scope follows the current route like {@link DefaultLayoutV2}. */ export function AppSidebarMobileSheetMenu() { + const router = useRouter() + const sheetScope: AppSidebarScope = router.pathname.startsWith('/project') + ? 'project' + : 'organization' + return (
- +
) diff --git a/apps/studio/components/layouts/ProjectLayout/index.tsx b/apps/studio/components/layouts/ProjectLayout/index.tsx index 39cbcc52ad1..b3632e71cbd 100644 --- a/apps/studio/components/layouts/ProjectLayout/index.tsx +++ b/apps/studio/components/layouts/ProjectLayout/index.tsx @@ -25,6 +25,7 @@ import { useEditorType } from '../editors/EditorsLayout.hooks' import { useSetMainScrollContainer } from '../MainScrollContainerContext' import { useMobileSheet } from '../Navigation/NavigationBar/MobileSheetContext' import ProductMenuBar from '../Navigation/ProductMenuBar' +import { AppSidebarMobileSheetMenu } from '../NavigationV2/AppSidebar' import BuildingState from './BuildingState' import ConnectingState from './ConnectingState' import { getSectionKeyFromPathname, MobileMenuContent } from './LayoutHeader/MobileMenuContent' @@ -37,6 +38,7 @@ import RestartingState from './RestartingState' import { RestoreFailedState } from './RestoreFailedState' import { RestoringState } from './RestoringState' import { UpgradingState } from './UpgradingState' +import { useIsNavigationV2Enabled } from '@/components/interfaces/App/FeaturePreview/FeaturePreviewContext' import { CreateBranchModal } from '@/components/interfaces/BranchManagement/CreateBranchModal' import { ProjectAPIDocs } from '@/components/interfaces/ProjectAPIDocs/ProjectAPIDocs' import { BannerFreeMicroUpgrade } from '@/components/ui/BannerStack/Banners/BannerFreeMicroUpgrade' @@ -134,6 +136,7 @@ export const ProjectLayout = forwardRef { const unregister = registerOpenMenu(() => { - setMobileSheetContent( - setMobileSheetContent(null)} - /> - ) + if (isNavigationV2) { + setMobileSheetContent() + } else { + setMobileSheetContent( + setMobileSheetContent(null)} + /> + ) + } }) return unregister - }, [registerOpenMenu, productMenu, product, currentSectionKey, setMobileSheetContent]) + }, [ + registerOpenMenu, + productMenu, + product, + currentSectionKey, + setMobileSheetContent, + isNavigationV2, + ]) return ( <>