-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add new HOC to get policy.connections
data
#39132
Conversation
// If the policy doesn't have the connections data when it has the accounting connections feature enabled, | ||
// call the API to get the data | ||
openPolicyAccountingPage(policy.id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aldo-expensify, is it accurate to say that the connections
object is empty when the user hasn't connected to any accounting software?
If that is the case, this useEffect
will keep calling openPolicyAccountingPage
indefinitely for workspaces that have the accounting feature enabled but that haven't connected to any accounting software.
Do you have any suggestion on how we can distinguish the situation when the user has connected to the accounting software but the connections
object hasn't populated? This is the only situation when we have to call openPolicyAccountingPage
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aldo-expensify, is it accurate to say that the connections object is empty when the user hasn't connected to any accounting software?
I just tested and it appears to me that the connections
key is completely missing. I guess what you could do is create a local state with useState
so you are sure that you only call openPolicyAccountingPage
once. Something like
if (!loadedPolicyConnections) {
openPolicyAccountingPage();
setLoadedPolicyConnections(true);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aldo's plan would work, but it might result in more API requests than necessary.
An alternate thought I wad was that maybe in the policy summaries that get sent to NewDot we could include a new property like connectCount: 2
so that we know how many connections to expect. That way, you could determine the difference between not having any connections configured, and not having the connections loaded in Onyx yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the thoughtful and creative ideas, both 😄
For now, I'll go with @aldo-expensify's suggestion as it's easier to implement. As an optimization to mitigate unnecessary API calls, I'll create a GH issue to implement @tgolen's suggestion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Created a GH issue to implement Tim's solution: https://github.com/Expensify/Expensify/issues/383660
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about instead of using a local state as I suggested, we use a context with a state, so if we open more pages that require the policy's connection settings, we can see that a different page already loaded it.
This is a sound idea. It addresses @tgolen's concerns about unnecessary API calls to a certain extent.
@tgolen, do you have any other concerns besides unnecessary API calls? I'm interested in understanding the potential issues your solution aims to resolve. 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My main concerns are unnecessary API calls, yes. They do not have a zero cost and I think it is a very naive approach there is a better solution. Whatever you do here is going to put a pattern in place that engineers are going to follow from here on out and I think it's a bad pattern.
It sounds like @aldo-expensify is concerned that a piece of policy data would be complex to keep track of, but this is just like any other piece of policy that exists on the policy and there is nothing more complex that needs to be done here that we aren't doing with all of the other policy data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should seek more opinions in engineering-chat, but meanwhile... I don't think the problem of "unnecessary API calls" is big enough to introduce this new piece of data. Why? The only cases that would happen are:
- User navigates to the main Accounting page: if
policy.connections
is missing, it will trigger a fetch, but just one and will get nothing (there was noconnections
). - User navigates to deeper Accounting page when there is no
policy.connections
: this can only happen if the user is entering directly using the url, which I think is a rare case.
In cases where there is actually a connection, after we load it, we won't do further calls to the API
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Slack discussion: https://expensify.slack.com/archives/C03TQ48KC/p1712185841746469
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We came to the consensus that we should go with the approach to fetch the connections
data once.
I'll modify the PR to use a Context as suggested by @aldo-expensify 👍
Reviewer Checklist
Screenshots/VideosAndroid: NativeAndroid: mWeb ChromeiOS: NativeiOS: mWeb SafariMacOS: Chrome / SafariMacOS: Desktop |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly the code looks good to me!
); | ||
} | ||
|
||
return null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't get why we return nothing if the connections
are false, I try to use it on the workspace profile page but it shows a blank page. Also, I'm curious about what case the HOC will be used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added some comments in the new commit. It explains the usage of the HOC and the context that I also added in that commit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't get why we return nothing if the connections are false
@mollfpr, @aldo-expensify, should we return LoadingPage
instead of null
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might be able to leverage this later. The only case I think we should return null
is where we want to navigate the page if there are no connections
to avoid rendering a component while animating the transition.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should should a spinner if policy.isLoadingConnections
is true, and if policy.isLoadingConnections
is false, hmmm 404? 🤷
@aldo-expensify, @mollfpr, I added a context in the new commit. Please review the PR again 🙇 The context was added to implement this suggestion |
Reassure test was failing. Merged the main. |
I feel like the new implementation with |
I completely agree with you, @tgolen! I decided to add a new Onyx collection key called I also removed the fields I added in previous commits 👍 |
@mollfpr, this PR is ready for another review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly looks good to me!
openPolicyAccountingPage(policy.id); | ||
}, [hasConnectionsDataBeenFetched, policy]); | ||
|
||
if (status === 'loading' || !hasConnectionsDataBeenFetched) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will always show the loader when the policy hasn't enabled the accounting feature. Should we let the OpenPolicyAccountingPage
API be called even though the policy hasn't enabled the feature?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to confirm, how is this accessible in the UI if accounting isn't enabled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mollfpr, this page won't be acceesible for users who hasn't enabled the accounting feature.
Also, even if the user somehow be able to access this page, it won't cause the infinite loading state. hasConnectionsDataBeenFetched
will be true if the fetch is attempted once (even if there is no data returned from the API call)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also, just to be clear, the connections
field might still be empty even if the user has enabled the accounting feature if the user hasn't connected to any accounting software
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems broken. I'm getting infinite loader when I try to visit the page again
Screen.Recording.2024-04-18.at.5.48.40.PM.mov
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@s77rt similar problem with going offline and then offline: #39132 (comment)
@hayata-suenaga is working on it here #40375
Co-authored-by: Luthfi <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍
@roryabraham 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] |
import ONYXKEYS from '@src/ONYXKEYS'; | ||
|
||
function openPolicyAccountingPage(policyID: string) { | ||
const hasConnectionsDataBeenFetchedKey = `${ONYXKEYS.COLLECTION.POLICY_HAS_CONNECTIONS_DATA_BEEN_FETCHED}${policyID}` as const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is as const
necessary here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fix: a084e52
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like you removed it from a different spot. Is it still necessary here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
haha I definitely moved the const
from a different place but it didn't cause the TS error 😆 for this particular one
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
const finallyData: OnyxUpdate[] = [ | ||
{ | ||
onyxMethod: Onyx.METHOD.MERGE, | ||
key: hasConnectionsDataBeenFetchedKey, | ||
value: true, | ||
}, | ||
]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hayata-suenaga After playing with this, I think you missed the failureData
setting hasConnectionsDataBeenFetched
to false
or something like that?
If you do:
- Create a workspace
- Enable
Accounting
, but don't got to the accounting settings yet - Disable your internet connection
- Open the
Accounting
settings
I would have expected that an Offline blocker would appear since we haven't loaded the policy connections, but it doesn't because hasConnectionsDataBeenFetched
is set true
even if OPEN_POLICY_ACCOUNTING_PAGE
fails
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is the PR to fix the issue. Thank you for letting me know of the issue 🙇
🚀 Deployed to staging by https://github.com/aldo-expensify in version: 1.4.63-0 🚀
|
🚀 Deployed to production by https://github.com/mountiny in version: 1.4.63-21 🚀
|
cc: @tgolen @aldo-expensify
Details
This PR does two things:
OpenPolicyAccountingPage
API commandpolicy
objectpolicy.connections
is setpolicy.connections
is not set, invoke the new action functionopenPolicyAccountingPage
to get data that populatespolicy.connections
policy.connections
is not set and being fetched, return the loading indicator.policy.connections
is not set and the device is offline, display the offline screenWe also store a boolean value inside Onyx to remember if the connections data for the given policy has been attempted to be fetched in the current user session. If the data is fetched previously but the connections field of the policy object is
null
orundefined
, that means that the data doesn't exist on the backend.Fixed Issues
$ #39108
PROPOSAL: N/A
Tests / Offline Tests / QA Steps
No QA. No test. This PR just adds the HOC component. This PR does not add a code to use the HOC. We can test the HOC in a PR that first uses it.
PR Author Checklist
### Fixed Issues
section aboveTests
sectionOffline steps
sectionQA steps
sectionBecause there is no way to test this PR, there is no screenshot to add
toggleReport
and notonIconClick
)myBool && <MyComponent />
.src/languages/*
files and using the translation methodSTYLE.md
) were followedAvatar
, I verified the components usingAvatar
are working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG)
)Avatar
is modified, I verified thatAvatar
is working as expected in all cases)Design
label and/or tagged@Expensify/design
so the design team can review the changes.ScrollView
component to make it scrollable when more elements are added to the page.main
branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTest
steps./** comment above it */
this
properly so there are no scoping issues (i.e. foronClick={this.submit}
the methodthis.submit
should be bound tothis
in the constructor)this
are necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);
ifthis.submit
is never passed to a component event handler likeonClick
)Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari
MacOS: Desktop