-
Notifications
You must be signed in to change notification settings - Fork 3.1k
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
fix: optimistically add personal details #22904
Changes from 1 commit
9cbe95d
571da94
f0d3a67
e6881a1
67258bf
1ee57d8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ import ROUTES from '../../ROUTES'; | |
import * as OptionsListUtils from '../OptionsListUtils'; | ||
import * as ErrorUtils from '../ErrorUtils'; | ||
import * as ReportUtils from '../ReportUtils'; | ||
import * as UserUtils from '../UserUtils'; | ||
import Log from '../Log'; | ||
import Permissions from '../Permissions'; | ||
|
||
|
@@ -344,6 +345,39 @@ function createPolicyExpenseChats(policyID, invitedEmailsToAccountIDs, betas) { | |
return workspaceMembersChats; | ||
} | ||
|
||
/** | ||
* Build personal details objects for a given list of logins and accountIDs | ||
* | ||
* @param {Array<string>} logins Array of user logins | ||
* @param {Array<number>} accountIDs Array of user accountIDs | ||
* @returns {Object} - object with optimisticData, successData and failureData (object of personal details objects) | ||
*/ | ||
function buildPolicyPersonalDetails(logins, accountIDs) { | ||
const policyPersonalDetails = { | ||
optimisticData: {}, | ||
successData: {}, | ||
failureData: {}, | ||
}; | ||
|
||
_.map(logins, (login, index) => { | ||
samh-nl marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const accountID = accountIDs[index]; | ||
|
||
if (_.isEmpty(personalDetails[accountID])) { | ||
policyPersonalDetails.optimisticData[accountID] = { | ||
login, | ||
accountID, | ||
avatar: UserUtils.getDefaultAvatarURL(accountID), | ||
displayName: login, | ||
}; | ||
|
||
policyPersonalDetails.successData[accountID] = null; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Won't this cause a flicker?
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The swapping of the optimistic data with the server data on success should happen within the same rendering cycle. The reason is that the optimistically set data is derived from the search result, and the search result is not an accurate depiction as no backend calls are made. In an ideal situation the search result is accurate and contains all information, but there may be performance/UX/privacy reasons why this was not pursued. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see that when creating a report with a new user, both the optimistic user and the BE user remain in My addition of Alternatively, we could add a boolean flag to the optimistic user and filter these out in the search results. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, same thing goes for |
||
policyPersonalDetails.failureData[accountID] = null; | ||
} | ||
}); | ||
|
||
return policyPersonalDetails; | ||
} | ||
|
||
/** | ||
* Adds members to the specified workspace/policyID | ||
* | ||
|
@@ -354,12 +388,19 @@ function createPolicyExpenseChats(policyID, invitedEmailsToAccountIDs, betas) { | |
*/ | ||
function addMembersToWorkspace(invitedEmailsToAccountIDs, welcomeNote, policyID, betas) { | ||
const membersListKey = `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`; | ||
const logins = _.map(_.keys(invitedEmailsToAccountIDs), (memberLogin) => OptionsListUtils.addSMSDomainIfPhoneNumber(memberLogin)); | ||
const accountIDs = _.values(invitedEmailsToAccountIDs); | ||
const policyPersonalDetails = buildPolicyPersonalDetails(logins, accountIDs); | ||
|
||
// create onyx data for policy expense chats for each new member | ||
const membersChats = createPolicyExpenseChats(policyID, invitedEmailsToAccountIDs, betas); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems we're doing same work in different issues. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cc: @rezkiy37 @madmax330 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
@0xmiroslav can you update your PR to do this? Then the two would complement each other right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #22410 is more optimized code as reusing optimistic members from workspace chat. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alright, go ahead and resolve the conflict in #22410 and we will review. |
||
|
||
const optimisticData = [ | ||
{ | ||
onyxMethod: Onyx.METHOD.MERGE, | ||
key: ONYXKEYS.PERSONAL_DETAILS_LIST, | ||
value: policyPersonalDetails.optimisticData, | ||
}, | ||
{ | ||
onyxMethod: Onyx.METHOD.MERGE, | ||
key: membersListKey, | ||
|
@@ -371,6 +412,11 @@ function addMembersToWorkspace(invitedEmailsToAccountIDs, welcomeNote, policyID, | |
]; | ||
|
||
const successData = [ | ||
{ | ||
onyxMethod: Onyx.METHOD.MERGE, | ||
key: ONYXKEYS.PERSONAL_DETAILS_LIST, | ||
value: policyPersonalDetails.successData, | ||
}, | ||
{ | ||
onyxMethod: Onyx.METHOD.MERGE, | ||
key: membersListKey, | ||
|
@@ -383,6 +429,11 @@ function addMembersToWorkspace(invitedEmailsToAccountIDs, welcomeNote, policyID, | |
]; | ||
|
||
const failureData = [ | ||
{ | ||
onyxMethod: Onyx.METHOD.MERGE, | ||
key: ONYXKEYS.PERSONAL_DETAILS_LIST, | ||
value: policyPersonalDetails.failureData, | ||
}, | ||
{ | ||
onyxMethod: Onyx.METHOD.MERGE, | ||
key: membersListKey, | ||
|
@@ -399,7 +450,6 @@ function addMembersToWorkspace(invitedEmailsToAccountIDs, welcomeNote, policyID, | |
...membersChats.onyxFailureData, | ||
]; | ||
|
||
const logins = _.map(_.keys(invitedEmailsToAccountIDs), (memberLogin) => OptionsListUtils.addSMSDomainIfPhoneNumber(memberLogin)); | ||
const params = { | ||
employees: JSON.stringify(_.map(logins, (login) => ({email: login}))), | ||
|
||
|
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.
The function name is not the most accurate, this data is not explicit to policies. Can we move this function to somewhere more fitting? e.g.
PersonalDetails.js
. Also I think we should indicate that the function will only return onyx data for non existing users.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 have:
PersonalDetailsUtils.js
.getNewPersonalDetailsOnyxData
.PersonalDetailsUtils.js
, wherepersonalDetails
is an array instead of an object.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.
Can we move that to
PersonalDetails
instead? HavingpersonalDetails
as an object is faster to access.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.
Would moving it to
PersonalDetails.js
be semantically correct? It's placed in the actions/ folder and primarily contains functions triggering API calls, although also a few helper functions so it might be reasonable.Yes iterating over the array is less efficient. It may have been done as a speed optimization if the other util functions are called often, so it's more efficient to cast it to an array at Onyx.connect instead of within the util function (executed many times). I would therefore be hesitant to change it to an object and put an extra cast to array inside the other existing functions, without further testing the performance implications.
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.
Maybe we should add another value to
PersonalDetailsUtils
? keepingpersonalDetails
as array and addingallPersonalDetails
as object.Then we make make a follow up PR to rewrite the util functions that use the array to use the object and remove the array variable.
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.
That seems like a good way forward. I have committed the change and will work on the refactor in a separate PR.