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

Migrate tasks to use childManagerAccountID #21781

Merged
merged 11 commits into from
Jul 6, 2023

Conversation

Beamanator
Copy link
Contributor

@Beamanator Beamanator commented Jun 28, 2023

currently holding on https://github.com/Expensify/Web-Expensify/pull/37963

Details

Just starting to use the new accountID property instead of email, in order to limit the emails we're passing around the app. This has been available for a few weeks but forgot to migrate this.

Fixed Issues

$ Part of #19007 (wasn't noticed before)

Tests

Tests related to #19990:

Tests for #19089

  1. Login with Expensifail account
  2. Go to FAB > Assign task
  3. Enter title, description and click on next button
  4. Click on assignee and select any user or enter an email or phone number to select a new user if don't have any user
  5. Click on confirm button to create a new task
  6. Verify that the assigned user displays as mention in the task preview
  7. Edit the title of this task
  8. Logout and login again
  9. Verify that the assigned users still displays as mention in the task preview as well

Tests for #19959

  1. Go to App and Click on + icon
  2. Select Assign task option
  3. Create a new task
  4. Go to settings > logout
  5. Login again
  6. Verify that the task name is created in above display

Tests for #19967

  1. Go to any chat
  2. Click on + icon and select Assign task option
  3. Enter title and description
  4. Click on Next button
  5. Click on confirm task button
  6. click on title
  7. Edit task title
  8. Go back to previous report screen
  9. Verify that Task title is updated

Make sure this still works (from this recent PR):

  1. Go to any chat (1:1 & group at least)
  2. Click + button in composer
  3. Click Assign task
  4. Input a title => Click next
  5. Verify that by default the "share somewhere" is in that chat, and will not set an assignee by default and no error message
  6. Click Confirm task.
  7. Verify that the task is created with no assignee & it doesn't show an empty avatar
  • Verify that no errors appear in the JS console

Offline tests

Same as above

QA Steps

Same as above

  • 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 the left part of a conditional rendering a React component is a boolean and NOT a string, e.g. myBool && <MyComponent />.
    • 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 grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is 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 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 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 Screenshot 2023-06-29 at 3 14 23 PM
Mobile Web - Chrome
Mobile Web - Safari
Desktop Screenshot 2023-06-29 at 3 17 50 PM
iOS
Android

Screenshot 2023-06-29 at 3 24 32 PM

@Beamanator Beamanator requested a review from a team as a code owner June 28, 2023 10:52
@Beamanator Beamanator self-assigned this Jun 28, 2023
@Beamanator Beamanator changed the title Migrate tasks to use childManagerAccountID [HOLD Web-E#37963] Migrate tasks to use childManagerAccountID Jun 28, 2023
@melvin-bot melvin-bot bot requested review from MariaHCD and removed request for a team June 28, 2023 10:53
@melvin-bot
Copy link

melvin-bot bot commented Jun 28, 2023

@MariaHCD 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]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Noticed this needed to be updated, maybe it belongs in a different PR? 🤷

Copy link
Contributor

Choose a reason for hiding this comment

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

What's this file change for? I don't see any lint issue in latest main

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You can see I'm just including extra prop types / default prop types that were missing. We used withCurrentUserPersonalDetails already, but didn't declare the prop types.

@Beamanator
Copy link
Contributor Author

Updated test steps & added screenshots - I thinkkkkk we could get a C+ to help test this, once the web-e PR is on staging :D

@Beamanator Beamanator changed the title [HOLD Web-E#37963] Migrate tasks to use childManagerAccountID Migrate tasks to use childManagerAccountID Jul 3, 2023
@Beamanator
Copy link
Contributor Author

No longer on hold since https://github.com/Expensify/Web-Expensify/pull/37963 is on prod!

@Beamanator
Copy link
Contributor Author

feel free to get a C+ to help review if you'd like!

also cc @puneetlath in case you're free to review

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.

does this instance need to be removed as well?

reportAction.reportAction.childManagerEmail = taskAssignee;

@Beamanator Beamanator requested a review from bondydaa July 4, 2023 12:49
@Beamanator
Copy link
Contributor Author

Beamanator commented Jul 4, 2023

Thanks @bondydaa , good find 🤦 ready again for review

bondydaa
bondydaa previously approved these changes Jul 5, 2023
@bondydaa
Copy link
Contributor

bondydaa commented Jul 5, 2023

asked in contributor plus to get someone to test and do the checklist for us.

@bondydaa bondydaa requested a review from 0xmiros July 5, 2023 14:41
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.

Bug (regression): task assignee not displaying in TaskPreview

Repro step:
Assign task to any random user (not in contact list) in any DM chat

Before:

before.mov

After:

after.mov

Copy link
Contributor

Choose a reason for hiding this comment

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

What's this file change for? I don't see any lint issue in latest main

@@ -59,7 +65,8 @@ function TaskPreview(props) {
? props.taskReport.stateNum === CONST.REPORT.STATE_NUM.SUBMITTED && props.taskReport.statusNum === CONST.REPORT.STATUS.APPROVED
: props.action.childStateNum === CONST.REPORT.STATE_NUM.SUBMITTED && props.action.childStatusNum === CONST.REPORT.STATUS.APPROVED;
const taskTitle = props.taskReport.reportName || props.action.childReportName;
const taskAssignee = props.taskReport.managerEmail || props.action.childManagerEmail;
const taskAssigneeAccountID = TaskUtils.getTaskAssigneeAccountID(props.taskReport);
Copy link
Contributor

Choose a reason for hiding this comment

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

props.action already has childManagerAccountID. Is there any problem using it directly?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think so - but since we were defaulting to managerEmail first, I thought it would be best if we default to managerID first as well, THEN use childManagerAccountID - and that logic exists in this function so I thought it would be better to reuse it, do you disagree?

Copy link
Contributor

Choose a reason for hiding this comment

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

ok agree. But as I reported, we should fallback to original logic if report.managerID or action.childManagerAccountID doesn't exist.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

"original logic" being props.taskReport.managerEmail || props.action.childManagerEmail;? We're trying to get rid of those :D

@Beamanator
Copy link
Contributor Author

Checking that regression you mentioned @0xmiroslav 👍

@puneetlath
Copy link
Contributor

Hm yeah that's interesting. We're going to migrate mentions to be accountID-based but it's just not quite done yet. So whatever we do for now will be temporary. I think we can just do whatever is easiest.

@Beamanator
Copy link
Contributor Author

Beamanator commented Jul 6, 2023

Awesome, then I will probably just switch to defaulting by displayName for now 👍

Mmmm nevermind I think it makes the most sense to keep defaulting to email (login), and if that doesn't exist we go for displayName

@Beamanator
Copy link
Contributor Author

@0xmiroslav ready for re-review please 🙏

@0xmiros
Copy link
Contributor

0xmiros commented Jul 6, 2023

Mmmm nevermind I think it makes the most sense to keep defaulting to email (login), and if that doesn't exist we go for displayName

What happens if both don't exist? as we faced the crash yesterday?

@Beamanator
Copy link
Contributor Author

Beamanator commented Jul 6, 2023

@0xmiroslav if neither exist then htmlForTaskPreview will just be <comment>${taskTitle}</comment>, no?

The crash you mentioned was what, the actorEmail issue?

@0xmiros
Copy link
Contributor

0xmiros commented Jul 6, 2023

@0xmiroslav if neither exist then htmlForTaskPreview will just be <comment>${taskTitle}</comment>, no?

correct. Just to confirm that this is temporary and won't be considered as regression. As production app shows email correctly.

The crash you mentioned was what, the actorEmail issue?

correct. It's not exact same case but similar. I just provided example.

@Beamanator
Copy link
Contributor Author

@0xmiroslav if neither exist then htmlForTaskPreview will just be <comment>${taskTitle}</comment>, no?

correct. Just to confirm that this is temporary and won't be considered as regression. As production app shows email correctly.

Correct, it's not a regression, it's more of a "new status quo" - we expect you to not have the user's login in these cases so it makes sense to default to their display name "for now"

The crash you mentioned was what, the actorEmail issue?

correct. It's not exact same case but similar. I just provided example.

Ok cool, that issue was due to not testing after merging & there being a bug introduced - this is a different situation. If it tests well now (including the new expected state mentioned above), we're good to go

@0xmiros
Copy link
Contributor

0xmiros commented Jul 6, 2023

Ok cool, that issue was due to not testing after merging & there being a bug introduced - this is a different situation

Oh I meant this crash - #21874 (comment)
You fixed it by adding || '' -> login || displayName || ''

@Beamanator
Copy link
Contributor Author

Aah right that one!! This PR should default to '' so shouldn't crash 👍 I believe your latest tests (assigning a brand new account) prove that

@0xmiros
Copy link
Contributor

0xmiros commented Jul 6, 2023

After logout and login, default avatar changes to empty avatar: (I confirmed that this happens on main so not a blocker)

Screenshot 2023-07-06 at 4 05 16 PM Screenshot 2023-07-06 at 4 06 02 PM

@0xmiros
Copy link
Contributor

0xmiros commented Jul 6, 2023

Reviewer Checklist

  • I have verified the author checklist is complete (all boxes are checked off).
  • I verified the correct issue is linked in the ### Fixed Issues section above
  • I verified testing steps are clear and they cover the changes made in this PR
    • I verified the steps for local testing are in the Tests section
    • I verified the steps for Staging and/or Production testing are in the QA steps section
    • I verified the steps cover any possible 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 checked that screenshots or videos are included for tests on all platforms
  • I included screenshots or videos for tests on all platforms
  • I verified tests pass on all platforms & I tested again on:
    • Android / native
    • Android / Chrome
    • iOS / native
    • iOS / Safari
    • MacOS / Chrome / Safari
    • MacOS / Desktop
  • If there are any errors in the console that are unrelated to this PR, I either fixed them (preferred) or linked to where I reported them in Slack
  • I verified proper code patterns were followed (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 the left part of a conditional rendering a React component is a boolean and NOT a string, e.g. myBool && <MyComponent />.
    • 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
    • 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 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 verified that this PR follows the guidelines as stated in the Review Guidelines
  • I verified other components that can be impacted by these changes have been tested, and I retested again (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar have been tested & I retested again)
  • 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
  • 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 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 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 reviewer checklist, including those that don't apply to this PR.

Screenshots/Videos

Web Screenshot 2023-07-06 at 3 58 06 PM Screenshot 2023-07-06 at 3 58 22 PM
Screen.Recording.2023-07-06.at.4.03.51.PM.mov
Mobile Web - Chrome
Mobile Web - Safari
Desktop
Screen.Recording.2023-07-06.at.4.01.28.PM.mov
iOS
Android

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.

LGTM!

@melvin-bot melvin-bot bot requested a review from yuwenmemon July 6, 2023 14:13
@melvin-bot
Copy link

melvin-bot bot commented Jul 6, 2023

@yuwenmemon 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]

@Beamanator Beamanator removed the request for review from yuwenmemon July 6, 2023 14:29
@@ -65,7 +66,7 @@ function TaskPreview(props) {
: props.action.childStateNum === CONST.REPORT.STATE_NUM.SUBMITTED && props.action.childStatusNum === CONST.REPORT.STATUS.APPROVED;
const taskTitle = props.taskReport.reportName || props.action.childReportName;
const taskAssigneeAccountID = TaskUtils.getTaskAssigneeAccountID(props.taskReport);
const taskAssignee = lodashGet(props.personalDetailsList, [taskAssigneeAccountID, 'login'], '');
const taskAssignee = lodashGet(props.personalDetailsList, [taskAssigneeAccountID, 'login'], lodashGet(props.personalDetailsList, [taskAssigneeAccountID, 'displayName'], ''));
Copy link
Contributor

Choose a reason for hiding this comment

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

personally not crazy about this nested lodash, would rather see something like:

Suggested change
const taskAssignee = lodashGet(props.personalDetailsList, [taskAssigneeAccountID, 'login'], lodashGet(props.personalDetailsList, [taskAssigneeAccountID, 'displayName'], ''));
const assigneeLogin = lodashGet(props.personalDetailsList, [taskAssigneeAccountID, 'login'], '');
const assigneeDisplayName = lodashGet(props.personalDetailsList, [taskAssigneeAccountID, 'displayName'], '');
const taskAssignee = assigneeLogin || assigneeDisplayName;

as it's more clear to me that displayName is a fall back if we don't have a login. instead of trying to reason how the 2nd lodashGet might get called and be a fallback for the first call.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ooh that's totally fair - I'll try to remember to clean this up later - i can see it being useful but not highest priority at the moment

Copy link
Contributor

Choose a reason for hiding this comment

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

Cleanup PR here: #22439

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.

NAB from me but if you want to clean it up then bonus points 😂

@puneetlath
Copy link
Contributor

Going to go ahead and merge given the urgency and since Alex is off for the day. Feel free to handle that in follow-up if you're so-inclined @Beamanator!

@puneetlath puneetlath merged commit 34b792a into main Jul 6, 2023
@puneetlath puneetlath deleted the beaman-migrateToChildManagerAccountID branch July 6, 2023 15:57
@OSBotify
Copy link
Contributor

OSBotify commented Jul 6, 2023

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@OSBotify
Copy link
Contributor

OSBotify commented Jul 7, 2023

🚀 Deployed to staging by https://github.com/puneetlath in version: 1.3.38-0 🚀

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

@OSBotify
Copy link
Contributor

🚀 Deployed to production by https://github.com/francoisl in version: 1.3.38-7 🚀

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

@@ -59,7 +65,8 @@ function TaskPreview(props) {
? props.taskReport.stateNum === CONST.REPORT.STATE_NUM.SUBMITTED && props.taskReport.statusNum === CONST.REPORT.STATUS.APPROVED
: props.action.childStateNum === CONST.REPORT.STATE_NUM.SUBMITTED && props.action.childStatusNum === CONST.REPORT.STATUS.APPROVED;
const taskTitle = props.taskReport.reportName || props.action.childReportName;
const taskAssignee = props.taskReport.managerEmail || props.action.childManagerEmail;
const taskAssigneeAccountID = TaskUtils.getTaskAssigneeAccountID(props.taskReport);
Copy link
Collaborator

Choose a reason for hiding this comment

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

We didn't consider the case where the taskReport could be empty and hence it caused a regression here, because the task assignment didn't show an email address.

Copy link
Contributor Author

@Beamanator Beamanator Jul 31, 2023

Choose a reason for hiding this comment

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

hmm if task report could be empty, would this have crashed before too? 🤔 (since we used to directly access props.taskReport.managerEmail)

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.

6 participants