diff --git a/backend/onyx/server/manage/slack_bot.py b/backend/onyx/server/manage/slack_bot.py index 0da66a5f607..1b0ebfa29e5 100644 --- a/backend/onyx/server/manage/slack_bot.py +++ b/backend/onyx/server/manage/slack_bot.py @@ -371,7 +371,9 @@ def get_all_channels_from_slack_api( _: User | None = Depends(current_admin_user), ) -> list[SlackChannel]: """ - Fetches channels the bot is a member of from the Slack API. + Fetches all channels in the Slack workspace using the conversations_list API. + This includes both public and private channels that are visible to the app, + not just the ones the bot is a member of. Handles pagination with a limit to avoid excessive API calls. """ tokens = fetch_slack_bot_tokens(db_session, bot_id) @@ -386,20 +388,20 @@ def get_all_channels_from_slack_api( current_page = 0 try: - # Use users_conversations with limited pagination + # Use conversations_list to get all channels in the workspace (including ones the bot is not a member of) while current_page < MAX_SLACK_PAGES: current_page += 1 # Make API call with cursor if we have one if next_cursor: - response = client.users_conversations( + response = client.conversations_list( types="public_channel,private_channel", exclude_archived=True, cursor=next_cursor, limit=SLACK_API_CHANNELS_PER_PAGE, ) else: - response = client.users_conversations( + response = client.conversations_list( types="public_channel,private_channel", exclude_archived=True, limit=SLACK_API_CHANNELS_PER_PAGE, diff --git a/web/src/app/admin/bots/[bot-id]/channels/SlackChannelConfigFormFields.tsx b/web/src/app/admin/bots/[bot-id]/channels/SlackChannelConfigFormFields.tsx index 9222205b8dd..67192b39d12 100644 --- a/web/src/app/admin/bots/[bot-id]/channels/SlackChannelConfigFormFields.tsx +++ b/web/src/app/admin/bots/[bot-id]/channels/SlackChannelConfigFormFields.tsx @@ -254,14 +254,14 @@ export function SlackChannelConfigFormFields({ onSearchTermChange={(term) => { form.setFieldValue("channel_name", term); }} + allowCustomValues={true} /> )}
- Note: This list shows public and private channels where the - bot is a member (up to 500 channels). If you don't see a - channel, make sure the bot is added to that channel in Slack - first, or type the channel name manually. + Note: This list shows existing public and private channels (up + to 500). You can either select from the list or type any + channel name directly.
> )} diff --git a/web/src/components/Dropdown.tsx b/web/src/components/Dropdown.tsx index 83cdf26d9dd..c74ddc72279 100644 --- a/web/src/components/Dropdown.tsx +++ b/web/src/components/Dropdown.tsx @@ -54,6 +54,7 @@ export function SearchMultiSelectDropdown({ onDelete, onSearchTermChange, initialSearchTerm = "", + allowCustomValues = false, }: { options: StringOrNumberOption[]; onSelect: (selected: StringOrNumberOption) => void; @@ -62,6 +63,7 @@ export function SearchMultiSelectDropdown({ onDelete?: (name: string) => void; onSearchTermChange?: (term: string) => void; initialSearchTerm?: string; + allowCustomValues?: boolean; }) { const [isOpen, setIsOpen] = useState(false); const [searchTerm, setSearchTerm] = useState(initialSearchTerm); @@ -77,12 +79,29 @@ export function SearchMultiSelectDropdown({ option.name.toLowerCase().includes(searchTerm.toLowerCase()) ); + // Handle selecting a custom value not in the options list + const handleCustomValueSelect = () => { + if (allowCustomValues && searchTerm.trim() !== "") { + const customOption: StringOrNumberOption = { + name: searchTerm, + value: searchTerm, + }; + onSelect(customOption); + setIsOpen(false); + } + }; + useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if ( dropdownRef.current && !dropdownRef.current.contains(event.target as Node) ) { + // If allowCustomValues is enabled and there's text in the search field, + // treat clicking outside as selecting the custom value + if (allowCustomValues && searchTerm.trim() !== "") { + handleCustomValueSelect(); + } setIsOpen(false); } }; @@ -91,7 +110,7 @@ export function SearchMultiSelectDropdown({ return () => { document.removeEventListener("mousedown", handleClickOutside); }; - }, []); + }, [allowCustomValues, searchTerm]); useEffect(() => { setSearchTerm(initialSearchTerm); @@ -102,17 +121,33 @@ export function SearchMultiSelectDropdown({