diff --git a/studio/components/interfaces/Database/Publications/PublicationsTables.tsx b/studio/components/interfaces/Database/Publications/PublicationsTables.tsx
index 70e44d7c19e..0e6b650674b 100644
--- a/studio/components/interfaces/Database/Publications/PublicationsTables.tsx
+++ b/studio/components/interfaces/Database/Publications/PublicationsTables.tsx
@@ -5,6 +5,7 @@ import { useState } from 'react'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
import NoSearchResults from 'components/to-be-cleaned/NoSearchResults'
import Table from 'components/to-be-cleaned/Table'
+import AlertError from 'components/ui/AlertError'
import InformationBox from 'components/ui/InformationBox'
import Connecting from 'components/ui/Loading/Loading'
import { useTablesQuery } from 'data/tables/tables-query'
@@ -31,6 +32,8 @@ const PublicationsTables = ({ selectedPublication, onSelectBack }: PublicationsT
data: tables,
isLoading,
isSuccess,
+ isError,
+ error,
} = useTablesQuery(
{
projectRef: project?.ref,
@@ -110,6 +113,9 @@ const PublicationsTables = ({ selectedPublication, onSelectBack }: PublicationsT
)}
+
+ {isError && }
+
{isSuccess &&
(tables.length === 0 ? (
diff --git a/studio/components/interfaces/Database/Schemas/SchemaGraph.tsx b/studio/components/interfaces/Database/Schemas/SchemaGraph.tsx
index d76abe61581..c2701e5e5b2 100644
--- a/studio/components/interfaces/Database/Schemas/SchemaGraph.tsx
+++ b/studio/components/interfaces/Database/Schemas/SchemaGraph.tsx
@@ -1,7 +1,8 @@
import dagre from '@dagrejs/dagre'
import clsx from 'clsx'
-import { observer } from 'mobx-react-lite'
import { uniqBy } from 'lodash'
+import { Diamond, Fingerprint } from 'lucide-react'
+import { observer } from 'mobx-react-lite'
import { useEffect, useMemo } from 'react'
import ReactFlow, {
Background,
@@ -17,11 +18,10 @@ import ReactFlow, {
import { PostgresTable } from '@supabase/postgres-meta'
import { useTheme } from 'common/Providers'
-import { useStore } from 'hooks'
-import { IconHash, IconKey, IconLoader, IconLock } from 'ui'
-import { Diamond, Fingerprint } from 'lucide-react'
-
+import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
+import { useTablesQuery } from 'data/tables/tables-query'
import 'reactflow/dist/style.css'
+import { IconHash, IconKey, IconLoader, IconLock } from 'ui'
type TableNodeData = {
name: string
@@ -347,23 +347,32 @@ const TablesGraph = ({ tables }: { tables: PostgresTable[] }) => {
}
const SchemaGraph = ({ schema }: { schema: string }) => {
- const { meta } = useStore()
- const tables = meta.tables.list((table: { schema: string }) => table.schema === schema)
+ const { project } = useProjectContext()
+ const {
+ data: tables,
+ isLoading,
+ isError,
+ error,
+ } = useTablesQuery({
+ projectRef: project?.ref,
+ connectionString: project?.connectionString,
+ schema,
+ })
- if (meta.tables.isLoading) {
+ if (isLoading) {
return (
-
Loading schemas...
+
Loading table...
)
}
- if (meta.tables.hasError) {
+ if (isError) {
return (
Error connecting to API
-
{`${meta.tables.error?.message ?? 'Unknown error'}`}
+
{`${error?.message ?? 'Unknown error'}`}
)
}
diff --git a/studio/components/interfaces/Database/Tables/TableList.tsx b/studio/components/interfaces/Database/Tables/TableList.tsx
index 624ea54e786..1e190ba7eb8 100644
--- a/studio/components/interfaces/Database/Tables/TableList.tsx
+++ b/studio/components/interfaces/Database/Tables/TableList.tsx
@@ -25,6 +25,7 @@ import {
Input,
Listbox,
} from 'ui'
+import AlertError from 'components/ui/AlertError'
interface TableListProps {
onAddTable: () => void
@@ -58,6 +59,8 @@ const TableList = ({
data: tables,
isLoading,
isSuccess,
+ isError,
+ error,
} = useTablesQuery(
{
projectRef: project?.ref,
@@ -180,6 +183,8 @@ const TableList = ({
)}
+ {isError && }
+
{isSuccess &&
(tables.length === 0 ? (
@@ -323,21 +328,6 @@ const TableList = ({
)}
-
- {/* }
- style={{ padding: 5 }}
- disabled={isLocked}
- onClick={() => onEditTable(x)}
- />
- }
- style={{ padding: 5 }}
- disabled={isLocked}
- onClick={() => onDeleteTable(x)}
- /> */}
diff --git a/studio/components/interfaces/TableGridEditor/DeleteConfirmationDialogs.tsx b/studio/components/interfaces/TableGridEditor/DeleteConfirmationDialogs.tsx
index a8587768038..87e9b29dcf8 100644
--- a/studio/components/interfaces/TableGridEditor/DeleteConfirmationDialogs.tsx
+++ b/studio/components/interfaces/TableGridEditor/DeleteConfirmationDialogs.tsx
@@ -6,21 +6,24 @@ import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectConte
import ConfirmationModal from 'components/ui/ConfirmationModal'
import { entityTypeKeys } from 'data/entity-types/keys'
import { sqlKeys } from 'data/sql/keys'
+import { tableKeys } from 'data/tables/keys'
import { useGetTables } from 'data/tables/tables-query'
import { useStore, useUrlState } from 'hooks'
import { TableLike } from 'hooks/misc/useTable'
+import { noop } from 'lib/void'
import { useTableEditorStateSnapshot } from 'state/table-editor'
import { Alert, Button, Checkbox, IconExternalLink, Modal } from 'ui'
-import { tableKeys } from 'data/tables/keys'
export type DeleteConfirmationDialogsProps = {
projectRef?: string
selectedTable?: TableLike
+ onAfterDeleteTable?: (tables: TableLike[]) => void
}
const DeleteConfirmationDialogs = ({
projectRef,
selectedTable,
+ onAfterDeleteTable = noop,
}: DeleteConfirmationDialogsProps) => {
const { project } = useProjectContext()
const snap = useTableEditorStateSnapshot()
@@ -117,12 +120,8 @@ const DeleteConfirmationDialogs = ({
await queryClient.invalidateQueries(entityTypeKeys.list(projectRef))
- // For simplicity for now, we just open the first table within the same schema
- if (tables.length > 0) {
- router.push(`/project/${projectRef}/editor/${tables[0].id}`)
- } else {
- router.push(`/project/${projectRef}/editor/`)
- }
+ onAfterDeleteTable(tables)
+
ui.setNotification({
category: 'success',
message: `Successfully deleted table "${selectedTableToDelete.name}"`,
diff --git a/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.tsx b/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.tsx
index 369f93b79f4..e4a495e8fb5 100644
--- a/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.tsx
+++ b/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.tsx
@@ -331,7 +331,10 @@ const SidePanelEditor = ({
duplicateTable,
})
- await queryClient.invalidateQueries(entityTypeKeys.list(project?.ref))
+ await Promise.all([
+ queryClient.invalidateQueries(tableKeys.list(project?.ref, table.schema)),
+ queryClient.invalidateQueries(entityTypeKeys.list(project?.ref)),
+ ])
ui.setNotification({
id: toastId,
@@ -355,7 +358,10 @@ const SidePanelEditor = ({
importContent
)
- await queryClient.invalidateQueries(entityTypeKeys.list(project?.ref))
+ await Promise.all([
+ queryClient.invalidateQueries(tableKeys.list(project?.ref, table.schema)),
+ queryClient.invalidateQueries(entityTypeKeys.list(project?.ref)),
+ ])
ui.setNotification({
id: toastId,
@@ -398,6 +404,7 @@ const SidePanelEditor = ({
])
),
queryClient.invalidateQueries(entityTypeKeys.list(project?.ref)),
+ queryClient.invalidateQueries(tableKeys.table(project?.ref, table.schema)),
])
ui.setNotification({
diff --git a/studio/components/layouts/TableEditorLayout/TableEditorLayout.tsx b/studio/components/layouts/TableEditorLayout/TableEditorLayout.tsx
index ca5590b091b..bccfbc672bb 100644
--- a/studio/components/layouts/TableEditorLayout/TableEditorLayout.tsx
+++ b/studio/components/layouts/TableEditorLayout/TableEditorLayout.tsx
@@ -7,9 +7,7 @@ import { useCheckPermissions, useStore } from 'hooks'
import { ProjectLayoutWithAuth } from '../'
import TableEditorMenu from './TableEditorMenu'
-export interface TableEditorLayoutProps {}
-
-const TableEditorLayout = ({ children }: PropsWithChildren) => {
+const TableEditorLayout = ({ children }: PropsWithChildren<{}>) => {
const { vault, meta, ui } = useStore()
const canReadTables = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_READ, 'tables')
diff --git a/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx b/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx
index 8707dbedef2..ffe27f2fa52 100644
--- a/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx
+++ b/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx
@@ -28,9 +28,7 @@ import {
import { useProjectContext } from '../ProjectLayout/ProjectContext'
import EntityListItem from './EntityListItem'
-export interface TableEditorMenuProps {}
-
-const TableEditorMenu = ({}: TableEditorMenuProps) => {
+const TableEditorMenu = () => {
const { id } = useParams()
const snap = useTableEditorStateSnapshot()
diff --git a/studio/data/tables/tables-query.ts b/studio/data/tables/tables-query.ts
index ea18061372b..eefe5c92879 100644
--- a/studio/data/tables/tables-query.ts
+++ b/studio/data/tables/tables-query.ts
@@ -3,6 +3,7 @@ import { useQuery, useQueryClient, UseQueryOptions } from '@tanstack/react-query
import { get } from 'lib/common/fetch'
import { API_URL } from 'lib/constants'
import { useCallback } from 'react'
+import { ResponseError } from 'types'
import { tableKeys } from './keys'
import { Table } from './table-query'
@@ -45,7 +46,7 @@ export async function getTables(
}
export type TablesData = Awaited>
-export type TablesError = unknown
+export type TablesError = ResponseError
export const useTablesQuery = (
{ projectRef, connectionString, schema }: TablesVariables,
diff --git a/studio/pages/project/[ref]/auth/policies.tsx b/studio/pages/project/[ref]/auth/policies.tsx
index 01fa9ffe6bd..16f5344a760 100644
--- a/studio/pages/project/[ref]/auth/policies.tsx
+++ b/studio/pages/project/[ref]/auth/policies.tsx
@@ -8,8 +8,9 @@ import { useParams } from 'common/hooks'
import { Policies } from 'components/interfaces/Auth/Policies'
import { AuthLayout } from 'components/layouts'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
-import Connecting from 'components/ui/Loading/Loading'
+import AlertError from 'components/ui/AlertError'
import NoPermission from 'components/ui/NoPermission'
+import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader'
import { useSchemasQuery } from 'data/database/schemas-query'
import { useTablesQuery } from 'data/tables/tables-query'
import { useCheckPermissions, useStore } from 'hooks'
@@ -80,6 +81,8 @@ const AuthPoliciesPage: NextPageWithLayout = () => {
data: tables,
isLoading,
isSuccess,
+ isError,
+ error,
} = useTablesQuery({
projectRef: project?.ref,
connectionString: project?.connectionString,
@@ -168,7 +171,8 @@ const AuthPoliciesPage: NextPageWithLayout = () => {
- {isLoading && }
+ {isLoading && }
+ {isError && }
{isSuccess && (
0} isLocked={isLocked} />
)}
diff --git a/studio/pages/project/[ref]/database/functions.tsx b/studio/pages/project/[ref]/database/functions.tsx
index f0dc7fa55f2..dfd219a8326 100644
--- a/studio/pages/project/[ref]/database/functions.tsx
+++ b/studio/pages/project/[ref]/database/functions.tsx
@@ -5,15 +5,13 @@ import { useEffect, useState } from 'react'
import { CreateFunction, DeleteFunction } from 'components/interfaces/Database'
import FunctionsList from 'components/interfaces/Database/Functions/FunctionsList/FunctionsList'
import { DatabaseLayout } from 'components/layouts'
-import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
+import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold'
import NoPermission from 'components/ui/NoPermission'
import { useCheckPermissions, useStore } from 'hooks'
import { NextPageWithLayout } from 'types'
-import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold'
const FunctionsPage: NextPageWithLayout = () => {
- const { meta } = useStore()
- const { project } = useProjectContext()
+ const { ui, meta } = useStore()
const [selectedFunction, setSelectedFunction] = useState()
const [showCreateFunctionForm, setShowCreateFunctionForm] = useState(false)
const [showDeleteFunctionForm, setShowDeleteFunctionForm] = useState(false)
@@ -21,10 +19,10 @@ const FunctionsPage: NextPageWithLayout = () => {
const canReadFunctions = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_READ, 'functions')
useEffect(() => {
- if (project?.ref) {
+ if (ui.selectedProjectRef) {
fetchFunctions()
}
- }, [project?.ref])
+ }, [ui.selectedProjectRef])
const fetchFunctions = async () => {
meta.functions.load()
diff --git a/studio/pages/project/[ref]/database/schemas.tsx b/studio/pages/project/[ref]/database/schemas.tsx
index e6109bb76bf..d9e67017988 100644
--- a/studio/pages/project/[ref]/database/schemas.tsx
+++ b/studio/pages/project/[ref]/database/schemas.tsx
@@ -4,6 +4,7 @@ import { useState } from 'react'
import SchemaGraph from 'components/interfaces/Database/Schemas/SchemaGraph'
import { DatabaseLayout } from 'components/layouts'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
+import AlertError from 'components/ui/AlertError'
import { useSchemasQuery } from 'data/database/schemas-query'
import { EXCLUDED_SCHEMAS } from 'lib/constants/schemas'
import { NextPageWithLayout } from 'types'
@@ -11,7 +12,13 @@ import { IconLock, Listbox } from 'ui'
const SchemasPage: NextPageWithLayout = () => {
const { project } = useProjectContext()
- const { data: schemas } = useSchemasQuery({
+ const {
+ data: schemas,
+ isSuccess,
+ isLoading,
+ isError,
+ error,
+ } = useSchemasQuery({
projectRef: project?.ref,
connectionString: project?.connectionString,
})
@@ -26,45 +33,53 @@ const SchemasPage: NextPageWithLayout = () => {
<>
-
}
- >
-
- Schemas
-
- {openSchemas.map((schema) => (
-
schema}
- >
- {schema.name}
-
- ))}
-
+ )}
+
+ {isError &&
}
+
+ {isSuccess && (
+
}
>
-
Protected schemas
-
- {protectedSchemas.map((schema) => (
-
schema}
- >
- {schema.name}
+
+ Schemas
- ))}
-
+ {openSchemas.map((schema) => (
+ schema}
+ >
+ {schema.name}
+
+ ))}
+
+ Protected schemas
+
+ {protectedSchemas.map((schema) => (
+ schema}
+ >
+ {schema.name}
+
+ ))}
+
+ )}
diff --git a/studio/pages/project/[ref]/editor/[id].tsx b/studio/pages/project/[ref]/editor/[id].tsx
index 31b390bbf67..0b31931bf2b 100644
--- a/studio/pages/project/[ref]/editor/[id].tsx
+++ b/studio/pages/project/[ref]/editor/[id].tsx
@@ -5,9 +5,11 @@ import DeleteConfirmationDialogs from 'components/interfaces/TableGridEditor/Del
import { TableEditorLayout } from 'components/layouts'
import { ProjectContextFromParamsProvider } from 'components/layouts/ProjectLayout/ProjectContext'
import useTable from 'hooks/misc/useTable'
+import { useRouter } from 'next/router'
import { NextPageWithLayout } from 'types'
const TableEditorPage: NextPageWithLayout = () => {
+ const router = useRouter()
const { isDarkMode } = useTheme()
const { id: _id, ref: projectRef } = useParams()
const id = _id ? Number(_id) : undefined
@@ -21,7 +23,18 @@ const TableEditorPage: NextPageWithLayout = () => {
selectedTable={selectedTable}
theme={isDarkMode ? 'dark' : 'light'}
/>
-
+
{
+ // For simplicity for now, we just open the first table within the same schema
+ if (tables.length > 0) {
+ router.push(`/project/${projectRef}/editor/${tables[0].id}`)
+ } else {
+ router.push(`/project/${projectRef}/editor/`)
+ }
+ }}
+ />
>
)
}