From edf5120d8532224b3cb54c7ac7c3182769dc0c8d 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 9c090f2137c79..54befcecbb508 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 50320fd1304bf..c6a26daada1da 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 0000000000000..48c7d58c52d58 --- /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} + + +