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

Moving topics between streams #13912

Closed

Conversation

dobleuber
Copy link
Contributor

@dobleuber dobleuber commented Feb 14, 2020

#6427

Feature Behaviour
Test topic - Zulip Dev - Zulip

@timabbott
Copy link
Sponsor Member

@dobleuber can you clean up the commit history? Check out the Zulip commit guidelines for more details: https://zulip.readthedocs.io/en/latest/contributing/version-control.html

user_profile: UserProfile,
stream: Stream,
topic_name: str
) -> List[Message]:
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line-wrapping doesn't match zulip's style. Please look at nearby code and follow our conventions.

user_profile=user_profile
)

recipient = stream.recipient
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This variable is unnecessary.

topic_name=topic_name,
)

return messages
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the above, but also I think this whole function could be like 2 lines of reasonable code; you possibly should just have the caller call filter_by_topic_name_via_message.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was getting this lint error:

avoid subject as a var at zerver/lib/actions.py line 5910:
message__subject__iexact=topic_name

So I called the method filter_by_topic_name_via_message

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I just mean it could be:

query = UserMessage.objects.filter(user_profile=user_profile, message__recipient=stream.recipient)
return filter_by_topic_name_via_message(query=query, topic_name=topic_name)

Which might be better inlined unless we need it for tests.

def do_move_topic_messages(
user_profile: UserProfile,
stream_origin: Stream,
stream_destiny: Stream,
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call these old_stream and new_stream.

user_messages = get_topic_messages(user_profile, stream_origin, topic_name)
recipient_destiny = get_stream_recipient(stream_destiny.id)

# We could use a bot for the breadcrump message too
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, let's change this to a message sent by Notification Bot.

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mateuszmandera I just noticed we have these get_stream_recipient and get_personal_recipient helper functions in a few places that this code is copying; we should just remove those and use stream.recipient etc., right? (And delete get_recipient and its cache as well, I think???)

In any case, for this PR, @dobleuber you can just use new_stream.recipient.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@timabbott Yeah, we still have a bunch of places where we use those functions that haven't been changed. It should be pretty quick to do though and then we can remove the functions completely. I'll add it to my list.


for user_message in user_messages:
user_message.message.recipient = recipient_destiny
user_message.message.save(update_fields=['recipient'])
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't going to work for caching and real-time sync reasons.

See https://zulip.readthedocs.io/en/latest/subsystems/caching.html and https://zulip.readthedocs.io/en/latest/subsystems/events-system.html for details.

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After some investigation, the caching situation might actually be fine, because flush_message ignores update_fields currently and just deletes any modified messages from the cache.

Real-time sync is going to be much more problematic; we'll need to extend the interface for "edit message" events to allow the stream to change. It shouldn't be too bad because the problem is very similar to that of topic editing which we already do that correctly for. I think ultimately what we'll want to do have this go through the edit message code path.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I'll continue reviewing do_update_message. It does a lot of things, I'm not sure if I can reuse that method (adding a stream parameter), because we could have performance issues. I'm going to continue reviewing the code, if I have any questions I'll let you know, thanks

@dobleuber dobleuber force-pushed the moving-topics-between-streams branch 2 times, most recently from 3cb4381 to db42c12 Compare February 17, 2020 23:23
@timabbott timabbott force-pushed the moving-topics-between-streams branch 2 times, most recently from b4805f8 to a3b2708 Compare February 19, 2020 01:32
@timabbott
Copy link
Sponsor Member

Thanks for working on this @dobleuber! I pushed back to this PR a set of commits that rewrite this to use the do_update_messages infrastructure. Some notes:

  • The tests need some cleanup; we never hardcode IDs like 10 in them, instead using user.id substitutions.
  • The use of do_update_messages partially fixes the message edit history for this feature. We'll also need to add display code for it, which we can leave for follow-up work as long as the data is there.
  • It also sets us up with just a bit of plumbing work in its views.py caller to provide this feature via the API rather than a management command, which both makes UI possible and doesn't require server shell access to use. I think probably we should plan to delete the management command work and instead focus on making the .
  • The send_event code for real-time sync needs work, both in this backend code (to decide what users to notify correctly) and on the frontend (to update the UI in exports.update_messages within message_events.js). I'm OK with a potentially somewhat weird intermediate state, since one can reload browser windows, but we should at least make sure we've thought through how this might work.

The events thing may be hard for you to fix efficiently, but @dobleuber in your next pass, can you work on cleaning up the tests, changing the guard messages to use narrow_url to provide nice links? Feel free to squash my new commit into yours; I think it's better squashed, but wanted to leave it separate just to make it easy for you to see what I did. Also you could work on making update_message_backend support this code path as an realm admins-only feature.

@dobleuber dobleuber force-pushed the moving-topics-between-streams branch 4 times, most recently from 2ea3206 to bfafaf1 Compare February 19, 2020 20:13
@dobleuber
Copy link
Contributor Author

@timabbott I worked in your last comments.
Please let me know if you have any other comment, thanks for your help :-)

@timabbott
Copy link
Sponsor Member

@dobleuber can you comment on which of the TODOs noted above you resolved, and how?

@dobleuber
Copy link
Contributor Author

  • cleanup the tests: I refactor a little the tests to avoid using hardcoded ids and to do the tests independent of the environment.
  • changing the guard messages to use narrow_url to provide nice links: I called the method topic_narrow_url to get the new topic url and added it to the message.
  • I added a condition to allow this method be run just for realm admin users

Oh! I miss the method update_message_backend. Working on it. thanks

@dobleuber dobleuber force-pushed the moving-topics-between-streams branch 2 times, most recently from 9561282 to e60953c Compare February 20, 2020 23:58
@dobleuber
Copy link
Contributor Author

  • Updated the method update_message_backend to allow changing messages stream.
  • Updated tests for api call to update_message_backend

@dobleuber
Copy link
Contributor Author

@timabbott Any feedback for this? meanwhile I am working in UI part:
image

@pirate
Copy link
Sponsor Contributor

pirate commented Feb 22, 2020

I love that UI, nice work so far @dobleuber.

@timabbott
Copy link
Sponsor Member

For UI, I think we should start with modifying the existing message editing UI where one can change topics to also have a "Stream" field; I think that will be a lot simpler as a way to start.

@timabbott timabbott force-pushed the moving-topics-between-streams branch 2 times, most recently from 49510b7 to 353c78d Compare February 27, 2020 00:06
@timabbott
Copy link
Sponsor Member

@dobleuber I just pushed an extra commit to this PR that does an incomplete version of a refactor that I think we should do before merging this; I didn't have time to clean up the tests (etc.), but basically, my hope is to eliminate both the management command and the extra function, and just have a single code path calling do_update_message with various arguments.

I also changed the code in a way that should fix some obviously broken behavior with the breadcrumb messages (various pieces were swapped).

You'll need to:

  • Fix the linter/syntax/etc. errors; this is totally untested
  • Rewrite the backend tests to use the API rather than calling do_* functions. (Or maybe just delete the do_move_topic tests, they may be basically duplicates of the API tests)
  • Do some manual testing and confirm that the links we generate are actually correct.

@dobleuber
Copy link
Contributor Author

@timabbott I just created this issue related with your comment: #14492

@dobleuber dobleuber force-pushed the moving-topics-between-streams branch 2 times, most recently from 55b3c66 to fedb464 Compare April 7, 2020 20:44
@timabbott timabbott force-pushed the moving-topics-between-streams branch from fedb464 to 7be3c14 Compare April 7, 2020 21:23
@timabbott
Copy link
Sponsor Member

@dobleuber OK I made the following changes:

  • Changed the parameter for message editing to stream_id, rather than new_stream_id, for consistency with the existing topic_name parameter.
  • Changed the backend tests to be cleaner and better match our style (including, critically, not assuming Iago's user ID will always be 10).
  • Switched the mentions in the automatic notifications to be silent mentions.
  • Rewrote much of the message_events.js code to
  • Added a Co-Authored-By for you since we seem to have squashed away your Git author info at some point along the way :).

The result is 843345d and 7990676.

The remaining commit is just the UI, which should be the simplest part. I'm going to open a few follow-up issues before I get to looking at that, however.

@timabbott
Copy link
Sponsor Member

I opened #14498 for the main known bug in this feature.

@timabbott
Copy link
Sponsor Member

And I opened #14499 for tracking the future work we'll want to do once #14498 is done and we've gotten some experience playing with the feature and we have more user feedback on how they'd want to configure the permissions for this in their organization.

hashirsarwar added a commit to hashirsarwar/zulip that referenced this pull request Apr 15, 2020
Previously, we had a restriction that we could only
edit and move the topics of 7 days old messages.
This buggy behaviour is now removed as in this
commit.

Fixes zulip#14492.
Part of zulip#13912.
hashirsarwar added a commit to hashirsarwar/zulip that referenced this pull request Apr 15, 2020
Previously, we had a restriction that we could only
edit and move the topics of 7 days old messages.
This buggy behaviour is now removed as in this
commit.

Fixes zulip#14492.
Part of zulip#13912.
const stream_id = topic_row.attr('data-stream-id');
const topic_name = topic_row.attr('data-topic-name');
const message = home_msg_list.all_messages()
.find(m => m.topic === topic_name && m.stream_id === +stream_id);
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check doesn't seem reliable; we may not have any messages from the topic cached in the frontend. I think the right fix is to fetch the latest message ID from stream_topic_history.js; that is guaranteed to have data given that this widget is visible at all.

@showell is there an existing function we can call, or does one need to be added to expose "any message ID from a given stream/topic appearing in the left sidebar"?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think sending a message id is the right thing here. Shouldn't it be handled better on the server side using old and new streams and topics?

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, for this UI, yes; but we'll also add this to "edit a single message" UI, and for that, the message ID is an important aspect of the meaning. (Basically whenever propagate_mode != all)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh! That's good then.

if (old_topic_name && select_stream_id) {
message_edit.move_message_to_stream(message_id, select_stream_id, topic_name);
$('#move_topic_modal').modal('hide');
}
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like we're missing stopPropagation/preventDefault here.

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed this and pushed back here.

This initial implementation of moving a topic to another stream works
as follows:

* Added a method to get all topic's messages in a stream:
    get_topic_messages
* Refactored update_message_backend method to allow changing the
    recipient of a message and the message topic
* Created method notify_topic_moved_streams to create notifications
    messages whenever a messages is moved
* Added a new option in topic's options to change stream
* Added logic to update ui after a topic is moved
* Added tests to support the code
* Added documentation page for the feature
@timabbott timabbott force-pushed the moving-topics-between-streams branch from 7be3c14 to 95d10a4 Compare April 23, 2020 23:55
@@ -854,4 +854,23 @@ exports.handle_narrow_deactivated = function () {
}
};

exports.move_message_to_stream = function (message_id, stream_id, topic_name) {
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's rename this to exports.move_topic_containing_message_to_stream, for clarity about what it does.

And maybe add a comment right here making clear the stream_id and topic_name are the NEW values, and the old ones are wherever the message is located, since that may not be intuitive.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I appended new_ before the variable. That is clear enough.

},
error: function (xhr) {
ui_report.error(i18n.t("Error moving the topic"), xhr,
$("#home-error"));
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you post a screenshot of this appearing?

Copy link
Member

@amanagr amanagr May 2, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Copy link
Member

@amanagr amanagr May 2, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cross icon in missing from the error popup.

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's probably good enough to just mark it to disappear after a few seconds.

@@ -262,6 +263,17 @@ function build_starred_messages_popover(e) {

}

function build_move_topic_to_stream_popover(e, message_id, stream_id, topic_name) {
const streams = stream_data.subscribed_subs().filter(s => s.stream_id !== stream_id);
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's call this variable available_streams.

I'll note that we currently include private streams in this list.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Added a TODO for keyboard navigation of the dropdown.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to exclude private streams?

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I think there's a product question about whether it's correct to limit it to just public streams. We should make a decision on that and adjust accordingly. Initially we did it just to manage complexity.


if (old_topic_name.trim() === topic_name.trim()) {
topic_name = undefined;
}
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a comment here noting that this is intended to request no change in the topic if it didn't change?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


1. Select **Move <topic name\> to another stream**.

1. Select the destination stream (and if desired, enter a new topic name).
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just call it "a new topic" here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@timabbott
Copy link
Sponsor Member

OK, I posted a batch of mostly small comments; the main thing we need to fix here is the computation of a message ID, which hopefully @showell can help with.


$("#move-a-topic-modal-holder").html(render_move_topic_to_stream(args));
$('#move_topic_modal').modal('show');
e.stopPropagation();
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can delete this stopPropagation; it's in the caller (and should be there)

@timabbott
Copy link
Sponsor Member

Closing in favor of #14844; @amanagr you still still read the last few comments here. Thanks @dobleuber!

@timabbott timabbott closed this May 2, 2020
@timabbott
Copy link
Sponsor Member

The UI for this was merged today. Thanks again for all the work on this @dobleuber!

timabbott pushed a commit that referenced this pull request May 8, 2020
Previously, we had a restriction that we could only
edit and move the topics of 7 days old messages.
This buggy behaviour is now removed as in this
commit.

Fixes #14492.
Part of #13912.
Dakkaron pushed a commit to Dakkaron/zulip that referenced this pull request May 12, 2020
Previously, we had a restriction that we could only
edit and move the topics of 7 days old messages.
This buggy behaviour is now removed as in this
commit.

Fixes zulip#14492.
Part of zulip#13912.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants