Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions src/hooks/useSearchBulkActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1238,7 +1238,7 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
);

const handleCSVExport = useCallback(
async (isBasicExport: boolean) => {
async (isBasicExport: boolean, isGroupsOnly = false) => {
if (hasOnlyEmptyReports) {
showEmptyReportsDownloadErrorModal(emptyReports.length);
return;
Expand All @@ -1248,7 +1248,7 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
return;
}

const exportName = translate(isBasicExport ? 'export.basicExport' : 'export.currentView');
const exportName = translate(isGroupsOnly ? 'export.currentViewGroupsOnly' : isBasicExport ? 'export.basicExport' : 'export.currentView');

if (areAllMatchingItemsSelected) {
const supportsAllMatchingExclusions = isExpenseType || isExpenseReportType;
Expand All @@ -1271,6 +1271,7 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
isBasicExport: exportParameters.isBasicExport,
exportColumnLabels: exportParameters.exportColumnLabels,
exportName,
isGroupsOnly,
});

// Clear the selection now that the export has started. The ExportDownloadStatusManager shows the modal.
Expand All @@ -1293,6 +1294,7 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
exportColumnLabels: exportParameters.exportColumnLabels,
exportName,
isGroupExport,
isGroupsOnly,
},
() => {
didFail = true;
Expand Down Expand Up @@ -1333,7 +1335,7 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
);

const handleBasicExport = useCallback(() => handleCSVExport(true), [handleCSVExport]);
const handleExportCurrentView = useCallback(() => handleCSVExport(false), [handleCSVExport]);
const handleExportCurrentView = useCallback((isGroupsOnly = false) => handleCSVExport(false, isGroupsOnly), [handleCSVExport]);

const handleApproveWithDEWCheck = useCallback(async () => {
if (isOffline) {
Expand Down Expand Up @@ -2447,6 +2449,19 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
addSeparatorBefore: true,
});

if (isGroupedSearch) {
exportOptions.push({
text: translate('export.currentViewGroupsOnly'),
value: CONST.SEARCH.BULK_ACTION_TYPES.EXPORT,
icon: expensifyIcons.Table,
onSelected: () => {
handleExportCurrentView(true);
},
shouldCloseModalOnSelect: true,
shouldCallAfterModalHide: true,
});
}

if (!allSelectedAreDeleted && canExportGroupWithTemplates) {
// Builds a single export sub-menu item for a template. `isDefaultTemplate` picks the icon and `addSeparatorBefore` draws the divider at the top of each group.
const buildExportOption = (template: ExportTemplate, isDefaultTemplate: boolean, addSeparatorBefore: boolean): ExportMenuItem => {
Expand Down
1 change: 1 addition & 0 deletions src/languages/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11791,6 +11791,7 @@ Hier ist ein *Testbeleg*, um dir zu zeigen, wie es funktioniert:`,
exportInProgress: 'Export wird ausgeführt',
conciergeWillSend: 'Concierge wird dir die Datei in Kürze senden.',
currentView: 'Aktuelle Ansicht',
currentViewGroupsOnly: 'Aktuelle Ansicht (nur Gruppen)',
},
exportDownload: {
preparingTitle: 'Preparing download...',
Expand Down
1 change: 1 addition & 0 deletions src/languages/el.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11986,6 +11986,7 @@ ${reportName}`,
export: {
basicExport: 'Βασική εξαγωγή',
currentView: 'Τρέχουσα προβολή',
currentViewGroupsOnly: 'Τρέχουσα προβολή (μόνο ομάδες)',
reportLevelExport: 'Όλα τα δεδομένα - σε επίπεδο αναφοράς',
expenseLevelExport: 'Όλα τα δεδομένα - επίπεδο δαπάνης',
multipleTaxExport: 'Καναδική εξαγωγή πολλαπλών φόρων',
Expand Down
1 change: 1 addition & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12062,6 +12062,7 @@ const translations = {
downloadStatementPDF: 'Download statement',
basicExport: 'Basic export',
currentView: 'Current view',
currentViewGroupsOnly: 'Current view (groups only)',
reportLevelExport: 'All Data - report level',
expenseLevelExport: 'All Data - expense level',
multipleTaxExport: 'Canadian Multiple Tax Export',
Expand Down
1 change: 1 addition & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11974,6 +11974,7 @@ ${reportName}`,
exportInProgress: 'Exportación en curso',
conciergeWillSend: 'Concierge te enviará el archivo en breve.',
currentView: 'Vista actual',
currentViewGroupsOnly: 'Vista actual (solo grupos)',
},
exportDownload: {
preparingTitle: 'Preparando descarga...',
Expand Down
1 change: 1 addition & 0 deletions src/languages/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11817,6 +11817,7 @@ Voici un *reçu test* pour vous montrer comment ça fonctionne :`,
exportInProgress: 'Export en cours',
conciergeWillSend: 'Concierge vous enverra le fichier sous peu.',
currentView: 'Vue actuelle',
currentViewGroupsOnly: 'Vue actuelle (groupes uniquement)',
},
exportDownload: {
preparingTitle: 'Preparing download...',
Expand Down
1 change: 1 addition & 0 deletions src/languages/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11741,6 +11741,7 @@ Ecco una *ricevuta di prova* per mostrarti come funziona:`,
exportInProgress: 'Esportazione in corso',
conciergeWillSend: 'Concierge ti invierà il file a breve.',
currentView: 'Vista corrente',
currentViewGroupsOnly: 'Vista corrente (solo gruppi)',
},
exportDownload: {
preparingTitle: 'Preparing download...',
Expand Down
1 change: 1 addition & 0 deletions src/languages/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11572,6 +11572,7 @@ ${reportName}`,
exportInProgress: 'エクスポート処理中',
conciergeWillSend: 'Conciergeがまもなくファイルを送信します。',
currentView: '現在のビュー',
currentViewGroupsOnly: '現在のビュー(グループのみ)',
},
exportDownload: {
preparingTitle: 'Preparing download...',
Expand Down
1 change: 1 addition & 0 deletions src/languages/nl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11702,6 +11702,7 @@ Hier is een *proefbon* om je te laten zien hoe het werkt:`,
exportInProgress: 'Export bezig',
conciergeWillSend: 'Concierge stuurt je het bestand zo meteen.',
currentView: 'Huidige weergave',
currentViewGroupsOnly: 'Huidige weergave (alleen groepen)',
},
exportDownload: {
preparingTitle: 'Preparing download...',
Expand Down
1 change: 1 addition & 0 deletions src/languages/pl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11722,6 +11722,7 @@ Oto *paragon testowy*, żeby pokazać Ci, jak to działa:`,
exportInProgress: 'Trwa eksport',
conciergeWillSend: 'Concierge wkrótce wyśle Ci plik.',
currentView: 'Bieżący widok',
currentViewGroupsOnly: 'Bieżący widok (tylko grupy)',
},
exportDownload: {
preparingTitle: 'Preparing download...',
Expand Down
1 change: 1 addition & 0 deletions src/languages/pt-BR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11695,6 +11695,7 @@ Aqui está um *comprovante de teste* para mostrar como funciona:`,
exportInProgress: 'Exportação em andamento',
conciergeWillSend: 'O Concierge enviará o arquivo para você em breve.',
currentView: 'Visualização atual',
currentViewGroupsOnly: 'Visualização atual (somente grupos)',
},
exportDownload: {
preparingTitle: 'Preparing download...',
Expand Down
1 change: 1 addition & 0 deletions src/languages/zh-hans.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11277,6 +11277,7 @@ ${reportName}`,
exportInProgress: '导出进行中',
conciergeWillSend: 'Concierge 将很快把文件发送给你。',
currentView: '当前视图',
currentViewGroupsOnly: '当前视图(仅分组)',
},
exportDownload: {
preparingTitle: 'Preparing download...',
Expand Down
1 change: 1 addition & 0 deletions src/libs/API/parameters/ExportSearchItemsToCSVParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ type ExportSearchItemsToCSVParams = {
exportColumnLabels: string;
exportName: string;
isGroupExport?: boolean;
isGroupsOnly?: boolean;
};

export default ExportSearchItemsToCSVParams;
5 changes: 4 additions & 1 deletion src/libs/actions/Search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2069,7 +2069,7 @@ function rejectMoneyRequestsOnSearch({
type Params = Record<string, ExportSearchItemsToCSVParams>;

function exportSearchItemsToCSV(
{jsonQuery, reportIDList, transactionIDList, excludedTransactionIDList, isBasicExport, exportColumnLabels, exportName, isGroupExport}: ExportSearchItemsToCSVParams,
{jsonQuery, reportIDList, transactionIDList, excludedTransactionIDList, isBasicExport, exportColumnLabels, exportName, isGroupExport, isGroupsOnly}: ExportSearchItemsToCSVParams,
onDownloadFailed: () => void,
translate: LocalizedTranslate,
allReportsTransactionsAndViolations: ReportTransactionsAndViolationsDerivedValue | undefined,
Expand Down Expand Up @@ -2107,6 +2107,7 @@ function exportSearchItemsToCSV(
isBasicExport,
exportColumnLabels,
isGroupExport,
isGroupsOnly,
}) as Params;

const formData = new FormData();
Expand Down Expand Up @@ -2140,6 +2141,7 @@ function queueExportSearchItemsToCSV({
isBasicExport,
exportColumnLabels,
exportName,
isGroupsOnly,
}: ExportSearchItemsToCSVParams): string {
const exportID = rand64();
const onyxKey = `${ONYXKEYS.COLLECTION.EXPORT_DOWNLOAD}${exportID}` as const;
Expand Down Expand Up @@ -2174,6 +2176,7 @@ function queueExportSearchItemsToCSV({
exportColumnLabels,
exportName,
exportID,
isGroupsOnly,
}) as QueueExportSearchItemsToCSVParams;

markExportInitiatedLocally(exportID);
Expand Down
44 changes: 44 additions & 0 deletions tests/unit/SearchActionsTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,25 @@ describe('SearchActions', () => {
});

describe('queueExportSearchItemsToCSV', () => {
it('passes the groups-only option to the queued export', () => {
// Given a summary-only export of a grouped search.
const parameters = {
jsonQuery: '{}',
reportIDList: [],
transactionIDList: [],
isBasicExport: false,
exportColumnLabels: '{}',
exportName: 'Current view (groups only)',
isGroupsOnly: true,
};

// When the export is queued.
queueExportSearchItemsToCSV(parameters);

// Then the worker receives the summary-only flag.
expect(mockWrite).toHaveBeenCalledWith(WRITE_COMMANDS.QUEUE_EXPORT_SEARCH_ITEMS_TO_CSV, expect.objectContaining({isGroupsOnly: true}), expect.any(Object));
});

it('sets optimistic Onyx data with state preparing and returns exportID', () => {
const exportID = queueExportSearchItemsToCSV({
jsonQuery: '{}',
Expand Down Expand Up @@ -255,6 +274,31 @@ describe('SearchActions', () => {
describe('exportSearchItemsToCSV', () => {
beforeEach(() => jest.clearAllMocks());

it('passes the groups-only option in the direct CSV form payload', () => {
// Given a summary-only export of a grouped search.
const appendSpy = jest.spyOn(FormData.prototype, 'append');

// When the export is downloaded directly.
exportSearchItemsToCSV(
{
jsonQuery: '{}',
reportIDList: [],
transactionIDList: [],
isBasicExport: false,
exportColumnLabels: '{}',
exportName: 'Current view (groups only)',
isGroupsOnly: true,
},
jest.fn(),
translateForTest,
undefined,
);

// Then the API receives the summary-only flag.
expect(appendSpy).toHaveBeenCalledWith('isGroupsOnly', 'true');
appendSpy.mockRestore();
});

it('includes excluded transaction IDs in the direct CSV form payload', () => {
const appendSpy = jest.spyOn(FormData.prototype, 'append');

Expand Down
Loading
Loading