0
- ? 'bg-destructive-600'
- : warningArray.length > 0
- ? 'bg-warning-600'
- : 'bg-transparent'
+ hasErrors ? 'bg-destructive-600' : hasWarnings ? 'bg-warning-600' : 'bg-transparent'
)}
/>
)
@@ -230,8 +223,6 @@ const ProjectLinks = () => {
const showReports = useIsFeatureEnabled('reports:all')
const { mutate: sendEvent } = useSendEventMutation()
- const isProjectActive = project?.status === PROJECT_STATUS.ACTIVE_HEALTHY
-
const isNewAPIDocsEnabled = useIsAPIDocsSidePanelEnabled()
const { isEnabled: isUnifiedLogsEnabled } = useUnifiedLogsPreview()
@@ -283,7 +274,6 @@ const ProjectLinks = () => {
{toolRoutes.map((route, i) => (
@@ -294,7 +284,6 @@ const ProjectLinks = () => {
{productRoutes.map((route, i) => (
@@ -322,41 +311,36 @@ const ProjectLinks = () => {
return (
)
} else if (route.key === 'advisors') {
return (
- {isProjectActive && ActiveDot(errorLints, securityLints)}
-
+ {!route.disabled && (
+
0}
+ hasWarnings={securityLints.length > 0}
+ />
+ )}
+
)
} else {
return (
-
+
)
}
})}
@@ -440,7 +424,6 @@ const OrganizationLinks = () => {
{navMenuItems.map((item, i) => (
{
link: item.href,
key: item.label,
icon: item.icon,
+ disabled: disableAccessMfa,
}}
/>
))}
diff --git a/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.utils.tsx b/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.utils.tsx
index 4a06b218dfe43..995e6915d8730 100644
--- a/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.utils.tsx
+++ b/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.utils.tsx
@@ -10,6 +10,7 @@ import { IS_PLATFORM, PROJECT_STATUS } from 'lib/constants'
import { Blocks, FileText, Lightbulb, List, Settings, Telescope } from 'lucide-react'
export const generateToolRoutes = (ref?: string, project?: Project, features?: {}): Route[] => {
+ const isProjectActive = project?.status === PROJECT_STATUS.ACTIVE_HEALTHY
const isProjectBuilding = project?.status === PROJECT_STATUS.COMING_UP
const buildingUrl = `/project/${ref}`
@@ -17,6 +18,7 @@ export const generateToolRoutes = (ref?: string, project?: Project, features?: {
{
key: 'editor',
label: 'Table Editor',
+ disabled: !isProjectActive,
icon: ,
link: ref && (isProjectBuilding ? buildingUrl : `/project/${ref}/editor`),
linkElement: ,
@@ -24,6 +26,7 @@ export const generateToolRoutes = (ref?: string, project?: Project, features?: {
{
key: 'sql',
label: 'SQL Editor',
+ disabled: !isProjectActive,
icon: ,
link: ref && (isProjectBuilding ? buildingUrl : `/project/${ref}/sql`),
},
@@ -58,6 +61,7 @@ export const generateProductRoutes = (
{
key: 'database',
label: 'Database',
+ disabled: !isProjectActive,
icon: ,
link:
ref &&
@@ -73,6 +77,7 @@ export const generateProductRoutes = (
{
key: 'auth',
label: 'Authentication',
+ disabled: !isProjectActive,
icon: ,
link:
ref &&
@@ -90,6 +95,7 @@ export const generateProductRoutes = (
{
key: 'storage',
label: 'Storage',
+ disabled: !isProjectActive,
icon: ,
link: ref && (isProjectBuilding ? buildingUrl : `/project/${ref}/storage/files`),
},
@@ -100,6 +106,7 @@ export const generateProductRoutes = (
{
key: 'functions',
label: 'Edge Functions',
+ disabled: false,
icon: ,
link: ref && `/project/${ref}/functions`,
},
@@ -110,6 +117,7 @@ export const generateProductRoutes = (
{
key: 'realtime',
label: 'Realtime',
+ disabled: !isProjectActive,
icon: ,
link: ref && (isProjectBuilding ? buildingUrl : `/project/${ref}/realtime/inspector`),
},
@@ -123,6 +131,7 @@ export const generateOtherRoutes = (
project?: Project,
features?: { unifiedLogs?: boolean; showReports?: boolean; apiDocsSidePanel?: boolean }
): Route[] => {
+ const isProjectActive = project?.status === PROJECT_STATUS.ACTIVE_HEALTHY
const isProjectBuilding = project?.status === PROJECT_STATUS.COMING_UP
const buildingUrl = `/project/${ref}`
@@ -135,6 +144,7 @@ export const generateOtherRoutes = (
{
key: 'advisors',
label: 'Advisors',
+ disabled: !isProjectActive,
icon: ,
link: ref && (isProjectBuilding ? buildingUrl : `/project/${ref}/advisors/security`),
},
@@ -143,6 +153,7 @@ export const generateOtherRoutes = (
{
key: 'observability',
label: 'Observability',
+ disabled: !isProjectActive,
icon: ,
link: ref && (isProjectBuilding ? buildingUrl : `/project/${ref}/observability`),
},
@@ -151,20 +162,16 @@ export const generateOtherRoutes = (
{
key: 'logs',
label: 'Logs',
+ disabled: false,
icon:
,
- link:
- ref &&
- (isProjectBuilding
- ? buildingUrl
- : unifiedLogsEnabled
- ? `/project/${ref}/logs`
- : `/project/${ref}/logs/explorer`),
+ link: ref && (unifiedLogsEnabled ? `/project/${ref}/logs` : `/project/${ref}/logs/explorer`),
},
...(apiDocsSidePanelEnabled
? [
{
key: 'api',
label: 'API Docs',
+ disabled: !isProjectActive,
icon: ,
link:
ref &&
@@ -175,6 +182,7 @@ export const generateOtherRoutes = (
{
key: 'integrations',
label: 'Integrations',
+ disabled: !isProjectActive,
icon: ,
link: ref && (isProjectBuilding ? buildingUrl : `/project/${ref}/integrations`),
},
@@ -192,6 +200,7 @@ export const generateSettingsRoutes = (ref?: string, project?: Project): Route[]
ref &&
(IS_PLATFORM ? `/project/${ref}/settings/general` : `/project/${ref}/settings/log-drains`),
items: settingsMenu,
+ disabled: false,
},
]
}
diff --git a/apps/studio/components/layouts/ProjectLayout/index.tsx b/apps/studio/components/layouts/ProjectLayout/index.tsx
index 660c784aa4193..5c63046e4dca2 100644
--- a/apps/studio/components/layouts/ProjectLayout/index.tsx
+++ b/apps/studio/components/layouts/ProjectLayout/index.tsx
@@ -1,7 +1,3 @@
-import Head from 'next/head'
-import { useRouter } from 'next/router'
-import { forwardRef, Fragment, PropsWithChildren, ReactNode, useEffect } from 'react'
-
import { mergeRefs, useParams } from 'common'
import { CreateBranchModal } from 'components/interfaces/BranchManagement/CreateBranchModal'
import { ProjectAPIDocs } from 'components/interfaces/ProjectAPIDocs/ProjectAPIDocs'
@@ -13,10 +9,14 @@ import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { withAuth } from 'hooks/misc/withAuth'
import { usePHFlag } from 'hooks/ui/useFlag'
import { PROJECT_STATUS } from 'lib/constants'
+import Head from 'next/head'
+import { useRouter } from 'next/router'
+import { forwardRef, Fragment, PropsWithChildren, ReactNode, useEffect } from 'react'
import { useAppStateSnapshot } from 'state/app-state'
import { useDatabaseSelectorStateSnapshot } from 'state/database-selector'
import { cn, LogoLoader, ResizableHandle, ResizablePanel, ResizablePanelGroup } from 'ui'
import MobileSheetNav from 'ui-patterns/MobileSheetNav/MobileSheetNav'
+
import { useEditorType } from '../editors/EditorsLayout.hooks'
import { useSetMainScrollContainer } from '../MainScrollContainerContext'
import BuildingState from './BuildingState'
@@ -35,27 +35,27 @@ import { UpgradingState } from './UpgradingState'
// [Joshen] This is temporary while we unblock users from managing their project
// if their project is not responding well for any reason. Eventually needs a bit of an overhaul
const routesToIgnoreProjectDetailsRequest = [
+ '/project/[ref]/settings/infrastructure',
+ '/project/[ref]/settings/addons',
'/project/[ref]/settings/general',
'/project/[ref]/database/settings',
'/project/[ref]/storage/settings',
- '/project/[ref]/settings/infrastructure',
- '/project/[ref]/settings/addons',
]
const routesToIgnoreDBConnection = [
'/project/[ref]/branches',
- '/project/[ref]/database/backups/scheduled',
- '/project/[ref]/database/backups/pitr',
- '/project/[ref]/settings/addons',
+ '/project/[ref]/database/backups',
+ '/project/[ref]/settings',
'/project/[ref]/functions',
+ '/project/[ref]/logs',
]
const routesToIgnorePostgrestConnection = [
- '/project/[ref]/reports',
'/project/[ref]/settings/general',
- '/project/[ref]/database/settings',
'/project/[ref]/settings/infrastructure',
'/project/[ref]/settings/addons',
+ '/project/[ref]/database/settings',
+ '/project/[ref]/reports',
]
export interface ProjectLayoutProps {
@@ -108,7 +108,8 @@ export const ProjectLayout = forwardRef
- {/* autoSaveId="project-layout" */}
{productMenu && (
router.pathname.includes(x))
const requiresPostgrestConnection = !routesToIgnorePostgrestConnection.includes(router.pathname)
const requiresProjectDetails = !routesToIgnoreProjectDetailsRequest.includes(router.pathname)
@@ -304,11 +296,11 @@ const ContentWrapper = ({ isLoading, isBlocking = true, children }: ContentWrapp
// handle redirect to home for building state
const shouldRedirectToHomeForBuilding =
- isHomeNew && requiresDbConnection && isProjectBuilding && !isBranchesPage && !isHomePage
+ isProjectBuilding && requiresDbConnection && isHomeNew && !isHomePage
// We won't be showing the building state with the new home page
const shouldShowBuildingState =
- requiresDbConnection && isProjectBuilding && !isBranchesPage && !(isHomeNew && isHomePage)
+ isProjectBuilding && requiresDbConnection && !(isHomeNew && isHomePage)
useEffect(() => {
if (shouldRedirectToHomeForBuilding && ref) {
@@ -352,7 +344,7 @@ const ContentWrapper = ({ isLoading, isBlocking = true, children }: ContentWrapp
return
}
- if (isProjectRestoreFailed && !isBackupsPage && !isEdgeFunctionPages) {
+ if (requiresDbConnection && isProjectRestoreFailed) {
return
}
diff --git a/apps/studio/components/layouts/ProjectSettingsLayout/SettingsMenu.utils.tsx b/apps/studio/components/layouts/ProjectSettingsLayout/SettingsMenu.utils.tsx
index cd82c7aa6a5f5..17320fc9d33ef 100644
--- a/apps/studio/components/layouts/ProjectSettingsLayout/SettingsMenu.utils.tsx
+++ b/apps/studio/components/layouts/ProjectSettingsLayout/SettingsMenu.utils.tsx
@@ -1,8 +1,7 @@
-import { ArrowUpRight } from 'lucide-react'
-
import type { ProductMenuGroup } from 'components/ui/ProductMenu/ProductMenu.types'
import type { Project } from 'data/projects/project-detail-query'
import { IS_PLATFORM, PROJECT_STATUS } from 'lib/constants'
+import { ArrowUpRight } from 'lucide-react'
import type { Organization } from 'types'
export const generateSettingsMenu = (
@@ -37,13 +36,7 @@ export const generateSettingsMenu = (
}
const isProjectActive = project?.status === PROJECT_STATUS.ACTIVE_HEALTHY
- const isProjectBuilding = project?.status === PROJECT_STATUS.COMING_UP
- const buildingUrl = `/project/${ref}`
- const authEnabled = features?.auth ?? true
- const authProvidersEnabled = features?.authProviders ?? true
- const edgeFunctionsEnabled = features?.edgeFunctions ?? true
- const storageEnabled = features?.storage ?? true
const legacyJwtKeysEnabled = features?.legacyJwtKeys ?? true
const billingEnabled = features?.billing ?? true
@@ -67,7 +60,7 @@ export const generateSettingsMenu = (
{
name: 'Infrastructure',
key: 'infrastructure',
- url: isProjectBuilding ? buildingUrl : `/project/${ref}/settings/infrastructure`,
+ url: `/project/${ref}/settings/infrastructure`,
items: [],
disabled: !isProjectActive,
},
@@ -118,14 +111,15 @@ export const generateSettingsMenu = (
{
name: 'Data API',
key: 'api',
- url: isProjectBuilding ? buildingUrl : `/project/${ref}/integrations/data_api/overview`,
+ url: `/project/${ref}/integrations/data_api/overview`,
items: [],
rightIcon: ,
+ disabled: !isProjectActive,
},
{
name: 'Vault',
key: 'vault',
- url: isProjectBuilding ? buildingUrl : `/project/${ref}/integrations/vault/overview`,
+ url: `/project/${ref}/integrations/vault/overview`,
items: [],
rightIcon: ,
label: 'Beta',
diff --git a/apps/studio/components/ui/HighQueryCost.tsx b/apps/studio/components/ui/HighQueryCost.tsx
index e6a73ac0ec551..ca266201e1c41 100644
--- a/apps/studio/components/ui/HighQueryCost.tsx
+++ b/apps/studio/components/ui/HighQueryCost.tsx
@@ -24,17 +24,26 @@ import { ResponseError } from '@/types'
interface HighQueryCostErrorProps {
error: ResponseError
suggestions?: string[]
+ onSelectLoadData?: () => void
}
-export const HighCostError = ({ error, suggestions }: HighQueryCostErrorProps) => {
- // [Joshen] The CTA could be to use a read replica to query or something?
+export const HighCostError = ({
+ error,
+ suggestions,
+ onSelectLoadData,
+}: HighQueryCostErrorProps) => {
return (
-
+
+ {!!onSelectLoadData && (
+
+ )}
+
+
)
}
@@ -45,9 +54,7 @@ const HighQueryCostDialog = ({ error, suggestions = [] }: HighQueryCostErrorProp
return (