Skip to content
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

Optimistically create policy expense chats for new members of workspaces #16764

Merged
merged 11 commits into from
Apr 28, 2023

Conversation

robertKozik
Copy link
Contributor

@robertKozik robertKozik commented Mar 30, 2023

Details

Add creating optimistic policy expense chats while adding new members to the workspace, so created chats would pop up while user is offline.

Fixed Issues

$ #14594
PROPOSAL: #14594 (comment)

Tests

Same as QA steps

  • Verify that no errors appear in the JS console

Offline tests

Same as the QA steps. Workspace chats for each member should appear optimistically

QA Steps

  1. Log in with account that has access to the policy-expense-chat beta
  2. Go offline by navigating to [profile icon] > Preferences > and enable Force offline
  3. Create a new workspace.
  4. Invite some people to the workspace. Verify that workspace chats for each member appear optimistically.
  5. Go online by navigating to [profile icon] > Preferences > disable Force online. Verify that workspace chats created for each members are updated accordingly
  • 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 / Chrome
    • iOS / native
    • iOS / 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 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 verified the translation was requested/reviewed 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 correct English and approved by marketing by adding the Waiting for Copy label for a copy review on the original GH to get the correct copy.
    • 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.js 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 a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately and each prop has a /** comment above it */
    • The file is named correctly
    • The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
    • The only data being stored in the state is data necessary for rendering and nothing else
    • For Class Components, any internal methods passed to components event handlers are bound to this properly so there are no scoping issues (i.e. for onClick={this.submit} the method this.submit should be bound to this in the constructor)
    • Any internal methods bound to this are necessary to be bound (i.e. avoid this.submit = this.submit.bind(this); if this.submit is never passed to a component event handler like onClick)
    • All JSX used for rendering exists in the render method
    • The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
  • 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(themeColors.componentBG)
  • 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 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.
  • 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.
  • I have checked off every checkbox in the PR author checklist, including those that don't apply to this PR.

Screenshots/Videos

Web
Screen.Recording.2023-03-30.at.12.58.35.mov
Mobile Web - Chrome
RPReplay_Final1680175838.MP4
Mobile Web - Safari
Screen.Recording.2023-03-30.at.13.23.18.mov
Desktop
Screen.Recording.2023-03-30.at.13.34.57.mov
iOS
Screen.Recording.2023-03-30.at.13.13.12.mov
Android
Screen.Recording.2023-03-30.at.15.50.22.mov

@robertKozik robertKozik requested a review from a team as a code owner March 30, 2023 18:08
@melvin-bot melvin-bot bot requested review from 0xmiros and bondydaa and removed request for a team March 30, 2023 18:08
@MelvinBot
Copy link

@bondydaa @0xmiroslav One of you needs to 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]

@github-actions
Copy link
Contributor

github-actions bot commented Mar 30, 2023

CLA Assistant Lite bot All contributors have signed the CLA ✍️ ✅

@robertKozik
Copy link
Contributor Author

I have read the CLA Document and I hereby sign the CLA

bondydaa
bondydaa previously approved these changes Apr 6, 2023
Copy link
Contributor

@bondydaa bondydaa left a comment

Choose a reason for hiding this comment

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

Just one small thing from me that you can change or leave as is, I don't have a strong opinion.

Tested on desktop and 👍 :chef-kiss:

const membersListKey = `${ONYXKEYS.COLLECTION.POLICY_MEMBER_LIST}${policyID}`;
const logins = _.map(memberLogins, memberLogin => OptionsListUtils.addSMSDomainIfPhoneNumber(memberLogin));

// create onyx data for policy expense chats for each new member
const membersChats = createPolicyExpenseChats(policyID, logins, betas);
Copy link
Contributor

Choose a reason for hiding this comment

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

NAB maybe a better variable name would be like membersChatData

@0xmiros
Copy link
Contributor

0xmiros commented Apr 6, 2023

oh sorry forgot this PR. reviewing now

@bondydaa
Copy link
Contributor

bondydaa commented Apr 6, 2023

all you @0xmiroslav let me know if you need help with the checklist.

@0xmiros
Copy link
Contributor

0xmiros commented Apr 6, 2023

@robertKozik can you please merge from main since branch is very behind

@robertKozik
Copy link
Contributor Author

@0xmiroslav rebased, so should be up to date

bondydaa
bondydaa previously approved these changes Apr 6, 2023
@0xmiros
Copy link
Contributor

0xmiros commented Apr 6, 2023

BUG: multiple workspace chats are created for the same user

bug.mov

@0xmiros
Copy link
Contributor

0xmiros commented Apr 6, 2023

@bondydaa should we also cross-out workspace chat when remove user from workspace offline?

Comment on lines 236 to 238
onyxSuccessData: [],
onyxOptimisticData: [],
optimisticReportIDs: {},
Copy link
Contributor

Choose a reason for hiding this comment

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

no need failureData here?

onyxMethod: CONST.ONYX.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${optimisticReport.reportID}`,
value: {
isLoadingReportActions: false,
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this necessary?

Copy link
Contributor Author

@robertKozik robertKozik Apr 7, 2023

Choose a reason for hiding this comment

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

I was modelling that on creating report inside Report.js file in function openReport (393:400 lines). If you think it can be ommited I'll remove it

Copy link
Contributor

Choose a reason for hiding this comment

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

If not needed, let's remove

Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like false is the default here

isLoadingReportActions: false,

and it's used here

const isLoadingInitialReportActions = _.isEmpty(this.props.reportActions) && this.props.report.isLoadingReportActions;

as well as here

src/pages/home/report/ReportActionsList.js
180:                        if (this.props.report.isLoadingReportActions && lastReportAction.actionName !== CONST.REPORT.ACTIONS.TYPE.CREATED) {

src/pages/home/report/ReportActionsView.js
134:        if (nextProps.report.isLoadingReportActions !== this.props.report.isLoadingReportActions) {

Seems like it can probably be removed.

@bondydaa
Copy link
Contributor

bondydaa commented Apr 7, 2023

should we also cross-out workspace chat when remove user from workspace offline?

Hmm I didn't considered that scenario initially.

I think let's try to keep the scope of this PR small and only focused on the AddMembersToWorkspace API method since I'm assuming the removing of a user is a different API command? We can spin up a new issue to ensure the offline behavior for removing a workspace member is handled properly.

@0xmiros
Copy link
Contributor

0xmiros commented Apr 7, 2023

BUG: multiple workspace chats are created for the same user

@bondydaa are you able to reproduce this one?

@bondydaa
Copy link
Contributor

bondydaa commented Apr 7, 2023

I didn't see more than 1 when I tested yesterday on desktop but let me try again. Did you only add 1 member while offline? Or multiple? I think I tested adding 2 users but not just a single user so I'll try both.

@0xmiros
Copy link
Contributor

0xmiros commented Apr 7, 2023

I didn't see more than 1 when I tested yesterday on desktop but let me try again. Did you only add 1 member while offline? Or multiple? I think I tested adding 2 users but not just a single user so I'll try both.

I tried only one. Please try to repeat adding/removing the same user.

@bondydaa
Copy link
Contributor

bondydaa commented Apr 7, 2023

Hmm yeah I am seeing some weird things when you remove the user while offline.

Steps are like:

  1. Go offline
  2. add new member to workspace, see optimistic report added to LHN
  3. remove user from workspace, optimistic report stays in LHN
  4. Go online
  5. optimistic report in LHN becomes "real chat", if you open that chat it then disappears from LHN and you see it's archived.

Though I think this is related more to removing a user vs adding a user so I think we handle that in the follow up GH for DeleteMembersFromWorkspace API command

@robertKozik
Copy link
Contributor Author

robertKozik commented Apr 7, 2023

@0xmiroslav @bondydaa I came up with quicker fix, as after removing the user chat remains as archived. We can look for this report and just change it's status to open as API will return it's ID as new chat. What you think about such an approach?

edit: @bondydaa I was testing it with following steps:

  1. Go offline
  2. add new member to workspace, see optimistic report added to LHN
  3. Go online
  4. Optimistic chat is replaced with real one
  5. remove user from workspace, optimistic report stays in LHN
  6. Go offline
  7. Add member simmilar to the one from step 1

I came across one more problem though @bondydaa . Now we are passing only the reportID and It's merging into one as it should. But as we are not passing the created report action ID, when user clicks the created chat after coming back online we have double welcome notice. I think we should also pass the reportActionID as it is done when creating normal chat
Here are steps to repo this:

  1. Go offline
  2. Invite new member to workspace (optimistic creation of report is doing fine)
  3. Go online
  4. click on created chat and wait for the data to come from server

@bondydaa
Copy link
Contributor

bondydaa commented Apr 7, 2023

I created this #17137 for the follow up issue. Let's keep adding reproduce steps for things we see related to removing a user from the workspace / DeleteMembersFromWorkspace APi command to that as we come across them.

@bondydaa
Copy link
Contributor

hmm nope still nodda locally for me, let me switch my new dot to staging as well and see if that does it since the workspace name change offline still reverted back.

@0xmiros
Copy link
Contributor

0xmiros commented Apr 26, 2023

@bondydaa please add Ready To Build label. I will test on release build.

@bondydaa
Copy link
Contributor

yeah even against staging I'm still seeing the optimistic Expense Policy Chats being created.

2023-04-26_17-01-00.mp4

@bondydaa
Copy link
Contributor

okay kicked off a build for this, workflow is here https://github.com/Expensify/App/actions/runs/4814233404. I guess a QR code should show up in like an hour or so?

@0xmiros
Copy link
Contributor

0xmiros commented Apr 26, 2023

okay kicked off a build for this, workflow is here https://github.com/Expensify/App/actions/runs/4814233404. I guess a QR code should show up in like an hour or so?

QR code should show up in a few hrs. I will test this tomorrow.

@OSBotify
Copy link
Contributor

@0xmiros
Copy link
Contributor

0xmiros commented Apr 27, 2023

All tests well but one issue:
Workspace admin (myself) is not in members list until online

members.mov

@robertKozik
Copy link
Contributor Author

Great catch, fixed 🔧

scree-bug.mov

}

_.each(members, (login) => {
const oldChat = ReportUtils.getChatByParticipantsAndPolicy([sessionEmail, login], policyID);
Copy link
Contributor

Choose a reason for hiding this comment

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

NAB for now since I think workspaces can only allow 1 admin anyways but as we expand to allow multiple admins this will break and only add the admin of the current user.

I think the members variable we pass to this method should have all users on the workspace right? I wonder if we could run something to check if they are a workspace admin and then add them to this array?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

members variable stores only users which are going to be add to the workspace. But we can get the policy members from Onyx store and filter out members to get all admins. The downside is that while being offline there is possibility of not having this info stored, so we would still fallback to the [newMember, ourMail] situation like here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It shouldn't be difficult to implement, so If you think it should support multiple admins already, I'm happy to help

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm I think this is probably better as is for now, if/when we start allowing more than 1 admin on a workspace we can update this code as needed.

Copy link
Contributor

@0xmiros 0xmiros left a comment

Choose a reason for hiding this comment

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

Looks good, tests well on all possible cases except the known workspace name issue on production backend. This is fixed in staging backend.
Anyway, not a blocker for this PR.

workspace.name.mov

@bondydaa bondydaa merged commit ffae56c into Expensify:main Apr 28, 2023
@OSBotify
Copy link
Contributor

🚀 Deployed to staging by https://github.com/bondydaa in version: 1.3.8-4 🚀

platform result
🤖 android 🤖 success ✅
🖥 desktop 🖥 success ✅
🍎 iOS 🍎 success ✅
🕸 web 🕸 success ✅

@OSBotify
Copy link
Contributor

OSBotify commented May 2, 2023

🚀 Deployed to production by https://github.com/marcaaron in version: 1.3.8-8 🚀

platform result
🤖 android 🤖 success ✅
🖥 desktop 🖥 success ✅
🍎 iOS 🍎 success ✅
🕸 web 🕸 success ✅

@bondydaa
Copy link
Contributor

bondydaa commented May 3, 2023

hmm testing this on staging and production right now isn't working anymore 😢

@bondydaa
Copy link
Contributor

bondydaa commented May 3, 2023

I think I remember seeing something about us changing the invite member page so my guess it's involved here.

looking at the the logs
image

@bondydaa
Copy link
Contributor

bondydaa commented May 3, 2023

oh think i might have figured it out, testing more, hold on to your butts

@bondydaa bondydaa mentioned this pull request May 3, 2023
55 tasks
@bondydaa
Copy link
Contributor

bondydaa commented May 3, 2023

yep confirmed, this #15672 broke it.

@roryabraham
Copy link
Contributor

Following up on @bondydaa's comment here, I am seeing that the workspace chats appear to be created optimistically:

image

Then successfully created when coming back online:

image

image

Testing on dev. Let me make sure my Web-E & Auth are up-to-date...

@roryabraham
Copy link
Contributor

Oh, maybe I lied and there was an error set on those chats...

@roryabraham
Copy link
Contributor

Would love it if we could follow-up with some automated tests for this btw... might have prevented it from breaking

@Gonals
Copy link
Contributor

Gonals commented Jun 6, 2024

This PR caused this bug. A user can be part of a workspace's room (if invited), but not part of the workspace. Inviting those users to the workspace would cause an error, as we'd wrongly identify the room as the Workspace chat.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants