Expensify / App

Welcome to New Expensify: a complete re-imagination of financial collaboration, centered around chat. Help us build the next generation of Expensify by sharing feedback and contributing to the code.
https://new.expensify.com
MIT License
3.57k stars 2.91k forks source link

[$250] Search - Empty row in "In" field when searching for messages in inaccessible group chat #52924

Open lanitochka17 opened 12 hours ago

lanitochka17 commented 12 hours ago

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!


Version Number: 9.0.65-3 Reproducible in staging?: Y Reproducible in production?: Y If this was caught on HybridApp, is this reproducible on New Expensify Standalone?: Y If this was caught during regression testing, add the test name, ID and link from TestRail: N/A Email or phone of affected tester (no customers): applausetester+kh0811007s2@applause.expensifail.com Issue reported by: Applause - Internal Team

Action Performed:

  1. Go to staging.new.expensify.com
  2. Go to group chat
  3. Click search router icon
  4. Click Search in
  5. Hit Enter to initiate the search (to keep search history for the next step)
  6. Go back to Inbox and leave the group
  7. Click search router icon
  8. Click on the search history created in Step 5
  9. Click Filters button
  10. Click "In" field

Expected Result:

There should be no empty row with a green checkmark

Actual Result:

There is an empty row with a green checkmark

Workaround:

Unknown

Platforms:

Which of our officially supported platforms is this issue occurring on?

Screenshots/Videos

Add any screenshot/video evidence

https://github.com/user-attachments/assets/db28f4b5-0b35-4dde-9a4b-ba6506021314

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~021859721962672586674
  • Upwork Job ID: 1859721962672586674
  • Last Price Increase: 2024-11-21
Issue OwnerCurrent Issue Owner: @ikevin127
melvin-bot[bot] commented 12 hours ago

Triggered auto assignment to @joekaufmanexpensify (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.

nyomanjyotisa commented 10 hours ago

Proposal

Please re-state the problem that we are trying to solve in this issue.

Search - Empty row in "In" field when searching for messages in inaccessible group chat

What is the root cause of that problem?

For deleted report, we still display it since we build the ReportUtils.OptionData with undefined/null/0 values first before assign the actual value. And there is not text and alternate text to display for deleted group chat so the option is empty

https://github.com/Expensify/App/blob/0e9f9346f46324e0b659f0cfcfbe476b85f9b8b0/src/libs/OptionsListUtils.ts#L637-L668

What changes do you think we should make in order to solve the problem?

Filter out selectedOptions if there is no text to display, so it won't display the empty option

    const selectedOptions = useMemo<OptionData[]>(() => {
        return selectedReportIDs
            .map((id) => {
                const report = getSelectedOptionData(OptionsListUtils.createOptionFromReport({...reports?.[`${ONYXKEYS.COLLECTION.REPORT}${id}`], reportID: id}, personalDetails));
                const alternateText = OptionsListUtils.getAlternateText(report, {});
                return {...report, alternateText};
            })
            .filter((option) => option.text)
    }, [personalDetails, reports, selectedReportIDs]);

What alternative solutions did you explore? (Optional)

joekaufmanexpensify commented 8 hours ago

Hmm, yeah we should probably just show no selection in the "in" filter in this case. I'm also curious if this only applies to group chats or other room types too?

Maybe it also applies to private rooms, and then also workspace rooms (if you're removed from the workspace)?

cc @luacmartins as I figure you'll have thoughts on this too.

melvin-bot[bot] commented 8 hours ago

Job added to Upwork: https://www.upwork.com/jobs/~021859721962672586674

melvin-bot[bot] commented 8 hours ago

Triggered auto assignment to Contributor-plus team member for initial proposal review - @ikevin127 (External)

bernhardoj commented 3 hours ago

Proposal

Please re-state the problem that we are trying to solve in this issue.

Empty selected row is shown in "In" filter page.

What is the root cause of that problem?

When we open the "In" filter page, it will show the initial selected report. https://github.com/Expensify/App/blob/686b8b45ca606453e4b8a5f11e2a16e75dd0b15d/src/components/Search/SearchFiltersChatsSelector.tsx#L50-L60 https://github.com/Expensify/App/blob/686b8b45ca606453e4b8a5f11e2a16e75dd0b15d/src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersInPage.tsx#L47

The initial selected report is assigned based on the query when we press the filter button. https://github.com/Expensify/App/blob/686b8b45ca606453e4b8a5f11e2a16e75dd0b15d/src/components/Search/SearchPageHeader.tsx#L330-L334

In buildFilterFormValuesFromQuery, we already filter out any report that doesn't exist. https://github.com/Expensify/App/blob/686b8b45ca606453e4b8a5f11e2a16e75dd0b15d/src/libs/SearchQueryUtils.ts#L435-L437

But the left group chat still exists on the onyx as an empty object.

image

It makes the filter fail to filter it out. The reason it becomes an empty object is because we set the successData to be an object that has all properties set to null. https://github.com/Expensify/App/blob/686b8b45ca606453e4b8a5f11e2a16e75dd0b15d/src/libs/actions/Report.ts#L2918-L2927

{
reportID: null,
reportName: null,
...
}

So, it becomes an empty object at the end.

What changes do you think we should make in order to solve the problem?

Change the successData to just null or don't set the successData at all because the BE already returns the onyx update to delete it.

const successData: OnyxUpdate[] = [
    {
        onyxMethod: Onyx.METHOD.MERGE,
        key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
        value: null,
    },
];

And, to be more precise, we need to filter out any report that doesn't have reportID https://github.com/Expensify/App/blob/686b8b45ca606453e4b8a5f11e2a16e75dd0b15d/src/libs/SearchQueryUtils.ts#L435-L437

filtersForm[filterKey] = filterValues.filter((id) => reports?.[`${ONYXKEYS.COLLECTION.REPORT}${id}`]?.reportID);

This is because, if we visit a report that doesn't exist, it will be added to the onyx with an error field and the filter will include it.

ikevin127 commented 2 hours ago

I second https://github.com/Expensify/App/issues/52924#issuecomment-2492454338, for reference this is the difference between the empty selected row and one that has data:

[!note]

  1. Empty row object lines are highlighted in 🔴 and non empty row in 🟢.
  2. Keys that don't show up with 🔴 is because they were undefined.
DIFF ```diff { - "text": "", + "text": "Kevin Bader (you)", - "alternateText": "", + "alternateText": "kevin.bader96+252@gmail.com", "allReportErrors": {}, "brickRoadIndicator": "", - "icons": [], + "icons": [ + { + "id": 17070261, + "source": "https://d2k5nsl2zxldvw.cloudfront.net/images/avatars/default-avatar_22.png", + "type": "avatar", + "name": "Kevin Bader", + "fallbackIcon": "" + } + ], "item": { - "reportID": "1719280750825503" + "chatType": "selfDM", + "currency": "USD", + "description": "", + "errorFields": {}, + "hasOutstandingChildRequest": false, + "hasOutstandingChildTask": false, + "isCancelledIOU": false, + "isOwnPolicyExpenseChat": false, + "isPinned": true, + "lastActionType": "CREATED", + "lastActorAccountID": "17070261", + "lastMessageHtml": "", + "lastMessageText": "", + "lastReadSequenceNumber": 0, + "lastReadTime": "2024-05-11 01:15:14.190", + "lastVisibleActionCreated": "2024-05-09 00:59:12.386", + "lastVisibleActionLastModified": "2024-05-09 00:59:12.386", + "managerID": 0, + "nonReimbursableTotal": 0, + "oldPolicyName": "", + "ownerAccountID": 17070261, + "participants": { + "17070261": { + "notificationPreference": "mute" + } + }, + "permissions": [], + "policyID": "_FAKE_", + "private_isArchived": "", + "reportID": "4530749671729272", + "reportName": "", + "stateNum": 0, + "statusNum": 0, + "total": 0, + "type": "chat", + "unheldNonReimbursableTotal": 0, + "unheldTotal": 0, + "welcomeMessage": "", + "writeCapability": "all" }, "tooltipText": "", + "tooltipText": "17070261", - "subtitle": "", + "subtitle": "Your space", - "participantsList": [], + "participantsList": [ + { + "accountID": 17070261, + "avatar": "https://d2k5nsl2zxldvw.cloudfront.net/images/avatars/default-avatar_22.png", + "firstName": "Kevin", + "lastName": "Bader", + "displayName": "Kevin Bader", + "login": "kevin.bader96+252@gmail.com", + "pronouns": "", + "timezone": { + "automatic": true, + "selected": "America/Los_Angeles" + }, + "phoneNumber": "", + "validated": true, + "localCurrencyCode": "USD" + } + ], - "accountID": NaN, + "accountID": 17070261, "reportID": "1719280750825503", + "reportID": "4530749671729272", "hasDraftComment": false, "keyForList": "1719280750825503", "isDefaultRoom": false, - "isPinned": undefined, + "isPinned": true, "iouReportAmount": 0, "iouReportID": undefined, - "isIOUReportOwner": false, + "isIOUReportOwner": true, "isChatRoom": false, "shouldShowSubscript": false, "isPolicyExpenseChat": false, "isOwnPolicyExpenseChat": false, "isExpenseReport": false, "lastMessageText": "", "isInvoiceRoom": false, "isMoneyRequestReport": false, "isThread": false, "isTaskReport": false, "isUnread": false, "isSelfDM": false, - "notificationPreference": "hidden", + "notificationPreference": "mute", "isSelected": true, + "login": "kevin.bader96+252@gmail.com", + "phoneNumber": "", + "hasDraftComment": false, + "keyForList": "4530749671729272", + "isWaitingOnBankAccount": false, + "policyID": "_FAKE_", + "lastMessageText": "", + "private_isArchived": "", + "isInvoiceRoom": false, + "isMoneyRequestReport": false, + "isThread": false, + "isTaskReport": false, + "isUnread": false, + "isSelfDM": true } ```

@luacmartins Could definitely use your take on whether we should simply filter out the empty row based on the text variable as suggested by the first proposal or go with a more in-depth approach like the second one which besides filtering out the empty row based on reportID, it also suggests either setting successData value to null or don't send it at all.

I tend to go with the second proposal as the RCA is more detailed and the solution seems more based. Wdyt ?