From 2deb472b75ecad9aea3e694d3d9ac5fda2b848c7 Mon Sep 17 00:00:00 2001 From: andres Date: Tue, 16 Jul 2024 11:57:58 +0200 Subject: [PATCH] wip: editable rows --- .../components/db-table-view/body-cell.tsx | 26 ++++++ .../src/components/db-table-view/columns.tsx | 85 +++++++++---------- .../db-table-view/url-with-preview.tsx | 28 ++++++ .../db/$dbName/tables/$tableName/data.tsx | 27 +++++- frontend/src/services/db/db.hooks.ts | 6 ++ 5 files changed, 128 insertions(+), 44 deletions(-) create mode 100644 frontend/src/components/db-table-view/body-cell.tsx create mode 100644 frontend/src/components/db-table-view/url-with-preview.tsx diff --git a/frontend/src/components/db-table-view/body-cell.tsx b/frontend/src/components/db-table-view/body-cell.tsx new file mode 100644 index 0000000..cbb6700 --- /dev/null +++ b/frontend/src/components/db-table-view/body-cell.tsx @@ -0,0 +1,26 @@ +import { cn } from "@/lib/utils"; +import type { ComponentPropsWithoutRef } from "react"; + +export function BodyCell({ + value, + dataType, + className, + ...rest +}: { value: any; dataType: string } & Omit< + ComponentPropsWithoutRef<"div">, + "children" +>) { + return ( +
+ {value} +
+ ); +} diff --git a/frontend/src/components/db-table-view/columns.tsx b/frontend/src/components/db-table-view/columns.tsx index a8fd73b..498553c 100644 --- a/frontend/src/components/db-table-view/columns.tsx +++ b/frontend/src/components/db-table-view/columns.tsx @@ -1,18 +1,17 @@ -import { cn, isImageUrl, isUrl } from "@/lib/utils"; +import { BodyCell } from "@/components/db-table-view/body-cell"; +import { UrlWithPreview } from "@/components/db-table-view/url-with-preview"; +import { cn, isUrl } from "@/lib/utils"; import { type TableColumns, useTableColumnsQuery } from "@/services/db"; import { useSettingsStore } from "@/state"; import type { ColumnDef } from "@tanstack/react-table"; -import { useMemo } from "react"; +import { useMemo, useState } from "react"; const buildColumns = ({ columns, formatDates, - showImagesPreview, }: { columns?: TableColumns; - formatDates: boolean; - showImagesPreview: boolean; }): ColumnDef[] => { if (!columns) return [] as ColumnDef[]; @@ -21,6 +20,7 @@ const buildColumns = ({ title: column_name, size: 300, id: column_name, + enableSorting: true, header: () => { return (
({
); }, - enableSorting: true, - cell: ({ row }) => { - const value = row.getValue(column_name) as any; + cell: ({ row, table, column }) => { + const initialValue = row.getValue(column_name) as any; + const [value, setValue] = useState(initialValue); + + const [isEditing, setIsEditing] = useState(false); + function handleDoubleClick() { + setIsEditing(true); + } + function handleSave() { + if (value === initialValue) return; + (table.options.meta as any)?.setEditedRows((old) => ({ + ...old, + [row.index]: true, + })); + (table.options.meta as any)?.updateData(row.index, column.id, value); + setIsEditing(false); + } + if (isEditing) { + return ( + + autoFocus={true} + className={"w-full focus:ring"} + value={value} + onChange={(e) => setValue(e.target.value)} + onBlur={handleSave} + /> + ); + } let finalValue = value; if ( formatDates && @@ -43,43 +69,18 @@ const buildColumns = ({ ) { finalValue = new Date(value as string).toLocaleString(); } - if (showImagesPreview && typeof value === "string" && isUrl(value)) { - const isImage = isImageUrl(value); - return ( - -
- {value} - {isImage && ( - {"preview"} - )} -
-
- ); + if (typeof value === "string" && isUrl(value)) { + return ; } if (typeof finalValue === "boolean") { finalValue = finalValue ? "true" : "false"; } return ( -
- {finalValue} -
+ ); }, })) as ColumnDef[]; @@ -91,13 +92,11 @@ export const useColumns = ({ }: { dbName: string; tableName: string }) => { const { data: details } = useTableColumnsQuery({ dbName, tableName }); const formatDates = useSettingsStore.use.formatDates(); - const showImagesPreview = useSettingsStore.use.showImagesPreview(); return useMemo(() => { return buildColumns({ columns: details, formatDates, - showImagesPreview, }); - }, [details, formatDates, showImagesPreview]); + }, [details, formatDates]); }; diff --git a/frontend/src/components/db-table-view/url-with-preview.tsx b/frontend/src/components/db-table-view/url-with-preview.tsx new file mode 100644 index 0000000..6814ea2 --- /dev/null +++ b/frontend/src/components/db-table-view/url-with-preview.tsx @@ -0,0 +1,28 @@ +import { cn, isImageUrl } from "@/lib/utils"; +import { useSettingsStore } from "@/state"; +import { memo } from "react"; + +const RawUrlWithPreview = ({ url }: { url: string }) => { + const showImagesPreview = useSettingsStore.use.showImagesPreview(); + const isImage = showImagesPreview && isImageUrl(url); + + return ( + +
+ {url} + {isImage && ( + {"preview"} + )} +
+
+ ); +}; + +export const UrlWithPreview = memo(RawUrlWithPreview); + +UrlWithPreview.displayName = "UrlWithPreview"; diff --git a/frontend/src/routes/db/$dbName/tables/$tableName/data.tsx b/frontend/src/routes/db/$dbName/tables/$tableName/data.tsx index 584870a..d0ece62 100644 --- a/frontend/src/routes/db/$dbName/tables/$tableName/data.tsx +++ b/frontend/src/routes/db/$dbName/tables/$tableName/data.tsx @@ -86,6 +86,14 @@ function Component() { sortDesc: filters.sortDesc, }); + const [tableData, setTableData] = useState>>([]); + console.log(tableData); + const [editedRows, setEditedRows] = useState({}); + console.log("editedRows", editedRows); + useEffect(() => { + setTableData(structuredClone(data?.data) ?? []); + }, [data]); + const handleWhereClauseFormSubmit = useCallback( ({ whereClause }: WhereClauseFormValues) => { if (whereClause === whereQuery) { @@ -120,9 +128,26 @@ function Component() { ); const table = useReactTable({ + meta: { + editedRows, + setEditedRows, + updateData: (rowIndex: number, columnId: string, value: string) => { + setTableData((old) => + old.map((row, index) => { + if (index === rowIndex) { + return { + ...old[rowIndex], + [columnId]: value, + }; + } + return row; + }), + ); + }, + }, columnResizeMode: "onChange", columns, - data: data?.data ?? [], + data: tableData, getCoreRowModel: getCoreRowModel(), manualPagination: true, manualSorting: true, diff --git a/frontend/src/services/db/db.hooks.ts b/frontend/src/services/db/db.hooks.ts index 86afa64..9a643ea 100644 --- a/frontend/src/services/db/db.hooks.ts +++ b/frontend/src/services/db/db.hooks.ts @@ -42,6 +42,12 @@ export const useTablesListQuery = (args: GetTablesListArgs) => { export const useTableDataQuery = (args: GetTableDataArgs) => { return useQuery({ + refetchOnWindowFocus: false, + refetchOnReconnect: false, + refetchOnMount: false, + refetchInterval: false, + refetchIntervalInBackground: false, + staleTime: Number.POSITIVE_INFINITY, queryKey: [DB_QUERY_KEYS.TABLES.DATA, args], queryFn: () => dbService.getTableData(args), placeholderData: (previousData, previousQuery) => {