add: better table with connection details

This commit is contained in:
2024-05-07 22:42:09 +02:00
parent b475be1cbd
commit a5b2975f38
12 changed files with 638 additions and 120 deletions

View 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>;
},
},
];

View File

@@ -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] }));
}}

View 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>
);
}

View File

@@ -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>
);