From 60271be712b09c6b35b1bf2d49bddd9a6216ed57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Di=20Domenico?= Date: Tue, 3 Jun 2025 17:11:12 +0200 Subject: [PATCH 1/2] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20use=20react=20query=20?= =?UTF-8?q?to=20fetch=20table=20data?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DatabaseBlock/DatabaseGrid.tsx | 2 +- .../src/features/grist/useGristTableData.ts | 46 ++++++++----------- 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/DatabaseBlock/DatabaseGrid.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/DatabaseBlock/DatabaseGrid.tsx index d30d112613..20f1e37f06 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/DatabaseBlock/DatabaseGrid.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/DatabaseBlock/DatabaseGrid.tsx @@ -46,7 +46,7 @@ export const DatabaseGrid = ({ const { colDefs, setColDefs } = useColumns(); useEffect(() => { - const filteredEntries = Object.entries(tableData).filter( + const filteredEntries = Object.entries(tableData || {}).filter( ([key]) => key !== 'manualSort', ); diff --git a/src/frontend/apps/impress/src/features/grist/useGristTableData.ts b/src/frontend/apps/impress/src/features/grist/useGristTableData.ts index 531b6cf356..c14971a0f3 100644 --- a/src/frontend/apps/impress/src/features/grist/useGristTableData.ts +++ b/src/frontend/apps/impress/src/features/grist/useGristTableData.ts @@ -1,42 +1,36 @@ -import { useEffect, useState } from 'react'; - import { APIError, errorCauses, gristFetchApi } from '@/api'; +import { useQuery } from '@tanstack/react-query'; export type UseGristTableDataArguments = { documentId: string; tableId: string; }; +const getTableData = async (documentId: string, tableId: string) => { + const url = `docs/${documentId}/tables/${tableId}/data`; + const response = await gristFetchApi(url); + if (!response.ok) { + throw new APIError( + 'Failed to fetch Grist table data', + await errorCauses(response), + ); + } + return (await response.json()) as Promise< + Record + >; +}; + export const useGristTableData = ({ documentId, tableId, }: UseGristTableDataArguments) => { - const [tableData, setTableData] = useState< - Record - >({}); - - useEffect(() => { - const fetchData = async () => { - const url = `docs/${documentId}/tables/${tableId}/data`; - const response = await gristFetchApi(url); - if (!response.ok) { - throw new APIError( - 'Failed to fetch Grist table data', - await errorCauses(response), - ); - } - return (await response.json()) as Promise; - }; + const { data: tableData, isLoading } = useQuery({ + queryKey: ['getTableData', documentId, tableId], + queryFn: () => getTableData(documentId, tableId), + }); - fetchData() - .then((res) => { - setTableData(res as Record); - }) - .catch((error) => { - console.error('Error fetching Grist table data:', error); - }); - }, [documentId, tableId]); return { tableData, + isLoading, }; }; From 4d07003d1d16beee5e9c6842a47f287752e980ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Di=20Domenico?= Date: Tue, 3 Jun 2025 19:02:09 +0200 Subject: [PATCH 2/2] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20use=20react=20query=20?= =?UTF-8?q?for=20crud=20on=20columns=20&=20records?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DatabaseBlock/AddRowButton.tsx | 2 +- .../DatabaseBlock/DatabaseGrid.tsx | 20 +++--- .../src/features/grist/useGristCrudColumns.ts | 64 +++++++++++-------- .../src/features/grist/useGristCrudRecords.ts | 64 +++++++++++-------- 4 files changed, 87 insertions(+), 63 deletions(-) diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/DatabaseBlock/AddRowButton.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/DatabaseBlock/AddRowButton.tsx index 52fdde5913..8774ed3e7b 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/DatabaseBlock/AddRowButton.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/DatabaseBlock/AddRowButton.tsx @@ -31,7 +31,7 @@ export const AddRowButton = ({ return updatedRows; }); - void createRecords(documentId, tableId, [{ fields: newRow }]); + createRecords({ documentId, tableId, records: [{ fields: newRow }] }); }; const color = '#817E77'; diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/DatabaseBlock/DatabaseGrid.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/DatabaseBlock/DatabaseGrid.tsx index 20f1e37f06..b468024d85 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/DatabaseBlock/DatabaseGrid.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/DatabaseBlock/DatabaseGrid.tsx @@ -124,15 +124,19 @@ export const DatabaseGrid = ({ return [...(prev !== undefined ? prev : []), newColDef]; }); - void createColumns(documentId, tableId, [ - { - id: columnName, - fields: { - label: columnName, - type: ColumnType.TEXT, + createColumns({ + documentId, + tableId, + columns: [ + { + id: columnName, + fields: { + label: columnName, + type: ColumnType.TEXT, + }, }, - }, - ]); + ], + }); }; const onCellEditingStopped = useCallback( diff --git a/src/frontend/apps/impress/src/features/grist/useGristCrudColumns.ts b/src/frontend/apps/impress/src/features/grist/useGristCrudColumns.ts index 0cd79d85e0..2e50dfe308 100644 --- a/src/frontend/apps/impress/src/features/grist/useGristCrudColumns.ts +++ b/src/frontend/apps/impress/src/features/grist/useGristCrudColumns.ts @@ -1,4 +1,5 @@ import { gristFetchApi } from '@/api'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; export enum ColumnType { TEXT = 'Text', @@ -11,35 +12,44 @@ type ColumnInput = { label: string; }; -export const useGristCrudColumns = () => { - const createColumns = async ( - documentId: string, - tableId: string, - columns: { id: string; fields: ColumnInput }[], - ) => { - const url = `docs/${documentId}/tables/${tableId}/columns`; - try { - const response = await gristFetchApi(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ columns }), - }); +const _createColumns = async ({ + documentId, + tableId, + columns, +}: { + documentId: string; + tableId: string; + columns: { id: string; fields: ColumnInput }[]; +}) => { + const url = `docs/${documentId}/tables/${tableId}/columns`; + const response = await gristFetchApi(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ columns }), + }); - if (!response.ok) { - const errorBody = await response.text(); - throw new Error( - `Failed to create columns: ${response.status} ${response.statusText} - ${errorBody}`, - ); - } + if (!response.ok) { + const errorBody = await response.text(); + throw new Error( + `Failed to create columns: ${response.status} ${response.statusText} - ${errorBody}`, + ); + } - return (await response.json()) as Promise<{ records: { id: string }[] }>; - } catch (error) { - console.error('Error creating Grist record:', error); - throw error; - } - }; + return (await response.json()) as Promise<{ records: { id: string }[] }>; +}; + +export const useGristCrudColumns = () => { + const queryClient = useQueryClient(); + const { mutate: createColumns } = useMutation({ + mutationFn: _createColumns, + onSuccess: (_, variables) => { + queryClient.invalidateQueries({ + queryKey: ['getTableData', variables.documentId, variables.tableId], + }); + }, + }); const deleteColumns = async ( documentId: string, diff --git a/src/frontend/apps/impress/src/features/grist/useGristCrudRecords.ts b/src/frontend/apps/impress/src/features/grist/useGristCrudRecords.ts index e90715d030..b9e4bac09a 100644 --- a/src/frontend/apps/impress/src/features/grist/useGristCrudRecords.ts +++ b/src/frontend/apps/impress/src/features/grist/useGristCrudRecords.ts @@ -1,34 +1,44 @@ import { gristFetchApi } from '@/api'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; -export const useGristCrudRecords = () => { - const createRecords = async ( - documentId: string, - tableId: string, - records: { fields: unknown }[], - ) => { - const url = `docs/${documentId}/tables/${tableId}/records`; - try { - const response = await gristFetchApi(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ records }), - }); +const _createRecords = async ({ + documentId, + tableId, + records, +}: { + documentId: string; + tableId: string; + records: { fields: unknown }[]; +}) => { + const url = `docs/${documentId}/tables/${tableId}/records`; + const response = await gristFetchApi(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ records }), + }); - if (!response.ok) { - const errorBody = await response.text(); - throw new Error( - `Failed to create record: ${response.status} ${response.statusText} - ${errorBody}`, - ); - } + if (!response.ok) { + const errorBody = await response.text(); + throw new Error( + `Failed to create record: ${response.status} ${response.statusText} - ${errorBody}`, + ); + } - return (await response.json()) as Promise<{ records: { id: string }[] }>; - } catch (error) { - console.error('Error creating Grist record:', error); - throw error; - } - }; + return (await response.json()) as Promise<{ records: { id: string }[] }>; +}; + +export const useGristCrudRecords = () => { + const queryClient = useQueryClient(); + const { mutate: createRecords } = useMutation({ + mutationFn: _createRecords, + onSuccess: (_, variables) => { + queryClient.invalidateQueries({ + queryKey: ['getTableData', variables.documentId, variables.tableId], + }); + }, + }); const deleteRecords = async ( documentId: string,