import Head from 'next/head' import { FC, ReactNode, PropsWithChildren } from 'react' import { observer } from 'mobx-react-lite' import { useRouter } from 'next/router' import { useStore, withAuth, useFlag } from 'hooks' import { PROJECT_STATUS } from 'lib/constants' import Connecting from 'components/ui/Loading' import NavigationBar from './NavigationBar/NavigationBar' import ProductMenuBar from './ProductMenuBar' import LayoutHeader from './LayoutHeader' import ConnectingState from './ConnectingState' import PausingState from './PausingState' import BuildingState from './BuildingState' interface Props { title?: string isLoading?: boolean product?: string productMenu?: ReactNode hideHeader?: boolean hideIconBar?: boolean } const ProjectLayout = ({ title, isLoading = false, product = '', productMenu, children, hideHeader = false, hideIconBar = false, }: PropsWithChildren) => { const ongoingIncident = useFlag('ongoingIncident') return ( <> {title ? `${title} | Supabase` : 'Supabase'}
{/* Left-most navigation side bar to access products */} {!hideIconBar && } {/* Product menu bar */} {productMenu}
{!hideHeader && } {children}
) } export const ProjectLayoutWithAuth = withAuth(ProjectLayout) export default ProjectLayout interface MenuBarWrapperProps { isLoading: boolean productMenu?: ReactNode } const MenuBarWrapper: FC = observer(({ isLoading, productMenu, children }) => { const { ui } = useStore() return <>{!isLoading && productMenu && ui.selectedProject !== undefined ? children : null} }) interface ContentWrapperProps { isLoading: boolean } /** * Check project.status to show building state or error state * * [Joshen] As of 210422: Current testing connection by pinging postgres * Ideally we'd have a more specific monitoring of the project such as during restarts * But that will come later: https://supabase.slack.com/archives/C01D6TWFFFW/p1650427619665549 * * Just note that this logic does not differentiate between a "restarting" state and * a "something is wrong and can't connect to project" state. * * [TODO] Next iteration should scrape long polling and just listen to the project's status */ const ContentWrapper: FC = observer(({ isLoading, children }) => { const { ui } = useStore() const router = useRouter() const routesToIgnorePostgrestConnection = [ '/project/[ref]/reports', '/project/[ref]/settings/general', '/project/[ref]/settings/database', '/project/[ref]/settings/billing', '/project/[ref]/settings/billing/update', '/project/[ref]/settings/billing/update/free', '/project/[ref]/settings/billing/update/pro', ] const requiresDbConnection: boolean = router.pathname !== '/project/[ref]/settings/general' const requiresPostgrestConnection = !routesToIgnorePostgrestConnection.includes(router.pathname) const isProjectBuilding = [PROJECT_STATUS.COMING_UP, PROJECT_STATUS.RESTORING].includes( ui.selectedProject?.status ?? '' ) const isProjectPausing = ui.selectedProject?.status === PROJECT_STATUS.GOING_DOWN const isProjectOffline = ui.selectedProject?.postgrestStatus === 'OFFLINE' return ( <> {isLoading || ui.selectedProject === undefined ? ( ) : isProjectPausing ? ( ) : requiresPostgrestConnection && isProjectOffline ? ( ) : requiresDbConnection && isProjectBuilding ? ( ) : ( <>{children} )} ) })