add: specs & database status
This commit is contained in:
@@ -3,12 +3,12 @@
|
||||
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';
|
||||
import { databaseProviders } from '@/lib/deploy/database-config';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
interface IDatabase extends Pick<Database, 'id' | 'name' | 'provider' | 'createdAt'> {}
|
||||
interface IDatabase extends Pick<Database, 'id' | 'name' | 'provider' | 'createdAt'> {
|
||||
status: any;
|
||||
}
|
||||
|
||||
export const columns: ColumnDef<IDatabase>[] = [
|
||||
{
|
||||
@@ -16,8 +16,9 @@ export const columns: ColumnDef<IDatabase>[] = [
|
||||
header: 'Provider',
|
||||
cell(props) {
|
||||
return (
|
||||
<div className="flex items-center">
|
||||
<div className="flex items-center relative">
|
||||
<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} />
|
||||
<span className={cn('absolute bottom-0 left-8 w-2 h-2 rounded-full', props.row.original.status.status.phase == 'Running' ? 'bg-emerald-400' : 'bg-red-400')}></span>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import { PostgresSpecsPage } from '@/components/deploy/database/provider/postgres';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
@@ -8,6 +9,7 @@ import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
|
||||
import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger } from '@/components/ui/sheet';
|
||||
import { useWorkspace } from '@/hooks/useWorkspace';
|
||||
import { deployDatabase } from '@/lib/deploy/database';
|
||||
import { databaseProviders, defaultDatabaseConfiguration, IDatabaseConfiguration } from '@/lib/deploy/database-config';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { Plus } from 'lucide-react';
|
||||
import Image from 'next/image';
|
||||
@@ -18,25 +20,6 @@ interface DatabaseNewSteps {
|
||||
display: string;
|
||||
}
|
||||
|
||||
interface IDatabaseProvider {
|
||||
id: string;
|
||||
display: string;
|
||||
image: {
|
||||
alt: string;
|
||||
src: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface IDatabaseConfig {
|
||||
workspaceId: string;
|
||||
name: string;
|
||||
provider: IDatabaseProvider;
|
||||
user: {
|
||||
username: string;
|
||||
password: string;
|
||||
};
|
||||
}
|
||||
|
||||
const steps: DatabaseNewSteps[] = [
|
||||
{
|
||||
display: 'Database Type',
|
||||
@@ -52,55 +35,26 @@ const steps: DatabaseNewSteps[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export const databaseProviders: IDatabaseProvider[] = [
|
||||
{
|
||||
id: 'vitess',
|
||||
display: 'Vitess',
|
||||
image: {
|
||||
alt: 'Vitess',
|
||||
src: '/vitess.png',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'redis',
|
||||
display: 'Redis',
|
||||
image: {
|
||||
alt: 'Redis',
|
||||
src: '/redis.svg',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'postgres',
|
||||
display: 'Postgres',
|
||||
image: {
|
||||
alt: 'Postgres',
|
||||
src: '/postgres.png',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export default function DatabaseNewForm() {
|
||||
const [open, setOpen] = useState<boolean>(false);
|
||||
const [currentSteps, setCurrentSteps] = useState<number>(1);
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
// TODO: Generate all data randomly, but leave the user the choice to modify
|
||||
const { id } = useWorkspace();
|
||||
const defaultDatabaseConfig: IDatabaseConfig = {
|
||||
workspaceId: id,
|
||||
name: 'my-new-cool-db',
|
||||
provider: databaseProviders[0],
|
||||
user: {
|
||||
username: 'my-new-super-user',
|
||||
password: 'a-super-strong-generated-password',
|
||||
},
|
||||
};
|
||||
|
||||
const [databaseConfig, setDatabaseConfig] = useState<IDatabaseConfig>(defaultDatabaseConfig);
|
||||
const [databaseConfig, setDatabaseConfig] = useState<IDatabaseConfiguration>(defaultDatabaseConfiguration(id));
|
||||
|
||||
return (
|
||||
<Sheet open={open} onOpenChange={() => setOpen((open) => !open)}>
|
||||
<Sheet
|
||||
open={open}
|
||||
onOpenChange={() => {
|
||||
setOpen((open) => !open);
|
||||
if (!open) {
|
||||
setDatabaseConfig(defaultDatabaseConfiguration(id));
|
||||
setCurrentSteps(1);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<SheetTrigger asChild>
|
||||
<Button className="flex gap-1 justify-center items-center bg-[#3A7BFE]">
|
||||
<Plus />
|
||||
@@ -152,8 +106,9 @@ export default function DatabaseNewForm() {
|
||||
|
||||
{currentSteps == 2 && (
|
||||
<div>
|
||||
<p>WIP for now 1CPU 2048Mb RAM</p>
|
||||
<p>Storage 1 GB</p>
|
||||
{databaseConfig.provider.id == 'vitess' && <div>Vitess</div>}
|
||||
{databaseConfig.provider.id == 'redis' && <div>Redis</div>}
|
||||
{databaseConfig.provider.id == 'postgres' && <PostgresSpecsPage config={databaseConfig} setConfig={setDatabaseConfig} />}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -197,11 +152,36 @@ export default function DatabaseNewForm() {
|
||||
|
||||
{currentSteps == 4 && (
|
||||
<div>
|
||||
<h2>Review your new database information :</h2>
|
||||
<p>Type : {databaseConfig.provider.display}</p>
|
||||
<p>Name : {databaseConfig.name}</p>
|
||||
<p>Username : {databaseConfig.user.username}</p>
|
||||
<p>Password : {databaseConfig.user.password}</p>
|
||||
<div className="flex flex-col gap-2">
|
||||
<div>
|
||||
<p className="text-muted-foreground text-sm">Database Type</p>
|
||||
<p>{databaseConfig.provider.display}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-muted-foreground text-sm">CPUs</p>
|
||||
<p>{databaseConfig.specs.cpu}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-muted-foreground text-sm">RAM</p>
|
||||
<p>{databaseConfig.specs.memory}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-muted-foreground text-sm">Storage</p>
|
||||
<p>{databaseConfig.specs.storage}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-muted-foreground text-sm">Name</p>
|
||||
<p>{databaseConfig.name}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-muted-foreground text-sm">Username</p>
|
||||
<p>{databaseConfig.user.username}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-muted-foreground text-sm">Password</p>
|
||||
<p>{databaseConfig.user.password}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -224,7 +204,7 @@ export default function DatabaseNewForm() {
|
||||
console.log(res);
|
||||
setOpen(false);
|
||||
setCurrentSteps(1);
|
||||
setDatabaseConfig(defaultDatabaseConfig);
|
||||
setDatabaseConfig(defaultDatabaseConfiguration(id));
|
||||
router.refresh();
|
||||
})
|
||||
.catch((err) => {
|
||||
|
||||
@@ -11,6 +11,7 @@ import { EllipsisVertical, X } from 'lucide-react';
|
||||
import { Dialog, DialogClose, DialogContent, DialogTrigger } from '@/components/ui/dialog';
|
||||
import { useState } from 'react';
|
||||
import { Database } from '@prisma/client';
|
||||
import { deleteDatabase } from '@/lib/deploy/database';
|
||||
|
||||
interface DataTableProps<TData, TValue> {
|
||||
columns: ColumnDef<TData, TValue>[];
|
||||
@@ -19,6 +20,7 @@ interface DataTableProps<TData, TValue> {
|
||||
|
||||
export function DatabaseTable<TData, TValue>({ columns, data }: DataTableProps<TData, TValue>) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [destroyOpen, setDestroyOpen] = useState(false);
|
||||
|
||||
const table = useReactTable({
|
||||
data,
|
||||
@@ -27,7 +29,7 @@ export function DatabaseTable<TData, TValue>({ columns, data }: DataTableProps<T
|
||||
});
|
||||
|
||||
const router = useRouter();
|
||||
const { slug } = useWorkspace();
|
||||
const { slug, id } = useWorkspace();
|
||||
|
||||
return (
|
||||
<div className="rounded-lg w-full overflow-hidden">
|
||||
@@ -106,7 +108,51 @@ export function DatabaseTable<TData, TValue>({ columns, data }: DataTableProps<T
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
<DropdownMenuItem className="text-red-400">Destroy</DropdownMenuItem>
|
||||
|
||||
<Dialog open={destroyOpen} onOpenChange={setDestroyOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<DropdownMenuItem
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
setDestroyOpen(true);
|
||||
}}
|
||||
className="text-red-400"
|
||||
>
|
||||
Destroy
|
||||
</DropdownMenuItem>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<div className="flex flex-col">
|
||||
<div className="flex flex-row justify-between mb-0">
|
||||
<h1 className="text-3xl font-semibold">Are you sure?</h1>
|
||||
<DialogClose asChild>
|
||||
<Button variant="ghost">
|
||||
<X size={17} />
|
||||
</Button>
|
||||
</DialogClose>
|
||||
</div>
|
||||
<p className="text-gray-700">Deleting a database if irreversible. This action cannot be undone.</p>
|
||||
</div>
|
||||
<div>
|
||||
<Button
|
||||
variant={'destructive'}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
deleteDatabase({ id: data[index].id, workspaceId: id })
|
||||
.then(() => {
|
||||
setDestroyOpen(false);
|
||||
router.refresh();
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}}
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</TableCell>
|
||||
|
||||
@@ -3,6 +3,7 @@ import DatabaseNewForm from './database-new-form';
|
||||
import prisma from '@/lib/prisma';
|
||||
import { DatabaseTable } from './database-table';
|
||||
import { columns } from './database-column';
|
||||
import { getDatabase } from '@/lib/deploy/database';
|
||||
|
||||
export default async function Databases({ params }: { params: { workspace: string } }) {
|
||||
const workspaceSlug = params.workspace;
|
||||
@@ -15,6 +16,16 @@ export default async function Databases({ params }: { params: { workspace: strin
|
||||
},
|
||||
});
|
||||
|
||||
const status = await Promise.all(
|
||||
workspace.Database.map(async (database) => {
|
||||
const res = await getDatabase({
|
||||
id: database.id,
|
||||
workspaceId: workspace.id,
|
||||
}).catch(() => ({ status: { phase: 'unknown' } }));
|
||||
return { ...res, id: database.id };
|
||||
})
|
||||
);
|
||||
|
||||
if (workspace?.Database.length == 0) {
|
||||
return (
|
||||
<div className="mt-12">
|
||||
@@ -47,7 +58,7 @@ export default async function Databases({ params }: { params: { workspace: strin
|
||||
</div>
|
||||
</div>
|
||||
))} */}
|
||||
<DatabaseTable columns={columns} data={workspace.Database} />
|
||||
<DatabaseTable columns={columns} data={workspace.Database.map((db) => ({ ...db, status: status.find((st) => st.id == db.id) }))} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user