From fe4ea54e19e21e59aaefa8efc9e37d9cd1537bd9 Mon Sep 17 00:00:00 2001 From: rsashank Date: Sat, 12 Oct 2024 11:27:50 +0530 Subject: [PATCH 1/5] views: Add PollResultsView class. Takes poll_question and options as an input and displays voters for each option. --- zulipterminal/ui_tools/views.py | 35 +++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/zulipterminal/ui_tools/views.py b/zulipterminal/ui_tools/views.py index 02b3afbd0b..effba3b7f5 100644 --- a/zulipterminal/ui_tools/views.py +++ b/zulipterminal/ui_tools/views.py @@ -23,6 +23,7 @@ from zulipterminal.config.symbols import ( CHECK_MARK, COLUMN_TITLE_BAR_LINE, + INVALID_MARKER, PINNED_STREAMS_DIVIDER, SECTION_DIVIDER_LINE, ) @@ -2176,3 +2177,37 @@ def keypress(self, size: urwid_Size, key: str) -> str: self.controller.exit_popup() return key return super().keypress(size, key) + + +class PollResultsView(PopUpView): + def __init__( + self, + controller: Any, + poll_question: str, + poll_options: Dict[str, Dict[str, Any]], + ) -> None: + poll_results_content: List[Tuple[str, List[Tuple[str, str]]]] = [("", [])] + + for option_key, option_data in poll_options.items(): + option_text = option_data["option"] + if len(option_text) >= 13: + option_text = option_text[:10] + "…" + voter_names = option_data["votes"] + + voters_display = ( + "\n".join(map(str, voter_names)) + if voter_names + else f"{INVALID_MARKER} No votes yet" + ) + + poll_results_content[0][1].append((option_text, voters_display)) + + popup_width, column_widths = self.calculate_table_widths( + poll_results_content, len(poll_question) + ) + + widgets = self.make_table_with_categories(poll_results_content, column_widths) + + super().__init__( + controller, widgets, "SHOW_POLL_VOTES", popup_width, poll_question + ) From 3feafcebbbe3c44fe20e2839baa25dbc1f39c631 Mon Sep 17 00:00:00 2001 From: rsashank Date: Sat, 12 Oct 2024 11:29:14 +0530 Subject: [PATCH 2/5] core: Add show_poll_vote method to Controller. Creates an instance of PollResultsView class and shows the popup. --- zulipterminal/core.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/zulipterminal/core.py b/zulipterminal/core.py index 61c5f79922..3540f527cb 100644 --- a/zulipterminal/core.py +++ b/zulipterminal/core.py @@ -43,6 +43,7 @@ MarkdownHelpView, MsgInfoView, NoticeView, + PollResultsView, PopUpConfirmationView, StreamInfoView, StreamMembersView, @@ -281,6 +282,34 @@ def show_msg_info( ) self.show_pop_up(msg_info_view, "area:msg") + def show_poll_vote( + self, + poll_question: str, + options: Dict[str, Dict[str, Any]], + ) -> None: + options_with_names = {} + for option_key, option_data in options.items(): + option_text = option_data["option"] + voter_ids = option_data["votes"] + + voter_names = [] + for voter_id in voter_ids: + voter_names.append(self.model.user_name_from_id(voter_id)) + + options_with_names[option_key] = { + "option": option_text, + "votes": voter_names if voter_names else [], + } + + self.show_pop_up( + PollResultsView( + self, + poll_question, + options_with_names, + ), + "area:msg", + ) + def show_emoji_picker(self, message: Message) -> None: all_emoji_units = [ (emoji_name, emoji["code"], emoji["aliases"]) From 25dfcd3b452deb1a58ea07c2ad333ebf3b9f815a Mon Sep 17 00:00:00 2001 From: rsashank Date: Sat, 12 Oct 2024 11:20:22 +0530 Subject: [PATCH 3/5] keys: Add SHOW_POLL_VOTES hotkey. SHOW_POLL_VOTES : 'v' to check votes for a given poll. --- docs/hotkeys.md | 1 + zulipterminal/config/keys.py | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/docs/hotkeys.md b/docs/hotkeys.md index 43bbf6125a..82cb3491f1 100644 --- a/docs/hotkeys.md +++ b/docs/hotkeys.md @@ -136,4 +136,5 @@ |View current message in browser|v| |Show/hide full rendered message|f| |Show/hide full raw message|r| +|Show/hide poll voter list|w| diff --git a/zulipterminal/config/keys.py b/zulipterminal/config/keys.py index a86420a364..4b8c36f958 100644 --- a/zulipterminal/config/keys.py +++ b/zulipterminal/config/keys.py @@ -457,6 +457,11 @@ class KeyBinding(TypedDict): 'help_text': 'Show/hide full raw message', 'key_category': 'msg_info', }, + 'SHOW_POLL_VOTES': { + 'keys': ['w'], + 'help_text': 'Show/hide poll voter list', + 'key_category': 'msg_info', + }, 'NEW_HINT': { 'keys': ['tab'], 'help_text': 'New footer hotkey hint', From 9a5bba5028f923e49724557fe375bb08067970bb Mon Sep 17 00:00:00 2001 From: rsashank Date: Sat, 12 Oct 2024 11:30:27 +0530 Subject: [PATCH 4/5] messages: Add logic to handle the SHOW_POLL_VOTES hotkey. --- zulipterminal/ui_tools/messages.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/zulipterminal/ui_tools/messages.py b/zulipterminal/ui_tools/messages.py index 8fe2bb8f5c..f2b6785245 100644 --- a/zulipterminal/ui_tools/messages.py +++ b/zulipterminal/ui_tools/messages.py @@ -69,6 +69,7 @@ def __init__(self, message: Message, model: "Model", last_message: Any) -> None: self.topic_links: Dict[str, Tuple[str, int, bool]] = dict() self.time_mentions: List[Tuple[str, str]] = list() self.last_message = last_message + self.widget_type: str = "" # if this is the first message if self.last_message is None: self.last_message = defaultdict(dict) @@ -733,9 +734,9 @@ def main_view(self) -> List[Any]: ) if self.message.get("submessages"): - widget_type = find_widget_type(self.message.get("submessages", [])) + self.widget_type = find_widget_type(self.message.get("submessages", [])) - if widget_type == "todo": + if self.widget_type == "todo": title, tasks = process_todo_widget(self.message.get("submessages", [])) todo_widget = "To-do\n" + f"{title}" @@ -757,28 +758,28 @@ def main_view(self) -> List[Any]: # though it's not very useful. self.message["content"] = todo_widget - elif widget_type == "poll": - poll_question, poll_options = process_poll_widget( + elif self.widget_type == "poll": + self.poll_question, self.poll_options = process_poll_widget( self.message.get("submessages", []) ) # TODO: ZT doesn't yet support adding poll questions after the # creation of the poll. So, if the poll question is not provided, # we show a message to add one via the web app. - if not poll_question: - poll_question = ( + if not self.poll_question: + self.poll_question = ( "No poll question is provided. Please add one via the web app." ) - poll_widget = f"Poll\n{poll_question}" + poll_widget = f"Poll\n{self.poll_question}" - if poll_options: + if self.poll_options: max_votes_len = max( len(str(len(option["votes"]))) - for option in poll_options.values() + for option in self.poll_options.values() ) - for option_info in poll_options.values(): + for option_info in self.poll_options.values(): padded_votes = f"{len(option_info['votes']):>{max_votes_len}}" poll_widget += f"\n[ {padded_votes} ] {option_info['option']}" else: @@ -1188,4 +1189,6 @@ def keypress(self, size: urwid_Size, key: str) -> Optional[str]: self.model.controller.show_emoji_picker(self.message) elif is_command_key("MSG_SENDER_INFO", key): self.model.controller.show_msg_sender_info(self.message["sender_id"]) + elif is_command_key("SHOW_POLL_VOTES", key) and self.widget_type == "poll": + self.model.controller.show_poll_vote(self.poll_question, self.poll_options) return key From f40487f1bbc74b11e2c5f483ba5d314a6d5f1239 Mon Sep 17 00:00:00 2001 From: "neiljp (Neil Pilgrim)" Date: Thu, 3 Apr 2025 19:35:05 -0700 Subject: [PATCH 5/5] WIP: keys: Adjust poll votes popup to 'M'. Using 'w' clashes with the global search-users hotkey. Use of 'M' is only temporary, to enable feature demonstration. --- docs/hotkeys.md | 2 +- zulipterminal/config/keys.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/hotkeys.md b/docs/hotkeys.md index 82cb3491f1..61433c8d14 100644 --- a/docs/hotkeys.md +++ b/docs/hotkeys.md @@ -136,5 +136,5 @@ |View current message in browser|v| |Show/hide full rendered message|f| |Show/hide full raw message|r| -|Show/hide poll voter list|w| +|Show/hide poll voter list|M| diff --git a/zulipterminal/config/keys.py b/zulipterminal/config/keys.py index 4b8c36f958..77e8cb639a 100644 --- a/zulipterminal/config/keys.py +++ b/zulipterminal/config/keys.py @@ -458,7 +458,7 @@ class KeyBinding(TypedDict): 'key_category': 'msg_info', }, 'SHOW_POLL_VOTES': { - 'keys': ['w'], + 'keys': ['M'], 'help_text': 'Show/hide poll voter list', 'key_category': 'msg_info', },