diff --git a/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx b/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx
index 74e4e6c19e1..d87be9046c1 100644
--- a/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx
+++ b/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx
@@ -38,11 +38,13 @@ import { JsonEditValue } from './SidePanelEditor/RowEditor/RowEditor.types'
import { ForeignRowSelectorProps } from './SidePanelEditor/RowEditor/ForeignRowSelector/ForeignRowSelector'
import TableDefinition from './TableDefinition'
import APIDocumentationPanel from './APIDocumentationPanel'
+import Connecting from 'components/ui/Loading/Loading'
export interface TableGridEditorProps {
/** Theme for the editor */
theme?: 'dark' | 'light'
+ isLoadingSelectedTable?: boolean
selectedTable: any // PostgresTable | SchemaView
/** Determines what side panel editor to show */
@@ -77,6 +79,7 @@ export interface TableGridEditorProps {
const TableGridEditor = ({
theme = 'dark',
+ isLoadingSelectedTable = false,
selectedTable,
sidePanelKey,
isDuplicating,
@@ -202,6 +205,10 @@ const TableGridEditor = ({
const entityType = useEntityType(selectedTable?.id)
+ if (isLoadingSelectedTable) {
+ return
+ }
+
// NOTE: DO NOT PUT HOOKS AFTER THIS LINE
if (isUndefined(selectedTable)) {
return
diff --git a/studio/components/layouts/TableEditorLayout/TableEditorLayout.tsx b/studio/components/layouts/TableEditorLayout/TableEditorLayout.tsx
index 8ab79999ccf..d27a43a4c85 100644
--- a/studio/components/layouts/TableEditorLayout/TableEditorLayout.tsx
+++ b/studio/components/layouts/TableEditorLayout/TableEditorLayout.tsx
@@ -1,21 +1,13 @@
import { PropsWithChildren, useEffect } from 'react'
-import { useRouter } from 'next/router'
import { noop } from 'lodash'
import { observer } from 'mobx-react-lite'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { checkPermissions, useStore } from 'hooks'
-import { useParams } from 'common/hooks'
import { Entity } from 'data/entity-types/entity-type-query'
-import { ENTITY_TYPE } from 'data/entity-types/entity-type-constants'
-import { useIsTableLoaded, useTableEditorGlobalStateSnapshot } from 'state/table-editor-global'
import ProjectLayout from '../'
import TableEditorMenu from './TableEditorMenu'
import NoPermission from 'components/ui/NoPermission'
-import useEntityType from 'hooks/misc/useEntityType'
-import Connecting from 'components/ui/Loading/Loading'
-import useLatest from 'hooks/misc/useLatest'
-import useTableRowsPrefetchWrapper from './TableEditorLayout.utils'
export interface TableEditorLayoutProps {
onAddTable: () => void
@@ -32,11 +24,7 @@ const TableEditorLayout = ({
children,
}: PropsWithChildren) => {
const { vault, meta, ui } = useStore()
- const router = useRouter()
- const { ref, id: _id } = useParams()
- const id = _id ? Number(_id) : undefined
- const snap = useTableEditorGlobalStateSnapshot()
const canReadTables = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_READ, 'tables')
const vaultExtension = meta.extensions.byId('supabase_vault')
@@ -51,56 +39,6 @@ const TableEditorLayout = ({
}
}, [ui.selectedProject?.ref])
- const isLoaded = useIsTableLoaded(ref, id)
-
- const entity = useEntityType(id, function onNotFound(id) {
- if (ref) snap.addLoadedId(ref, id)
- })
-
- const prefetch = useLatest(useTableRowsPrefetchWrapper())
-
- useEffect(() => {
- let mounted = true
-
- function loadTable() {
- if (entity?.type) {
- switch (entity.type) {
- case ENTITY_TYPE.MATERIALIZED_VIEW:
- return meta.materializedViews.loadById(entity.id)
-
- case ENTITY_TYPE.VIEW:
- return meta.views.loadById(entity.id)
-
- case ENTITY_TYPE.FOREIGN_TABLE:
- return meta.foreignTables.loadById(entity.id)
-
- default:
- return meta.tables.loadById(entity.id)
- }
- }
- }
-
- loadTable()
- ?.then(async (entity: any) => {
- await prefetch.current(entity)
- return entity
- })
- .then((entity: any) => {
- if (mounted && ref) {
- snap.addLoadedId(ref, entity.id)
- }
- })
- .catch(() => {
- if (mounted && entity?.id && ref) {
- snap.addLoadedId(ref, entity.id)
- }
- })
-
- return () => {
- mounted = false
- }
- }, [entity?.id])
-
useEffect(() => {
if (isVaultEnabled) {
vault.load()
@@ -127,7 +65,7 @@ const TableEditorLayout = ({
/>
}
>
- {router.isReady && id !== undefined ? isLoaded ? children : : children}
+ {children}
)
}
diff --git a/studio/data/foreign-tables/foreign-table-query.ts b/studio/data/foreign-tables/foreign-table-query.ts
new file mode 100644
index 00000000000..b10d74e0928
--- /dev/null
+++ b/studio/data/foreign-tables/foreign-table-query.ts
@@ -0,0 +1,57 @@
+import { PostgresTable } from '@supabase/postgres-meta'
+import { useQuery, UseQueryOptions } from '@tanstack/react-query'
+import { get } from 'lib/common/fetch'
+import { API_URL } from 'lib/constants'
+import { foreignTableKeys } from './keys'
+
+export type ForeignTableVariables = {
+ id?: number
+ projectRef?: string
+ connectionString?: string
+}
+
+export type ForeignTable = PostgresTable
+
+export type ForeignTableResponse = ForeignTable | { error?: any }
+
+export async function getForeignTable(
+ { id, projectRef, connectionString }: ForeignTableVariables,
+ signal?: AbortSignal
+) {
+ if (!projectRef) {
+ throw new Error('projectRef is required')
+ }
+ if (!id) {
+ throw new Error('id is required')
+ }
+
+ let headers = new Headers()
+ if (connectionString) headers.set('x-connection-encrypted', connectionString)
+
+ const response = (await get(`${API_URL}/pg-meta/${projectRef}/foreign-tables?id=${id}`, {
+ headers: Object.fromEntries(headers),
+ signal,
+ })) as ForeignTableResponse
+
+ if ('error' in response) {
+ throw response.error
+ }
+
+ return response as PostgresTable
+}
+
+export type ForeignTableData = Awaited>
+export type ForeignTableError = unknown
+
+export const useForeignTableQuery = (
+ { projectRef, id }: ForeignTableVariables,
+ { enabled = true, ...options }: UseQueryOptions = {}
+) =>
+ useQuery(
+ foreignTableKeys.foreignTable(projectRef, id),
+ ({ signal }) => getForeignTable({ projectRef, id }, signal),
+ {
+ enabled: enabled && typeof projectRef !== 'undefined' && typeof id !== 'undefined',
+ ...options,
+ }
+ )
diff --git a/studio/data/foreign-tables/foreign-tables-query.ts b/studio/data/foreign-tables/foreign-tables-query.ts
new file mode 100644
index 00000000000..99ce73a2a0f
--- /dev/null
+++ b/studio/data/foreign-tables/foreign-tables-query.ts
@@ -0,0 +1,49 @@
+import { PostgresTable } from '@supabase/postgres-meta'
+import { useQuery, UseQueryOptions } from '@tanstack/react-query'
+import { get } from 'lib/common/fetch'
+import { API_URL } from 'lib/constants'
+import { ForeignTable } from './foreign-table-query'
+import { foreignTableKeys } from './keys'
+
+export type ForeignTablesVariables = {
+ projectRef?: string
+ connectionString?: string
+}
+
+export type ForeignTablesResponse = ForeignTable[] | { error?: any }
+
+export async function getForeignTables(
+ { projectRef, connectionString }: ForeignTablesVariables,
+ signal?: AbortSignal
+) {
+ if (!projectRef) {
+ throw new Error('projectRef is required')
+ }
+
+ let headers = new Headers()
+ if (connectionString) headers.set('x-connection-encrypted', connectionString)
+
+ const response = (await get(`${API_URL}/pg-meta/${projectRef}/foreign-tables`, {
+ headers: Object.fromEntries(headers),
+ signal,
+ })) as ForeignTablesResponse
+
+ if (!Array.isArray(response) && response.error) {
+ throw response.error
+ }
+
+ return response as PostgresTable[]
+}
+
+export type ForeignTablesData = Awaited>
+export type ForeignTablesError = unknown
+
+export const useForeignTablesQuery = (
+ { projectRef, connectionString }: ForeignTablesVariables,
+ { enabled = true, ...options }: UseQueryOptions = {}
+) =>
+ useQuery(
+ foreignTableKeys.list(projectRef),
+ ({ signal }) => getForeignTables({ projectRef, connectionString }, signal),
+ { enabled: enabled && typeof projectRef !== 'undefined', ...options }
+ )
diff --git a/studio/data/foreign-tables/keys.ts b/studio/data/foreign-tables/keys.ts
new file mode 100644
index 00000000000..869cd2ccfad
--- /dev/null
+++ b/studio/data/foreign-tables/keys.ts
@@ -0,0 +1,5 @@
+export const foreignTableKeys = {
+ list: (projectRef: string | undefined) => ['projects', projectRef, 'foreignTables'] as const,
+ foreignTable: (projectRef: string | undefined, id: number | undefined) =>
+ ['projects', projectRef, 'foreignTables', id] as const,
+}
diff --git a/studio/data/materialized-views/keys.ts b/studio/data/materialized-views/keys.ts
new file mode 100644
index 00000000000..6e34f29b960
--- /dev/null
+++ b/studio/data/materialized-views/keys.ts
@@ -0,0 +1,5 @@
+export const materializedViewKeys = {
+ list: (projectRef: string | undefined) => ['projects', projectRef, 'materializedViews'] as const,
+ materializedView: (projectRef: string | undefined, id: number | undefined) =>
+ ['projects', projectRef, 'materializedViews', id] as const,
+}
diff --git a/studio/data/materialized-views/materialized-view-query.ts b/studio/data/materialized-views/materialized-view-query.ts
new file mode 100644
index 00000000000..6efd95ded42
--- /dev/null
+++ b/studio/data/materialized-views/materialized-view-query.ts
@@ -0,0 +1,60 @@
+import { PostgresMaterializedView } from '@supabase/postgres-meta'
+import { useQuery, UseQueryOptions } from '@tanstack/react-query'
+import { get } from 'lib/common/fetch'
+import { API_URL } from 'lib/constants'
+import { materializedViewKeys } from './keys'
+
+export type MaterializedViewVariables = {
+ id?: number
+ projectRef?: string
+ connectionString?: string
+}
+
+export type MaterializedView = PostgresMaterializedView
+
+export type MaterializedViewResponse = MaterializedView | { error?: any }
+
+export async function getMaterializedView(
+ { id, projectRef, connectionString }: MaterializedViewVariables,
+ signal?: AbortSignal
+) {
+ if (!projectRef) {
+ throw new Error('projectRef is required')
+ }
+ if (!id) {
+ throw new Error('id is required')
+ }
+
+ let headers = new Headers()
+ if (connectionString) headers.set('x-connection-encrypted', connectionString)
+
+ const response = (await get(`${API_URL}/pg-meta/${projectRef}/materialized-views?id=${id}`, {
+ headers: Object.fromEntries(headers),
+ signal,
+ })) as MaterializedViewResponse
+
+ if ('error' in response) {
+ throw response.error
+ }
+
+ return response as PostgresMaterializedView
+}
+
+export type MaterializedViewData = Awaited>
+export type MaterializedViewError = unknown
+
+export const useMaterializedViewQuery = (
+ { projectRef, connectionString, id }: MaterializedViewVariables,
+ {
+ enabled = true,
+ ...options
+ }: UseQueryOptions = {}
+) =>
+ useQuery(
+ materializedViewKeys.materializedView(projectRef, id),
+ ({ signal }) => getMaterializedView({ projectRef, connectionString, id }, signal),
+ {
+ enabled: enabled && typeof projectRef !== 'undefined' && typeof id !== 'undefined',
+ ...options,
+ }
+ )
diff --git a/studio/data/materialized-views/materialized-views-query.ts b/studio/data/materialized-views/materialized-views-query.ts
new file mode 100644
index 00000000000..5f84c001834
--- /dev/null
+++ b/studio/data/materialized-views/materialized-views-query.ts
@@ -0,0 +1,52 @@
+import { PostgresMaterializedView } from '@supabase/postgres-meta'
+import { useQuery, UseQueryOptions } from '@tanstack/react-query'
+import { get } from 'lib/common/fetch'
+import { API_URL } from 'lib/constants'
+import { materializedViewKeys } from './keys'
+import { MaterializedView } from './materialized-view-query'
+
+export type MaterializedViewsVariables = {
+ projectRef?: string
+ connectionString?: string
+}
+
+export type MaterializedViewsResponse = MaterializedView[] | { error?: any }
+
+export async function getMaterializedViews(
+ { projectRef, connectionString }: MaterializedViewsVariables,
+ signal?: AbortSignal
+) {
+ if (!projectRef) {
+ throw new Error('projectRef is required')
+ }
+
+ let headers = new Headers()
+ if (connectionString) headers.set('x-connection-encrypted', connectionString)
+
+ const response = (await get(`${API_URL}/pg-meta/${projectRef}/materialized-views`, {
+ headers: Object.fromEntries(headers),
+ signal,
+ })) as MaterializedViewsResponse
+
+ if (!Array.isArray(response) && response.error) {
+ throw response.error
+ }
+
+ return response as PostgresMaterializedView[]
+}
+
+export type MaterializedViewsData = Awaited>
+export type MaterializedViewsError = unknown
+
+export const useMaterializedViewsQuery = (
+ { projectRef, connectionString }: MaterializedViewsVariables,
+ {
+ enabled = true,
+ ...options
+ }: UseQueryOptions = {}
+) =>
+ useQuery(
+ materializedViewKeys.list(projectRef),
+ ({ signal }) => getMaterializedViews({ projectRef, connectionString }, signal),
+ { enabled: enabled && typeof projectRef !== 'undefined', ...options }
+ )
diff --git a/studio/data/tables/keys.ts b/studio/data/tables/keys.ts
new file mode 100644
index 00000000000..f40847ed5a5
--- /dev/null
+++ b/studio/data/tables/keys.ts
@@ -0,0 +1,5 @@
+export const tableKeys = {
+ list: (projectRef: string | undefined) => ['projects', projectRef, 'tables'] as const,
+ table: (projectRef: string | undefined, id: number | undefined) =>
+ ['projects', projectRef, 'tables', id] as const,
+}
diff --git a/studio/data/tables/table-query.ts b/studio/data/tables/table-query.ts
new file mode 100644
index 00000000000..447a371a43d
--- /dev/null
+++ b/studio/data/tables/table-query.ts
@@ -0,0 +1,57 @@
+import { PostgresTable } from '@supabase/postgres-meta'
+import { useQuery, UseQueryOptions } from '@tanstack/react-query'
+import { get } from 'lib/common/fetch'
+import { API_URL } from 'lib/constants'
+import { tableKeys } from './keys'
+
+export type TableVariables = {
+ id?: number
+ projectRef?: string
+ connectionString?: string
+}
+
+export type Table = PostgresTable
+
+export type TableResponse = Table | { error?: any }
+
+export async function getTable(
+ { id, projectRef, connectionString }: TableVariables,
+ signal?: AbortSignal
+) {
+ if (!projectRef) {
+ throw new Error('projectRef is required')
+ }
+ if (!id) {
+ throw new Error('id is required')
+ }
+
+ let headers = new Headers()
+ if (connectionString) headers.set('x-connection-encrypted', connectionString)
+
+ const response = (await get(`${API_URL}/pg-meta/${projectRef}/tables?id=${id}`, {
+ headers: Object.fromEntries(headers),
+ signal,
+ })) as TableResponse
+
+ if ('error' in response) {
+ throw response.error
+ }
+
+ return response as PostgresTable
+}
+
+export type TableData = Awaited>
+export type TableError = unknown
+
+export const useTableQuery = (
+ { projectRef, connectionString, id }: TableVariables,
+ { enabled = true, ...options }: UseQueryOptions = {}
+) =>
+ useQuery(
+ tableKeys.table(projectRef, id),
+ ({ signal }) => getTable({ projectRef, connectionString, id }, signal),
+ {
+ enabled: enabled && typeof projectRef !== 'undefined' && typeof id !== 'undefined',
+ ...options,
+ }
+ )
diff --git a/studio/data/tables/tables-query.ts b/studio/data/tables/tables-query.ts
new file mode 100644
index 00000000000..c258a168e3b
--- /dev/null
+++ b/studio/data/tables/tables-query.ts
@@ -0,0 +1,49 @@
+import { PostgresTable } from '@supabase/postgres-meta'
+import { useQuery, UseQueryOptions } from '@tanstack/react-query'
+import { get } from 'lib/common/fetch'
+import { API_URL } from 'lib/constants'
+import { tableKeys } from './keys'
+import { Table } from './table-query'
+
+export type TablesVariables = {
+ projectRef?: string
+ connectionString?: string
+}
+
+export type TablesResponse = Table[] | { error?: any }
+
+export async function getTables(
+ { projectRef, connectionString }: TablesVariables,
+ signal?: AbortSignal
+) {
+ if (!projectRef) {
+ throw new Error('projectRef is required')
+ }
+
+ let headers = new Headers()
+ if (connectionString) headers.set('x-connection-encrypted', connectionString)
+
+ const response = (await get(`${API_URL}/pg-meta/${projectRef}/tables`, {
+ headers: Object.fromEntries(headers),
+ signal,
+ })) as TablesResponse
+
+ if (!Array.isArray(response) && response.error) {
+ throw response.error
+ }
+
+ return response as PostgresTable[]
+}
+
+export type TablesData = Awaited>
+export type TablesError = unknown
+
+export const useTablesQuery = (
+ { projectRef, connectionString }: TablesVariables,
+ { enabled = true, ...options }: UseQueryOptions = {}
+) =>
+ useQuery(
+ tableKeys.list(projectRef),
+ ({ signal }) => getTables({ projectRef, connectionString }, signal),
+ { enabled: enabled && typeof projectRef !== 'undefined', ...options }
+ )
diff --git a/studio/data/views/keys.ts b/studio/data/views/keys.ts
new file mode 100644
index 00000000000..943f32500f1
--- /dev/null
+++ b/studio/data/views/keys.ts
@@ -0,0 +1,5 @@
+export const viewKeys = {
+ list: (projectRef: string | undefined) => ['projects', projectRef, 'views'] as const,
+ view: (projectRef: string | undefined, id: number | undefined) =>
+ ['projects', projectRef, 'views', id] as const,
+}
diff --git a/studio/data/views/view-query.ts b/studio/data/views/view-query.ts
new file mode 100644
index 00000000000..7b7b12a4793
--- /dev/null
+++ b/studio/data/views/view-query.ts
@@ -0,0 +1,57 @@
+import { PostgresView } from '@supabase/postgres-meta'
+import { useQuery, UseQueryOptions } from '@tanstack/react-query'
+import { get } from 'lib/common/fetch'
+import { API_URL } from 'lib/constants'
+import { viewKeys } from './keys'
+
+export type ViewVariables = {
+ id?: number
+ projectRef?: string
+ connectionString?: string
+}
+
+export type View = PostgresView
+
+export type ViewResponse = View | { error?: any }
+
+export async function getView(
+ { id, projectRef, connectionString }: ViewVariables,
+ signal?: AbortSignal
+) {
+ if (!projectRef) {
+ throw new Error('projectRef is required')
+ }
+ if (!id) {
+ throw new Error('id is required')
+ }
+
+ let headers = new Headers()
+ if (connectionString) headers.set('x-connection-encrypted', connectionString)
+
+ const response = (await get(`${API_URL}/pg-meta/${projectRef}/views?id=${id}`, {
+ headers: Object.fromEntries(headers),
+ signal,
+ })) as ViewResponse
+
+ if ('error' in response) {
+ throw response.error
+ }
+
+ return response as PostgresView
+}
+
+export type ViewData = Awaited>
+export type ViewError = unknown
+
+export const useViewQuery = (
+ { projectRef, connectionString, id }: ViewVariables,
+ { enabled = true, ...options }: UseQueryOptions = {}
+) =>
+ useQuery(
+ viewKeys.view(projectRef, id),
+ ({ signal }) => getView({ projectRef, connectionString, id }, signal),
+ {
+ enabled: enabled && typeof projectRef !== 'undefined' && typeof id !== 'undefined',
+ ...options,
+ }
+ )
diff --git a/studio/data/views/views-query.ts b/studio/data/views/views-query.ts
new file mode 100644
index 00000000000..08300ba9dfd
--- /dev/null
+++ b/studio/data/views/views-query.ts
@@ -0,0 +1,49 @@
+import { PostgresView } from '@supabase/postgres-meta'
+import { useQuery, UseQueryOptions } from '@tanstack/react-query'
+import { get } from 'lib/common/fetch'
+import { API_URL } from 'lib/constants'
+import { viewKeys } from './keys'
+import { View } from './view-query'
+
+export type ViewsVariables = {
+ projectRef?: string
+ connectionString?: string
+}
+
+export type ViewsResponse = View[] | { error?: any }
+
+export async function getViews(
+ { projectRef, connectionString }: ViewsVariables,
+ signal?: AbortSignal
+) {
+ if (!projectRef) {
+ throw new Error('projectRef is required')
+ }
+
+ let headers = new Headers()
+ if (connectionString) headers.set('x-connection-encrypted', connectionString)
+
+ const response = (await get(`${API_URL}/pg-meta/${projectRef}/views`, {
+ headers: Object.fromEntries(headers),
+ signal,
+ })) as ViewsResponse
+
+ if (!Array.isArray(response) && response.error) {
+ throw response.error
+ }
+
+ return response as PostgresView[]
+}
+
+export type ViewsData = Awaited>
+export type ViewsError = unknown
+
+export const useViewsQuery = (
+ { projectRef, connectionString }: ViewsVariables,
+ { enabled = true, ...options }: UseQueryOptions = {}
+) =>
+ useQuery(
+ viewKeys.list(projectRef),
+ ({ signal }) => getViews({ projectRef, connectionString }, signal),
+ { enabled: enabled && typeof projectRef !== 'undefined', ...options }
+ )
diff --git a/studio/hooks/misc/useTable.ts b/studio/hooks/misc/useTable.ts
new file mode 100644
index 00000000000..505ecf23e95
--- /dev/null
+++ b/studio/hooks/misc/useTable.ts
@@ -0,0 +1,76 @@
+import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
+import { ENTITY_TYPE } from 'data/entity-types/entity-type-constants'
+import { useForeignTableQuery } from 'data/foreign-tables/foreign-table-query'
+import { useMaterializedViewQuery } from 'data/materialized-views/materialized-view-query'
+import { useTableQuery } from 'data/tables/table-query'
+import { useViewQuery } from 'data/views/view-query'
+import useEntityType from './useEntityType'
+
+/**
+ * A hook that loads all table-like objects. e.g. tables, views, materialized views, etc...
+ */
+function useTable(id?: number) {
+ const { project } = useProjectContext()
+ const entity = useEntityType(id)
+
+ const tableResult = useTableQuery(
+ {
+ projectRef: project?.ref,
+ connectionString: project?.connectionString,
+ id: entity?.id,
+ },
+ {
+ enabled: entity?.type === ENTITY_TYPE.TABLE,
+ }
+ )
+
+ const viewResult = useViewQuery(
+ {
+ projectRef: project?.ref,
+ connectionString: project?.connectionString,
+ id: entity?.id,
+ },
+ {
+ enabled: entity?.type === ENTITY_TYPE.VIEW,
+ }
+ )
+
+ const materializedViewResult = useMaterializedViewQuery(
+ {
+ projectRef: project?.ref,
+ connectionString: project?.connectionString,
+ id: entity?.id,
+ },
+ {
+ enabled: entity?.type === ENTITY_TYPE.MATERIALIZED_VIEW,
+ }
+ )
+
+ const foreignTableResult = useForeignTableQuery(
+ {
+ projectRef: project?.ref,
+ connectionString: project?.connectionString,
+ id: entity?.id,
+ },
+ {
+ enabled: entity?.type === ENTITY_TYPE.FOREIGN_TABLE,
+ }
+ )
+
+ switch (entity?.type) {
+ case ENTITY_TYPE.TABLE:
+ return tableResult
+ case ENTITY_TYPE.VIEW:
+ return viewResult
+ case ENTITY_TYPE.MATERIALIZED_VIEW:
+ return materializedViewResult
+ case ENTITY_TYPE.FOREIGN_TABLE:
+ return foreignTableResult
+ default:
+ // While entity is loading, we can fallback
+ // to the loading state of the table query.
+ return tableResult
+ }
+}
+
+export default useTable
diff --git a/studio/pages/project/[ref]/editor/[id].tsx b/studio/pages/project/[ref]/editor/[id].tsx
index 3415d635902..93d2646c4fc 100644
--- a/studio/pages/project/[ref]/editor/[id].tsx
+++ b/studio/pages/project/[ref]/editor/[id].tsx
@@ -1,9 +1,9 @@
import { useQueryClient } from '@tanstack/react-query'
-import { useEffect, useState } from 'react'
+import { useState } from 'react'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { observer } from 'mobx-react-lite'
-import { isUndefined, isNaN } from 'lodash'
+import { isUndefined } from 'lodash'
import { Alert, Button, Checkbox, IconExternalLink, Modal } from 'ui'
import type { PostgresTable, PostgresColumn } from '@supabase/postgres-meta'
@@ -25,11 +25,13 @@ import {
import { ForeignRowSelectorProps } from 'components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/ForeignRowSelector'
import { useTheme } from 'common'
import { useTableEditorStateSnapshot } from 'state/table-editor'
+import useTable from 'hooks/misc/useTable'
const TableEditorPage: NextPageWithLayout = () => {
const router = useRouter()
const { isDarkMode } = useTheme()
- const { id, ref: projectRef } = useParams()
+ const { id: _id, ref: projectRef } = useParams()
+ const id = _id ? Number(_id) : undefined
const [_, setParams] = useUrlState({ arrayKeys: ['filter', 'sort'] })
const { project } = useProjectContext()
@@ -59,28 +61,7 @@ const TableEditorPage: NextPageWithLayout = () => {
column: any
}>()
- const tables: PostgresTable[] = meta.tables.list()
- const views: SchemaView[] = meta.views.list()
- const materializedViews = meta.materializedViews.list()
- const foreignTables: Partial[] = meta.foreignTables.list()
-
- const selectedTable = !isNaN(Number(id))
- ? // @ts-ignore
- tables
- // @ts-ignore
- .concat(views)
- // @ts-ignore
- .concat(materializedViews)
- // @ts-ignore
- .concat(foreignTables)
- .find((table) => table.id === Number(id))
- : undefined
-
- // useEffect(() => {
- // if (selectedTable && 'schema' in selectedTable) {
- // setSelectedSchema(selectedTable.schema)
- // }
- // }, [selectedTable?.name])
+ const { data: selectedTable, isLoading } = useTable(id)
const onAddRow = () => {
setSidePanelKey('row')
@@ -278,6 +259,7 @@ const TableEditorPage: NextPageWithLayout = () => {
onDuplicateTable={onDuplicateTable}
>