From fe941c64bed3b2922bb60edda80f911fc99686c8 Mon Sep 17 00:00:00 2001 From: Thomas Trompette Date: Fri, 31 May 2024 11:24:42 +0200 Subject: [PATCH] Build empty state for remote tables (#5652) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remote tables could be in an empty state because: - either we do not have data, which is normal - either the connexion is broken (issue with the server, table requires updates...) Apollo throws errors but these will quickly disappear and do not provide any tips to the user on how handle those. This PR adds a new empty state placeholder for remote objects, that will be display when the record list is empty. It will provide a link to the settings page. Capture d’écran 2024-05-30 à 11 49 33 --- .../object-record/hooks/useFindManyRecords.ts | 3 + .../hooks/useLoadRecordIndexTable.ts | 3 + .../components/RecordTableEmptyState.tsx | 59 +++++++++++++++++++ .../components/RecordTableWithWrappers.tsx | 42 ++++--------- .../RecordTableEmptyState.stories.tsx | 29 +++++++++ 5 files changed, 105 insertions(+), 31 deletions(-) create mode 100644 packages/twenty-front/src/modules/object-record/record-table/components/RecordTableEmptyState.tsx create mode 100644 packages/twenty-front/src/modules/object-record/record-table/components/__stories__/RecordTableEmptyState.stories.tsx diff --git a/packages/twenty-front/src/modules/object-record/hooks/useFindManyRecords.ts b/packages/twenty-front/src/modules/object-record/hooks/useFindManyRecords.ts index 9c090f213..54befcecb 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/useFindManyRecords.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/useFindManyRecords.ts @@ -33,6 +33,7 @@ export const useFindManyRecords = ({ orderBy, limit, onCompleted, + onError, skip, recordGqlFields, fetchPolicy, @@ -45,6 +46,7 @@ export const useFindManyRecords = ({ totalCount?: number; }, ) => void; + onError?: (error?: Error) => void; skip?: boolean; recordGqlFields?: RecordGqlOperationGqlRecordFields; fetchPolicy?: WatchQueryFetchPolicy; @@ -120,6 +122,7 @@ export const useFindManyRecords = ({ variant: SnackBarVariant.Error, }, ); + onError?.(error); }, }); diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexTable.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexTable.ts index 50320fd13..c6a26daad 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexTable.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexTable.ts @@ -61,6 +61,9 @@ export const useLoadRecordIndexTable = (objectNameSingular: string) => { setLastRowVisible(false); setIsRecordTableInitialLoading(false); }, + onError: () => { + setIsRecordTableInitialLoading(false); + }, }); return { diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableEmptyState.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableEmptyState.tsx new file mode 100644 index 000000000..48c7d58c5 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableEmptyState.tsx @@ -0,0 +1,59 @@ +import { useNavigate } from 'react-router-dom'; +import { IconPlus, IconSettings } from 'twenty-ui'; + +import { Button } from '@/ui/input/button/components/Button'; +import AnimatedPlaceholder from '@/ui/layout/animated-placeholder/components/AnimatedPlaceholder'; +import { + AnimatedPlaceholderEmptyContainer, + AnimatedPlaceholderEmptySubTitle, + AnimatedPlaceholderEmptyTextContainer, + AnimatedPlaceholderEmptyTitle, +} from '@/ui/layout/animated-placeholder/components/EmptyPlaceholderStyled'; + +type RecordTableEmptyStateProps = { + objectLabel: string; + createRecord: () => void; + isRemote: boolean; +}; + +export const RecordTableEmptyState = ({ + objectLabel, + createRecord, + isRemote, +}: RecordTableEmptyStateProps) => { + const navigate = useNavigate(); + + const [title, subTitle, Icon, onClick, buttonTitle] = isRemote + ? [ + 'No Data Available for Remote Table', + 'If this is unexpected, please verify your settings.', + IconSettings, + () => navigate('/settings/integrations'), + 'Go to Settings', + ] + : [ + `Add your first ${objectLabel}`, + `Use our API or add your first ${objectLabel} manually`, + IconPlus, + createRecord, + `Add a ${objectLabel}`, + ]; + + return ( + + + + {title} + + {subTitle} + + +