This commit is contained in:
pablonyx 2025-02-24 09:44:18 -08:00 committed by GitHub
parent f0c13b6558
commit 1263e21eb5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 66 additions and 55 deletions

View File

@ -1,5 +1,3 @@
from typing import Any
from fastapi import APIRouter
from fastapi import Depends
from fastapi import HTTPException
@ -345,6 +343,9 @@ def list_bot_configs(
]
MAX_CHANNELS = 200
@router.get(
"/admin/slack-app/bots/{bot_id}/channels",
)
@ -353,38 +354,40 @@ def get_all_channels_from_slack_api(
db_session: Session = Depends(get_session),
_: User | None = Depends(current_admin_user),
) -> list[SlackChannel]:
"""
Fetches all channels from the Slack API.
If the workspace has 200 or more channels, we raise an error.
"""
tokens = fetch_slack_bot_tokens(db_session, bot_id)
if not tokens or "bot_token" not in tokens:
raise HTTPException(
status_code=404, detail="Bot token not found for the given bot ID"
)
bot_token = tokens["bot_token"]
client = WebClient(token=bot_token)
client = WebClient(token=tokens["bot_token"])
try:
channels = []
cursor = None
while True:
response = client.conversations_list(
types="public_channel,private_channel",
exclude_archived=True,
limit=1000,
cursor=cursor,
)
for channel in response["channels"]:
channels.append(SlackChannel(id=channel["id"], name=channel["name"]))
response = client.conversations_list(
types="public_channel,private_channel",
exclude_archived=True,
limit=MAX_CHANNELS,
)
response_metadata: dict[str, Any] = response.get("response_metadata", {})
if isinstance(response_metadata, dict):
cursor = response_metadata.get("next_cursor")
if not cursor:
break
else:
break
channels = [
SlackChannel(id=channel["id"], name=channel["name"])
for channel in response["channels"]
]
if len(channels) == MAX_CHANNELS:
raise HTTPException(
status_code=400,
detail=f"Workspace has {MAX_CHANNELS} or more channels.",
)
return channels
except SlackApiError as e:
raise HTTPException(
status_code=500, detail=f"Error fetching channels from Slack API: {str(e)}"
status_code=500,
detail=f"Error fetching channels from Slack API: {str(e)}",
)

View File

@ -1,7 +1,7 @@
"use client";
import React, { useMemo, useState, useEffect } from "react";
import { Formik, Form, Field } from "formik";
import React, { useMemo } from "react";
import { Formik, Form } from "formik";
import * as Yup from "yup";
import { usePopup } from "@/components/admin/connectors/Popup";
import {
@ -13,17 +13,13 @@ import {
createSlackChannelConfig,
isPersonaASlackBotPersona,
updateSlackChannelConfig,
fetchSlackChannels,
} from "../lib";
import CardSection from "@/components/admin/CardSection";
import { useRouter } from "next/navigation";
import { Persona } from "@/app/admin/assistants/interfaces";
import { StandardAnswerCategoryResponse } from "@/components/standardAnswers/getStandardAnswerCategoriesIfEE";
import { SEARCH_TOOL_ID, SEARCH_TOOL_NAME } from "@/app/chat/tools/constants";
import {
SlackChannelConfigFormFields,
SlackChannelConfigFormFieldsProps,
} from "./SlackChannelConfigFormFields";
import { SEARCH_TOOL_ID } from "@/app/chat/tools/constants";
import { SlackChannelConfigFormFields } from "./SlackChannelConfigFormFields";
export const SlackChannelConfigCreationForm = ({
slack_bot_id,

View File

@ -1,13 +1,7 @@
"use client";
import React, { useState, useEffect, useMemo } from "react";
import {
FieldArray,
Form,
useFormikContext,
ErrorMessage,
Field,
} from "formik";
import { FieldArray, useFormikContext, ErrorMessage, Field } from "formik";
import { CCPairDescriptor, DocumentSet } from "@/lib/types";
import {
Label,
@ -18,14 +12,13 @@ import {
} from "@/components/admin/connectors/Field";
import { Button } from "@/components/ui/button";
import { Persona } from "@/app/admin/assistants/interfaces";
import { AdvancedOptionsToggle } from "@/components/AdvancedOptionsToggle";
import { DocumentSetSelectable } from "@/components/documentSet/DocumentSetSelectable";
import CollapsibleSection from "@/app/admin/assistants/CollapsibleSection";
import { StandardAnswerCategoryResponse } from "@/components/standardAnswers/getStandardAnswerCategoriesIfEE";
import { StandardAnswerCategoryDropdownField } from "@/components/standardAnswers/StandardAnswerCategoryDropdown";
import { RadioGroup } from "@/components/ui/radio-group";
import { RadioGroupItemField } from "@/components/ui/RadioGroupItemField";
import { AlertCircle, View } from "lucide-react";
import { AlertCircle } from "lucide-react";
import { useRouter } from "next/navigation";
import {
Tooltip,
@ -50,6 +43,7 @@ import {
import { Separator } from "@/components/ui/separator";
import { CheckFormField } from "@/components/ui/CheckField";
import { Input } from "@/components/ui/input";
export interface SlackChannelConfigFormFieldsProps {
isUpdate: boolean;
@ -178,9 +172,13 @@ export function SlackChannelConfigFormFields({
);
}, [documentSets]);
const { data: channelOptions, isLoading } = useSWR(
const {
data: channelOptions,
error,
isLoading,
} = useSWR(
`/api/manage/admin/slack-app/bots/${slack_bot_id}/channels`,
async (url: string) => {
async () => {
const channels = await fetchSlackChannels(slack_bot_id);
return channels.map((channel: any) => ({
name: channel.name,
@ -227,20 +225,34 @@ export function SlackChannelConfigFormFields({
>
Select A Slack Channel:
</label>{" "}
<Field name="channel_name">
{({ field, form }: { field: any; form: any }) => (
<SearchMultiSelectDropdown
options={channelOptions || []}
onSelect={(selected) => {
form.setFieldValue("channel_name", selected.name);
}}
initialSearchTerm={field.value}
onSearchTermChange={(term) => {
form.setFieldValue("channel_name", term);
}}
{error ? (
<div>
<div className="text-red-600 text-sm mb-4">
{error.message || "Unable to fetch Slack channels."}
{" Please enter the channel name manually."}
</div>
<TextFormField
name="channel_name"
label="Channel Name"
placeholder="Enter channel name"
/>
)}
</Field>
</div>
) : (
<Field name="channel_name">
{({ field, form }: { field: any; form: any }) => (
<SearchMultiSelectDropdown
options={channelOptions || []}
onSelect={(selected) => {
form.setFieldValue("channel_name", selected.name);
}}
initialSearchTerm={field.value}
onSearchTermChange={(term) => {
form.setFieldValue("channel_name", term);
}}
/>
)}
</Field>
)}
</>
)}
<div className="space-y-2 mt-4">