From e776027f1fce9968ca6417d3457099060d173bde Mon Sep 17 00:00:00 2001 From: Kareem Ebrahim Date: Mon, 16 Sep 2024 11:02:11 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20use=20auto=20save=20Ids=20for=20persist?= =?UTF-8?q?ing=20panels=20position=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/core/src/routes/dashboard/_layout.tsx | 40 ++++++++++--------- .../$tableName/-components/data-table.tsx | 2 +- .../$tableName/-components/table-actions.tsx | 9 +++-- .../dashboard/_layout/$tableName/route.tsx | 2 +- 4 files changed, 29 insertions(+), 24 deletions(-) diff --git a/apps/core/src/routes/dashboard/_layout.tsx b/apps/core/src/routes/dashboard/_layout.tsx index 27fef83..5f86d00 100644 --- a/apps/core/src/routes/dashboard/_layout.tsx +++ b/apps/core/src/routes/dashboard/_layout.tsx @@ -16,8 +16,9 @@ import { unwrapResult } from "@/lib/utils" import { cn } from "@tablex/lib/utils" import { createFileRoute, Link, Outlet, redirect } from "@tanstack/react-router" import { ArrowLeft, PanelLeftClose, Table } from "lucide-react" -import { useEffect, useRef, useState, type KeyboardEvent } from "react" +import { useEffect, useRef, useState } from "react" import type { ImperativePanelHandle } from "react-resizable-panels" +import { useDebounceCallback } from "usehooks-ts" import { z } from "zod" const dashboardConnectionSchema = z.object({ @@ -51,8 +52,8 @@ function DashboardLayout() { const data = Route.useLoaderData() const searchParams = Route.useSearch() const keybindingsManager = useKeybindings() - const [, setSideBarCollapsed] = useState(false) // NOTE: I don't know why this is needed, but collapsing doesn't work without it. - const [tables, setTables] = useState(data!.tables) + const [tables, setTables] = useState(data.tables) + const [, setSideBarCollapsed] = useState(false) const sidebarPanelRef = useRef(null) useEffect(() => { @@ -64,30 +65,31 @@ function DashboardLayout() { ]) }, [keybindingsManager]) - let timeout: NodeJS.Timeout - const handleKeyUp = (e: KeyboardEvent) => { - const searchPattern = e.currentTarget.value + const handleTableSearch = (searchPattern: string) => { if (searchPattern === "") return setTables(data!.tables) - clearTimeout(timeout) - - timeout = setTimeout(() => { - const filteredTables = tables.filter((table) => - table.includes(searchPattern) - ) - setTables(filteredTables) - }, 100) + const filteredTables = tables.filter((table) => + table.includes(searchPattern) + ) + setTables(filteredTables) } + const debounced = useDebounceCallback(handleTableSearch) + return ( - + setSideBarCollapsed(true)} onExpand={() => setSideBarCollapsed(false)} + onCollapse={() => setSideBarCollapsed(true)} collapsible - minSize={0} + minSize={12} + collapsedSize={0} className={cn( "flex flex-col items-start justify-between bg-zinc-800 p-4 pt-2 transition-all lg:p-6", sidebarPanelRef.current?.isCollapsed() && "w-0 p-0 lg:w-0 lg:p-0" @@ -126,7 +128,7 @@ function DashboardLayout() {
debounced(e.currentTarget.value)} placeholder="Search..." className="h-6 border-none text-sm transition-all placeholder:text-xs focus-visible:ring-0 focus-visible:ring-offset-0 lg:h-8 lg:w-[170px] lg:placeholder:text-base lg:focus:w-full" /> @@ -147,7 +149,7 @@ function DashboardLayout() { preload={false} key={index} className={cn( - "hover:bg-muted-foreground/30 flex w-full items-center gap-x-1 rounded-md p-1 text-sm text-white lg:text-base", + "hover:bg-muted-foreground/30 flex w-full items-center gap-x-1 overflow-x-hidden rounded-md p-1 text-sm text-white lg:text-base", searchParams.tableName === table && "bg-muted-foreground/30" )} diff --git a/apps/core/src/routes/dashboard/_layout/$tableName/-components/data-table.tsx b/apps/core/src/routes/dashboard/_layout/$tableName/-components/data-table.tsx index 5f9135e..6beb0d6 100644 --- a/apps/core/src/routes/dashboard/_layout/$tableName/-components/data-table.tsx +++ b/apps/core/src/routes/dashboard/_layout/$tableName/-components/data-table.tsx @@ -83,7 +83,7 @@ const DataTable = ({ columns }: DataTableProps) => { const virtualizer = useVirtualizer({ count: table.getRowCount(), getScrollElement: () => parentRef.current, - estimateSize: () => 50, // I reached to this number by trial and error + estimateSize: () => 34, // I reached to this number by trial and error overscan: 10, debug: import.meta.env.DEV }) diff --git a/apps/core/src/routes/dashboard/_layout/$tableName/-components/table-actions.tsx b/apps/core/src/routes/dashboard/_layout/$tableName/-components/table-actions.tsx index 8463a45..f25ec2f 100644 --- a/apps/core/src/routes/dashboard/_layout/$tableName/-components/table-actions.tsx +++ b/apps/core/src/routes/dashboard/_layout/$tableName/-components/table-actions.tsx @@ -21,6 +21,7 @@ import { } from "@/components/ui/dropdown-menu" import { Input } from "@/components/ui/input" import { useTableState } from "@/state/tableState" +import { useDebounceCallback } from "usehooks-ts" type TableActionsProps = { table: Table @@ -29,6 +30,10 @@ type TableActionsProps = { const TableActions = ({ table }: TableActionsProps) => { const { toggleDialog: toggleSqlEditor } = useSqlEditorState() const { tableName, setGlobalFilter } = useTableState() + const debounced = useDebounceCallback( + (filter: string) => setGlobalFilter(filter), + 200 + ) return ( <>
@@ -39,9 +44,7 @@ const TableActions = ({ table }: TableActionsProps) => { - setGlobalFilter(String(value.currentTarget.value)) - } + onChange={(value) => debounced(String(value.currentTarget.value))} />
diff --git a/apps/core/src/routes/dashboard/_layout/$tableName/route.tsx b/apps/core/src/routes/dashboard/_layout/$tableName/route.tsx index 22e88db..50107a8 100644 --- a/apps/core/src/routes/dashboard/_layout/$tableName/route.tsx +++ b/apps/core/src/routes/dashboard/_layout/$tableName/route.tsx @@ -43,7 +43,7 @@ function TableData() { if (isError) return toast.error(error.message, { id: "get_table_columns" }) return ( -
+
)