-
-
Notifications
You must be signed in to change notification settings - Fork 259
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
Add support for (un)resolving topics in ZT. #1235
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@srdeotarse This is a good almost-functional start with good commit separation, but possibly missing some consideration of the commit ordering. Looking forward to some tests later too, at least initially for the model.
e7c85d8
to
767c94f
Compare
I think it's better to remove |
497d317
to
0ecd465
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@srdeotarse The commit ordering here is cleaner and I've tested manually and confirmed it works for me - at least on topics I've written to 👍
As per the note inline, if the server has editing disabled then I believe topics cannot currently be resolved (and this will lead to this PR erroring?), and at the other end if 'community editing' is enabled (or various other options) then anyone can resolve at any time (perhaps excluding guests?) (which will lead to this PR not working when it should?). That may motivate a refactor of the existing topic-editing code to extract this logic, and connect to adding the community-editing feature (ie. not needing to have posted to a topic to edit it). I've also possibly seen some discussion elsewhere on czo about having separate topic resolution settings, but I believe these are currently still based on topic editing, though this would be good to confirm - and of course for now this remains the case.
I'm unsure if the updated UI is improved, particularly since multiple ENTER/SPACE/CLICK doesn't toggle (or show it), and there's no way of either avoiding it toggling on exiting the popup, or knowing if there will be an action on exiting the popup.
While there may be updates to the model logic, now that we're past WIP in that it works, it would be useful to get some preliminary tests for that logic - and that may help think about the error cases we can get and what messages the user may see and when. You may find that extracting the logic for knowing if a user can edit the topic separately (and testing that) will make this function less tangled, if you address that first.
0ecd465
to
8184d3e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your code is looking better than before, especially after handling the API better.
I've mostly reviewed the API calls and not the Popup. I'll give that a look soon. Maybe
@neiljp should also comment on the new API changes introduced as he's more familiar with them.
zulipterminal/model.py
Outdated
if response["messages"] != []: | ||
time_since_msg_sent = time.time() - response["messages"][0]["timestamp"] | ||
edit_time_limit = self.initial_data[ | ||
"realm_community_topic_editing_limit_seconds" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't know topics had a time limit. Then why do we show "Only topic editing allowed. Time limit for editing the message body has been exceeded."
when realm_message_content_edit_limit_seconds
is crossed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Who can resolve such a topic then, only admins? I assume it would be a future feature for ZT then? Probably comment it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We haven't added support for 'community' topic editing in the regular edit feature, so we give a notice there which represents the feature we support.
8184d3e
to
f4d592e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@srdeotarse I'm coming back to this after Rohitth did some reviews, but I think the basic UI will be fine for now, and I note you've updated the logic handling as per some of our discussion so I've mostly focused on reading the code 👍
I'm going to merge the first commit separately to shorten the PR and since this is independent and looks fine.
As some of the inline comments explain, I think the PR will benefit from introducing the can_user_edit_topic function at the start with all the error strings and checks you have in the toggle function, then simply going ahead in the toggle function otherwise.
I don't see a large reason to separate the first and second commits (currently 2nd and 3rd) changing the model, which would also make the can_user_edit_topic function more meaningful initially. The additional functionality for more featureful servers is perfectly fine to come later 👍
(if it modifies a mostly working can_user_edit_topic, then the upgraded functionality commits could potentially even come after the UI, and likely the commits will move fairly easily like that if those need further work, to enable merging of the basic+UI commits)
Note that the issue won't really be fixed until we have a UI element to access it, so that fixed line belongs in the last commit currently.
Along with my overall feedback here, note that we need tests, certainly initially for can_user_edit_topic and toggle_topic_resolved_status (which will then adjust in later commits with the extra server feature). I expect when you write the tests, you'll see how making the function split early simplifies them.
f4d592e
to
14459c7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@srdeotarse This is looking cleaner 👍
I would have posted the review sooner, but I have concerns over how we should best handle the logic generally. That is not down to your implementation in particular, but rather how it is documented and wider issues observed elsewhere. That seems related to how topic editing is dependent upon the message id in particular and if it belongs to the active user or not, as well as user roles.
eg.
- #issues > topic resolution order
- #issues > if marked as resolved it duplicates the argument
- #design > time restrictions on topic editing
- #21837
For now I think we should proceed as we are, and with the logic isolated and with tests we can consider if it matches expectations and adapt later.
We may want to use the first message in the narrow, as one possible example change.
zulipterminal/model.py
Outdated
if response["messages"] != []: | ||
time_since_msg_sent = time.time() - response["messages"][0]["timestamp"] | ||
edit_time_limit = self.initial_data[ | ||
"realm_community_topic_editing_limit_seconds" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We haven't added support for 'community' topic editing in the regular edit feature, so we give a notice there which represents the feature we support.
14459c7
to
e8c42ec
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@srdeotarse The reordering of commits is much easier to read now along with the tests. With extra tests I'd be comfortable starting to merge this, though as I've tried to clarify, we need to cover the different server versions properly, and the tests appear to describe strange editing behavior?
One other UI element to explore would be to lose the flashing cursor on the button. We do that elsewhere, so it's certainly achievable :)
I was testing this manually today and did trigger some thread tracebacks, but that's likely to be from the event handling instead.
96c5af4
to
95590f7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@srdeotarse Just a partial review here, since I think you didn't update everything from before and we discussed a few other points, and I wanted to get some feedback to you now.
95590f7
to
de19497
Compare
de19497
to
a10973d
Compare
@srdeotarse The last push was a good tidy following my review 👍 The first 3 commits were very close, so I just merged those with adjustments to commit messages, removed spaces at the start of some error strings, added a simple test case for no-edits in ZFL75 and the indexing point I mentioned at #1235 (comment) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@srdeotarse Here's some extra feedback after the partial merge. I followed up on some older comments too, but you may need to look further up the thread of comments for context.
Mostly it's regarding improved testing or fairly minor points.
In manual testing I did find one case where it claimed the topic/message was too old to be edited, but I could do so manually. I've not dug deeper to know if that's due to the logic in your remaining un-merged model function, since it's not as well-tested yet, or due to nuances in the server logic which we didn't incorporate in the code that's already merged. Once the function is better tested then that might be clearer, but we can treat fine-tuning to can_user_edit_topic after we've merged this PR.
zulipterminal/model.py
Outdated
edit_time_limit = self.initial_data[ | ||
"realm_community_topic_editing_limit_seconds" | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You've not addressed this point that the API can return null/None.
tests/model/test_model.py
Outdated
" Time limit for editing topic has been exceeded.", | ||
True, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two lines are confusing, though not for the specific content in this test case.
Rather, since there is no return value from the function being tested. Instead you use the return_value string to refer to either the successful new topic name, or the error string, depending on the bool value. I understand it's the "result" of the function, so kind of a 'return value' used for different purposes, and while the test will work, the naming is misleading.
So here instead of these parameters, you could have eg. expected_new_topic_name and expected_footer_error, and have both be the string expected in each case.
From another test you may remember we sometimes use either None or an empty string to indicate a sort of 'not applicable' in a given test case.
tests/model/test_model.py
Outdated
): | ||
model.initial_data = initial_data | ||
model.server_feature_level = server_feature_level | ||
initial_data["realm_community_topic_editing_limit_seconds"] = 86400 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fixed value doesn't test when the server sets different values, if the value is missing (older servers), or if it's None (newer servers).
@@ -1480,6 +1481,59 @@ def keypress(self, size: urwid_Size, key: str) -> str: | |||
return super().keypress(size, key) | |||
|
|||
|
|||
class TopicInfoView(PopUpView): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could add minimal tests for this, such as the expected title (since it varies) and the expected action of the button.
) | ||
|
||
if self.topic_name.startswith(RESOLVED_TOPIC_PREFIX): | ||
self.resolve_topic_setting_btn_lbl = "Unresolve Topic" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this need to be an attribute? I suppose it could help with a test.
a10973d
to
7f11cba
Compare
a89ad36
to
d4ed95e
Compare
The function verifies whether editing a message or editing a community topic is disabled. Also if the current user is eligible to edit a topic according to organization permissions is checked. New test added.
Fixes zulip#1075 The function calls get_latest_message_in_topic to fetch recent message in topic to be (un)resolved. It verifies user and editing conditions using can_user_edit_topic function and finally add or remove RESOLVED_TOPIC_PREFIX from topic name.
Hotkeys updated and "i" shortcut key added to KEYS_TO_EXCLUDE in generate_hotkeys.py file.
d4ed95e
to
8504cfc
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@srdeotarse Thanks for the update 👍
I went through some old comments, there are a few outstanding points to address from that and a quick read.
case( | ||
{"allow_message_editing": False, "edit_topic_policy": 1}, | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this test case being removed?
Generally I think the changes in this revised first commit are otherwise minor enough that we can drop them? The rest appear to be:
- reformatting (strings)
- errors prefixing with space
- comment removed
In any case, if we do include parts in some way, since this would be a modification of the previous function, the commit title would need adjusting.
{ | ||
"subject": "hi!", | ||
"timestamp": 11662271397, | ||
"id": 1, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This dict appears identical in each case, except for the time, so let's build it in the function to keep it simpler? You could test for the None
return value case, but that may be simpler in a separate test.
"id": 1, | ||
}, | ||
12, | ||
259200, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the timestamp within this time difference? The test case doesn't make it clear that's why we expect it to resolve.
time_since_msg_sent = time.time() - latest_msg["timestamp"] | ||
# ZFL < 11, community_topic_editing_limit_seconds | ||
# was hardcoded as int value in secs eg. 86400s (1 day) or None | ||
if self.server_feature_level is None or self.server_feature_level >= 11: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #1235 (comment)
For server 2.1, this will set edit_time_limit to None.
For server 3.0 (or ZFL 11 at least), this will set edit_time_limit to the value in the server (None or the value).
For servers between those (eg. ZFL 10), this will set edit_limit to the default, ie. 86400 - this is an edge case
My impression is that the expected server behavior was
old
86400 <-- 2.1<11
86400 <-- edge case>=11
86400 or None (per server value) <-- 3.0+
This appears to generate
old
None<11
86400>=11
86400 or None (per server value)
Is this going to fail for 2.1? If so, could you update the test to fail first?
# default return_value=True | ||
model.can_user_edit_topic = mocker.Mock(return_value=True) | ||
model.get_latest_message_in_topic = mocker.Mock(return_value=msg_response) | ||
model.update_stream_message = mocker.Mock(return_value={"result": "success"}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #1235 (comment)
This does not need a return value.
10, | ||
86400, | ||
"hi!", | ||
None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This value is always None
? Have we lost some test cases?
Heads up @srdeotarse, we just merged some commits that conflict with the changes you made in this pull request! You can review this repository's recent commits to see where the conflicts occur. Please rebase your feature branch against the |
What does this PR do?
This PR adds support for (un)resolving topics in ZT via
TopicInfoView
popup menu when topic is highlighted inleft_stream_bar
andi
key is pressed to toggletopic settings
.[WIP] #1075
Tested?
Commit flow
First commit adds
TOPIC_DESC
shortcut tokeys.py
Second commit adds above shorcut to
TopicButton
inbuttons.py
Third commit still figuring out a way to update topic name with
RESOLVED_TOPIC_PREFIX
inmodel.py
Fourth commit adds
TopicInfoView
toviews.py
Last commit adds
show_topic_info
function tocore.py
Notes & Questions
How to update the topic name by adding or removing
RESOLVED_TOPIC_PREFIX
whenTopic Resolved
checkbox is toggled?Interactions
Visual changes