From 595c7a9ba405d91a5c52455f49e16b2bc39a726e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Drago=C8=99=20Cojocaru?= Date: Thu, 14 Mar 2024 18:57:09 +0200 Subject: [PATCH] Migrate Export feature to the action bar (#4417) * Migrate Export feature to the action bar * Fixed predicate derived state * Fixed bug useFindManyParams outside context * Added export row selection --------- Co-authored-by: Lucas Bordeau --- .../ObjectMetadataItemsProvider.tsx | 12 ++++---- .../hooks/useRecordActionBar.tsx | 17 ++++++++++- .../hooks/useLoadRecordIndexTable.ts | 8 +++-- .../RecordIndexOptionsDropdownContent.tsx | 15 ---------- .../options/hooks/useExportTableData.ts | 30 +++++++++++++++++-- 5 files changed, 54 insertions(+), 28 deletions(-) diff --git a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx b/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx index 73441a496..a4a50ac35 100644 --- a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx +++ b/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx @@ -11,16 +11,14 @@ export const ObjectMetadataItemsProvider = ({ }: React.PropsWithChildren) => { const objectMetadataItems = useRecoilValue(objectMetadataItemsState()); const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState()); - const shouldDisplayChildren = () => { - if (objectMetadataItems.length > 0) { - return true; - } - return !currentWorkspaceMember; - }; + + const shouldDisplayChildren = + objectMetadataItems.length > 0 || !currentWorkspaceMember; + return ( <> - {shouldDisplayChildren() && ( + {shouldDisplayChildren && ( {children} diff --git a/packages/twenty-front/src/modules/object-record/record-action-bar/hooks/useRecordActionBar.tsx b/packages/twenty-front/src/modules/object-record/record-action-bar/hooks/useRecordActionBar.tsx index 5b18654a2..98ae1ee54 100644 --- a/packages/twenty-front/src/modules/object-record/record-action-bar/hooks/useRecordActionBar.tsx +++ b/packages/twenty-front/src/modules/object-record/record-action-bar/hooks/useRecordActionBar.tsx @@ -6,9 +6,11 @@ import { useFavorites } from '@/favorites/hooks/useFavorites'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { useDeleteManyRecords } from '@/object-record/hooks/useDeleteManyRecords'; import { useExecuteQuickActionOnOneRecord } from '@/object-record/hooks/useExecuteQuickActionOnOneRecord'; +import { useExportTableData } from '@/object-record/record-index/options/hooks/useExportTableData'; import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; import { IconClick, + IconFileExport, IconHeart, IconHeartOff, IconMail, @@ -94,6 +96,13 @@ export const useRecordActionBar = ({ ); }, [callback, executeQuickActionOnOneRecord, selectedRecordIds]); + const { progress, download } = useExportTableData({ + delayMs: 100, + filename: `${objectMetadataItem.nameSingular}.csv`, + objectNameSingular: objectMetadataItem.nameSingular, + recordIndexId: objectMetadataItem.namePlural, + }); + const baseActions: ContextMenuEntry[] = useMemo( () => [ { @@ -102,8 +111,14 @@ export const useRecordActionBar = ({ accent: 'danger', onClick: () => handleDeleteClick(), }, + { + label: `${progress === undefined ? `Export` : `Export (${progress}%)`}`, + Icon: IconFileExport, + accent: 'default', + onClick: () => download(), + }, ], - [handleDeleteClick], + [handleDeleteClick, download, progress], ); const dataExecuteQuickActionOnmentEnabled = useIsFeatureEnabled( 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 cc4005c49..90c4d46e2 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 @@ -10,12 +10,16 @@ import { SIGN_IN_BACKGROUND_MOCK_COMPANIES } from '@/sign-in-background-mock/con import { useFindManyRecords } from '../../hooks/useFindManyRecords'; -export const useFindManyParams = (objectNameSingular: string) => { +export const useFindManyParams = ( + objectNameSingular: string, + recordTableId?: string, +) => { const { objectMetadataItem } = useObjectMetadataItem({ objectNameSingular, }); - const { getTableFiltersState, getTableSortsState } = useRecordTableStates(); + const { getTableFiltersState, getTableSortsState } = + useRecordTableStates(recordTableId); const tableFilters = useRecoilValue(getTableFiltersState()); const tableSorts = useRecoilValue(getTableSortsState()); diff --git a/packages/twenty-front/src/modules/object-record/record-index/options/components/RecordIndexOptionsDropdownContent.tsx b/packages/twenty-front/src/modules/object-record/record-index/options/components/RecordIndexOptionsDropdownContent.tsx index d341b88b4..59831da29 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/options/components/RecordIndexOptionsDropdownContent.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/options/components/RecordIndexOptionsDropdownContent.tsx @@ -10,7 +10,6 @@ import { useSpreadsheetRecordImport } from '@/object-record/spreadsheet-import/u import { IconBaselineDensitySmall, IconChevronLeft, - IconFileExport, IconFileImport, IconTag, } from '@/ui/display/icon'; @@ -27,8 +26,6 @@ import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates' import { useViewBar } from '@/views/hooks/useViewBar'; import { ViewType } from '@/views/types/ViewType'; -import { useExportTableData } from '../hooks/useExportTableData'; - type RecordIndexOptionsMenu = 'fields'; type RecordIndexOptionsDropdownContentProps = { @@ -122,13 +119,6 @@ export const RecordIndexOptionsDropdownContent = ({ const { openRecordSpreadsheetImport } = useSpreadsheetRecordImport(objectNameSingular); - const { progress, download } = useExportTableData({ - delayMs: 100, - filename: `${objectNameSingular}.csv`, - objectNameSingular, - recordIndexId, - }); - return ( <> {!currentMenu && ( @@ -157,11 +147,6 @@ export const RecordIndexOptionsDropdownContent = ({ LeftIcon={IconFileImport} text="Import" /> - )} diff --git a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useExportTableData.ts b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useExportTableData.ts index a80bb7de8..ab72add28 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useExportTableData.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useExportTableData.ts @@ -108,12 +108,36 @@ export const useExportTableData = ({ const [pageCount, setPageCount] = useState(0); const [progress, setProgress] = useState(undefined); const [hasNextPage, setHasNextPage] = useState(true); - const { getVisibleTableColumnsSelector } = + + const { getVisibleTableColumnsSelector, getSelectedRowIdsSelector } = useRecordTableStates(recordIndexId); + const columns = useRecoilValue(getVisibleTableColumnsSelector()); - const params = useFindManyParams(objectNameSingular); + const selectedRowIds = useRecoilValue(getSelectedRowIdsSelector()); + + const hasSelectedRows = selectedRowIds.length > 0; + + const findManyRecordsParams = useFindManyParams( + objectNameSingular, + recordIndexId, + ); + + const selectedFindManyParams = { + ...findManyRecordsParams, + filter: { + ...findManyRecordsParams.filter, + id: { + in: selectedRowIds, + }, + }, + }; + + const usedFindManyParams = hasSelectedRows + ? selectedFindManyParams + : findManyRecordsParams; + const { totalCount, records, fetchMoreRecords } = useFindManyRecords({ - ...params, + ...usedFindManyParams, limit: pageSize, onCompleted: (_data, { hasNextPage }) => { setHasNextPage(hasNextPage ?? false);