Skip to content

Commit

Permalink
feat: store current table data in local storage ✨
Browse files Browse the repository at this point in the history
  • Loading branch information
kareemmahlees committed Sep 16, 2024
1 parent e776027 commit bbd6a47
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 42 deletions.
17 changes: 13 additions & 4 deletions apps/core/src/hooks/table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { getZodSchemaFromCols } from "@/commands/columns"
import { generateColumnsDefs } from "@/routes/dashboard/_layout/$tableName/-components/columns"
import { useSettings } from "@/settings/manager"
import { useTableState } from "@/state/tableState"
import { TableLocalStorage } from "@/types"
import { rankItem, type RankingInfo } from "@tanstack/match-sorter-utils"
import { useQuery } from "@tanstack/react-query"
import {
Expand All @@ -16,6 +17,7 @@ import {
type SortingState
} from "@tanstack/react-table"
import { useMemo, useRef, useState } from "react"
import { useLocalStorage } from "usehooks-ts"
import { useGetPaginatedRows } from "./row"

export const useGetTableColumns = (tableName: string) => {
Expand Down Expand Up @@ -60,6 +62,7 @@ const fuzzyFilter: FilterFn<any> = (row, columnId, value, addMeta) => {
type SetupReactTableOptions<TData, TValue> = {
columns: ColumnDef<TData, TValue>[]
tableName: string
connectionId: string
}

/**
Expand All @@ -68,10 +71,11 @@ type SetupReactTableOptions<TData, TValue> = {
*/
export const useSetupReactTable = <TData, TValue>({
tableName,
columns
columns,
connectionId
}: SetupReactTableOptions<TData, TValue>) => {
const { defaultData, pagination, setPagination, pageIndex, pageSize } =
useSetupPagination()
useSetupPagination(connectionId)
const { globalFilter, setGlobalFilter } = useTableState()

const { data: rows, isLoading: isRowsLoading } = useGetPaginatedRows(
Expand Down Expand Up @@ -121,10 +125,15 @@ export const useSetupReactTable = <TData, TValue>({
* Sets up the state and memoization for page index & page size
* to be used in paginating the rows.
*/
const useSetupPagination = () => {
const useSetupPagination = (connectionId: string) => {
const settings = useSettings()
const [{ pageIndex: persistedPageIndex }] =
useLocalStorage<TableLocalStorage>(`@tablex/${connectionId}`, {
tableName: "",
pageIndex: 0
})
const [{ pageIndex, pageSize }, setPagination] = useState<PaginationState>({
pageIndex: 0,
pageIndex: persistedPageIndex,
pageSize: settings.pageSize
})
const defaultData = useMemo(() => [], [])
Expand Down
22 changes: 12 additions & 10 deletions apps/core/src/routes/connections/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ import {
} from "@/components/ui/dropdown-menu"
import { Separator } from "@/components/ui/separator"
import { unwrapResult } from "@/lib/utils"
import { ActiveTableLocalStorage } from "@/types"
import { TableLocalStorage } from "@/types"
import { createFileRoute, redirect, useRouter } from "@tanstack/react-router"
import { MoreHorizontal, Trash } from "lucide-react"
import { Suspense } from "react"
import { useLocalStorage } from "usehooks-ts"

export const Route = createFileRoute("/connections")({
beforeLoad: async () => {
Expand All @@ -40,10 +39,6 @@ export const Route = createFileRoute("/connections")({
function ConnectionsPage() {
const router = useRouter()
const connections = Route.useLoaderData()
const [activeTable] = useLocalStorage<ActiveTableLocalStorage | null>(
"@tablex/active-table",
null
)

const onClickConnect = async (connectionId: string) => {
const connectionDetailsResult =
Expand All @@ -60,19 +55,26 @@ function ConnectionsPage() {

if (connectionEstablishment === false) return

if (activeTable?.connectionName == connectionDetails.connName) {
const connectionStorageData = localStorage.getItem(
`@tablex/${connectionId}`
)

if (connectionStorageData) {
const parsedConnectionData: TableLocalStorage = JSON.parse(
connectionStorageData
)
return router.navigate({
to: "/dashboard/$tableName",
params: {
tableName: activeTable.tableName
tableName: parsedConnectionData.tableName
},
search: { connectionName: connectionDetails.connName }
search: { connectionId }
})
}

router.navigate({
to: "/dashboard/land",
search: { connectionName: connectionDetails.connName }
search: { connectionId }
})
}

Expand Down
17 changes: 11 additions & 6 deletions apps/core/src/routes/dashboard/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,23 @@ import { useDebounceCallback } from "usehooks-ts"
import { z } from "zod"

const dashboardConnectionSchema = z.object({
connectionName: z.string(),
connectionId: z.string().uuid(),
tableName: z.string().optional()
})

export const Route = createFileRoute("/dashboard/_layout")({
validateSearch: dashboardConnectionSchema,
loaderDeps: ({ search: { tableName, connectionName } }) => ({
connectionName,
loaderDeps: ({ search: { tableName, connectionId } }) => ({
connectionId,
tableName
}),
loader: async ({ deps: { connectionName } }) => {
const connName = connectionName || "Temp Connection"
loader: async ({ deps: { connectionId } }) => {
const connectionDetailsResult =
await commands.getConnectionDetails(connectionId)
const connectionDetails = unwrapResult(connectionDetailsResult)

if (!connectionDetails) throw redirect({ to: "/connections" })
const connName = connectionDetails.connName || "Temp Connection"

const tables = unwrapResult(await commands.getTables())
if (!tables)
Expand Down Expand Up @@ -143,7 +148,7 @@ function DashboardLayout() {
tableName: table
}}
search={{
connectionName: deps.connectionName,
connectionId: deps.connectionId,
tableName: table
}}
preload={false}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,13 @@ import TableActions from "./table-actions"

interface DataTableProps {
columns: ColumnDef<ColumnProps>[]
connectionId: string
}

const DataTable = ({ columns }: DataTableProps) => {
const DataTable = ({ columns, connectionId }: DataTableProps) => {
const { tableName, pkColumn } = useTableState()
const { isRowsLoading, contextMenuRow, setContextMenuRow, table, tableRef } =
useSetupReactTable({ columns, tableName })
useSetupReactTable({ columns, tableName, connectionId })
const queryClient = useQueryClient()
const keybindingsManager = useKeybindings()
const { isOpen, toggleSheet } = useEditRowSheetState()
Expand Down Expand Up @@ -90,7 +91,7 @@ const DataTable = ({ columns }: DataTableProps) => {

return (
<Sheet open={isOpen} onOpenChange={toggleSheet}>
<TableActions table={table} />
<TableActions table={table} connectionId={connectionId} />
{isRowsLoading ? (
<LoadingSpinner />
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,20 @@ import {
} from "@/components/ui/dropdown-menu"
import { Input } from "@/components/ui/input"
import { useTableState } from "@/state/tableState"
import { useDebounceCallback } from "usehooks-ts"
import { TableLocalStorage } from "@/types"
import { useDebounceCallback, useLocalStorage } from "usehooks-ts"

type TableActionsProps = {
table: Table<any>
connectionId: string
}

const TableActions = ({ table }: TableActionsProps) => {
const TableActions = ({ table, connectionId }: TableActionsProps) => {
const { toggleDialog: toggleSqlEditor } = useSqlEditorState()
const { tableName, setGlobalFilter } = useTableState()
const debounced = useDebounceCallback(
(filter: string) => setGlobalFilter(filter),
200
500
)
return (
<>
Expand All @@ -48,7 +50,7 @@ const TableActions = ({ table }: TableActionsProps) => {
/>
</div>
<div className="flex flex-col items-end gap-y-1 lg:gap-y-3">
<DataTablePagination table={table} />
<DataTablePagination table={table} connectionId={connectionId} />
<div className="flex items-center gap-x-3">
<DataTableViewOptions table={table} />
<Button
Expand All @@ -72,11 +74,22 @@ export default TableActions

interface DataTablePaginationProps<TData> {
table: Table<TData>
connectionId: string
}

export function DataTablePagination<TData>({
table
table,
connectionId
}: DataTablePaginationProps<TData>) {
const { tableName } = useTableState()
const [, setConnectionStorage] = useLocalStorage<TableLocalStorage>(
`@tablex/${connectionId}`,
{
tableName,
pageIndex: 0
}
)

return (
<div className="flex items-center justify-between px-2">
<div className="text-muted-foreground hidden text-sm lg:flex">
Expand All @@ -92,7 +105,10 @@ export function DataTablePagination<TData>({
<Button
variant="outline"
className="hidden h-8 w-8 p-0 lg:flex"
onClick={() => table.setPageIndex(0)}
onClick={() => {
table.setPageIndex(0)
setConnectionStorage({ tableName, pageIndex: 0 })
}}
disabled={!table.getCanPreviousPage()}
>
<span className="sr-only">Go to first page</span>
Expand All @@ -101,7 +117,13 @@ export function DataTablePagination<TData>({
<Button
variant="outline"
className="h-8 w-8 p-0"
onClick={() => table.previousPage()}
onClick={() => {
setConnectionStorage({
tableName,
pageIndex: table.getState().pagination.pageIndex - 1
})
table.previousPage()
}}
disabled={!table.getCanPreviousPage()}
>
<span className="sr-only">Go to previous page</span>
Expand All @@ -110,7 +132,13 @@ export function DataTablePagination<TData>({
<Button
variant="outline"
className="h-8 w-8 p-0"
onClick={() => table.nextPage()}
onClick={() => {
setConnectionStorage({
tableName,
pageIndex: table.getState().pagination.pageIndex + 1
})
table.nextPage()
}}
disabled={!table.getCanNextPage()}
>
<span className="sr-only">Go to next page</span>
Expand All @@ -119,7 +147,13 @@ export function DataTablePagination<TData>({
<Button
variant="outline"
className="hidden h-8 w-8 p-0 lg:flex"
onClick={() => table.setPageIndex(table.getPageCount() - 1)}
onClick={() => {
table.setPageIndex(table.getPageCount() - 1)
setConnectionStorage({
tableName,
pageIndex: table.getPageCount() - 1
})
}}
disabled={!table.getCanNextPage()}
>
<span className="sr-only">Go to last page</span>
Expand Down
18 changes: 10 additions & 8 deletions apps/core/src/routes/dashboard/_layout/$tableName/route.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import LoadingSpinner from "@/components/loading-spinner"
import { useGetTableColumns } from "@/hooks/table"
import { useTableState } from "@/state/tableState"
import type { ActiveTableLocalStorage } from "@/types"
import type { TableLocalStorage } from "@/types"
import { createFileRoute } from "@tanstack/react-router"
import { useEffect } from "react"
import { toast } from "react-hot-toast"
Expand All @@ -10,8 +10,7 @@ import { z } from "zod"
import DataTable from "./-components/data-table"

const tablePageSchema = z.object({
tableName: z.string().optional(),
connectionName: z.string()
tableName: z.string().optional()
})

export const Route = createFileRoute("/dashboard/_layout/$tableName")({
Expand All @@ -21,15 +20,18 @@ export const Route = createFileRoute("/dashboard/_layout/$tableName")({

function TableData() {
const { tableName } = Route.useParams()
const { connectionName } = Route.useSearch()
const { connectionId } = Route.useSearch()
const { updateTableName } = useTableState()
const [, setActiveTable] = useLocalStorage<ActiveTableLocalStorage | null>(
"@tablex/active-table",
const [, setActiveTable] = useLocalStorage<TableLocalStorage | null>(
`@tablex/${connectionId}`,
null
)

useEffect(() => updateTableName(tableName), [tableName, updateTableName])
useEffect(() => setActiveTable({ connectionName, tableName }))
useEffect(
() => setActiveTable({ tableName, pageIndex: 0 }),
[setActiveTable, tableName]
)

const {
data: columns,
Expand All @@ -44,7 +46,7 @@ function TableData() {

return (
<section className="flex h-full w-full flex-col overflow-auto will-change-scroll">
<DataTable columns={columns!} />
<DataTable columns={columns!} connectionId={connectionId} />
</section>
)
}
4 changes: 2 additions & 2 deletions apps/core/src/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export type ActiveTableLocalStorage = {
connectionName: string
export type TableLocalStorage = {
tableName: string
pageIndex: number
}

0 comments on commit bbd6a47

Please sign in to comment.