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:
hj-danswer
2024-09-13 18:57:03 -07:00
committed by GitHub
parent a63cb9da43
commit 974f85da66
24 changed files with 514 additions and 371 deletions

View File

@@ -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>
)}

View File

@@ -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>

View File

@@ -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>
);

View File

@@ -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";

View File

@@ -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";

View File

@@ -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

View File

@@ -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 />
</>
);
};

View File

@@ -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,
};
}

View File

@@ -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*`);