From 7f4f51245d96b0184b717aa36883e21d23835397 Mon Sep 17 00:00:00 2001 From: bartektomczyk Date: Thu, 21 Mar 2024 12:00:57 +0100 Subject: [PATCH 01/38] feat: added component for displaying static message inm onboarding --- src/languages/en.ts | 10 ++ src/languages/es.ts | 10 ++ .../report/OnboardingReportFooterMessage.tsx | 92 +++++++++++++++++++ src/styles/index.ts | 4 + 4 files changed, 116 insertions(+) create mode 100644 src/pages/home/report/OnboardingReportFooterMessage.tsx diff --git a/src/languages/en.ts b/src/languages/en.ts index 3b670f7b6ebc..138b28260060 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -2665,6 +2665,16 @@ export default { welcomeMessage: 'Welcome to Expensify', welcomeSubtitle: 'What would you like to do?', }, + onboardingBottomMessage: { + [CONST.INTRO_CHOICES.MANAGE_TEAM]: { + phrase1: 'Chat with your setup specialist in ', + phrase2: ' for help', + }, + default: { + phrase1: 'Message ', + phrase2: ' for help with setup', + }, + }, manageTeams: { [CONST.MANAGE_TEAMS_CHOICE.MULTI_LEVEL]: 'Multi level approval', [CONST.MANAGE_TEAMS_CHOICE.CUSTOM_EXPENSE]: 'Custom expense coding', diff --git a/src/languages/es.ts b/src/languages/es.ts index 5027174b2922..0799aefac37d 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -3158,6 +3158,16 @@ export default { welcomeMessage: 'Bienvenido a Expensify', welcomeSubtitle: '¿Qué te gustaría hacer?', }, + onboardingBottomMessage: { + [CONST.INTRO_CHOICES.MANAGE_TEAM]: { + phrase1: 'Chat with your setup specialist in ', + phrase2: ' for help', + }, + default: { + phrase1: 'Message ', + phrase2: ' for help with setup', + }, + }, manageTeams: { [CONST.MANAGE_TEAMS_CHOICE.MULTI_LEVEL]: 'Aprobación multinivel', [CONST.MANAGE_TEAMS_CHOICE.CUSTOM_EXPENSE]: 'Codificación personalizada de gastos', diff --git a/src/pages/home/report/OnboardingReportFooterMessage.tsx b/src/pages/home/report/OnboardingReportFooterMessage.tsx new file mode 100644 index 000000000000..a48a609b51a7 --- /dev/null +++ b/src/pages/home/report/OnboardingReportFooterMessage.tsx @@ -0,0 +1,92 @@ +import React, {useMemo} from 'react'; +import {View} from 'react-native'; +import {withOnyx} from 'react-native-onyx'; +import type {OnyxCollection} from 'react-native-onyx'; +import type {ValueOf} from 'type-fest'; +import Text from '@components/Text'; +import TextLink from '@components/TextLink'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import useWindowDimensions from '@hooks/useWindowDimensions'; +import * as PolicyUtils from '@libs/PolicyUtils'; +import Navigation from '@navigation/Navigation'; +import * as ReportInstance from '@userActions/Report'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; +import type {Policy as PolicyType, Report} from '@src/types/onyx'; + +type OnboardingReportFooterMessageOnyxProps = {reports: OnyxCollection; policies: OnyxCollection}; +type OnboardingReportFooterMessageProps = OnboardingReportFooterMessageOnyxProps & {choice: ValueOf}; + +function OnboardingReportFooterMessage({choice, reports, policies}: OnboardingReportFooterMessageProps) { + const {translate} = useLocalize(); + const styles = useThemeStyles(); + const {isSmallScreenWidth} = useWindowDimensions(); + + const adminChatReport = useMemo(() => { + const adminsReports = reports ? Object.values(reports).filter((report) => report?.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ADMINS) : []; + const activePolicies = policies ? Object.values(policies).filter((policy) => PolicyUtils.shouldShowPolicy(policy, false)) : []; + + return adminsReports.find((report) => activePolicies.find((policy) => policy?.id === report?.policyID)); + }, [policies, reports]); + + const content = useMemo(() => { + switch (choice) { + case CONST.INTRO_CHOICES.MANAGE_TEAM: + return ( + <> + {`${translate('onboardingBottomMessage.newDotManageTeam.phrase1')}`} + Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(adminChatReport?.reportID ?? ''))} + > + {adminChatReport?.reportName ?? CONST.REPORT.WORKSPACE_CHAT_ROOMS.ADMINS} + + {`${translate('onboardingBottomMessage.newDotManageTeam.phrase2')}`} + + ); + default: + return ( + <> + {`${translate('onboardingBottomMessage.default.phrase1')}`} + ReportInstance.navigateToConciergeChat()} + > + {`${CONST?.CONCIERGE_CHAT_NAME}`} + + {`${translate('onboardingBottomMessage.default.phrase2')}`} + + ); + } + }, [adminChatReport?.reportName, adminChatReport?.reportID, choice, styles.label, translate]); + + return ( + + {content} + + ); +} +OnboardingReportFooterMessage.displayName = 'OnboardingReportFooterMessage'; +export default withOnyx({ + reports: { + key: ONYXKEYS.COLLECTION.REPORT, + }, + policies: { + key: ONYXKEYS.COLLECTION.POLICY, + }, +})(OnboardingReportFooterMessage); diff --git a/src/styles/index.ts b/src/styles/index.ts index f165974119ff..27178157f9f5 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -525,6 +525,10 @@ const styles = (theme: ThemeColors) => borderRadius: variables.buttonBorderRadius, }, + borderRadiusComponentLarge: { + borderRadius: variables.componentBorderRadiusLarge, + }, + bottomTabBarContainer: { flexDirection: 'row', height: variables.bottomTabHeight, From 26bcce68b747dde6bf8c26f73b5207d708004782 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Wed, 17 Apr 2024 16:00:02 +0200 Subject: [PATCH 02/38] add permissions to report --- src/CONST.ts | 6 ++++++ src/types/onyx/Report.ts | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/CONST.ts b/src/CONST.ts index 2b85bcb2c326..425391f6ebea 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -837,6 +837,12 @@ const CONST = { OWNER_EMAIL_FAKE: '__FAKE__', OWNER_ACCOUNT_ID_FAKE: 0, DEFAULT_REPORT_NAME: 'Chat Report', + PERMISSIONS: { + READ: 'read', + WRITE: 'write', + SHARE: 'share', + OWN: 'own', + } }, NEXT_STEP: { FINISHED: 'Finished!', diff --git a/src/types/onyx/Report.ts b/src/types/onyx/Report.ts index fe3eec6dc11e..36d345b1084c 100644 --- a/src/types/onyx/Report.ts +++ b/src/types/onyx/Report.ts @@ -186,6 +186,8 @@ type Report = OnyxCommon.OnyxValueWithOfflineFeedback< transactionThreadReportID?: string; fieldList?: Record; + + permissions?: Array>; }, PolicyReportField['fieldID'] >; From de29862ae77c1cd6b5fd2fa03fc8e0443ed133ed Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Wed, 17 Apr 2024 16:01:28 +0200 Subject: [PATCH 03/38] create isReadOnly --- src/libs/ReportUtils.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 39964bfcc4d7..6b9ef9031cf0 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -5989,6 +5989,13 @@ function canReportBeMentionedWithinPolicy(report: OnyxEntry, policyID: s return isChatRoom(report) && !isThread(report); } +/** + * + * Checks if report is in read-only mode. + */ +function isReadOnly(report: OnyxEntry): boolean { + return !report?.permissions?.includes(CONST.REPORT.PERMISSIONS.WRITE) ?? false; +} export { getReportParticipantsTitle, @@ -6228,6 +6235,7 @@ export { buildParticipantsFromAccountIDs, canReportBeMentionedWithinPolicy, getAllHeldTransactions, + isReadOnly, }; export type { From e2ad69dc9610992ac13438b4316c2f2bbe53d1a2 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Wed, 17 Apr 2024 16:08:32 +0200 Subject: [PATCH 04/38] integrate OnboardingReportFooterMessage into ReportFooter --- src/libs/ReportUtils.ts | 17 +++++++++-------- .../report/OnboardingReportFooterMessage.tsx | 11 +++++++---- src/pages/home/report/ReportFooter.tsx | 6 ++++++ 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 6b9ef9031cf0..e20686e1326a 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -5198,6 +5198,14 @@ function isMoneyRequestReportPendingDeletion(report: OnyxEntry | EmptyOb return parentReportAction?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; } +/** + * + * Checks if report is in read-only mode. + */ +function isReadOnly(report: OnyxEntry): boolean { + return !report?.permissions?.includes(CONST.REPORT.PERMISSIONS.WRITE) ?? false; +} + function canUserPerformWriteAction(report: OnyxEntry) { const reportErrors = getAddWorkspaceRoomOrChatReportErrors(report); @@ -5206,7 +5214,7 @@ function canUserPerformWriteAction(report: OnyxEntry) { return false; } - return !isArchivedRoom(report) && isEmptyObject(reportErrors) && report && isAllowedToComment(report) && !isAnonymousUser; + return !isArchivedRoom(report) && isEmptyObject(reportErrors) && report && isAllowedToComment(report) && !isAnonymousUser && !isReadOnly(report); } /** @@ -5989,13 +5997,6 @@ function canReportBeMentionedWithinPolicy(report: OnyxEntry, policyID: s return isChatRoom(report) && !isThread(report); } -/** - * - * Checks if report is in read-only mode. - */ -function isReadOnly(report: OnyxEntry): boolean { - return !report?.permissions?.includes(CONST.REPORT.PERMISSIONS.WRITE) ?? false; -} export { getReportParticipantsTitle, diff --git a/src/pages/home/report/OnboardingReportFooterMessage.tsx b/src/pages/home/report/OnboardingReportFooterMessage.tsx index a48a609b51a7..f6c91d3b9f12 100644 --- a/src/pages/home/report/OnboardingReportFooterMessage.tsx +++ b/src/pages/home/report/OnboardingReportFooterMessage.tsx @@ -1,8 +1,7 @@ import React, {useMemo} from 'react'; import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; -import type {OnyxCollection} from 'react-native-onyx'; -import type {ValueOf} from 'type-fest'; +import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import Text from '@components/Text'; import TextLink from '@components/TextLink'; import useLocalize from '@hooks/useLocalize'; @@ -16,8 +15,9 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {Policy as PolicyType, Report} from '@src/types/onyx'; -type OnboardingReportFooterMessageOnyxProps = {reports: OnyxCollection; policies: OnyxCollection}; -type OnboardingReportFooterMessageProps = OnboardingReportFooterMessageOnyxProps & {choice: ValueOf}; +// TODO: Use a proper choice type +type OnboardingReportFooterMessageOnyxProps = {choice: OnyxEntry; reports: OnyxCollection; policies: OnyxCollection}; +type OnboardingReportFooterMessageProps = OnboardingReportFooterMessageOnyxProps; function OnboardingReportFooterMessage({choice, reports, policies}: OnboardingReportFooterMessageProps) { const {translate} = useLocalize(); @@ -83,6 +83,9 @@ function OnboardingReportFooterMessage({choice, reports, policies}: OnboardingRe } OnboardingReportFooterMessage.displayName = 'OnboardingReportFooterMessage'; export default withOnyx({ + choice: { + key: ONYXKEYS.ONBOARDING_PURPOSE_SELECTED, + }, reports: { key: ONYXKEYS.COLLECTION.REPORT, }, diff --git a/src/pages/home/report/ReportFooter.tsx b/src/pages/home/report/ReportFooter.tsx index bd143f9ef196..bccec0597fb0 100644 --- a/src/pages/home/report/ReportFooter.tsx +++ b/src/pages/home/report/ReportFooter.tsx @@ -20,6 +20,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import type * as OnyxTypes from '@src/types/onyx'; import type {PendingAction} from '@src/types/onyx/OnyxCommon'; import type {EmptyObject} from '@src/types/utils/EmptyObject'; +import OnboardingReportFooterMessage from './OnboardingReportFooterMessage'; import ReportActionCompose from './ReportActionCompose/ReportActionCompose'; type ReportFooterOnyxProps = { @@ -81,6 +82,7 @@ function ReportFooter({ const isSmallSizeLayout = windowWidth - (isSmallScreenWidth ? 0 : variables.sideBarWidth) < variables.anonymousReportFooterBreakpoint; const hideComposer = !ReportUtils.canUserPerformWriteAction(report); + const isReadOnlyReport = ReportUtils.isReadOnly(report); const allPersonalDetails = usePersonalDetails(); @@ -125,6 +127,10 @@ function ReportFooter({ [report.reportID, handleCreateTask], ); + if (isReadOnlyReport) { + ; + } + return ( <> {hideComposer && ( From 471a02adff994ef218ec3128614a92534fa7f6c4 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Wed, 17 Apr 2024 16:09:13 +0200 Subject: [PATCH 05/38] prettify --- src/pages/home/report/OnboardingReportFooterMessage.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pages/home/report/OnboardingReportFooterMessage.tsx b/src/pages/home/report/OnboardingReportFooterMessage.tsx index f6c91d3b9f12..54659c14cf6e 100644 --- a/src/pages/home/report/OnboardingReportFooterMessage.tsx +++ b/src/pages/home/report/OnboardingReportFooterMessage.tsx @@ -81,7 +81,9 @@ function OnboardingReportFooterMessage({choice, reports, policies}: OnboardingRe ); } + OnboardingReportFooterMessage.displayName = 'OnboardingReportFooterMessage'; + export default withOnyx({ choice: { key: ONYXKEYS.ONBOARDING_PURPOSE_SELECTED, From b4aed0fa5eb550664687f06008359fc21bb881c3 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Wed, 17 Apr 2024 16:10:17 +0200 Subject: [PATCH 06/38] restrict task action in header --- src/components/TaskHeaderActionButton.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/TaskHeaderActionButton.tsx b/src/components/TaskHeaderActionButton.tsx index 2d964f58c253..a7e3abcd3012 100644 --- a/src/components/TaskHeaderActionButton.tsx +++ b/src/components/TaskHeaderActionButton.tsx @@ -25,6 +25,10 @@ function TaskHeaderActionButton({report, session}: TaskHeaderActionButtonProps) const {translate} = useLocalize(); const styles = useThemeStyles(); + if (ReportUtils.isReadOnly(report)) { + return null; + } + return (