mirror of
https://github.com/StanGirard/quivr.git
synced 2024-11-24 14:08:09 +03:00
feat(apiBrain): add api brain secrets field in knowledge tab (#1669)
Issue: https://github.com/StanGirard/quivr/issues/1572 Demo: https://github.com/StanGirard/quivr/assets/63923024/192ea114-c1a2-4fb1-8226-2c77a41129a7
This commit is contained in:
parent
3da64c0b0e
commit
d7d10e3674
@ -6,11 +6,12 @@ import Button from "@/lib/components/ui/Button";
|
||||
|
||||
import {
|
||||
BrainTabTrigger,
|
||||
KnowledgeTab,
|
||||
KnowledgeOrSecretsTab,
|
||||
PeopleTab,
|
||||
SettingsTab,
|
||||
} from "./components";
|
||||
import { DeleteOrUnsubscribeConfirmationModal } from "./components/Modals/DeleteOrUnsubscribeConfirmationModal";
|
||||
import { useBrainFetcher } from "./hooks/useBrainFetcher";
|
||||
import { useBrainManagementTabs } from "./hooks/useBrainManagementTabs";
|
||||
|
||||
export const BrainManagementTabs = (): JSX.Element => {
|
||||
@ -18,6 +19,7 @@ export const BrainManagementTabs = (): JSX.Element => {
|
||||
"translation",
|
||||
"config",
|
||||
"delete_or_unsubscribe_from_brain",
|
||||
"external_api_definition",
|
||||
]);
|
||||
const {
|
||||
selectedTab,
|
||||
@ -31,6 +33,14 @@ export const BrainManagementTabs = (): JSX.Element => {
|
||||
isOwnedByCurrentUser,
|
||||
isDeleteOrUnsubscribeRequestPending,
|
||||
} = useBrainManagementTabs();
|
||||
const { brain } = useBrainFetcher({
|
||||
brainId,
|
||||
});
|
||||
|
||||
const knowledgeOrSecretsTabLabel =
|
||||
brain?.brain_type === "doc"
|
||||
? t("knowledge", { ns: "config" })
|
||||
: t("secrets", { ns: "external_api_definition" });
|
||||
|
||||
if (brainId === undefined) {
|
||||
return <div />;
|
||||
@ -61,9 +71,9 @@ export const BrainManagementTabs = (): JSX.Element => {
|
||||
onChange={setSelectedTab}
|
||||
/>
|
||||
<BrainTabTrigger
|
||||
selected={selectedTab === "knowledge"}
|
||||
label={t("knowledge", { ns: "config" })}
|
||||
value="knowledge"
|
||||
selected={selectedTab === "knowledgeOrSecrets"}
|
||||
label={knowledgeOrSecretsTabLabel}
|
||||
value="knowledgeOrSecrets"
|
||||
onChange={setSelectedTab}
|
||||
/>
|
||||
</>
|
||||
@ -77,8 +87,11 @@ export const BrainManagementTabs = (): JSX.Element => {
|
||||
<Content value="people">
|
||||
<PeopleTab brainId={brainId} hasEditRights={hasEditRights} />
|
||||
</Content>
|
||||
<Content value="knowledge">
|
||||
<KnowledgeTab brainId={brainId} hasEditRights={hasEditRights} />
|
||||
<Content value="knowledgeOrSecrets">
|
||||
<KnowledgeOrSecretsTab
|
||||
brainId={brainId}
|
||||
hasEditRights={hasEditRights}
|
||||
/>
|
||||
</Content>
|
||||
</div>
|
||||
|
||||
|
@ -2,27 +2,35 @@
|
||||
import { UUID } from "crypto";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { ApiBrainSecretsInputs } from "@/lib/components/ApiBrainSecretsInputs/ApiBrainSecretsInputs";
|
||||
import { Divider } from "@/lib/components/ui/Divider";
|
||||
import { KnowledgeToFeedProvider } from "@/lib/context";
|
||||
|
||||
import { AddKnowledge } from "./components/AddKnowledge/AddKnowledge";
|
||||
import { AddedKnowledge } from "./components/AddedKnowledge/AddedKnowledge";
|
||||
import { useBrainFetcher } from "../../hooks/useBrainFetcher";
|
||||
import { NoAccess } from "../NoAccess";
|
||||
|
||||
type KnowledgeTabProps = {
|
||||
type KnowledgeOrSecretsTabProps = {
|
||||
brainId: UUID;
|
||||
hasEditRights: boolean;
|
||||
};
|
||||
export const KnowledgeTab = ({
|
||||
export const KnowledgeOrSecretsTab = ({
|
||||
brainId,
|
||||
hasEditRights,
|
||||
}: KnowledgeTabProps): JSX.Element => {
|
||||
}: KnowledgeOrSecretsTabProps): JSX.Element => {
|
||||
const { t } = useTranslation(["translation", "explore", "config"]);
|
||||
|
||||
const { brain } = useBrainFetcher({
|
||||
brainId,
|
||||
});
|
||||
if (!hasEditRights) {
|
||||
return <NoAccess />;
|
||||
}
|
||||
|
||||
if (brain?.brain_type === "api") {
|
||||
return <ApiBrainSecretsInputs brainId={brainId} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<KnowledgeToFeedProvider>
|
||||
<main>
|
@ -1,4 +1,4 @@
|
||||
export * from "./BrainTabTrigger";
|
||||
export * from "./KnowledgeTab";
|
||||
export * from "./KnowledgeOrSecretsTab";
|
||||
export * from "./PeopleTab";
|
||||
export * from "./SettingsTab";
|
||||
|
@ -1,3 +1,7 @@
|
||||
export const brainManagementTabs = ["settings", "people", "knowledge"] as const;
|
||||
export const brainManagementTabs = [
|
||||
"settings",
|
||||
"people",
|
||||
"knowledgeOrSecrets",
|
||||
] as const;
|
||||
|
||||
export type BrainManagementTab = (typeof brainManagementTabs)[number];
|
||||
|
@ -19,7 +19,8 @@ export const ApiBrainSecretsInputs = ({
|
||||
const { brain } = useBrainFetcher({
|
||||
brainId,
|
||||
});
|
||||
const { register, updateSecrets, isPending } = useApiBrainSecretsInputs({
|
||||
const { register, updateSecrets, isPending, isUpdateButtonDisabled } =
|
||||
useApiBrainSecretsInputs({
|
||||
brainId,
|
||||
onUpdate,
|
||||
});
|
||||
@ -61,7 +62,9 @@ export const ApiBrainSecretsInputs = ({
|
||||
))}
|
||||
</div>
|
||||
<div className="mt-4 flex justify-end">
|
||||
<Button isLoading={isPending}>{t("update_secrets_button")}</Button>
|
||||
<Button disabled={isUpdateButtonDisabled} isLoading={isPending}>
|
||||
{t("update_secrets_button")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -1,11 +1,14 @@
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { UUID } from "crypto";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { useBrainApi } from "@/lib/api/brain/useBrainApi";
|
||||
import { useToast } from "@/lib/hooks";
|
||||
|
||||
import { getNonEmptyValuesFromDict } from "../utils/getNonEmptyValuesFromDict";
|
||||
|
||||
type UseApiBrainSecretsInputsProps = {
|
||||
brainId: UUID;
|
||||
onUpdate?: () => void;
|
||||
@ -17,23 +20,21 @@ export const useApiBrainSecretsInputs = ({
|
||||
onUpdate,
|
||||
}: UseApiBrainSecretsInputsProps) => {
|
||||
const { t } = useTranslation(["brain"]);
|
||||
const { register, getValues } = useForm<Record<string, string>>();
|
||||
const { register, watch } = useForm<Record<string, string>>();
|
||||
const { updateBrainSecrets } = useBrainApi();
|
||||
const { publish } = useToast();
|
||||
|
||||
const updateSecretsHandler = async () => {
|
||||
const values = getValues();
|
||||
const nonEmptyValues = Object.entries(values).reduce(
|
||||
(acc, [key, value]) => {
|
||||
if (value !== "") {
|
||||
acc[key] = value;
|
||||
}
|
||||
const values = watch();
|
||||
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, string>
|
||||
);
|
||||
await updateBrainSecrets(brainId, nonEmptyValues);
|
||||
const [isUpdateButtonDisabled, setIsUpdateButtonDisabled] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const nonEmptyValues = getNonEmptyValuesFromDict(values);
|
||||
setIsUpdateButtonDisabled(Object.keys(nonEmptyValues).length === 0);
|
||||
}, [values]);
|
||||
|
||||
const updateSecretsHandler = async () => {
|
||||
await updateBrainSecrets(brainId, getNonEmptyValuesFromDict(values));
|
||||
onUpdate?.();
|
||||
};
|
||||
|
||||
@ -51,5 +52,6 @@ export const useApiBrainSecretsInputs = ({
|
||||
register,
|
||||
updateSecrets,
|
||||
isPending,
|
||||
isUpdateButtonDisabled,
|
||||
};
|
||||
};
|
||||
|
@ -0,0 +1,13 @@
|
||||
export const getNonEmptyValuesFromDict = (
|
||||
values: Record<string, string>
|
||||
): Record<string, string> => {
|
||||
const nonEmptyValues = Object.entries(values).reduce((acc, [key, value]) => {
|
||||
if (value !== "") {
|
||||
acc[key] = value;
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {} as Record<string, string>);
|
||||
|
||||
return nonEmptyValues;
|
||||
};
|
Loading…
Reference in New Issue
Block a user