add: better table with connection details
This commit is contained in:
36
app/(deploy)/[workspace]/databases/database-column.tsx
Normal file
36
app/(deploy)/[workspace]/databases/database-column.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
'use client';
|
||||
|
||||
import { Database } from '@prisma/client';
|
||||
import { ColumnDef } from '@tanstack/react-table';
|
||||
import Image from 'next/image';
|
||||
import { databaseProviders } from './database-new-form';
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from '@/components/ui/dropdown-menu';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { EllipsisVertical } from 'lucide-react';
|
||||
|
||||
interface IDatabase extends Pick<Database, 'id' | 'name' | 'provider' | 'createdAt'> {}
|
||||
|
||||
export const columns: ColumnDef<IDatabase>[] = [
|
||||
{
|
||||
accessorKey: 'provider',
|
||||
header: 'Provider',
|
||||
cell(props) {
|
||||
return (
|
||||
<div className="flex items-center">
|
||||
<Image src={databaseProviders.filter((pro) => pro.id.toUpperCase() === props.getValue())[0]?.image?.src} alt={databaseProviders.filter((pro) => pro.id.toUpperCase() === props.getValue())[0]?.image?.alt} width={32} height={32} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: 'name',
|
||||
header: 'Name',
|
||||
},
|
||||
{
|
||||
accessorKey: 'createdAt',
|
||||
header: 'Created',
|
||||
cell(props) {
|
||||
return <span>{new Date(props.getValue() as string).toLocaleDateString('en-US', { hour: '2-digit', minute: '2-digit' })}</span>;
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -52,7 +52,7 @@ const steps: DatabaseNewSteps[] = [
|
||||
},
|
||||
];
|
||||
|
||||
const databaseProviders: IDatabaseProvider[] = [
|
||||
export const databaseProviders: IDatabaseProvider[] = [
|
||||
{
|
||||
id: 'vitess',
|
||||
display: 'Vitess',
|
||||
@@ -69,6 +69,14 @@ const databaseProviders: IDatabaseProvider[] = [
|
||||
src: '/redis.svg',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'postgres',
|
||||
display: 'Postgres',
|
||||
image: {
|
||||
alt: 'Postgres',
|
||||
src: '/postgres.png',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export default function DatabaseNewForm() {
|
||||
@@ -122,6 +130,7 @@ export default function DatabaseNewForm() {
|
||||
<RadioGroup
|
||||
defaultValue={'vitess'}
|
||||
className="flex flex-col gap-2 mb-4"
|
||||
value={databaseConfig.provider.id}
|
||||
onValueChange={(id) => {
|
||||
setDatabaseConfig((prev) => ({ ...prev, provider: databaseProviders.filter((provider) => provider.id == id)[0] }));
|
||||
}}
|
||||
|
||||
126
app/(deploy)/[workspace]/databases/database-table.tsx
Normal file
126
app/(deploy)/[workspace]/databases/database-table.tsx
Normal file
@@ -0,0 +1,126 @@
|
||||
'use client';
|
||||
|
||||
import { ColumnDef, flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table';
|
||||
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
|
||||
import { useWorkspace } from '@/hooks/useWorkspace';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { EllipsisVertical, X } from 'lucide-react';
|
||||
import { Dialog, DialogClose, DialogContent, DialogTrigger } from '@/components/ui/dialog';
|
||||
import { useState } from 'react';
|
||||
import { Database } from '@prisma/client';
|
||||
|
||||
interface DataTableProps<TData, TValue> {
|
||||
columns: ColumnDef<TData, TValue>[];
|
||||
data: (TData & Database)[];
|
||||
}
|
||||
|
||||
export function DatabaseTable<TData, TValue>({ columns, data }: DataTableProps<TData, TValue>) {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const table = useReactTable({
|
||||
data,
|
||||
columns,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
});
|
||||
|
||||
const router = useRouter();
|
||||
const { slug } = useWorkspace();
|
||||
|
||||
return (
|
||||
<div className="rounded-lg w-full overflow-hidden">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<TableRow key={headerGroup.id}>
|
||||
{headerGroup.headers.map((header) => {
|
||||
return (
|
||||
<TableHead className="text-black" key={header.id}>
|
||||
{header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
|
||||
</TableHead>
|
||||
);
|
||||
})}
|
||||
<TableHead key={'actions'} className="text-black">
|
||||
Actions
|
||||
</TableHead>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{table.getRowModel().rows?.length ? (
|
||||
table.getRowModel().rows.map((row, index) => (
|
||||
<TableRow key={row.id} data-state={row.getIsSelected() && 'selected'} className="bg-white text-gray-700">
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<TableCell
|
||||
key={cell.id}
|
||||
onClick={(e) => {
|
||||
router.push(`/${slug}/databases/${(row.original as any)?.id}`);
|
||||
}}
|
||||
className="cursor-pointer"
|
||||
>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</TableCell>
|
||||
))}
|
||||
<TableCell key={'actions'} className="w-5">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant={'ghost'}>
|
||||
<EllipsisVertical size={20} />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
|
||||
<DropdownMenuContent>
|
||||
{/* <DropdownMenuLabel>Edit Database</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator /> */}
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<DropdownMenuItem
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
setOpen(true);
|
||||
}}
|
||||
>
|
||||
Connection details
|
||||
</DropdownMenuItem>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<div className="flex flex-col">
|
||||
<div className="flex flex-row justify-between mb-0">
|
||||
<h1 className="text-3xl font-semibold">Connection details</h1>
|
||||
<DialogClose asChild>
|
||||
<Button variant="ghost">
|
||||
<X size={17} />
|
||||
</Button>
|
||||
</DialogClose>
|
||||
</div>
|
||||
<p className="text-gray-700">Details to connect to your new database</p>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<p>Host: {data[index].host}</p>
|
||||
<p>Port: {data[index].port}</p>
|
||||
<p>Username: {data[index].username}</p>
|
||||
<p>Password: {data[index].password}</p>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
<DropdownMenuItem className="text-red-400">Destroy</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell colSpan={columns.length} className="h-24 text-center">
|
||||
No results.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Database } from 'lucide-react';
|
||||
import DatabaseNewForm from './database-new-form';
|
||||
import prisma from '@/lib/prisma';
|
||||
import { DatabaseTable } from './database-table';
|
||||
import { columns } from './database-column';
|
||||
|
||||
export default async function Databases({ params }: { params: { workspace: string } }) {
|
||||
const workspaceSlug = params.workspace;
|
||||
@@ -23,10 +25,6 @@ export default async function Databases({ params }: { params: { workspace: strin
|
||||
<h3 className="font-semibold">No database</h3>
|
||||
<p className="text-gray-700">Get started by creating a new database.</p>
|
||||
</div>
|
||||
{/* <Button className="flex gap-1 justify-center items-center bg-[#3A7BFE]">
|
||||
<Plus />
|
||||
New Database
|
||||
</Button> */}
|
||||
<DatabaseNewForm />
|
||||
</div>
|
||||
</div>
|
||||
@@ -35,9 +33,12 @@ export default async function Databases({ params }: { params: { workspace: strin
|
||||
|
||||
return (
|
||||
<div className="mt-12">
|
||||
<h1 className="text-3xl font-semibold">Databases</h1>
|
||||
<div className="bg-white py-6 flex flex-col items-center rounded-lg mt-6 gap-4">
|
||||
{workspace.Database.map((database) => (
|
||||
<div className="flex flex-row justify-between items-center">
|
||||
<h1 className="text-3xl font-semibold">Databases</h1>
|
||||
<DatabaseNewForm />
|
||||
</div>
|
||||
<div className="bg-white flex flex-col items-center rounded-lg mt-6 gap-4 mb-6">
|
||||
{/* {workspace.Database.map((database) => (
|
||||
<div key={database.id} className="flex flex-row">
|
||||
<Database size={64} className="text-gray-300" />
|
||||
<div className="text-center">
|
||||
@@ -45,8 +46,8 @@ export default async function Databases({ params }: { params: { workspace: strin
|
||||
<p className="text-gray-700">{database.provider}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<DatabaseNewForm />
|
||||
))} */}
|
||||
<DatabaseTable columns={columns} data={workspace.Database} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user