From b3fb8fc3bc2d71a72e73b4f0aa30c84255a77fc0 Mon Sep 17 00:00:00 2001 From: Mamadou DICKO <63923024+mamadoudicko@users.noreply.github.com> Date: Thu, 3 Aug 2023 17:00:05 +0200 Subject: [PATCH] feat: add public prompts picker (#841) * fix: update prompt_id logic in payload * feat: add getPublicPrompts to sdk * feat: add public prompt picker --- .../components/SettingsTab/SettingsTab.tsx | 5 +- .../SettingsTab/components/PublicPrompts.tsx | 57 +++++++++++++++++++ .../SettingsTab/hooks/useSettingsTab.ts | 22 ++++++- .../api/prompt/__tests__/usePromptApi.test.ts | 19 ++++++- frontend/lib/api/prompt/prompt.ts | 6 ++ frontend/lib/api/prompt/usePromptApi.ts | 2 + .../AddBrainModal/AddBrainModal.tsx | 3 + .../AddBrainModal/hooks/useAddBrainModal.ts | 16 ++++++ frontend/package.json | 1 + frontend/yarn.lock | 31 ++++++++++ 10 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/SettingsTab/components/PublicPrompts.tsx diff --git a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/SettingsTab/SettingsTab.tsx b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/SettingsTab/SettingsTab.tsx index 93c221495..4415b0d6b 100644 --- a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/SettingsTab/SettingsTab.tsx +++ b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/SettingsTab/SettingsTab.tsx @@ -10,6 +10,7 @@ import { TextArea } from "@/lib/components/ui/TextArea"; import { models, paidModels } from "@/lib/context/BrainConfigProvider/types"; import { defineMaxTokens } from "@/lib/helpers/defineMexTokens"; +import { PublicPrompts } from "./components/PublicPrompts"; import { useSettingsTab } from "./hooks/useSettingsTab"; type SettingsTabProps = { @@ -30,6 +31,7 @@ export const SettingsTab = ({ brainId }: SettingsTabProps): JSX.Element => { isDefaultBrain, formRef, promptId, + pickPublicPrompt, removeBrainPrompt, } = useSettingsTab({ brainId }); @@ -128,7 +130,8 @@ export const SettingsTab = ({ brainId }: SettingsTabProps): JSX.Element => { {...register("maxTokens")} /> - + + void; +}; + +export const PublicPrompts = ({ + onSelect, +}: PublicPromptsProps): JSX.Element => { + const [publicPrompts, setPublicPrompts] = useState([]); + + const { getPublicPrompts } = usePromptApi(); + + const fetchPublicPrompts = async () => { + setPublicPrompts(await getPublicPrompts()); + }; + + const handleChange = (event: ChangeEvent) => { + const selectedPrompt = publicPrompts.find( + (prompt) => prompt.id === event.target.value + ); + if (selectedPrompt) { + onSelect({ + title: selectedPrompt.title, + content: selectedPrompt.content, + }); + } + }; + + useEffect(() => { + void fetchPublicPrompts(); + }, []); + + return ( + + + Pick in public prompts + + + + + + ); +}; diff --git a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/SettingsTab/hooks/useSettingsTab.ts b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/SettingsTab/hooks/useSettingsTab.ts index 72afde4fe..c5db8d03b 100644 --- a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/SettingsTab/hooks/useSettingsTab.ts +++ b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/SettingsTab/hooks/useSettingsTab.ts @@ -257,13 +257,15 @@ export const useSettingsTab = ({ brainId }: UseSettingsTabProps) => { promptHandler(), ]); } - - return; } else { await updateBrain(brainId, { ...otherConfigs, max_tokens, openai_api_key, + prompt_id: + otherConfigs["prompt_id"] !== "" + ? otherConfigs["prompt_id"] + : undefined, }); } @@ -295,6 +297,21 @@ export const useSettingsTab = ({ brainId }: UseSettingsTabProps) => { } }; + const pickPublicPrompt = ({ + title, + content, + }: { + title: string; + content: string; + }): void => { + setValue("prompt.title", title, { + shouldDirty: true, + }); + setValue("prompt.content", content, { + shouldDirty: true, + }); + }; + return { handleSubmit, register, @@ -309,5 +326,6 @@ export const useSettingsTab = ({ brainId }: UseSettingsTabProps) => { formRef, promptId, removeBrainPrompt, + pickPublicPrompt, }; }; diff --git a/frontend/lib/api/prompt/__tests__/usePromptApi.test.ts b/frontend/lib/api/prompt/__tests__/usePromptApi.test.ts index 4d68dcb32..26972a723 100644 --- a/frontend/lib/api/prompt/__tests__/usePromptApi.test.ts +++ b/frontend/lib/api/prompt/__tests__/usePromptApi.test.ts @@ -1,5 +1,5 @@ import { renderHook } from "@testing-library/react"; -import { describe, expect, it, vi } from "vitest"; +import { afterEach, describe, expect, it, vi } from "vitest"; import { CreatePromptProps, PromptUpdatableProperties } from "../prompt"; import { usePromptApi } from "../usePromptApi"; @@ -19,6 +19,10 @@ vi.mock("@/lib/hooks", () => ({ })); describe("usePromptApi", () => { + afterEach(() => { + vi.resetAllMocks(); + }); + it("should call createPrompt with the correct parameters", async () => { const prompt: CreatePromptProps = { title: "Test Prompt", @@ -67,4 +71,17 @@ describe("usePromptApi", () => { expect(axiosPutMock).toHaveBeenCalledTimes(1); expect(axiosPutMock).toHaveBeenCalledWith(`/prompts/${promptId}`, prompt); }); + it("should call getPublicPrompts with the correct parameters", async () => { + axiosGetMock.mockReturnValue({ data: [] }); + const { + result: { + current: { getPublicPrompts }, + }, + } = renderHook(() => usePromptApi()); + + await getPublicPrompts(); + + expect(axiosGetMock).toHaveBeenCalledTimes(1); + expect(axiosGetMock).toHaveBeenCalledWith("/prompts"); + }); }); diff --git a/frontend/lib/api/prompt/prompt.ts b/frontend/lib/api/prompt/prompt.ts index 05a9531b7..bf1b82a51 100644 --- a/frontend/lib/api/prompt/prompt.ts +++ b/frontend/lib/api/prompt/prompt.ts @@ -32,3 +32,9 @@ export const updatePrompt = async ( ): Promise => { return (await axiosInstance.put(`/prompts/${promptId}`, prompt)).data; }; + +export const getPublicPrompts = async ( + axiosInstance: AxiosInstance +): Promise => { + return (await axiosInstance.get("/prompts")).data; +}; diff --git a/frontend/lib/api/prompt/usePromptApi.ts b/frontend/lib/api/prompt/usePromptApi.ts index 26341238e..079146133 100644 --- a/frontend/lib/api/prompt/usePromptApi.ts +++ b/frontend/lib/api/prompt/usePromptApi.ts @@ -4,6 +4,7 @@ import { createPrompt, CreatePromptProps, getPrompt, + getPublicPrompts, PromptUpdatableProperties, updatePrompt, } from "./prompt"; @@ -18,5 +19,6 @@ export const usePromptApi = () => { getPrompt: async (promptId: string) => getPrompt(promptId, axiosInstance), updatePrompt: async (promptId: string, prompt: PromptUpdatableProperties) => updatePrompt(promptId, prompt, axiosInstance), + getPublicPrompts: async () => await getPublicPrompts(axiosInstance), }; }; diff --git a/frontend/lib/components/AddBrainModal/AddBrainModal.tsx b/frontend/lib/components/AddBrainModal/AddBrainModal.tsx index e88e4b11e..2b5b70703 100644 --- a/frontend/lib/components/AddBrainModal/AddBrainModal.tsx +++ b/frontend/lib/components/AddBrainModal/AddBrainModal.tsx @@ -1,6 +1,7 @@ /* eslint-disable max-lines */ import { MdAdd } from "react-icons/md"; +import { PublicPrompts } from "@/app/brains-management/[brainId]/components/BrainManagementTabs/components/SettingsTab/components/PublicPrompts"; import Button from "@/lib/components/ui/Button"; import Field from "@/lib/components/ui/Field"; import { Modal } from "@/lib/components/ui/Modal"; @@ -22,6 +23,7 @@ export const AddBrainModal = (): JSX.Element => { maxTokens, model, isPending, + pickPublicPrompt, } = useAddBrainModal(); return ( @@ -116,6 +118,7 @@ export const AddBrainModal = (): JSX.Element => { /> + { } }; + const pickPublicPrompt = ({ + title, + content, + }: { + title: string; + content: string; + }): void => { + setValue("prompt.title", title, { + shouldDirty: true, + }); + setValue("prompt.content", content, { + shouldDirty: true, + }); + }; + return { isShareModalOpen, setIsShareModalOpen, @@ -133,5 +148,6 @@ export const useAddBrainModal = () => { temperature, maxTokens, isPending, + pickPublicPrompt, }; }; diff --git a/frontend/package.json b/frontend/package.json index c71286583..2b70493a7 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -20,6 +20,7 @@ "@emotion/styled": "^11.11.0", "@growthbook/growthbook-react": "^0.17.0", "@june-so/analytics-next": "^2.0.0", + "@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-dialog": "^1.0.3", "@radix-ui/react-popover": "^1.0.6", "@radix-ui/react-select": "^1.2.2", diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 42cd8186c..dd463558a 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -756,6 +756,22 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-accordion@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-accordion/-/react-accordion-1.1.2.tgz#738441f7343e5142273cdef94d12054c3287966f" + integrity sha512-fDG7jcoNKVjSK6yfmuAs0EnPDro0WMXIhMtXdTBWqEioVW206ku+4Lw07e+13lUkFkpoEQ2PdeMIAGpdqEAmDg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-collapsible" "1.0.3" + "@radix-ui/react-collection" "1.0.3" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-direction" "1.0.1" + "@radix-ui/react-id" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-use-controllable-state" "1.0.1" + "@radix-ui/react-arrow@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz#c24f7968996ed934d57fe6cde5d6ec7266e1d25d" @@ -764,6 +780,21 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-primitive" "1.0.3" +"@radix-ui/react-collapsible@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-collapsible/-/react-collapsible-1.0.3.tgz#df0e22e7a025439f13f62d4e4a9e92c4a0df5b81" + integrity sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-id" "1.0.1" + "@radix-ui/react-presence" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-use-controllable-state" "1.0.1" + "@radix-ui/react-use-layout-effect" "1.0.1" + "@radix-ui/react-collection@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.0.3.tgz#9595a66e09026187524a36c6e7e9c7d286469159"