Offline feedback and errors for optimistic room rows#11655
Conversation
|
I still need to check off 2 boxes and figure out why the jest unit tests are failing, but reviews can begin. |
|
Ready for reviews again. I think I have thoroughly addressed all comments. |
| const needsOpacity = (isOfflinePendingAction && !isUpdateOrDeleteError) || isAddError; | ||
| const needsStrikeThrough = props.network.isOffline && props.pendingAction === 'delete'; | ||
| const hideChildren = !props.network.isOffline && props.pendingAction === 'delete' && !hasErrors; | ||
| const showErrorMessages = props.shouldShowErrorMessages && hasErrors && !_.isEmpty(props.errors); |
There was a problem hiding this comment.
hasErrors already has that condition
| const showErrorMessages = props.shouldShowErrorMessages && hasErrors && !_.isEmpty(props.errors); | |
| const showErrorMessages = props.shouldShowErrorMessages && hasErrors; |
| result.isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(report); | ||
| result.shouldShowSubscript = result.isPolicyExpenseChat && !report.isOwnPolicyExpenseChat && !result.isArchivedRoom; | ||
| result.brickRoadIndicator = getBrickRoadIndicatorStatusForReport(report, reportActions); | ||
| result.pendingAction = report.pendingFields ? report.pendingFields.addWorkspaceRoom : null; |
There was a problem hiding this comment.
😕 what is addWorkspaceRoom doing here? Isn't this a generic component?
There was a problem hiding this comment.
I added a pendingAction key to the options for use with the OfflineWithFeedback component. For now I set the pendingAction only for adding the workspace room, but it can be updated to be a combination of more fields in the future.
That's from my description of the PR. Yes createOption is called several times by getOptions, which is used by getSearchOptions, getNewChatOptions, and getMemberInviteOptions. What's the harm in setting a pendingAction? What would you suggest instead?
There was a problem hiding this comment.
My confusion comes from: we only need to show RBR in the LHN, no? Wouldn't this make it show in all those other places too?
There was a problem hiding this comment.
We need to show the RBR / 50% opacity in the LHN and the search. It won't apply for a new chat, and I don't think it will apply for the member invite options, but I haven't confirmed that. Thanks for raising this point, because I should look into that. I will test / explain whether it applies for the member invite or not.
There was a problem hiding this comment.
createOption is called several times by getOptions, which is used by getSearchOptions, getNewChatOptions, and getMemberInviteOptions.
The pendingAction should be set for rooms when calling getSearchOptions.
getNewChatOptions only returns reports with a single participant. It skips options without a login.
App/src/libs/OptionsListUtils.js
Lines 546 to 549 in 2df16aa
The login is only set when creating the option if the report doesn't have multiple participants.
App/src/libs/OptionsListUtils.js
Lines 364 to 368 in 2df16aa
hasMultipleParticipants is always true for chatRooms.
App/src/libs/OptionsListUtils.js
Line 317 in 2df16aa
For getMemberInviteOptions we do not pass reports to getOptions so we won't access any rooms.
App/src/libs/OptionsListUtils.js
Lines 742 to 756 in 2df16aa
So in summary we will only have a pendingAction for rooms in the LHN and search, as intended.
|
Sorry for all the confusion with this PR. Let's get this back on track and moving forward again. Here are my goals.
Goal 3 is probably a premature optimization as @iwiznia hinted at here. I could do something like this, but that's also strange. <OfflineWithFeedback
pendingAction={optionItem.pendingAction}
errors={!_.isEmpty(optionItem.brickRoadIndicator) ? {hasErrors: true} : null}
shouldShowErrorMessages={false}
>I'll go ahead and write a function to get all possible errors on a report, similar to how the errors are accessed in getBrickRoadIndicatorStatusForReport, and then pass all those errors to OfflineWithFeedback. I'll remove the <OfflineWithFeedback
pendingAction={optionItem.pendingAction}
errors={ReportUtils.getAllErrors(props.reportID)}
shouldShowErrorMessages={false}
>Does that sound good? |
|
My above plan was approved in Slack here so I'm going to push those changes now. |
|
Ok there's a problem with my plan which is that the OptionRow and OptionRowLHN components do not currently have access to the report and reportActions, which are needed for I could write I could also subscribe to both report and reportActions in ReportUtils, but again that violates convention. Instead I think I will add a App/src/libs/OptionsListUtils.js Line 294 in d4bcc62 |
|
I'm having trouble writing the I've been tinkering around with underscore.js trying to figure out how to do this. |
|
Ready for another review 🙇 |
ScreenshotsWebScreen.Recording.2022-10-21.at.20.02.40.movMobile Web - ChromeMobile Web - SafariDesktopiOSAndroidScreen.Recording.2022-10-21.at.21.03.35.mov |
|
The code LGTM, I'm still testing on all platforms. I found a weird behavior on iOS (which probably is not related to this PR) is that the RBR indicator appears after I open the room chat (disabled my mac's wifi): Screen.Recording.2022-10-21.at.21.23.51.movAnd on Safari the error never showed up: Screen.Recording.2022-10-21.at.21.37.43.movEdit: For some reason the network status is not changing on the iOS simulator when I disabled the wifi (I wonder if there's an issue with the |
|
Thanks for reviewing and starting the checklist @marcochavezf!
Yeah offline testing on the iOS simulator doesn't really work. I had this PR up to add a switch to toggle offline mode for convenient testing, but it never actually got merged. You can try using the changes in that PR for testing. I'll put up another PR for it soon. Please DM me if you have questions about testing. I'll look into why that jest unit test is not passing. |
|
Cool, thanks @neil-marcellini, I recreated the Android emulator to test on Mobile Chrome and everything looks good 👍🏽 |
|
Sweet. I figured out what was wrong with the tests so it should be good to go now! |
| const allReportErrors = {}; | ||
| _.chain(errorSources) | ||
| .filter(errors => !_.isEmpty(errors)) | ||
| .each(errors => _.extend(allReportErrors, errors)); |
There was a problem hiding this comment.
Is this really doing a reduce? I think so, right? Wouldn't it be better to use the reduce method to make code clearer?
There was a problem hiding this comment.
Oh yeah good point. I'm on it.
87eca24
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🚀 Deployed to staging by @neil-marcellini in version: 1.2.20-0 🚀
|
|
🚀 Deployed to production by @chiragsalian in version: 1.2.20-3 🚀
|





Details
I have wrapped the OptionRowLHN and the search OptionRow components in OfflineWithFeedback so they they are grayed out (50% opacity) while pending creation offline, and when creation fails.
I added a
pendingActionkey and anallReportErrorskey to the options for use with the OfflineWithFeedback component. For now I set the pendingAction only for adding the workspace room, but it can be updated to be a combination of more fields in the future.To set
allReportErrorsI combined all the error sources related to a report into one big object of error messages keyed by microtime. I set thebrickRoadIndicatorbased on whetherallReportErrorsis empty.I also added one new prop to
OfflineWithFeedbackto handle cases where we want a component to be grayed out when needed, but we don't want to show the error messages under it. Before I achieved that by putting display none of the error messages container. It's better to render the messages only when we need them by settingshouldShowErrorMessagesto false.Related Issues
$ https://github.com/Expensify/Expensify/issues/232287
Tests
Offline success
Offline error
#ffroom), workspace, and hit save#ffroom)PR Review Checklist
PR Author Checklist
### Fixed Issuessection aboveTestssectionQA stepssectiontoggleReportand notonIconClick)src/languages/*filesWaiting for Copylabel for a copy review on the original GH to get the correct copy.STYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)/** comment above it */thisproperly so there are no scoping issues (i.e. foronClick={this.submit}the methodthis.submitshould be bound tothisin the constructor)thisare necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);ifthis.submitis never passed to a component event handler likeonClick)StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)Avataris modified, I verified thatAvataris working as expected in all cases)PR Reviewer Checklist
The reviewer will copy/paste it into a new comment and complete it after the author checklist is completed
### Fixed Issuessection aboveTestssectionQA stepssectiontoggleReportand notonIconClick).src/languages/*filesSTYLE.md) were followedAvatar, I verified the components usingAvatarhave been tested & I retested again)/** comment above it */displayNamepropertythisproperly so there are no scoping issues (i.e. foronClick={this.submit}the methodthis.submitshould be bound tothisin the constructor)thisare necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);ifthis.submitis never passed to a component event handler likeonClick)StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)Avataris modified, I verified thatAvataris working as expected in all cases)QA Steps
Run the tests above.
Screenshots
Web
Offline creation pending

Room creation failed grayed out in LHN and search

Mobile Web - Chrome
Offline pending creation success
https://user-images.githubusercontent.com/26260477/194970136-9617a0f6-40c6-40d9-a73d-b19ceb63daff.mov
Creation failed
https://user-images.githubusercontent.com/26260477/194970147-dd3a7346-16ad-4291-9324-81660ea946c7.mov
Mobile Web - Safari
Offline pending creation success
https://user-images.githubusercontent.com/26260477/194969401-d6f1d6e9-8845-4a6d-9ae1-ddb753a24ca9.mp4
Creation failed
https://user-images.githubusercontent.com/26260477/194969367-aec9c1ae-207f-474a-9824-6387ae3574a3.mp4
Desktop
Offline pending creation success
https://user-images.githubusercontent.com/26260477/195216730-505fb005-6450-472b-ad06-44bc2fd011a0.mov
Creation failed
https://user-images.githubusercontent.com/26260477/195216743-1060f31e-8c69-4059-b853-a649192e8666.mov
iOS
Offline pending creation success
https://user-images.githubusercontent.com/26260477/194968404-91eefdb0-128a-4645-abb2-353d65c962f4.mp4
Creation failed
https://user-images.githubusercontent.com/26260477/194968755-9d2952bf-391b-4465-9d80-c31b3e0000bd.mp4
Android
Offline pending creation success
android-success.mov
Creation failed
android-fail.mov