From 7ff64879c152aa9cdf4672f93f028d8c7d705b16 Mon Sep 17 00:00:00 2001 From: andres Date: Sun, 14 Jul 2024 16:02:28 +0200 Subject: [PATCH] store column sizes and column visibility in localstorage --- frontend/bun.lockb | Bin 143586 -> 144366 bytes frontend/package.json | 1 + frontend/src/hooks/use-filters.ts | 2 +- frontend/src/lib/tableSortMapper.ts | 32 ++++ .../db/$dbName/tables/$tableName/data.tsx | 159 +++++++++++++++--- 5 files changed, 168 insertions(+), 26 deletions(-) create mode 100644 frontend/src/lib/tableSortMapper.ts diff --git a/frontend/bun.lockb b/frontend/bun.lockb index a7b9bef0ff10f4e677db5382255eddee7e39b87c..7b36f4315095437329cbde99c6e6cd2b6e5c65a9 100755 GIT binary patch delta 26467 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 diff --git a/frontend/package.json b/frontend/package.json index 6a371b4..0451b01 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -38,6 +38,7 @@ "sonner": "^1.5.0", "tailwind-merge": "^2.4.0", "tailwindcss-animate": "^1.0.7", + "usehooks-ts": "^3.1.0", "zod": "^3.23.8", "zustand": "^4.5.4" }, diff --git a/frontend/src/hooks/use-filters.ts b/frontend/src/hooks/use-filters.ts index 06acbcc..178e987 100644 --- a/frontend/src/hooks/use-filters.ts +++ b/frontend/src/hooks/use-filters.ts @@ -13,7 +13,7 @@ export function useFilters>( const navigate = useNavigate(); const filters = routeApi.useSearch(); - const setFilters = (partialFilters: Partial) => + const setFilters = (partialFilters: Partial = {}) => navigate({ search: (prev) => cleanEmptyParams({ ...prev, ...partialFilters }), }); diff --git a/frontend/src/lib/tableSortMapper.ts b/frontend/src/lib/tableSortMapper.ts new file mode 100644 index 0000000..6bde362 --- /dev/null +++ b/frontend/src/lib/tableSortMapper.ts @@ -0,0 +1,32 @@ +import type { SortingState } from "@tanstack/react-table"; + +type SortBy = { + sortField?: string; + sortDesc?: boolean; +}; + +export const stateToSortBy = ( + sorting: SortingState | undefined, +): SortBy | undefined => { + if (!sorting || sorting.length === 0) + return { + sortField: undefined, + sortDesc: undefined, + }; + + const sort = sorting[0]; + + return { + sortField: sort.id, + sortDesc: sort.desc, + }; +}; + +export const sortByToState = ( + sortBy: Partial | undefined, +): SortingState => { + if (!sortBy) return []; + if (!sortBy.sortField) return []; + + return [{ id: sortBy.sortField, desc: sortBy.sortDesc ?? false }]; +}; diff --git a/frontend/src/routes/db/$dbName/tables/$tableName/data.tsx b/frontend/src/routes/db/$dbName/tables/$tableName/data.tsx index a46f1e7..9f67931 100644 --- a/frontend/src/routes/db/$dbName/tables/$tableName/data.tsx +++ b/frontend/src/routes/db/$dbName/tables/$tableName/data.tsx @@ -1,45 +1,154 @@ -import { DataTable } from "@/components/db-table-view/data-table"; -import { createFileRoute, useNavigate } from "@tanstack/react-router"; +import { useColumns } from "@/components/db-table-view/columns"; +import { ColumnsDropdown } from "@/components/db-table-view/columns-dropdown"; +import { + TableScrollContainer, + TableView, +} from "@/components/db-table-view/table"; +import { + WhereClauseForm, + type WhereClauseFormValues, +} from "@/components/db-table-view/where-clause-form"; +import { DataTablePagination } from "@/components/ui"; +import { useFilters } from "@/hooks/use-filters"; +import { DEFAULT_PAGE_INDEX, DEFAULT_PAGE_SIZE } from "@/lib/constants"; +import { sortByToState, stateToSortBy } from "@/lib/tableSortMapper"; +import { useTableDataQuery } from "@/services/db"; +import { createFileRoute } from "@tanstack/react-router"; +import { + type ColumnSizingState, + type OnChangeFn, + type PaginationState, + type SortingState, + type VisibilityState, + getCoreRowModel, + useReactTable, +} from "@tanstack/react-table"; +import { Rows3 } from "lucide-react"; +import { useCallback, useMemo, useState } from "react"; +import { useLocalStorage } from "usehooks-ts"; import { z } from "zod"; const tableSearchSchema = z.object({ pageSize: z.number().catch(10), pageIndex: z.number().catch(0), + sortField: z.string().optional(), + sortDesc: z.boolean().optional(), }); export const Route = createFileRoute("/db/$dbName/tables/$tableName/data")({ - component: TableView, + component: Component, validateSearch: (search) => tableSearchSchema.parse(search), }); -function TableView() { +function Component() { const { tableName, dbName } = Route.useParams(); - const { pageSize, pageIndex } = Route.useSearch(); - const navigate = useNavigate({ from: Route.fullPath }); + const { filters, setFilters } = useFilters(Route.fullPath); + const [whereQuery, setWhereQuery] = useState(""); + const [columnSizing, setColumnSizing] = useLocalStorage( + `columnSizing-${dbName}-${tableName}`, + {}, + ); + const [columnVisibility, setColumnVisibility] = + useLocalStorage( + `columnVisibility-${dbName}-${tableName}`, + {}, + ); - const updatePageSize = (value: number) => { - console.log(value); - return void navigate({ - search: (prev) => ({ ...prev, pageSize: value, pageIndex: 0 }), - }); - }; - const updatePageIndex = (pageIndex: number) => { - console.log(pageIndex); + const paginationState = useMemo( + () => ({ + pageIndex: filters.pageIndex ?? DEFAULT_PAGE_INDEX, + pageSize: filters.pageSize ?? DEFAULT_PAGE_SIZE, + }), + [filters], + ); - return void navigate({ search: (prev) => ({ ...prev, pageIndex }) }); - }; + const sortingState = useMemo(() => sortByToState(filters), [filters]); + const columns = useColumns({ dbName, tableName }); + + const { data, refetch } = useTableDataQuery({ + whereQuery, + tableName, + dbName, + perPage: filters.pageSize, + page: filters.pageIndex, + sortField: filters.sortField, + sortDesc: filters.sortDesc, + }); + + const handleWhereClauseFormSubmit = useCallback( + ({ whereClause }: WhereClauseFormValues) => { + if (whereClause === whereQuery) { + void refetch(); + return; + } + setWhereQuery(whereClause); + }, + [whereQuery, refetch], + ); + + const handleSortingChange: OnChangeFn = useCallback( + (updaterOrValue) => { + const newSortingState = + typeof updaterOrValue === "function" + ? updaterOrValue(sortingState) + : updaterOrValue; + return setFilters(stateToSortBy(newSortingState)); + }, + [sortingState, setFilters], + ); + + const handlePaginationChange: OnChangeFn = useCallback( + (pagination) => { + setFilters( + typeof pagination === "function" + ? pagination(paginationState) + : pagination, + ); + }, + [paginationState, setFilters], + ); + + const table = useReactTable({ + columnResizeMode: "onChange", + columns, + data: data?.data ?? [], + getCoreRowModel: getCoreRowModel(), + manualPagination: true, + manualSorting: true, + onColumnSizingChange: setColumnSizing, + onColumnVisibilityChange: setColumnVisibility, + onPaginationChange: handlePaginationChange, + onSortingChange: handleSortingChange, + rowCount: data?.count ?? 0, + state: { + sorting: sortingState, + columnSizing: columnSizing, + columnVisibility, + pagination: paginationState, + }, + }); return (
- +
+
+

+ {tableName} + +

+ +

+ Rows: {data?.count} +

+
+ +
+ + + +
+ +
); }