From 630dc6e1c26659f7d3b04e51ea18c0739759323f Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Wed, 25 Jan 2023 18:22:13 -0800 Subject: [PATCH 1/7] Show Domain Rooms to Domains that have at least one Approved! Accountant --- src/libs/ReportUtils.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index cf7cee7d5872..a840a21e3840 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -65,6 +65,13 @@ Onyx.connect({ callback: val => allReports = val, }); +let domainHasApprovedAccountant; +Onyx.connect({ + key: ONYXKEYS.ACCOUNT, + waitForCollectionCallback: true, + callback: val => domainHasApprovedAccountant = val.domainHasApprovedAccountant, +}); + function getChatType(report) { return report ? report.chatType : ''; } @@ -1179,6 +1186,11 @@ function shouldReportBeInOptionList(report, reportIDFromRoute, isInGSDMode, curr return true; } + // Include domain rooms for accounts that are on a domain with an Approved Accountant + if (isDomainRoom(report) && domainHasApprovedAccountant) { + return true; + } + // Include default rooms unless you're on the default room beta, unless you have an assigned guide if (isDefaultRoom(report) && !Permissions.canUseDefaultRooms(betas) && !hasExpensifyGuidesEmails(lodashGet(report, ['participants'], []))) { return false; From 86d4ca9126b40eb908c6965ed3f1f48edfd30fdf Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Thu, 26 Jan 2023 19:08:49 -0800 Subject: [PATCH 2/7] Make sure that we have an Expensify email in the domain room if we're going to show it --- src/libs/ReportUtils.js | 20 +++++++++++++++----- src/pages/DetailsPage.js | 2 +- src/pages/home/HeaderView.js | 2 +- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index a840a21e3840..5f87ca112274 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -65,11 +65,11 @@ Onyx.connect({ callback: val => allReports = val, }); -let domainHasApprovedAccountant; +let doesDomainHaveApprovedAccountant; Onyx.connect({ key: ONYXKEYS.ACCOUNT, waitForCollectionCallback: true, - callback: val => domainHasApprovedAccountant = val.domainHasApprovedAccountant, + callback: val => doesDomainHaveApprovedAccountant = val.doesDomainHaveApprovedAccountant, }); function getChatType(report) { @@ -376,10 +376,19 @@ function chatIncludesConcierge(report) { * @param {Array} emails * @returns {Boolean} */ -function hasExpensifyEmails(emails) { +function hasAutomatedExpensifyEmails(emails) { return _.intersection(emails, CONST.EXPENSIFY_EMAILS).length > 0; } +/** + * Returns true if there are any Expensify accounts (i.e. with domain 'expensify.com') in the set of emails. + * + * @param emails + */ +function hasExpensifyEmails(emails) { + return _.some(emails, email => Str.extractEmailDomain(email) === CONST.EXPENSIFY_PARTNER_NAME); +} + /** * Whether the time row should be shown for a report. * @param {Array} personalDetails @@ -1186,8 +1195,8 @@ function shouldReportBeInOptionList(report, reportIDFromRoute, isInGSDMode, curr return true; } - // Include domain rooms for accounts that are on a domain with an Approved Accountant - if (isDomainRoom(report) && domainHasApprovedAccountant) { + // Include domain rooms with Partner Managers (Expensify accounts) in them for accounts that are on a domain with an Approved Accountant + if (isDomainRoom(report) && doesDomainHaveApprovedAccountant && hasExpensifyEmails(lodashGet(report, ['participants'], []))) { return true; } @@ -1281,6 +1290,7 @@ export { getPolicyType, isArchivedRoom, isConciergeChatReport, + hasAutomatedExpensifyEmails, hasExpensifyEmails, hasExpensifyGuidesEmails, hasOutstandingIOU, diff --git a/src/pages/DetailsPage.js b/src/pages/DetailsPage.js index 0b97bfa89c16..1423efa37416 100755 --- a/src/pages/DetailsPage.js +++ b/src/pages/DetailsPage.js @@ -96,7 +96,7 @@ class DetailsPage extends React.PureComponent { // If we have a reportID param this means that we // arrived here via the ParticipantsPage and should be allowed to navigate back to it const shouldShowBackButton = Boolean(this.props.route.params.reportID); - const shouldShowLocalTime = !ReportUtils.hasExpensifyEmails([details.login]) && details.timezone; + const shouldShowLocalTime = !ReportUtils.hasAutomatedExpensifyEmails([details.login]) && details.timezone; let pronouns = details.pronouns; if (pronouns && pronouns.startsWith(CONST.PRONOUNS.PREFIX)) { diff --git a/src/pages/home/HeaderView.js b/src/pages/home/HeaderView.js index 6dd7b24046a7..c8bfe7eb6806 100644 --- a/src/pages/home/HeaderView.js +++ b/src/pages/home/HeaderView.js @@ -65,7 +65,7 @@ const HeaderView = (props) => { const subtitle = ReportUtils.getChatRoomSubtitle(props.report, props.policies); const isConcierge = participants.length === 1 && _.contains(participants, CONST.EMAIL.CONCIERGE); - const isAutomatedExpensifyAccount = (participants.length === 1 && ReportUtils.hasExpensifyEmails(participants)); + const isAutomatedExpensifyAccount = (participants.length === 1 && ReportUtils.hasAutomatedExpensifyEmails(participants)); // We hide the button when we are chatting with an automated Expensify account since it's not possible to contact // these users via alternative means. It is possible to request a call with Concierge so we leave the option for them. From 9b8be1c7e334ddae973bab34c805c618d12a087b Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Tue, 31 Jan 2023 12:41:24 -0800 Subject: [PATCH 3/7] Add JSDoc --- src/libs/ReportUtils.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index d00ee69fd8ef..58be120c702d 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -383,7 +383,8 @@ function hasAutomatedExpensifyEmails(emails) { /** * Returns true if there are any Expensify accounts (i.e. with domain 'expensify.com') in the set of emails. * - * @param emails + * @param {Array} emails + * @return {Boolean} */ function hasExpensifyEmails(emails) { return _.some(emails, email => Str.extractEmailDomain(email) === CONST.EXPENSIFY_PARTNER_NAME); From 33df6e37faf4907e0046246d00e99ddb4fc22f57 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Tue, 31 Jan 2023 15:02:51 -0800 Subject: [PATCH 4/7] Remove unneeded export --- src/libs/ReportUtils.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 58be120c702d..812ad89d108e 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1292,7 +1292,6 @@ export { isArchivedRoom, isConciergeChatReport, hasAutomatedExpensifyEmails, - hasExpensifyEmails, hasExpensifyGuidesEmails, hasOutstandingIOU, isIOUOwnedByCurrentUser, From 5ba35e136ed6903ea08eb62896bf3562713c6cd0 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Tue, 31 Jan 2023 18:36:15 -0800 Subject: [PATCH 5/7] DRY up code around default room permissions --- src/libs/ReportUtils.js | 34 ++++++++++++++++++++++------------ src/pages/home/ReportScreen.js | 11 +---------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 812ad89d108e..b986672738d5 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1137,6 +1137,26 @@ function isIOUOwnedByCurrentUser(report, currentUserLogin, iouReports = {}) { return false; } +function canSeeDefaultRoom(report, policies, betas) { + // Include default rooms for free plan policies (domain rooms aren't included in here because they do not belong to a policy) + if (getPolicyType(report, policies) === CONST.POLICY.TYPE.FREE) { + return true; + } + + // Include domain rooms with Partner Managers (Expensify accounts) in them for accounts that are on a domain with an Approved Accountant + if (isDomainRoom(report) && doesDomainHaveApprovedAccountant && hasExpensifyEmails(lodashGet(report, ['participants'], []))) { + return true; + } + + // If the room has an assigned guide, it can be seen. + if (hasExpensifyGuidesEmails(lodashGet(report, ['participants'], []))) { + return true; + } + + // For all other cases, just check that the user belongs to the default rooms beta + return Permissions.canUseDefaultRooms(betas); +} + /** * Takes several pieces of data from Onyx and evaluates if a report should be shown in the option list (either when searching * for reports or the reports shown in the LHN). @@ -1191,18 +1211,7 @@ function shouldReportBeInOptionList(report, reportIDFromRoute, isInGSDMode, curr return true; } - // Include default rooms for free plan policies - if (isDefaultRoom(report) && getPolicyType(report, policies) === CONST.POLICY.TYPE.FREE) { - return true; - } - - // Include domain rooms with Partner Managers (Expensify accounts) in them for accounts that are on a domain with an Approved Accountant - if (isDomainRoom(report) && doesDomainHaveApprovedAccountant && hasExpensifyEmails(lodashGet(report, ['participants'], []))) { - return true; - } - - // Include default rooms unless you're on the default room beta, unless you have an assigned guide - if (isDefaultRoom(report) && !Permissions.canUseDefaultRooms(betas) && !hasExpensifyGuidesEmails(lodashGet(report, ['participants'], []))) { + if (isDefaultRoom(report) && !canSeeDefaultRoom(report, policies, betas)) { return false; } @@ -1324,4 +1333,5 @@ export { isIOUReport, chatIncludesChronos, getNewMarkerReportActionID, + canSeeDefaultRoom, }; diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index d544d78a65e0..1be75b3e1d90 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -192,16 +192,7 @@ class ReportScreen extends React.Component { return null; } - // We create policy rooms for all policies, however we don't show them unless - // - It's a free plan workspace - // - The report includes guides participants (@team.expensify.com) for 1:1 Assigned - // - It's an archived room - if (!Permissions.canUseDefaultRooms(this.props.betas) - && ReportUtils.isDefaultRoom(this.props.report) - && ReportUtils.getPolicyType(this.props.report, this.props.policies) !== CONST.POLICY.TYPE.FREE - && !ReportUtils.hasExpensifyGuidesEmails(lodashGet(this.props.report, ['participants'], [])) - && !ReportUtils.isArchivedRoom(this.props.report) - ) { + if (ReportUtils.isDefaultRoom(this.props.report) && !ReportUtils.canSeeDefaultRoom(this.props.report, this.props.policies, this.props.betas)) { return null; } From 439d37a100e0610fff8fbfc95c951ff463d65d0b Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Wed, 1 Feb 2023 09:00:14 -0800 Subject: [PATCH 6/7] Add doc and update archived room case --- src/libs/ReportUtils.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index b986672738d5..2cae47d47761 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1137,7 +1137,21 @@ function isIOUOwnedByCurrentUser(report, currentUserLogin, iouReports = {}) { return false; } +/** + * Assuming the passed in report is a default room, lets us know whether we can see it or not, based on permissions and + * the various subsets of users we've allowed to use default rooms. + * + * @param {Object} report + * @param {Array} policies + * @param {Array>} betas + * @return {Boolean|boolean} + */ function canSeeDefaultRoom(report, policies, betas) { + // Include archived rooms + if (isArchivedRoom(report)) { + return true; + } + // Include default rooms for free plan policies (domain rooms aren't included in here because they do not belong to a policy) if (getPolicyType(report, policies) === CONST.POLICY.TYPE.FREE) { return true; From e15397d64f1a72f8f2d399a4c4d745c5a9d7089f Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Wed, 1 Feb 2023 09:18:57 -0800 Subject: [PATCH 7/7] JS Linting --- src/libs/ReportUtils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 2cae47d47761..cd7f67b22bf7 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1143,8 +1143,8 @@ function isIOUOwnedByCurrentUser(report, currentUserLogin, iouReports = {}) { * * @param {Object} report * @param {Array} policies - * @param {Array>} betas - * @return {Boolean|boolean} + * @param {Array} betas + * @return {Boolean} */ function canSeeDefaultRoom(report, policies, betas) { // Include archived rooms