Fix database tables page delete table confirmation modal

This commit is contained in:
Joshen Lim committed 2022-03-01 13:58:55 +08:00
1 parent 8e3377492d
commit 0bb2bec2ea
2 files changed
+154 -129

No files matched your search

@@ -13,7 +13,6 @@ import {
import { useStore } from 'hooks'
import Table from 'components/to-be-cleaned/Table'
import { confirmAlert } from 'components/to-be-cleaned/ModalsDeprecated/ConfirmModal'
const Header: FC<{
filterString: string
@@ -48,134 +47,109 @@ const Header: FC<{
const TableList: FC<{
onAddTable: () => void
onEditTable: (table: any) => void
onDeleteTable: (table: any) => void
onOpenTable: (table: any) => void
}> = observer(({ onAddTable = () => {}, onEditTable = () => {}, onOpenTable = () => {} }) => {
const { ui, meta } = useStore()
const [filterString, setFilterString] = useState<string>('')
const tables =
filterString.length === 0
? meta.tables.list((table: any) => table.schema === 'public')
: meta.tables.list(
(table: any) => table.schema === 'public' && table.name.includes(filterString)
)
}> = observer(
({
onAddTable = () => {},
onEditTable = () => {},
onDeleteTable = () => {},
onOpenTable = () => {},
}) => {
const { meta } = useStore()
const [filterString, setFilterString] = useState<string>('')
const tables =
filterString.length === 0
? meta.tables.list((table: any) => table.schema === 'public')
: meta.tables.list(
(table: any) => table.schema === 'public' && table.name.includes(filterString)
)
async function onDelete(table: any) {
confirmAlert({
title: 'Confirm to delete',
message: `Are you sure you want to delete "${table.name}" table? This action cannot be undone.`,
onAsyncConfirm: async () => {
try {
const response: any = await meta.tables.del(table.id)
if (response.error) {
throw response.error
} else {
ui.setNotification({
category: 'success',
message: `Successfully removed ${table.name}.`,
})
}
} catch (error: any) {
ui.setNotification({
category: 'error',
message: `Failed to delete ${table.name}: ${error.message}`,
})
}
},
})
return (
<>
<div>
{/* @ts-ignore */}
<Header
filterString={filterString}
setFilterString={setFilterString}
rightComponents={
<Button icon={<IconPlus />} onClick={() => onAddTable()}>
New
</Button>
}
/>
</div>
<div className="w-full my-4">
<Table
head={[
<Table.th key="name">Name</Table.th>,
<Table.th key="schema">Schema</Table.th>,
<Table.th key="description" className="hidden lg:table-cell">
Description
</Table.th>,
<Table.th key="rows" className="hidden xl:table-cell">
Rows (Estimated)
</Table.th>,
<Table.th key="size" className="hidden xl:table-cell">
Size (Estimated)
</Table.th>,
<Table.th key="buttons"></Table.th>,
]}
body={tables.map((x: any, i: any) => (
<Table.tr key={x.id}>
<Table.td>
<Typography.Text>{x.name}</Typography.Text>
</Table.td>
<Table.td>
<Typography.Text>{x.schema}</Typography.Text>
</Table.td>
<Table.td className=" truncate max-w-sm hidden lg:table-cell">
<Typography.Text>{x.comment}</Typography.Text>
</Table.td>
<Table.td className=" hidden xl:table-cell">
<Typography.Text small code>
{x.live_rows_estimate ?? x.live_row_count}
</Typography.Text>
</Table.td>
<Table.td className=" hidden xl:table-cell">
<Typography.Text small code>
{x.size}
</Typography.Text>
</Table.td>
<Table.td>
<div className="flex gap-2 justify-end">
<Button
iconRight={<IconColumns />}
type="default"
className="hover:border-gray-500 whitespace-nowrap"
style={{ paddingTop: 3, paddingBottom: 3 }}
onClick={() => {
onOpenTable(x)
}}
>
{x.columns.length} columns
</Button>
<Button
onClick={() => onEditTable(x)}
icon={<IconEdit3 />}
style={{ padding: 5 }}
type="text"
/>
<Button
onClick={() => onDeleteTable(x)}
icon={<IconTrash />}
style={{ padding: 5 }}
type="text"
/>
</div>
</Table.td>
</Table.tr>
))}
/>
</div>
</>
)
}
return (
<>
<div>
{/* @ts-ignore */}
<Header
filterString={filterString}
setFilterString={setFilterString}
rightComponents={
<Button icon={<IconPlus />} onClick={() => onAddTable()}>
New
</Button>
}
/>
</div>
<div className="w-full my-4">
<Table
head={[
<Table.th key="name">Name</Table.th>,
<Table.th key="schema">Schema</Table.th>,
<Table.th key="description" className="hidden lg:table-cell">
Description
</Table.th>,
<Table.th key="rows" className="hidden xl:table-cell">
Rows (Estimated)
</Table.th>,
<Table.th key="size" className="hidden xl:table-cell">
Size (Estimated)
</Table.th>,
<Table.th key="buttons"></Table.th>,
]}
body={tables.map((x: any, i: any) => (
<Table.tr key={x.id}>
<Table.td>
<Typography.Text>{x.name}</Typography.Text>
</Table.td>
<Table.td>
<Typography.Text>{x.schema}</Typography.Text>
</Table.td>
<Table.td className=" truncate max-w-sm hidden lg:table-cell">
<Typography.Text>{x.comment}</Typography.Text>
</Table.td>
<Table.td className=" hidden xl:table-cell">
<Typography.Text small code>
{x.live_rows_estimate ?? x.live_row_count}
</Typography.Text>
</Table.td>
<Table.td className=" hidden xl:table-cell">
<Typography.Text small code>
{x.size}
</Typography.Text>
</Table.td>
<Table.td>
<div className="flex gap-2 justify-end">
<Button
iconRight={<IconColumns />}
type="default"
className="hover:border-gray-500 whitespace-nowrap"
style={{ paddingTop: 3, paddingBottom: 3 }}
onClick={() => {
onOpenTable(x)
}}
>
{x.columns.length} columns
</Button>
<Button
onClick={() => onEditTable(x)}
icon={<IconEdit3 />}
style={{ padding: 5 }}
type="text"
// tooltip={{
// title: 'Edit Details',
// position: 'top-left',
// }}
/>
<Button
onClick={() => onDelete(x)}
icon={<IconTrash />}
style={{ padding: 5 }}
type="text"
// tooltip={{
// title: 'Delete table',
// position: 'top-left',
// }}
/>
</div>
</Table.td>
</Table.tr>
))}
/>
</div>
</>
)
})
)
export default TableList
+53 -2
View File
@@ -3,22 +3,27 @@ import { useState } from 'react'
import { observer } from 'mobx-react-lite'
import { isUndefined } from 'lodash'
import { PostgresColumn, PostgresTable } from '@supabase/postgres-meta'
import { Modal } from '@supabase/ui'
import { withAuth, useStore } from 'hooks'
import { DatabaseLayout } from 'components/layouts'
import ConfirmationModal from 'components/ui/ConfirmationModal'
import { TableList, ColumnList } from 'components/interfaces/Database'
import { SidePanelEditor } from 'components/interfaces/TableGridEditor'
const DatabaseTables: NextPage = () => {
const { meta } = useStore()
const tables = meta.tables.list()
const { meta, ui } = useStore()
const [isDeleting, setIsDeleting] = useState<boolean>(false)
const [selectedTable, setSelectedTable] = useState<any>()
const [sidePanelKey, setSidePanelKey] = useState<'column' | 'table'>()
const [selectedColumnToEdit, setSelectedColumnToEdit] = useState<PostgresColumn>()
const [selectedTableToEdit, setSelectedTableToEdit] = useState<PostgresTable>()
const [selectedColumnToDelete, setSelectedColumnToDelete] = useState<PostgresColumn>()
const [selectedTableToDelete, setSelectedTableToDelete] = useState<PostgresTable>()
const onAddTable = () => {
setSidePanelKey('table')
setSelectedTableToEdit(undefined)
@@ -29,6 +34,11 @@ const DatabaseTables: NextPage = () => {
setSelectedTableToEdit(table)
}
const onDeleteTable = (table: PostgresTable) => {
setIsDeleting(true)
setSelectedTableToDelete(table)
}
const onAddColumn = () => {
setSidePanelKey('column')
setSelectedColumnToEdit(undefined)
@@ -46,6 +56,30 @@ const DatabaseTables: NextPage = () => {
const onClosePanel = () => setSidePanelKey(undefined)
const onConfirmDeleteTable = async () => {
try {
if (isUndefined(selectedTableToDelete)) return
const response: any = await meta.tables.del(selectedTableToDelete.id)
if (response.error) {
throw response.error
} else {
ui.setNotification({
category: 'success',
message: `Successfully removed ${selectedTableToDelete.name}.`,
})
}
} catch (error: any) {
ui.setNotification({
category: 'error',
message: `Failed to delete ${selectedTableToDelete?.name}: ${error.message}`,
})
} finally {
setIsDeleting(false)
setSelectedTableToDelete(undefined)
}
}
return (
<DatabaseLayout title="Database">
<div className="p-4">
@@ -53,6 +87,7 @@ const DatabaseTables: NextPage = () => {
<TableList
onAddTable={onAddTable}
onEditTable={onEditTable}
onDeleteTable={onDeleteTable}
onOpenTable={setSelectedTable}
/>
) : (
@@ -65,6 +100,22 @@ const DatabaseTables: NextPage = () => {
/>
)}
</div>
<ConfirmationModal
danger
visible={isDeleting && !isUndefined(selectedTableToDelete)}
header={`Confirm deletion of table "${selectedTableToDelete?.name}"`}
children={
<Modal.Content>
<p className="py-4 text-sm text-scale-1100">
Are you sure you want to delete the selected table? This action cannot be undone.
</p>
</Modal.Content>
}
buttonLabel="Delete"
buttonLoadingLabel="Deleting"
onSelectCancel={() => setIsDeleting(false)}
onSelectConfirm={onConfirmDeleteTable}
/>
<SidePanelEditor
sidePanelKey={sidePanelKey}
selectedSchema="public"