[NoQA] Show feed even if no linkedPolicyIDs or preferredPolicy#91764
Conversation
madmax330
left a comment
There was a problem hiding this comment.
Can you also do the same thing for corporate card feeds?
|
@MelvinBot can you address the review comments? |
…ard feeds Add JSDoc explaining the fallback chain in isExpensifyCardFeedVisibleToAdmin. Update getCardFeedsForDisplayPerPolicy to index feeds by linkedPolicyIDs when present and fall back to workspaceAccountID matching for orphan feeds, mirroring the Expensify card feed behavior for corporate card feeds. Co-authored-by: Maxence Coulibaly <madmax330@users.noreply.github.com>
|
Updated
Callers in |
Codecov Report✅ Changes either increased or maintained existing code coverage, great job!
|
…tCardFeedsForDisplayPerPolicy Co-authored-by: Maxence Coulibaly <madmax330@users.noreply.github.com>
|
@MelvinBot can you fix the conflicts? |
Co-authored-by: Maxence Coulibaly <madmax330@users.noreply.github.com> # Conflicts: # src/pages/workspace/expensifyCard/WorkspaceExpensifyCardFeedSelectorPage.tsx
|
🤖 Conflicts resolved and merged There was one conflict in
|
|
@MelvinBot can you find a way to simplify this PR so that it doesn't add so many helper methods? Or is there no way to simplify it? |
|
⏱️ Ran out of time before I could finish. This usually means the task was too complex or I got stuck exploring. Please try again with a more specific request or post in #melvinbot-ai. |
|
Yes, this can be simplified. The helper sprawl is all in the feed-description path — not the visibility path — and it can drop from 4 new helpers to 2. The 4 new helpers ( Proposed change: merge the three orphan-feed fallback resolvers ( The visibility changes ( Before → after (illustrative)After — one consolidated fallback helper: /** Best-effort domain name for an orphan feed (no linkedPolicyIDs / preferredPolicy). */
function getOrphanFeedDomainName(
fundID: number | undefined,
domains: OnyxCollection<Domain> | undefined,
cardList: CardList | undefined,
policies: OnyxCollection<Policy> | undefined,
): string {
if (!fundID) {
return '';
}
const domainEmail = domains?.[`${ONYXKEYS.COLLECTION.DOMAIN}${fundID}`]?.email ?? Object.values(domains ?? {}).find((domain) => domain?.accountID === fundID && !!domain.email)?.email;
if (domainEmail) {
return Str.extractEmailDomain(domainEmail);
}
const cardDomainName = getDomainNameFromExpensifyCardFeed(fundID, cardList);
if (cardDomainName) {
return cardDomainName;
}
const workspaceOwner = Object.values(policies ?? {}).find((policy) => policy?.workspaceAccountID === fundID)?.owner;
return workspaceOwner ? Str.extractEmailDomain(workspaceOwner) : '';
}After — the description function collapses to 3 branches: function getExpensifyCardFeedDescription(
cardSettings: OnyxEntry<ExpensifyCardSettings>,
policies: OnyxCollection<Policy>,
domains?: OnyxCollection<Domain>,
fundID?: number,
cardList?: CardList,
): string {
// 1. Explicit domain name on the settings.
const settingsDomainName = getDomainNameFromExpensifyCardSettings(cardSettings);
if (settingsDomainName) {
return getDescriptionForPolicyDomainCard(settingsDomainName, policies);
}
// 2. Linked / preferred policy name.
const linkedPolicyIDs = getLinkedPolicyIDsFromExpensifyCardSettings(cardSettings);
const preferredPolicyID = getPreferredPolicyFromExpensifyCardSettings(cardSettings);
const policyIDForName = linkedPolicyIDs?.length ? linkedPolicyIDs.at(0) : preferredPolicyID;
const policyName = policyIDForName && policies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyIDForName.toUpperCase()}`]?.name;
if (policyName) {
return policyName;
}
// 3. Orphan feed fallback (fund domain -> its cards -> backing workspace owner).
const orphanDomainName = getOrphanFeedDomainName(fundID, domains, cardList, policies);
return orphanDomainName ? getDescriptionForPolicyDomainCard(orphanDomainName, policies) : '';
}Net: 4 new helpers → 2, three repeated If you want to trim further, the deeper question is whether all those orphan fallback sources (domain email -> card list -> workspace owner) are needed, or whether one authoritative source covers the real-world data — that would cut the helper to a couple of lines. Happy to dig into that if you tell me which source is reliable in practice. Next Steps: Reply with |
|
@MelvinBot implement this: #91764 (comment) |
…or orphan feed lookups - Replace non-existent Policy.workspaceAccountID with policyAccountID - Compare Card.fundID (string) against fundID.toString() - Update tests to match and replace unknown dictionary word Co-authored-by: Maxence Coulibaly <madmax330@users.noreply.github.com>
|
🤖 Pushed a fix for the failing typecheck and spellcheck checks (commit 5ac1be3). The Typecheck
Spellcheck
Tests
Verified locally: |
There was a problem hiding this comment.
Pull request overview
This PR updates Expensify Card feed selection and Company Card feed grouping so feeds still surface even when linkedPolicyIDs and preferredPolicy are missing (via domain-admin and policyAccountID fallback logic).
Changes:
- Expand Expensify Card feed visibility rules to include “orphan” feeds when the user is a domain admin (or when
policyAccountIDmatches the feed’sfundID). - Improve feed label/description resolution with additional fallbacks (domain email, card list domainName, workspace owner email domain).
- Update Company Card feed grouping per policy to index feeds by
linkedPolicyIDs, with apolicyAccountIDfallback for orphan feeds, plus added/updated unit tests.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/unit/hooks/useHasAnyAdminExpensifyCardFeed.test.ts | Adds coverage for domain-admin visibility when preferredPolicy is missing. |
| tests/unit/hooks/useExpensifyCardFeedsForFeedSelector.test.ts | Adds coverage for orphan feed inclusion/exclusion rules. |
| tests/unit/ExpensifyCardFeedSelectorUtilsTest.ts | Adds unit tests for the new description fallback chain. |
| tests/unit/CardFeedUtilsTest.ts | Updates expectations for linkedPolicyIDs indexing across multiple policies. |
| src/pages/workspace/expensifyCard/WorkspaceExpensifyCardListPage.tsx | Passes additional data to feed description (domains, card list). |
| src/pages/workspace/expensifyCard/WorkspaceExpensifyCardFeedSelectorPage.tsx | Uses enhanced feed descriptions in selector items. |
| src/libs/ExpensifyCardFeedSelectorUtils.ts | Implements orphan-feed visibility and richer description resolution. |
| src/libs/CardUtils.ts | Adds helper to read domainName from root or nested program blocks. |
| src/libs/CardFeedUtils.ts | Groups company card feeds per policy using linkedPolicyIDs / policyAccountID fallbacks. |
| src/hooks/useHasAnyAdminExpensifyCardFeed.ts | Includes domain collection + current user accountID in admin-feed detection. |
| src/hooks/useExpensifyCardFeedsForFeedSelector.ts | Includes domains + current user accountID to compute visible feeds. |
| src/hooks/useCardFeedsForDisplay.ts | Passes policies into company feed grouping (but introduces redundant policy subscriptions). |
| src/hooks/useCardFeedsForActivePolicies.ts | Passes policies into company feed grouping (but introduces redundant policy subscriptions). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@MelvinBot can you address the PR review feedback? |
Compute eligiblePoliciesIDsArray from the already-subscribed allPolicies instead of a second useOnyx selector subscription, per review feedback. Co-authored-by: Maxence Coulibaly <madmax330@users.noreply.github.com>
|
Addressed the outstanding review feedback in 83562b2 (pushed). The only unresolved feedback was the two Copilot comments about the duplicate Behavior is unchanged (same data, same re-render triggers) with one fewer Onyx listener per hook. Checks run locally
The earlier inline comments (JSDoc requests on |
|
@MelvinBot can you fix the conflicts? |
|
@madmax330 eslint check is failing. |
|
@MelvinBot can you fix the typescript and eslint checks? |
|
⏱️ Ran out of time before I could finish. This usually means the task was too complex or I got stuck exploring. Please try again with a more specific request or post in #melvinbot-ai. |
|
Hmm the typescript failures look unrelated, a lot of the ESlint ones as well 😕 |
|
@madmax330 should merging main fix that? Looks like Jest tests are failing now too. |
|
Yeah looks like they were fixed on main. The jest test was flakey so I fixed that also |
|
ESLint check is still failing for some reason. @MelvinBot any idea why? |
|
The failure is from Root cause: This PR added new How to fix — pick one:
The other failing run ( |
|
Alright @puneetlath the lint errors are fixed |
|
🚧 @puneetlath has triggered a test Expensify/App build. You can view the workflow run here. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
🚀 Deployed to staging by https://github.com/puneetlath in version: 9.4.5-0 🚀
Bundle Size Analysis (Sentry): |
|
🤖 Help site review: no changes required I reviewed the changes in this PR against the help articles under Why: This PR is an internal bug fix to the Expensify Card feed selector visibility logic. It makes an admin's card feed surface under the From other workspaces section even when the feed has no The change does not:
The help articles that mention "card feeds" (e.g. Set-Up-and-Manage-the-Expensify-Card.md, the Connect Credit Cards section) describe the customer-facing setup flows, which are unchanged by this edge-case display fix. The "From other workspaces" grouping in the feed selector is a UI detail that isn't (and doesn't need to be) documented. No draft PR was created since there is nothing to update. @madmax330, please confirm you agree with this assessment — if you'd like docs added for the "From other workspaces" behavior anyway, let me know and I'll draft a PR. |
|
🚀 Deployed to production by https://github.com/Julesssss in version: 9.4.5-6 🚀
|
Explanation of Change
Fixed Issues
$ #91765
PROPOSAL: N/A
Tests
Verify that no errors appear in the JS console
Log into an account with an expensify card feed that has no preferredPolicyID set and no linkedPolicyIDs
Enable expensify cards on the workspace
Click on issue cards and make sure you see that feed in the "From other worksapces" section like below:
Offline tests
N/A
QA Steps
// TODO: These must be filled out, or the issue title must include "[No QA]."
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, 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.ScrollViewcomponent to make it scrollable when more elements are added to the page.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