From 2a0c73d276e361f468a4f44056ef26d1c7f64efc Mon Sep 17 00:00:00 2001 From: Biswas Rai <38395536+BiswasRai@users.noreply.github.com> Date: Tue, 5 Aug 2025 03:18:00 +0545 Subject: [PATCH] Add snackbar on CSV exports (#13608) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #13516 Add the snackbar on CSV exports https://github.com/user-attachments/assets/d8288351-66f1-4175-814e-ecf0f5b57274 --------- Co-authored-by: Félix Malfait --- .../ExportMultipleRecordsAction.tsx | 58 ++++++++++++++++++- .../hooks/useRecordIndexExportRecords.ts | 2 +- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/ExportMultipleRecordsAction.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/ExportMultipleRecordsAction.tsx index 89f505a6f4..3c18ce5197 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/ExportMultipleRecordsAction.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/ExportMultipleRecordsAction.tsx @@ -1,9 +1,12 @@ -import { Action } from '@/action-menu/actions/components/Action'; +import { ActionDisplay } from '@/action-menu/actions/display/components/ActionDisplay'; +import { ActionConfigContext } from '@/action-menu/contexts/ActionConfigContext'; +import { useCloseActionMenu } from '@/action-menu/hooks/useCloseActionMenu'; import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow'; import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; import { useRecordIndexExportRecords } from '@/object-record/record-index/export/hooks/useRecordIndexExportRecords'; import { getRecordIndexIdFromObjectNamePluralAndViewId } from '@/object-record/utils/getRecordIndexIdFromObjectNamePluralAndViewId'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { useContext, useMemo } from 'react'; export const ExportMultipleRecordsAction = () => { const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow(); @@ -16,7 +19,7 @@ export const ExportMultipleRecordsAction = () => { throw new Error('Current view ID is not defined'); } - const { download } = useRecordIndexExportRecords({ + const { download, progress } = useRecordIndexExportRecords({ delayMs: 100, objectMetadataItem, recordIndexId: getRecordIndexIdFromObjectNamePluralAndViewId( @@ -26,5 +29,54 @@ export const ExportMultipleRecordsAction = () => { filename: `${objectMetadataItem.nameSingular}.csv`, }); - return ; + const { closeActionMenu } = useCloseActionMenu({}); + + const actionConfig = useContext(ActionConfigContext); + + const dynamicActionConfig = useMemo(() => { + if (!actionConfig) return null; + + const originalLabel = + typeof actionConfig.label === 'string' + ? actionConfig.label + : actionConfig.label?.message || 'Export'; + + const originalShortLabel = + typeof actionConfig.shortLabel === 'string' + ? actionConfig.shortLabel + : actionConfig.shortLabel?.message || 'Export'; + + const progressText = + progress?.exportedRecordCount !== undefined + ? progress.displayType === 'percentage' && progress.totalRecordCount + ? ` (${Math.round((progress.exportedRecordCount / progress.totalRecordCount) * 100)}%)` + : ` (${progress.exportedRecordCount})` + : ''; + + return { + ...actionConfig, + label: `${originalLabel}${progressText}`, + shortLabel: `${originalShortLabel}${progressText}`, + }; + }, [actionConfig, progress]); + + if (!dynamicActionConfig) { + return null; + } + + const handleClick = async () => { + try { + await download(); + closeActionMenu(); + } catch (error) { + closeActionMenu(); + throw error; + } + }; + + return ( + + + + ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-index/export/hooks/useRecordIndexExportRecords.ts b/packages/twenty-front/src/modules/object-record/record-index/export/hooks/useRecordIndexExportRecords.ts index 81581a8a9c..8910a75b3a 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/export/hooks/useRecordIndexExportRecords.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/export/hooks/useRecordIndexExportRecords.ts @@ -127,7 +127,7 @@ type UseExportTableDataOptions = Omit & { export const useRecordIndexExportRecords = ({ delayMs, filename, - maximumRequests = 100, + maximumRequests = 1000, objectMetadataItem, pageSize = EXPORT_TABLE_DATA_DEFAULT_PAGE_SIZE, recordIndexId,