diff --git a/frontend/src/Setting.tsx b/frontend/src/Setting.tsx index 56423797..87632ce1 100644 --- a/frontend/src/Setting.tsx +++ b/frontend/src/Setting.tsx @@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import ArrowLeft from './assets/arrow-left.svg'; import ArrowRight from './assets/arrow-right.svg'; +import Exit from './assets/exit.svg'; import Trash from './assets/trash.svg'; import { selectPrompt, @@ -21,13 +22,16 @@ type PromptProps = { }; const Setting: React.FC = () => { - const tabs = ['General', 'Prompts', 'Documents']; + const tabs = ['General', 'Prompts', 'Documents', 'API Keys']; //const tabs = ['General', 'Prompts', 'Documents', 'Widgets']; const [activeTab, setActiveTab] = useState('General'); const [prompts, setPrompts] = useState< { name: string; id: string; type: string }[] >([]); + const [apiKeys, setApiKeys] = useState< + { name: string; key: string; source: string; id: string }[] + >([]); const selectedPrompt = useSelector(selectPrompt); const [isAddPromptModalOpen, setAddPromptModalOpen] = useState(false); const documents = useSelector(selectSourceDocs); @@ -41,7 +45,18 @@ const Setting: React.FC = () => { const updateWidgetScreenshot = (screenshot: File | null) => { setWidgetScreenshot(screenshot); }; - + const fetchAPIKeys = async () => { + try { + const response = await fetch(`${apiHost}/api/get_api_keys`); + if (!response.ok) { + throw new Error('Failed to fetch API Keys'); + } + const apiKeys = await response.json(); + setApiKeys(apiKeys); + } catch (error) { + console.log(error); + } + }; useEffect(() => { const fetchPrompts = async () => { try { @@ -55,8 +70,8 @@ const Setting: React.FC = () => { console.error(error); } }; - fetchPrompts(); + fetchAPIKeys(); }, []); const onDeletePrompt = (name: string, id: string) => { @@ -184,6 +199,8 @@ const Setting: React.FC = () => { onWidgetScreenshotChange={updateWidgetScreenshot} // Add this line /> ); + case 'API Keys': + return ; default: return null; } @@ -468,7 +485,6 @@ const AddPromptModal: React.FC = ({ ); }; - type DocumentsProps = { documents: Doc[] | null; handleDeleteDocument: (index: number, document: Doc) => void; @@ -480,10 +496,10 @@ const Documents: React.FC = ({ }) => { return (
-
+
{/*

Documents

*/} -
+
@@ -617,7 +633,196 @@ const AddDocumentModal: React.FC = ({ ); }; +const APIKeys: React.FC = () => { + const apiKeys = [ + { name: 'Base', source: '2001', key: '131346543' }, + { name: 'Base', source: '2001', key: '131346543' }, + { name: 'Base', source: '2001', key: '131346543' }, + { name: 'Base', source: '2001', key: '131346543' }, + ]; + const [isCreateModalOpen, setCreateModal] = useState(false); + const [isSaveKeyModalOpen, setSaveKeyModal] = useState(true); + return ( +
+
+
+ +
+ {isCreateModalOpen && ( + setCreateModal(false)} /> + )} + {isSaveKeyModalOpen && ( + setSaveKeyModal(false)} + /> + )} +
+
+
+ + + + + + + + + + {apiKeys?.map((element, index) => ( + + + + + + + ))} + +
Name + Source document + API Key
{element.name}{element.source}{element.key} + Delete { + event.stopPropagation(); + console.log('deleted api key !'); + }} + /> +
+
+
+
+
+ ); +}; +type SaveAPIKeyModalProps = { + apiKey: string; + close: () => void; +}; +const SaveAPIKeyModal: React.FC = ({ apiKey, close }) => { + const [isCopied, setIsCopied] = useState(false); + const handleCopyKey = () => { + navigator.clipboard.writeText(apiKey); + setIsCopied(true); + }; + return ( +
+
+ +

Please save your Key

+

+ This is the only time your key will be shown. +

+
+
+

API Key

+ {apiKey} +
+ +
+ +
+
+ ); +}; +type CreateAPIKeyModalProps = { + close: () => void; +}; +const CreateAPIKeyModal: React.FC = ({ close }) => { + const [APIKeyName, setAPIKeyName] = useState(''); + const [selectedDocPath, setSelectedDocPath] = useState(null); + const docs = useSelector(selectSourceDocs); + const handleCreate = () => { + console.log(selectedDocPath, APIKeyName); + close(); + }; + const extractDocPaths = () => + docs + ? docs.map((doc: Doc) => { + let namePath = doc.name; + if (doc.language === namePath) { + namePath = '.project'; + } + let docPath = 'default'; + if (doc.location === 'local') { + docPath = 'local' + '/' + doc.name + '/'; + } else if (doc.location === 'remote') { + docPath = + doc.language + + '/' + + namePath + + '/' + + doc.version + + '/' + + doc.model + + '/'; + } + return { + label: namePath, + value: docPath, + }; + }) + : []; + + return ( +
+
+ +

Create New API Key

+
+ + API Key Name + + setAPIKeyName(e.target.value)} + /> +
+
+ setSelectedDocPath(value)} + options={extractDocPaths()} + /> +
+ +
+
+ ); +}; const Widgets: React.FC<{ widgetScreenshot: File | null; onWidgetScreenshotChange: (screenshot: File | null) => void; diff --git a/frontend/src/components/Dropdown.tsx b/frontend/src/components/Dropdown.tsx index 5654b430..6b063cc2 100644 --- a/frontend/src/components/Dropdown.tsx +++ b/frontend/src/components/Dropdown.tsx @@ -7,18 +7,20 @@ function Dropdown({ onSelect, showDelete, onDelete, + placeholder, }: { options: | string[] | { name: string; id: string; type: string }[] | { label: string; value: string }[]; - selectedValue: string | { label: string; value: string }; + selectedValue: string | { label: string; value: string } | null; onSelect: | ((value: string) => void) | ((value: { name: string; id: string; type: string }) => void) | ((value: { label: string; value: string }) => void); showDelete?: boolean; onDelete?: (value: string) => void; + placeholder?: string; }) { const [isOpen, setIsOpen] = useState(false); return ( @@ -51,7 +53,11 @@ function Dropdown({ !selectedValue && 'text-silver' }`} > - {selectedValue ? selectedValue.label : 'From URL'} + {selectedValue + ? selectedValue.label + : placeholder + ? placeholder + : 'From URL'} )}