From afecae37865962516cde1fc631dae94532552350 Mon Sep 17 00:00:00 2001 From: sarfaraz siddiqui Date: Sun, 31 Mar 2024 03:50:11 +0530 Subject: [PATCH 1/9] added feature #887 --- application/api/answer/routes.py | 4 +++- frontend/src/components/SourceDropdown.tsx | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/application/api/answer/routes.py b/application/api/answer/routes.py index bd1fa21f..b122eac1 100644 --- a/application/api/answer/routes.py +++ b/application/api/answer/routes.py @@ -207,7 +207,9 @@ def stream(): prompt_id = data["prompt_id"] else: prompt_id = 'default' - if 'chunks' in data: + if 'selectedDocs' in data and data['selectedDocs'] is None: + chunks = 0 + elif 'chunks' in data: chunks = int(data["chunks"]) else: chunks = 2 diff --git a/frontend/src/components/SourceDropdown.tsx b/frontend/src/components/SourceDropdown.tsx index 04b95d7c..353d49db 100644 --- a/frontend/src/components/SourceDropdown.tsx +++ b/frontend/src/components/SourceDropdown.tsx @@ -24,6 +24,12 @@ function SourceDropdown({ const embeddingsName = import.meta.env.VITE_EMBEDDINGS_NAME || 'huggingface_sentence-transformers/all-mpnet-base-v2'; + + const handleEmptyDocumentSelect = () => { + dispatch(setSelectedDocs(null)); + setIsDocsListOpen(false); + }; + return (
)} From 88b4fb8c2a0aeb69226320c1cecdcfcfaf5f6345 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 1 Apr 2024 11:25:31 +0100 Subject: [PATCH 2/9] Update API key in DocsGPTWidget.tsx --- extensions/react-widget/src/components/DocsGPTWidget.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/react-widget/src/components/DocsGPTWidget.tsx b/extensions/react-widget/src/components/DocsGPTWidget.tsx index 45cd2285..54e1beea 100644 --- a/extensions/react-widget/src/components/DocsGPTWidget.tsx +++ b/extensions/react-widget/src/components/DocsGPTWidget.tsx @@ -285,7 +285,7 @@ const Hero = ({ title, description }: { title: string, description: string }) => export const DocsGPTWidget = ({ apiHost = 'https://gptcloud.arc53.com', selectDocs = 'default', - apiKey = 'docsgpt-public', + apiKey = '82962c9a-aa77-4152-94e5-a4f84fd44c6a', avatar = 'https://d3dg1063dc54p9.cloudfront.net/cute-docsgpt.png', title = 'Get AI assistance', description = 'DocsGPT\'s AI Chatbot is here to help', From dadd12adb33dd2b454558e1b31f0209b9d0cf6ca Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 1 Apr 2024 11:25:59 +0100 Subject: [PATCH 3/9] Update API key in DocsGPTWidget.tsx --- docs/pages/_app.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/_app.mdx b/docs/pages/_app.mdx index 51f4539f..992283cc 100644 --- a/docs/pages/_app.mdx +++ b/docs/pages/_app.mdx @@ -4,7 +4,7 @@ export default function MyApp({ Component, pageProps }) { return ( <> - + ) } \ No newline at end of file From ec5166249af8e694837b966aaed26e59faef8745 Mon Sep 17 00:00:00 2001 From: Pavel Date: Mon, 1 Apr 2024 21:07:27 +0400 Subject: [PATCH 4/9] api update A description of 3 more api methods in documentation. --- docs/pages/Developing/API-docs.md | 116 ++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/docs/pages/Developing/API-docs.md b/docs/pages/Developing/API-docs.md index ee43d848..c5bd8970 100644 --- a/docs/pages/Developing/API-docs.md +++ b/docs/pages/Developing/API-docs.md @@ -227,3 +227,119 @@ JSON response indicating the status of the operation: ```json { "status": "ok" } ``` + +### 7. /api/get_api_keys +**Description:** + +The endpoint retrieves a list of API keys for the user. + +**Request:** + +**Method**: `GET` + +**Sample JavaScript Fetch Request:** +```js +// get_api_keys (GET http://127.0.0.1:5000/api/get_api_keys) +fetch("http://localhost:5001/api/get_api_keys", { + "method": "GET", + "headers": { + "Content-Type": "application/json; charset=utf-8" + }, +}) +.then((res) => res.text()) +.then(console.log.bind(console)) + +``` +**Response:** + +JSON response with a list of created API keys: + +```json +[ + { + "id": "string", + "name": "string", + "key": "string", + "source": "string" + }, + ... + ] +``` + +### 8. /api/create_api_key + +**Description:** + +Create a new API key for the user. + +**Request:** + +**Method**: `POST` + +**Headers**: Content-Type should be set to `application/json; charset=utf-8` + +**Request Body**: JSON object with the following fields: +* `name` — A name for the API key. +* `source` — The source documents that will be used. + +Here is a JavaScript Fetch Request example: +```js +// create_api_key (POST http://127.0.0.1:5000/api/create_api_key) +fetch("http://127.0.0.1:5000/api/create_api_key", { + "method": "POST", + "headers": { + "Content-Type": "application/json; charset=utf-8" + }, + "body": JSON.stringify({"name":"Example Key Name","source":"Example Source"}) +}) +.then((res) => res.json()) +.then(console.log.bind(console)) +``` + +**Response** + +In response, you will get a JSON document containing the `id` and `key`: +```json +{ + "id": "string", + "key": "string" +} +``` + +### 9. /api/delete_api_key + +**Description:** + +Delete an API key for the user. + +**Request:** + +**Method**: `POST` + +**Headers**: Content-Type should be set to `application/json; charset=utf-8` + +**Request Body**: JSON object with the field: +* `id` — The unique identifier of the API key to be deleted. + +Here is a JavaScript Fetch Request example: +```js +// delete_api_key (POST http://127.0.0.1:5000/api/delete_api_key) +fetch("http://127.0.0.1:5000/api/delete_api_key", { + "method": "POST", + "headers": { + "Content-Type": "application/json; charset=utf-8" + }, + "body": JSON.stringify({"id":"API_KEY_ID"}) +}) +.then((res) => res.json()) +.then(console.log.bind(console)) +``` + +**Response:** + +In response, you will get a JSON document indicating the status of the operation: +```json +{ + "status": "ok" +} +``` \ No newline at end of file From 02d4f7f2da3bf3974fd54aa0b74045dd8e617dfd Mon Sep 17 00:00:00 2001 From: sarfaraz siddiqui Date: Wed, 3 Apr 2024 18:08:46 +0530 Subject: [PATCH 5/9] functions can accept null --- frontend/src/conversation/conversationApi.ts | 113 ++++++++++--------- 1 file changed, 59 insertions(+), 54 deletions(-) diff --git a/frontend/src/conversation/conversationApi.ts b/frontend/src/conversation/conversationApi.ts index e586366b..e3a82191 100644 --- a/frontend/src/conversation/conversationApi.ts +++ b/frontend/src/conversation/conversationApi.ts @@ -6,7 +6,7 @@ const apiHost = import.meta.env.VITE_API_HOST || 'https://docsapi.arc53.com'; export function fetchAnswerApi( question: string, signal: AbortSignal, - selectedDocs: Doc, + selectedDocs: Doc | null, history: Array = [], conversationId: string | null, promptId: string | null, @@ -28,24 +28,26 @@ export function fetchAnswerApi( title: any; } > { - let namePath = selectedDocs.name; - if (selectedDocs.language === namePath) { - namePath = '.project'; - } - let docPath = 'default'; - if (selectedDocs.location === 'local') { - docPath = 'local' + '/' + selectedDocs.name + '/'; - } else if (selectedDocs.location === 'remote') { - docPath = - selectedDocs.language + - '/' + - namePath + - '/' + - selectedDocs.version + - '/' + - selectedDocs.model + - '/'; + + if (selectedDocs) { + let namePath = selectedDocs.name; + if (selectedDocs.language === namePath) { + namePath = '.project'; + } + if (selectedDocs.location === 'local') { + docPath = 'local' + '/' + selectedDocs.name + '/'; + } else if (selectedDocs.location === 'remote') { + docPath = + selectedDocs.language + + '/' + + namePath + + '/' + + selectedDocs.version + + '/' + + selectedDocs.model + + '/'; + } } //in history array remove all keys except prompt and response history = history.map((item) => { @@ -89,31 +91,33 @@ export function fetchAnswerApi( export function fetchAnswerSteaming( question: string, signal: AbortSignal, - selectedDocs: Doc, + selectedDocs: Doc | null, history: Array = [], conversationId: string | null, promptId: string | null, chunks: string, onEvent: (event: MessageEvent) => void, ): Promise { - let namePath = selectedDocs.name; - if (selectedDocs.language === namePath) { - namePath = '.project'; - } - let docPath = 'default'; - if (selectedDocs.location === 'local') { - docPath = 'local' + '/' + selectedDocs.name + '/'; - } else if (selectedDocs.location === 'remote') { - docPath = - selectedDocs.language + - '/' + - namePath + - '/' + - selectedDocs.version + - '/' + - selectedDocs.model + - '/'; + + if (selectedDocs) { + let namePath = selectedDocs.name; + if (selectedDocs.language === namePath) { + namePath = '.project'; + } + if (selectedDocs.location === 'local') { + docPath = 'local' + '/' + selectedDocs.name + '/'; + } else if (selectedDocs.location === 'remote') { + docPath = + selectedDocs.language + + '/' + + namePath + + '/' + + selectedDocs.version + + '/' + + selectedDocs.model + + '/'; + } } history = history.map((item) => { @@ -186,7 +190,7 @@ export function fetchAnswerSteaming( } export function searchEndpoint( question: string, - selectedDocs: Doc, + selectedDocs: Doc | null, conversation_id: string | null, history: Array = [], chunks: string, @@ -196,24 +200,25 @@ export function searchEndpoint( "question": "Summarise", "conversation_id": null, "history": "[]" */ - let namePath = selectedDocs.name; - if (selectedDocs.language === namePath) { - namePath = '.project'; - } - let docPath = 'default'; - if (selectedDocs.location === 'local') { - docPath = 'local' + '/' + selectedDocs.name + '/'; - } else if (selectedDocs.location === 'remote') { - docPath = - selectedDocs.language + - '/' + - namePath + - '/' + - selectedDocs.version + - '/' + - selectedDocs.model + - '/'; + if (selectedDocs) { + let namePath = selectedDocs.name; + if (selectedDocs.language === namePath) { + namePath = '.project'; + } + if (selectedDocs.location === 'local') { + docPath = 'local' + '/' + selectedDocs.name + '/'; + } else if (selectedDocs.location === 'remote') { + docPath = + selectedDocs.language + + '/' + + namePath + + '/' + + selectedDocs.version + + '/' + + selectedDocs.model + + '/'; + } } const body = { From 729fa2352b45b5aa0f646df3c20d8727a0e7625a Mon Sep 17 00:00:00 2001 From: Siddhant Rai Date: Thu, 4 Apr 2024 00:48:49 +0530 Subject: [PATCH 6/9] feat: added prompts section under general in settings --- frontend/src/Setting.tsx | 322 ++++++++++------------ frontend/src/components/Dropdown.tsx | 55 ++-- frontend/src/preferences/PromptsModal.tsx | 213 ++++++++++++++ frontend/src/upload/Upload.tsx | 2 + 4 files changed, 402 insertions(+), 190 deletions(-) create mode 100644 frontend/src/preferences/PromptsModal.tsx diff --git a/frontend/src/Setting.tsx b/frontend/src/Setting.tsx index 172691a0..26c8701d 100644 --- a/frontend/src/Setting.tsx +++ b/frontend/src/Setting.tsx @@ -15,23 +15,24 @@ import { import { Doc } from './preferences/preferenceApi'; import { useDarkTheme } from './hooks'; import Dropdown from './components/Dropdown'; +import { ActiveState } from './models/misc'; +import PromptsModal from './preferences/PromptsModal'; +type PromptProps = { + prompts: { name: string; id: string; type: string }[]; + selectedPrompt: { name: string; id: string; type: string }; + onSelectPrompt: (name: string, id: string, type: string) => void; + setPrompts: (prompts: { name: string; id: string; type: string }[]) => void; + apiHost: string; +}; const apiHost = import.meta.env.VITE_API_HOST || 'https://docsapi.arc53.com'; - const embeddingsName = import.meta.env.VITE_EMBEDDINGS_NAME || 'huggingface_sentence-transformers/all-mpnet-base-v2'; -const Setting: React.FC = () => { - const tabs = ['General', 'Prompts', 'Documents', 'API Keys']; - //const tabs = ['General', 'Prompts', 'Documents', 'Widgets']; +const Setting: React.FC = () => { + const tabs = ['General', 'Documents']; const [activeTab, setActiveTab] = useState('General'); - const [prompts, setPrompts] = useState< - { name: string; id: string; type: string }[] - >([]); - const selectedPrompt = useSelector(selectPrompt); - const [isAddPromptModalOpen, setAddPromptModalOpen] = useState(false); const documents = useSelector(selectSourceDocs); - const [isAddDocumentModalOpen, setAddDocumentModalOpen] = useState(false); const dispatch = useDispatch(); @@ -41,43 +42,6 @@ const Setting: React.FC = () => { setWidgetScreenshot(screenshot); }; - useEffect(() => { - const fetchPrompts = async () => { - try { - const response = await fetch(`${apiHost}/api/get_prompts`); - if (!response.ok) { - throw new Error('Failed to fetch prompts'); - } - const promptsData = await response.json(); - setPrompts(promptsData); - } catch (error) { - console.error(error); - } - }; - fetchPrompts(); - }, []); - - const onDeletePrompt = (name: string, id: string) => { - setPrompts(prompts.filter((prompt) => prompt.id !== id)); - - fetch(`${apiHost}/api/delete_prompt`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - // send id in body only - body: JSON.stringify({ id: id }), - }) - .then((response) => { - if (!response.ok) { - throw new Error('Failed to delete prompt'); - } - }) - .catch((error) => { - console.error(error); - }); - }; - const handleDeleteClick = (index: number, doc: Doc) => { const docPath = 'indexes/' + 'local' + '/' + doc.name; @@ -156,17 +120,6 @@ const Setting: React.FC = () => { switch (activeTab) { case 'General': return ; - case 'Prompts': - return ( - - dispatch(setPrompt({ name: name, id: id, type: type })) - } - setPrompts={setPrompts} - /> - ); case 'Documents': return ( { const themes = ['Light', 'Dark']; const languages = ['English']; const chunks = ['0', '2', '4', '6', '8', '10']; + const [prompts, setPrompts] = useState< + { name: string; id: string; type: string }[] + >([]); const selectedChunks = useSelector(selectChunks); const [isDarkTheme, toggleTheme] = useDarkTheme(); const [selectedTheme, setSelectedTheme] = useState( @@ -200,6 +156,24 @@ const General: React.FC = () => { ); const dispatch = useDispatch(); const [selectedLanguage, setSelectedLanguage] = useState(languages[0]); + const selectedPrompt = useSelector(selectPrompt); + const apiHost = import.meta.env.VITE_API_HOST || 'https://docsapi.arc53.com'; + + useEffect(() => { + const fetchPrompts = async () => { + try { + const response = await fetch(`${apiHost}/api/get_prompts`); + if (!response.ok) { + throw new Error('Failed to fetch prompts'); + } + const promptsData = await response.json(); + setPrompts(promptsData); + } catch (error) { + console.error(error); + } + }; + fetchPrompts(); + }, []); return (
@@ -211,6 +185,8 @@ const General: React.FC = () => { setSelectedTheme(option); option !== selectedTheme && toggleTheme(); }} + size="w-56" + rounded="3xl" />
@@ -221,9 +197,11 @@ const General: React.FC = () => { options={languages} selectedValue={selectedLanguage} onSelect={setSelectedLanguage} + size="w-56" + rounded="3xl" />
-
+

Chunks processed per query

@@ -231,6 +209,19 @@ const General: React.FC = () => { options={chunks} selectedValue={selectedChunks} onSelect={(value: string) => dispatch(setChunks(value))} + size="w-56" + rounded="3xl" + /> +
+
+ + dispatch(setPrompt({ name: name, id: id, type: type })) + } + setPrompts={setPrompts} + apiHost={apiHost} />
@@ -238,12 +229,6 @@ const General: React.FC = () => { }; export default Setting; -type PromptProps = { - prompts: { name: string; id: string; type: string }[]; - selectedPrompt: { name: string; id: string; type: string }; - onSelectPrompt: (name: string, id: string, type: string) => void; - setPrompts: (prompts: { name: string; id: string; type: string }[]) => void; -}; const Prompts: React.FC = ({ prompts, @@ -260,11 +245,20 @@ const Prompts: React.FC = ({ id: string; type: string; }) => { - setNewPromptName(name); + setEditPromptName(name); onSelectPrompt(name, id, type); }; - const [newPromptName, setNewPromptName] = useState(selectedPrompt.name); + const [newPromptName, setNewPromptName] = useState(''); const [newPromptContent, setNewPromptContent] = useState(''); + const [editPromptName, setEditPromptName] = useState(''); + const [editPromptContent, setEditPromptContent] = useState(''); + const [currentPromptEdit, setCurrentPromptEdit] = useState({ + id: '', + name: '', + type: '', + }); + const [modalType, setModalType] = useState<'ADD' | 'EDIT'>('ADD'); + const [modalState, setModalState] = useState('INACTIVE'); const handleAddPrompt = async () => { try { @@ -295,16 +289,14 @@ const Prompts: React.FC = ({ } }; - const handleDeletePrompt = () => { - setPrompts(prompts.filter((prompt) => prompt.id !== selectedPrompt.id)); - console.log('selectedPrompt.id', selectedPrompt.id); - + const handleDeletePrompt = (id: string) => { + setPrompts(prompts.filter((prompt) => prompt.id !== id)); fetch(`${apiHost}/api/delete_prompt`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, - body: JSON.stringify({ id: selectedPrompt.id }), + body: JSON.stringify({ id: id }), }) .then((response) => { if (!response.ok) { @@ -321,50 +313,45 @@ const Prompts: React.FC = ({ }); }; - useEffect(() => { - const fetchPromptContent = async () => { - console.log('fetching prompt content'); - try { - const response = await fetch( - `${apiHost}/api/get_single_prompt?id=${selectedPrompt.id}`, - { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - }, + const fetchPromptContent = async (name: string) => { + console.log('fetching prompt content'); + try { + const response = await fetch( + `${apiHost}/api/get_single_prompt?id=${name}`, + { + method: 'GET', + headers: { + 'Content-Type': 'application/json', }, - ); - if (!response.ok) { - throw new Error('Failed to fetch prompt content'); - } - const promptContent = await response.json(); - setNewPromptContent(promptContent.content); - } catch (error) { - console.error(error); + }, + ); + if (!response.ok) { + throw new Error('Failed to fetch prompt content'); } - }; + const promptContent = await response.json(); + setEditPromptContent(promptContent.content); + } catch (error) { + console.error(error); + } + }; - fetchPromptContent(); - }, [selectedPrompt]); - - const handleSaveChanges = () => { + const handleSaveChanges = (id: string, type: string) => { fetch(`${apiHost}/api/update_prompt`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ - id: selectedPrompt.id, - name: newPromptName, - content: newPromptContent, + id: id, + name: editPromptName, + content: editPromptContent, }), }) .then((response) => { if (!response.ok) { throw new Error('Failed to update prompt'); } - onSelectPrompt(newPromptName, selectedPrompt.id, selectedPrompt.type); - setNewPromptName(newPromptName); + onSelectPrompt(editPromptName, id, type); }) .catch((error) => { console.error(error); @@ -372,76 +359,65 @@ const Prompts: React.FC = ({ }; return ( -
-
-

Active Prompt

- + <> +
+
+
+

Active Prompt

+ { + setModalType('EDIT'); + setEditPromptName(name); + fetchPromptContent(name); + setCurrentPromptEdit({ id: id, name: name, type: type }); + setModalState('ACTIVE'); + }} + onDelete={handleDeletePrompt} + /> +
+ +
- -
-

Prompt name

{' '} -

- start by editing name -

- setNewPromptName(e.target.value)} - /> -
- -
-

Prompt content

- +
+
+ + +
+
+ ); +} + +function EditPrompt({ + setModalState, + handleEditPrompt, + editPromptName, + setEditPromptName, + editPromptContent, + setEditPromptContent, + currentPromptEdit, +}: { + setModalState: (state: ActiveState) => void; + handleEditPrompt?: (id: string, type: string) => void; + editPromptName: string; + setEditPromptName: (name: string) => void; + editPromptContent: string; + setEditPromptContent: (content: string) => void; + currentPromptEdit: { name: string; id: string; type: string }; +}) { + return ( +
+

Edit Prompt

+

+ Edit your custom prompt and save it to DocsGPT. +

+
+ setEditPromptName(e.target.value)} + > +
+ + Prompt Name + +
+
+ + Prompt Text + +
+ +
+
+ + +
+
+ ); +} + +export default function PromptsModal({ + modalState, + setModalState, + type, + newPromptName, + setNewPromptName, + newPromptContent, + setNewPromptContent, + editPromptName, + setEditPromptName, + editPromptContent, + setEditPromptContent, + currentPromptEdit, + handleAddPrompt, + handleEditPrompt, +}: { + modalState: ActiveState; + setModalState: (state: ActiveState) => void; + type: 'ADD' | 'EDIT'; + newPromptName: string; + setNewPromptName: (name: string) => void; + newPromptContent: string; + setNewPromptContent: (content: string) => void; + editPromptName: string; + setEditPromptName: (name: string) => void; + editPromptContent: string; + setEditPromptContent: (content: string) => void; + currentPromptEdit: { name: string; id: string; type: string }; + handleAddPrompt?: () => void; + handleEditPrompt?: (id: string, type: string) => void; +}) { + let view; + + if (type === 'ADD') { + view = ( + + ); + } else if (type === 'EDIT') { + view = ( + + ); + } else { + view = <>; + } + return ( +
+
+ {view} +
+
+ ); +} diff --git a/frontend/src/upload/Upload.tsx b/frontend/src/upload/Upload.tsx index 45fc4e1a..15ae206b 100644 --- a/frontend/src/upload/Upload.tsx +++ b/frontend/src/upload/Upload.tsx @@ -307,6 +307,8 @@ export default function Upload({ onSelect={(value: { label: string; value: string }) => setUrlType(value) } + size="w-full" + rounded="3xl" /> {urlType.label !== 'Reddit' ? ( <> From 9cadd74a96340f6823feb1f23fe17ca9a1fce8e6 Mon Sep 17 00:00:00 2001 From: Siddhant Rai Date: Thu, 4 Apr 2024 13:42:32 +0530 Subject: [PATCH 7/9] fix: minor ui changes --- frontend/src/Setting.tsx | 2 +- frontend/src/components/Dropdown.tsx | 20 ++++++++++++++------ frontend/src/preferences/PromptsModal.tsx | 8 ++++---- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/frontend/src/Setting.tsx b/frontend/src/Setting.tsx index 26c8701d..7834ae2d 100644 --- a/frontend/src/Setting.tsx +++ b/frontend/src/Setting.tsx @@ -281,6 +281,7 @@ const Prompts: React.FC = ({ ...prompts, { name: newPromptName, id: newPrompt.id, type: 'private' }, ]); + setModalState('INACTIVE'); } onSelectPrompt(newPromptName, newPrompt.id, newPromptContent); setNewPromptName(newPromptName); @@ -305,7 +306,6 @@ const Prompts: React.FC = ({ // get 1st prompt and set it as selected if (prompts.length > 0) { onSelectPrompt(prompts[0].name, prompts[0].id, prompts[0].type); - setNewPromptName(prompts[0].name); } }) .catch((error) => { diff --git a/frontend/src/components/Dropdown.tsx b/frontend/src/components/Dropdown.tsx index f14df984..5c22de2f 100644 --- a/frontend/src/components/Dropdown.tsx +++ b/frontend/src/components/Dropdown.tsx @@ -76,7 +76,7 @@ function Dropdown({ /> {isOpen && ( -
+
{options.map((option: any, index) => (
)} {showDelete && onDelete && ( - Delete onDelete(option.id)} - /> + disabled={option.type === 'public'} + > + Delete + )}
))} diff --git a/frontend/src/preferences/PromptsModal.tsx b/frontend/src/preferences/PromptsModal.tsx index ce0ecb47..596c9f59 100644 --- a/frontend/src/preferences/PromptsModal.tsx +++ b/frontend/src/preferences/PromptsModal.tsx @@ -48,7 +48,7 @@ function AddPrompt({
@@ -86,7 +86,7 @@ function EditPrompt({

Edit Prompt

- Edit your custom prompt and save it to DocsGPT. + Edit your custom prompt and save it to DocsGPT