Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[HOLD for payment 2024-02-14] [$500] MEDIUM: Show full thread ancestry (front end, 1/2) #32618

Closed
quinthar opened this issue Dec 7, 2023 · 56 comments
Assignees
Labels
Awaiting Payment Auto-added when associated PR is deployed to production Daily KSv2 External Added to denote the issue can be worked on by a contributor NewFeature Something to build that is a new item.

Comments

@quinthar
Copy link
Contributor

quinthar commented Dec 7, 2023

Strategy:
To capture a billion users requires captures billions of conversations, and organizing them in an intuitive fashion. One method of allowing many users to talk at the same time is to use "threads", which capture a conversation's many branches and side-branches in an organized fashion. One major differentiation we have from Slack is our ability to "infinite thread": every conversation can branch and re-branch as many times as it needs to.

Problem:
Our testing with NewDot #social has already revealed that once you get a level or two away from the original conversation, it's easy to lose the context of the current thread. We do show the "parent comment", but if that parent is itself a thread a level or two under the "root", it's easy to get lost.

Solution:
At the top of the thread show not just the immediate parent, but its parent, and so on back to the "root" of the conversation. This provides a form of "breadcrumbs" such that if you ever get lost in the conversation, you can look at the top of the thread to remind yourself how you got to this particular conversational branch. This can be done with the following changes:

  • Back-end: (See MEDIUM: Show full thread ancestry (back end, 2/2) #34085) The back end will ensure that ancestor data is added when deep linking specifically to a thread. However, this feature can be implemented on the front end without this back-end feature, by just navigating naturally down a thread hierarchy, which will populate Onyx with the correct data organically.

  • Front-end: (To be done by a contributor.) Render the ancestor comments at the top of the chat as follows:

    • Each thread already renders its immediate parent comment at the start of the chat, followed by a simple line separator. This already figures out how to render that using the Onyx stored in a totally standard fashion, with no redundant storage, such that any changes to the parent comment are automatically reflected within the thread. So the bulk of the complexity is already worked out for a single level of ancestry.
    • Propose how to extend that existing code in the simplest and most obvious way to support multiple levels of ancestry that look and work exactly the same. Make sure the result looks like the mockup below.
    • And then add the ability to press (click or tap) on an ancestor chat in order to directly navigate to that specific chat on the parent report.
      • Note: We currently support the ability to get a direct link to a specific comment, and it will open the right report, but doesn't currently scroll to the right comment. Use that link, and don't worry about the fact that it doesn't scroll correctly.

image

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~0192639c03063bdc61
  • Upwork Job ID: 1744243475279429632
  • Last Price Increase: 2024-01-08
  • Automatic offers:
    • mollfpr | Reviewer | 28104781
    • dukenv0307 | Contributor | 28104782
@quinthar quinthar converted this from a draft issue Dec 7, 2023
@melvin-bot melvin-bot bot added the Monthly KSv2 label Dec 11, 2023
@quinthar quinthar moved this from MEDIUM to HIGH in [#whatsnext] #vip-vsb Dec 19, 2023
@quinthar quinthar moved this from HIGH to MEDIUM in [#whatsnext] #vip-vsb Dec 19, 2023
@quinthar quinthar added the Hot Pick Ready for an engineer to pick up and run with label Jan 2, 2024
@quinthar quinthar changed the title MEDIUM: Show thread ancestors MEDIUM: Show full thread ancestry, when available in Onyx Jan 8, 2024
@quinthar quinthar changed the title MEDIUM: Show full thread ancestry, when available in Onyx MEDIUM: Show full thread ancestry, when available in Onyx (front end, 1/2) Jan 8, 2024
@quinthar quinthar changed the title MEDIUM: Show full thread ancestry, when available in Onyx (front end, 1/2) MEDIUM: Show full thread ancestry (front end, 1/2) Jan 8, 2024
@quinthar quinthar added External Added to denote the issue can be worked on by a contributor Daily KSv2 NewFeature Something to build that is a new item. and removed Monthly KSv2 Hot Pick Ready for an engineer to pick up and run with labels Jan 8, 2024
@melvin-bot melvin-bot bot added the Overdue label Jan 8, 2024
Copy link

melvin-bot bot commented Jan 8, 2024

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

Copy link

melvin-bot bot commented Jan 8, 2024

@melvin-bot melvin-bot bot changed the title MEDIUM: Show full thread ancestry (front end, 1/2) [$500] MEDIUM: Show full thread ancestry (front end, 1/2) Jan 8, 2024
@melvin-bot melvin-bot bot added Weekly KSv2 Help Wanted Apply this label when an issue is open to proposals by contributors and removed Overdue Daily KSv2 labels Jan 8, 2024
Copy link

melvin-bot bot commented Jan 8, 2024

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

@melvin-bot melvin-bot bot added Daily KSv2 and removed Weekly KSv2 labels Jan 8, 2024
@dukenv0307
Copy link
Contributor

dukenv0307 commented Jan 8, 2024

Proposal

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

This is new feature

What is the root cause of that problem?

This is new feature

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

  1. In here. Recursively navigate the thread hierarchy from bottom up to find all pairs of report and parentReportAction of that report, and put in an array. This can be done in a while loop and can be extracted to an util for reuse.
function getAllParentReportActions(report: Report): Parent[] {
    let parentReportID = report.parentReportID;
    let parentReportActionID = report.parentReportActionID;
    let currentReport = report;
    let allParents: Parent[] = [];
    while (!!parentReportID) {
        const parentReport = getReport(parentReportID);
        const parentReportAction = ReportActionsUtils.getReportAction(parentReportID, parentReportActionID ?? '0');
        if (!parentReportAction || ReportActionsUtils.isTransactionThread(parentReportAction) || !parentReport) {
            break;
        }
        allParents.push({ report: currentReport, reportAction: parentReportAction});
        parentReportID = parentReport?.parentReportID;
        parentReportActionID = parentReport?.parentReportActionID;
        if (!isEmptyObject(parentReport)) {
            currentReport = parentReport;
        }
    } 

    return allParents;
}
  1. Then in here, map the above array to a list of components that contain the ReportActionItem and the divider line.
{allParents.reverse().map((parent, index) => {
      return (
          <OfflineWithFeedback
              shouldDisableOpacity={Boolean(lodashGet(parent.reportAction, 'pendingAction'))}
              pendingAction={lodashGet(parent.report, 'pendingFields.addWorkspaceRoom') || lodashGet(parent.report, 'pendingFields.createChat')}
              errors={lodashGet(parent.report, 'errorFields.addWorkspaceRoom') || lodashGet(parent.report, 'errorFields.createChat')}
              errorRowStyles={[styles.ml10, styles.mr2]}
              onClose={() => Report.navigateToConciergeChatAndDeleteReport(parent.report.reportID)}
          >
              <ReportActionItem
                  onPress={() => Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(parent.report.reportID))}
                  report={parent.report}
                  action={parent.reportAction}
                  displayAsGroup={false}
                  isMostRecentIOUReportAction={false}
                  shouldDisplayNewMarker={props.shouldDisplayNewMarker}
                  index={index}
              />
              <View style={[styles.threadDividerLine]} />
          </OfflineWithFeedback>
      )
  })}
  1. Handle action when pressing those ReportActionItem as well to navigate to the correct chat thread, with comment linking baked in.
<PressableWithSecondaryInteraction
            ref={popoverAnchorRef}
            onPress={props.onPress}
  1. [Optional] If we want to do this without the back-end feature, when recursively navigating the hierachy, we have to recursively call the openReport to fetch the data (if not existing in Onyx yet), but I think it's better to wait for the back-end on this

However, this feature can be implemented on the front end without this back-end feature, by just navigating naturally down a thread hierarchy, which will populate Onyx with the correct data organically.

You can test in this branch if need: https://github.com/dukenv0307/App/tree/fix/34085.

What alternative solutions did you explore? (Optional)

NA

@rojiphil
Copy link
Contributor

rojiphil commented Jan 8, 2024

Proposal

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

In a thread report, along with the immediate parent, we want to show its parent, and so on back to the "root" of the conversation

What is the root cause of that problem?

This is a new feature.

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

The following changes can be done:

  1. Here, we get the list of actions that should be shown for a report. In additional to these actions, we can iteratively fetch the parent Report Action if the Report itself has a parentReportID and parentReportActionID until its root. The ancestor Report Actions can be prepended to the existing Thread Report Actions which can be used for rendering.

To make the changes, if there are ancestors for this report, we can gather them in ReportScreen here for reportID like this:

    const reportActionsWithAncestors = useMemo(() => {
        const ancestorReportActions = [];
        ReportUtils.getAncestorReportActions(reportID,ancestorReportActions);    
        if(!ancestorReportActions.length) {
            return reportActions;
        }
        const createdReportAction = reportActions.pop();
        return [...reportActions, ...ancestorReportActions, createdReportAction];
    }, [reportActions]);

The utility function can be like this in ReportUtils

function getAncestorReportActions(reportID: string, reportActions: OnyxEntry<ReportAction>[] | null) {
    const report = getReport(reportID);
    if(isEmptyObject(report) || isMoneyRequestReport(report) || isTaskReport(report)) {
        return reportActions;
    }
    if(report?.parentReportID && report?.parentReportActionID) {
        const parentReportAction = ReportActionsUtils.getReportAction(report?.parentReportID ?? '', report?.parentReportActionID ?? '');       
        if (ReportActionsUtils.isTransactionThread(parentReportAction)) {        
            return reportActions;
        }     
        reportActions?.push(parentReportAction);
        getAncestorReportActions(report?.parentReportID, reportActions);
    }
    return reportActions;
}

We can, now, use the reportActionsWithAncestors here and here and here instead of reportActions.

  1. When displayed as an ancestor of a chat, we should disable display of thread replies here by checking if the parent action is displayed as an ancestor in thread report. Also, a divider line can be displayed in the similar manner.

To prevent display of thread replies and to display the divider line, we can leverage the existing ReportActionItemParentAction here.

Since we have also included the ancestor Report Actions for display, we can display them using ReportActionItemParentAction by including these actions in shouldDisplayParentAction here like this:

    const childReport = ReportUtils.getReport(reportAction.childReportID);    
    const isParentReportAction = !_.isEmpty(childReport) && childReport.parentReportID !== report.reportID;
    const shouldDisplayParentAction =
        (isParentReportAction || reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED) && 

Based on the context of the parent action, we can pass the reportID and parentReportID so that ReportActionItemParentAction can correctly display the parent action. We can pass like this here

    reportID={childReport.reportID}
    parentReportID={`${childReport.parentReportID}`}

Further, we can also use ReportActionItemParentAction to display the welcome style for the CREATED action of the thread report. For this, we can add a property reportAction to ReportActionItemParentAction and pass the current report action like this here.

    reportAction={reportAction}

Since we have all the required information in ReportActionItemParentAction , let us update the rendering code here so that parent actions are displayed as expected like this:

            {props.reportAction && props.reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED && (
                <View style={StyleUtils.getReportWelcomeContainerStyle(props.isSmallScreenWidth)}>
                    <AnimatedEmptyStateBackground />
                    <View style={[styles.p5, StyleUtils.getReportWelcomeTopMarginStyle(props.isSmallScreenWidth)]} />
                </View>
            )}
            {parentReportAction && (
                <ReportActionItem
                    report={props.report}
                    action={parentReportAction}
                    displayAsGroup={false}
                    isMostRecentIOUReportAction={false}
                    shouldDisplayNewMarker={props.shouldDisplayNewMarker}
                    index={0}
                />
            )}
  1. Since we can identify the Report ID to which an ancestor Report Action belongs to, we can easily navigate to the parent chat using this.

For this, we can add onPress handler for ReportActionItem here like this:

            onPress={() => Report.navigateToAndOpenChildReport(props.parentReportID)}

And, trigger the onPress by adding to PressableWithSecondaryInteraction here like this onPress={props.onPress}

Test branch is here

What alternative solutions did you explore? (Optional)

@dukenv0307
Copy link
Contributor

@mollfpr I responded in the PR.

@quinthar
Copy link
Contributor Author

quinthar commented Feb 1, 2024

Hey all, what's the latest here? This has sat for a week with no updates. We need to accelerate the turnaround here. What are the exact next steps, who is doing them, and when will they be done?

@dukenv0307
Copy link
Contributor

I'm working on the PR to resolve the suggestion from @marcaaron.

@marcaaron
Copy link
Contributor

This is now merged.

@abekkala
Copy link
Contributor

abekkala commented Feb 5, 2024

not yet deployed to staging: #34640 (comment)

@melvin-bot melvin-bot bot added Weekly KSv2 Awaiting Payment Auto-added when associated PR is deployed to production and removed Weekly KSv2 labels Feb 7, 2024
@melvin-bot melvin-bot bot changed the title [$500] MEDIUM: Show full thread ancestry (front end, 1/2) [HOLD for payment 2024-02-14] [$500] MEDIUM: Show full thread ancestry (front end, 1/2) Feb 7, 2024
@melvin-bot melvin-bot bot removed the Reviewing Has a PR in review label Feb 7, 2024
Copy link

melvin-bot bot commented Feb 7, 2024

Reviewing label has been removed, please complete the "BugZero Checklist".

Copy link

melvin-bot bot commented Feb 7, 2024

The solution for this issue has been 🚀 deployed to production 🚀 in version 1.4.37-7 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:

If no regressions arise, payment will be issued on 2024-02-14. 🎊

For reference, here are some details about the assignees on this issue:

Copy link

melvin-bot bot commented Feb 7, 2024

BugZero Checklist: The PR adding this new feature has been merged! The following checklist (instructions) will need to be completed before the issue can be closed:

  • [@mollfpr] Please propose regression test steps to ensure the new feature will work correctly on production in further releases.
  • [@abekkala] Link the GH issue for creating/updating the regression test once above steps have been agreed upon.

@abekkala
Copy link
Contributor

abekkala commented Feb 8, 2024

PAYMENTS FOR FEB 14

@melvin-bot melvin-bot bot added Daily KSv2 and removed Weekly KSv2 labels Feb 13, 2024
@mollfpr
Copy link
Contributor

mollfpr commented Feb 15, 2024

[@mollfpr] Please propose regression test steps to ensure the new feature will work correctly on production in further releases.

  1. Open any report
  2. Send a message
  3. Reply in the thread of this message
  4. Report steps 2-3 serval times
  5. Verify that in each thread, all ancestors of this thread are displayed
  6. Click on any ancestor action, and verify that we go to the current thread of this action
  7. 👍 or 👎

@abekkala
Copy link
Contributor

  1. Open any report
  2. Send a message
  3. Reply in the thread of this message
  4. Report steps 2-3 serval times
  5. Verify that in each thread, all ancestors of this thread are displayed
  6. Click on any ancestor action
  7. Verify that we go to the current thread of this action

@abekkala
Copy link
Contributor

@dukenv0307 payment sent and contract ended - thank you! 🎉

@abekkala
Copy link
Contributor

@mollfpr can you accept the offer in Upwork so I can send payment to you? It expires today

@mollfpr
Copy link
Contributor

mollfpr commented Feb 15, 2024

@abekkala I'll do a manual request in NewDot 🚀

@abekkala
Copy link
Contributor

I'll do a manual request in NewDot 🚀

oh that is correct - thanks for the reminder! I'll post a payment summary for the person who is paying you in NewDot!

@abekkala
Copy link
Contributor

NewDot Payment Summary: FEB 14

@melvin-bot melvin-bot bot added the Overdue label Feb 19, 2024
Copy link

melvin-bot bot commented Feb 19, 2024

@abekkala, @mollfpr, @marcaaron, @dukenv0307 Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!

@abekkala
Copy link
Contributor

closing - payment is in NewDot - payment summary above.

@melvin-bot melvin-bot bot removed the Overdue label Feb 19, 2024
@github-project-automation github-project-automation bot moved this from MEDIUM to CRITICAL in [#whatsnext] #vip-vsb Feb 19, 2024
@JmillsExpensify
Copy link

$500 approved for @mollfpr based on this comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting Payment Auto-added when associated PR is deployed to production Daily KSv2 External Added to denote the issue can be worked on by a contributor NewFeature Something to build that is a new item.
Projects
No open projects
Status: CRITICAL
Development

No branches or pull requests

8 participants