mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-07-13 06:32:57 +02:00
Update slack bot listing endpoint (#4325)
* update slack bot listing endpoint * nit
This commit is contained in:
@ -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,
|
||||
|
@ -254,14 +254,14 @@ export function SlackChannelConfigFormFields({
|
||||
onSearchTermChange={(term) => {
|
||||
form.setFieldValue("channel_name", term);
|
||||
}}
|
||||
allowCustomValues={true}
|
||||
/>
|
||||
)}
|
||||
</Field>
|
||||
<p className="mt-2 text-sm dark:text-neutral-400 text-neutral-600">
|
||||
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.
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
|
@ -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({
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search..."
|
||||
placeholder={
|
||||
allowCustomValues ? "Search or enter custom value..." : "Search..."
|
||||
}
|
||||
value={searchTerm}
|
||||
onChange={(e: ChangeEvent<HTMLInputElement>) => {
|
||||
setSearchTerm(e.target.value);
|
||||
if (e.target.value) {
|
||||
const newValue = e.target.value;
|
||||
setSearchTerm(newValue);
|
||||
if (onSearchTermChange) {
|
||||
onSearchTermChange(newValue);
|
||||
}
|
||||
if (newValue) {
|
||||
setIsOpen(true);
|
||||
} else {
|
||||
setIsOpen(false);
|
||||
}
|
||||
}}
|
||||
onFocus={() => setIsOpen(true)}
|
||||
onKeyDown={(e) => {
|
||||
if (
|
||||
e.key === "Enter" &&
|
||||
allowCustomValues &&
|
||||
searchTerm.trim() !== ""
|
||||
) {
|
||||
e.preventDefault();
|
||||
handleCustomValueSelect();
|
||||
}
|
||||
}}
|
||||
className="inline-flex justify-between w-full px-4 py-2 text-sm bg-white dark:bg-transparent text-text-800 border border-background-300 rounded-md shadow-sm"
|
||||
/>
|
||||
<button
|
||||
@ -153,6 +188,22 @@ export function SearchMultiSelectDropdown({
|
||||
)
|
||||
)}
|
||||
|
||||
{allowCustomValues &&
|
||||
searchTerm.trim() !== "" &&
|
||||
!filteredOptions.some(
|
||||
(option) =>
|
||||
option.name.toLowerCase() === searchTerm.toLowerCase()
|
||||
) && (
|
||||
<button
|
||||
className="w-full text-left flex items-center px-4 py-2 text-sm text-text-800 hover:bg-background-100"
|
||||
role="menuitem"
|
||||
onClick={handleCustomValueSelect}
|
||||
>
|
||||
<PlusIcon className="w-4 h-4 mr-2 text-text-600" />
|
||||
Use "{searchTerm}" as custom value
|
||||
</button>
|
||||
)}
|
||||
|
||||
{onCreate &&
|
||||
searchTerm.trim() !== "" &&
|
||||
!filteredOptions.some(
|
||||
@ -177,7 +228,8 @@ export function SearchMultiSelectDropdown({
|
||||
)}
|
||||
|
||||
{filteredOptions.length === 0 &&
|
||||
(!onCreate || searchTerm.trim() === "") && (
|
||||
((!onCreate && !allowCustomValues) ||
|
||||
searchTerm.trim() === "") && (
|
||||
<div className="px-4 py-2.5 text-sm text-text-500">
|
||||
No matches found
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user