diff --git a/src/components/MoneyRequestConfirmationList.js b/src/components/MoneyRequestConfirmationList.js index f203154ab3db..1b4967a9c54c 100755 --- a/src/components/MoneyRequestConfirmationList.js +++ b/src/components/MoneyRequestConfirmationList.js @@ -239,7 +239,7 @@ function MoneyRequestConfirmationList(props) { const policyTagList = lodashGet(policyTag, 'tags', {}); const policyTagListName = lodashGet(policyTag, 'name', translate('common.tag')); // A flag for showing the tags field - const shouldShowTags = props.isPolicyExpenseChat && OptionsListUtils.hasEnabledOptions(_.values(policyTagList)); + const shouldShowTags = props.isPolicyExpenseChat && (props.iouTag || OptionsListUtils.hasEnabledOptions(_.values(policyTagList))); // A flag for showing the billable field const shouldShowBillable = !lodashGet(props.policy, 'disabledFields.defaultBillable', true); diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index f6c3090143f4..8f2382111f34 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -646,7 +646,7 @@ function isUserCreatedPolicyRoom(report: OnyxEntry): boolean { * Whether the provided report is a Policy Expense chat. */ function isPolicyExpenseChat(report: OnyxEntry): boolean { - return getChatType(report) === CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT; + return getChatType(report) === CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT || (report?.isPolicyExpenseChat ?? false); } /** Wether the provided report belongs to a Control policy and is an epxense chat diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index 91ec0cd6471b..d9de984ad12c 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -63,34 +63,6 @@ Onyx.connect({ }, }); -let allRecentlyUsedTags = {}; -Onyx.connect({ - key: ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS, - waitForCollectionCallback: true, - callback: (value) => { - if (!value) { - allRecentlyUsedTags = {}; - return; - } - - allRecentlyUsedTags = value; - }, -}); - -let allPolicyTags = {}; -Onyx.connect({ - key: ONYXKEYS.COLLECTION.POLICY_TAGS, - waitForCollectionCallback: true, - callback: (value) => { - if (!value) { - allPolicyTags = {}; - return; - } - - allPolicyTags = value; - }, -}); - let userAccountID = ''; let currentUserEmail = ''; Onyx.connect({ @@ -508,21 +480,9 @@ function getMoneyRequestInformation( billable, ); - let optimisticPolicyRecentlyUsedCategories = []; - if (category) { - optimisticPolicyRecentlyUsedCategories = Policy.buildOptimisticPolicyRecentlyUsedCategories(iouReport.policyID, category); - } + const optimisticPolicyRecentlyUsedCategories = Policy.buildOptimisticPolicyRecentlyUsedCategories(iouReport.policyID, category); - const optimisticPolicyRecentlyUsedTags = {}; - const policyTags = allPolicyTags[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${iouReport.policyID}`]; - const recentlyUsedPolicyTags = allRecentlyUsedTags[`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${iouReport.policyID}`]; - - if (policyTags) { - // For now it only uses the first tag of the policy, since multi-tags are not yet supported - const tagListKey = _.first(_.keys(policyTags)); - const uniquePolicyRecentlyUsedTags = recentlyUsedPolicyTags ? _.filter(recentlyUsedPolicyTags[tagListKey], (recentlyUsedPolicyTag) => recentlyUsedPolicyTag !== tag) : []; - optimisticPolicyRecentlyUsedTags[tagListKey] = [tag, ...uniquePolicyRecentlyUsedTags]; - } + const optimisticPolicyRecentlyUsedTags = Policy.buildOptimisticPolicyRecentlyUsedTags(iouReport.policyID, tag); // If there is an existing transaction (which is the case for distance requests), then the data from the existing transaction // needs to be manually merged into the optimistic transaction. This is because buildOnyxDataForMoneyRequest() uses `Onyx.set()` for the transaction @@ -920,11 +880,12 @@ function requestMoney( * @param {String} comment * @param {String} currency * @param {String} category + * @param {String} tag * @param {String} existingSplitChatReportID - the report ID where the split bill happens, could be a group chat or a workspace chat * * @return {Object} */ -function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAccountID, amount, comment, currency, category, existingSplitChatReportID = '') { +function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAccountID, amount, comment, currency, category, tag, existingSplitChatReportID = '') { const currentUserEmailForIOUSplit = OptionsListUtils.addSMSDomainIfPhoneNumber(currentUserLogin); const participantAccountIDs = _.map(participants, (participant) => Number(participant.accountID)); const existingSplitChatReport = @@ -952,6 +913,7 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco undefined, undefined, category, + tag, ); // Note: The created action must be optimistically generated before the IOU action so there's no chance that the created action appears after the IOU action in the chat @@ -1142,6 +1104,7 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco undefined, undefined, category, + tag, ); // STEP 4: Build optimistic reportActions. We need: @@ -1190,10 +1153,10 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco } // Add category to optimistic policy recently used categories when a participant is a workspace - let optimisticPolicyRecentlyUsedCategories = []; - if (isPolicyExpenseChat) { - optimisticPolicyRecentlyUsedCategories = Policy.buildOptimisticPolicyRecentlyUsedCategories(participant.policyID, category); - } + const optimisticPolicyRecentlyUsedCategories = isPolicyExpenseChat ? Policy.buildOptimisticPolicyRecentlyUsedCategories(participant.policyID, category) : []; + + // Add tag to optimistic policy recently used tags when a participant is a workspace + const optimisticPolicyRecentlyUsedTags = isPolicyExpenseChat ? Policy.buildOptimisticPolicyRecentlyUsedTags(participant.policyID, tag) : {}; // STEP 5: Build Onyx Data const [oneOnOneOptimisticData, oneOnOneSuccessData, oneOnOneFailureData] = buildOnyxDataForMoneyRequest( @@ -1206,7 +1169,7 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco oneOnOnePersonalDetailListAction, oneOnOneReportPreviewAction, optimisticPolicyRecentlyUsedCategories, - {}, + optimisticPolicyRecentlyUsedTags, isNewOneOnOneChatReport, shouldCreateNewOneOnOneIOUReport, ); @@ -1256,10 +1219,11 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco * @param {String} comment * @param {String} currency * @param {String} category + * @param {String} tag * @param {String} existingSplitChatReportID - Either a group DM or a workspace chat */ -function splitBill(participants, currentUserLogin, currentUserAccountID, amount, comment, currency, category, existingSplitChatReportID = '') { - const {splitData, splits, onyxData} = createSplitsAndOnyxData(participants, currentUserLogin, currentUserAccountID, amount, comment, currency, category, existingSplitChatReportID); +function splitBill(participants, currentUserLogin, currentUserAccountID, amount, comment, currency, category, tag, existingSplitChatReportID = '') { + const {splitData, splits, onyxData} = createSplitsAndOnyxData(participants, currentUserLogin, currentUserAccountID, amount, comment, currency, category, tag, existingSplitChatReportID); API.write( 'SplitBill', { @@ -1269,6 +1233,7 @@ function splitBill(participants, currentUserLogin, currentUserAccountID, amount, currency, comment, category, + tag, transactionID: splitData.transactionID, reportActionID: splitData.reportActionID, createdReportActionID: splitData.createdReportActionID, @@ -1290,10 +1255,10 @@ function splitBill(participants, currentUserLogin, currentUserAccountID, amount, * @param {String} comment * @param {String} currency * @param {String} category + * @param {String} tag */ -function splitBillAndOpenReport(participants, currentUserLogin, currentUserAccountID, amount, comment, currency, category) { - const {splitData, splits, onyxData} = createSplitsAndOnyxData(participants, currentUserLogin, currentUserAccountID, amount, comment, currency, category); - +function splitBillAndOpenReport(participants, currentUserLogin, currentUserAccountID, amount, comment, currency, category, tag) { + const {splitData, splits, onyxData} = createSplitsAndOnyxData(participants, currentUserLogin, currentUserAccountID, amount, comment, currency, category, tag); API.write( 'SplitBillAndOpenReport', { @@ -1303,6 +1268,7 @@ function splitBillAndOpenReport(participants, currentUserLogin, currentUserAccou currency, comment, category, + tag, transactionID: splitData.transactionID, reportActionID: splitData.reportActionID, createdReportActionID: splitData.createdReportActionID, @@ -1832,16 +1798,7 @@ function editRegularMoneyRequest(transactionID, transactionThreadReportID, trans updatedChatReport.lastMessageHtml = messageText; } - const optimisticPolicyRecentlyUsedTags = {}; - if (_.has(transactionChanges, 'tag')) { - const tagListName = transactionChanges.tagListName; - const recentlyUsedPolicyTags = allRecentlyUsedTags[`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${iouReport.policyID}`]; - - const uniquePolicyRecentlyUsedTags = recentlyUsedPolicyTags - ? _.filter(recentlyUsedPolicyTags[tagListName], (recentlyUsedPolicyTag) => recentlyUsedPolicyTag !== transactionChanges.tag) - : []; - optimisticPolicyRecentlyUsedTags[tagListName] = [transactionChanges.tag, ...uniquePolicyRecentlyUsedTags]; - } + const optimisticPolicyRecentlyUsedTags = Policy.buildOptimisticPolicyRecentlyUsedTags(iouReport.policyID, transactionChanges.tag); const isScanning = TransactionUtils.hasReceipt(updatedTransaction) && TransactionUtils.isReceiptBeingScanned(updatedTransaction); diff --git a/src/libs/actions/Policy.js b/src/libs/actions/Policy.js index bcc371b3a609..659fc96db468 100644 --- a/src/libs/actions/Policy.js +++ b/src/libs/actions/Policy.js @@ -91,6 +91,27 @@ Onyx.connect({ callback: (val) => (allRecentlyUsedCategories = val), }); +let allPolicyTags = {}; +Onyx.connect({ + key: ONYXKEYS.COLLECTION.POLICY_TAGS, + waitForCollectionCallback: true, + callback: (value) => { + if (!value) { + allPolicyTags = {}; + return; + } + + allPolicyTags = value; + }, +}); + +let allRecentlyUsedTags = {}; +Onyx.connect({ + key: ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS, + waitForCollectionCallback: true, + callback: (val) => (allRecentlyUsedTags = val), +}); + let networkStatus = {}; Onyx.connect({ key: ONYXKEYS.NETWORK, @@ -1471,6 +1492,27 @@ function buildOptimisticPolicyRecentlyUsedCategories(policyID, category) { return lodashUnion([category], policyRecentlyUsedCategories); } +/** + * @param {String} policyID + * @param {String} tag + * @returns {Object} + */ +function buildOptimisticPolicyRecentlyUsedTags(policyID, tag) { + if (!policyID || !tag) { + return {}; + } + + const policyTags = lodashGet(allPolicyTags, `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, {}); + // For now it only uses the first tag of the policy, since multi-tags are not yet supported + const tagListKey = _.first(_.keys(policyTags)); + const policyRecentlyUsedTags = lodashGet(allRecentlyUsedTags, `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${policyID}`, {}); + + return { + ...policyRecentlyUsedTags, + [tagListKey]: lodashUnion([tag], lodashGet(policyRecentlyUsedTags, [tagListKey], [])), + }; +} + /** * This flow is used for bottom up flow converting IOU report to an expense report. When user takes this action, * we create a Collect type workspace when the person taking the action becomes an owner and an admin, while we @@ -1900,6 +1942,7 @@ export { dismissAddedWithPrimaryLoginMessages, openDraftWorkspaceRequest, buildOptimisticPolicyRecentlyUsedCategories, + buildOptimisticPolicyRecentlyUsedTags, createDraftInitialWorkspace, setWorkspaceInviteMessageDraft, }; diff --git a/src/pages/iou/SplitBillDetailsPage.js b/src/pages/iou/SplitBillDetailsPage.js index d1fe21d8cf4e..002dc3d48b55 100644 --- a/src/pages/iou/SplitBillDetailsPage.js +++ b/src/pages/iou/SplitBillDetailsPage.js @@ -101,6 +101,7 @@ function SplitBillDetailsPage(props) { merchant: splitMerchant, created: splitCreated, category: splitCategory, + tag: splitTag, } = isEditingSplitBill && props.draftTransaction ? ReportUtils.getTransactionDetails(props.draftTransaction) : ReportUtils.getTransactionDetails(props.transaction); const onConfirm = useCallback( @@ -131,6 +132,7 @@ function SplitBillDetailsPage(props) { iouCreated={splitCreated} iouMerchant={splitMerchant} iouCategory={splitCategory} + iouTag={splitTag} iouType={CONST.IOU.TYPE.SPLIT} isReadOnly={!isEditingSplitBill} shouldShowSmartScanFields diff --git a/src/pages/iou/steps/MoneyRequestConfirmPage.js b/src/pages/iou/steps/MoneyRequestConfirmPage.js index 29257d9201fa..44995e6ec3d8 100644 --- a/src/pages/iou/steps/MoneyRequestConfirmPage.js +++ b/src/pages/iou/steps/MoneyRequestConfirmPage.js @@ -234,6 +234,7 @@ function MoneyRequestConfirmPage(props) { trimmedComment, props.iou.currency, props.iou.category, + props.iou.tag, reportID, ); return; @@ -249,6 +250,7 @@ function MoneyRequestConfirmPage(props) { trimmedComment, props.iou.currency, props.iou.category, + props.iou.tag, ); return; } @@ -272,6 +274,7 @@ function MoneyRequestConfirmPage(props) { props.currentUserPersonalDetails.accountID, props.iou.currency, props.iou.category, + props.iou.tag, props.iou.receiptPath, props.iou.receiptFilename, isDistanceRequest, diff --git a/src/types/onyx/Report.ts b/src/types/onyx/Report.ts index 75c79358e510..b49599913543 100644 --- a/src/types/onyx/Report.ts +++ b/src/types/onyx/Report.ts @@ -19,6 +19,9 @@ type Report = { /** Whether the user is not an admin of policyExpenseChat chat */ isOwnPolicyExpenseChat?: boolean; + /** Whether the report is policyExpenseChat */ + isPolicyExpenseChat?: boolean; + /** Indicates if the report is pinned to the LHN or not */ isPinned?: boolean;