Skip to content

Consolidate integration to one Connection screen - #102265

Open
Krishna2323 wants to merge 38 commits into
Expensify:mainfrom
Krishna2323:krishna2323/101509-connections-page
Open

Krishna2323 wants to merge 38 commits into
Expensify:mainfrom
Krishna2323:krishna2323/101509-connections-page

Conversation

@Krishna2323

@Krishna2323 Krishna2323 commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Explanation of Change

Fixed Issues

$ #101509
PROPOSAL

Tests

Setup: use a Control workspace where you're an admin. Connect QuickBooks Online (or Xero) to it, plus one HR provider (for example BambooHR) and Uber for Business.

  1. Menu and tooltip
    1. Open the workspace. Check that the left menu shows a single "Connections" item. There should be no separate Accounting, HR, Receipt partners or MCP items.
    2. Check that a tooltip reading "New All your connections in one place" points at Connections. "New" should be bold and green.
    3. Click Connections. Check that the tooltip disappears.
    4. Reload the page. Check that the tooltip doesn't come back.
    5. With a new account, open a workspace and let the tooltip show. Then open a different menu item, such as Members. Check that the tooltip is dismissed and doesn't come back after a reload.
  2. Page layout
    1. Check the order on the Connections page: connected integrations first, then the tabs Popular, All, Accounting, People, Travel & Delivery and AI & MCP, then the search box, then the listings, then the "Don't see yours? Suggest an integration, we'll look into it. >" footer.
    2. Check that each connected card shows an "Active" or "Broken" badge and a sync message. It should have a Configure button, or a red Fix button if it's broken.
    3. Switch between the tabs. Check that each one shows the matching listings. Popular should show QBO, Xero, NetSuite, Uber for Business, Claude, ChatGPT, Gusto and BambooHR, minus any that are already connected.
    4. Click the footer. Check that Concierge opens.
  3. Search
    1. Type "net". Check that NetSuite appears.
    2. Type "zzzz". Check that "No results found matching "zzzz"" appears above the footer. The search box shouldn't change width, and the layout shouldn't shift.
    3. Clear the search. Check that the active tab's listings come back.
  4. Responsive layout: resize the browser across the 1024px mark.
    1. At 1024px and wider, check that the cards sit two per row and the search box sits to the right of the tabs.
    2. Below 1024px, check that each card takes the full width and the search box moves to its own full-width row below the tabs.
  5. Accounting replace warning
    1. With QBO connected, click "+" on Xero.
    2. Check that a modal appears with the title "You already got an active accounting integration" and a red "Replace integration" button.
    3. Click Cancel. Check that nothing changes.
  6. Connect flows
    1. Click "+" on an HR provider while another HR provider is connected. Check that the "Cannot connect to multiple HR platforms" modal opens at the wide modal width.
    2. Click "+" on Claude or ChatGPT. Check that the connect link opens in a new tab.
  7. Configure panels: click Configure on each of QBO, BambooHR and Uber.
    1. Check that a right-hand panel opens. Its header should show a round logo, the integration name, the sync status and a ⋮ menu.
    2. Check that the rows below it (Import, Export, Advanced and so on) span the panel edge to edge, with hover highlights that don't overflow.
    3. Check that the ⋮ menu offers Sync now and Disconnect.
    4. Click Sync now. Check that a spinner replaces ⋮ while it syncs.
    5. Disconnect the integration. Check that you're taken back to Connections and the card moves into the listings.
  8. More features
    1. Open More features. Check that there are no toggles for Accounting, Receipt partners, HR or MCP.
    2. Check that the other toggles still work.
  9. Permissions
    1. Log in as an Auditor on the workspace. Check that Connections appears in the menu and the page opens rather than showing Not Found.
    2. Click "+" on any listing. Check that the read-only modal appears instead of a connect flow.
  10. Onboarding: create a new account and choose the accounting-software option. Check that onboarding works exactly as it does on main.
  11. Old routes: paste an old URL such as /workspaces/<policyID>/accounting or /hr. Check that it doesn't crash and doesn't show a blank screen.

Mobile (iOS and Android):

  • Repeat steps 1–3 and step 7.

  • Check that the back button on the Connections page and on each panel returns to the previous screen.

  • Check that the footer's ">" lines up with the text.

  • Verify that no errors appear in the JS console

Offline tests

  1. Go offline. Check that the "+" on unconnected cards is disabled.
  2. Check that the Configure panels still open.

QA Steps

  • Same as tests

  • Verify that no errors appear in the JS console

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
    • I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • Android: Native
    • Android: mWeb Chrome
    • iOS: Native
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
    • MacOS: Desktop
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I verified there are no new alerts related to the canBeMissing param for useOnyx
  • I followed proper code patterns (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method
      • If any non-english text was added/modified, I used JaimeGPT to get English > Spanish translation. I then posted it in #expensify-open-source and it was approved by an internal Expensify engineer. Link to Slack message:
    • I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the guidelines as stated in the Review Guidelines
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.ts or at the top of the file that uses the constant) are defined as such
  • I verified that if a function's arguments changed that all usages have also been updated correctly
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))
  • If new assets were added or existing ones were modified, I verified that:
    • The assets are optimized and compressed (for SVG files, run npm run compress-svg)
    • The assets load correctly across all supported platforms.
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
  • I added unit tests for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.

Screenshots/Videos

Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
@melvin-bot

melvin-bot Bot commented Sep 25, 2026

Copy link
Copy Markdown

Hey, I noticed you changed src/languages/en.ts in a PR from a fork. For security reasons, translations are not generated automatically for PRs from forks.

If you want to automatically generate translations for other locales, an Expensify employee will have to:

  1. Look at the code and make sure there are no malicious changes.
  2. Run the Generate static translations GitHub workflow. If you have write access and the K2 extension, you can simply click: [this button]

Alternatively, if you are an external contributor, you can run the translation script locally with your own OpenAI API key. To learn more, try running:

npx bun ./scripts/generateTranslations.ts --help

Typically, you'd want to translate only what you changed by running npx bun ./scripts/generateTranslations.ts --compare-ref main

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
@Krishna2323
Krishna2323 marked this pull request as ready for review September 25, 2026 17:01
@Krishna2323
Krishna2323 requested review from a team as code owners September 25, 2026 17:01
@Krishna2323
Krishna2323 marked this pull request as draft September 25, 2026 17:01
@melvin-bot
melvin-bot Bot requested review from JmillsExpensify and situchan and removed request for a team September 25, 2026 17:01
@melvin-bot

melvin-bot Bot commented Sep 25, 2026

Copy link
Copy Markdown

@situchan Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]

@melvin-bot
melvin-bot Bot removed the request for review from a team September 25, 2026 17:01
@Krishna2323

Copy link
Copy Markdown
Contributor Author

Sorry, marked it as ready by mistake. It's still in progress.

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
…ltip

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
@Krishna2323 Krishna2323 changed the title Krishna2323/101509 connections page Consolidate integration to one Connection screen Sep 29, 2026
@dubielzyk-expensify

Copy link
Copy Markdown
Contributor

Also, should we be seeing 3 columns at wider screen sizes?

We have this already. Set it at the breakpoint 1800px. What did you have in mind?

CleanShot 2026-10-01 at 8 17 33 PM@2x

@shawnborton

Copy link
Copy Markdown
Contributor

I think we can trigger it much earlier, I was surprised not to see three columns in my screenshot above. We have so much empty space in each card.

…cted, tighten the card gap, keep the selected tab

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
@Krishna2323

Copy link
Copy Markdown
Contributor Author

Updated:

  1. The offer badge is now a condensed pink "Offer" badge right after the integration name.
  2. Offers badge no longer show once an integration is connectet.
  3. Card spacing is now 12px, matching More features.
  4. The selected tab is now saved, so coming back from a connect flow in another browser tab keeps your place instead of going back to All.
Monosnap.screencast.2026-10-01.16-08-34.mp4

@Krishna2323

Copy link
Copy Markdown
Contributor Author

@Expensify/design I was trying to make the columns auto-wrap based on the available space, and here's the result. Each card is at least 300px wide. Does that work? Should I push it for testing?

Monosnap.screencast.2026-10-01.16-46-58.mp4

@shawnborton

Copy link
Copy Markdown
Contributor

That feels more expected to me personally, but let's see what JDubz thinks!

@trjExpensify

Copy link
Copy Markdown
Contributor

The offer only applies to new connections, not existing ones. So I think it's better to not show it once connected, since it doesn't apply. @trjExpensify please correct us if that's not correct.

Agreed. 👍

@trjExpensify

trjExpensify commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Looks like I'm missing the Offer badge on Xero. 🤔

image

... and the U4B connection has the Offer badge when connected.

@trjExpensify

Copy link
Copy Markdown
Contributor

Other than that, looking good! I didn't test the presence of Recruiting but I take it that's hidden behind the greenhouse beta or something?

@dubielzyk-expensify

Copy link
Copy Markdown
Contributor

That feels more expected to me personally, but let's see what JDubz thinks!

LGTM 👍

Agree with the other comments. Looking real good and very close on this. Thanks for the great testing and comments

Copy link
Copy Markdown
Contributor

Great, let's get this out of draft and into C+ review.

@Krishna2323

Copy link
Copy Markdown
Contributor Author

@JS00001 could you please run the translations script? Thanks!

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
… breakpoint

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
@Krishna2323
Krishna2323 marked this pull request as ready for review October 2, 2026 11:08
@Krishna2323
Krishna2323 requested a review from a team as a code owner October 2, 2026 11:08
@Krishna2323

Copy link
Copy Markdown
Contributor Author

Looks like I'm missing the Offer badge on Xero. 🤔

Its the same on staging also, when a accounting integration is connected, the badge is hidden.

image

the U4B connection has the Offer badge when connected.

I think this was an older adhoc build. The badge is hidden once Uber is connected.

@Krishna2323

Copy link
Copy Markdown
Contributor Author

@situchan could you please start reviewing this when you get a chance? The failing checks are only from missing translations, and I'll add those once the translation script runs. I'll also add the recordings shortly, but that shouldn't block testing.

@situchan

situchan commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

The changes are quite big.
While not separating into smaller PRs, can we have beta?

@OSBotify

OSBotify commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

🦜 Polyglot Parrot! 🦜

Squawk! Looks like you added some shiny new English strings. Allow me to parrot them back to you in other tongues:

The diff is too large to include in this comment (130KB), so I've created a gist for you:

📋 View the translation diff here 📋

Note

You can apply these changes to your branch by copying the patch to your clipboard, then running pbpaste | git apply, or directly by running gh gist view --raw 2f1be7f6f0db6614edf1a5cf01d1062a | git apply 😉

View workflow run

@JS00001

JS00001 commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

ran translations, do you guys have an internal eng for this issue? Maybe someone from the integrations projects?

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
@Krishna2323

Copy link
Copy Markdown
Contributor Author

Oops, I tagged you because it became muscle memory to tag you on UI issues 😅 @JmillsExpensify, who’s gonna handle this one?

@JmillsExpensify

Copy link
Copy Markdown
Contributor

Assigned Lucien.

@Krishna2323

Copy link
Copy Markdown
Contributor Author

The changes are quite big.
While not separating into smaller PRs, can we have beta?

@lakchote what do you think about this? I'm fine either way. Adding a beta would be a bit more work for me, so I'd prefer not to if we don't really need it 😅

@situchan

situchan commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

I am open to any idea which doesn't lead to revert after several blockers found by QA

@lakchote lakchote left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left comments

policyID={policyID}
accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN]}
featureName={config.featureName}
policyFeature={CONST.POLICY.POLICY_FEATURE.MORE_FEATURES}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding policyFeature makes this page check read access instead of its previous admin check.

As a result, an auditor can now open a direct Xero or Uber offer link and press Connect.

Can you fix this?

@lakchote

lakchote commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

I’d prefer a beta here given the changes to navigation, permissions and integration setup @Krishna2323.

That would let us switch back if testing finds problems. The issues already identified and failing checks should still be fixed too

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.