From 2612ce5ad91ac19f6e06d0211753cec36015c51d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Feb 2025 20:34:44 +0000 Subject: [PATCH 01/12] build(deps): bump duckduckgo-search from 6.3.0 to 7.4.2 in /application Bumps [duckduckgo-search](https://github.com/deedy5/duckduckgo_search) from 6.3.0 to 7.4.2. - [Release notes](https://github.com/deedy5/duckduckgo_search/releases) - [Commits](https://github.com/deedy5/duckduckgo_search/compare/v6.3.0...v7.4.2) --- updated-dependencies: - dependency-name: duckduckgo-search dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- application/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/requirements.txt b/application/requirements.txt index 1707ad80..ffb96ecd 100644 --- a/application/requirements.txt +++ b/application/requirements.txt @@ -4,7 +4,7 @@ beautifulsoup4==4.12.3 celery==5.4.0 dataclasses-json==0.6.7 docx2txt==0.8 -duckduckgo-search==6.3.0 +duckduckgo-search==7.4.2 ebooklib==0.18 elastic-transport==8.17.0 elasticsearch==8.17.0 From 04730ba8c7bbe4027e3f336dbd24a809f86591d6 Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Tue, 18 Feb 2025 04:20:20 +0530 Subject: [PATCH 02/12] (feat:theme)exacting the designs --- frontend/src/Hero.tsx | 2 +- frontend/src/modals/WrapperModal.tsx | 2 +- frontend/src/upload/Upload.tsx | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/frontend/src/Hero.tsx b/frontend/src/Hero.tsx index 9fe965a1..a000ab2e 100644 --- a/frontend/src/Hero.tsx +++ b/frontend/src/Hero.tsx @@ -37,7 +37,7 @@ export default function Hero({ @@ -706,7 +706,7 @@ function Upload({ } }} disabled={isUploadDisabled()} - className={`rounded-3xl px-4 py-2 font-medium ${ + className={`rounded-3xl px-4 py-2 font-medium text-[14px] ${ isUploadDisabled() ? 'cursor-not-allowed bg-gray-300 text-gray-500' : 'cursor-pointer bg-purple-30 text-white hover:bg-purple-40' From 13cd221fe5442c9779c76d775d8ea7e4cf47acdc Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Tue, 18 Feb 2025 14:19:53 +0530 Subject: [PATCH 03/12] (feat:widget) udpate docs --- docs/pages/Extensions/chat-widget.mdx | 1 + docs/pages/_app.mdx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/pages/Extensions/chat-widget.mdx b/docs/pages/Extensions/chat-widget.mdx index 4cc887dc..5eae2fc9 100644 --- a/docs/pages/Extensions/chat-widget.mdx +++ b/docs/pages/Extensions/chat-widget.mdx @@ -143,6 +143,7 @@ The DocsGPT Widget offers a range of customizable properties that allow you to t | **`buttonIcon`** | `string` | `"https://your-icon"` | URL for the icon image used in the widget's launch button. | | **`buttonBg`** | `string` | `"#222327"` | Background color of the widget's launch button. | | **`size`** | `"small" \| "medium"` | `"medium"` | Size of the widget. Options: `"small"` or `"medium"`. Defaults to `"medium"`. | +| **`showSources`** | `boolean` | `false` | Enables displaying source URLs for data fetched within the widget. When set to `true`, the widget will show the original sources of the fetched data. | --- diff --git a/docs/pages/_app.mdx b/docs/pages/_app.mdx index 0111cd96..e7fcf8c5 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 03ee16f5ca2a533cf4926eaa96812946de5c4209 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 18 Feb 2025 09:09:37 +0000 Subject: [PATCH 04/12] Update _app.mdx --- docs/pages/_app.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/pages/_app.mdx b/docs/pages/_app.mdx index e7fcf8c5..817cc517 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 750345d209a0b1529b8c022f75c7272a61b8bbaa Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 18 Feb 2025 14:51:17 +0000 Subject: [PATCH 05/12] feat: architecrure guide --- docs/pages/Guides/Architecture.mdx | 157 +++++++++++++++++++++++++++++ docs/pages/Guides/_meta.json | 4 + 2 files changed, 161 insertions(+) create mode 100644 docs/pages/Guides/Architecture.mdx diff --git a/docs/pages/Guides/Architecture.mdx b/docs/pages/Guides/Architecture.mdx new file mode 100644 index 00000000..247abda6 --- /dev/null +++ b/docs/pages/Guides/Architecture.mdx @@ -0,0 +1,157 @@ +--- +title: Architecture +description: High-level architecture of DocsGPT +--- + +## Introduction + +DocsGPT is designed as a modular and scalable application for knowledge based GenAI system. This document outlines the high-level architecture of DocsGPT, highlighting its key components. + +## High-Level Architecture + +This diagram provides a bird's-eye view of the DocsGPT architecture, illustrating the main components and their interactions. + +```mermaid +flowchart LR + User["User"] --> Frontend["Frontend (React/Vite)"] + Frontend --> Backend["Backend API (Flask)"] + Backend --> LLM["LLM Integration Layer"] & VectorStore["Vector Stores"] & TaskQueue["Task Queue (Celery)"] & Databases["Databases (MongoDB, Redis)"] + LLM -- Cloud APIs / Local Engines --> InferenceEngine["Inference Engine"] + VectorStore -- Document Embeddings --> Indexes[("Indexes")] + TaskQueue -- Asynchronous Tasks --> DocumentIngestion["Document Ingestion"] + + style Frontend fill:#AA00FF,color:#FFFFFF + style Backend fill:#AA00FF,color:#FFFFFF + style LLM fill:#AA00FF,color:#FFFFFF + style TaskQueue fill:#AA00FF,color:#FFFFFF,stroke:#AA00FF + style DocumentIngestion fill:#AA00FF,color:#FFFFFF,stroke:none +``` + +## Component Descriptions + +### 1. Frontend (React/Vite) + +* **Technology:** Built using React and Vite. +* **Responsibility:** This is the user interface of DocsGPT, providing users with an UI to ask questions and receive answers, configure prompts, tools and other settings. It handles user input, displays conversation history, shows sources, and manages settings. +* **Key Features:** + * Clean and responsive UI. + * Simple static client-side rendering. + * Manages conversation state and settings. + * Communicates with the Backend API for data retrieval and processing. + +### 2. Backend API (Flask) + +* **Technology:** Implemented using Flask (Python). +* **Responsibility:** The Backend API serves as the core logic and orchestration layer of DocsGPT. It receives requests from the Frontend, Extensions or API clients, processes them, and coordinates interactions between different components. +* **Key Features:** + * API endpoints for handling user queries, document uploads, and settings configurations. + * Manages the overall application flow and logic. + * Integrates with the LLM Integration Layer, Vector Stores, Task Queue, Tools, Agents and Databases. + * Provides Swagger documentation for API endpoints. + +### 3. LLM Integration Layer (Part of backend) + +* **Technology:** Supports multiple LLM APIs and local engines. +* **Responsibility:** This layer provides an abstraction for interacting with Large Language Models (LLMs). +* **Key Features:** + * Supports LLMs from OpenAI, Google, Anthropic, Groq, HuggingFace Inference API, Azure OpenAI, also compatable with local models like Ollama, LLaMa.cpp, Text Generation Inference (TGI), SGLang, vLLM, Aphrodite, FriendliAI, and LMDeploy. + * Manages API key handling and request formatting and Tool fromatting. + * Offers caching mechanisms to improve response times and reduce API usage. + * Handles streaming responses for a more interactive user experience. + +### 4. Vector Stores (Part of backend) + +* **Technology:** Supports multiple vector databases. +* **Responsibility:** Vector Stores are used to store and retrieve vector embeddings of document chunks. This enables semantic search and retrieval of relevant document snippets in response to user queries. +* **Key Features:** + * Supports vector databases including FAISS, Elasticsearch, Qdrant, Milvus, and LanceDB. + * Provides storage and indexing of high-dimensional vector embeddings. + * Enables editing and updating of vector indexes including specific chunks. + +### 5. Parser Integration Layer (Part of backend) + +* **Technology:** Supports multiple formats for file processing and remote source uploading. +* **Responsibility:** Parser Integration Layer handles uploading, parsing, chunking, embedding, and indexing documents. +* **Key Features:** + * Supports various document formats (PDF, DOCX, TXT, etc.) and remote sources (web URLs, sitemaps). + * Handles document parsing, text chunking, and embedding generation. + * Utilizes Celery for asynchronous processing, ensuring efficient handling of large documents. + +### 6. Task Queue (Celery) + +* **Technology:** Celery with Redis as broker and backend. +* **Responsibility:** Celery handles asynchronous task processing, for long-running operations such as document ingestion and indexing. This ensures that the main application remains responsive and efficient. +* **Key Features:** + * Manages background tasks for document processing and indexing. + * Improves application responsiveness by offloading heavy tasks. + * Enhances scalability and reliability through distributed task processing. + +### 7. Databases (MongoDB, Redis) + +* **Technology:** MongoDB and Redis. +* **Responsibility:** Databases are used for persistent data storage and caching. MongoDB stores structured data such as conversations, documents, user settings, and API keys. Redis is used as a cache, as well as a message broker for Celery. + +## Request Flow Diagram + +This diagram illustrates the sequence of steps involved when a user submits a question to DocsGPT. + +```mermaid +sequenceDiagram + participant User + participant Frontend + participant BackendAPI + participant LLMIntegrationLayer + participant VectorStores + participant InferenceEngine + + User->>Frontend: User asks a question + Frontend->>BackendAPI: API Request (Question) + BackendAPI->>VectorStores: Fetch relevant document chunks (Similarity Search) + VectorStores-->>BackendAPI: Return document chunks + BackendAPI->>LLMIntegrationLayer: Send question and document chunks + LLMIntegrationLayer->>InferenceEngine: LLM API Request (Prompt + Context) + InferenceEngine-->>LLMIntegrationLayer: LLM API Response (Answer) + LLMIntegrationLayer-->>BackendAPI: Return Answer + BackendAPI->>Frontend: API Response (Answer) + Frontend->>User: Display Answer + + Note over Frontend,BackendAPI: Data flow is simplified for clarity +``` + +## Deployment Architecture + +DocsGPT is designed to be deployed using Docker and Kubernetes, here is a qucik overview of a simple k8s deployment. + +```mermaid +graph LR + subgraph Kubernetes Cluster + subgraph Nodes + subgraph Node 1 + FrontendPod[Frontend Pod] + BackendAPIPod[Backend API Pod] + end + subgraph Node 2 + CeleryWorkerPod[Celery Worker Pod] + RedisPod[Redis Pod] + end + subgraph Node 3 + MongoDBPod[MongoDB Pod] + VectorStorePod[Vector Store Pod] + end + end + LoadBalancer[Load Balancer] --> docsgpt-frontend-service[docsgpt-frontend-service] + LoadBalancer --> docsgpt-api-service[docsgpt-api-service] + docsgpt-frontend-service --> FrontendPod + docsgpt-api-service --> BackendAPIPod + BackendAPIPod --> CeleryWorkerPod + BackendAPIPod --> RedisPod + BackendAPIPod --> MongoDBPod + BackendAPIPod --> VectorStorePod + CeleryWorkerPod --> RedisPod + BackendAPIPod --> InferenceEngine[(Inference Engine)] + VectorStorePod --> Indexes[(Indexes)] + MongoDBPod --> Data[(Data)] + RedisPod --> Cache[(Cache)] + end + User[User] --> LoadBalancer +``` diff --git a/docs/pages/Guides/_meta.json b/docs/pages/Guides/_meta.json index 1a331167..a88202d1 100644 --- a/docs/pages/Guides/_meta.json +++ b/docs/pages/Guides/_meta.json @@ -16,5 +16,9 @@ "title": "💭️ Avoiding hallucinations", "href": "/Guides/My-AI-answers-questions-using-external-knowledge", "display": "hidden" + }, + "Architecture": { + "title": "🏗️ Architecture", + "href": "/Guides/Architecture" } } \ No newline at end of file From 0d9fc26119f3f20ce8d0c0d9abe972cdd9362b3d Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Wed, 19 Feb 2025 03:39:15 +0530 Subject: [PATCH 06/12] (refactor): purge unused files --- frontend/src/modals/index.tsx | 50 --------------- frontend/src/preferences/APIKeyModal.tsx | 80 ------------------------ 2 files changed, 130 deletions(-) delete mode 100644 frontend/src/modals/index.tsx delete mode 100644 frontend/src/preferences/APIKeyModal.tsx diff --git a/frontend/src/modals/index.tsx b/frontend/src/modals/index.tsx deleted file mode 100644 index 1dcffd6d..00000000 --- a/frontend/src/modals/index.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import * as React from 'react'; -import { useTranslation } from 'react-i18next'; -interface ModalProps { - handleSubmit: () => void; - isCancellable: boolean; - handleCancel?: () => void; - render: () => JSX.Element; - modalState: string; - isError: boolean; - errorMessage?: string; - textDelete?: boolean; -} - -const Modal = (props: ModalProps) => { - const { t } = useTranslation(); - return ( -
- {props.render()} -
-
- - {props.isCancellable && ( - - )} -
- {props.isError && ( -

- {props.errorMessage} -

- )} -
-
- ); -}; - -export default Modal; diff --git a/frontend/src/preferences/APIKeyModal.tsx b/frontend/src/preferences/APIKeyModal.tsx deleted file mode 100644 index 43698fe1..00000000 --- a/frontend/src/preferences/APIKeyModal.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { useRef, useState } from 'react'; -import { useDispatch, useSelector } from 'react-redux'; -import { ActiveState } from '../models/misc'; -import { selectApiKey, setApiKey } from './preferenceSlice'; -import { useMediaQuery, useOutsideAlerter } from './../hooks'; -import Modal from '../modals'; -import Input from '../components/Input'; - -export default function APIKeyModal({ - modalState, - setModalState, - isCancellable = true, -}: { - modalState: ActiveState; - setModalState: (val: ActiveState) => void; - isCancellable?: boolean; -}) { - const dispatch = useDispatch(); - const apiKey = useSelector(selectApiKey); - const [key, setKey] = useState(apiKey); - const [isError, setIsError] = useState(false); - const modalRef = useRef(null); - const { isMobile } = useMediaQuery(); - - useOutsideAlerter(modalRef, () => { - if (isMobile && modalState === 'ACTIVE') { - setModalState('INACTIVE'); - } - }, [modalState]); - - function handleSubmit() { - if (key.length <= 1) { - setIsError(true); - } else { - dispatch(setApiKey(key)); - setModalState('INACTIVE'); - setIsError(false); - } - } - - function handleCancel() { - setKey(apiKey); - setIsError(false); - setModalState('INACTIVE'); - } - - return ( - { - return ( -
-

OpenAI API Key

-

- Before you can start using DocsGPT we need you to provide an API - key for llm. Currently, we support only OpenAI but soon many more. - You can find it here. -

- setKey(e.target.value)} - > -
- ); - }} - /> - ); -} From 85893037536e8466e5a892318aad87c141893880 Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Wed, 19 Feb 2025 04:01:14 +0530 Subject: [PATCH 07/12] (feat:consitency)modals, dropdowns --- frontend/src/components/Dropdown.tsx | 2 +- frontend/src/components/SourceDropdown.tsx | 2 +- frontend/src/modals/SaveAPIKeyModal.tsx | 52 +++++++-------- frontend/src/preferences/PromptsModal.tsx | 60 ++++++----------- frontend/src/settings/Analytics.tsx | 70 ++++++++++--------- frontend/src/settings/Prompts.tsx | 2 +- frontend/src/upload/Upload.tsx | 78 +++++++++++----------- 7 files changed, 123 insertions(+), 143 deletions(-) diff --git a/frontend/src/components/Dropdown.tsx b/frontend/src/components/Dropdown.tsx index 15923661..5932933e 100644 --- a/frontend/src/components/Dropdown.tsx +++ b/frontend/src/components/Dropdown.tsx @@ -119,7 +119,7 @@ function Dropdown({ {options.map((option: any, index) => (
{ diff --git a/frontend/src/components/SourceDropdown.tsx b/frontend/src/components/SourceDropdown.tsx index f92173a0..080ad320 100644 --- a/frontend/src/components/SourceDropdown.tsx +++ b/frontend/src/components/SourceDropdown.tsx @@ -83,7 +83,7 @@ function SourceDropdown({ return (
{ dispatch(setSelectedDocs(option)); setIsDocsListOpen(false); diff --git a/frontend/src/modals/SaveAPIKeyModal.tsx b/frontend/src/modals/SaveAPIKeyModal.tsx index d91d0c2d..d28d2d0c 100644 --- a/frontend/src/modals/SaveAPIKeyModal.tsx +++ b/frontend/src/modals/SaveAPIKeyModal.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; -import Exit from '../assets/exit.svg'; import { SaveAPIKeyModalProps } from '../models/misc'; +import WrapperModal from './WrapperModal'; export default function SaveAPIKeyModal({ apiKey, @@ -15,38 +15,34 @@ export default function SaveAPIKeyModal({ navigator.clipboard.writeText(apiKey); setIsCopied(true); }; + return ( -
-
- -

- {' '} - {t('modals.saveKey.note')} -

-

- {t('modals.saveKey.disclaimer')} -

-
-
-

API Key

- {apiKey} -
- + +

+ {t('modals.saveKey.note')} +

+

+ {t('modals.saveKey.disclaimer')} +

+
+
+

API Key

+ {apiKey}
-
+ + ); } + diff --git a/frontend/src/preferences/PromptsModal.tsx b/frontend/src/preferences/PromptsModal.tsx index 11cb0685..1a143cbd 100644 --- a/frontend/src/preferences/PromptsModal.tsx +++ b/frontend/src/preferences/PromptsModal.tsx @@ -1,8 +1,8 @@ import { ActiveState } from '../models/misc'; -import Exit from '../assets/exit.svg'; import Input from '../components/Input'; import React from 'react'; import { useTranslation } from 'react-i18next'; +import WrapperModal from '../modals/WrapperModal'; function AddPrompt({ setModalState, @@ -24,19 +24,7 @@ function AddPrompt({ const { t } = useTranslation(); return ( -
- -
+

{t('modals.prompts.addPrompt')}

@@ -50,17 +38,13 @@ function AddPrompt({ setNewPromptName(e.target.value)} /> -
- - {t('modals.prompts.promptName')} - -
- + {t('modals.prompts.promptText')}
@@ -87,7 +71,6 @@ function AddPrompt({ {t('modals.prompts.save')}
-
); } @@ -114,16 +97,7 @@ function EditPrompt({ const { t } = useTranslation(); return ( -
- +

{t('modals.prompts.editPrompt')} @@ -271,15 +245,19 @@ export default function PromptsModal({ } else { view = <>; } - return ( -

{ + setModalState('INACTIVE'); + if (type === 'ADD') { + setNewPromptName(''); + setNewPromptContent(''); + } + }} + className="sm:w-[512px] mt-24" > -
- {view} -
-
- ); + {view} + + ) : null; } diff --git a/frontend/src/settings/Analytics.tsx b/frontend/src/settings/Analytics.tsx index 4d390495..53538833 100644 --- a/frontend/src/settings/Analytics.tsx +++ b/frontend/src/settings/Analytics.tsx @@ -92,8 +92,10 @@ export default function Analytics() { const [loadingMessages, setLoadingMessages] = useLoaderState(true); const [loadingTokens, setLoadingTokens] = useLoaderState(true); const [loadingFeedback, setLoadingFeedback] = useLoaderState(true); + const [loadingChatbots, setLoadingChatbots] = useLoaderState(true); const fetchChatbots = async () => { + setLoadingChatbots(true); try { const response = await userService.getAPIKeys(); if (!response.ok) { @@ -103,6 +105,8 @@ export default function Analytics() { setChatbots(chatbots); } catch (error) { console.error(error); + } finally { + setLoadingChatbots(false); } }; @@ -188,37 +192,41 @@ export default function Analytics() { return (
-
-

- {t('settings.analytics.filterByChatbot')} -

- ({ - label: chatbot.name, - value: chatbot.id, - })), - { label: t('settings.analytics.none'), value: '' }, - ]} - placeholder={t('settings.analytics.selectChatbot')} - onSelect={(chatbot: { label: string; value: string }) => { - setSelectedChatbot( - chatbots.find((item) => item.id === chatbot.value), - ); - }} - selectedValue={ - (selectedChatbot && { - label: selectedChatbot.name, - value: selectedChatbot.id, - }) || - null - } - rounded="3xl" - border="border" - borderColor="gray-700" - /> -
+ {loadingChatbots ? ( + + ) : ( +
+

+ {t('settings.analytics.filterByChatbot')} +

+ ({ + label: chatbot.name, + value: chatbot.id, + })), + { label: t('settings.analytics.none'), value: '' }, + ]} + placeholder={t('settings.analytics.selectChatbot')} + onSelect={(chatbot: { label: string; value: string }) => { + setSelectedChatbot( + chatbots.find((item) => item.id === chatbot.value), + ); + }} + selectedValue={ + (selectedChatbot && { + label: selectedChatbot.name, + value: selectedChatbot.id, + }) || + null + } + rounded="3xl" + border="border" + borderColor="gray-700" + /> +
+ )} {/* Messages Analytics */}
diff --git a/frontend/src/settings/Prompts.tsx b/frontend/src/settings/Prompts.tsx index 611b0b90..ed1d82d7 100644 --- a/frontend/src/settings/Prompts.tsx +++ b/frontend/src/settings/Prompts.tsx @@ -168,7 +168,7 @@ export default function Prompts({ />
- -
-
- )} +
+

+ {t('modals.uploadDoc.select')} +

+
+ + +
+
+)} {activeTab === 'file' && ( <> setDocName(e.target.value)} borderVariant="thin" - > -
- - {t('modals.uploadDoc.name')} - -
-
+ placeholder={t('modals.uploadDoc.name')} + label={t('modals.uploadDoc.name')} + required={true} + /> +
{t('modals.uploadDoc.choose')} @@ -649,7 +647,7 @@ function Upload({ {activeTab === 'remote' && ( <> opt.value === ingestor.type) || null @@ -664,7 +662,7 @@ function Upload({ setRemoteName(e.target.value)} borderVariant="thin" From 28489d244c5e4be9562bf35708c98bb83036ecdb Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Wed, 19 Feb 2025 04:10:14 +0530 Subject: [PATCH 08/12] (feat:input) consistent colors --- frontend/src/components/Input.tsx | 2 +- frontend/src/modals/WrapperModal.tsx | 21 ++++++++++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/Input.tsx b/frontend/src/components/Input.tsx index f224e2ba..e703ff14 100644 --- a/frontend/src/components/Input.tsx +++ b/frontend/src/components/Input.tsx @@ -47,7 +47,7 @@ const Input = ({ {label && (
- + {label} {required && ( diff --git a/frontend/src/modals/WrapperModal.tsx b/frontend/src/modals/WrapperModal.tsx index c2b22a90..eee205f0 100644 --- a/frontend/src/modals/WrapperModal.tsx +++ b/frontend/src/modals/WrapperModal.tsx @@ -1,12 +1,21 @@ import React, { useEffect, useRef } from 'react'; import Exit from '../assets/exit.svg'; -import { WrapperModalPropsType } from './types'; + +interface WrapperModalPropsType { + children: React.ReactNode; + close: () => void; + isPerformingTask?: boolean; + className?: string; + contentClassName?: string; +} export default function WrapperModal({ children, close, - isPerformingTask, + isPerformingTask = false, + className = 'sm:w-[512px]', // Default width, but can be overridden + contentClassName = 'p-8', // Default padding, but can be overridden }: WrapperModalPropsType) { const modalRef = useRef(null); @@ -40,17 +49,19 @@ export default function WrapperModal({
{!isPerformingTask && ( )} - {children} +
+ {children} +
); From 4e948d8bff017490b088fac5e50d363832ff4173 Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Wed, 19 Feb 2025 04:15:31 +0530 Subject: [PATCH 09/12] (refactor:tools modal) reuse wrapper modal --- frontend/src/modals/AddToolModal.tsx | 31 ++----- frontend/src/modals/ConfigToolModal.tsx | 114 +++++++++++------------- 2 files changed, 60 insertions(+), 85 deletions(-) diff --git a/frontend/src/modals/AddToolModal.tsx b/frontend/src/modals/AddToolModal.tsx index ba555df4..d48882a1 100644 --- a/frontend/src/modals/AddToolModal.tsx +++ b/frontend/src/modals/AddToolModal.tsx @@ -7,6 +7,7 @@ import { useOutsideAlerter } from '../hooks'; import { ActiveState } from '../models/misc'; import ConfigToolModal from './ConfigToolModal'; import { AvailableToolType } from './types'; +import WrapperComponent from './WrapperModal'; export default function AddToolModal({ message, @@ -88,28 +89,12 @@ export default function AddToolModal({ return ( <> -
-
setModalState('INACTIVE')} + className="h-[85vh] w-[90vw] md:w-[75vw]" > -
- +

{t('settings.tools.selectToolSetup')} @@ -153,8 +138,8 @@ export default function AddToolModal({

-
-
+ + )} void; + tool: AvailableToolType | null; + getUserTools: () => void; +} + export default function ConfigToolModal({ modalState, setModalState, tool, getUserTools, -}: { - modalState: ActiveState; - setModalState: (state: ActiveState) => void; - tool: AvailableToolType | null; - getUserTools: () => void; -}) { +}: ConfigToolModalProps) { const { t } = useTranslation(); const [authKey, setAuthKey] = React.useState(''); @@ -36,63 +38,51 @@ export default function ConfigToolModal({ getUserTools(); }); }; + + // Only render when modal is active + if (modalState !== 'ACTIVE') return null; + return ( -
setModalState('INACTIVE')} + className="sm:w-[512px]" + contentClassName="" > -
-
- -
-

- {t('modals.configTool.title')} -

-

- {t('modals.configTool.type')}:{' '} - {tool?.name} -

-
- - {t('modals.configTool.apiKeyLabel')} - - setAuthKey(e.target.value)} - borderVariant="thin" - placeholder={t('modals.configTool.apiKeyPlaceholder')} - > -
-
- - -
-
+
+

+ {t('modals.configTool.title')} +

+

+ {t('modals.configTool.type')}:{' '} + {tool?.name} +

+
+ setAuthKey(e.target.value)} + borderVariant="thin" + placeholder={t('modals.configTool.apiKeyPlaceholder')} + label={t('modals.configTool.apiKeyLabel')} + />
-
-
+
+ + +
+
+ ); } From 3aa85bb51cde9e9d8f60463bf3a15600864dee30 Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Wed, 19 Feb 2025 04:35:33 +0530 Subject: [PATCH 10/12] (refactor:modals) reuse wrapper modal --- frontend/src/modals/AddActionModal.tsx | 106 ++++++++++------------ frontend/src/modals/ConfigToolModal.tsx | 4 +- frontend/src/modals/CreateAPIKeyModal.tsx | 2 +- frontend/src/modals/WrapperModal.tsx | 8 +- 4 files changed, 52 insertions(+), 68 deletions(-) diff --git a/frontend/src/modals/AddActionModal.tsx b/frontend/src/modals/AddActionModal.tsx index 6ff88ae6..a2160146 100644 --- a/frontend/src/modals/AddActionModal.tsx +++ b/frontend/src/modals/AddActionModal.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; -import Exit from '../assets/exit.svg'; +import WrapperModal from './WrapperModal'; import Input from '../components/Input'; import { ActiveState } from '../models/misc'; @@ -35,67 +35,53 @@ export default function AddActionModal({ setModalState('INACTIVE'); }; + // Only render when modal is active + if (modalState !== 'ACTIVE') return null; + return ( -
setModalState('INACTIVE')} + className="sm:w-[512px]" > -
-
- -
-

- New Action -

-
- - Action Name - - setActionName(e.target.value)} - borderVariant="thin" - placeholder={'Enter name'} - /> -

- Use only letters, numbers, underscores, and hyphens (e.g., - `get_user_data`, `send-report`). -

- {functionNameError && ( -

- Invalid function name format. Use only letters, numbers, - underscores, and hyphens. -

- )} -
-
- - -
-
+
+

+ New Action +

+
+ setActionName(e.target.value)} + borderVariant="thin" + placeholder="Enter name" + label="Action Name" + /> +

+ Use only letters, numbers, underscores, and hyphens (e.g., + `get_user_data`, `send-report`). +

+ {functionNameError && ( +

+ Invalid function name format. Use only letters, numbers, + underscores, and hyphens. +

+ )}
-
-
+
+ + +
+
+ ); } diff --git a/frontend/src/modals/ConfigToolModal.tsx b/frontend/src/modals/ConfigToolModal.tsx index 4a582a49..d8585899 100644 --- a/frontend/src/modals/ConfigToolModal.tsx +++ b/frontend/src/modals/ConfigToolModal.tsx @@ -45,10 +45,8 @@ export default function ConfigToolModal({ return ( setModalState('INACTIVE')} - className="sm:w-[512px]" - contentClassName="" > -
+

{t('modals.configTool.title')}

diff --git a/frontend/src/modals/CreateAPIKeyModal.tsx b/frontend/src/modals/CreateAPIKeyModal.tsx index 5c8c75b8..36ec59a8 100644 --- a/frontend/src/modals/CreateAPIKeyModal.tsx +++ b/frontend/src/modals/CreateAPIKeyModal.tsx @@ -73,7 +73,7 @@ export default function CreateAPIKeyModal({ handleFetchPrompts(); }, []); return ( - +
{t('modals.createAPIKey.label')} diff --git a/frontend/src/modals/WrapperModal.tsx b/frontend/src/modals/WrapperModal.tsx index eee205f0..b945a60a 100644 --- a/frontend/src/modals/WrapperModal.tsx +++ b/frontend/src/modals/WrapperModal.tsx @@ -14,8 +14,8 @@ export default function WrapperModal({ children, close, isPerformingTask = false, - className = 'sm:w-[512px]', // Default width, but can be overridden - contentClassName = 'p-8', // Default padding, but can be overridden + className = '', // Default width, but can be overridden + contentClassName = '', // Default padding, but can be overridden }: WrapperModalPropsType) { const modalRef = useRef(null); @@ -49,7 +49,7 @@ export default function WrapperModal({
{!isPerformingTask && ( )} -
+
{children}
From cc4acb8766e17c75d811071a1f4c6929101b0085 Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Wed, 19 Feb 2025 04:38:49 +0530 Subject: [PATCH 11/12] (feat:createAPIModal): UI inconsistency --- frontend/src/modals/CreateAPIKeyModal.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/frontend/src/modals/CreateAPIKeyModal.tsx b/frontend/src/modals/CreateAPIKeyModal.tsx index 36ec59a8..5495f520 100644 --- a/frontend/src/modals/CreateAPIKeyModal.tsx +++ b/frontend/src/modals/CreateAPIKeyModal.tsx @@ -80,14 +80,13 @@ export default function CreateAPIKeyModal({
- - {t('modals.createAPIKey.apiKeyName')} - setAPIKeyName(e.target.value)} + borderVariant='thin' >
From 877b44ec0a6aa5268b95f4ca1f775e76ca640f85 Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Wed, 19 Feb 2025 04:49:22 +0530 Subject: [PATCH 12/12] (lint) --- frontend/src/modals/AddToolModal.tsx | 3 +- frontend/src/modals/ConfigToolModal.tsx | 4 +- frontend/src/modals/CreateAPIKeyModal.tsx | 4 +- frontend/src/modals/SaveAPIKeyModal.tsx | 9 ++- frontend/src/modals/WrapperModal.tsx | 4 +- frontend/src/preferences/PromptsModal.tsx | 90 +++++++++++------------ frontend/src/upload/Upload.tsx | 58 +++++++-------- 7 files changed, 85 insertions(+), 87 deletions(-) diff --git a/frontend/src/modals/AddToolModal.tsx b/frontend/src/modals/AddToolModal.tsx index d48882a1..c11a5043 100644 --- a/frontend/src/modals/AddToolModal.tsx +++ b/frontend/src/modals/AddToolModal.tsx @@ -2,7 +2,6 @@ import React, { useRef } from 'react'; import { useTranslation } from 'react-i18next'; import userService from '../api/services/userService'; -import Exit from '../assets/exit.svg'; import { useOutsideAlerter } from '../hooks'; import { ActiveState } from '../models/misc'; import ConfigToolModal from './ConfigToolModal'; @@ -90,7 +89,7 @@ export default function AddToolModal({ return ( <> {modalState === 'ACTIVE' && ( - setModalState('INACTIVE')} className="h-[85vh] w-[90vw] md:w-[75vw]" > diff --git a/frontend/src/modals/ConfigToolModal.tsx b/frontend/src/modals/ConfigToolModal.tsx index d8585899..04553677 100644 --- a/frontend/src/modals/ConfigToolModal.tsx +++ b/frontend/src/modals/ConfigToolModal.tsx @@ -43,9 +43,7 @@ export default function ConfigToolModal({ if (modalState !== 'ACTIVE') return null; return ( - setModalState('INACTIVE')} - > + setModalState('INACTIVE')}>

{t('modals.configTool.title')} diff --git a/frontend/src/modals/CreateAPIKeyModal.tsx b/frontend/src/modals/CreateAPIKeyModal.tsx index 5495f520..128bdff6 100644 --- a/frontend/src/modals/CreateAPIKeyModal.tsx +++ b/frontend/src/modals/CreateAPIKeyModal.tsx @@ -73,7 +73,7 @@ export default function CreateAPIKeyModal({ handleFetchPrompts(); }, []); return ( - +
{t('modals.createAPIKey.label')} @@ -86,7 +86,7 @@ export default function CreateAPIKeyModal({ value={APIKeyName} label={t('modals.createAPIKey.apiKeyName')} onChange={(e) => setAPIKeyName(e.target.value)} - borderVariant='thin' + borderVariant="thin" >
diff --git a/frontend/src/modals/SaveAPIKeyModal.tsx b/frontend/src/modals/SaveAPIKeyModal.tsx index d28d2d0c..abe862cb 100644 --- a/frontend/src/modals/SaveAPIKeyModal.tsx +++ b/frontend/src/modals/SaveAPIKeyModal.tsx @@ -26,8 +26,12 @@ export default function SaveAPIKeyModal({

-

API Key

- {apiKey} +

+ API Key +

+ + {apiKey} +
)} -
- {children} -
+
{children}
); diff --git a/frontend/src/preferences/PromptsModal.tsx b/frontend/src/preferences/PromptsModal.tsx index 1a143cbd..f2512210 100644 --- a/frontend/src/preferences/PromptsModal.tsx +++ b/frontend/src/preferences/PromptsModal.tsx @@ -25,52 +25,52 @@ function AddPrompt({ return (
-

- {t('modals.prompts.addPrompt')} -

-

- {t('modals.prompts.addDescription')} -

-
- - setNewPromptName(e.target.value)} - /> -
- - {t('modals.prompts.promptText')} - -
- - -
-
- +

+ {t('modals.prompts.addPrompt')} +

+

+ {t('modals.prompts.addDescription')} +

+
+ + setNewPromptName(e.target.value)} + /> +
+ + {t('modals.prompts.promptText')} +
+ + +
+
+ +
); } diff --git a/frontend/src/upload/Upload.tsx b/frontend/src/upload/Upload.tsx index c8c9ef6d..f97473d5 100644 --- a/frontend/src/upload/Upload.tsx +++ b/frontend/src/upload/Upload.tsx @@ -571,34 +571,34 @@ function Upload({ {t('modals.uploadDoc.label')}

{!activeTab && ( -
-

- {t('modals.uploadDoc.select')} -

-
- - -
-
-)} +
+

+ {t('modals.uploadDoc.select')} +

+
+ + +
+
+ )} {activeTab === 'file' && ( <> @@ -612,7 +612,7 @@ function Upload({ label={t('modals.uploadDoc.name')} required={true} /> -
+
{t('modals.uploadDoc.choose')}