mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-06-05 12:39:33 +02:00
k (#4102)
This commit is contained in:
parent
f0c13b6558
commit
1263e21eb5
@ -1,5 +1,3 @@
|
|||||||
from typing import Any
|
|
||||||
|
|
||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
from fastapi import Depends
|
from fastapi import Depends
|
||||||
from fastapi import HTTPException
|
from fastapi import HTTPException
|
||||||
@ -345,6 +343,9 @@ def list_bot_configs(
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
MAX_CHANNELS = 200
|
||||||
|
|
||||||
|
|
||||||
@router.get(
|
@router.get(
|
||||||
"/admin/slack-app/bots/{bot_id}/channels",
|
"/admin/slack-app/bots/{bot_id}/channels",
|
||||||
)
|
)
|
||||||
@ -353,38 +354,40 @@ def get_all_channels_from_slack_api(
|
|||||||
db_session: Session = Depends(get_session),
|
db_session: Session = Depends(get_session),
|
||||||
_: User | None = Depends(current_admin_user),
|
_: User | None = Depends(current_admin_user),
|
||||||
) -> list[SlackChannel]:
|
) -> 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)
|
tokens = fetch_slack_bot_tokens(db_session, bot_id)
|
||||||
if not tokens or "bot_token" not in tokens:
|
if not tokens or "bot_token" not in tokens:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=404, detail="Bot token not found for the given bot ID"
|
status_code=404, detail="Bot token not found for the given bot ID"
|
||||||
)
|
)
|
||||||
|
|
||||||
bot_token = tokens["bot_token"]
|
client = WebClient(token=tokens["bot_token"])
|
||||||
client = WebClient(token=bot_token)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
channels = []
|
response = client.conversations_list(
|
||||||
cursor = None
|
types="public_channel,private_channel",
|
||||||
while True:
|
exclude_archived=True,
|
||||||
response = client.conversations_list(
|
limit=MAX_CHANNELS,
|
||||||
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_metadata: dict[str, Any] = response.get("response_metadata", {})
|
channels = [
|
||||||
if isinstance(response_metadata, dict):
|
SlackChannel(id=channel["id"], name=channel["name"])
|
||||||
cursor = response_metadata.get("next_cursor")
|
for channel in response["channels"]
|
||||||
if not cursor:
|
]
|
||||||
break
|
|
||||||
else:
|
if len(channels) == MAX_CHANNELS:
|
||||||
break
|
raise HTTPException(
|
||||||
|
status_code=400,
|
||||||
|
detail=f"Workspace has {MAX_CHANNELS} or more channels.",
|
||||||
|
)
|
||||||
|
|
||||||
return channels
|
return channels
|
||||||
|
|
||||||
except SlackApiError as e:
|
except SlackApiError as e:
|
||||||
raise HTTPException(
|
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)}",
|
||||||
)
|
)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import React, { useMemo, useState, useEffect } from "react";
|
import React, { useMemo } from "react";
|
||||||
import { Formik, Form, Field } from "formik";
|
import { Formik, Form } from "formik";
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
import { usePopup } from "@/components/admin/connectors/Popup";
|
import { usePopup } from "@/components/admin/connectors/Popup";
|
||||||
import {
|
import {
|
||||||
@ -13,17 +13,13 @@ import {
|
|||||||
createSlackChannelConfig,
|
createSlackChannelConfig,
|
||||||
isPersonaASlackBotPersona,
|
isPersonaASlackBotPersona,
|
||||||
updateSlackChannelConfig,
|
updateSlackChannelConfig,
|
||||||
fetchSlackChannels,
|
|
||||||
} from "../lib";
|
} from "../lib";
|
||||||
import CardSection from "@/components/admin/CardSection";
|
import CardSection from "@/components/admin/CardSection";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||||
import { StandardAnswerCategoryResponse } from "@/components/standardAnswers/getStandardAnswerCategoriesIfEE";
|
import { StandardAnswerCategoryResponse } from "@/components/standardAnswers/getStandardAnswerCategoriesIfEE";
|
||||||
import { SEARCH_TOOL_ID, SEARCH_TOOL_NAME } from "@/app/chat/tools/constants";
|
import { SEARCH_TOOL_ID } from "@/app/chat/tools/constants";
|
||||||
import {
|
import { SlackChannelConfigFormFields } from "./SlackChannelConfigFormFields";
|
||||||
SlackChannelConfigFormFields,
|
|
||||||
SlackChannelConfigFormFieldsProps,
|
|
||||||
} from "./SlackChannelConfigFormFields";
|
|
||||||
|
|
||||||
export const SlackChannelConfigCreationForm = ({
|
export const SlackChannelConfigCreationForm = ({
|
||||||
slack_bot_id,
|
slack_bot_id,
|
||||||
|
@ -1,13 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import React, { useState, useEffect, useMemo } from "react";
|
import React, { useState, useEffect, useMemo } from "react";
|
||||||
import {
|
import { FieldArray, useFormikContext, ErrorMessage, Field } from "formik";
|
||||||
FieldArray,
|
|
||||||
Form,
|
|
||||||
useFormikContext,
|
|
||||||
ErrorMessage,
|
|
||||||
Field,
|
|
||||||
} from "formik";
|
|
||||||
import { CCPairDescriptor, DocumentSet } from "@/lib/types";
|
import { CCPairDescriptor, DocumentSet } from "@/lib/types";
|
||||||
import {
|
import {
|
||||||
Label,
|
Label,
|
||||||
@ -18,14 +12,13 @@ import {
|
|||||||
} from "@/components/admin/connectors/Field";
|
} from "@/components/admin/connectors/Field";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||||
import { AdvancedOptionsToggle } from "@/components/AdvancedOptionsToggle";
|
|
||||||
import { DocumentSetSelectable } from "@/components/documentSet/DocumentSetSelectable";
|
import { DocumentSetSelectable } from "@/components/documentSet/DocumentSetSelectable";
|
||||||
import CollapsibleSection from "@/app/admin/assistants/CollapsibleSection";
|
import CollapsibleSection from "@/app/admin/assistants/CollapsibleSection";
|
||||||
import { StandardAnswerCategoryResponse } from "@/components/standardAnswers/getStandardAnswerCategoriesIfEE";
|
import { StandardAnswerCategoryResponse } from "@/components/standardAnswers/getStandardAnswerCategoriesIfEE";
|
||||||
import { StandardAnswerCategoryDropdownField } from "@/components/standardAnswers/StandardAnswerCategoryDropdown";
|
import { StandardAnswerCategoryDropdownField } from "@/components/standardAnswers/StandardAnswerCategoryDropdown";
|
||||||
import { RadioGroup } from "@/components/ui/radio-group";
|
import { RadioGroup } from "@/components/ui/radio-group";
|
||||||
import { RadioGroupItemField } from "@/components/ui/RadioGroupItemField";
|
import { RadioGroupItemField } from "@/components/ui/RadioGroupItemField";
|
||||||
import { AlertCircle, View } from "lucide-react";
|
import { AlertCircle } from "lucide-react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import {
|
import {
|
||||||
Tooltip,
|
Tooltip,
|
||||||
@ -50,6 +43,7 @@ import {
|
|||||||
import { Separator } from "@/components/ui/separator";
|
import { Separator } from "@/components/ui/separator";
|
||||||
|
|
||||||
import { CheckFormField } from "@/components/ui/CheckField";
|
import { CheckFormField } from "@/components/ui/CheckField";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
|
||||||
export interface SlackChannelConfigFormFieldsProps {
|
export interface SlackChannelConfigFormFieldsProps {
|
||||||
isUpdate: boolean;
|
isUpdate: boolean;
|
||||||
@ -178,9 +172,13 @@ export function SlackChannelConfigFormFields({
|
|||||||
);
|
);
|
||||||
}, [documentSets]);
|
}, [documentSets]);
|
||||||
|
|
||||||
const { data: channelOptions, isLoading } = useSWR(
|
const {
|
||||||
|
data: channelOptions,
|
||||||
|
error,
|
||||||
|
isLoading,
|
||||||
|
} = useSWR(
|
||||||
`/api/manage/admin/slack-app/bots/${slack_bot_id}/channels`,
|
`/api/manage/admin/slack-app/bots/${slack_bot_id}/channels`,
|
||||||
async (url: string) => {
|
async () => {
|
||||||
const channels = await fetchSlackChannels(slack_bot_id);
|
const channels = await fetchSlackChannels(slack_bot_id);
|
||||||
return channels.map((channel: any) => ({
|
return channels.map((channel: any) => ({
|
||||||
name: channel.name,
|
name: channel.name,
|
||||||
@ -227,20 +225,34 @@ export function SlackChannelConfigFormFields({
|
|||||||
>
|
>
|
||||||
Select A Slack Channel:
|
Select A Slack Channel:
|
||||||
</label>{" "}
|
</label>{" "}
|
||||||
<Field name="channel_name">
|
{error ? (
|
||||||
{({ field, form }: { field: any; form: any }) => (
|
<div>
|
||||||
<SearchMultiSelectDropdown
|
<div className="text-red-600 text-sm mb-4">
|
||||||
options={channelOptions || []}
|
{error.message || "Unable to fetch Slack channels."}
|
||||||
onSelect={(selected) => {
|
{" Please enter the channel name manually."}
|
||||||
form.setFieldValue("channel_name", selected.name);
|
</div>
|
||||||
}}
|
<TextFormField
|
||||||
initialSearchTerm={field.value}
|
name="channel_name"
|
||||||
onSearchTermChange={(term) => {
|
label="Channel Name"
|
||||||
form.setFieldValue("channel_name", term);
|
placeholder="Enter channel name"
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
)}
|
</div>
|
||||||
</Field>
|
) : (
|
||||||
|
<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">
|
<div className="space-y-2 mt-4">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user