diff --git a/apps/studio/TANSTACK_MIGRATION.md b/apps/studio/TANSTACK_MIGRATION.md index e112a426448..fb8ba8cc114 100644 --- a/apps/studio/TANSTACK_MIGRATION.md +++ b/apps/studio/TANSTACK_MIGRATION.md @@ -180,7 +180,7 @@ These are the layout-only TanStack files. Most hold a single product layout comp - [x] A `routes/project/$ref/database/publications/$id.tsx` ← `pages/project/[ref]/database/publications/[id].tsx` - [x] A `routes/project/$ref/database/replication/index.tsx` ← `pages/project/[ref]/database/replication/index.tsx` - [x] A `routes/project/$ref/database/replication/$pipelineId.tsx` ← `pages/project/[ref]/database/replication/[pipelineId].tsx` -- [x] A `routes/project/$ref/database/replication/replica/$replicaId.tsx` ← `pages/project/[ref]/database/replication/replica/[replicaId].tsx` +- [x] A `routes/project/$ref/database/replication/replica/$replicaId.tsx` ← `pages/project/[ref]/database/replication/replica/[replicaId].tsx` (redirects to Infrastructure) - [x] A `routes/project/$ref/database/triggers/index.tsx` ← `pages/project/[ref]/database/triggers/index.tsx` - [x] A `routes/project/$ref/database/triggers/data.tsx` ← `pages/project/[ref]/database/triggers/data.tsx` (sub-shell at `database/triggers.tsx` provides PageLayout + nav, parent shell provides DatabaseLayout) - [x] A `routes/project/$ref/database/triggers/event.tsx` ← `pages/project/[ref]/database/triggers/event.tsx` (same as data) @@ -296,7 +296,8 @@ These are the layout-only TanStack files. Most hold a single product layout comp - [x] A `routes/project/$ref/settings/addons.tsx` ← `pages/project/[ref]/settings/addons.tsx` - [x] A `routes/project/$ref/settings/api.tsx` ← `pages/project/[ref]/settings/api.tsx` (sets `skipSettingsLayout: true` — page is a useEffect redirect) - [x] A `routes/project/$ref/settings/dashboard.tsx` ← `pages/project/[ref]/settings/dashboard.tsx` -- [x] A `routes/project/$ref/settings/infrastructure.tsx` ← `pages/project/[ref]/settings/infrastructure.tsx` +- [x] A `routes/project/$ref/settings/infrastructure/index.tsx` ← `pages/project/[ref]/settings/infrastructure.tsx` +- [x] A `routes/project/$ref/settings/infrastructure/replica/$replicaId.tsx` ← `pages/project/[ref]/settings/infrastructure/replica/[replicaId].tsx` - [x] A `routes/project/$ref/settings/integrations.tsx` ← `pages/project/[ref]/settings/integrations.tsx` - [x] A `routes/project/$ref/settings/log-drains.tsx` ← `pages/project/[ref]/settings/log-drains.tsx` - [x] A `routes/project/$ref/settings/api-keys/index.tsx` ← `pages/project/[ref]/settings/api-keys/index.tsx` (under `api-keys.tsx` sub-shell with ApiKeysLayout) diff --git a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceNode.tsx b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceNode.tsx index 89fec06b3ac..d890b143fc8 100644 --- a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceNode.tsx +++ b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceNode.tsx @@ -33,6 +33,7 @@ import { } from './InstanceConfiguration.constants' import { formatSeconds } from './InstanceConfiguration.utils' import { metricColor } from './InstanceNode.utils' +import { getReadReplicaPath } from '@/components/interfaces/Settings/Infrastructure/Infrastructure.utils' import { REPLICA_STATUS } from '@/components/interfaces/Settings/Infrastructure/ReadReplicas/ReadReplicas.constants' import { SparkBar } from '@/components/ui/SparkBar' import { @@ -417,9 +418,7 @@ export const ReplicaNode = ({ data }: NodeProps>) => { - - Manage replica - + Manage replica diff --git a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/MapView.tsx b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/MapView.tsx index 7894593313d..d94bb31fd50 100644 --- a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/MapView.tsx +++ b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/MapView.tsx @@ -27,6 +27,7 @@ import { TimestampInfo } from 'ui-patterns/TimestampInfo' import { AVAILABLE_REPLICA_REGIONS } from './InstanceConfiguration.constants' import GeographyData from './MapData.json' +import { getReadReplicaPath } from '@/components/interfaces/Settings/Infrastructure/Infrastructure.utils' import { REPLICA_STATUS } from '@/components/interfaces/Settings/Infrastructure/ReadReplicas/ReadReplicas.constants' import { useReadReplicasQuery } from '@/data/read-replicas/replicas-query' import { formatDatabaseID } from '@/data/read-replicas/replicas.utils' @@ -303,9 +304,7 @@ const MapView = () => { - + Manage replica diff --git a/apps/studio/components/interfaces/Settings/Infrastructure/ReadReplicas/ReadReplicaRow.tsx b/apps/studio/components/interfaces/Settings/Infrastructure/ReadReplicas/ReadReplicaRow.tsx index 5895abb13d8..d8fc7ebe61b 100644 --- a/apps/studio/components/interfaces/Settings/Infrastructure/ReadReplicas/ReadReplicaRow.tsx +++ b/apps/studio/components/interfaces/Settings/Infrastructure/ReadReplicas/ReadReplicaRow.tsx @@ -24,6 +24,7 @@ import { DropReplicaConfirmationModal } from './DropReplicaConfirmationModal' import { REPLICA_STATUS } from './ReadReplicas.constants' import { getIsInTransition, getStatusLabel } from './ReadReplicas.utils' import { RestartReplicaConfirmationModal } from './RestartReplicaConfirmationModal' +import { getReadReplicaPath } from '@/components/interfaces/Settings/Infrastructure/Infrastructure.utils' import { useReplicationLagQuery } from '@/data/read-replicas/replica-lag-query' import { type Database } from '@/data/read-replicas/replicas-query' import { formatDatabaseID } from '@/data/read-replicas/replicas.utils' @@ -105,10 +106,6 @@ export const ReadReplicaRow = ({ replica, onUpdateReplica }: ReadReplicaRow) => )} - - - -
diff --git a/apps/studio/pages/project/[ref]/database/replication/replica/[replicaId].tsx b/apps/studio/pages/project/[ref]/database/replication/replica/[replicaId].tsx index e129249b1e3..1c1d35880f1 100644 --- a/apps/studio/pages/project/[ref]/database/replication/replica/[replicaId].tsx +++ b/apps/studio/pages/project/[ref]/database/replication/replica/[replicaId].tsx @@ -1,186 +1,34 @@ import { useParams } from 'common' -import { Database } from 'icons' -import { Loader2, Trash } from 'lucide-react' -import Link from 'next/link' import { useRouter } from 'next/router' -import { useEffect, useMemo, useState } from 'react' -import { AWS_REGIONS } from 'shared-data' -import { Badge, Button } from 'ui' -import { ShimmeringLoader } from 'ui-patterns/ShimmeringLoader' +import { useEffect } from 'react' +import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader' -import { DropReplicaConfirmationModal } from '@/components/interfaces/Settings/Infrastructure/ReadReplicas/DropReplicaConfirmationModal' -import { ReadReplicaDetails } from '@/components/interfaces/Settings/Infrastructure/ReadReplicas/ReadReplicaDetails' -import { REPLICA_STATUS } from '@/components/interfaces/Settings/Infrastructure/ReadReplicas/ReadReplicas.constants' -import { - getIsInTransition, - getStatusLabel, -} from '@/components/interfaces/Settings/Infrastructure/ReadReplicas/ReadReplicas.utils' -import { RestartReplicaConfirmationModal } from '@/components/interfaces/Settings/Infrastructure/ReadReplicas/RestartReplicaConfirmationModal' +import { getReadReplicaPath } from '@/components/interfaces/Settings/Infrastructure/Infrastructure.utils' import DatabaseLayout from '@/components/layouts/DatabaseLayout/DatabaseLayout' import { DefaultLayout } from '@/components/layouts/DefaultLayout' -import { PageLayout } from '@/components/layouts/PageLayout/PageLayout' -import { ScaffoldDescription, ScaffoldTitle } from '@/components/layouts/Scaffold' -import { ButtonTooltip } from '@/components/ui/ButtonTooltip' -import CopyButton from '@/components/ui/CopyButton' -import { useReadReplicasQuery } from '@/data/read-replicas/replicas-query' -import { - ReplicaInitializationStatus, - useReadReplicasStatusesQuery, -} from '@/data/read-replicas/replicas-status-query' import type { NextPageWithLayout } from '@/types' -const DatabaseReadReplicaPage: NextPageWithLayout = () => { +/** @deprecated Redirects to Settings → Infrastructure replica detail. */ +const DatabaseReadReplicaRedirectPage: NextPageWithLayout = () => { const router = useRouter() const { ref, replicaId } = useParams() - const [showConfirmRestart, setShowConfirmRestart] = useState(false) - const [showConfirmDrop, setShowConfirmDrop] = useState(false) - const [statusRefetchInterval, setStatusRefetchInterval] = useState(5000) - - const { - data: databases = [], - isPending: isLoadingDatabases, - isSuccess: isSuccessDatabases, - } = useReadReplicasQuery({ projectRef: ref }) - const replica = databases.find((x) => x.identifier === replicaId) - const { identifier, region, status: baseStatus } = replica ?? {} - - const { data: statuses = [], isSuccess: isSuccessReplicasStatuses } = - useReadReplicasStatusesQuery({ projectRef: ref }, { refetchInterval: statusRefetchInterval }) - const replicaStatus = statuses.find((x) => x.identifier === identifier) - const status = replicaStatus?.status ?? baseStatus - const initStatus = replicaStatus?.replicaInitializationStatus?.status - - const regionLabel = Object.values(AWS_REGIONS).find((x) => x.code === region)?.displayName - const statusLabel = useMemo(() => getStatusLabel({ initStatus, status }), [initStatus, status]) - const isInTransition = useMemo( - () => getIsInTransition({ initStatus, status }), - [initStatus, status] - ) - useEffect(() => { - if (!isSuccessReplicasStatuses) return - - const pollReplicas = async () => { - const fixedStatuses = [ - REPLICA_STATUS.ACTIVE_HEALTHY, - REPLICA_STATUS.ACTIVE_UNHEALTHY, - REPLICA_STATUS.INIT_READ_REPLICA_FAILED, - ] - const replicasInTransition = statuses.filter((db) => { - const { status } = db.replicaInitializationStatus || {} - return ( - !fixedStatuses.includes(db.status) || status === ReplicaInitializationStatus.InProgress - ) - }) - const hasTransientStatus = replicasInTransition.length > 0 - - // If all replicas are active healthy, stop fetching statuses - if (!hasTransientStatus && statuses.length === databases.length) { - setStatusRefetchInterval(false) - } - } - - pollReplicas() - }, [databases.length, isSuccessReplicasStatuses, statuses]) + if (!ref || !replicaId) return + router.replace(getReadReplicaPath(ref, replicaId)) + }, [ref, replicaId, router]) return ( - - Read Replica - {isSuccessDatabases && ( - <> - - {statusLabel} - - {isInTransition && } - - )} -
- } - subtitle={ - isLoadingDatabases ? ( - - ) : ( -
- ID: {identifier} - -
- ) - } - icon={ -
- -
- } - breadcrumbs={[ - { - label: 'Replication', - href: `/project/${ref}/database/replication`, - }, - { - label: `Read Replica - ${regionLabel}`, - }, - ]} - secondaryActions={ - } - tooltip={{ - content: { side: 'bottom', text: 'Drop replica' }, - }} - onClick={() => setShowConfirmDrop(true)} - /> - } - primaryActions={[ - , - , - ]} - > - - - router.push(`/project/${ref}/database/replication`)} - onCancel={() => setShowConfirmDrop(false)} - /> - - setStatusRefetchInterval(5000)} - onCancel={() => setShowConfirmRestart(false)} - /> - +
+ +
) } -DatabaseReadReplicaPage.getLayout = (page) => ( +DatabaseReadReplicaRedirectPage.getLayout = (page) => ( {page} ) -export default DatabaseReadReplicaPage +export default DatabaseReadReplicaRedirectPage diff --git a/apps/studio/pages/project/[ref]/settings/infrastructure/replica/[replicaId].tsx b/apps/studio/pages/project/[ref]/settings/infrastructure/replica/[replicaId].tsx new file mode 100644 index 00000000000..4724913bcb5 --- /dev/null +++ b/apps/studio/pages/project/[ref]/settings/infrastructure/replica/[replicaId].tsx @@ -0,0 +1,176 @@ +import { useParams } from 'common' +import { Database } from 'icons' +import { Loader2, Trash } from 'lucide-react' +import Link from 'next/link' +import { useRouter } from 'next/router' +import { useEffect, useMemo, useState } from 'react' +import { AWS_REGIONS } from 'shared-data' +import { Badge, Button } from 'ui' +import { ShimmeringLoader } from 'ui-patterns/ShimmeringLoader' + +import { getInfrastructurePath } from '@/components/interfaces/Settings/Infrastructure/Infrastructure.utils' +import { DropReplicaConfirmationModal } from '@/components/interfaces/Settings/Infrastructure/ReadReplicas/DropReplicaConfirmationModal' +import { ReadReplicaDetails } from '@/components/interfaces/Settings/Infrastructure/ReadReplicas/ReadReplicaDetails' +import { REPLICA_STATUS } from '@/components/interfaces/Settings/Infrastructure/ReadReplicas/ReadReplicas.constants' +import { + getIsInTransition, + getStatusLabel, +} from '@/components/interfaces/Settings/Infrastructure/ReadReplicas/ReadReplicas.utils' +import { RestartReplicaConfirmationModal } from '@/components/interfaces/Settings/Infrastructure/ReadReplicas/RestartReplicaConfirmationModal' +import { DefaultLayout } from '@/components/layouts/DefaultLayout' +import { PageLayout } from '@/components/layouts/PageLayout/PageLayout' +import SettingsLayout from '@/components/layouts/ProjectSettingsLayout/SettingsLayout' +import { ScaffoldDescription, ScaffoldTitle } from '@/components/layouts/Scaffold' +import { ButtonTooltip } from '@/components/ui/ButtonTooltip' +import CopyButton from '@/components/ui/CopyButton' +import { useReadReplicasQuery } from '@/data/read-replicas/replicas-query' +import { + ReplicaInitializationStatus, + useReadReplicasStatusesQuery, +} from '@/data/read-replicas/replicas-status-query' +import type { NextPageWithLayout } from '@/types' + +const STATUS_BADGE_VARIANT: Record = { + Healthy: 'success', + Failed: 'destructive', +} + +const InfrastructureReadReplicaPage: NextPageWithLayout = () => { + const router = useRouter() + const { ref, replicaId } = useParams() + + const [showConfirmRestart, setShowConfirmRestart] = useState(false) + const [showConfirmDrop, setShowConfirmDrop] = useState(false) + const [statusRefetchInterval, setStatusRefetchInterval] = useState(5000) + + const { + data: databases = [], + isPending: isLoadingDatabases, + isSuccess: isSuccessDatabases, + } = useReadReplicasQuery({ projectRef: ref }) + const replica = databases.find((x) => x.identifier === replicaId) + const { identifier, region, status: baseStatus } = replica ?? {} + + const { data: statuses = [], isSuccess: isSuccessReplicasStatuses } = + useReadReplicasStatusesQuery({ projectRef: ref }, { refetchInterval: statusRefetchInterval }) + const replicaStatus = statuses.find((x) => x.identifier === identifier) + const status = replicaStatus?.status ?? baseStatus + const initStatus = replicaStatus?.replicaInitializationStatus?.status + + const regionLabel = Object.values(AWS_REGIONS).find((x) => x.code === region)?.displayName + const statusLabel = useMemo(() => getStatusLabel({ initStatus, status }), [initStatus, status]) + const isInTransition = useMemo( + () => getIsInTransition({ initStatus, status }), + [initStatus, status] + ) + + useEffect(() => { + if (!isSuccessReplicasStatuses) return + + const fixedStatuses = [ + REPLICA_STATUS.ACTIVE_HEALTHY, + REPLICA_STATUS.ACTIVE_UNHEALTHY, + REPLICA_STATUS.INIT_READ_REPLICA_FAILED, + ] + const replicasInTransition = statuses.filter((db) => { + const { status: init } = db.replicaInitializationStatus || {} + return !fixedStatuses.includes(db.status) || init === ReplicaInitializationStatus.InProgress + }) + const hasTransientStatus = replicasInTransition.length > 0 + + if (!hasTransientStatus && statuses.length === databases.length) { + setStatusRefetchInterval(false) + } + }, [databases.length, isSuccessReplicasStatuses, statuses]) + + return ( + + Read Replica + {isSuccessDatabases && ( + <> + {statusLabel} + {isInTransition && } + + )} + + } + subtitle={ + isLoadingDatabases ? ( + + ) : ( +
+ ID: {identifier} + +
+ ) + } + icon={ +
+ +
+ } + breadcrumbs={[ + { + label: 'Infrastructure', + href: getInfrastructurePath(ref), + }, + { + label: regionLabel ? `Read Replica - ${regionLabel}` : 'Read Replica', + }, + ]} + secondaryActions={ + } + disabled={!replica} + tooltip={{ + content: { side: 'bottom', text: 'Drop replica' }, + }} + onClick={() => setShowConfirmDrop(true)} + /> + } + primaryActions={[ + , + , + ]} + > + + + router.push(getInfrastructurePath(ref))} + onCancel={() => setShowConfirmDrop(false)} + /> + + setStatusRefetchInterval(5000)} + onCancel={() => setShowConfirmRestart(false)} + /> +
+ ) +} + +InfrastructureReadReplicaPage.getLayout = (page) => ( + + {page} + +) + +export default InfrastructureReadReplicaPage diff --git a/apps/studio/redirects.shared.test.ts b/apps/studio/redirects.shared.test.ts index 1aa495d6e0e..5667989470f 100644 --- a/apps/studio/redirects.shared.test.ts +++ b/apps/studio/redirects.shared.test.ts @@ -66,6 +66,19 @@ describe('matchRedirect query/hash preservation', () => { }) }) + it('redirects legacy replication replica detail to infrastructure', () => { + expect( + matchRedirect({ + pathname: '/project/abc/database/replication/replica/replica-1', + search: {}, + isPlatform: true, + }) + ).toEqual({ + destination: '/project/abc/settings/infrastructure/replica/replica-1', + permanent: true, + }) + }) + it('redirects the legacy compute billing panel to the CPU section', () => { expect( matchRedirect({ diff --git a/apps/studio/redirects.shared.ts b/apps/studio/redirects.shared.ts index 845f11cb68a..e3f2b6f6f53 100644 --- a/apps/studio/redirects.shared.ts +++ b/apps/studio/redirects.shared.ts @@ -119,6 +119,11 @@ export const SHARED_REDIRECTS: StudioRedirect[] = [ destination: '/project/:ref/settings/infrastructure', permanent: true, }, + { + source: '/project/:ref/database/replication/replica/:replicaId', + destination: '/project/:ref/settings/infrastructure/replica/:replicaId', + permanent: true, + }, { source: '/project/:ref/settings/billing/subscription', has: [{ type: 'query', key: 'panel', value: 'pitr' }], diff --git a/apps/studio/routeTree.gen.ts b/apps/studio/routeTree.gen.ts index 3e9a16ff2da..244dfef9eae 100644 --- a/apps/studio/routeTree.gen.ts +++ b/apps/studio/routeTree.gen.ts @@ -106,7 +106,7 @@ import { Route as ProjectRefSqlExamplesRouteImport } from './routes/project/$ref import { Route as ProjectRefSqlIdRouteImport } from './routes/project/$ref/sql/$id' import { Route as ProjectRefSettingsLogDrainsRouteImport } from './routes/project/$ref/settings/log-drains' import { Route as ProjectRefSettingsIntegrationsRouteImport } from './routes/project/$ref/settings/integrations' -import { Route as ProjectRefSettingsInfrastructureRouteImport } from './routes/project/$ref/settings/infrastructure' +import { Route as ProjectRefSettingsInfrastructureIndexRouteImport } from './routes/project/$ref/settings/infrastructure/index' import { Route as ProjectRefSettingsGeneralRouteImport } from './routes/project/$ref/settings/general' import { Route as ProjectRefSettingsDashboardRouteImport } from './routes/project/$ref/settings/dashboard' import { Route as ProjectRefSettingsApiKeysRouteImport } from './routes/project/$ref/settings/api-keys' @@ -285,6 +285,7 @@ import { Route as ApiPlatformAuthRefUsersIndexRouteImport } from './routes/api/p import { Route as ProjectRefStorageVectorsBucketsBucketIdRouteImport } from './routes/project/$ref/storage/vectors/buckets/$bucketId' import { Route as ProjectRefStorageFilesBucketsBucketIdRouteImport } from './routes/project/$ref/storage/files/buckets/$bucketId' import { Route as ProjectRefStorageAnalyticsBucketsBucketIdRouteImport } from './routes/project/$ref/storage/analytics/buckets/$bucketId' +import { Route as ProjectRefSettingsInfrastructureReplicaReplicaIdRouteImport } from './routes/project/$ref/settings/infrastructure/replica/$replicaId' import { Route as ProjectRefDatabaseReplicationReplicaReplicaIdRouteImport } from './routes/project/$ref/database/replication/replica/$replicaId' import { Route as ApiV1ProjectsRefTypesTypescriptRouteImport } from './routes/api/v1/projects/$ref/types/typescript' import { Route as ApiV1ProjectsRefDatabaseMigrationsRouteImport } from './routes/api/v1/projects/$ref/database/migrations' @@ -823,10 +824,10 @@ const ProjectRefSettingsIntegrationsRoute = path: '/integrations', getParentRoute: () => ProjectRefSettingsRoute, } as any) -const ProjectRefSettingsInfrastructureRoute = - ProjectRefSettingsInfrastructureRouteImport.update({ - id: '/infrastructure', - path: '/infrastructure', +const ProjectRefSettingsInfrastructureIndexRoute = + ProjectRefSettingsInfrastructureIndexRouteImport.update({ + id: '/infrastructure/', + path: '/infrastructure/', getParentRoute: () => ProjectRefSettingsRoute, } as any) const ProjectRefSettingsGeneralRoute = @@ -1851,6 +1852,12 @@ const ProjectRefStorageAnalyticsBucketsBucketIdRoute = path: '/analytics/buckets/$bucketId', getParentRoute: () => ProjectRefStorageRoute, } as any) +const ProjectRefSettingsInfrastructureReplicaReplicaIdRoute = + ProjectRefSettingsInfrastructureReplicaReplicaIdRouteImport.update({ + id: '/infrastructure/replica/$replicaId', + path: '/infrastructure/replica/$replicaId', + getParentRoute: () => ProjectRefSettingsRoute, + } as any) const ProjectRefDatabaseReplicationReplicaReplicaIdRoute = ProjectRefDatabaseReplicationReplicaReplicaIdRouteImport.update({ id: '/replication/replica/$replicaId', @@ -2249,7 +2256,7 @@ export interface FileRoutesByFullPath { '/project/$ref/settings/api-keys': typeof ProjectRefSettingsApiKeysRouteWithChildren '/project/$ref/settings/dashboard': typeof ProjectRefSettingsDashboardRoute '/project/$ref/settings/general': typeof ProjectRefSettingsGeneralRoute - '/project/$ref/settings/infrastructure': typeof ProjectRefSettingsInfrastructureRoute + '/project/$ref/settings/infrastructure/': typeof ProjectRefSettingsInfrastructureIndexRoute '/project/$ref/settings/integrations': typeof ProjectRefSettingsIntegrationsRoute '/project/$ref/settings/log-drains': typeof ProjectRefSettingsLogDrainsRoute '/project/$ref/sql/$id': typeof ProjectRefSqlIdRoute @@ -2356,6 +2363,7 @@ export interface FileRoutesByFullPath { '/api/v1/projects/$ref/database/migrations': typeof ApiV1ProjectsRefDatabaseMigrationsRoute '/api/v1/projects/$ref/types/typescript': typeof ApiV1ProjectsRefTypesTypescriptRoute '/project/$ref/database/replication/replica/$replicaId': typeof ProjectRefDatabaseReplicationReplicaReplicaIdRoute + '/project/$ref/settings/infrastructure/replica/$replicaId': typeof ProjectRefSettingsInfrastructureReplicaReplicaIdRoute '/project/$ref/storage/analytics/buckets/$bucketId': typeof ProjectRefStorageAnalyticsBucketsBucketIdRoute '/project/$ref/storage/files/buckets/$bucketId': typeof ProjectRefStorageFilesBucketsBucketIdRoute '/project/$ref/storage/vectors/buckets/$bucketId': typeof ProjectRefStorageVectorsBucketsBucketIdRoute @@ -2549,7 +2557,7 @@ export interface FileRoutesByTo { '/project/$ref/settings/api': typeof ProjectRefSettingsApiRoute '/project/$ref/settings/dashboard': typeof ProjectRefSettingsDashboardRoute '/project/$ref/settings/general': typeof ProjectRefSettingsGeneralRoute - '/project/$ref/settings/infrastructure': typeof ProjectRefSettingsInfrastructureRoute + '/project/$ref/settings/infrastructure': typeof ProjectRefSettingsInfrastructureIndexRoute '/project/$ref/settings/integrations': typeof ProjectRefSettingsIntegrationsRoute '/project/$ref/settings/log-drains': typeof ProjectRefSettingsLogDrainsRoute '/project/$ref/sql/$id': typeof ProjectRefSqlIdRoute @@ -2656,6 +2664,7 @@ export interface FileRoutesByTo { '/api/v1/projects/$ref/database/migrations': typeof ApiV1ProjectsRefDatabaseMigrationsRoute '/api/v1/projects/$ref/types/typescript': typeof ApiV1ProjectsRefTypesTypescriptRoute '/project/$ref/database/replication/replica/$replicaId': typeof ProjectRefDatabaseReplicationReplicaReplicaIdRoute + '/project/$ref/settings/infrastructure/replica/$replicaId': typeof ProjectRefSettingsInfrastructureReplicaReplicaIdRoute '/project/$ref/storage/analytics/buckets/$bucketId': typeof ProjectRefStorageAnalyticsBucketsBucketIdRoute '/project/$ref/storage/files/buckets/$bucketId': typeof ProjectRefStorageFilesBucketsBucketIdRoute '/project/$ref/storage/vectors/buckets/$bucketId': typeof ProjectRefStorageVectorsBucketsBucketIdRoute @@ -2866,7 +2875,7 @@ export interface FileRoutesById { '/project/$ref/settings/api-keys': typeof ProjectRefSettingsApiKeysRouteWithChildren '/project/$ref/settings/dashboard': typeof ProjectRefSettingsDashboardRoute '/project/$ref/settings/general': typeof ProjectRefSettingsGeneralRoute - '/project/$ref/settings/infrastructure': typeof ProjectRefSettingsInfrastructureRoute + '/project/$ref/settings/infrastructure/': typeof ProjectRefSettingsInfrastructureIndexRoute '/project/$ref/settings/integrations': typeof ProjectRefSettingsIntegrationsRoute '/project/$ref/settings/log-drains': typeof ProjectRefSettingsLogDrainsRoute '/project/$ref/sql/$id': typeof ProjectRefSqlIdRoute @@ -2973,6 +2982,7 @@ export interface FileRoutesById { '/api/v1/projects/$ref/database/migrations': typeof ApiV1ProjectsRefDatabaseMigrationsRoute '/api/v1/projects/$ref/types/typescript': typeof ApiV1ProjectsRefTypesTypescriptRoute '/project/$ref/database/replication/replica/$replicaId': typeof ProjectRefDatabaseReplicationReplicaReplicaIdRoute + '/project/$ref/settings/infrastructure/replica/$replicaId': typeof ProjectRefSettingsInfrastructureReplicaReplicaIdRoute '/project/$ref/storage/analytics/buckets/$bucketId': typeof ProjectRefStorageAnalyticsBucketsBucketIdRoute '/project/$ref/storage/files/buckets/$bucketId': typeof ProjectRefStorageFilesBucketsBucketIdRoute '/project/$ref/storage/vectors/buckets/$bucketId': typeof ProjectRefStorageVectorsBucketsBucketIdRoute @@ -3182,7 +3192,7 @@ export interface FileRouteTypes { | '/project/$ref/settings/api-keys' | '/project/$ref/settings/dashboard' | '/project/$ref/settings/general' - | '/project/$ref/settings/infrastructure' + | '/project/$ref/settings/infrastructure/' | '/project/$ref/settings/integrations' | '/project/$ref/settings/log-drains' | '/project/$ref/sql/$id' @@ -3289,6 +3299,7 @@ export interface FileRouteTypes { | '/api/v1/projects/$ref/database/migrations' | '/api/v1/projects/$ref/types/typescript' | '/project/$ref/database/replication/replica/$replicaId' + | '/project/$ref/settings/infrastructure/replica/$replicaId' | '/project/$ref/storage/analytics/buckets/$bucketId' | '/project/$ref/storage/files/buckets/$bucketId' | '/project/$ref/storage/vectors/buckets/$bucketId' @@ -3589,6 +3600,7 @@ export interface FileRouteTypes { | '/api/v1/projects/$ref/database/migrations' | '/api/v1/projects/$ref/types/typescript' | '/project/$ref/database/replication/replica/$replicaId' + | '/project/$ref/settings/infrastructure/replica/$replicaId' | '/project/$ref/storage/analytics/buckets/$bucketId' | '/project/$ref/storage/files/buckets/$bucketId' | '/project/$ref/storage/vectors/buckets/$bucketId' @@ -3798,7 +3810,7 @@ export interface FileRouteTypes { | '/project/$ref/settings/api-keys' | '/project/$ref/settings/dashboard' | '/project/$ref/settings/general' - | '/project/$ref/settings/infrastructure' + | '/project/$ref/settings/infrastructure/' | '/project/$ref/settings/integrations' | '/project/$ref/settings/log-drains' | '/project/$ref/sql/$id' @@ -3905,6 +3917,7 @@ export interface FileRouteTypes { | '/api/v1/projects/$ref/database/migrations' | '/api/v1/projects/$ref/types/typescript' | '/project/$ref/database/replication/replica/$replicaId' + | '/project/$ref/settings/infrastructure/replica/$replicaId' | '/project/$ref/storage/analytics/buckets/$bucketId' | '/project/$ref/storage/files/buckets/$bucketId' | '/project/$ref/storage/vectors/buckets/$bucketId' @@ -4748,11 +4761,11 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof ProjectRefSettingsIntegrationsRouteImport parentRoute: typeof ProjectRefSettingsRoute } - '/project/$ref/settings/infrastructure': { - id: '/project/$ref/settings/infrastructure' + '/project/$ref/settings/infrastructure/': { + id: '/project/$ref/settings/infrastructure/' path: '/infrastructure' - fullPath: '/project/$ref/settings/infrastructure' - preLoaderRoute: typeof ProjectRefSettingsInfrastructureRouteImport + fullPath: '/project/$ref/settings/infrastructure/' + preLoaderRoute: typeof ProjectRefSettingsInfrastructureIndexRouteImport parentRoute: typeof ProjectRefSettingsRoute } '/project/$ref/settings/general': { @@ -6001,6 +6014,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof ProjectRefStorageAnalyticsBucketsBucketIdRouteImport parentRoute: typeof ProjectRefStorageRoute } + '/project/$ref/settings/infrastructure/replica/$replicaId': { + id: '/project/$ref/settings/infrastructure/replica/$replicaId' + path: '/infrastructure/replica/$replicaId' + fullPath: '/project/$ref/settings/infrastructure/replica/$replicaId' + preLoaderRoute: typeof ProjectRefSettingsInfrastructureReplicaReplicaIdRouteImport + parentRoute: typeof ProjectRefSettingsRoute + } '/project/$ref/database/replication/replica/$replicaId': { id: '/project/$ref/database/replication/replica/$replicaId' path: '/replication/replica/$replicaId' @@ -6802,7 +6822,8 @@ interface ProjectRefSettingsRouteChildren { ProjectRefSettingsApiKeysRoute: typeof ProjectRefSettingsApiKeysRouteWithChildren ProjectRefSettingsDashboardRoute: typeof ProjectRefSettingsDashboardRoute ProjectRefSettingsGeneralRoute: typeof ProjectRefSettingsGeneralRoute - ProjectRefSettingsInfrastructureRoute: typeof ProjectRefSettingsInfrastructureRoute + ProjectRefSettingsInfrastructureIndexRoute: typeof ProjectRefSettingsInfrastructureIndexRoute + ProjectRefSettingsInfrastructureReplicaReplicaIdRoute: typeof ProjectRefSettingsInfrastructureReplicaReplicaIdRoute ProjectRefSettingsIntegrationsRoute: typeof ProjectRefSettingsIntegrationsRoute ProjectRefSettingsLogDrainsRoute: typeof ProjectRefSettingsLogDrainsRoute ProjectRefSettingsBillingUsageRoute: typeof ProjectRefSettingsBillingUsageRoute @@ -6818,7 +6839,10 @@ const ProjectRefSettingsRouteChildren: ProjectRefSettingsRouteChildren = { ProjectRefSettingsApiKeysRoute: ProjectRefSettingsApiKeysRouteWithChildren, ProjectRefSettingsDashboardRoute: ProjectRefSettingsDashboardRoute, ProjectRefSettingsGeneralRoute: ProjectRefSettingsGeneralRoute, - ProjectRefSettingsInfrastructureRoute: ProjectRefSettingsInfrastructureRoute, + ProjectRefSettingsInfrastructureIndexRoute: + ProjectRefSettingsInfrastructureIndexRoute, + ProjectRefSettingsInfrastructureReplicaReplicaIdRoute: + ProjectRefSettingsInfrastructureReplicaReplicaIdRoute, ProjectRefSettingsIntegrationsRoute: ProjectRefSettingsIntegrationsRoute, ProjectRefSettingsLogDrainsRoute: ProjectRefSettingsLogDrainsRoute, ProjectRefSettingsBillingUsageRoute: ProjectRefSettingsBillingUsageRoute, diff --git a/apps/studio/routes/project/$ref/database/replication/replica/$replicaId.tsx b/apps/studio/routes/project/$ref/database/replication/replica/$replicaId.tsx index bb4df6c4b8c..c30762ebd41 100644 --- a/apps/studio/routes/project/$ref/database/replication/replica/$replicaId.tsx +++ b/apps/studio/routes/project/$ref/database/replication/replica/$replicaId.tsx @@ -1,6 +1,6 @@ import { createFileRoute } from '@tanstack/react-router' -import DatabaseReadReplicaPage from '@/pages/project/[ref]/database/replication/replica/[replicaId]' +import DatabaseReadReplicaRedirectPage from '@/pages/project/[ref]/database/replication/replica/[replicaId]' export const Route = createFileRoute('/project/$ref/database/replication/replica/$replicaId')({ component: DatabaseReplicationReplicaRoute, @@ -10,5 +10,5 @@ export const Route = createFileRoute('/project/$ref/database/replication/replica }) function DatabaseReplicationReplicaRoute() { - return + return } diff --git a/apps/studio/routes/project/$ref/settings/infrastructure.tsx b/apps/studio/routes/project/$ref/settings/infrastructure/index.tsx similarity index 96% rename from apps/studio/routes/project/$ref/settings/infrastructure.tsx rename to apps/studio/routes/project/$ref/settings/infrastructure/index.tsx index 5c968a103fd..b5642759177 100644 --- a/apps/studio/routes/project/$ref/settings/infrastructure.tsx +++ b/apps/studio/routes/project/$ref/settings/infrastructure/index.tsx @@ -2,7 +2,7 @@ import { createFileRoute } from '@tanstack/react-router' import ProjectInfrastructure from '@/pages/project/[ref]/settings/infrastructure' -export const Route = createFileRoute('/project/$ref/settings/infrastructure')({ +export const Route = createFileRoute('/project/$ref/settings/infrastructure/')({ component: SettingsInfrastructureRoute, staticData: { settingsLayoutTitle: 'Infrastructure' }, }) diff --git a/apps/studio/routes/project/$ref/settings/infrastructure/replica/$replicaId.tsx b/apps/studio/routes/project/$ref/settings/infrastructure/replica/$replicaId.tsx new file mode 100644 index 00000000000..604d39e9958 --- /dev/null +++ b/apps/studio/routes/project/$ref/settings/infrastructure/replica/$replicaId.tsx @@ -0,0 +1,12 @@ +import { createFileRoute } from '@tanstack/react-router' + +import InfrastructureReadReplicaPage from '@/pages/project/[ref]/settings/infrastructure/replica/[replicaId]' + +export const Route = createFileRoute('/project/$ref/settings/infrastructure/replica/$replicaId')({ + component: InfrastructureReadReplicaRoute, + staticData: { settingsLayoutTitle: 'Infrastructure' }, +}) + +function InfrastructureReadReplicaRoute() { + return +}