From 6fd67693a9f9deba02474c2351b5eda2a230bdba Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Wed, 21 Feb 2024 15:11:03 +0700 Subject: [PATCH 001/565] Add policy avatar --- src/libs/ReportUtils.ts | 10 +++++----- src/pages/home/ReportScreen.js | 2 ++ src/types/onyx/Report.ts | 3 +++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 05e2db66d62..413af029862 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -1476,11 +1476,11 @@ function getIconsForParticipants(participants: number[], personalDetails: OnyxCo */ function getWorkspaceIcon(report: OnyxEntry, policy: OnyxEntry = null): Icon { const workspaceName = getPolicyName(report, false, policy); - const rootParentReport = getRootParentReport(report); - const hasCustomAvatar = - !(isEmptyObject(rootParentReport) || isDefaultRoom(rootParentReport) || isChatRoom(rootParentReport) || isArchivedRoom(rootParentReport)) && - allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`]?.avatar; - const policyExpenseChatAvatarSource = hasCustomAvatar ? allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`]?.avatar : getDefaultWorkspaceAvatar(workspaceName); + // disabling to protect against empty strings + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + const policyAvatarURL = report?.policyAvatar || allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`]?.avatar; + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + const policyExpenseChatAvatarSource = policyAvatarURL || getDefaultWorkspaceAvatar(workspaceName); const workspaceIcon: Icon = { source: policyExpenseChatAvatarSource ?? '', diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index 7fba188dced..d6960a2b9e6 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -205,6 +205,7 @@ function ReportScreen({ visibility: reportProp.visibility, oldPolicyName: reportProp.oldPolicyName, policyName: reportProp.policyName, + policyAvatar: reportProp.policyAvatar, isOptimisticReport: reportProp.isOptimisticReport, lastMentionedTime: reportProp.lastMentionedTime, }), @@ -242,6 +243,7 @@ function ReportScreen({ reportProp.visibility, reportProp.oldPolicyName, reportProp.policyName, + reportProp.policyAvatar, reportProp.isOptimisticReport, reportProp.lastMentionedTime, ], diff --git a/src/types/onyx/Report.ts b/src/types/onyx/Report.ts index fbd61a9c536..1b8d026898c 100644 --- a/src/types/onyx/Report.ts +++ b/src/types/onyx/Report.ts @@ -64,6 +64,9 @@ type Report = { /** The current user's notification preference for this report */ notificationPreference?: NotificationPreference; + /** The policy avatar to use, if any */ + policyAvatar?: string | null; + /** The policy name to use */ policyName?: string | null; From 898573b2a9fd8ea40cd795dbcfd801942d3a795d Mon Sep 17 00:00:00 2001 From: dominictb Date: Tue, 6 Aug 2024 17:08:06 +0700 Subject: [PATCH 002/565] fix: update logic to render thread divider in money report view --- .../ReportActionItem/MoneyReportView.tsx | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/components/ReportActionItem/MoneyReportView.tsx b/src/components/ReportActionItem/MoneyReportView.tsx index 7c2e29bd983..0a7f43ba25a 100644 --- a/src/components/ReportActionItem/MoneyReportView.tsx +++ b/src/components/ReportActionItem/MoneyReportView.tsx @@ -10,6 +10,7 @@ import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import SpacerView from '@components/SpacerView'; import Text from '@components/Text'; +import UnreadActionIndicator from '@components/UnreadActionIndicator'; import useLocalize from '@hooks/useLocalize'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; @@ -76,6 +77,22 @@ function MoneyReportView({report, policy, isCombinedReport = false, shouldShowTo const shouldShowReportField = !ReportUtils.isClosedExpenseReportWithNoExpenses(report) && ReportUtils.isPaidGroupPolicyExpenseReport(report) && (!isCombinedReport || !isOnlyTitleFieldEnabled); + const renderThreadDivider = useMemo( + () => + shouldHideThreadDividerLine && !isCombinedReport ? ( + + ) : ( + + ), + [shouldHideThreadDividerLine, report.reportID, styles.reportHorizontalRule, isCombinedReport], + ); + return ( <> @@ -197,12 +214,7 @@ function MoneyReportView({report, policy, isCombinedReport = false, shouldShowTo )} - {(shouldShowReportField || shouldShowBreakdown || shouldShowTotal) && ( - - )} + {(shouldShowReportField || shouldShowBreakdown || shouldShowTotal) && renderThreadDivider} ); } From aed6ba5a688b88a13c2bba1e7cde746be3e8525e Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Wed, 7 Aug 2024 10:12:50 +0700 Subject: [PATCH 003/565] =?UTF-8?q?fix:=20button=20doesn=E2=80=99t=20work?= =?UTF-8?q?=20after=20using=203DS=20flow=20to=20add=20GBP=20payment=20card?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Subscription/CardAuthenticationModal/index.tsx | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/pages/settings/Subscription/CardAuthenticationModal/index.tsx b/src/pages/settings/Subscription/CardAuthenticationModal/index.tsx index 80cde4cb862..c0bde6d9857 100644 --- a/src/pages/settings/Subscription/CardAuthenticationModal/index.tsx +++ b/src/pages/settings/Subscription/CardAuthenticationModal/index.tsx @@ -6,11 +6,9 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Modal from '@components/Modal'; import ScreenWrapper from '@components/ScreenWrapper'; import useThemeStyles from '@hooks/useThemeStyles'; -import Navigation from '@libs/Navigation/Navigation'; import * as PaymentMethods from '@userActions/PaymentMethods'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; type CardAuthenticationModalProps = { /** Title shown in the header of the modal */ @@ -20,21 +18,12 @@ function CardAuthenticationModal({headerTitle}: CardAuthenticationModalProps) { const styles = useThemeStyles(); const [authenticationLink] = useOnyx(ONYXKEYS.VERIFY_3DS_SUBSCRIPTION); const [session] = useOnyx(ONYXKEYS.SESSION); - const [privateStripeCustomerID] = useOnyx(ONYXKEYS.NVP_PRIVATE_STRIPE_CUSTOMER_ID); const [isLoading, setIsLoading] = useState(true); const onModalClose = () => { PaymentMethods.clearPaymentCard3dsVerification(); }; - useEffect(() => { - if (privateStripeCustomerID?.status !== CONST.STRIPE_GBP_AUTH_STATUSES.SUCCEEDED) { - return; - } - PaymentMethods.clearPaymentCard3dsVerification(); - Navigation.navigate(ROUTES.SETTINGS_SUBSCRIPTION); - }, [privateStripeCustomerID]); - const handleGBPAuthentication = useCallback( (event: MessageEvent) => { const message = event.data; From 3ac4099d71fa1b0b2d59a922f5400d36c3d77416 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Thu, 8 Aug 2024 15:55:07 +0800 Subject: [PATCH 004/565] remove the reaction when pressing on the added reaction --- .../Reactions/ReportActionItemEmojiReactions.tsx | 4 ++-- src/libs/actions/Report.ts | 3 ++- src/pages/home/report/ReportActionItem.tsx | 8 ++++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/components/Reactions/ReportActionItemEmojiReactions.tsx b/src/components/Reactions/ReportActionItemEmojiReactions.tsx index c6bf4f9e401..943158607db 100644 --- a/src/components/Reactions/ReportActionItemEmojiReactions.tsx +++ b/src/components/Reactions/ReportActionItemEmojiReactions.tsx @@ -33,7 +33,7 @@ type ReportActionItemEmojiReactionsProps = WithCurrentUserPersonalDetailsProps & * This can also be an emoji the user already reacted with, * hence this function asks to toggle the reaction by emoji. */ - toggleReaction: (emoji: Emoji) => void; + toggleReaction: (emoji: Emoji, ignoreSkinToneOnCompare?: boolean) => void; /** We disable reacting with emojis on report actions that have errors */ shouldBlockReactions?: boolean; @@ -107,7 +107,7 @@ function ReportActionItemEmojiReactions({ totalReactionCount += reactionCount; const onPress = () => { - toggleReaction(emoji); + toggleReaction(emoji, true); }; const onReactionListOpen = (event: ReactionListEvent) => { diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index ca489b92326..dc0d44535c8 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -2549,6 +2549,7 @@ function toggleEmojiReaction( reactionObject: Emoji, existingReactions: OnyxEntry, paramSkinTone: number = preferredSkinTone, + ignoreSkinToneOnCompare = false, ) { const originalReportID = ReportUtils.getOriginalReportID(reportID, reportAction); @@ -2570,7 +2571,7 @@ function toggleEmojiReaction( // Only use skin tone if emoji supports it const skinTone = emoji.types === undefined ? -1 : paramSkinTone; - if (existingReactionObject && EmojiUtils.hasAccountIDEmojiReacted(currentUserAccountID, existingReactionObject.users, skinTone)) { + if (existingReactionObject && EmojiUtils.hasAccountIDEmojiReacted(currentUserAccountID, existingReactionObject.users, ignoreSkinToneOnCompare ? undefined : skinTone)) { removeEmojiReaction(originalReportID, reportAction.reportActionID, emoji); return; } diff --git a/src/pages/home/report/ReportActionItem.tsx b/src/pages/home/report/ReportActionItem.tsx index 68ced63d12d..0799e257d42 100644 --- a/src/pages/home/report/ReportActionItem.tsx +++ b/src/pages/home/report/ReportActionItem.tsx @@ -380,8 +380,8 @@ function ReportActionItem({ }, [index, originalMessage, prevActionResolution, reportScrollManager, isActionableWhisper]); const toggleReaction = useCallback( - (emoji: Emoji) => { - Report.toggleEmojiReaction(report.reportID, action, emoji, emojiReactions); + (emoji: Emoji, ignoreSkinToneOnCompare?: boolean) => { + Report.toggleEmojiReaction(report.reportID, action, emoji, emojiReactions, undefined, ignoreSkinToneOnCompare); }, [report, action, emojiReactions], ); @@ -749,7 +749,7 @@ function ReportActionItem({ reportAction={action} emojiReactions={emojiReactions} shouldBlockReactions={hasErrors} - toggleReaction={(emoji) => { + toggleReaction={(emoji, ignoreSkinToneOnCompare) => { if (Session.isAnonymousUser()) { hideContextMenu(false); @@ -757,7 +757,7 @@ function ReportActionItem({ Session.signOutAndRedirectToSignIn(); }); } else { - toggleReaction(emoji); + toggleReaction(emoji, ignoreSkinToneOnCompare); } }} setIsEmojiPickerActive={setIsEmojiPickerActive} From 5dc06468b26be3f112d64bf300caae8caa649817 Mon Sep 17 00:00:00 2001 From: Mateusz Titz Date: Thu, 8 Aug 2024 16:17:03 +0200 Subject: [PATCH 005/565] Add policyID to search grammar --- src/libs/SearchParser/searchParser.js | 66 +++++++++++++++--------- src/libs/SearchParser/searchParser.peggy | 1 + 2 files changed, 43 insertions(+), 24 deletions(-) diff --git a/src/libs/SearchParser/searchParser.js b/src/libs/SearchParser/searchParser.js index 53d0ac82bec..91923cd50d2 100644 --- a/src/libs/SearchParser/searchParser.js +++ b/src/libs/SearchParser/searchParser.js @@ -199,7 +199,8 @@ function peg$parse(input, options) { var peg$c21 = "keyword"; var peg$c22 = "sortBy"; var peg$c23 = "sortOrder"; - var peg$c24 = "\""; + var peg$c24 = "policyID"; + var peg$c25 = "\""; var peg$r0 = /^[:=]/; var peg$r1 = /^[^"\r\n]/; @@ -231,11 +232,12 @@ function peg$parse(input, options) { var peg$e22 = peg$literalExpectation("keyword", false); var peg$e23 = peg$literalExpectation("sortBy", false); var peg$e24 = peg$literalExpectation("sortOrder", false); - var peg$e25 = peg$literalExpectation("\"", false); - var peg$e26 = peg$classExpectation(["\"", "\r", "\n"], true, false); - var peg$e27 = peg$classExpectation([["A", "Z"], ["a", "z"], ["0", "9"], "_", "@", ".", "/", "#", "&", "+", "-", "\\", "'", ","], false, false); - var peg$e28 = peg$otherExpectation("whitespace"); - var peg$e29 = peg$classExpectation([" ", "\t", "\r", "\n"], false, false); + var peg$e25 = peg$literalExpectation("policyID", false); + var peg$e26 = peg$literalExpectation("\"", false); + var peg$e27 = peg$classExpectation(["\"", "\r", "\n"], true, false); + var peg$e28 = peg$classExpectation([["A", "Z"], ["a", "z"], ["0", "9"], "_", "@", ".", "/", "#", "&", "+", "-", "\\", "'", ","], false, false); + var peg$e29 = peg$otherExpectation("whitespace"); + var peg$e30 = peg$classExpectation([" ", "\t", "\r", "\n"], false, false); var peg$f0 = function(filters) { return applyDefaults(filters); }; var peg$f1 = function(head, tail) { @@ -285,10 +287,11 @@ function peg$parse(input, options) { var peg$f25 = function() { return "keyword"; }; var peg$f26 = function() { return "sortBy"; }; var peg$f27 = function() { return "sortOrder"; }; - var peg$f28 = function(parts) { return parts.join(''); }; - var peg$f29 = function(chars) { return chars.join(''); }; + var peg$f28 = function() { return "policyID"; }; + var peg$f29 = function(parts) { return parts.join(''); }; var peg$f30 = function(chars) { return chars.join(''); }; - var peg$f31 = function() { return "and"; }; + var peg$f31 = function(chars) { return chars.join(''); }; + var peg$f32 = function() { return "and"; }; var peg$currPos = options.peg$currPos | 0; var peg$savedPos = peg$currPos; var peg$posDetailsCache = [{ line: 1, column: 1 }]; @@ -897,6 +900,21 @@ function peg$parse(input, options) { s1 = peg$f27(); } s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 8) === peg$c24) { + s1 = peg$c24; + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e25); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f28(); + } + s0 = s1; + } } } } @@ -941,7 +959,7 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f28(s1); + s1 = peg$f29(s1); } s0 = s1; @@ -953,11 +971,11 @@ function peg$parse(input, options) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 34) { - s1 = peg$c24; + s1 = peg$c25; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e25); } + if (peg$silentFails === 0) { peg$fail(peg$e26); } } if (s1 !== peg$FAILED) { s2 = []; @@ -966,7 +984,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e26); } + if (peg$silentFails === 0) { peg$fail(peg$e27); } } while (s3 !== peg$FAILED) { s2.push(s3); @@ -975,19 +993,19 @@ function peg$parse(input, options) { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e26); } + if (peg$silentFails === 0) { peg$fail(peg$e27); } } } if (input.charCodeAt(peg$currPos) === 34) { - s3 = peg$c24; + s3 = peg$c25; peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e25); } + if (peg$silentFails === 0) { peg$fail(peg$e26); } } if (s3 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f29(s2); + s0 = peg$f30(s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1010,7 +1028,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e27); } + if (peg$silentFails === 0) { peg$fail(peg$e28); } } if (s2 !== peg$FAILED) { while (s2 !== peg$FAILED) { @@ -1020,7 +1038,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e27); } + if (peg$silentFails === 0) { peg$fail(peg$e28); } } } } else { @@ -1028,7 +1046,7 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f30(s1); + s1 = peg$f31(s1); } s0 = s1; @@ -1041,7 +1059,7 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = peg$parse_(); peg$savedPos = s0; - s1 = peg$f31(); + s1 = peg$f32(); s0 = s1; return s0; @@ -1057,7 +1075,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e29); } + if (peg$silentFails === 0) { peg$fail(peg$e30); } } while (s1 !== peg$FAILED) { s0.push(s1); @@ -1066,12 +1084,12 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e29); } + if (peg$silentFails === 0) { peg$fail(peg$e30); } } } peg$silentFails--; s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e28); } + if (peg$silentFails === 0) { peg$fail(peg$e29); } return s0; } diff --git a/src/libs/SearchParser/searchParser.peggy b/src/libs/SearchParser/searchParser.peggy index 310e942bbb8..d13adcfd265 100644 --- a/src/libs/SearchParser/searchParser.peggy +++ b/src/libs/SearchParser/searchParser.peggy @@ -100,6 +100,7 @@ key / "keyword" { return "keyword"; } / "sortBy" { return "sortBy"; } / "sortOrder" { return "sortOrder"; } + / "policyID" { return "policyID"; } identifier = parts:(quotedString / alphanumeric)+ { return parts.join(''); } From df18001ea7c45206318ea9004979c7934ffa5b54 Mon Sep 17 00:00:00 2001 From: Wojciech Boman Date: Thu, 8 Aug 2024 16:58:30 +0200 Subject: [PATCH 006/565] Add todo comments --- src/CONST.ts | 1 + src/ROUTES.ts | 3 +-- src/components/Search/SearchPageHeader.tsx | 1 + src/components/Search/index.tsx | 5 ++--- src/libs/API/parameters/Search.ts | 2 -- src/libs/Navigation/linkTo/index.ts | 2 ++ .../Navigation/linkingConfig/extractPolicyIDsFromState.ts | 1 + src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts | 1 + src/libs/Navigation/switchPolicyID.ts | 4 ++-- src/libs/Navigation/types.ts | 3 +-- src/libs/actions/Search.ts | 4 ++-- 11 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index eaae7b82ef7..87c837721c2 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -5324,6 +5324,7 @@ const CONST = { CARD_ID: 'cardID', REPORT_ID: 'reportID', KEYWORD: 'keyword', + POLICY_ID: 'policyID', }, }, diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 27f565929c5..af1224d666d 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -35,8 +35,7 @@ const ROUTES = { SEARCH_CENTRAL_PANE: { route: 'search', - getRoute: ({query, isCustomQuery = false, policyIDs}: {query: SearchQueryString; isCustomQuery?: boolean; policyIDs?: string}) => - `search?q=${query}&isCustomQuery=${isCustomQuery}${policyIDs ? `&policyIDs=${policyIDs}` : ''}` as const, + getRoute: ({query, isCustomQuery = false}: {query: SearchQueryString; isCustomQuery?: boolean}) => `search?q=${query}&isCustomQuery=${isCustomQuery}` as const, }, SEARCH_ADVANCED_FILTERS: 'search/filters', diff --git a/src/components/Search/SearchPageHeader.tsx b/src/components/Search/SearchPageHeader.tsx index 039526923b3..fd8ff41173b 100644 --- a/src/components/Search/SearchPageHeader.tsx +++ b/src/components/Search/SearchPageHeader.tsx @@ -112,6 +112,7 @@ function SearchPageHeader({queryJSON, hash, onSelectDeleteOption, setOfflineModa const theme = useTheme(); const styles = useThemeStyles(); const {isOffline} = useNetwork(); + // @TODO: Obtain the policyID from queryJSON const {activeWorkspaceID} = useActiveWorkspace(); const {isSmallScreenWidth} = useResponsiveLayout(); const {selectedTransactions, clearSelectedTransactions} = useSearchContext(); diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index 7283a36e9f5..1c003e19b46 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -36,7 +36,6 @@ import type {SearchColumnType, SearchQueryJSON, SearchStatus, SelectedTransactio type SearchProps = { queryJSON: SearchQueryJSON; isCustomQuery: boolean; - policyIDs?: string; }; const transactionItemMobileHeight = 100; @@ -73,7 +72,7 @@ function prepareTransactionsList(item: TransactionListItemType, selectedTransact return {...selectedTransactions, [item.keyForList]: {isSelected: true, canDelete: item.canDelete, canHold: item.canHold, canUnhold: item.canUnhold, action: item.action}}; } -function Search({queryJSON, policyIDs, isCustomQuery}: SearchProps) { +function Search({queryJSON, isCustomQuery}: SearchProps) { const {isOffline} = useNetwork(); const {translate} = useLocalize(); const styles = useThemeStyles(); @@ -115,7 +114,7 @@ function Search({queryJSON, policyIDs, isCustomQuery}: SearchProps) { return; } - SearchActions.search({queryJSON, offset, policyIDs}); + SearchActions.search({queryJSON, offset}); // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps }, [isOffline, offset, queryJSON]); diff --git a/src/libs/API/parameters/Search.ts b/src/libs/API/parameters/Search.ts index 530388dc7f4..64bfc5baf5a 100644 --- a/src/libs/API/parameters/Search.ts +++ b/src/libs/API/parameters/Search.ts @@ -3,8 +3,6 @@ import type {SearchQueryString} from '@components/Search/types'; type SearchParams = { hash: number; jsonQuery: SearchQueryString; - // Tod this is temporary, remove top level policyIDs as part of: https://github.com/Expensify/App/issues/46592 - policyIDs?: string; }; export default SearchParams; diff --git a/src/libs/Navigation/linkTo/index.ts b/src/libs/Navigation/linkTo/index.ts index d5a72db3a30..8bda6107fe5 100644 --- a/src/libs/Navigation/linkTo/index.ts +++ b/src/libs/Navigation/linkTo/index.ts @@ -49,6 +49,7 @@ export default function linkTo(navigation: NavigationContainerRef>; // Creating path with /w/ included if necessary. const topmostCentralPaneRoute = getTopmostCentralPaneRoute(rootState); + // @TODO Here check if policyID exists in q param instead of reading it from policyIDs, rename this variable const policyIDs = !!topmostCentralPaneRoute?.params && 'policyIDs' in topmostCentralPaneRoute.params ? (topmostCentralPaneRoute?.params?.policyIDs as string) : ''; const extractedPolicyID = extractPolicyIDFromPath(`/${path}`); const policyIDFromState = getPolicyIDFromState(rootState); @@ -117,6 +118,7 @@ export default function linkTo(navigation: NavigationContainerRef).policyIDs = policyID; } diff --git a/src/libs/Navigation/linkingConfig/extractPolicyIDsFromState.ts b/src/libs/Navigation/linkingConfig/extractPolicyIDsFromState.ts index fdaf7e6eb49..2dc099ba869 100644 --- a/src/libs/Navigation/linkingConfig/extractPolicyIDsFromState.ts +++ b/src/libs/Navigation/linkingConfig/extractPolicyIDsFromState.ts @@ -3,6 +3,7 @@ import {findFocusedRoute} from '@react-navigation/native'; import SCREENS from '@src/SCREENS'; function extractPolicyIDsFromState(state: InitialState) { + // @TODO Try extracting policyID from q param, if there are multiple then return undefined const focusedRoute = findFocusedRoute(state); if (focusedRoute && focusedRoute.name === SCREENS.SEARCH.CENTRAL_PANE && focusedRoute.params && 'policyIDs' in focusedRoute.params) { return focusedRoute.params.policyIDs as string; diff --git a/src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts b/src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts index 594f76eee2f..0bc3b98b690 100644 --- a/src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts +++ b/src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts @@ -381,6 +381,7 @@ const getAdaptedStateFromPath: GetAdaptedStateFromPath = (path, options) => { } // Only on SCREENS.SEARCH.CENTRAL_PANE policyID is stored differently as "policyIDs" param, so we're handling this case here + // @TODO Modify this method to handle extracting ids from q param const policyIDs = extractPolicyIDsFromState(state); return getAdaptedState(state, policyID ?? policyIDs); diff --git a/src/libs/Navigation/switchPolicyID.ts b/src/libs/Navigation/switchPolicyID.ts index 28de413b090..9ae49b4ff4e 100644 --- a/src/libs/Navigation/switchPolicyID.ts +++ b/src/libs/Navigation/switchPolicyID.ts @@ -19,7 +19,7 @@ type ActionPayloadParams = { path?: string; }; -type CentralPaneRouteParams = Record & {policyID?: string; policyIDs?: string; reportID?: string}; +type CentralPaneRouteParams = Record & {policyID?: string; q?: string; reportID?: string}; function checkIfActionPayloadNameIsEqual(action: Writable, screenName: string) { return action?.payload && 'name' in action.payload && action?.payload?.name === screenName; @@ -108,9 +108,9 @@ export default function switchPolicyID(navigation: NavigationContainerRef & {policyID: string}; + [SCREENS.SEARCH.BOTTOM_TAB]: CentralPaneScreensParamList[typeof SCREENS.SEARCH.CENTRAL_PANE] & {policyID: string}; [SCREENS.SETTINGS.ROOT]: {policyID?: string}; }; diff --git a/src/libs/actions/Search.ts b/src/libs/actions/Search.ts index 040fd6e4749..d4a8fc57ddc 100644 --- a/src/libs/actions/Search.ts +++ b/src/libs/actions/Search.ts @@ -49,7 +49,7 @@ function getOnyxLoadingData(hash: number): {optimisticData: OnyxUpdate[]; finall return {optimisticData, finallyData}; } -function search({queryJSON, offset, policyIDs}: {queryJSON: SearchQueryJSON; offset?: number; policyIDs?: string}) { +function search({queryJSON, offset}: {queryJSON: SearchQueryJSON; offset?: number}) { const {optimisticData, finallyData} = getOnyxLoadingData(queryJSON.hash); const queryWithOffset = { @@ -58,7 +58,7 @@ function search({queryJSON, offset, policyIDs}: {queryJSON: SearchQueryJSON; off }; const jsonQuery = JSON.stringify(queryWithOffset); - API.read(READ_COMMANDS.SEARCH, {hash: queryJSON.hash, jsonQuery, policyIDs}, {optimisticData, finallyData}); + API.read(READ_COMMANDS.SEARCH, {hash: queryJSON.hash, jsonQuery}, {optimisticData, finallyData}); } /** From beb2a92e577bba046b2f09551639113ad6189644 Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Fri, 9 Aug 2024 19:15:33 +0200 Subject: [PATCH 007/565] feat: [WIP] updateSettlementFrequency and updateSettlementAccount --- .../UpdateCardSettlementAccountParams.ts | 6 + .../UpdateCardSettlementFrequencyParams.ts | 9 + src/libs/API/parameters/index.ts | 2 + src/libs/API/types.ts | 4 + src/libs/actions/Card.ts | 164 ++++++++---------- .../WorkspaceExpensifyCardBankAccounts.tsx | 8 +- .../WorkspaceSettlementAccountPage.tsx | 14 +- .../WorkspaceSettlementFrequencyPage.tsx | 10 +- src/types/onyx/Policy.ts | 3 + 9 files changed, 121 insertions(+), 99 deletions(-) create mode 100644 src/libs/API/parameters/UpdateCardSettlementAccountParams.ts create mode 100644 src/libs/API/parameters/UpdateCardSettlementFrequencyParams.ts diff --git a/src/libs/API/parameters/UpdateCardSettlementAccountParams.ts b/src/libs/API/parameters/UpdateCardSettlementAccountParams.ts new file mode 100644 index 00000000000..8af37bb9d4c --- /dev/null +++ b/src/libs/API/parameters/UpdateCardSettlementAccountParams.ts @@ -0,0 +1,6 @@ +type UpdateCardSettlementAccountParams = { + domainName: string; + settlementBankAccountID: number; +}; + +export default UpdateCardSettlementAccountParams; diff --git a/src/libs/API/parameters/UpdateCardSettlementFrequencyParams.ts b/src/libs/API/parameters/UpdateCardSettlementFrequencyParams.ts new file mode 100644 index 00000000000..6085713bac9 --- /dev/null +++ b/src/libs/API/parameters/UpdateCardSettlementFrequencyParams.ts @@ -0,0 +1,9 @@ +import type {ValueOf} from 'type-fest'; +import type CONST from '@src/CONST'; + +type UpdateCardSettlementFrequencyParams = { + settlementFrequency: ValueOf; + workspaceAccountID: number; +}; + +export default UpdateCardSettlementFrequencyParams; diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index c89bf660fcd..9a955fd0bd3 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -270,3 +270,5 @@ export type {default as ExportSearchItemsToCSVParams} from './ExportSearchItemsT export type {default as UpdateExpensifyCardLimitParams} from './UpdateExpensifyCardLimitParams'; export type {CreateWorkspaceApprovalParams, UpdateWorkspaceApprovalParams, RemoveWorkspaceApprovalParams} from './WorkspaceApprovalParams'; export type {default as StartIssueNewCardFlowParams} from './StartIssueNewCardFlowParams'; +export type {default as UpdateCardSettlementFrequencyParams} from './UpdateCardSettlementFrequencyParams'; +export type {default as UpdateCardSettlementAccountParams} from './UpdateCardSettlementAccountParams'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 57350bf6de1..ac0ab098d23 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -325,6 +325,8 @@ const WRITE_COMMANDS = { CREATE_WORKSPACE_APPROVAL: 'CreateWorkspaceApproval', UPDATE_WORKSPACE_APPROVAL: 'UpdateWorkspaceApproval', REMOVE_WORKSPACE_APPROVAL: 'RemoveWorkspaceApproval', + UPDATE_CARD_SETTLEMENT_FREQUENCY: 'UpdateCardSettlementFrequency', + UPDATE_CARD_SETTLEMENT_ACCOUNT: 'UpdateCardSettlementAccount', } as const; type WriteCommand = ValueOf; @@ -656,6 +658,8 @@ type WriteCommandParameters = { [WRITE_COMMANDS.CREATE_WORKSPACE_APPROVAL]: Parameters.CreateWorkspaceApprovalParams; [WRITE_COMMANDS.UPDATE_WORKSPACE_APPROVAL]: Parameters.UpdateWorkspaceApprovalParams; [WRITE_COMMANDS.REMOVE_WORKSPACE_APPROVAL]: Parameters.RemoveWorkspaceApprovalParams; + [WRITE_COMMANDS.UPDATE_CARD_SETTLEMENT_FREQUENCY]: Parameters.UpdateCardSettlementFrequencyParams; + [WRITE_COMMANDS.UPDATE_CARD_SETTLEMENT_ACCOUNT]: Parameters.UpdateCardSettlementAccountParams; }; const READ_COMMANDS = { diff --git a/src/libs/actions/Card.ts b/src/libs/actions/Card.ts index 205a8dc41bb..414fbd1ffe4 100644 --- a/src/libs/actions/Card.ts +++ b/src/libs/actions/Card.ts @@ -206,100 +206,84 @@ function revealVirtualCardDetails(cardID: number): Promise }); } -function updateSettlementFrequency(policyID: string, frequency: ValueOf) { - // TODO: remove this code when the API is ready - if (frequency === CONST.EXPENSIFY_CARD.FREQUENCY_SETTING.DAILY) { - Onyx.merge(`${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_EXPENSIFY_CARD_SETTINGS}${policyID}`, { - monthlySettlementDate: null, - }); - } else { - Onyx.merge(`${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_EXPENSIFY_CARD_SETTINGS}${policyID}`, { - monthlySettlementDate: new Date(), - }); - } +function updateSettlementFrequency(workspaceAccountID: number, settlementFrequency: ValueOf) { + const monthlySettlementDate = settlementFrequency === CONST.EXPENSIFY_CARD.FREQUENCY_SETTING.DAILY ? null : new Date(); + + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_EXPENSIFY_CARD_SETTINGS}${workspaceAccountID}`, + value: { + monthlySettlementDate, + }, + }, + ]; + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_EXPENSIFY_CARD_SETTINGS}${workspaceAccountID}`, + value: { + monthlySettlementDate, + }, + }, + ]; + + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_EXPENSIFY_CARD_SETTINGS}${workspaceAccountID}`, + value: { + monthlySettlementDate: null, + }, + }, + ]; + + const parameters = { + workspaceAccountID, + settlementFrequency, + }; - // TODO: uncomment this code when the API is ready - // const optimisticData: OnyxUpdate[] = [ - // { - // onyxMethod: Onyx.METHOD.MERGE, - // key: `${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_EXPENSIFY_CARD_SETTINGS}${policyID}`, - // value: { - // monthlySettlementDate: '', - // }, - // }, - // ]; - // - // const successData: OnyxUpdate[] = [ - // { - // onyxMethod: Onyx.METHOD.MERGE, - // key: `${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_EXPENSIFY_CARD_SETTINGS}${policyID}`, - // value: { - // monthlySettlementDate: '', - // }, - // }, - // ]; - // - // const failureData: OnyxUpdate[] = [ - // { - // onyxMethod: Onyx.METHOD.MERGE, - // key: `${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_EXPENSIFY_CARD_SETTINGS}${policyID}`, - // value: { - // monthlySettlementDate: null, - // }, - // }, - // ]; - // - // const parameters = { - // workspaceAccountID: policyID, - // settlementFrequency: frequency, - // }; - // - // API.write(WRITE_COMMANDS.UPDATE_CARD_SETTLEMENT_FREQUENCY, parameters, {optimisticData, successData, failureData}); + API.write(WRITE_COMMANDS.UPDATE_CARD_SETTLEMENT_FREQUENCY, parameters, {optimisticData, successData, failureData}); } -function updateSettlementAccount(policyID: string, accountID: number) { - // TODO: remove this code when the API is ready - Onyx.merge(`${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_EXPENSIFY_CARD_SETTINGS}${policyID}`, { - paymentBankAccountID: accountID, - }); +function updateSettlementAccount(workspaceAccountID: number, domainName: string, settlementBankAccountID: number) { + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_EXPENSIFY_CARD_SETTINGS}${workspaceAccountID}`, + value: { + paymentBankAccountID: settlementBankAccountID, + }, + }, + ]; + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_EXPENSIFY_CARD_SETTINGS}${workspaceAccountID}`, + value: { + paymentBankAccountID: settlementBankAccountID, + }, + }, + ]; + + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_EXPENSIFY_CARD_SETTINGS}${workspaceAccountID}`, + value: { + paymentBankAccountID: null, + }, + }, + ]; + + const parameters = { + domainName, + settlementBankAccountID, + }; - // TODO: uncomment this code when the API is ready - // const optimisticData: OnyxUpdate[] = [ - // { - // onyxMethod: Onyx.METHOD.MERGE, - // key: `${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_EXPENSIFY_CARD_SETTINGS}${policyID}`, - // value: { - // paymentBankAccountID: accountID, - // }, - // }, - // ]; - // - // const successData: OnyxUpdate[] = [ - // { - // onyxMethod: Onyx.METHOD.MERGE, - // key: `${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_EXPENSIFY_CARD_SETTINGS}${policyID}`, - // value: { - // paymentBankAccountID: accountID, - // }, - // }, - // ]; - // - // const failureData: OnyxUpdate[] = [ - // { - // onyxMethod: Onyx.METHOD.MERGE, - // key: `${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_EXPENSIFY_CARD_SETTINGS}${policyID}`, - // value: { - // paymentBankAccountID: null, - // }, - // }, - // ]; - // - // const parameters = { - // workspaceAccountID: policyID, - // settlementBankAccountID: accountID, - // }; - // - // API.write(WRITE_COMMANDS.UPDATE_CARD_SETTLEMENT_ACCOUNT, parameters, {optimisticData, successData, failureData}); + API.write(WRITE_COMMANDS.UPDATE_CARD_SETTLEMENT_ACCOUNT, parameters, {optimisticData, successData, failureData}); } function setIssueNewCardStepAndData({data, isEditing, step}: IssueNewCardFlowData) { diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx index 470b2c683e7..52e2a1348fa 100644 --- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx +++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx @@ -30,13 +30,19 @@ function WorkspaceExpensifyCardBankAccounts({route}: WorkspaceExpensifyCardBankA const policyID = route?.params?.policyID ?? '-1'; + // TODO: change for getWorkspaceAccountID + const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`); + + const workspaceAccountID = policy?.workspaceAccountID ?? 0; + const handleAddBankAccount = () => { // TODO: call to API - UpdateCardSettlementAccount Navigation.navigate(ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute('new', policyID, ROUTES.WORKSPACE_EXPENSIFY_CARD.getRoute(policyID))); }; const handleSelectBankAccount = (value: number) => { - Card.updateSettlementAccount(policyID, value); + // TODO: policy domainName + Card.updateSettlementAccount(workspaceAccountID, '', value); Navigation.navigate(ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW.getRoute(policyID)); }; diff --git a/src/pages/workspace/expensifyCard/WorkspaceSettlementAccountPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceSettlementAccountPage.tsx index cea951dec45..fdb41131980 100644 --- a/src/pages/workspace/expensifyCard/WorkspaceSettlementAccountPage.tsx +++ b/src/pages/workspace/expensifyCard/WorkspaceSettlementAccountPage.tsx @@ -31,10 +31,15 @@ function WorkspaceSettlementAccountPage({route}: WorkspaceSettlementAccountPageP const styles = useThemeStyles(); const {translate} = useLocalize(); const policyID = route.params?.policyID ?? '-1'; + // TODO: change for getWorkspaceAccountID + const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`); + + const workspaceAccountID = policy?.workspaceAccountID ?? 0; + const [bankAccountsList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST); - const [cardSettings] = useOnyx(`${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_EXPENSIFY_CARD_SETTINGS}${policyID}`); - const [isUsedContinuousReconciliation] = useOnyx(`${ONYXKEYS.COLLECTION.SHARED_NVP_EXPENSIFY_CARD_USE_CONTINUOUS_RECONCILIATION}${policyID}`); - const [reconciliationConnection] = useOnyx(`${ONYXKEYS.COLLECTION.SHARED_NVP_EXPENSIFY_CARD_CONTINUOUS_RECONCILIATION_CONNECTION}${policyID}`); + const [cardSettings] = useOnyx(`${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_EXPENSIFY_CARD_SETTINGS}${workspaceAccountID}`); + const [isUsedContinuousReconciliation] = useOnyx(`${ONYXKEYS.COLLECTION.SHARED_NVP_EXPENSIFY_CARD_USE_CONTINUOUS_RECONCILIATION}${workspaceAccountID}`); + const [reconciliationConnection] = useOnyx(`${ONYXKEYS.COLLECTION.SHARED_NVP_EXPENSIFY_CARD_CONTINUOUS_RECONCILIATION_CONNECTION}${workspaceAccountID}`); const paymentBankAccountID = cardSettings?.paymentBankAccountID ?? ''; const paymentBankAccountNumber = bankAccountsList?.[paymentBankAccountID]?.accountData?.accountNumber ?? ''; @@ -70,7 +75,8 @@ function WorkspaceSettlementAccountPage({route}: WorkspaceSettlementAccountPageP }, [eligibleBankAccounts, paymentBankAccountID, styles, translate]); const updateSettlementAccount = (value: number) => { - Card.updateSettlementAccount(policyID, value); + // TODO: policy domainName + Card.updateSettlementAccount(workspaceAccountID, '', value); Navigation.goBack(); }; diff --git a/src/pages/workspace/expensifyCard/WorkspaceSettlementFrequencyPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceSettlementFrequencyPage.tsx index 2d6b9bcfad5..254b8080d6a 100644 --- a/src/pages/workspace/expensifyCard/WorkspaceSettlementFrequencyPage.tsx +++ b/src/pages/workspace/expensifyCard/WorkspaceSettlementFrequencyPage.tsx @@ -25,10 +25,12 @@ function WorkspaceSettlementFrequencyPage({route}: WorkspaceSettlementFrequencyP const {translate} = useLocalize(); const policyID = route.params?.policyID ?? '-1'; - const [cardSettings] = useOnyx(`${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_EXPENSIFY_CARD_SETTINGS}${policyID}`); + const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`); - // TODO: change true for false after API is ready - true is for testing purposes - const shouldShowMonthlyOption = cardSettings?.isMonthlySettlementAllowed ?? true; + const workspaceAccountID = policy?.workspaceAccountID ?? 0; + const [cardSettings] = useOnyx(`${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_EXPENSIFY_CARD_SETTINGS}${workspaceAccountID}`); + + const shouldShowMonthlyOption = cardSettings?.isMonthlySettlementAllowed ?? false; const selectedFrequency = cardSettings?.monthlySettlementDate ? CONST.EXPENSIFY_CARD.FREQUENCY_SETTING.MONTHLY : CONST.EXPENSIFY_CARD.FREQUENCY_SETTING.DAILY; const data = useMemo(() => { @@ -54,7 +56,7 @@ function WorkspaceSettlementFrequencyPage({route}: WorkspaceSettlementFrequencyP }, [translate, shouldShowMonthlyOption, selectedFrequency]); const updateSettlementFrequency = (value: ValueOf) => { - Card.updateSettlementFrequency(policyID, value); + Card.updateSettlementFrequency(workspaceAccountID, value); }; return ( diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index 9724229361e..b1a20348d04 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -1539,6 +1539,9 @@ type Policy = OnyxCommon.OnyxValueWithOfflineFeedback< /** Whether GL codes are enabled */ glCodes?: boolean; + + /** ID for the Expensify Card */ + workspaceAccountID?: number; } & Partial, 'generalSettings' | 'addWorkspaceRoom' | keyof ACHAccount >; From a23976a681df6e600287bb73bb9bacf058a29eb2 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Sat, 10 Aug 2024 14:42:18 +0800 Subject: [PATCH 008/565] optimistically remove hold when paying --- src/libs/actions/IOU.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index ef5f6d6d61c..c1d55a6afd1 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -6705,6 +6705,29 @@ function getPayMoneyRequestParams( }); } + if (full) { + for (const transaction of TransactionUtils.getAllReportTransactions(iouReport.reportID)) { + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`, + value: { + comment: { + hold: null, + }, + }, + }); + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`, + value: { + comment: { + hold: transaction.comment?.hold, + }, + }, + }); + } + } + let optimisticHoldReportID; let optimisticHoldActionID; let optimisticHoldReportExpenseActionIDs; From a06431bdeb621625be28b74166b0d452caa0ff1b Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Mon, 12 Aug 2024 17:01:43 +0300 Subject: [PATCH 009/565] add delegate access type --- src/types/onyx/Account.ts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/types/onyx/Account.ts b/src/types/onyx/Account.ts index e0f6fb79331..d968204ca78 100644 --- a/src/types/onyx/Account.ts +++ b/src/types/onyx/Account.ts @@ -6,6 +6,24 @@ import type * as OnyxCommon from './OnyxCommon'; /** Two factor authentication steps */ type TwoFactorAuthStep = ValueOf | ''; +/** Model of delegate */ +type Delegate = { + /** The email of the delegate */ + email: string; + + /** The role of the delegate */ + role: 'submitter' | 'all'; +}; + +/** Model of delegated access data */ +type DelegatedAccess = { + /** The the users you can access as a delegate */ + delegates: Delegate[]; + + /** The users that can access your account as a delegate */ + delegators: Delegate[]; +}; + /** Model of user account */ type Account = { /** Whether SAML is enabled for the current account */ @@ -88,6 +106,9 @@ type Account = { /** Indicates whether the user has at least one previous purchase */ hasPurchases?: boolean; + + /** The users you can access as delegate and the users who can access your account as a delegate */ + delegatedAccess: DelegatedAccess; }; export default Account; From 567058b3036f29d9b0b09b39a76f2340357eae31 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Mon, 12 Aug 2024 17:02:03 +0300 Subject: [PATCH 010/565] add auth token for delegate access --- src/types/onyx/Response.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/types/onyx/Response.ts b/src/types/onyx/Response.ts index c2628065225..ef558896c55 100644 --- a/src/types/onyx/Response.ts +++ b/src/types/onyx/Response.ts @@ -41,6 +41,9 @@ type Response = { /** Used to load resources like attachment videos and images */ encryptedAuthToken?: string; + /** User session auth token when connecting as a delegate */ + restrictedToken?: string; + /** Used to pass error messages for error handling purposes */ message?: string; From 40c55fb85ae212b921b9b962238f09e557c18cfa Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Mon, 12 Aug 2024 17:02:20 +0300 Subject: [PATCH 011/565] add connect as delegate action --- .../API/parameters/ConnectAsDelegateParams.ts | 5 ++++ src/libs/API/parameters/index.ts | 1 + src/libs/API/types.ts | 2 ++ src/libs/actions/Delegate.ts | 30 +++++++++++++++++++ 4 files changed, 38 insertions(+) create mode 100644 src/libs/API/parameters/ConnectAsDelegateParams.ts create mode 100644 src/libs/actions/Delegate.ts diff --git a/src/libs/API/parameters/ConnectAsDelegateParams.ts b/src/libs/API/parameters/ConnectAsDelegateParams.ts new file mode 100644 index 00000000000..6bd2c666e1b --- /dev/null +++ b/src/libs/API/parameters/ConnectAsDelegateParams.ts @@ -0,0 +1,5 @@ +type ConnectAsDelegateParams = { + to: string; +}; + +export default ConnectAsDelegateParams; diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index c89bf660fcd..d979332ac80 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -270,3 +270,4 @@ export type {default as ExportSearchItemsToCSVParams} from './ExportSearchItemsT export type {default as UpdateExpensifyCardLimitParams} from './UpdateExpensifyCardLimitParams'; export type {CreateWorkspaceApprovalParams, UpdateWorkspaceApprovalParams, RemoveWorkspaceApprovalParams} from './WorkspaceApprovalParams'; export type {default as StartIssueNewCardFlowParams} from './StartIssueNewCardFlowParams'; +export type {default as ConnectAsDelegateParams} from './ConnectAsDelegateParams'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 57350bf6de1..dc05a9b2b51 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -781,6 +781,7 @@ const SIDE_EFFECT_REQUEST_COMMANDS = { REVEAL_EXPENSIFY_CARD_DETAILS: 'RevealExpensifyCardDetails', SWITCH_TO_OLD_DOT: 'SwitchToOldDot', TWO_FACTOR_AUTH_VALIDATE: 'TwoFactorAuth_Validate', + CONNECT_AS_DELEGATE: 'ConnectAsDelegate', } as const; type SideEffectRequestCommand = ValueOf; @@ -797,6 +798,7 @@ type SideEffectRequestCommandParameters = { [SIDE_EFFECT_REQUEST_COMMANDS.ADD_PAYMENT_CARD_GBP]: Parameters.AddPaymentCardParams; [SIDE_EFFECT_REQUEST_COMMANDS.ACCEPT_SPOTNANA_TERMS]: null; [SIDE_EFFECT_REQUEST_COMMANDS.TWO_FACTOR_AUTH_VALIDATE]: Parameters.ValidateTwoFactorAuthParams; + [SIDE_EFFECT_REQUEST_COMMANDS.CONNECT_AS_DELEGATE]: Parameters.ConnectAsDelegateParams; }; type ApiRequestCommandParameters = WriteCommandParameters & ReadCommandParameters & SideEffectRequestCommandParameters; diff --git a/src/libs/actions/Delegate.ts b/src/libs/actions/Delegate.ts new file mode 100644 index 00000000000..3ed22552bec --- /dev/null +++ b/src/libs/actions/Delegate.ts @@ -0,0 +1,30 @@ +import Onyx from 'react-native-onyx'; +import * as API from '@libs/API'; +import {SIDE_EFFECT_REQUEST_COMMANDS} from '@libs/API/types'; +import * as NetworkStore from '@libs/Network/NetworkStore'; +import * as SequentialQueue from '@libs/Network/SequentialQueue'; +import {KEYS_TO_PRESERVE, openApp} from './App'; +import updateSessionAuthTokens from './Session/updateSessionAuthTokens'; + +function connect(email: string) { + // eslint-disable-next-line rulesdir/no-api-side-effects-method + API.makeRequestWithSideEffects(SIDE_EFFECT_REQUEST_COMMANDS.CONNECT_AS_DELEGATE, {to: email}, {}) + .then((response) => { + return SequentialQueue.waitForIdle() + .then(() => Onyx.clear(KEYS_TO_PRESERVE)) + .then(() => { + // Update authToken in Onyx and in our local variables so that API requests will use the new authToken + updateSessionAuthTokens(response?.restrictedToken, response?.encryptedAuthToken); + + NetworkStore.setAuthToken(response?.restrictedToken ?? null); + openApp(); + }); + }) + .catch((error) => { + // Handle any errors that occur during the process + console.error('Error during connect:', error); + }); +} + +// eslint-disable-next-line import/prefer-default-export +export {connect}; From 62ee90577fbabdd222b3274bc72bce30811e4c8f Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Mon, 12 Aug 2024 17:07:47 +0300 Subject: [PATCH 012/565] make delegated access optional --- src/types/onyx/Account.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/onyx/Account.ts b/src/types/onyx/Account.ts index d968204ca78..3f726f9884d 100644 --- a/src/types/onyx/Account.ts +++ b/src/types/onyx/Account.ts @@ -108,7 +108,7 @@ type Account = { hasPurchases?: boolean; /** The users you can access as delegate and the users who can access your account as a delegate */ - delegatedAccess: DelegatedAccess; + delegatedAccess?: DelegatedAccess; }; export default Account; From 3d31f79d9b36057c8e6ea23cec3d5999a77af0f1 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Mon, 12 Aug 2024 17:55:53 +0300 Subject: [PATCH 013/565] rm display name and email --- src/libs/actions/Delegate.ts | 5 ++--- src/pages/settings/InitialSettingsPage.tsx | 14 -------------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/src/libs/actions/Delegate.ts b/src/libs/actions/Delegate.ts index 3ed22552bec..b743b5c77e7 100644 --- a/src/libs/actions/Delegate.ts +++ b/src/libs/actions/Delegate.ts @@ -3,7 +3,7 @@ import * as API from '@libs/API'; import {SIDE_EFFECT_REQUEST_COMMANDS} from '@libs/API/types'; import * as NetworkStore from '@libs/Network/NetworkStore'; import * as SequentialQueue from '@libs/Network/SequentialQueue'; -import {KEYS_TO_PRESERVE, openApp} from './App'; +import {openApp} from './App'; import updateSessionAuthTokens from './Session/updateSessionAuthTokens'; function connect(email: string) { @@ -11,7 +11,7 @@ function connect(email: string) { API.makeRequestWithSideEffects(SIDE_EFFECT_REQUEST_COMMANDS.CONNECT_AS_DELEGATE, {to: email}, {}) .then((response) => { return SequentialQueue.waitForIdle() - .then(() => Onyx.clear(KEYS_TO_PRESERVE)) + .then(() => Onyx.clear()) .then(() => { // Update authToken in Onyx and in our local variables so that API requests will use the new authToken updateSessionAuthTokens(response?.restrictedToken, response?.encryptedAuthToken); @@ -21,7 +21,6 @@ function connect(email: string) { }); }) .catch((error) => { - // Handle any errors that occur during the process console.error('Error during connect:', error); }); } diff --git a/src/pages/settings/InitialSettingsPage.tsx b/src/pages/settings/InitialSettingsPage.tsx index bc98a943263..ecd0b31cf88 100755 --- a/src/pages/settings/InitialSettingsPage.tsx +++ b/src/pages/settings/InitialSettingsPage.tsx @@ -435,20 +435,6 @@ function InitialSettingsPage({session, userWallet, bankAccountList, fundList, wa editIconStyle={styles.smallEditIconAccount} /> - - {currentUserPersonalDetails.displayName ? currentUserPersonalDetails.displayName : formatPhoneNumber(session?.email ?? '')} - - {!!currentUserPersonalDetails.displayName && ( - - {formatPhoneNumber(session?.email ?? '')} - - )} )} From 90a0bc996e6673312afed0c8c6044f71d4f9a290 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Mon, 12 Aug 2024 18:32:35 +0300 Subject: [PATCH 014/565] fix padding bottom style --- src/styles/utils/spacing.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/styles/utils/spacing.ts b/src/styles/utils/spacing.ts index 5b416f5a120..f2f989efc6a 100644 --- a/src/styles/utils/spacing.ts +++ b/src/styles/utils/spacing.ts @@ -377,7 +377,7 @@ export default { padding: 20, }, - pb6: { + p6: { padding: 24, }, @@ -613,6 +613,10 @@ export default { paddingBottom: 20, }, + pb6: { + paddingBottom: 24, + }, + pb8: { paddingBottom: 32, }, From 0a2b2f743cb4abafde736db2ce042d356910c989 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Mon, 12 Aug 2024 18:32:44 +0300 Subject: [PATCH 015/565] fix padding bottom style --- .../accounting/intacct/SageIntacctPrerequisitesPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/accounting/intacct/SageIntacctPrerequisitesPage.tsx b/src/pages/workspace/accounting/intacct/SageIntacctPrerequisitesPage.tsx index de0e0c6b3c9..4e5863d4831 100644 --- a/src/pages/workspace/accounting/intacct/SageIntacctPrerequisitesPage.tsx +++ b/src/pages/workspace/accounting/intacct/SageIntacctPrerequisitesPage.tsx @@ -79,7 +79,7 @@ function SageIntacctPrerequisitesPage({route}: SageIntacctPrerequisitesPageProps - {translate('workspace.intacct.prerequisitesTitle')} + {translate('workspace.intacct.prerequisitesTitle')} Date: Mon, 12 Aug 2024 18:33:00 +0300 Subject: [PATCH 016/565] move profile photo to profile page --- src/pages/settings/InitialSettingsPage.tsx | 21 ----------------- src/pages/settings/Profile/ProfilePage.tsx | 26 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/pages/settings/InitialSettingsPage.tsx b/src/pages/settings/InitialSettingsPage.tsx index ecd0b31cf88..2b2219fa9fb 100755 --- a/src/pages/settings/InitialSettingsPage.tsx +++ b/src/pages/settings/InitialSettingsPage.tsx @@ -414,27 +414,6 @@ function InitialSettingsPage({session, userWallet, bankAccountList, fundList, wa - - Navigation.navigate(ROUTES.PROFILE_AVATAR.getRoute(String(accountID)))} - previewSource={UserUtils.getFullSizeAvatar(avatarURL, accountID)} - originalFileName={currentUserDetails.originalFileName} - headerTitle={translate('profilePage.profileAvatar')} - fallbackIcon={currentUserDetails?.fallbackIcon} - editIconStyle={styles.smallEditIconAccount} - /> - )} diff --git a/src/pages/settings/Profile/ProfilePage.tsx b/src/pages/settings/Profile/ProfilePage.tsx index 988b68ca5bf..72944f36ce8 100755 --- a/src/pages/settings/Profile/ProfilePage.tsx +++ b/src/pages/settings/Profile/ProfilePage.tsx @@ -2,6 +2,7 @@ import React from 'react'; import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; +import AvatarWithImagePicker from '@components/AvatarWithImagePicker'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import * as Illustrations from '@components/Icon/Illustrations'; @@ -21,6 +22,7 @@ import * as LocalePhoneNumber from '@libs/LocalePhoneNumber'; import Navigation from '@libs/Navigation/Navigation'; import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; import * as UserUtils from '@libs/UserUtils'; +import * as PersonalDetails from '@userActions/PersonalDetails'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -68,6 +70,9 @@ function ProfilePage({ return pronounsKey ? translate(`pronouns.${pronounsKey}` as TranslationPaths) : translate('profilePage.selectYourPronouns'); }; + const avatarURL = currentUserPersonalDetails?.avatar ?? ''; + const accountID = currentUserPersonalDetails?.accountID ?? '-1'; + const contactMethodBrickRoadIndicator = UserUtils.getLoginListBrickRoadIndicator(loginList); const emojiCode = currentUserPersonalDetails?.status?.emojiCode ?? ''; const privateDetails = privatePersonalDetails ?? {}; @@ -143,6 +148,27 @@ function ProfilePage({ childrenStyles={styles.pt5} titleStyles={styles.accountSettingsSectionTitle} > + + Navigation.navigate(ROUTES.PROFILE_AVATAR.getRoute(String(accountID)))} + previewSource={UserUtils.getFullSizeAvatar(avatarURL, accountID)} + originalFileName={currentUserPersonalDetails.originalFileName} + headerTitle={translate('profilePage.profileAvatar')} + fallbackIcon={currentUserPersonalDetails?.fallbackIcon} + editIconStyle={styles.smallEditIconAccount} + /> + {publicOptions.map((detail, index) => ( Date: Mon, 12 Aug 2024 18:36:56 +0300 Subject: [PATCH 017/565] align left --- src/pages/settings/Profile/ProfilePage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/Profile/ProfilePage.tsx b/src/pages/settings/Profile/ProfilePage.tsx index 72944f36ce8..2e2f4c6acba 100755 --- a/src/pages/settings/Profile/ProfilePage.tsx +++ b/src/pages/settings/Profile/ProfilePage.tsx @@ -148,7 +148,7 @@ function ProfilePage({ childrenStyles={styles.pt5} titleStyles={styles.accountSettingsSectionTitle} > - + Date: Mon, 12 Aug 2024 18:40:11 +0300 Subject: [PATCH 018/565] cleanup --- src/pages/settings/InitialSettingsPage.tsx | 88 +++++++++------------- 1 file changed, 37 insertions(+), 51 deletions(-) diff --git a/src/pages/settings/InitialSettingsPage.tsx b/src/pages/settings/InitialSettingsPage.tsx index 2b2219fa9fb..30deb190f7f 100755 --- a/src/pages/settings/InitialSettingsPage.tsx +++ b/src/pages/settings/InitialSettingsPage.tsx @@ -6,7 +6,6 @@ import {NativeModules, View} from 'react-native'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import {useOnyx, withOnyx} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; -import AvatarWithImagePicker from '@components/AvatarWithImagePicker'; import ConfirmModal from '@components/ConfirmModal'; import CurrentUserPersonalDetailsSkeletonView from '@components/CurrentUserPersonalDetailsSkeletonView'; import Icon from '@components/Icon'; @@ -37,7 +36,6 @@ import * as ReportActionContextMenu from '@pages/home/report/ContextMenu/ReportA import variables from '@styles/variables'; import * as Link from '@userActions/Link'; import * as PaymentMethods from '@userActions/PaymentMethods'; -import * as PersonalDetails from '@userActions/PersonalDetails'; import * as Session from '@userActions/Session'; import * as Wallet from '@userActions/Wallet'; import CONST from '@src/CONST'; @@ -51,9 +49,6 @@ import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type IconAsset from '@src/types/utils/IconAsset'; type InitialSettingsPageOnyxProps = { - /** The user's session */ - session: OnyxEntry; - /** The user's wallet account */ userWallet: OnyxEntry; @@ -97,14 +92,14 @@ type MenuData = { type Menu = {sectionStyle: StyleProp; sectionTranslationKey: TranslationPaths; items: MenuData[]}; -function InitialSettingsPage({session, userWallet, bankAccountList, fundList, walletTerms, loginList, currentUserPersonalDetails, policies}: InitialSettingsPageProps) { +function InitialSettingsPage({userWallet, bankAccountList, fundList, walletTerms, loginList, currentUserPersonalDetails, policies}: InitialSettingsPageProps) { const network = useNetwork(); const theme = useTheme(); const styles = useThemeStyles(); const {isExecuting, singleExecution} = useSingleExecution(); const waitForNavigate = useWaitForNavigation(); const popoverAnchor = useRef(null); - const {translate, formatPhoneNumber} = useLocalize(); + const {translate} = useLocalize(); const activeCentralPaneRoute = useActiveCentralPaneRoute(); const emojiCode = currentUserPersonalDetails?.status?.emojiCode ?? ''; @@ -364,57 +359,51 @@ function InitialSettingsPage({session, userWallet, bankAccountList, fundList, wa const generalMenuItems = useMemo(() => getMenuItemsSection(generalMenuItemsData), [generalMenuItemsData, getMenuItemsSection]); const workspaceMenuItems = useMemo(() => getMenuItemsSection(workspaceMenuItemsData), [workspaceMenuItemsData, getMenuItemsSection]); - const currentUserDetails = currentUserPersonalDetails; - const avatarURL = currentUserDetails?.avatar ?? ''; - const accountID = currentUserDetails?.accountID ?? '-1'; - const headerContent = ( {isEmptyObject(currentUserPersonalDetails) || currentUserPersonalDetails.displayName === undefined ? ( ) : ( - <> - - - Navigation.navigate(ROUTES.SETTINGS_SHARE_CODE)} - > - + + + Navigation.navigate(ROUTES.SETTINGS_SHARE_CODE)} + > + + + + + + + Navigation.navigate(ROUTES.SETTINGS_STATUS)} + > + + {emojiCode ? ( + {emojiCode} + ) : ( - - - - - Navigation.navigate(ROUTES.SETTINGS_STATUS)} - > - - {emojiCode ? ( - {emojiCode} - ) : ( - - )} - - - - - + )} + + + + )} ); @@ -494,9 +483,6 @@ export default withCurrentUserPersonalDetails( loginList: { key: ONYXKEYS.LOGIN_LIST, }, - session: { - key: ONYXKEYS.SESSION, - }, policies: { key: ONYXKEYS.COLLECTION.POLICY, }, From 1a5e6f76b0b6e89b88abc8d027a9c633a65843cf Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Mon, 12 Aug 2024 20:52:30 +0300 Subject: [PATCH 019/565] move share button to profile page --- src/pages/settings/InitialSettingsPage.tsx | 17 --------------- src/pages/settings/Profile/ProfilePage.tsx | 25 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/pages/settings/InitialSettingsPage.tsx b/src/pages/settings/InitialSettingsPage.tsx index 30deb190f7f..77132619c9b 100755 --- a/src/pages/settings/InitialSettingsPage.tsx +++ b/src/pages/settings/InitialSettingsPage.tsx @@ -365,23 +365,6 @@ function InitialSettingsPage({userWallet, bankAccountList, fundList, walletTerms ) : ( - - Navigation.navigate(ROUTES.SETTINGS_SHARE_CODE)} - > - - - - - ))} + + + Navigation.navigate(ROUTES.SETTINGS_SHARE_CODE)} + style={[styles.button, styles.flexRow, styles.gap1]} + > + + {translate('common.share')} + + +
Date: Mon, 12 Aug 2024 20:58:31 +0300 Subject: [PATCH 020/565] add padding to share btn --- src/pages/settings/Profile/ProfilePage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/Profile/ProfilePage.tsx b/src/pages/settings/Profile/ProfilePage.tsx index a1c21dbf97c..ef338d7ee0f 100755 --- a/src/pages/settings/Profile/ProfilePage.tsx +++ b/src/pages/settings/Profile/ProfilePage.tsx @@ -194,7 +194,7 @@ function ProfilePage({ accessibilityRole="button" accessible onPress={() => Navigation.navigate(ROUTES.SETTINGS_SHARE_CODE)} - style={[styles.button, styles.flexRow, styles.gap1]} + style={[styles.button, styles.flexRow, styles.gap1, styles.ph4]} > Date: Mon, 12 Aug 2024 21:43:47 +0300 Subject: [PATCH 021/565] create account switcher component --- src/components/AccountSwitcher.tsx | 50 ++++++++++++++++++++++ src/pages/settings/InitialSettingsPage.tsx | 2 + 2 files changed, 52 insertions(+) create mode 100644 src/components/AccountSwitcher.tsx diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx new file mode 100644 index 00000000000..feb98aadea4 --- /dev/null +++ b/src/components/AccountSwitcher.tsx @@ -0,0 +1,50 @@ +import React from 'react'; +import {View} from 'react-native'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import CONST from '@src/CONST'; +import Avatar from './Avatar'; +import {PressableWithFeedback} from './Pressable'; +import Text from './Text'; + +function AccountSwitcher() { + const currentUserPersonalDetails = useCurrentUserPersonalDetails(); + const avatarUrl = currentUserPersonalDetails?.avatar ?? ''; + const accountID = currentUserPersonalDetails?.accountID ?? -1; + const styles = useThemeStyles(); + const {translate} = useLocalize(); + + return ( + + + + + + {currentUserPersonalDetails?.displayName} + + + {currentUserPersonalDetails?.login} + + + + + ); +} + +export default AccountSwitcher; diff --git a/src/pages/settings/InitialSettingsPage.tsx b/src/pages/settings/InitialSettingsPage.tsx index 77132619c9b..aac9f2822a0 100755 --- a/src/pages/settings/InitialSettingsPage.tsx +++ b/src/pages/settings/InitialSettingsPage.tsx @@ -6,6 +6,7 @@ import {NativeModules, View} from 'react-native'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import {useOnyx, withOnyx} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; +import AccountSwitcher from '@components/AccountSwitcher'; import ConfirmModal from '@components/ConfirmModal'; import CurrentUserPersonalDetailsSkeletonView from '@components/CurrentUserPersonalDetailsSkeletonView'; import Icon from '@components/Icon'; @@ -365,6 +366,7 @@ function InitialSettingsPage({userWallet, bankAccountList, fundList, walletTerms ) : ( + Date: Tue, 13 Aug 2024 08:34:40 +0300 Subject: [PATCH 022/565] adjust styles to be responsive and text overflow --- src/components/AccountSwitcher.tsx | 31 +++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx index feb98aadea4..f5181cd1fdd 100644 --- a/src/components/AccountSwitcher.tsx +++ b/src/components/AccountSwitcher.tsx @@ -2,9 +2,13 @@ import React from 'react'; import {View} from 'react-native'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; +import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; +import variables from '@styles/variables'; import CONST from '@src/CONST'; import Avatar from './Avatar'; +import Icon from './Icon'; +import * as Expensicons from './Icon/Expensicons'; import {PressableWithFeedback} from './Pressable'; import Text from './Text'; @@ -14,11 +18,14 @@ function AccountSwitcher() { const accountID = currentUserPersonalDetails?.accountID ?? -1; const styles = useThemeStyles(); const {translate} = useLocalize(); + const theme = useTheme(); return ( {}} + wrapperStyle={[styles.flexGrow1, styles.accountSwitcherWrapper, styles.justifyContentCenter]} > - - - {currentUserPersonalDetails?.displayName} - + + + + {currentUserPersonalDetails?.displayName} + + + + + Date: Tue, 13 Aug 2024 08:34:55 +0300 Subject: [PATCH 023/565] add caret up down icon --- assets/images/caret-up-down.svg | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 assets/images/caret-up-down.svg diff --git a/assets/images/caret-up-down.svg b/assets/images/caret-up-down.svg new file mode 100644 index 00000000000..d08aa2a1ebb --- /dev/null +++ b/assets/images/caret-up-down.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + \ No newline at end of file From d0cf30bd1784972600eb49de94f99b869ac4f6f4 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 13 Aug 2024 08:35:00 +0300 Subject: [PATCH 024/565] add caret up down icon --- src/components/Icon/Expensicons.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/Icon/Expensicons.ts b/src/components/Icon/Expensicons.ts index cb68f33face..69131493c8a 100644 --- a/src/components/Icon/Expensicons.ts +++ b/src/components/Icon/Expensicons.ts @@ -32,6 +32,7 @@ import Calendar from '@assets/images/calendar.svg'; import Camera from '@assets/images/camera.svg'; import CarWithKey from '@assets/images/car-with-key.svg'; import Car from '@assets/images/car.svg'; +import CaretUpDown from '@assets/images/caret-up-down.svg'; import Cash from '@assets/images/cash.svg'; import Chair from '@assets/images/chair.svg'; import ChatBubbleAdd from '@assets/images/chatbubble-add.svg'; @@ -384,4 +385,5 @@ export { Filters, CalendarSolid, Filter, + CaretUpDown, }; From 6112f607e4984b2a909d305821249376fc617d7a Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 13 Aug 2024 08:35:23 +0300 Subject: [PATCH 025/565] show account switcher --- src/pages/settings/InitialSettingsPage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/settings/InitialSettingsPage.tsx b/src/pages/settings/InitialSettingsPage.tsx index aac9f2822a0..73e3c497894 100755 --- a/src/pages/settings/InitialSettingsPage.tsx +++ b/src/pages/settings/InitialSettingsPage.tsx @@ -361,11 +361,11 @@ function InitialSettingsPage({userWallet, bankAccountList, fundList, walletTerms const workspaceMenuItems = useMemo(() => getMenuItemsSection(workspaceMenuItemsData), [workspaceMenuItemsData, getMenuItemsSection]); const headerContent = ( - + {isEmptyObject(currentUserPersonalDetails) || currentUserPersonalDetails.displayName === undefined ? ( ) : ( - + Date: Tue, 13 Aug 2024 08:36:58 +0300 Subject: [PATCH 026/565] add min width 0 style --- src/styles/index.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/styles/index.ts b/src/styles/index.ts index 59803541bfe..a1f1f17bfcc 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/naming-convention */ import type {LineLayerStyleProps} from '@rnmapbox/maps/src/utils/MapboxStyles'; +import {min} from 'lodash'; import lodashClamp from 'lodash/clamp'; import type {LineLayer} from 'react-map-gl'; import type {AnimatableNumericValue, Animated, ImageStyle, TextStyle, ViewStyle} from 'react-native'; @@ -5159,6 +5160,11 @@ const styles = (theme: ThemeColors) => marginLeft: 19, backgroundColor: theme.border, }, + + accountSwitcherWrapper: { + minWidth: 0, + flex: 1, + }, } satisfies Styles); type ThemeStyles = ReturnType; From cebf12924f49edf22c14eeaffea2bb7214d364c9 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 13 Aug 2024 08:39:32 +0300 Subject: [PATCH 027/565] add beta --- src/CONST.ts | 1 + src/libs/Permissions.ts | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/CONST.ts b/src/CONST.ts index 57c6da815eb..9ce618284ec 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -381,6 +381,7 @@ const CONST = { REPORT_FIELDS_FEATURE: 'reportFieldsFeature', WORKSPACE_FEEDS: 'workspaceFeeds', NETSUITE_USA_TAX: 'netsuiteUsaTax', + NEW_DOT_COPILOT: 'newDotCopilot', }, BUTTON_STATES: { DEFAULT: 'default', diff --git a/src/libs/Permissions.ts b/src/libs/Permissions.ts index f652c2a423e..0581fd41853 100644 --- a/src/libs/Permissions.ts +++ b/src/libs/Permissions.ts @@ -40,6 +40,10 @@ function canUseNetSuiteUSATax(betas: OnyxEntry): boolean { return !!betas?.includes(CONST.BETAS.NETSUITE_USA_TAX) || canUseAllBetas(betas); } +function canUseNewDotCopilot(betas: OnyxEntry): boolean { + return !!betas?.includes(CONST.BETAS.NEW_DOT_COPILOT) || canUseAllBetas(betas); +} + /** * Link previews are temporarily disabled. */ @@ -57,4 +61,5 @@ export default { canUseReportFieldsFeature, canUseWorkspaceFeeds, canUseNetSuiteUSATax, + canUseNewDotCopilot, }; From 3655383bad5e01c695b5882ea8bd2cfa4f7ebb12 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 13 Aug 2024 08:42:00 +0300 Subject: [PATCH 028/565] rm unnecessary style --- src/components/AccountSwitcher.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx index f5181cd1fdd..14ee4a60051 100644 --- a/src/components/AccountSwitcher.tsx +++ b/src/components/AccountSwitcher.tsx @@ -39,7 +39,7 @@ function AccountSwitcher() { {currentUserPersonalDetails?.displayName} From 57dfbede700e6be22c702d542836f814375ca745 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 13 Aug 2024 09:24:51 +0300 Subject: [PATCH 029/565] add popover menu to show delegates --- src/components/AccountSwitcher.tsx | 117 ++++++++++++++++++++--------- src/styles/index.ts | 6 ++ 2 files changed, 88 insertions(+), 35 deletions(-) diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx index 14ee4a60051..6426a254903 100644 --- a/src/components/AccountSwitcher.tsx +++ b/src/components/AccountSwitcher.tsx @@ -1,14 +1,20 @@ -import React from 'react'; +import {set} from 'lodash'; +import React, {useEffect, useRef, useState} from 'react'; import {View} from 'react-native'; +import Onyx, {useOnyx} from 'react-native-onyx'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; +import usePermissions from '@hooks/usePermissions'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import variables from '@styles/variables'; import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; import Avatar from './Avatar'; import Icon from './Icon'; import * as Expensicons from './Icon/Expensicons'; +import PopoverMenu from './PopoverMenu'; +import type {PopoverMenuItem} from './PopoverMenu/types'; import {PressableWithFeedback} from './Pressable'; import Text from './Text'; @@ -19,48 +25,89 @@ function AccountSwitcher() { const styles = useThemeStyles(); const {translate} = useLocalize(); const theme = useTheme(); + const {canUseNewDotCopilot} = usePermissions(); + const [account] = useOnyx(ONYXKEYS.ACCOUNT); + const [shouldShowDelegateMenu, setShouldShowDelegateMenu] = useState(false); + + const buttonRef = useRef(null); + + const delegates = account?.delegatedAccess?.delegates ?? []; + const shouldShowDelegates = delegates.length > 0 && canUseNewDotCopilot; + + const delegateMenuItems: PopoverMenuItem[] = delegates.map(({email, role}) => ({ + text: `${email} (${role})`, + onPress: () => {}, + })); + + useEffect(() => { + // eslint-disable-next-line rulesdir/prefer-actions-set-data + Onyx.merge(ONYXKEYS.ACCOUNT, { + delegatedAccess: { + delegates: [ + {email: 'delegate1@expensify.com', role: 'all'}, + {email: 'delegate2@expensify.com', role: 'submitter'}, + ], + }, + }); + }, []); return ( - {}} - wrapperStyle={[styles.flexGrow1, styles.accountSwitcherWrapper, styles.justifyContentCenter]} - > - - - - + <> + { + setShouldShowDelegateMenu(!shouldShowDelegateMenu); + }} + ref={buttonRef} + wrapperStyle={[styles.flexGrow1, styles.accountSwitcherWrapper, styles.justifyContentCenter]} + > + + + + + + {currentUserPersonalDetails?.displayName} + + {shouldShowDelegates && ( + + + + )} + - {currentUserPersonalDetails?.displayName} + {currentUserPersonalDetails?.login} - - - - - {currentUserPersonalDetails?.login} - - - + + setShouldShowDelegateMenu(false)} + onItemSelected={() => {}} + menuItems={delegateMenuItems} + anchorRef={buttonRef} + anchorPosition={styles.createAccountSwitcherPosition()} + /> + ); } diff --git a/src/styles/index.ts b/src/styles/index.ts index a1f1f17bfcc..8c5e3e49905 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -1711,6 +1711,12 @@ const styles = (theme: ThemeColors) => lineHeight: variables.fontSizeOnlyEmojisHeight, }, + createAccountSwitcherPosition: () => + ({ + horizontal: 12, + vertical: 285, + } satisfies AnchorPosition), + createMenuPositionSidebar: (windowHeight: number) => ({ horizontal: 18, From 190a319d96711314f33deef8c4c558f5df14061a Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 13 Aug 2024 11:04:52 +0300 Subject: [PATCH 030/565] cleanup --- src/components/AccountSwitcher.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx index 6426a254903..35c9a85eb80 100644 --- a/src/components/AccountSwitcher.tsx +++ b/src/components/AccountSwitcher.tsx @@ -1,4 +1,3 @@ -import {set} from 'lodash'; import React, {useEffect, useRef, useState} from 'react'; import {View} from 'react-native'; import Onyx, {useOnyx} from 'react-native-onyx'; @@ -14,7 +13,7 @@ import Avatar from './Avatar'; import Icon from './Icon'; import * as Expensicons from './Icon/Expensicons'; import PopoverMenu from './PopoverMenu'; -import type {PopoverMenuItem} from './PopoverMenu/types'; +import type {PopoverMenuItem} from './PopoverMenu'; import {PressableWithFeedback} from './Pressable'; import Text from './Text'; From b43f7c04e6913ade3960877892e84eb44f781668 Mon Sep 17 00:00:00 2001 From: Wiktor Gut Date: Tue, 13 Aug 2024 12:58:22 +0200 Subject: [PATCH 031/565] pulling from, to filters --- src/pages/Search/AdvancedSearchFilters.tsx | 5 +++ src/pages/Search/SearchFiltersInPage.tsx | 42 +++++++++++++++++++++ src/types/form/SearchAdvancedFiltersForm.ts | 2 + 3 files changed, 49 insertions(+) create mode 100644 src/pages/Search/SearchFiltersInPage.tsx diff --git a/src/pages/Search/AdvancedSearchFilters.tsx b/src/pages/Search/AdvancedSearchFilters.tsx index 644ae64466f..9a7688fdc26 100644 --- a/src/pages/Search/AdvancedSearchFilters.tsx +++ b/src/pages/Search/AdvancedSearchFilters.tsx @@ -190,6 +190,11 @@ function AdvancedSearchFilters() { description: 'common.to' as const, route: ROUTES.SEARCH_ADVANCED_FILTERS_TO, }, + { + title: getFilterParticipantDisplayTitle(searchAdvancedFilters.in ?? [], personalDetails), + description: 'common.to' as const, + route: ROUTES.SEARCH_ADVANCED_FILTERS_TO, + }, ], [searchAdvancedFilters, translate, cardList, taxRates, personalDetails], ); diff --git a/src/pages/Search/SearchFiltersInPage.tsx b/src/pages/Search/SearchFiltersInPage.tsx new file mode 100644 index 00000000000..1bcf1ea6624 --- /dev/null +++ b/src/pages/Search/SearchFiltersInPage.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import {View} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import ScreenWrapper from '@components/ScreenWrapper'; +import SearchFiltersParticipantsSelector from '@components/Search/SearchFiltersParticipantsSelector'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import * as SearchActions from '@userActions/Search'; +import ONYXKEYS from '@src/ONYXKEYS'; + +function SearchFiltersStatusPage() { + const styles = useThemeStyles(); + const {translate} = useLocalize(); + + const [searchAdvancedFiltersForm] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM); + + return ( + + + + { + SearchActions.updateAdvancedFilters({ + from: selectedAccountIDs, + }); + }} + /> + + + ); +} + +SearchFiltersStatusPage.displayName = 'SearchFiltersStatusPage'; + +export default SearchFiltersStatusPage; diff --git a/src/types/form/SearchAdvancedFiltersForm.ts b/src/types/form/SearchAdvancedFiltersForm.ts index f2643c0c987..2afc63b7a2d 100644 --- a/src/types/form/SearchAdvancedFiltersForm.ts +++ b/src/types/form/SearchAdvancedFiltersForm.ts @@ -17,6 +17,7 @@ const FILTER_KEYS = { KEYWORD: 'keyword', FROM: 'from', TO: 'to', + IN: 'in', } as const; type InputID = ValueOf; @@ -39,6 +40,7 @@ type SearchAdvancedFiltersForm = Form< [FILTER_KEYS.TAG]: string[]; [FILTER_KEYS.FROM]: string[]; [FILTER_KEYS.TO]: string[]; + [FILTER_KEYS.IN]: string[]; } >; From 9c26711b8132f48c90e49816785c047dca55580e Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Tue, 13 Aug 2024 13:21:08 +0200 Subject: [PATCH 032/565] feat: create getDomainNameForPolicy util --- src/CONST.ts | 3 +++ src/libs/PolicyUtils.ts | 9 +++++++++ .../expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx | 6 +++--- .../expensifyCard/WorkspaceSettlementAccountPage.tsx | 4 ++-- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 84b393a1f5a..a2086872dd9 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -632,6 +632,9 @@ const CONST = { INBOX: 'inbox', }, + EXPENSIFY_POLICY_DOMAIN: 'expensify_policy', + EXPENSIFY_POLICY_DOMAIN_EXTENSION: '.exfy', + SIGN_IN_FORM_WIDTH: 300, REQUEST_CODE_DELAY: 30, diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 37016b8821f..67085d9e317 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -969,6 +969,14 @@ function getWorkspaceAccountID(policyID: string) { return policy.workspaceAccountID ?? 0; } +function getDomainNameForPolicy(policyID?: string): string { + if (!policyID) { + return ''; + } + + return `${CONST.EXPENSIFY_POLICY_DOMAIN}${policyID}${CONST.EXPENSIFY_POLICY_DOMAIN_EXTENSION}`; +} + export { canEditTaxRate, extractPolicyIDFromPath, @@ -1074,6 +1082,7 @@ export { getWorkspaceAccountID, getAllTaxRatesNamesAndKeys as getAllTaxRates, getTagNamesFromTagsLists, + getDomainNameForPolicy, }; export type {MemberEmailsToAccountIDs}; diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx index aa6f542ede5..9d24330d039 100644 --- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx +++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx @@ -40,8 +40,8 @@ function WorkspaceExpensifyCardBankAccounts({route}: WorkspaceExpensifyCardBankA const handleSelectBankAccount = (value?: number) => { Card.configureExpensifyCardsForPolicy(policyID, value); const handleSelectBankAccount = (value: number) => { - // TODO: policy domainName - Card.updateSettlementAccount(workspaceAccountID, '', value); + const domainName = PolicyUtils.getDomainNameForPolicy(policyID); + Card.updateSettlementAccount(workspaceAccountID, domainName, value); Navigation.navigate(ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW.getRoute(policyID)); }; @@ -55,7 +55,7 @@ function WorkspaceExpensifyCardBankAccounts({route}: WorkspaceExpensifyCardBankA return eligibleBankAccounts.map((bankAccount) => { const bankName = (bankAccount.accountData?.addressName ?? '') as BankName; const bankAccountNumber = bankAccount.accountData?.accountNumber ?? ''; - const bankAccountID = bankAccount.accountData?.bankAccountID; + const bankAccountID = bankAccount.accountData?.bankAccountID; const {icon, iconSize, iconStyles} = getBankIcon({bankName, styles}); diff --git a/src/pages/workspace/expensifyCard/WorkspaceSettlementAccountPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceSettlementAccountPage.tsx index 6c885127d2f..ab7ed2153c7 100644 --- a/src/pages/workspace/expensifyCard/WorkspaceSettlementAccountPage.tsx +++ b/src/pages/workspace/expensifyCard/WorkspaceSettlementAccountPage.tsx @@ -73,8 +73,8 @@ function WorkspaceSettlementAccountPage({route}: WorkspaceSettlementAccountPageP }, [eligibleBankAccounts, paymentBankAccountID, styles, translate]); const updateSettlementAccount = (value: number) => { - // TODO: policy domainName - Card.updateSettlementAccount(workspaceAccountID, value); + const domainName = PolicyUtils.getDomainNameForPolicy(policyID); + Card.updateSettlementAccount(workspaceAccountID, domainName, value); Navigation.goBack(); }; From 8a405f0f1ac6d0a9a5865a4842819bc988fc9ff0 Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Tue, 13 Aug 2024 13:28:13 +0200 Subject: [PATCH 033/565] fix: minor fix --- src/libs/actions/Card.ts | 6 +- .../WorkspaceExpensifyCardBankAccounts.tsx | 110 +++++++++--------- 2 files changed, 59 insertions(+), 57 deletions(-) diff --git a/src/libs/actions/Card.ts b/src/libs/actions/Card.ts index c2c5aac1ad0..ec47e3beba7 100644 --- a/src/libs/actions/Card.ts +++ b/src/libs/actions/Card.ts @@ -247,7 +247,11 @@ function updateSettlementFrequency(workspaceAccountID: number, settlementFrequen API.write(WRITE_COMMANDS.UPDATE_CARD_SETTLEMENT_FREQUENCY, parameters, {optimisticData, successData, failureData}); } -function updateSettlementAccount(workspaceAccountID: number, domainName: string, settlementBankAccountID: number) { +function updateSettlementAccount(workspaceAccountID: number, domainName: string, settlementBankAccountID?: number) { + if (!settlementBankAccountID) { + return; + } + const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx index 9d24330d039..ae9a660b0d5 100644 --- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx +++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx @@ -37,69 +37,67 @@ function WorkspaceExpensifyCardBankAccounts({route}: WorkspaceExpensifyCardBankA Navigation.navigate(ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute('new', policyID, ROUTES.WORKSPACE_EXPENSIFY_CARD.getRoute(policyID))); }; - const handleSelectBankAccount = (value?: number) => { + const handleSelectBankAccount = (value: number) => { Card.configureExpensifyCardsForPolicy(policyID, value); - const handleSelectBankAccount = (value: number) => { - const domainName = PolicyUtils.getDomainNameForPolicy(policyID); - Card.updateSettlementAccount(workspaceAccountID, domainName, value); - Navigation.navigate(ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW.getRoute(policyID)); - }; + const domainName = PolicyUtils.getDomainNameForPolicy(policyID); + Card.updateSettlementAccount(workspaceAccountID, domainName, value); + Navigation.navigate(ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW.getRoute(policyID)); + }; - const renderBankOptions = () => { - if (!bankAccountsList || isEmptyObject(bankAccountsList)) { - return null; - } + const renderBankOptions = () => { + if (!bankAccountsList || isEmptyObject(bankAccountsList)) { + return null; + } - const eligibleBankAccounts = CardUtils.getEligibleBankAccountsForCard(bankAccountsList); + const eligibleBankAccounts = CardUtils.getEligibleBankAccountsForCard(bankAccountsList); - return eligibleBankAccounts.map((bankAccount) => { - const bankName = (bankAccount.accountData?.addressName ?? '') as BankName; - const bankAccountNumber = bankAccount.accountData?.accountNumber ?? ''; - const bankAccountID = bankAccount.accountData?.bankAccountID; + return eligibleBankAccounts.map((bankAccount) => { + const bankName = (bankAccount.accountData?.addressName ?? '') as BankName; + const bankAccountNumber = bankAccount.accountData?.accountNumber ?? ''; + const bankAccountID = bankAccount.accountData?.bankAccountID; - const {icon, iconSize, iconStyles} = getBankIcon({bankName, styles}); + const {icon, iconSize, iconStyles} = getBankIcon({bankName, styles}); - return ( - handleSelectBankAccount(bankAccountID)} - icon={icon} - iconHeight={iconSize} - iconWidth={iconSize} - iconStyles={iconStyles} - shouldShowRightIcon - displayInDefaultIconColor - /> - ); - }); - }; + return ( + handleSelectBankAccount(bankAccountID)} + icon={icon} + iconHeight={iconSize} + iconWidth={iconSize} + iconStyles={iconStyles} + shouldShowRightIcon + displayInDefaultIconColor + /> + ); + }); + }; - return ( - - Navigation.goBack()} - title={translate('workspace.expensifyCard.chooseBankAccount')} + return ( + + Navigation.goBack()} + title={translate('workspace.expensifyCard.chooseBankAccount')} + /> + + {translate('workspace.expensifyCard.chooseExistingBank')} + {renderBankOptions()} + - - {translate('workspace.expensifyCard.chooseExistingBank')} - {renderBankOptions()} - - - - ); - } + + + ); +} - WorkspaceExpensifyCardBankAccounts.displayName = 'WorkspaceExpensifyCardBankAccounts'; +WorkspaceExpensifyCardBankAccounts.displayName = 'WorkspaceExpensifyCardBankAccounts'; - export default WorkspaceExpensifyCardBankAccounts; +export default WorkspaceExpensifyCardBankAccounts; From 110af748c682b64da39732f52097a5f9d049f635 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 13 Aug 2024 16:22:01 +0300 Subject: [PATCH 034/565] add styling for menu item --- src/components/AccountSwitcher.tsx | 77 +++++++++++++++++++++++------- 1 file changed, 60 insertions(+), 17 deletions(-) diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx index 35c9a85eb80..d8db6ae6f42 100644 --- a/src/components/AccountSwitcher.tsx +++ b/src/components/AccountSwitcher.tsx @@ -1,19 +1,22 @@ +import {Str} from 'expensify-common'; import React, {useEffect, useRef, useState} from 'react'; import {View} from 'react-native'; import Onyx, {useOnyx} from 'react-native-onyx'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; import usePermissions from '@hooks/usePermissions'; +import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; +import {getPersonalDetailByEmail} from '@libs/PersonalDetailsUtils'; import variables from '@styles/variables'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import Avatar from './Avatar'; import Icon from './Icon'; import * as Expensicons from './Icon/Expensicons'; -import PopoverMenu from './PopoverMenu'; -import type {PopoverMenuItem} from './PopoverMenu'; +import MenuItem from './MenuItem'; +import Popover from './Popover'; import {PressableWithFeedback} from './Pressable'; import Text from './Text'; @@ -32,19 +35,52 @@ function AccountSwitcher() { const delegates = account?.delegatedAccess?.delegates ?? []; const shouldShowDelegates = delegates.length > 0 && canUseNewDotCopilot; + const {isSmallScreenWidth} = useResponsiveLayout(); - const delegateMenuItems: PopoverMenuItem[] = delegates.map(({email, role}) => ({ - text: `${email} (${role})`, - onPress: () => {}, - })); + const delegateMenuItems = delegates.map(({email, role}) => { + const personalDetail = getPersonalDetailByEmail(email); + + return { + key: email, + title: personalDetail?.displayName ?? email, + description: personalDetail?.displayName ? email : '', + badgeText: Str.recapitalize(role), + onPress: () => {}, + avatarID: personalDetail?.accountID ?? -1, + icon: personalDetail?.avatar ?? '', + iconType: CONST.ICON_TYPE_AVATAR, + outerWrapperStyle: isSmallScreenWidth ? {} : styles.accountSwitcherPopover, + numberOfLinesDescription: 1, + }; + }); + + const delegateMenuItemsWithCurrentUser = [ + { + key: currentUserPersonalDetails?.login, + title: currentUserPersonalDetails?.displayName ?? currentUserPersonalDetails?.login, + description: currentUserPersonalDetails?.displayName ? currentUserPersonalDetails?.login : '', + onPress: () => {}, + iconRight: Expensicons.Checkmark, + shouldShowRightIcon: true, + success: true, + avatarID: currentUserPersonalDetails?.accountID ?? -1, + icon: avatarUrl, + iconType: CONST.ICON_TYPE_AVATAR, + outerWrapperStyle: isSmallScreenWidth ? {} : styles.accountSwitcherPopover, + numberOfLinesDescription: 1, + wrapperStyle: [styles.buttonDefaultBG], + focused: true, + }, + ...delegateMenuItems, + ]; useEffect(() => { // eslint-disable-next-line rulesdir/prefer-actions-set-data Onyx.merge(ONYXKEYS.ACCOUNT, { delegatedAccess: { delegates: [ - {email: 'delegate1@expensify.com', role: 'all'}, - {email: 'delegate2@expensify.com', role: 'submitter'}, + {email: 'rushatgabhane@gmail.com', role: 'all'}, + {email: 'expensifyopensource+10041232131212321@protonmail.com', role: 'submitter'}, ], }, }); @@ -97,15 +133,22 @@ function AccountSwitcher() { - setShouldShowDelegateMenu(false)} - onItemSelected={() => {}} - menuItems={delegateMenuItems} - anchorRef={buttonRef} - anchorPosition={styles.createAccountSwitcherPosition()} - /> + {shouldShowDelegates && ( + setShouldShowDelegateMenu(false)} + anchorRef={buttonRef} + anchorPosition={{top: 80, left: 12}} + > + + {translate('delegate.switchAccount')} + {delegateMenuItemsWithCurrentUser.map((item) => ( + // eslint-disable-next-line react/jsx-props-no-spreading + + ))} + + + )} ); } From 890b23e34f8189d58d0ddf708769e5452cf9e799 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 13 Aug 2024 16:22:18 +0300 Subject: [PATCH 035/565] add badge text --- src/components/PopoverMenu.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/PopoverMenu.tsx b/src/components/PopoverMenu.tsx index e9df68d43d0..135f0c9061e 100644 --- a/src/components/PopoverMenu.tsx +++ b/src/components/PopoverMenu.tsx @@ -266,6 +266,7 @@ function PopoverMenu({ renderTooltipContent={item.renderTooltipContent} numberOfLinesTitle={item.numberOfLinesTitle} interactive={item.interactive} + badgeText={item.badgeText} /> ))} From d15ffabb559e84308362a8c4d5af6668486a649e Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 13 Aug 2024 16:22:27 +0300 Subject: [PATCH 036/565] add lang --- src/languages/en.ts | 3 +++ src/languages/es.ts | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/languages/en.ts b/src/languages/en.ts index bfe0eef7017..ed49cb449f1 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -4353,4 +4353,7 @@ export default { updateRoomDescription: 'set the room description to:', clearRoomDescription: 'cleared the room description', }, + delegate: { + switchAccount: 'Switch accounts:', + }, } satisfies TranslationBase; diff --git a/src/languages/es.ts b/src/languages/es.ts index 76d55a09680..1c79c828bc0 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -4873,4 +4873,7 @@ export default { updateRoomDescription: 'establece la descripción de la sala a:', clearRoomDescription: 'la descripción de la habitación ha sido borrada', }, + delegate: { + switchAccount: 'Cambiar cuentas:', + }, } satisfies EnglishTranslation; From e0aaba50e06f86326072c3597b441dd9cc81310f Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 13 Aug 2024 16:23:22 +0300 Subject: [PATCH 037/565] add width for account switcher popover --- src/styles/index.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/styles/index.ts b/src/styles/index.ts index 8c5e3e49905..7c8882693fe 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -1,6 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ import type {LineLayerStyleProps} from '@rnmapbox/maps/src/utils/MapboxStyles'; -import {min} from 'lodash'; import lodashClamp from 'lodash/clamp'; import type {LineLayer} from 'react-map-gl'; import type {AnimatableNumericValue, Animated, ImageStyle, TextStyle, ViewStyle} from 'react-native'; @@ -1711,12 +1710,6 @@ const styles = (theme: ThemeColors) => lineHeight: variables.fontSizeOnlyEmojisHeight, }, - createAccountSwitcherPosition: () => - ({ - horizontal: 12, - vertical: 285, - } satisfies AnchorPosition), - createMenuPositionSidebar: (windowHeight: number) => ({ horizontal: 18, @@ -5171,6 +5164,10 @@ const styles = (theme: ThemeColors) => minWidth: 0, flex: 1, }, + + accountSwitcherPopover: { + width: variables.sideBarWidth - 19, + }, } satisfies Styles); type ThemeStyles = ReturnType; From e05b5d9b9ef61611c96ea9c123f94466765e94e5 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 13 Aug 2024 16:24:11 +0300 Subject: [PATCH 038/565] cleanup --- src/components/AccountSwitcher.tsx | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx index d8db6ae6f42..33913baa496 100644 --- a/src/components/AccountSwitcher.tsx +++ b/src/components/AccountSwitcher.tsx @@ -74,18 +74,6 @@ function AccountSwitcher() { ...delegateMenuItems, ]; - useEffect(() => { - // eslint-disable-next-line rulesdir/prefer-actions-set-data - Onyx.merge(ONYXKEYS.ACCOUNT, { - delegatedAccess: { - delegates: [ - {email: 'rushatgabhane@gmail.com', role: 'all'}, - {email: 'expensifyopensource+10041232131212321@protonmail.com', role: 'submitter'}, - ], - }, - }); - }, []); - return ( <> Date: Tue, 13 Aug 2024 16:24:45 +0300 Subject: [PATCH 039/565] cleanup --- src/components/AccountSwitcher.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx index 33913baa496..fc254c1d01a 100644 --- a/src/components/AccountSwitcher.tsx +++ b/src/components/AccountSwitcher.tsx @@ -1,7 +1,7 @@ import {Str} from 'expensify-common'; -import React, {useEffect, useRef, useState} from 'react'; +import React, {useRef, useState} from 'react'; import {View} from 'react-native'; -import Onyx, {useOnyx} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; import usePermissions from '@hooks/usePermissions'; From cc3c7225e17ead425aef0e23a84fb20bb08f0e2c Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 13 Aug 2024 16:31:20 +0300 Subject: [PATCH 040/565] cleanup --- src/components/AccountSwitcher.tsx | 2 +- src/styles/index.ts | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx index fc254c1d01a..d9fa42a586d 100644 --- a/src/components/AccountSwitcher.tsx +++ b/src/components/AccountSwitcher.tsx @@ -126,7 +126,7 @@ function AccountSwitcher() { isVisible={shouldShowDelegateMenu} onClose={() => setShouldShowDelegateMenu(false)} anchorRef={buttonRef} - anchorPosition={{top: 80, left: 12}} + anchorPosition={styles.accountSwitcherAnchorPosition} > {translate('delegate.switchAccount')} diff --git a/src/styles/index.ts b/src/styles/index.ts index 7c8882693fe..102bfa93f33 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -5168,6 +5168,11 @@ const styles = (theme: ThemeColors) => accountSwitcherPopover: { width: variables.sideBarWidth - 19, }, + + accountSwitcherAnchorPosition: { + top: 80, + left: 12, + }, } satisfies Styles); type ThemeStyles = ReturnType; From b298b0b86ca58e4e1cf0fe55ccd7ae48bdde4aaf Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 13 Aug 2024 16:35:38 +0300 Subject: [PATCH 041/565] add menu item type --- src/components/AccountSwitcher.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx index d9fa42a586d..0b928ba92f4 100644 --- a/src/components/AccountSwitcher.tsx +++ b/src/components/AccountSwitcher.tsx @@ -16,6 +16,7 @@ import Avatar from './Avatar'; import Icon from './Icon'; import * as Expensicons from './Icon/Expensicons'; import MenuItem from './MenuItem'; +import type {MenuItemProps} from './MenuItem'; import Popover from './Popover'; import {PressableWithFeedback} from './Pressable'; import Text from './Text'; @@ -37,11 +38,10 @@ function AccountSwitcher() { const shouldShowDelegates = delegates.length > 0 && canUseNewDotCopilot; const {isSmallScreenWidth} = useResponsiveLayout(); - const delegateMenuItems = delegates.map(({email, role}) => { + const delegateMenuItems: MenuItemProps[] = delegates.map(({email, role}) => { const personalDetail = getPersonalDetailByEmail(email); return { - key: email, title: personalDetail?.displayName ?? email, description: personalDetail?.displayName ? email : '', badgeText: Str.recapitalize(role), @@ -54,9 +54,8 @@ function AccountSwitcher() { }; }); - const delegateMenuItemsWithCurrentUser = [ + const delegateMenuItemsWithCurrentUser: MenuItemProps[] = [ { - key: currentUserPersonalDetails?.login, title: currentUserPersonalDetails?.displayName ?? currentUserPersonalDetails?.login, description: currentUserPersonalDetails?.displayName ? currentUserPersonalDetails?.login : '', onPress: () => {}, From 30c56d1121f849ae855b3e465d82a9d643a6f554 Mon Sep 17 00:00:00 2001 From: daledah Date: Tue, 13 Aug 2024 20:29:12 +0700 Subject: [PATCH 042/565] fix: maintain tax assign when tax code changes --- src/libs/actions/TaxRate.ts | 60 +++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/libs/actions/TaxRate.ts b/src/libs/actions/TaxRate.ts index 0e7245a93f7..869c1401760 100644 --- a/src/libs/actions/TaxRate.ts +++ b/src/libs/actions/TaxRate.ts @@ -21,6 +21,7 @@ import INPUT_IDS from '@src/types/form/WorkspaceNewTaxForm'; import {default as INPUT_IDS_TAX_CODE} from '@src/types/form/WorkspaceTaxCodeForm'; import type {Policy, TaxRate, TaxRates} from '@src/types/onyx'; import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; +import type {CustomUnit, Rate} from '@src/types/onyx/Policy'; import type {OnyxData} from '@src/types/onyx/Request'; let allPolicies: OnyxCollection; @@ -486,6 +487,63 @@ function renamePolicyTax(policyID: string, taxID: string, newName: string) { function setPolicyTaxCode(policyID: string, oldTaxCode: string, newTaxCode: string) { const policy = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`]; const originalTaxRate = {...policy?.taxRates?.taxes[oldTaxCode]}; + const customUnits = Object.values(policy?.customUnits ?? {}); + const optimisticCustomUnit = { + customUnits: { + ...policy?.customUnits, + ...customUnits.reduce((units, customUnit) => { + // eslint-disable-next-line no-param-reassign + units[customUnit.customUnitID] = { + ...customUnit, + rates: { + ...customUnit.rates, + ...Object.keys(customUnit.rates).reduce((rates, rateID) => { + if (customUnit.rates[rateID].attributes?.taxRateExternalID === oldTaxCode) { + // eslint-disable-next-line no-param-reassign + rates[rateID] = { + ...customUnit.rates[rateID], + attributes: { + ...customUnit.rates[rateID].attributes, + taxRateExternalID: newTaxCode, + }, + }; + } + return rates; + }, {} as Record), + } as Record, + }; + return units; + }, {} as Record), + }, + }; + const failureCustomUnit = { + customUnits: { + ...policy?.customUnits, + ...customUnits.reduce((units, customUnit) => { + // eslint-disable-next-line no-param-reassign + units[customUnit.customUnitID] = { + ...customUnit, + rates: { + ...customUnit.rates, + ...Object.keys(customUnit.rates).reduce((rates, rateID) => { + if (customUnit.rates[rateID].attributes?.taxRateExternalID === oldTaxCode) { + // eslint-disable-next-line no-param-reassign + rates[rateID] = { + ...customUnit.rates[rateID], + attributes: { + ...customUnit.rates[rateID].attributes, + taxRateExternalID: oldTaxCode, + }, + }; + } + return rates; + }, {} as Record), + } as Record, + }; + return units; + }, {} as Record), + }, + }; const onyxData: OnyxData = { optimisticData: [ { @@ -504,6 +562,7 @@ function setPolicyTaxCode(policyID: string, oldTaxCode: string, newTaxCode: stri }, }, }, + ...(!!customUnits && optimisticCustomUnit), }, }, ], @@ -544,6 +603,7 @@ function setPolicyTaxCode(policyID: string, oldTaxCode: string, newTaxCode: stri }, }, }, + ...(!!customUnits && failureCustomUnit), }, }, ], From f426c002a93b98c3534e8095c3ec46d59af0b83d Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 13 Aug 2024 17:15:38 +0300 Subject: [PATCH 043/565] add todo for error handling --- src/components/AccountSwitcher.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx index 0b928ba92f4..262551c3647 100644 --- a/src/components/AccountSwitcher.tsx +++ b/src/components/AccountSwitcher.tsx @@ -133,6 +133,7 @@ function AccountSwitcher() { // eslint-disable-next-line react/jsx-props-no-spreading ))} + {/* TODO error handling on API error Oops something went wrong. Please try again */} )} From 4f64b1d6c610b2caf9dc3b7d3e330d0ff7bbe4a1 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 13 Aug 2024 17:15:54 +0300 Subject: [PATCH 044/565] correct border color --- src/pages/settings/Profile/ProfilePage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/Profile/ProfilePage.tsx b/src/pages/settings/Profile/ProfilePage.tsx index ef338d7ee0f..b62342aa56f 100755 --- a/src/pages/settings/Profile/ProfilePage.tsx +++ b/src/pages/settings/Profile/ProfilePage.tsx @@ -172,7 +172,7 @@ function ProfilePage({ originalFileName={currentUserPersonalDetails.originalFileName} headerTitle={translate('profilePage.profileAvatar')} fallbackIcon={currentUserPersonalDetails?.fallbackIcon} - editIconStyle={styles.smallEditIconAccount} + editIconStyle={styles.profilePageAvatar} /> {publicOptions.map((detail, index) => ( From 94811774cf837900781c1085446bad00aca62075 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 13 Aug 2024 17:16:02 +0300 Subject: [PATCH 045/565] correct border color --- src/styles/index.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/styles/index.ts b/src/styles/index.ts index 102bfa93f33..2eea5479bcf 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -4515,6 +4515,10 @@ const styles = (theme: ThemeColors) => overflow: 'hidden', }, + profilePageAvatar: { + borderColor: theme.highlightBG, + }, + justSignedInModalAnimation: (is2FARequired: boolean) => ({ height: is2FARequired ? variables.modalTopIconHeight : variables.modalTopBigIconHeight, }), From cacd33ef34e89c1503b53a49017c320c777e522b Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Tue, 13 Aug 2024 16:16:11 +0200 Subject: [PATCH 046/565] fix: typecheck --- .../expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx index ae9a660b0d5..78060487d35 100644 --- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx +++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx @@ -37,7 +37,7 @@ function WorkspaceExpensifyCardBankAccounts({route}: WorkspaceExpensifyCardBankA Navigation.navigate(ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute('new', policyID, ROUTES.WORKSPACE_EXPENSIFY_CARD.getRoute(policyID))); }; - const handleSelectBankAccount = (value: number) => { + const handleSelectBankAccount = (value?: number) => { Card.configureExpensifyCardsForPolicy(policyID, value); const domainName = PolicyUtils.getDomainNameForPolicy(policyID); Card.updateSettlementAccount(workspaceAccountID, domainName, value); From 1005b60b643f77fcea3b664f5be209359cb70c5f Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Tue, 13 Aug 2024 16:29:01 +0200 Subject: [PATCH 047/565] fix: minor fix --- .../workspace/expensifyCard/WorkspaceSettlementFrequencyPage.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/workspace/expensifyCard/WorkspaceSettlementFrequencyPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceSettlementFrequencyPage.tsx index 182b0563924..84c02c65b3f 100644 --- a/src/pages/workspace/expensifyCard/WorkspaceSettlementFrequencyPage.tsx +++ b/src/pages/workspace/expensifyCard/WorkspaceSettlementFrequencyPage.tsx @@ -29,7 +29,6 @@ function WorkspaceSettlementFrequencyPage({route}: WorkspaceSettlementFrequencyP const [cardSettings] = useOnyx(`${ONYXKEYS.COLLECTION.PRIVATE_EXPENSIFY_CARD_SETTINGS}${workspaceAccountID}`); - // TODO: change true for false after API is ready - true is for testing purposes const shouldShowMonthlyOption = cardSettings?.isMonthlySettlementAllowed ?? false; const selectedFrequency = cardSettings?.monthlySettlementDate ? CONST.EXPENSIFY_CARD.FREQUENCY_SETTING.MONTHLY : CONST.EXPENSIFY_CARD.FREQUENCY_SETTING.DAILY; From acc9224b298791af0e476b6cc1707f23843b1bce Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Tue, 13 Aug 2024 16:45:19 +0200 Subject: [PATCH 048/565] fix: apply requested changes --- src/libs/actions/Card.ts | 8 ++++---- .../expensifyCard/WorkspaceSettlementAccountPage.tsx | 2 +- .../expensifyCard/WorkspaceSettlementFrequencyPage.tsx | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libs/actions/Card.ts b/src/libs/actions/Card.ts index 441c7ba45ca..2ca77c22c5f 100644 --- a/src/libs/actions/Card.ts +++ b/src/libs/actions/Card.ts @@ -206,7 +206,7 @@ function revealVirtualCardDetails(cardID: number): Promise }); } -function updateSettlementFrequency(workspaceAccountID: number, settlementFrequency: ValueOf) { +function updateSettlementFrequency(workspaceAccountID: number, settlementFrequency: ValueOf, currentFrequency?: Date) { const monthlySettlementDate = settlementFrequency === CONST.EXPENSIFY_CARD.FREQUENCY_SETTING.DAILY ? null : new Date(); const optimisticData: OnyxUpdate[] = [ @@ -234,7 +234,7 @@ function updateSettlementFrequency(workspaceAccountID: number, settlementFrequen onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.PRIVATE_EXPENSIFY_CARD_SETTINGS}${workspaceAccountID}`, value: { - monthlySettlementDate: null, + monthlySettlementDate: currentFrequency, }, }, ]; @@ -247,7 +247,7 @@ function updateSettlementFrequency(workspaceAccountID: number, settlementFrequen API.write(WRITE_COMMANDS.UPDATE_CARD_SETTLEMENT_FREQUENCY, parameters, {optimisticData, successData, failureData}); } -function updateSettlementAccount(workspaceAccountID: number, domainName: string, settlementBankAccountID?: number) { +function updateSettlementAccount(workspaceAccountID: number, domainName: string, settlementBankAccountID?: number, currentSettlementBankAccountID?: number) { if (!settlementBankAccountID) { return; } @@ -277,7 +277,7 @@ function updateSettlementAccount(workspaceAccountID: number, domainName: string, onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.PRIVATE_EXPENSIFY_CARD_SETTINGS}${workspaceAccountID}`, value: { - paymentBankAccountID: null, + paymentBankAccountID: currentSettlementBankAccountID, }, }, ]; diff --git a/src/pages/workspace/expensifyCard/WorkspaceSettlementAccountPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceSettlementAccountPage.tsx index ab7ed2153c7..9e91a55dd04 100644 --- a/src/pages/workspace/expensifyCard/WorkspaceSettlementAccountPage.tsx +++ b/src/pages/workspace/expensifyCard/WorkspaceSettlementAccountPage.tsx @@ -74,7 +74,7 @@ function WorkspaceSettlementAccountPage({route}: WorkspaceSettlementAccountPageP const updateSettlementAccount = (value: number) => { const domainName = PolicyUtils.getDomainNameForPolicy(policyID); - Card.updateSettlementAccount(workspaceAccountID, domainName, value); + Card.updateSettlementAccount(workspaceAccountID, domainName, value, paymentBankAccountID); Navigation.goBack(); }; diff --git a/src/pages/workspace/expensifyCard/WorkspaceSettlementFrequencyPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceSettlementFrequencyPage.tsx index 84c02c65b3f..84f1bb810af 100644 --- a/src/pages/workspace/expensifyCard/WorkspaceSettlementFrequencyPage.tsx +++ b/src/pages/workspace/expensifyCard/WorkspaceSettlementFrequencyPage.tsx @@ -55,7 +55,7 @@ function WorkspaceSettlementFrequencyPage({route}: WorkspaceSettlementFrequencyP }, [translate, shouldShowMonthlyOption, selectedFrequency]); const updateSettlementFrequency = (value: ValueOf) => { - Card.updateSettlementFrequency(workspaceAccountID, value); + Card.updateSettlementFrequency(workspaceAccountID, value, cardSettings?.monthlySettlementDate); }; return ( From d85b8afcab6056f1f9fb98de2998ffbf284f92d5 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 13 Aug 2024 17:48:29 +0300 Subject: [PATCH 049/565] add api call to connect --- src/components/AccountSwitcher.tsx | 6 ++++-- src/libs/actions/Delegate.ts | 6 ++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx index 262551c3647..9a2c2b39591 100644 --- a/src/components/AccountSwitcher.tsx +++ b/src/components/AccountSwitcher.tsx @@ -8,6 +8,7 @@ import usePermissions from '@hooks/usePermissions'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; +import {connect} from '@libs/actions/Delegate'; import {getPersonalDetailByEmail} from '@libs/PersonalDetailsUtils'; import variables from '@styles/variables'; import CONST from '@src/CONST'; @@ -45,7 +46,9 @@ function AccountSwitcher() { title: personalDetail?.displayName ?? email, description: personalDetail?.displayName ? email : '', badgeText: Str.recapitalize(role), - onPress: () => {}, + onPress: () => { + connect(email); + }, avatarID: personalDetail?.accountID ?? -1, icon: personalDetail?.avatar ?? '', iconType: CONST.ICON_TYPE_AVATAR, @@ -58,7 +61,6 @@ function AccountSwitcher() { { title: currentUserPersonalDetails?.displayName ?? currentUserPersonalDetails?.login, description: currentUserPersonalDetails?.displayName ? currentUserPersonalDetails?.login : '', - onPress: () => {}, iconRight: Expensicons.Checkmark, shouldShowRightIcon: true, success: true, diff --git a/src/libs/actions/Delegate.ts b/src/libs/actions/Delegate.ts index b743b5c77e7..2a3295a9dfd 100644 --- a/src/libs/actions/Delegate.ts +++ b/src/libs/actions/Delegate.ts @@ -10,6 +10,11 @@ function connect(email: string) { // eslint-disable-next-line rulesdir/no-api-side-effects-method API.makeRequestWithSideEffects(SIDE_EFFECT_REQUEST_COMMANDS.CONNECT_AS_DELEGATE, {to: email}, {}) .then((response) => { + if (!response?.restrictedToken || !response?.encryptedAuthToken) { + // TODO: Show an error message to the user + console.error('Error during connect: No authToken returned'); + return; + } return SequentialQueue.waitForIdle() .then(() => Onyx.clear()) .then(() => { @@ -21,6 +26,7 @@ function connect(email: string) { }); }) .catch((error) => { + // TODO: Show an error message to the user console.error('Error during connect:', error); }); } From 9a2a35d143596fb9eea92c22cd4dcd8f288d34cd Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Tue, 13 Aug 2024 21:47:47 +0300 Subject: [PATCH 050/565] add gap --- src/components/AccountSwitcher.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx index 9a2c2b39591..cf4c0491de3 100644 --- a/src/components/AccountSwitcher.tsx +++ b/src/components/AccountSwitcher.tsx @@ -94,7 +94,7 @@ function AccountSwitcher() { source={avatarUrl} fallbackIcon={currentUserPersonalDetails.fallbackIcon} /> - + Date: Wed, 14 Aug 2024 14:50:06 +0700 Subject: [PATCH 051/565] refactor: simplify optimistic and failture data --- src/libs/actions/TaxRate.ts | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/src/libs/actions/TaxRate.ts b/src/libs/actions/TaxRate.ts index 869c1401760..decb74c1a64 100644 --- a/src/libs/actions/TaxRate.ts +++ b/src/libs/actions/TaxRate.ts @@ -490,58 +490,48 @@ function setPolicyTaxCode(policyID: string, oldTaxCode: string, newTaxCode: stri const customUnits = Object.values(policy?.customUnits ?? {}); const optimisticCustomUnit = { customUnits: { - ...policy?.customUnits, ...customUnits.reduce((units, customUnit) => { // eslint-disable-next-line no-param-reassign units[customUnit.customUnitID] = { - ...customUnit, rates: { - ...customUnit.rates, ...Object.keys(customUnit.rates).reduce((rates, rateID) => { if (customUnit.rates[rateID].attributes?.taxRateExternalID === oldTaxCode) { // eslint-disable-next-line no-param-reassign rates[rateID] = { - ...customUnit.rates[rateID], attributes: { - ...customUnit.rates[rateID].attributes, taxRateExternalID: newTaxCode, }, }; } return rates; }, {} as Record), - } as Record, + }, }; return units; - }, {} as Record), + }, {} as Record>), }, }; const failureCustomUnit = { customUnits: { - ...policy?.customUnits, ...customUnits.reduce((units, customUnit) => { // eslint-disable-next-line no-param-reassign units[customUnit.customUnitID] = { - ...customUnit, rates: { - ...customUnit.rates, ...Object.keys(customUnit.rates).reduce((rates, rateID) => { if (customUnit.rates[rateID].attributes?.taxRateExternalID === oldTaxCode) { // eslint-disable-next-line no-param-reassign rates[rateID] = { - ...customUnit.rates[rateID], attributes: { - ...customUnit.rates[rateID].attributes, taxRateExternalID: oldTaxCode, }, }; } return rates; }, {} as Record), - } as Record, + }, }; return units; - }, {} as Record), + }, {} as Record>), }, }; const onyxData: OnyxData = { From c3e63638667ebdad1f8b8f5f8659081282fb39f6 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Wed, 14 Aug 2024 11:20:06 +0300 Subject: [PATCH 052/565] use menuitem list and delegators --- src/components/AccountSwitcher.tsx | 32 +++++++++++++----------------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx index cf4c0491de3..cd1fb9d894f 100644 --- a/src/components/AccountSwitcher.tsx +++ b/src/components/AccountSwitcher.tsx @@ -16,8 +16,8 @@ import ONYXKEYS from '@src/ONYXKEYS'; import Avatar from './Avatar'; import Icon from './Icon'; import * as Expensicons from './Icon/Expensicons'; -import MenuItem from './MenuItem'; import type {MenuItemProps} from './MenuItem'; +import MenuItemList from './MenuItemList'; import Popover from './Popover'; import {PressableWithFeedback} from './Pressable'; import Text from './Text'; @@ -30,16 +30,15 @@ function AccountSwitcher() { const {translate} = useLocalize(); const theme = useTheme(); const {canUseNewDotCopilot} = usePermissions(); + const {isSmallScreenWidth} = useResponsiveLayout(); const [account] = useOnyx(ONYXKEYS.ACCOUNT); - const [shouldShowDelegateMenu, setShouldShowDelegateMenu] = useState(false); - const buttonRef = useRef(null); + const [shouldShowDelegatorMenu, setShouldShowDelegatorMenu] = useState(false); - const delegates = account?.delegatedAccess?.delegates ?? []; - const shouldShowDelegates = delegates.length > 0 && canUseNewDotCopilot; - const {isSmallScreenWidth} = useResponsiveLayout(); + const delegators = account?.delegatedAccess?.delegators ?? []; + const shouldShowDelegators = delegators.length > 0 && canUseNewDotCopilot; - const delegateMenuItems: MenuItemProps[] = delegates.map(({email, role}) => { + const delegatorMenuItems: MenuItemProps[] = delegators.map(({email, role}) => { const personalDetail = getPersonalDetailByEmail(email); return { @@ -57,7 +56,7 @@ function AccountSwitcher() { }; }); - const delegateMenuItemsWithCurrentUser: MenuItemProps[] = [ + const delegatorMenuItemsWithCurrentUser: MenuItemProps[] = [ { title: currentUserPersonalDetails?.displayName ?? currentUserPersonalDetails?.login, description: currentUserPersonalDetails?.displayName ? currentUserPersonalDetails?.login : '', @@ -72,7 +71,7 @@ function AccountSwitcher() { wrapperStyle: [styles.buttonDefaultBG], focused: true, }, - ...delegateMenuItems, + ...delegatorMenuItems, ]; return ( @@ -81,7 +80,7 @@ function AccountSwitcher() { accessible accessibilityLabel={translate('common.profile')} onPress={() => { - setShouldShowDelegateMenu(!shouldShowDelegateMenu); + setShouldShowDelegatorMenu(!shouldShowDelegatorMenu); }} ref={buttonRef} wrapperStyle={[styles.flexGrow1, styles.accountSwitcherWrapper, styles.justifyContentCenter]} @@ -102,7 +101,7 @@ function AccountSwitcher() { > {currentUserPersonalDetails?.displayName} - {shouldShowDelegates && ( + {shouldShowDelegators && ( - {shouldShowDelegates && ( + {shouldShowDelegators && ( setShouldShowDelegateMenu(false)} + isVisible={shouldShowDelegatorMenu} + onClose={() => setShouldShowDelegatorMenu(false)} anchorRef={buttonRef} anchorPosition={styles.accountSwitcherAnchorPosition} > {translate('delegate.switchAccount')} - {delegateMenuItemsWithCurrentUser.map((item) => ( - // eslint-disable-next-line react/jsx-props-no-spreading - - ))} + {/* TODO error handling on API error Oops something went wrong. Please try again */} From fb29be15d6bd7b467feeb960b8cb6e58aa153a26 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Wed, 14 Aug 2024 11:20:15 +0300 Subject: [PATCH 053/565] correct docs --- src/types/onyx/Account.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/types/onyx/Account.ts b/src/types/onyx/Account.ts index 3f726f9884d..776e591de5c 100644 --- a/src/types/onyx/Account.ts +++ b/src/types/onyx/Account.ts @@ -17,10 +17,10 @@ type Delegate = { /** Model of delegated access data */ type DelegatedAccess = { - /** The the users you can access as a delegate */ + /** The users that can access your account as a delegate */ delegates: Delegate[]; - /** The users that can access your account as a delegate */ + /** The the users you can access as a delegate */ delegators: Delegate[]; }; From 477ecb6d9e603898ec5ccca5de555756fb6fdcff Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Wed, 14 Aug 2024 11:27:34 +0300 Subject: [PATCH 054/565] single execution --- src/components/AccountSwitcher.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx index cd1fb9d894f..4de85e9e23d 100644 --- a/src/components/AccountSwitcher.tsx +++ b/src/components/AccountSwitcher.tsx @@ -130,7 +130,10 @@ function AccountSwitcher() { > {translate('delegate.switchAccount')} - + {/* TODO error handling on API error Oops something went wrong. Please try again */} From 46a62e40623c5ba0b30d0398f294daedf50e9eae Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Wed, 14 Aug 2024 11:28:53 +0300 Subject: [PATCH 055/565] import style --- src/components/AccountSwitcher.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx index 4de85e9e23d..4de9b4c4e53 100644 --- a/src/components/AccountSwitcher.tsx +++ b/src/components/AccountSwitcher.tsx @@ -9,7 +9,7 @@ import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {connect} from '@libs/actions/Delegate'; -import {getPersonalDetailByEmail} from '@libs/PersonalDetailsUtils'; +import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; import variables from '@styles/variables'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -39,7 +39,7 @@ function AccountSwitcher() { const shouldShowDelegators = delegators.length > 0 && canUseNewDotCopilot; const delegatorMenuItems: MenuItemProps[] = delegators.map(({email, role}) => { - const personalDetail = getPersonalDetailByEmail(email); + const personalDetail = PersonalDetailsUtils.getPersonalDetailByEmail(email); return { title: personalDetail?.displayName ?? email, From ebce5ec46b5710b47e4f12a41323e153da6fa6c1 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Wed, 14 Aug 2024 11:53:57 +0300 Subject: [PATCH 056/565] change skeleton to fit account switcher --- .../index.tsx | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/components/CurrentUserPersonalDetailsSkeletonView/index.tsx b/src/components/CurrentUserPersonalDetailsSkeletonView/index.tsx index 21e82c26f76..a41d63caeb7 100644 --- a/src/components/CurrentUserPersonalDetailsSkeletonView/index.tsx +++ b/src/components/CurrentUserPersonalDetailsSkeletonView/index.tsx @@ -23,34 +23,31 @@ function CurrentUserPersonalDetailsSkeletonView({shouldAnimate = true, avatarSiz const StyleUtils = useStyleUtils(); const avatarPlaceholderSize = StyleUtils.getAvatarSize(avatarSize); const avatarPlaceholderRadius = avatarPlaceholderSize / 2; - const spaceBetweenAvatarAndHeadline = styles.mb3.marginBottom + styles.mt1.marginTop + (variables.lineHeightXXLarge - variables.fontSizeXLarge) / 2; - const headlineSize = variables.fontSizeXLarge; - const spaceBetweenHeadlineAndLabel = styles.mt1.marginTop + (variables.lineHeightXXLarge - variables.fontSizeXLarge) / 2; - const labelSize = variables.fontSizeLabel; + return ( From 8f4b5b33f6c27394b089ca9ce347850f1dc168fc Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Wed, 14 Aug 2024 11:54:46 +0300 Subject: [PATCH 057/565] rm padding from avatar skeleton --- src/styles/index.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/styles/index.ts b/src/styles/index.ts index dd11f34e86a..40a73f8c01d 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -2808,8 +2808,6 @@ const styles = (theme: ThemeColors) => avatarSectionWrapperSkeleton: { width: '100%', - paddingHorizontal: 20, - paddingBottom: 20, }, avatarSectionWrapperSettings: { From 3d12f3f40842156d23c0b949023dbac11f4f00bc Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Wed, 14 Aug 2024 11:54:55 +0300 Subject: [PATCH 058/565] avatar size medium --- src/pages/settings/InitialSettingsPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/InitialSettingsPage.tsx b/src/pages/settings/InitialSettingsPage.tsx index 73e3c497894..e2449198623 100755 --- a/src/pages/settings/InitialSettingsPage.tsx +++ b/src/pages/settings/InitialSettingsPage.tsx @@ -363,7 +363,7 @@ function InitialSettingsPage({userWallet, bankAccountList, fundList, walletTerms const headerContent = ( {isEmptyObject(currentUserPersonalDetails) || currentUserPersonalDetails.displayName === undefined ? ( - + ) : ( From f0500f5e53dbb33c6e47fee943c645cab517f38a Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Wed, 14 Aug 2024 11:56:15 +0300 Subject: [PATCH 059/565] cleanup --- .../CurrentUserPersonalDetailsSkeletonView/index.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/CurrentUserPersonalDetailsSkeletonView/index.tsx b/src/components/CurrentUserPersonalDetailsSkeletonView/index.tsx index a41d63caeb7..e192a99d7b2 100644 --- a/src/components/CurrentUserPersonalDetailsSkeletonView/index.tsx +++ b/src/components/CurrentUserPersonalDetailsSkeletonView/index.tsx @@ -6,7 +6,6 @@ import SkeletonViewContentLoader from '@components/SkeletonViewContentLoader'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import variables from '@styles/variables'; import CONST from '@src/CONST'; type CurrentUserPersonalDetailsSkeletonViewProps = { @@ -23,6 +22,7 @@ function CurrentUserPersonalDetailsSkeletonView({shouldAnimate = true, avatarSiz const StyleUtils = useStyleUtils(); const avatarPlaceholderSize = StyleUtils.getAvatarSize(avatarSize); const avatarPlaceholderRadius = avatarPlaceholderSize / 2; + const x = 30; return ( @@ -33,18 +33,18 @@ function CurrentUserPersonalDetailsSkeletonView({shouldAnimate = true, avatarSiz height={avatarPlaceholderSize + styles.pb5.paddingBottom} > Date: Wed, 14 Aug 2024 11:58:24 +0300 Subject: [PATCH 060/565] add type for delegate --- src/types/onyx/Account.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/types/onyx/Account.ts b/src/types/onyx/Account.ts index 776e591de5c..114ea57abb8 100644 --- a/src/types/onyx/Account.ts +++ b/src/types/onyx/Account.ts @@ -22,6 +22,9 @@ type DelegatedAccess = { /** The the users you can access as a delegate */ delegators: Delegate[]; + + /** The email of original user when they are acting as a delegate for another account */ + delegate?: string; }; /** Model of user account */ From c0468bfb5cd1c659f63753844ba7e511fb0384d2 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Wed, 14 Aug 2024 12:29:31 +0300 Subject: [PATCH 061/565] add type delegate role --- src/types/onyx/Account.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/types/onyx/Account.ts b/src/types/onyx/Account.ts index 114ea57abb8..a545ed9fdfe 100644 --- a/src/types/onyx/Account.ts +++ b/src/types/onyx/Account.ts @@ -6,13 +6,16 @@ import type * as OnyxCommon from './OnyxCommon'; /** Two factor authentication steps */ type TwoFactorAuthStep = ValueOf | ''; +/** The role of the delegate */ +type DelegateRole = ValueOf; + /** Model of delegate */ type Delegate = { /** The email of the delegate */ email: string; /** The role of the delegate */ - role: 'submitter' | 'all'; + role: DelegateRole; }; /** Model of delegated access data */ @@ -115,4 +118,4 @@ type Account = { }; export default Account; -export type {TwoFactorAuthStep}; +export type {TwoFactorAuthStep, DelegateRole}; From 41da8e80ff59a67aec1d1ec07dcebac1e2eebce5 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Wed, 14 Aug 2024 12:29:44 +0300 Subject: [PATCH 062/565] add mapping for delegate role --- src/languages/en.ts | 11 +++++++++++ src/languages/es.ts | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/languages/en.ts b/src/languages/en.ts index 41d8ffe6148..237c5843729 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -2,6 +2,7 @@ import {CONST as COMMON_CONST, Str} from 'expensify-common'; import {startCase} from 'lodash'; import CONST from '@src/CONST'; import type {Country} from '@src/CONST'; +import type {DelegateRole} from '@src/types/onyx/Account'; import type {ConnectionName, PolicyConnectionSyncStage, SageIntacctMappingName} from '@src/types/onyx/Policy'; import type { AddressLineParams, @@ -4371,5 +4372,15 @@ export default { }, delegate: { switchAccount: 'Switch accounts:', + role: (role: DelegateRole): string => { + switch (role) { + case CONST.DELEGATE_ROLE.ALL: + return 'All'; + case CONST.DELEGATE_ROLE.SUBMITTER: + return 'Limited'; + default: + return ''; + } + }, }, } satisfies TranslationBase; diff --git a/src/languages/es.ts b/src/languages/es.ts index 55a1e222207..941baff62cb 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -1,5 +1,6 @@ import {Str} from 'expensify-common'; import CONST from '@src/CONST'; +import type {DelegateRole} from '@src/types/onyx/Account'; import type {ConnectionName, PolicyConnectionSyncStage, SageIntacctMappingName} from '@src/types/onyx/Policy'; import type { AddressLineParams, @@ -4891,5 +4892,15 @@ export default { }, delegate: { switchAccount: 'Cambiar cuentas:', + role: (role: DelegateRole): string => { + switch (role) { + case CONST.DELEGATE_ROLE.ALL: + return 'All'; + case CONST.DELEGATE_ROLE.SUBMITTER: + return 'Limited'; + default: + return ''; + } + }, }, } satisfies EnglishTranslation; From 4e4ff407c66d2499c909cbf8277e608730f89116 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Wed, 14 Aug 2024 12:30:00 +0300 Subject: [PATCH 063/565] move role to const --- src/CONST.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/CONST.ts b/src/CONST.ts index bad91f18dfe..8a5dd6b5077 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -3905,6 +3905,10 @@ const CONST = { ENABLED: 'ENABLED', DISABLED: 'DISABLED', }, + DELEGATE_ROLE: { + SUBMITTER: 'submitter', + ALL: 'all', + }, STRIPE_GBP_AUTH_STATUSES: { SUCCEEDED: 'succeeded', }, From 22fb81dc8d6ec4fe2fb276076e5b9860c7a67bec Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Wed, 14 Aug 2024 12:31:47 +0300 Subject: [PATCH 064/565] show full or limited as role --- src/components/AccountSwitcher.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx index 4de9b4c4e53..da4160540a3 100644 --- a/src/components/AccountSwitcher.tsx +++ b/src/components/AccountSwitcher.tsx @@ -1,4 +1,3 @@ -import {Str} from 'expensify-common'; import React, {useRef, useState} from 'react'; import {View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; @@ -44,7 +43,7 @@ function AccountSwitcher() { return { title: personalDetail?.displayName ?? email, description: personalDetail?.displayName ? email : '', - badgeText: Str.recapitalize(role), + badgeText: translate('delegate.role', role), onPress: () => { connect(email); }, From 4cd7ab1965cdbf4af83dabb0daec309fa52e283c Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Wed, 14 Aug 2024 11:35:05 +0200 Subject: [PATCH 065/565] fix: add a comment --- src/CONST.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CONST.ts b/src/CONST.ts index 312a084aba3..48b669bbe56 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -632,6 +632,7 @@ const CONST = { INBOX: 'inbox', }, + // TODO: change to expensify-policy once the new domain is available EXPENSIFY_POLICY_DOMAIN: 'expensify_policy', EXPENSIFY_POLICY_DOMAIN_EXTENSION: '.exfy', From 65df1c22706708c0e87303e7af0d14abcf8ee2b3 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Wed, 14 Aug 2024 12:35:23 +0300 Subject: [PATCH 066/565] show full or limited as role --- src/languages/en.ts | 2 +- src/languages/es.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index 237c5843729..675e8635e77 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -4375,7 +4375,7 @@ export default { role: (role: DelegateRole): string => { switch (role) { case CONST.DELEGATE_ROLE.ALL: - return 'All'; + return 'Full'; case CONST.DELEGATE_ROLE.SUBMITTER: return 'Limited'; default: diff --git a/src/languages/es.ts b/src/languages/es.ts index 941baff62cb..536b73c9a80 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -4895,9 +4895,9 @@ export default { role: (role: DelegateRole): string => { switch (role) { case CONST.DELEGATE_ROLE.ALL: - return 'All'; + return 'Completo'; case CONST.DELEGATE_ROLE.SUBMITTER: - return 'Limited'; + return 'Limitado'; default: return ''; } From d43e7a87b6f821aee884eb307bcb4227448a7461 Mon Sep 17 00:00:00 2001 From: daledah Date: Wed, 14 Aug 2024 17:44:43 +0700 Subject: [PATCH 067/565] refactor: simplify failureCustomUnits --- src/libs/actions/TaxRate.ts | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/src/libs/actions/TaxRate.ts b/src/libs/actions/TaxRate.ts index decb74c1a64..29aa3c2fadf 100644 --- a/src/libs/actions/TaxRate.ts +++ b/src/libs/actions/TaxRate.ts @@ -512,27 +512,7 @@ function setPolicyTaxCode(policyID: string, oldTaxCode: string, newTaxCode: stri }, }; const failureCustomUnit = { - customUnits: { - ...customUnits.reduce((units, customUnit) => { - // eslint-disable-next-line no-param-reassign - units[customUnit.customUnitID] = { - rates: { - ...Object.keys(customUnit.rates).reduce((rates, rateID) => { - if (customUnit.rates[rateID].attributes?.taxRateExternalID === oldTaxCode) { - // eslint-disable-next-line no-param-reassign - rates[rateID] = { - attributes: { - taxRateExternalID: oldTaxCode, - }, - }; - } - return rates; - }, {} as Record), - }, - }; - return units; - }, {} as Record>), - }, + customUnits: policy?.customUnits, }; const onyxData: OnyxData = { optimisticData: [ From 4a30ea6af49f6415e4490055319815c8deb2cabf Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Wed, 14 Aug 2024 15:51:08 +0300 Subject: [PATCH 068/565] add error msg to translate --- src/languages/en.ts | 1 + src/languages/es.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/src/languages/en.ts b/src/languages/en.ts index 675e8635e77..4ce7cf9fa81 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -4382,5 +4382,6 @@ export default { return ''; } }, + genericError: 'Oops something went wrong. Please try again.', }, } satisfies TranslationBase; diff --git a/src/languages/es.ts b/src/languages/es.ts index 536b73c9a80..6feee19b523 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -4902,5 +4902,6 @@ export default { return ''; } }, + genericError: 'Oops algo salió mal. Por favor, inténtalo de nuevo.', }, } satisfies EnglishTranslation; From 19f2501212f758904eb0bcc91a671579af60c546 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Wed, 14 Aug 2024 15:51:37 +0300 Subject: [PATCH 069/565] show error message in account switcher --- src/components/AccountSwitcher.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx index da4160540a3..02929c133f3 100644 --- a/src/components/AccountSwitcher.tsx +++ b/src/components/AccountSwitcher.tsx @@ -37,21 +37,23 @@ function AccountSwitcher() { const delegators = account?.delegatedAccess?.delegators ?? []; const shouldShowDelegators = delegators.length > 0 && canUseNewDotCopilot; - const delegatorMenuItems: MenuItemProps[] = delegators.map(({email, role}) => { + const delegatorMenuItems: MenuItemProps[] = delegators.map(({email, role, error}) => { const personalDetail = PersonalDetailsUtils.getPersonalDetailByEmail(email); - return { title: personalDetail?.displayName ?? email, description: personalDetail?.displayName ? email : '', badgeText: translate('delegate.role', role), onPress: () => { - connect(email); + connect(email, role); }, avatarID: personalDetail?.accountID ?? -1, icon: personalDetail?.avatar ?? '', iconType: CONST.ICON_TYPE_AVATAR, outerWrapperStyle: isSmallScreenWidth ? {} : styles.accountSwitcherPopover, numberOfLinesDescription: 1, + errorText: error ? translate(error) : '', + shouldShowRedDotIndicator: !!error, + errorTextStyle: styles.mt2, }; }); @@ -133,7 +135,6 @@ function AccountSwitcher() { menuItems={delegatorMenuItemsWithCurrentUser} shouldUseSingleExecution /> - {/* TODO error handling on API error Oops something went wrong. Please try again */} )} From 97e581d886b92a1a10bd970f124a3b1d2c078a22 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Wed, 14 Aug 2024 15:52:18 +0300 Subject: [PATCH 070/565] add onyx data to handle errors --- src/libs/actions/Delegate.ts | 64 ++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/src/libs/actions/Delegate.ts b/src/libs/actions/Delegate.ts index 2a3295a9dfd..107ee41d5af 100644 --- a/src/libs/actions/Delegate.ts +++ b/src/libs/actions/Delegate.ts @@ -1,18 +1,70 @@ import Onyx from 'react-native-onyx'; +import type {OnyxUpdate} from 'react-native-onyx'; import * as API from '@libs/API'; import {SIDE_EFFECT_REQUEST_COMMANDS} from '@libs/API/types'; +import Log from '@libs/Log'; import * as NetworkStore from '@libs/Network/NetworkStore'; import * as SequentialQueue from '@libs/Network/SequentialQueue'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type {DelegatedAccess, DelegateRole} from '@src/types/onyx/Account'; import {openApp} from './App'; import updateSessionAuthTokens from './Session/updateSessionAuthTokens'; -function connect(email: string) { +let delegatedAccess: DelegatedAccess; +Onyx.connect({ + key: ONYXKEYS.ACCOUNT, + callback: (val) => { + delegatedAccess = val?.delegatedAccess ?? {}; + }, +}); + +function connect(email: string, role: DelegateRole) { + if (!delegatedAccess?.delegators) { + return; + } + + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.ACCOUNT, + value: { + delegatedAccess: { + delegators: delegatedAccess.delegators.map((delegator) => (delegator.email === email ? {email, role, error: undefined} : delegator)), + }, + }, + }, + ]; + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.ACCOUNT, + value: { + delegatedAccess: { + delegators: delegatedAccess.delegators.map((delegator) => (delegator.email === email ? {email, role, error: undefined} : delegator)), + }, + }, + }, + ]; + + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.ACCOUNT, + value: { + delegatedAccess: { + delegators: delegatedAccess.delegators.map((delegator) => (delegator.email === email ? {email, role, error: 'delegate.genericError'} : delegator)), + }, + }, + }, + ]; + // eslint-disable-next-line rulesdir/no-api-side-effects-method - API.makeRequestWithSideEffects(SIDE_EFFECT_REQUEST_COMMANDS.CONNECT_AS_DELEGATE, {to: email}, {}) + API.makeRequestWithSideEffects(SIDE_EFFECT_REQUEST_COMMANDS.CONNECT_AS_DELEGATE, {to: email}, {optimisticData, successData, failureData}) .then((response) => { if (!response?.restrictedToken || !response?.encryptedAuthToken) { - // TODO: Show an error message to the user - console.error('Error during connect: No authToken returned'); + Log.alert('[Delegate] No auth token returned while connecting as a delegate'); + Onyx.update(failureData); return; } return SequentialQueue.waitForIdle() @@ -26,8 +78,8 @@ function connect(email: string) { }); }) .catch((error) => { - // TODO: Show an error message to the user - console.error('Error during connect:', error); + Log.alert('[Delegate] Error connecting as delegate', {error}); + Onyx.update(failureData); }); } From 313e8e9cd93efbec07a60beeef04faad45ee2a6e Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Wed, 14 Aug 2024 15:53:42 +0300 Subject: [PATCH 071/565] add error type --- src/types/onyx/Account.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/types/onyx/Account.ts b/src/types/onyx/Account.ts index a545ed9fdfe..e1356e7e613 100644 --- a/src/types/onyx/Account.ts +++ b/src/types/onyx/Account.ts @@ -1,5 +1,6 @@ import type {ValueOf} from 'type-fest'; import type CONST from '@src/CONST'; +import type {TranslationPaths} from '@src/languages/types'; import type DismissedReferralBanners from './DismissedReferralBanners'; import type * as OnyxCommon from './OnyxCommon'; @@ -16,15 +17,18 @@ type Delegate = { /** The role of the delegate */ role: DelegateRole; + + /** Authentication failure errors */ + error?: TranslationPaths; }; /** Model of delegated access data */ type DelegatedAccess = { /** The users that can access your account as a delegate */ - delegates: Delegate[]; + delegates?: Delegate[]; /** The the users you can access as a delegate */ - delegators: Delegate[]; + delegators?: Delegate[]; /** The email of original user when they are acting as a delegate for another account */ delegate?: string; @@ -118,4 +122,4 @@ type Account = { }; export default Account; -export type {TwoFactorAuthStep, DelegateRole}; +export type {TwoFactorAuthStep, DelegateRole, DelegatedAccess}; From 91f2ecf27844acb84c8091b379130ce0af97547e Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Wed, 14 Aug 2024 16:03:29 +0300 Subject: [PATCH 072/565] clear errors after closing popover --- src/components/AccountSwitcher.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx index 02929c133f3..b42e9a9a582 100644 --- a/src/components/AccountSwitcher.tsx +++ b/src/components/AccountSwitcher.tsx @@ -7,7 +7,7 @@ import usePermissions from '@hooks/usePermissions'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import {connect} from '@libs/actions/Delegate'; +import {clearDelegatorErrors, connect} from '@libs/actions/Delegate'; import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; import variables from '@styles/variables'; import CONST from '@src/CONST'; @@ -44,7 +44,7 @@ function AccountSwitcher() { description: personalDetail?.displayName ? email : '', badgeText: translate('delegate.role', role), onPress: () => { - connect(email, role); + connect(email); }, avatarID: personalDetail?.accountID ?? -1, icon: personalDetail?.avatar ?? '', @@ -125,7 +125,10 @@ function AccountSwitcher() { {shouldShowDelegators && ( setShouldShowDelegatorMenu(false)} + onClose={() => { + setShouldShowDelegatorMenu(false); + clearDelegatorErrors(); + }} anchorRef={buttonRef} anchorPosition={styles.accountSwitcherAnchorPosition} > From ba51bba5cd046d60210ecdc37b3de925527bef97 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Wed, 14 Aug 2024 16:03:45 +0300 Subject: [PATCH 073/565] add func to clear errors --- src/libs/actions/Delegate.ts | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/libs/actions/Delegate.ts b/src/libs/actions/Delegate.ts index 107ee41d5af..8f7654f4f1c 100644 --- a/src/libs/actions/Delegate.ts +++ b/src/libs/actions/Delegate.ts @@ -18,7 +18,7 @@ Onyx.connect({ }, }); -function connect(email: string, role: DelegateRole) { +function connect(email: string) { if (!delegatedAccess?.delegators) { return; } @@ -29,7 +29,7 @@ function connect(email: string, role: DelegateRole) { key: ONYXKEYS.ACCOUNT, value: { delegatedAccess: { - delegators: delegatedAccess.delegators.map((delegator) => (delegator.email === email ? {email, role, error: undefined} : delegator)), + delegators: delegatedAccess.delegators.map((delegator) => (delegator.email === email ? {...delegator, error: undefined} : delegator)), }, }, }, @@ -41,7 +41,7 @@ function connect(email: string, role: DelegateRole) { key: ONYXKEYS.ACCOUNT, value: { delegatedAccess: { - delegators: delegatedAccess.delegators.map((delegator) => (delegator.email === email ? {email, role, error: undefined} : delegator)), + delegators: delegatedAccess.delegators.map((delegator) => (delegator.email === email ? {...delegator, error: undefined} : delegator)), }, }, }, @@ -53,7 +53,7 @@ function connect(email: string, role: DelegateRole) { key: ONYXKEYS.ACCOUNT, value: { delegatedAccess: { - delegators: delegatedAccess.delegators.map((delegator) => (delegator.email === email ? {email, role, error: 'delegate.genericError'} : delegator)), + delegators: delegatedAccess.delegators.map((delegator) => (delegator.email === email ? {...delegator, error: 'delegate.genericError'} : delegator)), }, }, }, @@ -83,5 +83,12 @@ function connect(email: string, role: DelegateRole) { }); } +function clearDelegatorErrors() { + if (!delegatedAccess?.delegators) { + return; + } + Onyx.merge(ONYXKEYS.ACCOUNT, {delegatedAccess: {delegators: delegatedAccess.delegators.map((delegator) => ({...delegator, error: undefined}))}}); +} + // eslint-disable-next-line import/prefer-default-export -export {connect}; +export {connect, clearDelegatorErrors}; From 0576180fb180fe0a9597ec6a61476281a42d2ec0 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Wed, 14 Aug 2024 16:06:09 +0300 Subject: [PATCH 074/565] cleanup --- src/libs/actions/Delegate.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Delegate.ts b/src/libs/actions/Delegate.ts index 8f7654f4f1c..8a66a537f27 100644 --- a/src/libs/actions/Delegate.ts +++ b/src/libs/actions/Delegate.ts @@ -6,7 +6,7 @@ import Log from '@libs/Log'; import * as NetworkStore from '@libs/Network/NetworkStore'; import * as SequentialQueue from '@libs/Network/SequentialQueue'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {DelegatedAccess, DelegateRole} from '@src/types/onyx/Account'; +import type {DelegatedAccess} from '@src/types/onyx/Account'; import {openApp} from './App'; import updateSessionAuthTokens from './Session/updateSessionAuthTokens'; From 0312b7cb797c298f227224c9adb450ea198c5b70 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Wed, 14 Aug 2024 16:24:08 +0300 Subject: [PATCH 075/565] add min width 0 --- src/styles/utils/sizing.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/styles/utils/sizing.ts b/src/styles/utils/sizing.ts index 8d75294564b..f4be70391eb 100644 --- a/src/styles/utils/sizing.ts +++ b/src/styles/utils/sizing.ts @@ -52,6 +52,10 @@ export default { minHeight: 0, }, + mnw0: { + minWidth: 0, + }, + mnw2: { minWidth: 8, }, From f2da059c9246090984307c6cfba599f03958e8f1 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Wed, 14 Aug 2024 16:24:18 +0300 Subject: [PATCH 076/565] cleanup --- src/components/AccountSwitcher.tsx | 2 +- src/styles/index.ts | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx index b42e9a9a582..f4533f292ac 100644 --- a/src/components/AccountSwitcher.tsx +++ b/src/components/AccountSwitcher.tsx @@ -84,7 +84,7 @@ function AccountSwitcher() { setShouldShowDelegatorMenu(!shouldShowDelegatorMenu); }} ref={buttonRef} - wrapperStyle={[styles.flexGrow1, styles.accountSwitcherWrapper, styles.justifyContentCenter]} + wrapperStyle={[styles.flexGrow1, styles.flex1, styles.mnw0, styles.justifyContentCenter]} > backgroundColor: theme.border, }, - accountSwitcherWrapper: { - minWidth: 0, - flex: 1, - }, - accountSwitcherPopover: { width: variables.sideBarWidth - 19, }, From 964fdd536f1c6342b2b2b80cc182d3c7baa550bf Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Thu, 15 Aug 2024 05:34:23 +0300 Subject: [PATCH 077/565] preserve keys for copilot --- src/libs/actions/Delegate.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Delegate.ts b/src/libs/actions/Delegate.ts index 8a66a537f27..f33ea5d4663 100644 --- a/src/libs/actions/Delegate.ts +++ b/src/libs/actions/Delegate.ts @@ -68,7 +68,7 @@ function connect(email: string) { return; } return SequentialQueue.waitForIdle() - .then(() => Onyx.clear()) + .then(() => Onyx.clear([ONYXKEYS.NVP_TRY_FOCUS_MODE, ONYXKEYS.PREFERRED_THEME, ONYXKEYS.NVP_PREFERRED_LOCALE, ONYXKEYS.SESSION])) .then(() => { // Update authToken in Onyx and in our local variables so that API requests will use the new authToken updateSessionAuthTokens(response?.restrictedToken, response?.encryptedAuthToken); From c38d79882f0b32a49ed29ce4140152f0da082b8f Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Thu, 15 Aug 2024 05:36:21 +0300 Subject: [PATCH 078/565] move to const --- src/libs/actions/Delegate.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libs/actions/Delegate.ts b/src/libs/actions/Delegate.ts index f33ea5d4663..7eaaee798be 100644 --- a/src/libs/actions/Delegate.ts +++ b/src/libs/actions/Delegate.ts @@ -18,6 +18,8 @@ Onyx.connect({ }, }); +const KEYS_TO_PRESERVE_DELEGATE_ACCESS = [ONYXKEYS.NVP_TRY_FOCUS_MODE, ONYXKEYS.PREFERRED_THEME, ONYXKEYS.NVP_PREFERRED_LOCALE, ONYXKEYS.SESSION]; + function connect(email: string) { if (!delegatedAccess?.delegators) { return; @@ -68,7 +70,7 @@ function connect(email: string) { return; } return SequentialQueue.waitForIdle() - .then(() => Onyx.clear([ONYXKEYS.NVP_TRY_FOCUS_MODE, ONYXKEYS.PREFERRED_THEME, ONYXKEYS.NVP_PREFERRED_LOCALE, ONYXKEYS.SESSION])) + .then(() => Onyx.clear(KEYS_TO_PRESERVE_DELEGATE_ACCESS)) .then(() => { // Update authToken in Onyx and in our local variables so that API requests will use the new authToken updateSessionAuthTokens(response?.restrictedToken, response?.encryptedAuthToken); From 907d57af3449d137ed13725c8d9841a7321eedc5 Mon Sep 17 00:00:00 2001 From: daledah Date: Thu, 15 Aug 2024 11:06:50 +0700 Subject: [PATCH 079/565] fix: remove settled transactions from duplicates --- .../MoneyRequestPreview/MoneyRequestPreviewContent.tsx | 10 ++++++---- src/libs/ReportUtils.ts | 5 +++++ src/libs/TransactionUtils/index.ts | 5 +++-- src/pages/TransactionDuplicate/Review.tsx | 4 ++++ 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx index 8597654576f..df463acc12c 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx @@ -125,9 +125,11 @@ function MoneyRequestPreviewContent({ // Get transaction violations for given transaction id from onyx, find duplicated transactions violations and get duplicates const duplicates = useMemo( () => - transactionViolations?.[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transaction?.transactionID}`]?.find( - (violation) => violation.name === CONST.VIOLATIONS.DUPLICATED_TRANSACTION, - )?.data?.duplicates ?? [], + ReportUtils.removeSettledTransactions( + transactionViolations?.[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transaction?.transactionID}`]?.find( + (violation) => violation.name === CONST.VIOLATIONS.DUPLICATED_TRANSACTION, + )?.data?.duplicates ?? [], + ), [transaction?.transactionID, transactionViolations], ); @@ -438,7 +440,7 @@ function MoneyRequestPreviewContent({ ]} > {childContainer} - {isReviewDuplicateTransactionPage && ( + {isReviewDuplicateTransactionPage && !isSettled && (
- { - setIsConfirmModalVisible(false); - setStep(CONST.TWO_FACTOR_AUTH_STEPS.DISABLED); - Session.toggleTwoFactorAuth(false); - }} - onCancel={() => setIsConfirmModalVisible(false)} - onModalHide={() => setIsConfirmModalVisible(false)} - isVisible={isConfirmModalVisible} - prompt={translate('twoFactorAuth.disableTwoFactorAuthConfirmation')} - confirmText={translate('common.disable')} - cancelText={translate('common.cancel')} - shouldShowCancelButton - danger - /> ); diff --git a/src/pages/settings/Security/TwoFactorAuth/Steps/GetCode.tsx b/src/pages/settings/Security/TwoFactorAuth/Steps/GetCode.tsx index 5843bedba75..6d963f3ec44 100644 --- a/src/pages/settings/Security/TwoFactorAuth/Steps/GetCode.tsx +++ b/src/pages/settings/Security/TwoFactorAuth/Steps/GetCode.tsx @@ -1,6 +1,6 @@ import type {RouteProp} from '@react-navigation/native'; import {useRoute} from '@react-navigation/native'; -import React, {useEffect, useRef, useState} from 'react'; +import React, {useEffect, useRef} from 'react'; import {ActivityIndicator, View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import Button from '@components/Button'; From 61af1b2942ddd5cb0d9ca74cf25c92e2bec267f3 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Mon, 26 Aug 2024 14:05:05 -0600 Subject: [PATCH 294/565] Clean up imports --- .../Security/TwoFactorAuth/Steps/GetCode.tsx | 24 ++++--------------- .../TwoFactorAuth/TwoFactorAuthSteps.tsx | 2 +- 2 files changed, 5 insertions(+), 21 deletions(-) diff --git a/src/pages/settings/Security/TwoFactorAuth/Steps/GetCode.tsx b/src/pages/settings/Security/TwoFactorAuth/Steps/GetCode.tsx index 6d963f3ec44..45cc899498f 100644 --- a/src/pages/settings/Security/TwoFactorAuth/Steps/GetCode.tsx +++ b/src/pages/settings/Security/TwoFactorAuth/Steps/GetCode.tsx @@ -1,35 +1,19 @@ -import type {RouteProp} from '@react-navigation/native'; -import {useRoute} from '@react-navigation/native'; -import React, {useEffect, useRef} from 'react'; -import {ActivityIndicator, View} from 'react-native'; +import React, {useRef} from 'react'; +import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import Button from '@components/Button'; import FixedFooter from '@components/FixedFooter'; -import FormHelpMessage from '@components/FormHelpMessage'; -import * as Expensicons from '@components/Icon/Expensicons'; -import * as Illustrations from '@components/Icon/Illustrations'; -import PressableWithDelayToggle from '@components/Pressable/PressableWithDelayToggle'; import ScrollView from '@components/ScrollView'; -import Section from '@components/Section'; import Text from '@components/Text'; -import ValidateAccountMessage from '@components/ValidateAccountMessage'; import useLocalize from '@hooks/useLocalize'; -import useResponsiveLayout from '@hooks/useResponsiveLayout'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import Clipboard from '@libs/Clipboard'; -import localFileDownload from '@libs/localFileDownload'; -import type {BackToParams, SettingsNavigatorParamList} from '@libs/Navigation/types'; +import type {BackToParams} from '@libs/Navigation/types'; import StepWrapper from '@pages/settings/Security/TwoFactorAuth/StepWrapper/StepWrapper'; import useTwoFactorAuthContext from '@pages/settings/Security/TwoFactorAuth/TwoFactorAuthContext/useTwoFactorAuth'; import TwoFactorAuthForm from '@pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm'; -import type {BaseTwoFactorAuthFormOnyxProps} from '@pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/types'; -import * as Session from '@userActions/Session'; -import * as TwoFactorAuthActions from '@userActions/TwoFactorAuthActions'; +import type {BaseTwoFactorAuthFormOnyxProps, BaseTwoFactorAuthFormRef} from '@pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/types'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; -import type SCREENS from '@src/SCREENS'; type CodesStepProps = BaseTwoFactorAuthFormOnyxProps & BackToParams; diff --git a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthSteps.tsx b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthSteps.tsx index ca8af81e170..c49b88c2ac0 100644 --- a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthSteps.tsx +++ b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthSteps.tsx @@ -13,9 +13,9 @@ import type {TwoFactorAuthStep} from '@src/types/onyx/Account'; import CodesStep from './Steps/CodesStep'; import DisabledStep from './Steps/DisabledStep'; import EnabledStep from './Steps/EnabledStep'; +import GetCodeStep from './Steps/GetCode'; import SuccessStep from './Steps/SuccessStep'; import VerifyStep from './Steps/VerifyStep'; -import GetCodeStep from './Steps/GetCode'; import TwoFactorAuthContext from './TwoFactorAuthContext'; import type {BaseTwoFactorAuthFormOnyxProps} from './TwoFactorAuthForm/types'; From 65c3218ec0cce52982af8ed7de377f29c2279425 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Mon, 26 Aug 2024 14:52:11 -0600 Subject: [PATCH 295/565] Add comment and fix parameter --- src/libs/actions/Session/index.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libs/actions/Session/index.ts b/src/libs/actions/Session/index.ts index 503f0de17ea..133c395c7d6 100644 --- a/src/libs/actions/Session/index.ts +++ b/src/libs/actions/Session/index.ts @@ -878,7 +878,7 @@ function unlinkLogin(accountID: number, validateCode: string) { /** * Toggles two-factor authentication based on the `enable` parameter */ -function toggleTwoFactorAuth(enable: boolean, twoFactorAuthCode: string) { +function toggleTwoFactorAuth(enable: boolean, twoFactorAuthCode = '') { const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, @@ -895,6 +895,8 @@ function toggleTwoFactorAuth(enable: boolean, twoFactorAuthCode: string) { key: ONYXKEYS.ACCOUNT, value: { isLoading: false, + + // When disabling 2FA, the user needs to end up on the step that confirms the setting was disabled twoFactorAuthStep: enable ? undefined : CONST.TWO_FACTOR_AUTH_STEPS.DISABLED, }, }, From 48360bc52dc21cd8e8b88d3f5977a2b2784bda3d Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Mon, 26 Aug 2024 14:57:28 -0600 Subject: [PATCH 296/565] Remove unused translations --- src/languages/en.ts | 1 - src/languages/es.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index e22822bc5ac..9da1dda30c0 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1110,7 +1110,6 @@ export default { twoFactorAuthEnabled: 'Two-factor authentication enabled', whatIsTwoFactorAuth: 'Two-factor authentication (2FA) helps keep your account safe. When logging in, you’ll need to enter a code generated by your preferred authenticator app.', disableTwoFactorAuth: 'Disable two-factor authentication', - disableTwoFactorAuthConfirmation: 'Two-factor authentication keeps your account more secure. Are you sure you want to disable it?', explainProcessToRemove: 'In order to disable Two-factor authentication, please enter a valid code from your authentication app.', disabled: 'Two-factor authentication is now disabled', noAuthenticatorApp: 'You’ll no longer require an authenticator app to log into Expensify.', diff --git a/src/languages/es.ts b/src/languages/es.ts index 9423a91b042..ed1fb12de3a 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -1115,7 +1115,6 @@ export default { whatIsTwoFactorAuth: 'La autenticación de dos factores (2FA) ayuda a mantener tu cuenta segura. Al iniciar sesión, deberás ingresar un código generado por tu aplicación de autenticación preferida.', disableTwoFactorAuth: 'Deshabilitar la autenticación de dos factores', - disableTwoFactorAuthConfirmation: 'La autenticación de dos factores mantiene tu cuenta más segura. ¿Estás seguro de que quieres desactivarla?', explainProcessToRemove: 'In order to disable Two-factor authentication, please enter a valid code from your authentication app.', disabled: 'La autenticación de dos factores está ahora deshabilitada', noAuthenticatorApp: 'Ya no necesitarás una aplicación de autenticación para iniciar sesión en Expensify.', From 5cd9a8e6bb37510570eade23485269079661bbd2 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Mon, 26 Aug 2024 15:22:21 -0600 Subject: [PATCH 297/565] Lint --- .../settings/Security/TwoFactorAuth/Steps/EnabledStep.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/pages/settings/Security/TwoFactorAuth/Steps/EnabledStep.tsx b/src/pages/settings/Security/TwoFactorAuth/Steps/EnabledStep.tsx index 39b1b695ed4..ae9156928da 100644 --- a/src/pages/settings/Security/TwoFactorAuth/Steps/EnabledStep.tsx +++ b/src/pages/settings/Security/TwoFactorAuth/Steps/EnabledStep.tsx @@ -1,6 +1,5 @@ -import React, {useState} from 'react'; +import React from 'react'; import {View} from 'react-native'; -import ConfirmModal from '@components/ConfirmModal'; import * as Expensicons from '@components/Icon/Expensicons'; import * as Illustrations from '@components/Icon/Illustrations'; import ScrollView from '@components/ScrollView'; @@ -11,13 +10,11 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import StepWrapper from '@pages/settings/Security/TwoFactorAuth/StepWrapper/StepWrapper'; import useTwoFactorAuthContext from '@pages/settings/Security/TwoFactorAuth/TwoFactorAuthContext/useTwoFactorAuth'; -import * as Session from '@userActions/Session'; import CONST from '@src/CONST'; function EnabledStep() { const theme = useTheme(); const styles = useThemeStyles(); - const [isConfirmModalVisible, setIsConfirmModalVisible] = useState(false); const {setStep} = useTwoFactorAuthContext(); From 2f6850227fd534ae96bb5c72a79dfdf06a621014 Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Mon, 26 Aug 2024 18:17:50 -0600 Subject: [PATCH 298/565] rm dead code --- src/libs/SearchUtils.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/libs/SearchUtils.ts b/src/libs/SearchUtils.ts index ce2429c5653..5baf35fee51 100644 --- a/src/libs/SearchUtils.ts +++ b/src/libs/SearchUtils.ts @@ -291,11 +291,6 @@ function getSortedSections(type: SearchDataTypes, status: SearchStatus, data: Li } } -function getQueryHash(query: string, policyID?: string, sortBy?: string, sortOrder?: string): number { - const textToHash = [query, policyID, sortOrder, sortBy].filter(Boolean).join('_'); - return UserUtils.hashText(textToHash, 2 ** 32); -} - function getSortedTransactionData(data: TransactionListItemType[], sortBy?: SearchColumnType, sortOrder?: SortOrder) { if (!sortBy || !sortOrder) { return data; @@ -601,7 +596,6 @@ export { getCurrentSearchParams, getFilters, getListItem, - getQueryHash, getSearchHeaderTitle, getSearchType, getSections, From 07bd8a1fcd24ea7e1f1b77be682ecbe9367c81d0 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Tue, 27 Aug 2024 10:22:58 +0700 Subject: [PATCH 299/565] fix: lint --- .../settings/Subscription/CardAuthenticationModal/index.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pages/settings/Subscription/CardAuthenticationModal/index.tsx b/src/pages/settings/Subscription/CardAuthenticationModal/index.tsx index a48386d4982..6f49e9bd050 100644 --- a/src/pages/settings/Subscription/CardAuthenticationModal/index.tsx +++ b/src/pages/settings/Subscription/CardAuthenticationModal/index.tsx @@ -6,11 +6,9 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Modal from '@components/Modal'; import ScreenWrapper from '@components/ScreenWrapper'; import useThemeStyles from '@hooks/useThemeStyles'; -import Navigation from '@libs/Navigation/Navigation'; import * as PaymentMethods from '@userActions/PaymentMethods'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; type CardAuthenticationModalProps = { /** Title shown in the header of the modal */ From a32c06ba71c5a60640fbb32e64e092ec06abe1cf Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Tue, 27 Aug 2024 12:30:15 +0800 Subject: [PATCH 300/565] disconnect it earlier --- src/libs/actions/Report.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index d21e9cd086c..bc5f7a347cd 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -2668,9 +2668,15 @@ function openReportFromDeepLink(url: string) { // Navigate to the report after sign-in/sign-up. InteractionManager.runAfterInteractions(() => { Session.waitForUserSignIn().then(() => { - const connectionID = Onyx.connect({ + const connection = Onyx.connect({ key: ONYXKEYS.NVP_ONBOARDING, callback: (onboarding) => { + if (onboarding) { + // Once the onboarding data is available, we want to disconnect the connection + // so it won't trigger the deeplink again every time the data is changed, for example, when relogin. + Onyx.disconnect(connection); + } + Navigation.waitForProtectedRoutes().then(() => { if (route && Session.isAnonymousUser() && !Session.canAnonymousUserAccessRoute(route)) { Session.signOutAndRedirectToSignIn(true); @@ -2707,7 +2713,6 @@ function openReportFromDeepLink(url: string) { return; } - Onyx.disconnect(connectionID); Navigation.navigate(route as Route, CONST.NAVIGATION.ACTION_TYPE.PUSH); }); }, From 212197d87242ce96091859cd0d8355a4f2594019 Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Tue, 27 Aug 2024 08:31:18 +0200 Subject: [PATCH 301/565] code review updates --- src/libs/ExportOnyxState/common.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/libs/ExportOnyxState/common.ts b/src/libs/ExportOnyxState/common.ts index 044f2e38c3e..87766814954 100644 --- a/src/libs/ExportOnyxState/common.ts +++ b/src/libs/ExportOnyxState/common.ts @@ -2,6 +2,8 @@ import {Str} from 'expensify-common'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Session} from '@src/types/onyx'; +const MASKING_PATTERN = '***'; + const maskSessionDetails = (data: Record): Record => { const session = data.session as Session; @@ -9,7 +11,7 @@ const maskSessionDetails = (data: Record): Record, parentKey?: string): Rec const value = data[key]; if (typeof value === 'string' && Str.isValidEmail(value)) { - maskedData[key] = '***'; + maskedData[key] = MASKING_PATTERN; } else if (parentKey && parentKey.includes(ONYXKEYS.COLLECTION.REPORT_ACTIONS) && (key === 'text' || key === 'html')) { - maskedData[key] = '***'; + maskedData[key] = MASKING_PATTERN; } else if (typeof value === 'object') { maskedData[key] = maskFragileData(value as Record, key.includes(ONYXKEYS.COLLECTION.REPORT_ACTIONS) ? key : parentKey); } else { @@ -49,10 +51,10 @@ const maskFragileData = (data: Record, parentKey?: string): Rec const maskOnyxState = (data: Record, isMaskingFragileDataEnabled?: boolean) => { let onyxState = data; // Mask session details by default - onyxState = maskSessionDetails(data); + onyxState = maskSessionDetails(onyxState); // Mask fragile data other than session details if the user has enabled the option if (isMaskingFragileDataEnabled) { - onyxState = maskFragileData(data); + onyxState = maskFragileData(onyxState); } return onyxState; From f05103950b0050eb46fa5d34aff2ebfee0746c0b Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Tue, 27 Aug 2024 10:18:19 +0300 Subject: [PATCH 302/565] avoid merge conflicts --- ...ddedFeedEmptyState.svg => emptystate__card-pos.svg} | 0 src/components/Icon/Illustrations.ts | 4 ++-- .../WorkspaceCompanyCardsFeedAddedEmptyPage.tsx | 4 ++-- src/styles/index.ts | 10 +++++----- 4 files changed, 9 insertions(+), 9 deletions(-) rename assets/images/companyCards/{addedFeedEmptyState.svg => emptystate__card-pos.svg} (100%) diff --git a/assets/images/companyCards/addedFeedEmptyState.svg b/assets/images/companyCards/emptystate__card-pos.svg similarity index 100% rename from assets/images/companyCards/addedFeedEmptyState.svg rename to assets/images/companyCards/emptystate__card-pos.svg diff --git a/src/components/Icon/Illustrations.ts b/src/components/Icon/Illustrations.ts index 555ec27ce31..b9f64238a62 100644 --- a/src/components/Icon/Illustrations.ts +++ b/src/components/Icon/Illustrations.ts @@ -1,4 +1,4 @@ -import EmptyAddedFeedState from '@assets/images/companyCards/addedFeedEmptyState.svg'; +import CompanyCardsEmptyState from '@assets/images/companyCards/emptystate__card-pos.svg'; import EmptyCardState from '@assets/images/emptystate__expensifycard.svg'; import ExpensifyCardIllustration from '@assets/images/expensifyCard/cardIllustration.svg'; import LaptopwithSecondScreenandHourglass from '@assets/images/LaptopwithSecondScreenandHourglass.svg'; @@ -215,9 +215,9 @@ export { EmptyState, FolderWithPapers, VirtualCard, - EmptyAddedFeedState, Tire, BigVault, Filters, Rules, + CompanyCardsEmptyState, }; diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsFeedAddedEmptyPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsFeedAddedEmptyPage.tsx index 719aba504b4..ff268bc51b6 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsFeedAddedEmptyPage.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsFeedAddedEmptyPage.tsx @@ -14,9 +14,9 @@ function WorkspaceCompanyCardsFeedAddedEmptyPage() { diff --git a/src/styles/index.ts b/src/styles/index.ts index c4d44fdde22..1183d349bab 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -5067,6 +5067,11 @@ const styles = (theme: ThemeColors) => height: 188, }, + emptyStateCardIllustration: { + width: 164, + height: 190, + }, + cardIcon: { overflow: 'hidden', borderRadius: variables.cardBorderRadius, @@ -5151,11 +5156,6 @@ const styles = (theme: ThemeColors) => justifyContent: 'flex-start', }, - emptyStateCompanyCardsIconSize: { - width: 164, - height: 190, - }, - workflowApprovalVerticalLine: { height: 16, width: 1, From 7b8998e86a0dc49250498902665c55eeb4b31d33 Mon Sep 17 00:00:00 2001 From: Wiktor Gut Date: Tue, 27 Aug 2024 09:27:32 +0200 Subject: [PATCH 303/565] working, ready for second look --- src/components/Search/SearchFiltersChatsSelector.tsx | 10 +++++----- src/libs/OptionsListUtils.ts | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/components/Search/SearchFiltersChatsSelector.tsx b/src/components/Search/SearchFiltersChatsSelector.tsx index 23849ddfd1b..f4b4403cf5f 100644 --- a/src/components/Search/SearchFiltersChatsSelector.tsx +++ b/src/components/Search/SearchFiltersChatsSelector.tsx @@ -11,7 +11,6 @@ import useScreenWrapperTranstionStatus from '@hooks/useScreenWrapperTransitionSt import * as DeviceCapabilities from '@libs/DeviceCapabilities'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import type {Option} from '@libs/OptionsListUtils'; -import * as ReportUtils from '@libs/ReportUtils'; import type {OptionData} from '@libs/ReportUtils'; import Navigation from '@navigation/Navigation'; import * as Report from '@userActions/Report'; @@ -54,10 +53,11 @@ function SearchFiltersChatsSelector({initialIDs, onFiltersUpdate, isScreenTransi const cleanSearchTerm = useMemo(() => searchTerm.trim().toLowerCase(), [searchTerm]); const selectedOptions = useMemo(() => { - const selectedReports = selectedReportIDs.map((id) => - getSelectedOptionData(OptionsListUtils.createOptionFromReport({...reports?.[`${ONYXKEYS.COLLECTION.REPORT}${id}`], reportID: id}, personalDetails)), - ); - return selectedReports.map((rep) => (!rep.alternateText ? {...rep, alternateText: ReportUtils.getPolicyName(rep)} : rep)); + return selectedReportIDs + .map((id) => getSelectedOptionData(OptionsListUtils.createOptionFromReport({...reports?.[`${ONYXKEYS.COLLECTION.REPORT}${id}`], reportID: id}, personalDetails))) + .map((rep) => { + return {...rep, alternateText: OptionsListUtils.getAlternateText(rep, {showChatPreviewLine: true})}; + }); }, [personalDetails, reports, selectedReportIDs]); const defaultOptions = useMemo(() => { diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index 3f519f4de7c..ba21cc43a1e 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -2544,6 +2544,7 @@ export { getCurrentUserSearchTerms, getEmptyOptions, shouldUseBoldText, + getAlternateText, }; export type {MemberForList, CategorySection, CategoryTreeSection, Options, OptionList, SearchOption, PayeePersonalDetails, Category, Tax, TaxRatesOption, Option, OptionTree}; From 1ec852c7de66797e7847a830fddf9d8054018ad2 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Tue, 27 Aug 2024 15:54:59 +0700 Subject: [PATCH 304/565] fix: logic show submit expense button --- src/libs/ReportUtils.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 574ee5bd184..9f7e84ea910 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -1654,10 +1654,6 @@ function canAddOrDeleteTransactions(moneyRequestReport: OnyxEntry): bool return false; } - if (currentUserAccountID !== moneyRequestReport?.managerID && currentUserAccountID !== moneyRequestReport?.ownerAccountID) { - return false; - } - const policy = getPolicy(moneyRequestReport?.policyID); if (PolicyUtils.isInstantSubmitEnabled(policy) && PolicyUtils.isSubmitAndClose(policy) && hasOnlyNonReimbursableTransactions(moneyRequestReport?.reportID)) { return false; @@ -6311,6 +6307,11 @@ function canRequestMoney(report: OnyxEntry, policy: OnyxEntry, o return false; } + // Current user must be a manager or owner of this expense + if (currentUserAccountID !== report?.managerID && currentUserAccountID !== report?.ownerAccountID) { + return false; + } + // User can submit expenses in any IOU report, unless paid, but the user can only submit expenses in an expense report // which is tied to their workspace chat. if (isMoneyRequestReport(report)) { From 3570e9e5fffe742f3fd664058a1b715a02ff952c Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Tue, 27 Aug 2024 16:57:38 +0800 Subject: [PATCH 305/565] set the instance ID when the modal is visible --- .../home/report/ContextMenu/PopoverReportActionContextMenu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.tsx b/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.tsx index 50b424fc736..48b1b669c7e 100644 --- a/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.tsx +++ b/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.tsx @@ -180,7 +180,6 @@ function PopoverReportActionContextMenu(_props: unknown, ref: ForwardedRef { + setInstanceID(Math.random().toString(36).substr(2, 5)); setDisabledActions(disabledOptions); typeRef.current = type; reportIDRef.current = reportID ?? '-1'; From 1734242a5a77a0406b522767731dd4476b45473f Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Tue, 27 Aug 2024 16:01:47 +0700 Subject: [PATCH 306/565] fix jest test --- tests/unit/ReportUtilsTest.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.ts index 741b550e093..6161fa57f75 100644 --- a/tests/unit/ReportUtilsTest.ts +++ b/tests/unit/ReportUtilsTest.ts @@ -713,6 +713,7 @@ describe('ReportUtils', () => { ...LHNTestUtils.getFakeReport(), chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, isOwnPolicyExpenseChat: true, + managerID: currentUserAccountID, }; const moneyRequestOptions = ReportUtils.temporary_getMoneyRequestOptions(report, undefined, [currentUserAccountID, ...participantsAccountIDs]); expect(moneyRequestOptions.length).toBe(3); From 45632a5c72ab7f5b68836f5670892443e5e3226b Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Tue, 27 Aug 2024 17:06:46 +0800 Subject: [PATCH 307/565] reverts --- src/libs/actions/Workflow.ts | 2 +- .../workspace/workflows/approvals/ApprovalWorkflowEditor.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/Workflow.ts b/src/libs/actions/Workflow.ts index a4086f9b6eb..946d7682675 100644 --- a/src/libs/actions/Workflow.ts +++ b/src/libs/actions/Workflow.ts @@ -352,7 +352,7 @@ function validateApprovalWorkflow(approvalWorkflow: ApprovalWorkflowOnyx): appro } if (!approvalWorkflow.approvers.length) { - errors['approver-0'] = 'common.error.fieldRequired'; + errors.additionalApprover = 'common.error.fieldRequired'; } Onyx.merge(ONYXKEYS.APPROVAL_WORKFLOW, {errors}); diff --git a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx index 7721e0d5854..a07aa150d0e 100644 --- a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx +++ b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx @@ -128,7 +128,7 @@ function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, polic interactive={!approvalWorkflow.isDefault} /> - {(approvalWorkflow.approvers.length > 0 ? approvalWorkflow.approvers : [undefined]).map((approver, approverIndex) => { + {approvalWorkflow.approvers.map((approver, approverIndex) => { const errorText = approverErrorMessage(approver, approverIndex); const hintText = !errorText && approvalWorkflow.usedApproverEmails.some((approverEmail) => approverEmail === approver?.email) From 4415d28eb7dda8e974ccac190ac99d7486396071 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Tue, 27 Aug 2024 17:12:19 +0800 Subject: [PATCH 308/565] show approver instead of additional approver if approver is empty --- .../workspace/workflows/approvals/ApprovalWorkflowEditor.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx index a07aa150d0e..30ab039d488 100644 --- a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx +++ b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx @@ -94,7 +94,7 @@ function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, polic // User should be allowed to add additional approver only if they upgraded to Control Plan, otherwise redirected to the Upgrade Page const addAdditionalApprover = useCallback(() => { - if (!PolicyUtils.isControlPolicy(policy)) { + if (!PolicyUtils.isControlPolicy(policy) && approvalWorkflow.approvers.length > 0) { Navigation.navigate(ROUTES.WORKSPACE_UPGRADE.getRoute(policyID, CONST.UPGRADE_FEATURE_INTRO_MAPPING.approvals.alias, Navigation.getActiveRoute())); return; } @@ -156,7 +156,7 @@ function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, polic })} 0 ? translate('workflowsCreateApprovalsPage.additionalApprover') : translate('workflowsPage.approver')} onPress={addAdditionalApprover} shouldShowRightIcon wrapperStyle={styles.sectionMenuItemTopDescription} From 9653b57d54c6762b8bcc61f99b51424c2406b6ab Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Tue, 27 Aug 2024 17:14:36 +0800 Subject: [PATCH 309/565] store the approver length to a var --- .../workflows/approvals/ApprovalWorkflowEditor.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx index 30ab039d488..6325ce1da21 100644 --- a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx +++ b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx @@ -38,11 +38,11 @@ function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, polic const styles = useThemeStyles(); const theme = useTheme(); const {translate, toLocaleOrdinal} = useLocalize(); + const approverCount = approvalWorkflow.approvers.length; const approverDescription = useCallback( - (index: number) => - approvalWorkflow.approvers.length > 1 ? `${toLocaleOrdinal(index + 1, true)} ${translate('workflowsPage.approver').toLowerCase()}` : `${translate('workflowsPage.approver')}`, - [approvalWorkflow.approvers.length, toLocaleOrdinal, translate], + (index: number) => (approverCount > 1 ? `${toLocaleOrdinal(index + 1, true)} ${translate('workflowsPage.approver').toLowerCase()}` : `${translate('workflowsPage.approver')}`), + [approverCount, toLocaleOrdinal, translate], ); const members = useMemo(() => { @@ -94,15 +94,15 @@ function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, polic // User should be allowed to add additional approver only if they upgraded to Control Plan, otherwise redirected to the Upgrade Page const addAdditionalApprover = useCallback(() => { - if (!PolicyUtils.isControlPolicy(policy) && approvalWorkflow.approvers.length > 0) { + if (!PolicyUtils.isControlPolicy(policy) && approverCount > 0) { Navigation.navigate(ROUTES.WORKSPACE_UPGRADE.getRoute(policyID, CONST.UPGRADE_FEATURE_INTRO_MAPPING.approvals.alias, Navigation.getActiveRoute())); return; } Navigation.navigate( - ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.getRoute(policyID, approvalWorkflow.approvers.length, ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID)), + ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.getRoute(policyID, approverCount, ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID)), CONST.NAVIGATION.ACTION_TYPE.PUSH, ); - }, [approvalWorkflow.approvers.length, policy, policyID]); + }, [approverCount, policy, policyID]); return ( 0 ? translate('workflowsCreateApprovalsPage.additionalApprover') : translate('workflowsPage.approver')} + description={approverCount > 0 ? translate('workflowsCreateApprovalsPage.additionalApprover') : translate('workflowsPage.approver')} onPress={addAdditionalApprover} shouldShowRightIcon wrapperStyle={styles.sectionMenuItemTopDescription} From 57920f50ce6ab5f2ccde0a8c2fe09758899487fe Mon Sep 17 00:00:00 2001 From: daledah Date: Tue, 27 Aug 2024 16:15:15 +0700 Subject: [PATCH 310/565] fix: admin has 2 payment options on indirect reimbursement --- src/components/SettlementButton.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index bd2d7ad76b6..18f8a707bf5 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -162,7 +162,9 @@ function SettlementButton({ const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${chatReportID || -1}`); const isInvoiceReport = (!isEmptyObject(iouReport) && ReportUtils.isInvoiceReport(iouReport)) || false; const isPaidGroupPolicy = ReportUtils.isPaidGroupPolicyExpenseChat(chatReport); - const shouldShowPaywithExpensifyOption = !isPaidGroupPolicy || (!shouldHidePaymentOptions && ReportUtils.isPayer(session, iouReport)); + const shouldShowPaywithExpensifyOption = + !isPaidGroupPolicy || + (!shouldHidePaymentOptions && ReportUtils.isPayer(session, iouReport) && policy?.reimbursementChoice !== CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL); const shouldShowPayElsewhereOption = (!isPaidGroupPolicy || policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL) && !isInvoiceReport; const paymentButtonOptions = useMemo(() => { const isExpenseReport = ReportUtils.isExpenseReport(iouReport); From e37ff531da98c359955679d50db76b3d2987a9f2 Mon Sep 17 00:00:00 2001 From: Mateusz Titz Date: Tue, 27 Aug 2024 11:25:07 +0200 Subject: [PATCH 311/565] fix BottomTabBar to handle policyID when navigating to search --- ios/tmp.xcconfig | 9 --------- output.txt | 5 ----- .../createCustomBottomTabNavigator/BottomTabBar.tsx | 8 ++++---- 3 files changed, 4 insertions(+), 18 deletions(-) delete mode 100644 ios/tmp.xcconfig delete mode 100644 output.txt diff --git a/ios/tmp.xcconfig b/ios/tmp.xcconfig deleted file mode 100644 index 2f250266945..00000000000 --- a/ios/tmp.xcconfig +++ /dev/null @@ -1,9 +0,0 @@ -NEW_EXPENSIFY_URL=https:/$()/new.expensify.com/ -SECURE_EXPENSIFY_URL=https:/$()/secure.expensify.com/ -EXPENSIFY_URL=https:/$()/www.expensify.com/ -EXPENSIFY_PARTNER_NAME=chat-expensify-com -EXPENSIFY_PARTNER_PASSWORD=e21965746fd75f82bb66 -PUSHER_APP_KEY=268df511a204fbb60884 -USE_WEB_PROXY=false -ENVIRONMENT=production -SEND_CRASH_REPORTS=true diff --git a/output.txt b/output.txt deleted file mode 100644 index 2e171753e0b..00000000000 --- a/output.txt +++ /dev/null @@ -1,5 +0,0 @@ - -> new.expensify@9.0.23-0 react-compiler-healthcheck -> react-compiler-healthcheck --verbose - -- Checking diff --git a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx index a419759ab45..394a617278d 100644 --- a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx +++ b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/BottomTabBar.tsx @@ -130,11 +130,11 @@ function BottomTabBar({selectedTab}: BottomTabBarProps) { ); return; } - Navigation.navigate(ROUTES.SEARCH_CENTRAL_PANE.getRoute({query: SearchUtils.buildCannedSearchQuery()})); - // Fixme add policyID - // const query = activeWorkspaceID ? `${CONST.SEARCH.TAB.EXPENSE.ALL} policyID:${activeWorkspaceID}` : CONST.SEARCH.TAB.EXPENSE.ALL; - // Navigation.navigate(ROUTES.SEARCH_CENTRAL_PANE.getRoute({query})); + const defaultCannedQuery = SearchUtils.buildCannedSearchQuery(); + // when navigating to search we might have an activePolicyID set from workspace switcher + const query = activeWorkspaceID ? `${defaultCannedQuery} ${CONST.SEARCH.SYNTAX_ROOT_KEYS.POLICY_ID}:${activeWorkspaceID}` : defaultCannedQuery; + Navigation.navigate(ROUTES.SEARCH_CENTRAL_PANE.getRoute({query})); }); }, [activeWorkspaceID, selectedTab]); From 1331d533844a226091045762129c16c3e3f7c402 Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Tue, 27 Aug 2024 11:34:22 +0200 Subject: [PATCH 312/565] add shouldShow to filters --- src/pages/Search/AdvancedSearchFilters.tsx | 25 ++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/pages/Search/AdvancedSearchFilters.tsx b/src/pages/Search/AdvancedSearchFilters.tsx index 83f3aaf8eef..4dc848f035b 100644 --- a/src/pages/Search/AdvancedSearchFilters.tsx +++ b/src/pages/Search/AdvancedSearchFilters.tsx @@ -136,87 +136,104 @@ function AdvancedSearchFilters() { const taxRates = getAllTaxRates(); const personalDetails = usePersonalDetails(); + const currentType = searchAdvancedFilters.type ?? CONST.SEARCH.DATA_TYPES.EXPENSE; + const shouldShowExpenseFilter = currentType === CONST.SEARCH.DATA_TYPES.EXPENSE; + const shouldShowChatFilter = currentType === CONST.SEARCH.DATA_TYPES.CHAT; + const advancedFilters = useMemo( () => [ { title: getFilterDisplayTitle(searchAdvancedFilters, CONST.SEARCH.SYNTAX_FILTER_KEYS.DATE, translate), description: 'common.date' as const, route: ROUTES.SEARCH_ADVANCED_FILTERS_DATE, + shouldShow: true, }, { title: getFilterDisplayTitle(searchAdvancedFilters, CONST.SEARCH.SYNTAX_FILTER_KEYS.CURRENCY, translate), description: 'common.currency' as const, route: ROUTES.SEARCH_ADVANCED_FILTERS_CURRENCY, + shouldShow: shouldShowExpenseFilter, }, { title: getFilterDisplayTitle(searchAdvancedFilters, CONST.SEARCH.SYNTAX_FILTER_KEYS.MERCHANT, translate), description: 'common.merchant' as const, route: ROUTES.SEARCH_ADVANCED_FILTERS_MERCHANT, + shouldShow: shouldShowExpenseFilter, }, { title: getFilterDisplayTitle(searchAdvancedFilters, CONST.SEARCH.SYNTAX_FILTER_KEYS.DESCRIPTION, translate), description: 'common.description' as const, route: ROUTES.SEARCH_ADVANCED_FILTERS_DESCRIPTION, + shouldShow: true, }, { title: getFilterDisplayTitle(searchAdvancedFilters, CONST.SEARCH.SYNTAX_FILTER_KEYS.REPORT_ID, translate), description: 'common.reportID' as const, route: ROUTES.SEARCH_ADVANCED_FILTERS_REPORT_ID, + shouldShow: true, }, { title: getFilterDisplayTitle(searchAdvancedFilters, CONST.SEARCH.SYNTAX_FILTER_KEYS.AMOUNT, translate), description: 'common.total' as const, route: ROUTES.SEARCH_ADVANCED_FILTERS_AMOUNT, + shouldShow: shouldShowExpenseFilter, }, { title: getFilterDisplayTitle(searchAdvancedFilters, CONST.SEARCH.SYNTAX_FILTER_KEYS.CATEGORY, translate), description: 'common.category' as const, route: ROUTES.SEARCH_ADVANCED_FILTERS_CATEGORY, + shouldShow: shouldShowExpenseFilter, }, { title: getFilterDisplayTitle(searchAdvancedFilters, CONST.SEARCH.SYNTAX_FILTER_KEYS.KEYWORD, translate), description: 'search.filters.hasKeywords' as const, route: ROUTES.SEARCH_ADVANCED_FILTERS_KEYWORD, + shouldShow: true, }, { title: getFilterCardDisplayTitle(searchAdvancedFilters, cardList), description: 'common.card' as const, route: ROUTES.SEARCH_ADVANCED_FILTERS_CARD, - shouldHide: Object.keys(cardList).length === 0, + shouldShow: shouldShowExpenseFilter && Object.keys(cardList).length !== 0, }, { title: getFilterTaxRateDisplayTitle(searchAdvancedFilters, taxRates), description: 'workspace.taxes.taxRate' as const, route: ROUTES.SEARCH_ADVANCED_FILTERS_TAX_RATE, + shouldShow: shouldShowExpenseFilter, }, { title: getExpenseTypeDisplayTitle(searchAdvancedFilters, translate), description: 'search.expenseType' as const, route: ROUTES.SEARCH_ADVANCED_FILTERS_EXPENSE_TYPE, + shouldShow: shouldShowExpenseFilter, }, { title: getFilterDisplayTitle(searchAdvancedFilters, CONST.SEARCH.SYNTAX_FILTER_KEYS.TAG, translate), description: 'common.tag' as const, route: ROUTES.SEARCH_ADVANCED_FILTERS_TAG, + shouldShow: shouldShowExpenseFilter, }, { title: getFilterParticipantDisplayTitle(searchAdvancedFilters.from ?? [], personalDetails), description: 'common.from' as const, route: ROUTES.SEARCH_ADVANCED_FILTERS_FROM, + shouldShow: true, }, { title: getFilterParticipantDisplayTitle(searchAdvancedFilters.to ?? [], personalDetails), description: 'common.to' as const, route: ROUTES.SEARCH_ADVANCED_FILTERS_TO, + shouldShow: true, }, { title: getFilterDisplayTitle(searchAdvancedFilters, CONST.SEARCH.SYNTAX_FILTER_KEYS.HAS, translate), description: 'search.filters.has' as const, route: ROUTES.SEARCH_ADVANCED_FILTERS_HAS, - shouldHide: searchAdvancedFilters?.type !== CONST.SEARCH.DATA_TYPES.CHAT, + shouldShow: shouldShowChatFilter, }, ], - [searchAdvancedFilters, translate, cardList, taxRates, personalDetails], + [searchAdvancedFilters, translate, shouldShowExpenseFilter, cardList, taxRates, personalDetails, shouldShowChatFilter], ); const onFormSubmit = () => { @@ -236,7 +253,7 @@ function AdvancedSearchFilters() { {advancedFilters.map((item) => { const onPress = singleExecution(waitForNavigate(() => Navigation.navigate(item.route))); - if (item.shouldHide) { + if (!item.shouldShow) { return undefined; } return ( From 4207b25b9c1dd583bb229d4410002dbcb7785240 Mon Sep 17 00:00:00 2001 From: Mateusz Titz Date: Tue, 27 Aug 2024 11:36:51 +0200 Subject: [PATCH 313/565] tweak code comment --- src/libs/Navigation/linkTo/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/Navigation/linkTo/index.ts b/src/libs/Navigation/linkTo/index.ts index 8cdeee0c80b..1fc99c771ca 100644 --- a/src/libs/Navigation/linkTo/index.ts +++ b/src/libs/Navigation/linkTo/index.ts @@ -59,7 +59,7 @@ export default function linkTo(navigation: NavigationContainerRef Date: Tue, 27 Aug 2024 11:46:07 +0200 Subject: [PATCH 314/565] stylistic touches --- src/components/Search/SearchFiltersChatsSelector.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/components/Search/SearchFiltersChatsSelector.tsx b/src/components/Search/SearchFiltersChatsSelector.tsx index f4b4403cf5f..a3d9b1e9b8c 100644 --- a/src/components/Search/SearchFiltersChatsSelector.tsx +++ b/src/components/Search/SearchFiltersChatsSelector.tsx @@ -91,12 +91,13 @@ function SearchFiltersChatsSelector({initialIDs, onFiltersUpdate, isScreenTransi ); newSections.push(formattedResults.section); - const reportsWithSearch = chatOptions.recentReports.map((report) => (selectedReportIDs.includes(report.reportID) ? getSelectedOptionData(report) : report)); - const reportsWithEmptySearch = chatOptions.recentReports.filter((report) => !selectedReportIDs.includes(report.reportID)); - const recentReportsFiltered = cleanSearchTerm === '' ? reportsWithEmptySearch : reportsWithSearch; + + const visibleReportWhenSearching = chatOptions.recentReports.map((report) => (selectedReportIDs.includes(report.reportID) ? getSelectedOptionData(report) : report)); + const visibleReportsWithEmptySearch = chatOptions.recentReports.filter((report) => !selectedReportIDs.includes(report.reportID)); + const recentReportsFiltered = cleanSearchTerm === '' ? visibleReportsWithEmptySearch : visibleReportWhenSearching; newSections.push({ - title: 'recent', + title: undefined, data: recentReportsFiltered, shouldShow: chatOptions.recentReports.length > 0, }); From fefe5b47644fa5c9ac52070520711c7dc84418e8 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Tue, 27 Aug 2024 11:49:31 +0200 Subject: [PATCH 315/565] Remove wrong merge conflict --- src/components/FeatureTrainingModal.tsx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/components/FeatureTrainingModal.tsx b/src/components/FeatureTrainingModal.tsx index 257627361a0..a2ff1c2824f 100644 --- a/src/components/FeatureTrainingModal.tsx +++ b/src/components/FeatureTrainingModal.tsx @@ -229,12 +229,6 @@ function FeatureTrainingModal({ text={helpText} /> )} -