mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-09-20 21:33:56 +02:00
Migrate standard answers implementations to ee/ (#2378)
* Migrate standard answers implementations to ee/ * renaming * Clean up slackbot non-ee standard answers import * Move backend api/manage/standard_answer route to ee * Move standard answers web UI to ee * Hide standard answer controls in bot edit page * Kwargs for fetch_versioned_implementation * Add docstring explaining return types for handle_standard_answers * Consolidate blocks into ee/handle_standard_answers --------- Co-authored-by: Hyeong Joon Suh <hyeongjoonsuh@Hyeongs-MacBook-Pro.local> Co-authored-by: danswer-trial <danswer-trial@danswer-trials-MacBook-Pro.local>
This commit is contained in:
@@ -3,11 +3,7 @@
|
||||
import { ArrayHelpers, FieldArray, Form, Formik } from "formik";
|
||||
import * as Yup from "yup";
|
||||
import { usePopup } from "@/components/admin/connectors/Popup";
|
||||
import {
|
||||
DocumentSet,
|
||||
SlackBotConfig,
|
||||
StandardAnswerCategory,
|
||||
} from "@/lib/types";
|
||||
import { DocumentSet, SlackBotConfig } from "@/lib/types";
|
||||
import {
|
||||
BooleanFormField,
|
||||
Label,
|
||||
@@ -28,16 +24,18 @@ import MultiSelectDropdown from "@/components/MultiSelectDropdown";
|
||||
import { AdvancedOptionsToggle } from "@/components/AdvancedOptionsToggle";
|
||||
import { DocumentSetSelectable } from "@/components/documentSet/DocumentSetSelectable";
|
||||
import CollapsibleSection from "../assistants/CollapsibleSection";
|
||||
import { StandardAnswerCategoryResponse } from "@/components/standardAnswers/getStandardAnswerCategoriesIfEE";
|
||||
import { StandardAnswerCategoryDropdownField } from "@/components/standardAnswers/StandardAnswerCategoryDropdown";
|
||||
|
||||
export const SlackBotCreationForm = ({
|
||||
documentSets,
|
||||
personas,
|
||||
standardAnswerCategories,
|
||||
standardAnswerCategoryResponse,
|
||||
existingSlackBotConfig,
|
||||
}: {
|
||||
documentSets: DocumentSet[];
|
||||
personas: Persona[];
|
||||
standardAnswerCategories: StandardAnswerCategory[];
|
||||
standardAnswerCategoryResponse: StandardAnswerCategoryResponse;
|
||||
existingSlackBotConfig?: SlackBotConfig;
|
||||
}) => {
|
||||
const isUpdate = existingSlackBotConfig !== undefined;
|
||||
@@ -356,38 +354,15 @@ export const SlackBotCreationForm = ({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Label>Standard Answer Categories</Label>
|
||||
<div className="w-4/12">
|
||||
<MultiSelectDropdown
|
||||
name="standard_answer_categories"
|
||||
label=""
|
||||
onChange={(selected_options) => {
|
||||
const selected_categories = selected_options.map(
|
||||
(option) => {
|
||||
return {
|
||||
id: Number(option.value),
|
||||
name: option.label,
|
||||
};
|
||||
}
|
||||
);
|
||||
setFieldValue(
|
||||
"standard_answer_categories",
|
||||
selected_categories
|
||||
);
|
||||
}}
|
||||
creatable={false}
|
||||
options={standardAnswerCategories.map((category) => ({
|
||||
label: category.name,
|
||||
value: category.id.toString(),
|
||||
}))}
|
||||
initialSelectedOptions={values.standard_answer_categories.map(
|
||||
(category) => ({
|
||||
label: category.name,
|
||||
value: category.id.toString(),
|
||||
})
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<StandardAnswerCategoryDropdownField
|
||||
standardAnswerCategoryResponse={
|
||||
standardAnswerCategoryResponse
|
||||
}
|
||||
categories={values.standard_answer_categories}
|
||||
setCategories={(categories) =>
|
||||
setFieldValue("standard_answer_categories", categories)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
@@ -3,11 +3,7 @@ import { CPUIcon } from "@/components/icons/icons";
|
||||
import { SlackBotCreationForm } from "../SlackBotConfigCreationForm";
|
||||
import { fetchSS } from "@/lib/utilsSS";
|
||||
import { ErrorCallout } from "@/components/ErrorCallout";
|
||||
import {
|
||||
DocumentSet,
|
||||
SlackBotConfig,
|
||||
StandardAnswerCategory,
|
||||
} from "@/lib/types";
|
||||
import { DocumentSet, SlackBotConfig } from "@/lib/types";
|
||||
import { Text } from "@tremor/react";
|
||||
import { BackButton } from "@/components/BackButton";
|
||||
import { InstantSSRAutoRefresh } from "@/components/SSRAutoRefresh";
|
||||
@@ -15,27 +11,28 @@ import {
|
||||
FetchAssistantsResponse,
|
||||
fetchAssistantsSS,
|
||||
} from "@/lib/assistants/fetchAssistantsSS";
|
||||
import { getStandardAnswerCategoriesIfEE } from "@/components/standardAnswers/getStandardAnswerCategoriesIfEE";
|
||||
|
||||
async function Page({ params }: { params: { id: string } }) {
|
||||
const tasks = [
|
||||
fetchSS("/manage/admin/slack-bot/config"),
|
||||
fetchSS("/manage/document-set"),
|
||||
fetchAssistantsSS(),
|
||||
fetchSS("/manage/admin/standard-answer/category"),
|
||||
];
|
||||
|
||||
const [
|
||||
slackBotsResponse,
|
||||
documentSetsResponse,
|
||||
[assistants, assistantsFetchError],
|
||||
standardAnswerCategoriesResponse,
|
||||
] = (await Promise.all(tasks)) as [
|
||||
Response,
|
||||
Response,
|
||||
FetchAssistantsResponse,
|
||||
Response,
|
||||
];
|
||||
|
||||
const eeStandardAnswerCategoryResponse =
|
||||
await getStandardAnswerCategoriesIfEE();
|
||||
|
||||
if (!slackBotsResponse.ok) {
|
||||
return (
|
||||
<ErrorCallout
|
||||
@@ -77,18 +74,6 @@ async function Page({ params }: { params: { id: string } }) {
|
||||
);
|
||||
}
|
||||
|
||||
if (!standardAnswerCategoriesResponse.ok) {
|
||||
return (
|
||||
<ErrorCallout
|
||||
errorTitle="Something went wrong :("
|
||||
errorMsg={`Failed to fetch standard answer categories - ${await standardAnswerCategoriesResponse.text()}`}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const standardAnswerCategories =
|
||||
(await standardAnswerCategoriesResponse.json()) as StandardAnswerCategory[];
|
||||
|
||||
return (
|
||||
<div className="container mx-auto">
|
||||
<InstantSSRAutoRefresh />
|
||||
@@ -107,7 +92,7 @@ async function Page({ params }: { params: { id: string } }) {
|
||||
<SlackBotCreationForm
|
||||
documentSets={documentSets}
|
||||
personas={assistants}
|
||||
standardAnswerCategories={standardAnswerCategories}
|
||||
standardAnswerCategoryResponse={eeStandardAnswerCategoryResponse}
|
||||
existingSlackBotConfig={slackBotConfig}
|
||||
/>
|
||||
</div>
|
||||
|
@@ -10,13 +10,10 @@ import {
|
||||
FetchAssistantsResponse,
|
||||
fetchAssistantsSS,
|
||||
} from "@/lib/assistants/fetchAssistantsSS";
|
||||
import { getStandardAnswerCategoriesIfEE } from "@/components/standardAnswers/getStandardAnswerCategoriesIfEE";
|
||||
|
||||
async function Page() {
|
||||
const tasks = [
|
||||
fetchSS("/manage/document-set"),
|
||||
fetchAssistantsSS(),
|
||||
fetchSS("/manage/admin/standard-answer/category"),
|
||||
];
|
||||
const tasks = [fetchSS("/manage/document-set"), fetchAssistantsSS()];
|
||||
const [
|
||||
documentSetsResponse,
|
||||
[assistants, assistantsFetchError],
|
||||
@@ -27,6 +24,9 @@ async function Page() {
|
||||
Response,
|
||||
];
|
||||
|
||||
const eeStandardAnswerCategoryResponse =
|
||||
await getStandardAnswerCategoriesIfEE();
|
||||
|
||||
if (!documentSetsResponse.ok) {
|
||||
return (
|
||||
<ErrorCallout
|
||||
@@ -46,18 +46,6 @@ async function Page() {
|
||||
);
|
||||
}
|
||||
|
||||
if (!standardAnswerCategoriesResponse.ok) {
|
||||
return (
|
||||
<ErrorCallout
|
||||
errorTitle="Something went wrong :("
|
||||
errorMsg={`Failed to fetch standard answer categories - ${await standardAnswerCategoriesResponse.text()}`}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const standardAnswerCategories =
|
||||
(await standardAnswerCategoriesResponse.json()) as StandardAnswerCategory[];
|
||||
|
||||
return (
|
||||
<div className="container mx-auto">
|
||||
<BackButton />
|
||||
@@ -69,7 +57,7 @@ async function Page() {
|
||||
<SlackBotCreationForm
|
||||
documentSets={documentSets}
|
||||
personas={assistants}
|
||||
standardAnswerCategories={standardAnswerCategories}
|
||||
standardAnswerCategoryResponse={eeStandardAnswerCategoryResponse}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { AdminPageTitle } from "@/components/admin/Title";
|
||||
import { StandardAnswerCreationForm } from "@/app/admin/standard-answer/StandardAnswerCreationForm";
|
||||
import { StandardAnswerCreationForm } from "@/app/ee/admin/standard-answer/StandardAnswerCreationForm";
|
||||
import { fetchSS } from "@/lib/utilsSS";
|
||||
import { ErrorCallout } from "@/components/ErrorCallout";
|
||||
import { BackButton } from "@/components/BackButton";
|
@@ -1,5 +1,5 @@
|
||||
import { AdminPageTitle } from "@/components/admin/Title";
|
||||
import { StandardAnswerCreationForm } from "@/app/admin/standard-answer/StandardAnswerCreationForm";
|
||||
import { StandardAnswerCreationForm } from "@/app/ee/admin/standard-answer/StandardAnswerCreationForm";
|
||||
import { fetchSS } from "@/lib/utilsSS";
|
||||
import { ErrorCallout } from "@/components/ErrorCallout";
|
||||
import { BackButton } from "@/components/BackButton";
|
@@ -145,15 +145,6 @@ export function ClientLayout({
|
||||
),
|
||||
link: "/admin/tools",
|
||||
},
|
||||
{
|
||||
name: (
|
||||
<div className="flex">
|
||||
<ClipboardIcon size={18} />
|
||||
<div className="ml-1">Standard Answers</div>
|
||||
</div>
|
||||
),
|
||||
link: "/admin/standard-answer",
|
||||
},
|
||||
{
|
||||
name: (
|
||||
<div className="flex">
|
||||
@@ -165,6 +156,19 @@ export function ClientLayout({
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(enableEnterprise
|
||||
? [
|
||||
{
|
||||
name: (
|
||||
<div className="flex">
|
||||
<ClipboardIcon size={18} />
|
||||
<div className="ml-1">Standard Answers</div>
|
||||
</div>
|
||||
),
|
||||
link: "/admin/standard-answer",
|
||||
},
|
||||
]
|
||||
: []),
|
||||
],
|
||||
},
|
||||
...(isCurator
|
||||
|
@@ -0,0 +1,71 @@
|
||||
import { FC } from "react";
|
||||
import { StandardAnswerCategoryResponse } from "./getStandardAnswerCategoriesIfEE";
|
||||
import { Label } from "../admin/connectors/Field";
|
||||
import MultiSelectDropdown from "../MultiSelectDropdown";
|
||||
import { StandardAnswerCategory } from "@/lib/types";
|
||||
import { ErrorCallout } from "../ErrorCallout";
|
||||
import { LoadingAnimation } from "../Loading";
|
||||
import { Divider } from "@tremor/react";
|
||||
|
||||
interface StandardAnswerCategoryDropdownFieldProps {
|
||||
standardAnswerCategoryResponse: StandardAnswerCategoryResponse;
|
||||
categories: StandardAnswerCategory[];
|
||||
setCategories: (categories: StandardAnswerCategory[]) => void;
|
||||
}
|
||||
|
||||
export const StandardAnswerCategoryDropdownField: FC<
|
||||
StandardAnswerCategoryDropdownFieldProps
|
||||
> = ({ standardAnswerCategoryResponse, categories, setCategories }) => {
|
||||
if (!standardAnswerCategoryResponse.paidEnterpriseFeaturesEnabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (standardAnswerCategoryResponse.error != null) {
|
||||
return (
|
||||
<ErrorCallout
|
||||
errorTitle="Something went wrong :("
|
||||
errorMsg={`Failed to fetch standard answer categories - ${standardAnswerCategoryResponse.error.message}`}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (standardAnswerCategoryResponse.categories == null) {
|
||||
return <LoadingAnimation />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<Label>Standard Answer Categories</Label>
|
||||
<div className="w-4/12">
|
||||
<MultiSelectDropdown
|
||||
name="standard_answer_categories"
|
||||
label=""
|
||||
onChange={(selectedOptions) => {
|
||||
const selectedCategories = selectedOptions.map((option) => {
|
||||
return {
|
||||
id: Number(option.value),
|
||||
name: option.label,
|
||||
};
|
||||
});
|
||||
setCategories(selectedCategories);
|
||||
}}
|
||||
creatable={false}
|
||||
options={standardAnswerCategoryResponse.categories.map(
|
||||
(category) => ({
|
||||
label: category.name,
|
||||
value: category.id.toString(),
|
||||
})
|
||||
)}
|
||||
initialSelectedOptions={categories.map((category) => ({
|
||||
label: category.name,
|
||||
value: category.id.toString(),
|
||||
}))}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Divider />
|
||||
</>
|
||||
);
|
||||
};
|
@@ -0,0 +1,47 @@
|
||||
import { SERVER_SIDE_ONLY__PAID_ENTERPRISE_FEATURES_ENABLED } from "@/lib/constants";
|
||||
import { StandardAnswerCategory } from "@/lib/types";
|
||||
import { fetchSS } from "@/lib/utilsSS";
|
||||
|
||||
export type StandardAnswerCategoryResponse =
|
||||
| EEStandardAnswerCategoryResponse
|
||||
| NoEEAvailable;
|
||||
|
||||
interface NoEEAvailable {
|
||||
paidEnterpriseFeaturesEnabled: false;
|
||||
}
|
||||
|
||||
interface EEStandardAnswerCategoryResponse {
|
||||
paidEnterpriseFeaturesEnabled: true;
|
||||
error?: {
|
||||
message: string;
|
||||
};
|
||||
categories?: StandardAnswerCategory[];
|
||||
}
|
||||
|
||||
export async function getStandardAnswerCategoriesIfEE(): Promise<StandardAnswerCategoryResponse> {
|
||||
if (!SERVER_SIDE_ONLY__PAID_ENTERPRISE_FEATURES_ENABLED) {
|
||||
return {
|
||||
paidEnterpriseFeaturesEnabled: false,
|
||||
};
|
||||
}
|
||||
|
||||
const standardAnswerCategoriesResponse = await fetchSS(
|
||||
"/manage/admin/standard-answer/category"
|
||||
);
|
||||
if (!standardAnswerCategoriesResponse.ok) {
|
||||
return {
|
||||
paidEnterpriseFeaturesEnabled: true,
|
||||
error: {
|
||||
message: await standardAnswerCategoriesResponse.text(),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const categories =
|
||||
(await standardAnswerCategoriesResponse.json()) as StandardAnswerCategory[];
|
||||
|
||||
return {
|
||||
paidEnterpriseFeaturesEnabled: true,
|
||||
categories,
|
||||
};
|
||||
}
|
@@ -9,6 +9,7 @@ const eePaths = [
|
||||
"/admin/performance/query-history",
|
||||
"/admin/whitelabeling",
|
||||
"/admin/performance/custom-analytics",
|
||||
"/admin/standard-answer",
|
||||
];
|
||||
|
||||
const eePathsForMatcher = eePaths.map((path) => `${path}/:path*`);
|
||||
|
Reference in New Issue
Block a user