From 4bc9374a78304af9c9fa188a0347bb1bd46a215c Mon Sep 17 00:00:00 2001 From: balibabu Date: Tue, 8 Oct 2024 17:38:34 +0800 Subject: [PATCH] feat: Move the system page to the home page #1841 (#1985) ### What problem does this PR solve? feat: Move the system page to the home page #1841 ### Type of change - [x] New Feature (non-breaking change which adds functionality) --- gui/app/(dashboard)/databases/page.tsx | 61 +++++++ gui/app/(dashboard)/layout.tsx | 9 +- gui/app/(dashboard)/page.tsx | 165 +++++++++++++----- gui/app/(dashboard)/tables/context-menu.tsx | 33 ++++ gui/app/(dashboard)/tables/page.tsx | 135 ++++++++++++++ .../tables/table-creating-dialog.tsx | 40 +++++ .../tables/table-creating-form.tsx | 110 ++++++++++++ gui/public/table.svg | 6 + 8 files changed, 508 insertions(+), 51 deletions(-) create mode 100644 gui/app/(dashboard)/databases/page.tsx create mode 100644 gui/app/(dashboard)/tables/context-menu.tsx create mode 100644 gui/app/(dashboard)/tables/page.tsx create mode 100644 gui/app/(dashboard)/tables/table-creating-dialog.tsx create mode 100644 gui/app/(dashboard)/tables/table-creating-form.tsx create mode 100644 gui/public/table.svg diff --git a/gui/app/(dashboard)/databases/page.tsx b/gui/app/(dashboard)/databases/page.tsx new file mode 100644 index 0000000000..6d7c355fc6 --- /dev/null +++ b/gui/app/(dashboard)/databases/page.tsx @@ -0,0 +1,61 @@ +import { Card, CardHeader, CardTitle } from '@/components/ui/card'; +import AddIcon from '/public/add.svg'; + +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue +} from '@radix-ui/react-select'; +import { listDatabase } from '../actions'; +import { DatabaseCard } from '../database-card'; +import { DatabaseCreatingDialog } from '../database-creating-dialog'; + +interface IDatabaseSelectProps { + placeholder?: string; + options: Array<{ label: string; value: string }>; +} + +export function DatabaseSelect({ placeholder, options }: IDatabaseSelectProps) { + return ( + + ); +} + +export default async function HomePage({ + searchParams +}: { + searchParams: { q: string; offset: string }; +}) { + const ret = await listDatabase(); + const search = searchParams.q ?? ''; + const offset = searchParams.offset ?? 0; + + return ( +
+ {ret.databases.map((x: string, idx: number) => ( + + ))} + + + + + Create Database + + + +
+ ); +} diff --git a/gui/app/(dashboard)/layout.tsx b/gui/app/(dashboard)/layout.tsx index 1b7ff9b4e3..caecb64136 100644 --- a/gui/app/(dashboard)/layout.tsx +++ b/gui/app/(dashboard)/layout.tsx @@ -32,6 +32,7 @@ import { SearchInput } from './search'; import { User } from './user'; import DatabaseIcon from '/public/database.svg'; import Logo from '/public/logo.svg'; +import TableIcon from '/public/table.svg'; export default function DashboardLayout({ children @@ -75,12 +76,12 @@ function DesktopNav() { - - + + - - + + diff --git a/gui/app/(dashboard)/page.tsx b/gui/app/(dashboard)/page.tsx index b96d335fae..05c93eddc3 100644 --- a/gui/app/(dashboard)/page.tsx +++ b/gui/app/(dashboard)/page.tsx @@ -1,60 +1,131 @@ -import { Card, CardHeader, CardTitle } from '@/components/ui/card'; -import AddIcon from '/public/add.svg'; - import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue -} from '@radix-ui/react-select'; -import { listDatabase } from './actions'; -import { DatabaseCard } from './database-card'; -import { DatabaseCreatingDialog } from './database-creating-dialog'; - -interface IDatabaseSelectProps { - placeholder?: string; - options: Array<{ label: string; value: string }>; -} - -export function DatabaseSelect({ placeholder, options }: IDatabaseSelectProps) { - return ( - - ); -} + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle +} from '@/components/ui/card'; +import { showConfigs, showVariables } from './actions'; +// import { getProducts } from '@/lib/db'; -export default async function HomePage({ +export default async function ProductsPage({ searchParams }: { searchParams: { q: string; offset: string }; }) { - const ret = await listDatabase(); const search = searchParams.q ?? ''; const offset = searchParams.offset ?? 0; + const configs = await showConfigs(); + const variables = await showVariables(); + // const { products, newOffset, totalProducts } = await getProducts( + // search, + // Number(offset) + // ); + console.log(variables); + // const products = await request('http://localhost:3000/products'); + + const { newOffset, totalProducts, products } = { + newOffset: 0, + totalProducts: 0, + products: [] + }; return ( -
- {ret.databases.map((x: string, idx: number) => ( - - ))} - - - - - Create Database - - +
+ + + Briefs + Node briefs. + + + + + Configures + System configures. + + +

buffer_manager_size: {configs['buffer_manager_size']}

+

cleanup_interval: {configs['cleanup_interval']}

+

client_port: {configs['client_port']}

+

compact_interval: {configs['compact_interval']}

+

connection_pool_size: {configs['connection_pool_size']}

+

cpu_limit: {configs['cpu_limit']}

+

data_dir: {configs['data_dir']}

+

+ {' '} + delta_checkpoint_interval: { + configs['delta_checkpoint_interval'] + }{' '} +

+

+ {' '} + delta_checkpoint_threshold: { + configs['delta_checkpoint_threshold'] + }{' '} +

+

+ {' '} + full_checkpoint_interval: {configs['full_checkpoint_interval']}{' '} +

+

http_port: {configs['http_port']}

+

log_dir: {configs['log_dir']}

+

log_file_max_size: {configs['log_file_max_size']}

+

log_file_rotate_count: {configs['log_file_rotate_count']}

+

log_filename: {configs['log_filename']}

+

log_level: {configs['log_level']}

+

log_to_stdout: {configs['log_to_stdout']}

+

mem_index_capacity: {configs['mem_index_capacity']}

+

optimize_interval: {configs['optimize_interval']}

+

peer_ip: {configs['peer_ip']}

+

peer_port: {configs['peer_port']}

+

+ {' '} + peer_server_connection_pool_size:{' '} + {configs['peer_server_connection_pool_size']}{' '} +

+

postgres_port: {configs['postgres_port']}

+

record_running_query: {configs['record_running_query']}

+

resource_dir: {configs['resource_dir']}

+

server_address: {configs['server_address']}

+

temp_dir: {configs['temp_dir']}

+

time_zone: {configs['time_zone']}

+

version: {configs['version']}

+

wal_compact_threshold: {configs['wal_compact_threshold']}

+

wal_dir: {configs['wal_dir']}

+

wal_flush: {configs['wal_flush']}

+
+
+ + + Variables + System global variables. + + +

active_txn_count: {variables['active_txn_count:']}

+

active_wal_filename: {variables['active_wal_filename']}

+

bg_task_count: {variables['bg_task_count']}

+

buffer_object_count: {variables['buffer_object_count']}

+

buffer_usage: {variables['buffer_usage']}

+

cpu_usage: {variables['cpu_usage']}

+

current_timestamp: {variables['current_timestamp']}

+

delta_log_count: {variables['delta_log_count']}

+

jeprof: {variables['jeprof']}

+

next_transaction_id: {variables['next_transaction_id']}

+

open_file_count: {variables['open_file_count']}

+

+ {' '} + profile_record_capacity: {variables['profile_record_capacity']}{' '} +

+

query_count: {variables['query_count']}

+

running_bg_task: {variables['running_bg_task']}

+

running_compact_task: {variables['running_compact_task']}

+

schedule_policy: {variables['schedule_policy']}

+

session_count: {variables['session_count']}

+

system_memory_usage: {variables['system_memory_usage']}

+

total_commit_count: {variables['total_commit_count']}

+

total_rollback_count: {variables['total_rollback_count']}

+

unused_buffer_object: {variables['unused_buffer_object']}

+
); diff --git a/gui/app/(dashboard)/tables/context-menu.tsx b/gui/app/(dashboard)/tables/context-menu.tsx new file mode 100644 index 0000000000..95c5b40c02 --- /dev/null +++ b/gui/app/(dashboard)/tables/context-menu.tsx @@ -0,0 +1,33 @@ +'use client'; + +import { + ContextMenuContent, + ContextMenuItem +} from '@/components/ui/context-menu'; +import { useSeDialogState } from '@/lib/hooks'; +import { TableCreatingDialog } from './table-creating-dialog'; +import AddIcon from '/public/add.svg'; + +export function InfinityContextMenuContent({ + databaseName +}: { + databaseName: string; +}) { + const { showDialog, visible, hideDialog, switchVisible } = useSeDialogState(); + return ( + <> + + +
+ Add +
+
+
+ + + ); +} diff --git a/gui/app/(dashboard)/tables/page.tsx b/gui/app/(dashboard)/tables/page.tsx new file mode 100644 index 0000000000..d0048320c1 --- /dev/null +++ b/gui/app/(dashboard)/tables/page.tsx @@ -0,0 +1,135 @@ +import SideMenu, { MenuItem } from '@/components/ui/side-menu'; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow +} from '@/components/ui/table'; +import { listDatabase, listTable } from '../actions'; +import { InfinityContextMenuContent } from './context-menu'; + +const invoices = [ + { + invoice: 'INV001', + paymentStatus: 'Paid', + totalAmount: '$250.00', + paymentMethod: 'Credit Card' + }, + { + invoice: 'INV002', + paymentStatus: 'Pending', + totalAmount: '$150.00', + paymentMethod: 'PayPal' + }, + { + invoice: 'INV003', + paymentStatus: 'Unpaid', + totalAmount: '$350.00', + paymentMethod: 'Bank Transfer' + }, + { + invoice: 'INV004', + paymentStatus: 'Paid', + totalAmount: '$450.00', + paymentMethod: 'Credit Card' + }, + { + invoice: 'INV005', + paymentStatus: 'Paid', + totalAmount: '$550.00', + paymentMethod: 'PayPal' + }, + { + invoice: 'INV006', + paymentStatus: 'Pending', + totalAmount: '$200.00', + paymentMethod: 'Bank Transfer' + }, + { + invoice: 'INV007', + paymentStatus: 'Unpaid', + totalAmount: '$300.00', + paymentMethod: 'Credit Card' + } +]; + +function InfinityTable() { + return ( + + + + Name + Type + Default + + + + {invoices.map((invoice) => ( + + {invoice.invoice} + {invoice.paymentStatus} + {invoice.paymentMethod} + + ))} + +
+ ); +} + +export default async function DatabasePage({ + searchParams +}: { + searchParams: { q: string; offset: string }; +}) { + const search = searchParams.q ?? ''; + const offset = searchParams.offset ?? 0; + + const items: MenuItem[] = [ + { + key: 'sub1', + label: 'Navigation', + children: [ + { + key: 'g1', + label: 'Item 1' + }, + { + key: 'g2', + label: 'Item 2' + } + ] + } + ]; + + const ret = await listDatabase(); + if (ret.databases.length > 1) { + const latestDatabase = ret.databases.at(-1); + const tables = await listTable(latestDatabase); + console.log('🚀 ~ ret:', tables); + items.push({ + key: latestDatabase, + label: latestDatabase, + children: tables.tables + }); + } + + return ( +
+
+ ( + + )} + > +
+
+ +
+
+ ); +} diff --git a/gui/app/(dashboard)/tables/table-creating-dialog.tsx b/gui/app/(dashboard)/tables/table-creating-dialog.tsx new file mode 100644 index 0000000000..f99be95179 --- /dev/null +++ b/gui/app/(dashboard)/tables/table-creating-dialog.tsx @@ -0,0 +1,40 @@ +'use client'; + +import { Button } from '@/components/ui/button'; +import { + Dialog, + DialogContent, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger +} from '@/components/ui/dialog'; +import { IDialogProps } from '@/lib/interfaces'; +import React from 'react'; +import { TableCreatingForm } from './table-creating-form'; + +export function TableCreatingDialog({ + children, + visible, + switchVisible, + hideDialog +}: React.PropsWithChildren>) { + return ( + + {children} + + + Create Table + +
+ +
+ + + +
+
+ ); +} diff --git a/gui/app/(dashboard)/tables/table-creating-form.tsx b/gui/app/(dashboard)/tables/table-creating-form.tsx new file mode 100644 index 0000000000..d66302bfb8 --- /dev/null +++ b/gui/app/(dashboard)/tables/table-creating-form.tsx @@ -0,0 +1,110 @@ +'use client'; + +import { zodResolver } from '@hookform/resolvers/zod'; +import { useRouter } from 'next/navigation'; +import { useForm } from 'react-hook-form'; +import { z } from 'zod'; + +import { toast } from '@/components/hooks/use-toast'; +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage +} from '@/components/ui/form'; +import { Input } from '@/components/ui/input'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue +} from '@/components/ui/select'; +import { CreateOption } from '@/lib/constant/common'; +import { createDatabase } from '../actions'; + +export const FormSchema = z.object({ + name: z + .string({ + required_error: 'Please input name' + }) + .trim(), + fields: z.array(), + create_option: z.nativeEnum(CreateOption) +}); + +interface IProps { + hide(): void; +} + +export function TableCreatingForm({ hide }: IProps) { + const router = useRouter(); + const form = useForm>({ + resolver: zodResolver(FormSchema), + defaultValues: { + create_option: CreateOption.Error + } + }); + + async function onSubmit(data: z.infer) { + const ret = await createDatabase(data); + console.log('🚀 ~ onSubmit ~ ret:', ret); + if (ret.error_code === 0) { + router.refresh(); + hide(); + toast({ + title: 'Create Success', + description: '' + }); + } + } + + return ( +
+ + ( + + Name + + + + + + )} + /> + ( + + Create option + + + + )} + /> + + + ); +} diff --git a/gui/public/table.svg b/gui/public/table.svg new file mode 100644 index 0000000000..f598ced6c1 --- /dev/null +++ b/gui/public/table.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file