From 45e17da2411c441c7d874b0d545a8700bbc7f87d Mon Sep 17 00:00:00 2001 From: Wentao Lyu <35-wentao.lyu@users.noreply.git.stereye.tech> Date: Sun, 2 Apr 2023 04:15:07 +0800 Subject: [PATCH] feat: add preset and edit preset. --- client/src/App.jsx | 16 ++ .../components/Endpoints/EditPresetDialog.jsx | 134 +++++++++++++ .../EndpointOptionsPopover.jsx | 2 +- .../OpenAI}/OptionHover.jsx | 0 .../OpenAI}/Settings.jsx | 9 +- .../Endpoints/SaveAsPresetDialog.jsx | 75 ++++++++ .../components/Input/Endpoints/MenuItems.jsx | 17 -- .../Input/Endpoints/ModelDialog.jsx | 156 --------------- .../components/Input/Endpoints/ModelItem.jsx | 180 ------------------ ...dpointMenu.jsx => NewConversationMenu.jsx} | 137 +++++-------- .../components/Input/Endpoints/PresetItem.jsx | 65 +++++++ .../Input/Endpoints/PresetItems.jsx | 18 ++ client/src/components/Input/Footer.jsx | 6 +- .../components/Input/OpenAIOptions/index.jsx | 22 +-- client/src/components/Input/index.jsx | 2 +- client/src/components/ui/Dialog.tsx | 2 +- client/src/components/ui/DialogTemplate.jsx | 18 +- client/src/components/ui/Dropdown.jsx | 73 +++++++ client/src/components/ui/Landing.jsx | 2 +- .../OpenAIOptions => ui}/ModelDropDown.jsx | 17 +- .../OpenAIOptions => ui}/ModelSelect.jsx | 4 +- .../src/components/{Prompts => ui}/Prompt.jsx | 0 .../components/{Prompts => ui}/Templates.jsx | 0 client/src/store/conversation.js | 13 +- client/src/store/index.js | 4 +- client/src/store/preset.js | 40 ++++ client/src/utils/buildPresetByConversation.js | 56 ++++++ client/src/utils/fetchers.js | 11 +- client/src/utils/getDefaultConversation.js | 6 +- 29 files changed, 592 insertions(+), 493 deletions(-) create mode 100644 client/src/components/Endpoints/EditPresetDialog.jsx rename client/src/components/{ui => Endpoints}/EndpointOptionsPopover.jsx (97%) rename client/src/components/{Input/OpenAIOptions => Endpoints/OpenAI}/OptionHover.jsx (100%) rename client/src/components/{Input/OpenAIOptions => Endpoints/OpenAI}/Settings.jsx (94%) create mode 100644 client/src/components/Endpoints/SaveAsPresetDialog.jsx delete mode 100644 client/src/components/Input/Endpoints/MenuItems.jsx delete mode 100644 client/src/components/Input/Endpoints/ModelDialog.jsx delete mode 100644 client/src/components/Input/Endpoints/ModelItem.jsx rename client/src/components/Input/Endpoints/{EndpointMenu.jsx => NewConversationMenu.jsx} (52%) create mode 100644 client/src/components/Input/Endpoints/PresetItem.jsx create mode 100644 client/src/components/Input/Endpoints/PresetItems.jsx create mode 100644 client/src/components/ui/Dropdown.jsx rename client/src/components/{Input/OpenAIOptions => ui}/ModelDropDown.jsx (81%) rename client/src/components/{Input/OpenAIOptions => ui}/ModelSelect.jsx (94%) rename client/src/components/{Prompts => ui}/Prompt.jsx (100%) rename client/src/components/{Prompts => ui}/Templates.jsx (100%) create mode 100644 client/src/store/preset.js create mode 100644 client/src/utils/buildPresetByConversation.js diff --git a/client/src/App.jsx b/client/src/App.jsx index d5df7345cc..b63e474677 100644 --- a/client/src/App.jsx +++ b/client/src/App.jsx @@ -39,6 +39,7 @@ const App = () => { const [user, setUser] = useRecoilState(store.user); const setIsSearchEnabled = useSetRecoilState(store.isSearchEnabled); const setEndpointsConfig = useSetRecoilState(store.endpointsConfig); + const setPresets = useSetRecoilState(store.presets); useEffect(() => { // fetch if seatch enabled @@ -70,6 +71,21 @@ const App = () => { console.log('Not login!'); window.location.href = '/auth/login'; }); + + // fetch presets + axios + .get('/api/presets', { + timeout: 1000, + withCredentials: true + }) + .then(({ data }) => { + setPresets(data); + }) + .catch(error => { + console.error(error); + console.log('Not login!'); + window.location.href = '/auth/login'; + }); }, []); if (user) diff --git a/client/src/components/Endpoints/EditPresetDialog.jsx b/client/src/components/Endpoints/EditPresetDialog.jsx new file mode 100644 index 0000000000..c3ae5eceba --- /dev/null +++ b/client/src/components/Endpoints/EditPresetDialog.jsx @@ -0,0 +1,134 @@ +import React, { useEffect, useState } from 'react'; +import { useSetRecoilState, useRecoilValue } from 'recoil'; +import axios from 'axios'; +import DialogTemplate from '../ui/DialogTemplate'; +import { Dialog } from '../ui/Dialog.tsx'; +import { Input } from '../ui/Input.tsx'; +import { Label } from '../ui/Label.tsx'; +import Dropdown from '../ui/Dropdown'; +import { cn } from '~/utils/'; +import OpenAISettings from './OpenAI/Settings'; + +import store from '~/store'; + +const EditPresetDialog = ({ open, onOpenChange, preset: _preset }) => { + // const [title, setTitle] = useState('My Preset'); + const [preset, setPreset] = useState({}); + const setPresets = useSetRecoilState(store.presets); + + const availableEndpoints = useRecoilValue(store.availableEndpoints); + + const setOption = param => newValue => { + let update = {}; + update[param] = newValue; + setPreset(prevState => ({ + ...prevState, + ...update + })); + }; + + const renderSettings = () => { + const { endpoint } = preset || {}; + + if (endpoint === 'openAI') + return ( + + ); + else return null; + }; + + const defaultTextProps = + 'rounded-md border border-gray-200 focus:bg-gray-50 bg-transparent text-sm shadow-[0_0_10px_rgba(0,0,0,0.05)] outline-none placeholder:text-gray-400 focus:outline-none focus:ring-gray-400 focus:ring-opacity-20 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-500 dark:bg-gray-700 focus:dark:bg-gray-600 dark:text-gray-50 dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] dark:focus:border-gray-400 dark:focus:outline-none dark:focus:ring-0 dark:focus:ring-gray-400 dark:focus:ring-offset-0'; + + const submitPreset = () => { + axios({ + method: 'post', + url: '/api/presets', + data: preset, + withCredentials: true + }).then(res => { + setPresets(res?.data); + }); + }; + + useEffect(() => { + setPreset(_preset); + }, [open]); + + return ( + + +
+
+ + setOption('title')(e.target.value || '')} + placeholder="Set a custom name, in case you can find this preset" + className={cn( + defaultTextProps, + 'flex h-10 max-h-10 w-full resize-none px-3 py-2 focus:outline-none focus:ring-0 focus:ring-opacity-0 focus:ring-offset-0' + )} + /> +
+
+ + +
+
+
+
{renderSettings()}
+
+ selection={{ + selectHandler: submitPreset, + selectClasses: 'bg-green-600 hover:bg-green-700 dark:hover:bg-green-800 text-white', + selectText: 'Save' + }} + /> +
+ ); +}; + +export default EditPresetDialog; diff --git a/client/src/components/ui/EndpointOptionsPopover.jsx b/client/src/components/Endpoints/EndpointOptionsPopover.jsx similarity index 97% rename from client/src/components/ui/EndpointOptionsPopover.jsx rename to client/src/components/Endpoints/EndpointOptionsPopover.jsx index 701eee1323..ad499d0b2e 100644 --- a/client/src/components/ui/EndpointOptionsPopover.jsx +++ b/client/src/components/Endpoints/EndpointOptionsPopover.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Button } from './Button.tsx'; +import { Button } from '../ui/Button.tsx'; import SwitchIcon from '../svg/SwitchIcon'; import SaveIcon from '../svg/SaveIcon'; diff --git a/client/src/components/Input/OpenAIOptions/OptionHover.jsx b/client/src/components/Endpoints/OpenAI/OptionHover.jsx similarity index 100% rename from client/src/components/Input/OpenAIOptions/OptionHover.jsx rename to client/src/components/Endpoints/OpenAI/OptionHover.jsx diff --git a/client/src/components/Input/OpenAIOptions/Settings.jsx b/client/src/components/Endpoints/OpenAI/Settings.jsx similarity index 94% rename from client/src/components/Input/OpenAIOptions/Settings.jsx rename to client/src/components/Endpoints/OpenAI/Settings.jsx index 8924557eea..22060dd05d 100644 --- a/client/src/components/Input/OpenAIOptions/Settings.jsx +++ b/client/src/components/Endpoints/OpenAI/Settings.jsx @@ -1,6 +1,6 @@ import React from 'react'; import TextareaAutosize from 'react-textarea-autosize'; -import ModelDropDown from './ModelDropDown'; +import ModelDropDown from '../../ui/ModelDropDown'; import { Input } from '~/components/ui/Input.tsx'; import { Label } from '~/components/ui/Label.tsx'; import { Slider } from '~/components/ui/Slider.tsx'; @@ -8,7 +8,7 @@ import OptionHover from './OptionHover'; import { HoverCard, HoverCardTrigger } from '~/components/ui/HoverCard.tsx'; import { cn } from '~/utils/'; const defaultTextProps = - 'rounded-md border border-gray-300 bg-transparent text-sm shadow-[0_0_10px_rgba(0,0,0,0.10)] outline-none placeholder:text-gray-400 focus:outline-none focus:ring-gray-400 focus:ring-opacity-20 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-400 dark:bg-gray-700 dark:text-gray-50 dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] dark:focus:border-gray-400 dark:focus:outline-none dark:focus:ring-0 dark:focus:ring-gray-400 dark:focus:ring-offset-0'; + 'rounded-md border border-gray-200 focus:bg-gray-50 bg-transparent text-sm shadow-[0_0_10px_rgba(0,0,0,0.05)] outline-none placeholder:text-gray-400 focus:outline-none focus:ring-gray-400 focus:ring-opacity-20 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-500 dark:bg-gray-700 focus:dark:bg-gray-600 dark:text-gray-50 dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] dark:focus:border-gray-400 dark:focus:outline-none dark:focus:ring-0 dark:focus:ring-gray-400 dark:focus:ring-offset-0'; const optionText = 'p-0 shadow-none text-right pr-1 h-8 border-transparent focus:ring-[#10a37f] focus:ring-offset-0 focus:ring-opacity-100 hover:bg-gray-800/10 dark:hover:bg-white/10 focus:bg-gray-800/10 dark:focus:bg-white/10 transition-colors'; @@ -40,6 +40,11 @@ function Settings(props) { model={model} setModel={setModel} endpoint="openAI" + className={cn( + defaultTextProps, + 'flex w-full resize-none focus:outline-none focus:ring-0 focus:ring-opacity-0 focus:ring-offset-0' + )} + containerClassName="flex w-full resize-none" /> {/*