From d81f65f2e9d7aaf67735bbabf8067c46985d81e2 Mon Sep 17 00:00:00 2001 From: JisanAR03 Date: Sat, 22 Jun 2024 15:16:12 +0600 Subject: [PATCH 1/5] update the project slash command --- src/sammich/plugins/project.py | 69 ++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 7 deletions(-) diff --git a/src/sammich/plugins/project.py b/src/sammich/plugins/project.py index 364a5ac..ec785d1 100644 --- a/src/sammich/plugins/project.py +++ b/src/sammich/plugins/project.py @@ -1,32 +1,87 @@ import json +import re from machine.clients.slack import SlackClient from machine.plugins.base import MachineBasePlugin -from machine.plugins.decorators import command +from machine.plugins.decorators import action, command from machine.storage import PluginStorage from machine.utils.collections import CaseInsensitiveDict +PROJECTS_PER_PAGE = 100 + class ProjectPlugin(MachineBasePlugin): def __init__(self, client: SlackClient, settings: CaseInsensitiveDict, storage: PluginStorage): super().__init__(client, settings, storage) + with open("data/projects.json") as f: self.project_data = json.load(f) @command("/project") async def project(self, command): - text = command.text.strip() - project_name = text.strip().lower() + project_name = command.text.strip().lower() + channel_id = command._cmd_payload["channel_id"] project = self.project_data.get(project_name) if project: project_list = "\n".join(project) message = f"Hello, here the information about '{project_name}':\n{project_list}" + await command.say(message) else: - message = ( - f"Hello, the project '{project_name}' is not recognized. " - "Please try different query." + await self.show_project_page(channel_id) + + async def show_project_page(self, channel_id): + projects = list(self.project_data.keys()) + + if not projects: + await self.web_client.chat_postMessage( + channel=channel_id, text="No projects available." + ) + return + + # Calculate the number of dropdowns needed + num_dropdowns = (len(projects) + PROJECTS_PER_PAGE - 1) // PROJECTS_PER_PAGE + + blocks = [] + for i in range(num_dropdowns): + start_index = i * PROJECTS_PER_PAGE + end_index = start_index + PROJECTS_PER_PAGE + project_slice = projects[start_index:end_index] + + options = [ + {"text": {"type": "plain_text", "text": project[:75]}, "value": project} + for project in project_slice + ] + + blocks.append( + { + "type": "section", + "block_id": f"project_select_block_{i}", + "text": { + "type": "mrkdwn", + "text": f"Select a project (Page {i + 1}):", + }, + "accessory": { + "type": "static_select", + "placeholder": { + "type": "plain_text", + "text": f"Select a project (Page {i + 1})", + }, + "options": options, + "action_id": f"project_select_action_{i}", + }, + } ) - await command.say(message) + await self.web_client.chat_postMessage( + channel=channel_id, blocks=blocks, text="Available Projects" + ) + + @action(action_id=re.compile(r"project_select_action_.*"), block_id=None) + async def handle_dropdown_selection(self, action): + selected_project = action.payload.actions[0].selected_option.value + project = self.project_data.get(selected_project) + project_list = "\n".join(project) + message = f"Hello, here is the information about '{selected_project}':\n{project_list}" + await action.say(message) From 976d99ceec7145582fe3229176ad3e589724edb7 Mon Sep 17 00:00:00 2001 From: JisanAR03 Date: Tue, 25 Jun 2024 13:03:28 +0600 Subject: [PATCH 2/5] implement some suggestion --- src/sammich/plugins/project.py | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/sammich/plugins/project.py b/src/sammich/plugins/project.py index ec785d1..e6554da 100644 --- a/src/sammich/plugins/project.py +++ b/src/sammich/plugins/project.py @@ -14,8 +14,11 @@ class ProjectPlugin(MachineBasePlugin): def __init__(self, client: SlackClient, settings: CaseInsensitiveDict, storage: PluginStorage): super().__init__(client, settings, storage) - with open("data/projects.json") as f: - self.project_data = json.load(f) + try: + with open("data/projects.json") as f: + self.project_data = json.load(f) + except json.JSONDecodeError: + self.project_data = {} @command("/project") async def project(self, command): @@ -29,29 +32,30 @@ async def project(self, command): message = f"Hello, here the information about '{project_name}':\n{project_list}" await command.say(message) else: + # if the self.project_data is empty, return a message + if not self.project_data: + await command.say("No projects available") + return None await self.show_project_page(channel_id) async def show_project_page(self, channel_id): projects = list(self.project_data.keys()) - if not projects: - await self.web_client.chat_postMessage( - channel=channel_id, text="No projects available." - ) - return - # Calculate the number of dropdowns needed num_dropdowns = (len(projects) + PROJECTS_PER_PAGE - 1) // PROJECTS_PER_PAGE blocks = [] for i in range(num_dropdowns): - start_index = i * PROJECTS_PER_PAGE - end_index = start_index + PROJECTS_PER_PAGE - project_slice = projects[start_index:end_index] + project_for_each_page = 75 options = [ - {"text": {"type": "plain_text", "text": project[:75]}, "value": project} - for project in project_slice + { + "text": {"type": "plain_text", "text": project[:project_for_each_page]}, + "value": project, + } + for project in projects[ + i * PROJECTS_PER_PAGE : i * PROJECTS_PER_PAGE + PROJECTS_PER_PAGE + ] ] blocks.append( @@ -78,7 +82,7 @@ async def show_project_page(self, channel_id): channel=channel_id, blocks=blocks, text="Available Projects" ) - @action(action_id=re.compile(r"project_select_action_.*"), block_id=None) + @action(action_id=re.compile(r"project_select_action_.*")) async def handle_dropdown_selection(self, action): selected_project = action.payload.actions[0].selected_option.value project = self.project_data.get(selected_project) From b7c877e8b8b6b2e8bcf54daa0274dc2c9b06a939 Mon Sep 17 00:00:00 2001 From: JisanAR03 Date: Wed, 26 Jun 2024 03:06:07 +0600 Subject: [PATCH 3/5] move variable out of the loop --- src/sammich/plugins/project.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sammich/plugins/project.py b/src/sammich/plugins/project.py index e6554da..1179e51 100644 --- a/src/sammich/plugins/project.py +++ b/src/sammich/plugins/project.py @@ -45,9 +45,8 @@ async def show_project_page(self, channel_id): num_dropdowns = (len(projects) + PROJECTS_PER_PAGE - 1) // PROJECTS_PER_PAGE blocks = [] + project_for_each_page = 75 for i in range(num_dropdowns): - project_for_each_page = 75 - options = [ { "text": {"type": "plain_text", "text": project[:project_for_each_page]}, From 1f75ae9143e9f61c5f266f350c7dbf05638d53eb Mon Sep 17 00:00:00 2001 From: JisanAR03 Date: Wed, 26 Jun 2024 06:03:16 +0600 Subject: [PATCH 4/5] adding comment for the issue we had about .say() --- src/sammich/plugins/project.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/sammich/plugins/project.py b/src/sammich/plugins/project.py index 1179e51..e6d9e75 100644 --- a/src/sammich/plugins/project.py +++ b/src/sammich/plugins/project.py @@ -77,6 +77,12 @@ async def show_project_page(self, channel_id): } ) + # Here, we use `self.web_client.chat_postMessage` instead of `command.say()` + # because `command.say()` sends an ephemeral message (is_ephemeral=True) by default. + # When is_ephemeral is true, Slack API restricts interactions with the message, + # making it impossible to trigger actions from it. + # Therefore, we use `web_client.chat_postMessage` to post a standard message + # that allows interactive elements like dropdowns to work correctly. await self.web_client.chat_postMessage( channel=channel_id, blocks=blocks, text="Available Projects" ) From 97b7fbddd315ba23ae54ff94363b1ccbc2043941 Mon Sep 17 00:00:00 2001 From: JisanAR03 Date: Wed, 26 Jun 2024 06:06:36 +0600 Subject: [PATCH 5/5] adding comment for the issue we had about .say() --- src/sammich/plugins/project.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sammich/plugins/project.py b/src/sammich/plugins/project.py index e6d9e75..46a3ece 100644 --- a/src/sammich/plugins/project.py +++ b/src/sammich/plugins/project.py @@ -77,11 +77,11 @@ async def show_project_page(self, channel_id): } ) - # Here, we use `self.web_client.chat_postMessage` instead of `command.say()` - # because `command.say()` sends an ephemeral message (is_ephemeral=True) by default. - # When is_ephemeral is true, Slack API restricts interactions with the message, - # making it impossible to trigger actions from it. - # Therefore, we use `web_client.chat_postMessage` to post a standard message + # Here, we use `self.web_client.chat_postMessage` instead of `command.say()` + # because `command.say()` sends an ephemeral message (is_ephemeral=True) by default. + # When is_ephemeral is true, Slack API restricts interactions with the message, + # making it impossible to trigger actions from it. + # Therefore, we use `web_client.chat_postMessage` to post a standard message # that allows interactive elements like dropdowns to work correctly. await self.web_client.chat_postMessage( channel=channel_id, blocks=blocks, text="Available Projects"