Group bulk export options by integration for multi-workspace selections - #96728
Group bulk export options by integration for multi-workspace selections#96728MelvinBot wants to merge 6 commits into
Conversation
Co-authored-by: ahmedGaber93 <ahmedGaber93@users.noreply.github.com>
|
I created this PR from an upstream branch since I don't have push access to your fork. To take ownership of this branch and be able to push updates, run: Then you can close this PR and open a new one from your fork. |
|
🤖 I checked all the checks on this PR. No code fix is needed — every real CI check passes. The only failing check is
This is expected for a draft PR: the Everything else is green: Next step: |
Codecov Report❌ Looks like you've decreased code coverage for some files. Please write tests to increase, or at least maintain, the existing level of code coverage. See our documentation here for how to interpret this table.
|
|
@MelvinBot Update the bulk action sorting to group each integration's actions together:
instead of:
|
…ether Co-authored-by: ahmedGaber93 <ahmedGaber93@users.noreply.github.com>
|
Done — pushed The two loops in
See Also extended the multi-workspace unit test to assert the new grouped ordering. AI checks run locally:
|
|
I analyzed the failing checks — there's no code failure to fix here. The only failing check is PR Author Checklist / checklist, and it's not a code/CI test. It fails because the manual checklist hasn't been filled out:
Since this is an automated draft PR, the checklist boxes and the Every functional and AI check is green: I didn't push any change because there's nothing broken in the code. |
|
@MelvinBot Please update with the following changes. 1) Add a partial-export confirmation modalWhen a selection spans multiple integrations, clicking "Export to " only exports the subset of reports connected to that integration. Before exporting, if it's a partial export (the integration's report count is less than the total number of selected reports), show a confirmation modal:
2) Show BOTH confirmations in sequence when applicableIf the chosen integration's subset ALSO contains reports that were already exported, show two confirmations in sequence (never combined):
Confirming both proceeds with the export; cancelling either one aborts. Present them sequentially (present the second only after the first resolves) so they don't overlap. 3) Apply the SAME flow to "Mark as exported"Route mark-as-exported through the same shared confirmation flow used by export so the behavior stays identical. 4) TestsUpdate
Please run |
- Show a partial-export modal when Export/Mark-as-exported to an integration only covers a subset of the multi-integration selection - Present the partial modal and the existing export-again modal sequentially - Detect already-exported reports from report actions (live Onyx first, then the search snapshot) instead of the stale isExportedToIntegration field - Route Mark as exported through the same shared confirmation flow - Cover the new flows in useSearchBulkActionsExportTest Co-authored-by: ahmedGaber93 <ahmedGaber93@users.noreply.github.com>
|
Done — pushed to What changed1 & 2 — Partial-export modal, shown in sequence with export-again New copy lives under 3 — Already-exported detection from report actions 4 — Mark as exported uses the exact same 5 — Tests — Checks (run locally)
One note for the human co-author: the plural |
|
The only failing check is PR Author Checklist / checklist, and it's not a code problem — there's nothing for me to fix or push. It failed with:
This is a human-only step: the PR Author Checklist must be filled out (and the
Everything else is green or still building — no failing code checks:
|
|
Hi @MelvinBot — please add these changes. This builds on the existing partial-export confirmation work in that PR. GoalRestructure the bulk export confirmation modals so each one shows a fixed subtitle on top and a scrollable list of report names below it. To support this, add a reusable What to do
Resulting modal (example)
Please run our formatter, typecheck, lint, and the |
…ed subtitle + scrollable report list - Add subtitle/subtitleStyles props to ConfirmContent + ConfirmModal; subtitle renders between title and prompt and stays fixed above a scrollable prompt - Partial-export modal: descriptive text moves to the subtitle, the scrollable prompt lists the report names that will be exported - Export-again modal: reuse exportAgainModal.description (without the inline list) as the subtitle, list already-exported report names in the prompt - Update useSearchBulkActionsExportTest to assert the subtitle/prompt split Co-authored-by: ahmedGaber93 <ahmedGaber93@users.noreply.github.com>
|
Done — pushed to What changed1 — 2 — Partial-export modal ( 3 — Export-again modal ( Checks (run locally)
Same note as before: the non-English translations for the new |
|
Still the same, and there's nothing for me to fix in code. The only failing check is PR Author Checklist / checklist, failing with:
This is a human-only attestation — I don't tick those boxes on your behalf. The remaining |
|
@MelvinBot Merge main branch and fix the conflict |
…iWorkspaceIntegration Co-authored-by: ahmedGaber93 <ahmedGaber93@users.noreply.github.com> # Conflicts: # src/hooks/useSearchBulkActions.ts
|
🤖 Merged Conflict: one overlapping change in the import type {BillingGraceEndPeriod, ExportTemplate, Policy, Report, ReportAction, ReportActions, ReportNameValuePairs, SearchResults, Transaction, TransactionViolations} from '@src/types/onyx';Both types are used in the merged file — |
|
MelvinBot has made 5 consecutive commits trying to fix CI failures. Automatic CI fix dispatches are now paused for this PR. Next steps: A human should review the recent commits and resolve the conflicting CI errors manually. |
|
Hi @MelvinBot — please add the following changes. 1. Show the export option when only some selected reports are eligibleIn
2. Align already-exported detection with the backend responseRevert 3. Split the partial-export subtitle into two case-based reasonsTests
Please run the formatter, |
- Show Export/Mark-as-exported when at least one report in a group is eligible; act only on the eligible subset - Revert already-exported detection to the backend-aligned pendingFields.export/isExportedToIntegration check - Split the partial-export subtitle into per-case reasons (other integrations and/or ineligible reports) - Update and add useSearchBulkActionsExport tests Co-authored-by: ahmedGaber93 <ahmedGaber93@users.noreply.github.com>
|
Done — pushed to 1. Show the export option when only some selected reports are eligible — replaced the 2. Align already-exported detection with the backend response — reverted 3. Split the partial-export subtitle into two case-based reasons — the description now takes Tests — added a mixed approved + submitted (same workspace) case that asserts the option still shows, the partial-export modal appears, and only the approved report is exported; updated the Checks run: Two notes:
|

Explanation of Change
Bulk integration export options (export to accounting + "Mark as exported") only appeared when every selected report belonged to a single workspace, because
getExportOptions()inuseSearchBulkActionsderived a singleconnectedIntegrationfromselectedPolicyIDs.length === 1. When a selection spanned multiple workspaces (e.g. one QBO report + one Sage Intacct report),policywasundefined, so no integration options were shown at all — even though each report was individually exportable. This matched neither Classic Expensify nor user expectations.This PR groups the selected reports by their connected accounting integration and builds one "Export to " option and one "Mark as exported" option per integration, each scoped to just the reports for that integration. Export options are listed first, followed by the mark-as-exported options. A single-workspace selection collapses to one group, so the previous behavior is unchanged.
AI checks run locally (by MelvinBot):
npm test tests/unit/hooks/useSearchBulkActionsExportTest.ts— ✅ pass (3 tests, includes a new multi-workspace case)npm run typecheck-tsgo— ✅ passnpm run lint-changed— ✅ passnpm run fmt(oxfmt) — ✅ applied, only the two changed files reformattednpm run react-compiler-compliance-check check src/hooks/useSearchBulkActions.ts— no new divergence: the reported ref-access errors are pre-existing (identical error set onorigin/main; the file already carries areact-hooks/refseslint-disable)Fixed Issues
$ #95820
PROPOSAL: #95820 (comment)
Tests
// TODO: The human co-author must fill out the tests you ran before marking this PR as "ready for review".
Suggested steps:
Offline tests
QA Steps
// TODO: The human co-author must fill out the QA tests before marking this PR as "ready for review". These must be filled out, or the issue title must include "[No QA]."
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectionAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari