remove prime ng and fix table layout. Fix select

This commit is contained in:
2024-07-13 12:59:07 +02:00
parent 6bf181525c
commit 7c562e8057
8 changed files with 234 additions and 213 deletions

Binary file not shown.

View File

@@ -5,7 +5,6 @@ import {
DropdownMenuCheckboxItem, DropdownMenuCheckboxItem,
DropdownMenuContent, DropdownMenuContent,
DropdownMenuTrigger, DropdownMenuTrigger,
ScrollArea,
Table, Table,
TableBody, TableBody,
TableCell, TableCell,
@@ -167,7 +166,7 @@ export const DataTable = ({
}); });
return ( return (
<div className={"flex flex-col gap-4 flex-1 max-h-full h-full pb-3"}> <div className={"flex flex-col gap-4 flex-1 max-h-full pb-3"}>
<div className={"flex gap-4 items-center justify-between"}> <div className={"flex gap-4 items-center justify-between"}>
<h1 className="text-2xl font-bold flex items-center gap-2"> <h1 className="text-2xl font-bold flex items-center gap-2">
<Rows3 /> {tableName} <Rows3 /> {tableName}
@@ -201,103 +200,105 @@ export const DataTable = ({
</p> </p>
</div> </div>
<ScrollArea className="rounded-md border min-h-0 h-full w-full min-w-0"> <div className="rounded-md border min-h-0 h-full w-full min-w-0 flex flex-col">
<Table <div className={"flex flex-col flex-1 overflow-auto relative"}>
className={"table-fixed min-w-full"} <Table
{...{ className={"table-fixed min-w-full"}
style: { {...{
width: table.getCenterTotalSize(), style: {
}, width: table.getCenterTotalSize(),
}} },
> }}
<TableHeader> >
{table.getHeaderGroups().map((headerGroup) => ( <TableHeader>
<TableRow key={headerGroup.id}> {table.getHeaderGroups().map((headerGroup) => (
{headerGroup.headers.map((header) => { <TableRow key={headerGroup.id} className={"sticky top-0"}>
const sorted = header.column.getIsSorted(); {headerGroup.headers.map((header) => {
const sorted = header.column.getIsSorted();
return ( return (
<TableHead <TableHead
className={"p-0 relative"} className={"p-0 relative"}
key={header.id} key={header.id}
style={{ style={{
width: header.getSize(), width: header.getSize(),
}}
>
<Button
variant="ghost"
onClick={header.column.getToggleSortingHandler()}
title={
header.column.getNextSortingOrder() === "asc"
? "Sort ascending"
: header.column.getNextSortingOrder() === "desc"
? "Sort descending"
: "Clear sort"
}
>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext(),
)}
<ArrowUp
className={cn(
"ml-2 size-4 opacity-0 transition-transform",
sorted && "opacity-100",
(sorted as string) === "desc" && "rotate-180",
)}
/>
</Button>
<div
{...{
onDoubleClick: () => header.column.resetSize(),
onMouseDown: header.getResizeHandler(),
onTouchStart: header.getResizeHandler(),
className: `resizer ${header.column.getIsResizing() ? "isResizing" : ""}`,
}} }}
/> >
</TableHead> <Button
); variant="ghost"
})} onClick={header.column.getToggleSortingHandler()}
</TableRow> title={
))} header.column.getNextSortingOrder() === "asc"
</TableHeader> ? "Sort ascending"
<TableBody> : header.column.getNextSortingOrder() === "desc"
{table.getRowModel().rows?.length ? ( ? "Sort descending"
table.getRowModel().rows.map((row) => ( : "Clear sort"
<TableRow }
key={row.id} >
data-state={row.getIsSelected() && "selected"} {header.isPlaceholder
> ? null
{row.getVisibleCells().map((cell) => ( : flexRender(
<TableCell header.column.columnDef.header,
key={cell.id} header.getContext(),
style={{ )}
width: cell.column.getSize(), <ArrowUp
}} className={cn(
> "ml-2 size-4 opacity-0 transition-transform",
{flexRender( sorted && "opacity-100",
cell.column.columnDef.cell, (sorted as string) === "desc" && "rotate-180",
cell.getContext(), )}
)} />
</TableCell> </Button>
))} <div
{...{
onDoubleClick: () => header.column.resetSize(),
onMouseDown: header.getResizeHandler(),
onTouchStart: header.getResizeHandler(),
className: `resizer ${header.column.getIsResizing() ? "isResizing" : ""}`,
}}
/>
</TableHead>
);
})}
</TableRow> </TableRow>
)) ))}
) : ( </TableHeader>
<TableRow> <TableBody>
<TableCell {table.getRowModel().rows?.length ? (
colSpan={columns.length} table.getRowModel().rows.map((row) => (
className="h-24 text-center" <TableRow
> key={row.id}
No results. data-state={row.getIsSelected() && "selected"}
</TableCell> >
</TableRow> {row.getVisibleCells().map((cell) => (
)} <TableCell
</TableBody> key={cell.id}
</Table> style={{
</ScrollArea> width: cell.column.getSize(),
}}
>
{flexRender(
cell.column.columnDef.cell,
cell.getContext(),
)}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell
colSpan={columns.length}
className="h-24 text-center"
>
No results.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
</div>
<DataTablePagination table={table} /> <DataTablePagination table={table} />
</div> </div>
); );

View File

@@ -49,8 +49,10 @@ function RawSessionSelector() {
value={currentSessionId ? currentSessionId.toString() : ""} value={currentSessionId ? currentSessionId.toString() : ""}
onValueChange={handleSessionSelected} onValueChange={handleSessionSelected}
> >
<SelectTrigger className="max-w-full"> <SelectTrigger className="w-full">
<SelectValue placeholder="Select a Database" /> <span className={"truncate max-w-[calc(100%-1.5rem)]"}>
<SelectValue placeholder="Select a Database" />
</span>
</SelectTrigger> </SelectTrigger>
<SelectContent>{mappedSessions}</SelectContent> <SelectContent>{mappedSessions}</SelectContent>
</Select> </Select>

View File

@@ -0,0 +1,119 @@
import { SessionSelector } from "@/components/sidebar/session-selector";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
buttonVariants,
} from "@/components/ui";
import { cn } from "@/lib/utils";
import { Route } from "@/routes/__root";
import { useDatabasesListQuery, useTablesListQuery } from "@/services/db";
import { useUiStore } from "@/state";
import { Link, useNavigate, useParams } from "@tanstack/react-router";
import { Database, Rows3 } from "lucide-react";
import type { PropsWithChildren } from "react";
function SidebarContent() {
const { data } = useDatabasesListQuery();
const showSidebar = useUiStore.use.showSidebar();
const params = useParams({ strict: false });
const dbName = params.dbName ?? "";
const { data: tables } = useTablesListQuery({ dbName });
const navigate = useNavigate({ from: Route.fullPath });
const handleSelectedDb = (dbName: string) => {
void navigate({ to: "/db/$dbName/tables", params: { dbName } });
};
if (!showSidebar) return null;
return (
<>
<SessionSelector />
<Select value={dbName} onValueChange={handleSelectedDb}>
<SelectTrigger className="w-full mt-4">
<SelectValue placeholder="Select a Database" />
</SelectTrigger>
<SelectContent>
{data?.map((db) => {
return (
<SelectItem value={db} key={db}>
{db}
</SelectItem>
);
})}
</SelectContent>
</Select>
<nav className="flex flex-col gap-1 mt-4">
{dbName && (
<Link
to={"/db/$dbName/tables"}
params={{ dbName }}
activeOptions={{ exact: true }}
title={dbName}
className={cn(
"flex items-center gap-2 rounded py-1.5 pl-1.5",
"hover:bg-muted",
"[&.active]:bg-muted [&.active]:font-semibold",
)}
>
<Database className={"size-4"} />
<span className={"max-w-full inline-block truncate"}>{dbName}</span>
</Link>
)}
{tables?.map((table) => {
return (
<div
key={table.table_name}
className={cn(
"flex items-center gap-2 px-2.5 rounded py-1.5 justify-between w-full",
)}
>
<Link
className={cn(
"max-w-full inline-block truncate",
"hover:underline",
"[&.active]:font-medium",
)}
title={table.table_name}
to={"/db/$dbName/tables/$tableName"}
params={{ tableName: table.table_name, dbName: dbName }}
>
{table.table_name}
</Link>
<Link
className={cn(
"shrink-0",
"hover:underline",
buttonVariants({ variant: "ghost", size: "iconSm" }),
"[&.active]:bg-muted",
)}
title={"Explore Data"}
aria-label={"Explore Data"}
to={"/db/$dbName/tables/$tableName/data"}
params={{ tableName: table.table_name, dbName: dbName }}
search={{ pageIndex: 0, pageSize: 10 }}
>
<Rows3 className={"size-4 shrink-0"} />
</Link>
</div>
);
})}
</nav>
</>
);
}
function SidebarContainer({ children }: PropsWithChildren) {
return <aside className={"p-3"}>{children}</aside>;
}
export function Sidebar() {
return (
<SidebarContainer>
<SidebarContent />
</SidebarContainer>
);
}

View File

@@ -21,7 +21,7 @@ const SelectTrigger = forwardRef<
<SelectPrimitive.Trigger <SelectPrimitive.Trigger
ref={ref} ref={ref}
className={cn( className={cn(
"flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1", "flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
className, className,
)} )}
{...props} {...props}

View File

@@ -8,7 +8,7 @@ import {
const Table = forwardRef<HTMLTableElement, HTMLAttributes<HTMLTableElement>>( const Table = forwardRef<HTMLTableElement, HTMLAttributes<HTMLTableElement>>(
({ className, ...props }, ref) => ( ({ className, ...props }, ref) => (
<div className="relative w-full overflow-auto"> <div className="relative w-full overflow-auto rounded-md">
<table <table
ref={ref} ref={ref}
className={cn("w-full caption-bottom text-sm", className)} className={cn("w-full caption-bottom text-sm", className)}
@@ -23,7 +23,11 @@ const TableHeader = forwardRef<
HTMLTableSectionElement, HTMLTableSectionElement,
HTMLAttributes<HTMLTableSectionElement> HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} /> <thead
ref={ref}
className={cn("[&_tr]:border-b [&_tr]:bg-background", className)}
{...props}
/>
)); ));
TableHeader.displayName = "TableHeader"; TableHeader.displayName = "TableHeader";

View File

@@ -74,11 +74,11 @@
text-underline-position: under; text-underline-position: under;
--sidebar-width: 264px; --sidebar-width: 264px;
} }
.sidebar-closed { .sidebar-closed {
--sidebar-width: 0; --sidebar-width: 0;
} }
.grid-rows-layout { .grid-rows-layout {
grid-template-rows: 60px 1fr; grid-template-rows: 60px 1fr;
} }

View File

@@ -1,27 +1,11 @@
import { SessionSelector } from "@/components/session-selector";
import { SettingsDialog } from "@/components/settings-dialog"; import { SettingsDialog } from "@/components/settings-dialog";
import { import { Sidebar } from "@/components/sidebar/sidebar";
Button, import { Button, ModeToggle } from "@/components/ui";
ModeToggle,
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
buttonVariants,
} from "@/components/ui";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { useDatabasesListQuery, useTablesListQuery } from "@/services/db";
import { useUiStore } from "@/state"; import { useUiStore } from "@/state";
import { import { Link, Outlet, createRootRoute } from "@tanstack/react-router";
Link,
Outlet,
createRootRoute,
useNavigate,
useParams,
} from "@tanstack/react-router";
import { TanStackRouterDevtools } from "@tanstack/router-devtools"; import { TanStackRouterDevtools } from "@tanstack/router-devtools";
import { Database, PanelLeft, PanelLeftClose, Rows3 } from "lucide-react"; import { PanelLeft, PanelLeftClose } from "lucide-react";
export const Route = createRootRoute({ export const Route = createRootRoute({
component: Root, component: Root,
@@ -31,16 +15,6 @@ function Root() {
const showSidebar = useUiStore.use.showSidebar(); const showSidebar = useUiStore.use.showSidebar();
const toggleSidebar = useUiStore.use.toggleSidebar(); const toggleSidebar = useUiStore.use.toggleSidebar();
const { data } = useDatabasesListQuery();
const params = useParams({ strict: false });
const dbName = params.dbName ?? "";
const navigate = useNavigate({ from: Route.fullPath });
const handleSelectedDb = (dbName: string) => {
void navigate({ to: "/db/$dbName/tables", params: { dbName } });
};
const { data: tables } = useTablesListQuery({ dbName });
return ( return (
<> <>
<div <div
@@ -70,86 +44,7 @@ function Root() {
<SettingsDialog /> <SettingsDialog />
</div> </div>
</header> </header>
<Sidebar />
<aside className={"p-3"}>
{showSidebar && (
<>
<SessionSelector />
<Select value={dbName} onValueChange={handleSelectedDb}>
<SelectTrigger className="w-full mt-4">
<SelectValue placeholder="Select a Database" />
</SelectTrigger>
<SelectContent>
{data?.map((db) => {
return (
<SelectItem value={db} key={db}>
{db}
</SelectItem>
);
})}
</SelectContent>
</Select>
<nav className="flex flex-col gap-1 mt-4">
{dbName && (
<Link
to={"/db/$dbName/tables"}
params={{ dbName }}
activeOptions={{ exact: true }}
title={dbName}
className={cn(
"flex items-center gap-2 rounded py-1.5 pl-1.5",
"hover:bg-muted",
"[&.active]:bg-muted [&.active]:font-semibold",
)}
>
<Database className={"size-4"} />
<span className={"max-w-full inline-block truncate"}>
{dbName}
</span>
</Link>
)}
{tables?.map((table) => {
return (
<div
key={table.table_name}
className={cn(
"flex items-center gap-2 px-2.5 rounded py-1.5 justify-between w-full",
)}
>
<Link
className={cn(
"max-w-full inline-block truncate",
"hover:underline",
"[&.active]:font-medium",
)}
title={table.table_name}
to={"/db/$dbName/tables/$tableName"}
params={{ tableName: table.table_name, dbName: dbName }}
>
{table.table_name}
</Link>
<Link
className={cn(
"shrink-0",
"hover:underline",
buttonVariants({ variant: "ghost", size: "iconSm" }),
"[&.active]:bg-muted",
)}
title={"Explore Data"}
aria-label={"Explore Data"}
to={"/db/$dbName/tables/$tableName/data"}
params={{ tableName: table.table_name, dbName: dbName }}
search={{ pageIndex: 0, pageSize: 10 }}
>
<Rows3 className={"size-4 shrink-0"} />
</Link>
</div>
);
})}
</nav>
</>
)}
</aside>
<Outlet /> <Outlet />
</div> </div>
<TanStackRouterDevtools /> <TanStackRouterDevtools />