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 2023-11-02] [$500] Workspace - Archived Chat shows the edit composer for the message #26887

Closed
1 of 6 tasks
izarutskaya opened this issue Sep 6, 2023 · 58 comments
Assignees
Labels
Awaiting Payment Auto-added when associated PR is deployed to production Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 Engineering External Added to denote the issue can be worked on by a contributor Internal Requires API changes or must be handled by Expensify staff

Comments

@izarutskaya
Copy link

izarutskaya commented Sep 6, 2023

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


Action Performed:

  1. Open App > Go to Settings > Workspaces > Press New Workspace
  2. Send a message to the newly created admin workspace channel
  3. Press Edit Comment. It will open the edit composer for the message
  4. Now, Go to Settings > Workspace > Newly created workspace > Press 3 dot from the top menu > Press Delete Workspace
  5. Navigate back to the admin channel

Expected Result:

If Chat is archived, the edit composer should be hidden because the Edit message for archived Chat is prevented from BE

Actual Result:

Chat is archived, but the edit composer shows the message.

Workaround:

Unknown

Platforms:

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

  • Android / native
  • Android / Chrome
  • iOS / native
  • iOS / Safari
  • MacOS / Chrome / Safari
  • MacOS / Desktop

Version Number: v1.3.64-2

Reproducible in staging?: Y

Reproducible in production?: Y

If this was caught during regression testing, add the test name, ID and link from TestRail:

Email or phone of affected tester (no customers):

Logs: https://stackoverflow.com/c/expensify/questions/4856

Notes/Photos/Videos: Any additional supporting documentation

Archived-Workspace-Edit-Composer.mp4
Recording.1466.mp4

Expensify/Expensify Issue URL:

Issue reported by: @jayeshmangwani

Slack conversation: https://expensify.slack.com/archives/C049HHMV9SM/p1693300421650139

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~0144ce6446180ed0fc
  • Upwork Job ID: 1701302019279601664
  • Last Price Increase: 2023-10-02
  • Automatic offers:
    • aimane-chnaif | Reviewer | 27282551
    • bernhardoj | Contributor | 27282553
    • jayeshmangwani | Reporter | 27282554
@izarutskaya izarutskaya added the Daily KSv2 label Sep 6, 2023
@namhihi237
Copy link
Contributor

namhihi237 commented Sep 6, 2023

Proposal

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

If the room is archived, the edit composer should be hidden

What is the root cause of that problem?

We are displaying the ReportActionItemMessageEdit component to edit the message when props.draftMessage is not empty in here:

That's why when the workspace is deleted, the room is also archived. But because there is still draftMessage not empty, the composer edit message is still displayed.

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

We should delete draft Message when room is archived.

    useEffect(() => {
        if (!props.draftMessage || !ReportUtils.isArchivedRoom(props.report)) {
            return;
        }
        const originalReportID = ReportUtils.getOriginalReportID(props.report.reportID, props.action)

        Report.saveReportActionDraft(originalReportID, props.action.reportActionID, '');
    }, [props.report])

What alternative solutions did you explore? (Optional)

N/A

@izarutskaya izarutskaya added the Bug Something is broken. Auto assigns a BugZero manager. label Sep 6, 2023
@melvin-bot
Copy link

melvin-bot bot commented Sep 6, 2023

Triggered auto assignment to @sakluger (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details.

@melvin-bot
Copy link

melvin-bot bot commented Sep 6, 2023

Bug0 Triage Checklist (Main S/O)

  • This "bug" occurs on a supported platform (ensure Platforms in OP are ✅)
  • This bug is not a duplicate report (check E/App issues and #expensify-bugs)
    • If it is, comment with a link to the original report, close the issue and add any novel details to the original issue instead
  • This bug is reproducible using the reproduction steps in the OP. S/O
    • If the reproduction steps are clear and you're unable to reproduce the bug, check with the reporter and QA first, then close the issue.
    • If the reproduction steps aren't clear and you determine the correct steps, please update the OP.
  • This issue is filled out as thoroughly and clearly as possible
    • Pay special attention to the title, results, platforms where the bug occurs, and if the bug happens on staging/production.
  • I have reviewed and subscribed to the linked Slack conversation to ensure Slack/Github stay in sync

@dukenv0307
Copy link
Contributor

Proposal

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

Workspace - Archived Chat shows the edit composer for the message

What is the root cause of that problem?

We don't delete the draft message when the workspace is deleted, so it still displays with the condition here

{!props.draftMessage ? (

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

In ReportActionItemMessageEdit, we should add a useEffect to delete the draft message when the report cannot add comments

const hideComposer = ReportUtils.shouldDisableWriteActions(props.report);
useEffect(() => {
    if (!hideComposer) {
        return;
    }
    deleteDraft();
}, [hideComposer])

What alternative solutions did you explore? (Optional)

NA

Result

Screencast.from.07-09-2023.11.12.08.webm

@bernhardoj
Copy link
Contributor

Proposal

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

Message stays in edit mode even after the policy/workspace chat is deleted.

What is the root cause of that problem?

The message enters the edit mode if it has a draft message.

{!props.draftMessage ? (
<View style={props.displayAsGroup && hasBeenFlagged ? styles.blockquote : {}}>
<ReportActionItemMessage
action={props.action}
displayAsGroup={props.displayAsGroup}
isHidden={isHidden}
style={[
_.contains(
[..._.values(CONST.REPORT.ACTIONS.TYPE.POLICYCHANGELOG), CONST.REPORT.ACTIONS.TYPE.IOU, CONST.REPORT.ACTIONS.TYPE.APPROVED],
props.action.actionName,
)
? styles.colorMuted
: undefined,
]}
/>
{hasBeenFlagged && (
<Button
small
style={[styles.mt2, styles.alignSelfStart]}
onPress={() => setIsHidden(!isHidden)}
>
<Text
style={styles.buttonSmallText}
selectable={false}
dataSet={{[CONST.SELECTION_SCRAPER_HIDDEN_ELEMENT]: true}}
>
{isHidden ? props.translate('moderation.revealMessage') : props.translate('moderation.hideMessage')}
</Text>
</Button>
)}
</View>
) : (
<ReportActionItemMessageEdit
action={props.action}
draftMessage={props.draftMessage}
reportID={props.report.reportID}
index={props.index}
ref={textInputRef}
report={props.report}
// Avoid defining within component due to an existing Onyx bug
preferredSkinTone={props.preferredSkinTone}
shouldDisableEmojiPicker={
(ReportUtils.chatIncludesConcierge(props.report) && User.isBlockedFromConcierge(props.blockedFromConcierge)) || ReportUtils.isArchivedRoom(props.report)
}
/>

When we delete a workspace/policy, we never delete their draft message which is why it stays in the edit mode.

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

Currently, there is no easy way to delete draft message from a report because the onyx key of report action draft is designed like this:
reportActionsDrafts_{reportID}_{reportActionID}: value

If we want to clear all draft from a report, we would need to iterate over all existing report action draft and set the value to null one by one. To make everything easier, I would like to propose to change the onyx key of report actions drafts to be:

reportActionsDrafts_{reportID}: {
    [reportActionID]: value,
}

This has the same structure as report actions onyx which will allow us to clear all the draft easily as below:

(add below code to Policy.deleteWorkspace optimisticData)

..._.map(reports, ({reportID}) => ({
    onyxMethod: Onyx.METHOD.SET,
    key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}${reportID}`,
    value: null,
})),

As we change the onyx structure, we need to adjust some code access the new key correctly:

view

App/src/libs/actions/Report.js

Lines 1194 to 1196 in 46e6e20

function saveReportActionDraft(reportID, reportActionID, draftMessage) {
Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}${reportID}_${reportActionID}`, draftMessage);
}

to:

Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}${reportID}`, {[reportActionID]: draftMessage});

withReportActionsDrafts({
propName: 'draftMessage',
transformValue: (drafts, props) => {
const draftKey = `${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}${props.report.reportID}_${props.action.reportActionID}`;
return lodashGet(drafts, draftKey, '');
},
}),

to:

const draftKey = `${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}${props.report.reportID}`;
return lodashGet(drafts, [draftKey, props.action.reportActionID], '');

if (report.parentReportActionID && lodashGet(props.action, 'childType', '') === CONST.REPORT.TYPE.CHAT) {
if (lodashGet(props.drafts, [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}${report.parentReportID}_${props.action.reportActionID}`], undefined)) {
Report.saveReportActionDraft(report.parentReportID, props.action.reportActionID, trimmedNewDraft);
}
}
// Updates in the parent message should cause the child draft message to change
if (props.action.childReportID) {
if (lodashGet(props.drafts, [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}${props.action.childReportID}_${props.action.reportActionID}`], undefined)) {
Report.saveReportActionDraft(props.action.childReportID, props.action.reportActionID, trimmedNewDraft);
}
}

to:

if (lodashGet(props.drafts, [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}${report.parentReportID}`, props.action.reportActionID], undefined)) {

Last, there are 2 things to do:

  1. Create an onyx migration file to migrate the old to new onyx key (see below)
  2. Check on the BE whether we use the old onyx key and if yes, we should update it (I doubt BE use it because draft is only saved locally for now)
migration code
import _ from 'underscore';
import Onyx from 'react-native-onyx';
import Log from '../Log';
import ONYXKEYS from '../../ONYXKEYS';

/**
 * This migration updates reportActionsDrafts data to be keyed by reportActionID.
 *
 * Before: reportActionsDrafts_reportID_reportActionID: value
 * After: reportActionsDrafts_reportID: {[reportActionID]: value}
 *
 * @returns {Promise}
 */
export default function () {
    return new Promise((resolve) => {
        const connectionID = Onyx.connect({
            key: ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS,
            waitForCollectionCallback: true,
            callback: (allReportActionsDrafts) => {
                Onyx.disconnect(connectionID);

                if (!allReportActionsDrafts) {
                    Log.info('[Migrate Onyx] Skipped migration KeyReportActionsDraftByReportActionID because there were no reportActionsDrafts');
                    return resolve();
                }

                const newReportActionsDrafts = {};
                _.each(allReportActionsDrafts, (reportActionDraft, onyxKey) => {
                    if (_.isString(reportActionDraft)) {
                        newReportActionsDrafts[onyxKey] = null;

                        const reportActionID = onyxKey.split('_').pop();
                        const newOnyxKey = onyxKey.replace(`_${reportActionID}`, '');
                        newReportActionsDrafts[newOnyxKey] = {
                            ...(newReportActionsDrafts[newOnyxKey] || allReportActionsDrafts[newOnyxKey]),
                            [reportActionID]: reportActionDraft,
                        };
                    }
                });

                if (_.isEmpty(newReportActionsDrafts)) {
                    Log.info('[Migrate Onyx] Skipped migration KeyReportActionsDraftByReportActionID because there are no actions drafts to migrate');
                    return resolve();
                }

                Log.info(`[Migrate Onyx] Re-keying reportActionsDrafts by reportActionID for ${_.keys(newReportActionsDrafts).length} actions drafts`);
                // eslint-disable-next-line rulesdir/prefer-actions-set-data
                return Onyx.multiSet(newReportActionsDrafts).then(resolve);
            },
        });
    });
}

@melvin-bot melvin-bot bot added the Overdue label Sep 11, 2023
@sakluger
Copy link
Contributor

Good find!

@melvin-bot melvin-bot bot removed the Overdue label Sep 11, 2023
@sakluger sakluger added the External Added to denote the issue can be worked on by a contributor label Sep 11, 2023
@melvin-bot melvin-bot bot changed the title Workspace - Archived Chat shows the edit composer for the message [$500] Workspace - Archived Chat shows the edit composer for the message Sep 11, 2023
@melvin-bot
Copy link

melvin-bot bot commented Sep 11, 2023

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

@melvin-bot melvin-bot bot added the Help Wanted Apply this label when an issue is open to proposals by contributors label Sep 11, 2023
@melvin-bot
Copy link

melvin-bot bot commented Sep 11, 2023

Current assignee @sakluger is eligible for the External assigner, not assigning anyone new.

@melvin-bot
Copy link

melvin-bot bot commented Sep 11, 2023

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

@melvin-bot melvin-bot bot added the Overdue label Sep 14, 2023
@sakluger
Copy link
Contributor

@aimane-chnaif could you please review the proposals we've received so far?

@melvin-bot melvin-bot bot removed the Overdue label Sep 14, 2023
@aimane-chnaif
Copy link
Contributor

@bernhardoj thanks for the research. Draft is local Onyx data. How will you clear draft message when delete workspace from another device? Especially if user closed app at the moment when delete workspace so user won't receive pusher event.

@bernhardoj
Copy link
Contributor

@aimane-chnaif oh, I didn't think of that case, but I found in Policy.js that we actually tried to delete the draft when deleting the workspace from another device, but it doesn't work because of how the draft onyx is structured. If we do the draft onyx migration, it should work without any further changes needed. The changes come from this PR. It successfully set the hasDraft to false, but not the draft report actions.

Onyx.connect({
key: ONYXKEYS.COLLECTION.POLICY,
callback: (val, key) => {
if (!key) {
return;
}
if (val === null || val === undefined) {
// If we are deleting a policy, we have to check every report linked to that policy
// and unset the draft indicator (pencil icon) alongside removing any draft comments. Clearing these values will keep the newly archived chats from being displayed in the LHN.
// More info: https://github.com/Expensify/App/issues/14260
const policyID = key.replace(ONYXKEYS.COLLECTION.POLICY, '');
const policyReports = ReportUtils.getAllPolicyReports(policyID);
const cleanUpMergeQueries = {};
const cleanUpSetQueries = {};
_.each(policyReports, ({reportID}) => {
cleanUpMergeQueries[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`] = {hasDraft: false};
cleanUpSetQueries[`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${reportID}`] = null;
});
Onyx.mergeCollection(ONYXKEYS.COLLECTION.REPORT, cleanUpMergeQueries);
Onyx.multiSet(cleanUpSetQueries);
delete allPolicies[key];
return;
}

note: we have an onyx issue where setting null doesn't really clear the data, refreshing the app will show the data again, so I think we should wait for it to be resolved.

@melvin-bot melvin-bot bot added the Overdue label Sep 18, 2023
@melvin-bot
Copy link

melvin-bot bot commented Sep 18, 2023

@sakluger, @aimane-chnaif Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!

@aimane-chnaif
Copy link
Contributor

note: we have an onyx issue where setting null doesn't really clear the data, refreshing the app will show the data again, so I think we should wait for it to be resolved

Onyx PR was merged. I think we can wait a bit more until package version is bumped in app which will likely happen soon.

@melvin-bot melvin-bot bot removed the Overdue label Sep 18, 2023
@melvin-bot
Copy link

melvin-bot bot commented Sep 18, 2023

📣 It's been a week! Do we have any satisfactory proposals yet? Do we need to adjust the bounty for this issue? 💸

@melvin-bot
Copy link

melvin-bot bot commented Sep 20, 2023

@sakluger @aimane-chnaif this issue was created 2 weeks ago. Are we close to approving a proposal? If not, what's blocking us from getting this issue assigned? Don't hesitate to create a thread in #expensify-open-source to align faster in real time. Thanks!

@melvin-bot melvin-bot bot added the Overdue label Sep 20, 2023
@cead22 cead22 added External Added to denote the issue can be worked on by a contributor Internal Requires API changes or must be handled by Expensify staff labels Oct 19, 2023
@melvin-bot melvin-bot bot added the Help Wanted Apply this label when an issue is open to proposals by contributors label Oct 19, 2023
@melvin-bot
Copy link

melvin-bot bot commented Oct 19, 2023

Current assignee @aimane-chnaif is eligible for the Internal assigner, not assigning anyone new.

@melvin-bot
Copy link

melvin-bot bot commented Oct 19, 2023

Current assignee @aimane-chnaif is eligible for the External assigner, not assigning anyone new.

@melvin-bot melvin-bot bot removed the Help Wanted Apply this label when an issue is open to proposals by contributors label Oct 19, 2023
@melvin-bot
Copy link

melvin-bot bot commented Oct 19, 2023

📣 @aimane-chnaif 🎉 An offer has been automatically sent to your Upwork account for the Reviewer role 🎉 Thanks for contributing to the Expensify app!

Offer link
Upwork job

@melvin-bot
Copy link

melvin-bot bot commented Oct 19, 2023

📣 @bernhardoj 🎉 An offer has been automatically sent to your Upwork account for the Contributor role 🎉 Thanks for contributing to the Expensify app!

Offer link
Upwork job
Please accept the offer and leave a comment on the Github issue letting us know when we can expect a PR to be ready for review 🧑‍💻
Keep in mind: Code of Conduct | Contributing 📖

@melvin-bot
Copy link

melvin-bot bot commented Oct 19, 2023

📣 @jayeshmangwani 🎉 An offer has been automatically sent to your Upwork account for the Reporter role 🎉 Thanks for contributing to the Expensify app!

Offer link
Upwork job

@bernhardoj
Copy link
Contributor

It looks like the backend doesn't use the drafts key

Thanks for the confirmation.

Let's fallback on '' instead of undefined in the proposed code copied below

I just checked the latest code and that code is not present anymore, so nothing to change here.

PR is ready

cc: @aimane-chnaif

@melvin-bot
Copy link

melvin-bot bot commented Oct 25, 2023

Based on my calculations, the pull request did not get merged within 3 working days of assignment. Please, check out my computations here:

  • when @bernhardoj got assigned: 2023-10-19 18:19:12 Z
  • when the PR got merged: 2023-10-25 16:55:52 UTC
  • days elapsed: 3

On to the next one 🚀

@melvin-bot melvin-bot bot added Weekly KSv2 Awaiting Payment Auto-added when associated PR is deployed to production and removed Weekly KSv2 labels Oct 26, 2023
@melvin-bot melvin-bot bot changed the title [$500] Workspace - Archived Chat shows the edit composer for the message [HOLD for payment 2023-11-02] [$500] Workspace - Archived Chat shows the edit composer for the message Oct 26, 2023
@melvin-bot melvin-bot bot removed the Reviewing Has a PR in review label Oct 26, 2023
@melvin-bot
Copy link

melvin-bot bot commented Oct 26, 2023

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

@melvin-bot
Copy link

melvin-bot bot commented Oct 26, 2023

The solution for this issue has been 🚀 deployed to production 🚀 in version 1.3.91-8 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 2023-11-02. 🎊

After the hold period is over and BZ checklist items are completed, please complete any of the applicable payments for this issue, and check them off once done.

  • External issue reporter
  • Contributor that fixed the issue
  • Contributor+ that helped on the issue and/or PR

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

@melvin-bot
Copy link

melvin-bot bot commented Oct 26, 2023

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

  • [@aimane-chnaif] The PR that introduced the bug has been identified. Link to the PR:
  • [@aimane-chnaif] The offending PR has been commented on, pointing out the bug it caused and why, so the author and reviewers can learn from the mistake. Link to comment:
  • [@aimane-chnaif] A discussion in #expensify-bugs has been started about whether any other steps should be taken (e.g. updating the PR review checklist) in order to catch this type of bug sooner. Link to discussion:
  • [@aimane-chnaif] Determine if we should create a regression test for this bug.
  • [@aimane-chnaif] If we decide to create a regression test for the bug, please propose the regression test steps to ensure the same bug will not reach production again.
  • [@sakluger] Link the GH issue for creating/updating the regression test once above steps have been agreed upon:

@melvin-bot melvin-bot bot added Daily KSv2 and removed Weekly KSv2 labels Nov 2, 2023
@sakluger
Copy link
Contributor

sakluger commented Nov 2, 2023

I've completed payment to @jayeshmangwani and @bernhardoj. @aimane-chnaif could you please complete the BZ checklist? Once you do I can finish payments and close the issue.

@aimane-chnaif
Copy link
Contributor

No regression. This bug existed from the beginning.

Regression Test Proposal

  1. Create workspace if not exist
  2. Go to #admins or #announce room
  3. Send any message
  4. Press the pencil icon to start editing the message
  5. Verify that the message is in edit mode
  6. Delete the workspace
  7. Verify that the message is now in non-edit mode

@sakluger
Copy link
Contributor

sakluger commented Nov 3, 2023

Thanks!

@sakluger sakluger closed this as completed Nov 3, 2023
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 Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 Engineering External Added to denote the issue can be worked on by a contributor Internal Requires API changes or must be handled by Expensify staff
Projects
None yet
Development

No branches or pull requests

7 participants