From 81f925b314388591384f4f470a25019a7f4243f9 Mon Sep 17 00:00:00 2001 From: Joe Gambino Date: Wed, 7 Jul 2021 20:56:55 -0700 Subject: [PATCH 1/5] Treat reports with user-owed balances as pinned chats --- src/libs/OptionsListUtils.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 8047bb3b7b47..7d547ef93a38 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -45,6 +45,16 @@ Onyx.connect({ }, }); +const iouReports = {}; +Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT_IOUS, + callback: (iouReport, key) => { + if (iouReport && key && iouReport.ownerEmail) { + iouReports[key] = iouReport; + } + }, +}); + /** * Helper method to return a default avatar * @@ -307,6 +317,8 @@ function getOptions(reports, personalDetails, draftComments, activeReportID, { const reportDraftComment = report && draftComments && lodashGet(draftComments, `${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${report.reportID}`, ''); + const reportContainsUserOwedIOU = lodashGet(report, 'hasOutstandingIOU', false) + && lodashGet(iouReports, [`${ONYXKEYS.COLLECTION.REPORT_IOUS}${report.iouReportID}`, 'ownerEmail'], '') !== currentUserLogin; const shouldFilterReportIfEmpty = !showReportsWithNoComments && report.lastMessageTimestamp === 0; const shouldFilterReportIfRead = hideReadReports && report.unreadActionCount === 0; @@ -315,7 +327,8 @@ function getOptions(reports, personalDetails, draftComments, activeReportID, { if (report.reportID !== activeReportID && !report.isPinned && !shouldShowReportIfHasDraft - && shouldFilterReport) { + && shouldFilterReport + && !reportContainsUserOwedIOU) { return; } From 8e6cbd6c449bea7f5f2ce97497a0707a5fcc65d1 Mon Sep 17 00:00:00 2001 From: Joe Gambino Date: Wed, 7 Jul 2021 21:07:54 -0700 Subject: [PATCH 2/5] style --- src/libs/OptionsListUtils.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 7d547ef93a38..e261a900a70c 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -317,9 +317,11 @@ function getOptions(reports, personalDetails, draftComments, activeReportID, { const reportDraftComment = report && draftComments && lodashGet(draftComments, `${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${report.reportID}`, ''); - const reportContainsUserOwedIOU = lodashGet(report, 'hasOutstandingIOU', false) - && lodashGet(iouReports, [`${ONYXKEYS.COLLECTION.REPORT_IOUS}${report.iouReportID}`, 'ownerEmail'], '') !== currentUserLogin; + const iouReportOwner = lodashGet(report, 'hasOutstandingIOU', false) + ? lodashGet(iouReports, [`${ONYXKEYS.COLLECTION.REPORT_IOUS}${report.iouReportID}`, 'ownerEmail'], '') + : ''; + const reportContainsUserOwedIOU = iouReportOwner && iouReportOwner !== currentUserLogin; const shouldFilterReportIfEmpty = !showReportsWithNoComments && report.lastMessageTimestamp === 0; const shouldFilterReportIfRead = hideReadReports && report.unreadActionCount === 0; const shouldShowReportIfHasDraft = showReportsWithDrafts && reportDraftComment && reportDraftComment.length > 0; From 195f64bbc839e971154a7e5ddc914496a7995eaf Mon Sep 17 00:00:00 2001 From: Joe Gambino Date: Wed, 7 Jul 2021 22:20:02 -0700 Subject: [PATCH 3/5] add iou debts to top of list in recent mode --- src/libs/OptionsListUtils.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index e261a900a70c..6497ac969938 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -190,6 +190,10 @@ function createOption(personalDetailList, report, draftComments, { && lodashGet(draftComments, `${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${report.reportID}`, ''); const hasOutstandingIOU = lodashGet(report, 'hasOutstandingIOU', false); + const iouReport = hasOutstandingIOU + ? lodashGet(iouReports, `${ONYXKEYS.COLLECTION.REPORT_IOUS}${report.iouReportID}`, {}) + : {}; + const lastActorDetails = report ? _.find(personalDetailList, {login: report.lastActorEmail}) : null; const lastMessageText = report ? (hasMultipleParticipants && lastActorDetails @@ -236,6 +240,8 @@ function createOption(personalDetailList, report, draftComments, { isPinned: lodashGet(report, 'isPinned', false), hasOutstandingIOU, iouReportID: lodashGet(report, 'iouReportID'), + isIOUReportOwner: lodashGet(iouReport, 'ownerEmail', false), + iouReportAmount: lodashGet(iouReport, 'amount', 0), isDefaultChatRoom, }; } @@ -290,10 +296,12 @@ function getOptions(reports, personalDetails, draftComments, activeReportID, { hideReadReports = false, sortByAlphaAsc = false, forcePolicyNamePreview = false, + prioritizeIOUDebts = false, }) { let recentReportOptions = []; const pinnedReportOptions = []; const personalDetailsOptions = []; + const iouDebtReportOptions = []; const reportMapForLogins = {}; let sortProperty = sortByLastMessageTimestamp @@ -395,6 +403,8 @@ function getOptions(reports, personalDetails, draftComments, activeReportID, { // collect the pinned reports so we can sort them alphabetically once they are collected if (prioritizePinnedReports && reportOption.isPinned) { pinnedReportOptions.push(reportOption); + } else if (prioritizeIOUDebts && reportOption.hasOutstandingIOU && reportOption.isIOUReportOwner) { + iouDebtReportOptions.push(reportOption); } else { recentReportOptions.push(reportOption); } @@ -406,6 +416,12 @@ function getOptions(reports, personalDetails, draftComments, activeReportID, { } } + // If we are prioritizing IOUs the user owes, add them before the normal recent report options + if (prioritizeIOUDebts) { + const sortedIOUReports = lodashOrderBy(iouDebtReportOptions, ['amount'], ['desc']); + recentReportOptions = sortedIOUReports.concat(recentReportOptions); + } + // If we are prioritizing our pinned reports then shift them to the front and sort them by report name if (prioritizePinnedReports) { const sortedPinnedReports = lodashOrderBy(pinnedReportOptions, ['text'], ['asc']); @@ -490,6 +506,7 @@ function getSearchOptions( includePersonalDetails: true, sortByLastMessageTimestamp: false, forcePolicyNamePreview: true, + prioritizeIOUDebts: false, }); } @@ -604,6 +621,7 @@ function getSidebarOptions( ) { let sideBarOptions = { prioritizePinnedReports: true, + prioritizeIOUDebts: true, }; if (priorityMode === CONST.PRIORITY_MODE.GSD) { sideBarOptions = { From 212ffdfdbb545d48e1264c27c82098ed7f09f977 Mon Sep 17 00:00:00 2001 From: Joe Gambino Date: Wed, 7 Jul 2021 22:49:43 -0700 Subject: [PATCH 4/5] fix sorting --- src/libs/OptionsListUtils.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 6497ac969938..c18dfcde7372 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -240,8 +240,8 @@ function createOption(personalDetailList, report, draftComments, { isPinned: lodashGet(report, 'isPinned', false), hasOutstandingIOU, iouReportID: lodashGet(report, 'iouReportID'), - isIOUReportOwner: lodashGet(iouReport, 'ownerEmail', false), - iouReportAmount: lodashGet(iouReport, 'amount', 0), + isIOUReportOwner: lodashGet(iouReport, 'ownerEmail', '') === currentUserLogin, + iouReportAmount: lodashGet(iouReport, 'total', 0), isDefaultChatRoom, }; } @@ -329,7 +329,7 @@ function getOptions(reports, personalDetails, draftComments, activeReportID, { ? lodashGet(iouReports, [`${ONYXKEYS.COLLECTION.REPORT_IOUS}${report.iouReportID}`, 'ownerEmail'], '') : ''; - const reportContainsUserOwedIOU = iouReportOwner && iouReportOwner !== currentUserLogin; + const reportContainsIOUDebt = iouReportOwner && iouReportOwner !== currentUserLogin; const shouldFilterReportIfEmpty = !showReportsWithNoComments && report.lastMessageTimestamp === 0; const shouldFilterReportIfRead = hideReadReports && report.unreadActionCount === 0; const shouldShowReportIfHasDraft = showReportsWithDrafts && reportDraftComment && reportDraftComment.length > 0; @@ -338,7 +338,7 @@ function getOptions(reports, personalDetails, draftComments, activeReportID, { && !report.isPinned && !shouldShowReportIfHasDraft && shouldFilterReport - && !reportContainsUserOwedIOU) { + && !reportContainsIOUDebt) { return; } @@ -403,7 +403,7 @@ function getOptions(reports, personalDetails, draftComments, activeReportID, { // collect the pinned reports so we can sort them alphabetically once they are collected if (prioritizePinnedReports && reportOption.isPinned) { pinnedReportOptions.push(reportOption); - } else if (prioritizeIOUDebts && reportOption.hasOutstandingIOU && reportOption.isIOUReportOwner) { + } else if (prioritizeIOUDebts && reportOption.hasOutstandingIOU && !reportOption.isIOUReportOwner) { iouDebtReportOptions.push(reportOption); } else { recentReportOptions.push(reportOption); @@ -418,7 +418,7 @@ function getOptions(reports, personalDetails, draftComments, activeReportID, { // If we are prioritizing IOUs the user owes, add them before the normal recent report options if (prioritizeIOUDebts) { - const sortedIOUReports = lodashOrderBy(iouDebtReportOptions, ['amount'], ['desc']); + const sortedIOUReports = lodashOrderBy(iouDebtReportOptions, ['iouReportAmount'], ['desc']); recentReportOptions = sortedIOUReports.concat(recentReportOptions); } @@ -628,6 +628,8 @@ function getSidebarOptions( hideReadReports: true, sortByAlphaAsc: true, showReportsWithDrafts: true, + prioritizePinnedReports: true, + prioritizeIOUDebts: true, }; } From c1469609a7ac180430963ef88b93ca48f347f348 Mon Sep 17 00:00:00 2001 From: Joe Gambino Date: Thu, 8 Jul 2021 18:59:50 -0700 Subject: [PATCH 5/5] sort alphabetically in focus mode, fix tests --- src/libs/OptionsListUtils.js | 2 -- tests/unit/OptionsListUtilsTest.js | 39 +++++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index c18dfcde7372..8b254de6f106 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -628,8 +628,6 @@ function getSidebarOptions( hideReadReports: true, sortByAlphaAsc: true, showReportsWithDrafts: true, - prioritizePinnedReports: true, - prioritizeIOUDebts: true, }; } diff --git a/tests/unit/OptionsListUtilsTest.js b/tests/unit/OptionsListUtilsTest.js index 2a54da5e2015..27ee71d6976a 100644 --- a/tests/unit/OptionsListUtilsTest.js +++ b/tests/unit/OptionsListUtilsTest.js @@ -86,6 +86,19 @@ describe('OptionsListUtils', () => { reportName: 'Silver Surfer', unreadActionCount: 0, }, + + // Note: This report has an IOU + 9: { + lastVisitedTimestamp: 1610666739302, + lastMessageTimestamp: 1611282168, + isPinned: false, + reportID: 9, + participants: ['mistersinister@marauders.com'], + reportName: 'Mister Sinister', + unreadActionCount: 0, + iouReportID: 100, + hasOutstandingIOU: true, + }, }; // And a set of personalDetails some with existing reports and some without @@ -119,6 +132,10 @@ describe('OptionsListUtils', () => { displayName: 'Captain America', login: 'steverogers@expensify.com', }, + 'mistersinister@marauders.com': { + displayName: 'Mr Sinister', + login: 'mistersinister@marauders.com', + }, // These do not exist in reports at all 'natasharomanoff@expensify.com': { @@ -134,11 +151,11 @@ describe('OptionsListUtils', () => { const REPORTS_WITH_CONCIERGE = { ...REPORTS, - 9: { + 10: { lastVisitedTimestamp: 1610666739302, lastMessageTimestamp: 1, isPinned: false, - reportID: 9, + reportID: 10, participants: ['concierge@expensify.com'], reportName: 'Concierge', unreadActionCount: 1, @@ -160,6 +177,10 @@ describe('OptionsListUtils', () => { keys: ONYXKEYS, initialKeyStates: { [ONYXKEYS.SESSION]: {email: 'tonystark@expensify.com'}, + [`${ONYXKEYS.COLLECTION.REPORT_IOUS}100`]: { + ownerEmail: 'mistersinister@marauders.com', + total: '1000', + }, }, registerStorageEventListener: () => {}, }); @@ -404,11 +425,11 @@ describe('OptionsListUtils', () => { ...REPORTS, // Note: This report has no lastMessageTimestamp but is also pinned - 9: { + 10: { lastVisitedTimestamp: 1610666739300, lastMessageTimestamp: 0, isPinned: true, - reportID: 9, + reportID: 10, participants: ['captain_britain@expensify.com'], reportName: 'Captain Britain', }, @@ -436,8 +457,11 @@ describe('OptionsListUtils', () => { // And the most recent pinned report is first in the list of reports expect(results.recentReports[0].login).toBe('captain_britain@expensify.com'); - // And the third report is the report with a lastMessageTimestamp - expect(results.recentReports[2].login).toBe('steverogers@expensify.com'); + // And the third report is the report with an IOU debt + expect(results.recentReports[2].login).toBe('mistersinister@marauders.com'); + + // And the fourth report is the report with the lastMessage timestamp + expect(results.recentReports[3].login).toBe('steverogers@expensify.com'); }); it('getSidebarOptions() with GSD priority mode', () => { @@ -457,5 +481,8 @@ describe('OptionsListUtils', () => { // And Black Panther is alphabetically the first report and has an unread message expect(results.recentReports[0].login).toBe('tchalla@expensify.com'); + + // And Mister Sinister is alphabetically the fifth report and has an IOU debt despite not being pinned + expect(results.recentReports[5].login).toBe('mistersinister@marauders.com'); }); });