mirror of
https://github.com/arc53/DocsGPT.git
synced 2025-11-29 08:33:20 +00:00
Merge branch 'main' of https://github.com/arc53/DocsGPT
This commit is contained in:
@@ -1,15 +1,30 @@
|
||||
import { Routes, Route } from 'react-router-dom';
|
||||
import Navigation from './Navigation';
|
||||
import Conversation from './conversation/Conversation';
|
||||
import About from './About';
|
||||
import PageNotFound from './PageNotFound';
|
||||
import { useMediaQuery } from './hooks';
|
||||
import { useState } from 'react';
|
||||
import Setting from './settings';
|
||||
import './locale/i18n';
|
||||
import { Outlet } from 'react-router-dom';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { Outlet, Route, Routes } from 'react-router-dom';
|
||||
|
||||
import About from './About';
|
||||
import Spinner from './components/Spinner';
|
||||
import Conversation from './conversation/Conversation';
|
||||
import { SharedConversation } from './conversation/SharedConversation';
|
||||
import { useDarkTheme } from './hooks';
|
||||
import { useDarkTheme, useMediaQuery } from './hooks';
|
||||
import useTokenAuth from './hooks/useTokenAuth';
|
||||
import Navigation from './Navigation';
|
||||
import PageNotFound from './PageNotFound';
|
||||
import Setting from './settings';
|
||||
|
||||
function AuthWrapper({ children }: { children: React.ReactNode }) {
|
||||
const { isAuthLoading } = useTokenAuth();
|
||||
|
||||
if (isAuthLoading) {
|
||||
return (
|
||||
<div className="h-screen flex items-center justify-center">
|
||||
<Spinner />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
function MainLayout() {
|
||||
const { isMobile } = useMediaQuery();
|
||||
@@ -39,7 +54,13 @@ export default function App() {
|
||||
return (
|
||||
<div className="h-full relative overflow-auto">
|
||||
<Routes>
|
||||
<Route element={<MainLayout />}>
|
||||
<Route
|
||||
element={
|
||||
<AuthWrapper>
|
||||
<MainLayout />
|
||||
</AuthWrapper>
|
||||
}
|
||||
>
|
||||
<Route index element={<Conversation />} />
|
||||
<Route path="/about" element={<About />} />
|
||||
<Route path="/settings" element={<Setting />} />
|
||||
|
||||
@@ -2,28 +2,35 @@ import { useEffect, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { NavLink, useNavigate } from 'react-router-dom';
|
||||
|
||||
import conversationService from './api/services/conversationService';
|
||||
import userService from './api/services/userService';
|
||||
import Add from './assets/add.svg';
|
||||
import openNewChat from './assets/openNewChat.svg';
|
||||
import Hamburger from './assets/hamburger.svg';
|
||||
import DocsGPT3 from './assets/cute_docsgpt3.svg';
|
||||
import Discord from './assets/discord.svg';
|
||||
import Expand from './assets/expand.svg';
|
||||
import Github from './assets/github.svg';
|
||||
import Hamburger from './assets/hamburger.svg';
|
||||
import openNewChat from './assets/openNewChat.svg';
|
||||
import SettingGear from './assets/settingGear.svg';
|
||||
import SpinnerDark from './assets/spinner-dark.svg';
|
||||
import Spinner from './assets/spinner.svg';
|
||||
import Twitter from './assets/TwitterX.svg';
|
||||
import UploadIcon from './assets/upload.svg';
|
||||
import Help from './components/Help';
|
||||
import SourceDropdown from './components/SourceDropdown';
|
||||
import {
|
||||
handleAbort,
|
||||
selectQueries,
|
||||
setConversation,
|
||||
updateConversationId,
|
||||
handleAbort,
|
||||
} from './conversation/conversationSlice';
|
||||
import ConversationTile from './conversation/ConversationTile';
|
||||
import { useDarkTheme, useMediaQuery } from './hooks';
|
||||
import useDefaultDocument from './hooks/useDefaultDocument';
|
||||
import useTokenAuth from './hooks/useTokenAuth';
|
||||
import DeleteConvModal from './modals/DeleteConvModal';
|
||||
import JWTModal from './modals/JWTModal';
|
||||
import { ActiveState, Doc } from './models/misc';
|
||||
import { getConversations, getDocs } from './preferences/preferenceApi';
|
||||
import {
|
||||
@@ -31,20 +38,17 @@ import {
|
||||
selectConversationId,
|
||||
selectConversations,
|
||||
selectModalStateDeleteConv,
|
||||
selectPaginatedDocuments,
|
||||
selectSelectedDocs,
|
||||
selectSourceDocs,
|
||||
selectPaginatedDocuments,
|
||||
selectToken,
|
||||
setConversations,
|
||||
setModalStateDeleteConv,
|
||||
setPaginatedDocuments,
|
||||
setSelectedDocs,
|
||||
setSourceDocs,
|
||||
setPaginatedDocuments,
|
||||
} from './preferences/preferenceSlice';
|
||||
import Spinner from './assets/spinner.svg';
|
||||
import SpinnerDark from './assets/spinner-dark.svg';
|
||||
import { selectQueries } from './conversation/conversationSlice';
|
||||
import Upload from './upload/Upload';
|
||||
import Help from './components/Help';
|
||||
|
||||
interface NavigationProps {
|
||||
navOpen: boolean;
|
||||
@@ -53,6 +57,7 @@ interface NavigationProps {
|
||||
|
||||
export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
|
||||
const dispatch = useDispatch();
|
||||
const token = useSelector(selectToken);
|
||||
const queries = useSelector(selectQueries);
|
||||
const docs = useSelector(selectSourceDocs);
|
||||
const selectedDocs = useSelector(selectSelectedDocs);
|
||||
@@ -68,6 +73,8 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
|
||||
const { t } = useTranslation();
|
||||
const isApiKeySet = useSelector(selectApiKeyStatus);
|
||||
|
||||
const { showTokenModal, handleTokenSubmit } = useTokenAuth();
|
||||
|
||||
const [uploadModalState, setUploadModalState] =
|
||||
useState<ActiveState>('INACTIVE');
|
||||
|
||||
@@ -86,7 +93,7 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
|
||||
|
||||
async function fetchConversations() {
|
||||
dispatch(setConversations({ ...conversations, loading: true }));
|
||||
return await getConversations()
|
||||
return await getConversations(token)
|
||||
.then((fetchedConversations) => {
|
||||
dispatch(setConversations(fetchedConversations));
|
||||
})
|
||||
@@ -99,7 +106,7 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
|
||||
const handleDeleteAllConversations = () => {
|
||||
setIsDeletingConversation(true);
|
||||
conversationService
|
||||
.deleteAll()
|
||||
.deleteAll(token)
|
||||
.then(() => {
|
||||
fetchConversations();
|
||||
})
|
||||
@@ -109,7 +116,7 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
|
||||
const handleDeleteConversation = (id: string) => {
|
||||
setIsDeletingConversation(true);
|
||||
conversationService
|
||||
.delete(id, {})
|
||||
.delete(id, {}, token)
|
||||
.then(() => {
|
||||
fetchConversations();
|
||||
resetConversation();
|
||||
@@ -119,9 +126,9 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
|
||||
|
||||
const handleDeleteClick = (doc: Doc) => {
|
||||
userService
|
||||
.deletePath(doc.id ?? '')
|
||||
.deletePath(doc.id ?? '', token)
|
||||
.then(() => {
|
||||
return getDocs();
|
||||
return getDocs(token);
|
||||
})
|
||||
.then((updatedDocs) => {
|
||||
dispatch(setSourceDocs(updatedDocs));
|
||||
@@ -145,7 +152,7 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
|
||||
|
||||
const handleConversationClick = (index: string) => {
|
||||
conversationService
|
||||
.getConversation(index)
|
||||
.getConversation(index, token)
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
navigate('/');
|
||||
@@ -177,7 +184,7 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
|
||||
id: string;
|
||||
}) {
|
||||
await conversationService
|
||||
.update(updatedConversation)
|
||||
.update(updatedConversation, token)
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
if (data) {
|
||||
@@ -197,8 +204,8 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
|
||||
useEffect(() => {
|
||||
setNavOpen(!isMobile);
|
||||
}, [isMobile]);
|
||||
useDefaultDocument();
|
||||
|
||||
useDefaultDocument();
|
||||
return (
|
||||
<>
|
||||
{!navOpen && (
|
||||
@@ -472,6 +479,10 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
|
||||
close={() => setUploadModalState('INACTIVE')}
|
||||
></Upload>
|
||||
)}
|
||||
<JWTModal
|
||||
modalState={showTokenModal ? 'ACTIVE' : 'INACTIVE'}
|
||||
handleTokenSubmit={handleTokenSubmit}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,14 +4,24 @@ const defaultHeaders = {
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
|
||||
const getHeaders = (token: string | null, customHeaders = {}): HeadersInit => {
|
||||
return {
|
||||
...defaultHeaders,
|
||||
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
||||
...customHeaders,
|
||||
};
|
||||
};
|
||||
|
||||
const apiClient = {
|
||||
get: (url: string, headers = {}, signal?: AbortSignal): Promise<any> =>
|
||||
get: (
|
||||
url: string,
|
||||
token: string | null,
|
||||
headers = {},
|
||||
signal?: AbortSignal,
|
||||
): Promise<any> =>
|
||||
fetch(`${baseURL}${url}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
...defaultHeaders,
|
||||
...headers,
|
||||
},
|
||||
headers: getHeaders(token, headers),
|
||||
signal,
|
||||
}).then((response) => {
|
||||
return response;
|
||||
@@ -20,15 +30,13 @@ const apiClient = {
|
||||
post: (
|
||||
url: string,
|
||||
data: any,
|
||||
token: string | null,
|
||||
headers = {},
|
||||
signal?: AbortSignal,
|
||||
): Promise<any> =>
|
||||
fetch(`${baseURL}${url}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
...defaultHeaders,
|
||||
...headers,
|
||||
},
|
||||
headers: getHeaders(token, headers),
|
||||
body: JSON.stringify(data),
|
||||
signal,
|
||||
}).then((response) => {
|
||||
@@ -38,28 +46,28 @@ const apiClient = {
|
||||
put: (
|
||||
url: string,
|
||||
data: any,
|
||||
token: string | null,
|
||||
headers = {},
|
||||
signal?: AbortSignal,
|
||||
): Promise<any> =>
|
||||
fetch(`${baseURL}${url}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
...defaultHeaders,
|
||||
...headers,
|
||||
},
|
||||
headers: getHeaders(token, headers),
|
||||
body: JSON.stringify(data),
|
||||
signal,
|
||||
}).then((response) => {
|
||||
return response;
|
||||
}),
|
||||
|
||||
delete: (url: string, headers = {}, signal?: AbortSignal): Promise<any> =>
|
||||
delete: (
|
||||
url: string,
|
||||
token: string | null,
|
||||
headers = {},
|
||||
signal?: AbortSignal,
|
||||
): Promise<any> =>
|
||||
fetch(`${baseURL}${url}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
...defaultHeaders,
|
||||
...headers,
|
||||
},
|
||||
headers: getHeaders(token, headers),
|
||||
signal,
|
||||
}).then((response) => {
|
||||
return response;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
const endpoints = {
|
||||
USER: {
|
||||
CONFIG: '/api/config',
|
||||
NEW_TOKEN: '/api/generate_token',
|
||||
DOCS: '/api/sources',
|
||||
DOCS_CHECK: '/api/docs_check',
|
||||
DOCS_PAGINATED: '/api/sources/paginated',
|
||||
|
||||
@@ -2,31 +2,58 @@ import apiClient from '../client';
|
||||
import endpoints from '../endpoints';
|
||||
|
||||
const conversationService = {
|
||||
answer: (data: any, signal: AbortSignal): Promise<any> =>
|
||||
apiClient.post(endpoints.CONVERSATION.ANSWER, data, {}, signal),
|
||||
answerStream: (data: any, signal: AbortSignal): Promise<any> =>
|
||||
apiClient.post(endpoints.CONVERSATION.ANSWER_STREAMING, data, {}, signal),
|
||||
search: (data: any): Promise<any> =>
|
||||
apiClient.post(endpoints.CONVERSATION.SEARCH, data),
|
||||
feedback: (data: any): Promise<any> =>
|
||||
apiClient.post(endpoints.CONVERSATION.FEEDBACK, data),
|
||||
getConversation: (id: string): Promise<any> =>
|
||||
apiClient.get(endpoints.CONVERSATION.CONVERSATION(id)),
|
||||
getConversations: (): Promise<any> =>
|
||||
apiClient.get(endpoints.CONVERSATION.CONVERSATIONS),
|
||||
shareConversation: (isPromptable: boolean, data: any): Promise<any> =>
|
||||
answer: (
|
||||
data: any,
|
||||
token: string | null,
|
||||
signal: AbortSignal,
|
||||
): Promise<any> =>
|
||||
apiClient.post(endpoints.CONVERSATION.ANSWER, data, token, {}, signal),
|
||||
answerStream: (
|
||||
data: any,
|
||||
token: string | null,
|
||||
signal: AbortSignal,
|
||||
): Promise<any> =>
|
||||
apiClient.post(
|
||||
endpoints.CONVERSATION.ANSWER_STREAMING,
|
||||
data,
|
||||
token,
|
||||
{},
|
||||
signal,
|
||||
),
|
||||
search: (data: any, token: string | null): Promise<any> =>
|
||||
apiClient.post(endpoints.CONVERSATION.SEARCH, data, token, {}),
|
||||
feedback: (data: any, token: string | null): Promise<any> =>
|
||||
apiClient.post(endpoints.CONVERSATION.FEEDBACK, data, token, {}),
|
||||
getConversation: (id: string, token: string | null): Promise<any> =>
|
||||
apiClient.get(endpoints.CONVERSATION.CONVERSATION(id), token, {}),
|
||||
getConversations: (token: string | null): Promise<any> =>
|
||||
apiClient.get(endpoints.CONVERSATION.CONVERSATIONS, token, {}),
|
||||
shareConversation: (
|
||||
isPromptable: boolean,
|
||||
data: any,
|
||||
token: string | null,
|
||||
): Promise<any> =>
|
||||
apiClient.post(
|
||||
endpoints.CONVERSATION.SHARE_CONVERSATION(isPromptable),
|
||||
data,
|
||||
token,
|
||||
{},
|
||||
),
|
||||
getSharedConversation: (identifier: string): Promise<any> =>
|
||||
apiClient.get(endpoints.CONVERSATION.SHARED_CONVERSATION(identifier)),
|
||||
delete: (id: string, data: any): Promise<any> =>
|
||||
apiClient.post(endpoints.CONVERSATION.DELETE(id), data),
|
||||
deleteAll: (): Promise<any> =>
|
||||
apiClient.get(endpoints.CONVERSATION.DELETE_ALL),
|
||||
update: (data: any): Promise<any> =>
|
||||
apiClient.post(endpoints.CONVERSATION.UPDATE, data),
|
||||
getSharedConversation: (
|
||||
identifier: string,
|
||||
token: string | null,
|
||||
): Promise<any> =>
|
||||
apiClient.get(
|
||||
endpoints.CONVERSATION.SHARED_CONVERSATION(identifier),
|
||||
token,
|
||||
{},
|
||||
),
|
||||
delete: (id: string, data: any, token: string | null): Promise<any> =>
|
||||
apiClient.post(endpoints.CONVERSATION.DELETE(id), data, token, {}),
|
||||
deleteAll: (token: string | null): Promise<any> =>
|
||||
apiClient.get(endpoints.CONVERSATION.DELETE_ALL, token, {}),
|
||||
update: (data: any, token: string | null): Promise<any> =>
|
||||
apiClient.post(endpoints.CONVERSATION.UPDATE, data, token, {}),
|
||||
};
|
||||
|
||||
export default conversationService;
|
||||
|
||||
@@ -2,63 +2,74 @@ import apiClient from '../client';
|
||||
import endpoints from '../endpoints';
|
||||
|
||||
const userService = {
|
||||
getDocs: (): Promise<any> => apiClient.get(`${endpoints.USER.DOCS}`),
|
||||
getDocsWithPagination: (query: string): Promise<any> =>
|
||||
apiClient.get(`${endpoints.USER.DOCS_PAGINATED}?${query}`),
|
||||
checkDocs: (data: any): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.DOCS_CHECK, data),
|
||||
getAPIKeys: (): Promise<any> => apiClient.get(endpoints.USER.API_KEYS),
|
||||
createAPIKey: (data: any): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.CREATE_API_KEY, data),
|
||||
deleteAPIKey: (data: any): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.DELETE_API_KEY, data),
|
||||
getPrompts: (): Promise<any> => apiClient.get(endpoints.USER.PROMPTS),
|
||||
createPrompt: (data: any): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.CREATE_PROMPT, data),
|
||||
deletePrompt: (data: any): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.DELETE_PROMPT, data),
|
||||
updatePrompt: (data: any): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.UPDATE_PROMPT, data),
|
||||
getSinglePrompt: (id: string): Promise<any> =>
|
||||
apiClient.get(endpoints.USER.SINGLE_PROMPT(id)),
|
||||
deletePath: (docPath: string): Promise<any> =>
|
||||
apiClient.get(endpoints.USER.DELETE_PATH(docPath)),
|
||||
getTaskStatus: (task_id: string): Promise<any> =>
|
||||
apiClient.get(endpoints.USER.TASK_STATUS(task_id)),
|
||||
getMessageAnalytics: (data: any): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.MESSAGE_ANALYTICS, data),
|
||||
getTokenAnalytics: (data: any): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.TOKEN_ANALYTICS, data),
|
||||
getFeedbackAnalytics: (data: any): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.FEEDBACK_ANALYTICS, data),
|
||||
getLogs: (data: any): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.LOGS, data),
|
||||
manageSync: (data: any): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.MANAGE_SYNC, data),
|
||||
getAvailableTools: (): Promise<any> =>
|
||||
apiClient.get(endpoints.USER.GET_AVAILABLE_TOOLS),
|
||||
getUserTools: (): Promise<any> =>
|
||||
apiClient.get(endpoints.USER.GET_USER_TOOLS),
|
||||
createTool: (data: any): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.CREATE_TOOL, data),
|
||||
updateToolStatus: (data: any): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.UPDATE_TOOL_STATUS, data),
|
||||
updateTool: (data: any): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.UPDATE_TOOL, data),
|
||||
deleteTool: (data: any): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.DELETE_TOOL, data),
|
||||
getConfig: (): Promise<any> => apiClient.get(endpoints.USER.CONFIG, null),
|
||||
getNewToken: (): Promise<any> =>
|
||||
apiClient.get(endpoints.USER.NEW_TOKEN, null),
|
||||
getDocs: (token: string | null): Promise<any> =>
|
||||
apiClient.get(`${endpoints.USER.DOCS}`, token),
|
||||
getDocsWithPagination: (query: string, token: string | null): Promise<any> =>
|
||||
apiClient.get(`${endpoints.USER.DOCS_PAGINATED}?${query}`, token),
|
||||
checkDocs: (data: any, token: string | null): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.DOCS_CHECK, data, token),
|
||||
getAPIKeys: (token: string | null): Promise<any> =>
|
||||
apiClient.get(endpoints.USER.API_KEYS, token),
|
||||
createAPIKey: (data: any, token: string | null): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.CREATE_API_KEY, data, token),
|
||||
deleteAPIKey: (data: any, token: string | null): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.DELETE_API_KEY, data, token),
|
||||
getPrompts: (token: string | null): Promise<any> =>
|
||||
apiClient.get(endpoints.USER.PROMPTS, token),
|
||||
createPrompt: (data: any, token: string | null): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.CREATE_PROMPT, data, token),
|
||||
deletePrompt: (data: any, token: string | null): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.DELETE_PROMPT, data, token),
|
||||
updatePrompt: (data: any, token: string | null): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.UPDATE_PROMPT, data, token),
|
||||
getSinglePrompt: (id: string, token: string | null): Promise<any> =>
|
||||
apiClient.get(endpoints.USER.SINGLE_PROMPT(id), token),
|
||||
deletePath: (docPath: string, token: string | null): Promise<any> =>
|
||||
apiClient.get(endpoints.USER.DELETE_PATH(docPath), token),
|
||||
getTaskStatus: (task_id: string, token: string | null): Promise<any> =>
|
||||
apiClient.get(endpoints.USER.TASK_STATUS(task_id), token),
|
||||
getMessageAnalytics: (data: any, token: string | null): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.MESSAGE_ANALYTICS, data, token),
|
||||
getTokenAnalytics: (data: any, token: string | null): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.TOKEN_ANALYTICS, data, token),
|
||||
getFeedbackAnalytics: (data: any, token: string | null): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.FEEDBACK_ANALYTICS, data, token),
|
||||
getLogs: (data: any, token: string | null): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.LOGS, data, token),
|
||||
manageSync: (data: any, token: string | null): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.MANAGE_SYNC, data, token),
|
||||
getAvailableTools: (token: string | null): Promise<any> =>
|
||||
apiClient.get(endpoints.USER.GET_AVAILABLE_TOOLS, token),
|
||||
getUserTools: (token: string | null): Promise<any> =>
|
||||
apiClient.get(endpoints.USER.GET_USER_TOOLS, token),
|
||||
createTool: (data: any, token: string | null): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.CREATE_TOOL, data, token),
|
||||
updateToolStatus: (data: any, token: string | null): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.UPDATE_TOOL_STATUS, data, token),
|
||||
updateTool: (data: any, token: string | null): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.UPDATE_TOOL, data, token),
|
||||
deleteTool: (data: any, token: string | null): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.DELETE_TOOL, data, token),
|
||||
getDocumentChunks: (
|
||||
docId: string,
|
||||
page: number,
|
||||
perPage: number,
|
||||
token: string | null,
|
||||
): Promise<any> =>
|
||||
apiClient.get(endpoints.USER.GET_CHUNKS(docId, page, perPage)),
|
||||
addChunk: (data: any): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.ADD_CHUNK, data),
|
||||
deleteChunk: (docId: string, chunkId: string): Promise<any> =>
|
||||
apiClient.delete(endpoints.USER.DELETE_CHUNK(docId, chunkId)),
|
||||
updateChunk: (data: any): Promise<any> =>
|
||||
apiClient.put(endpoints.USER.UPDATE_CHUNK, data),
|
||||
apiClient.get(endpoints.USER.GET_CHUNKS(docId, page, perPage), token),
|
||||
addChunk: (data: any, token: string | null): Promise<any> =>
|
||||
apiClient.post(endpoints.USER.ADD_CHUNK, data, token),
|
||||
deleteChunk: (
|
||||
docId: string,
|
||||
chunkId: string,
|
||||
token: string | null,
|
||||
): Promise<any> =>
|
||||
apiClient.delete(endpoints.USER.DELETE_CHUNK(docId, chunkId), token),
|
||||
updateChunk: (data: any, token: string | null): Promise<any> =>
|
||||
apiClient.put(endpoints.USER.UPDATE_CHUNK, data, token),
|
||||
};
|
||||
|
||||
export default userService;
|
||||
|
||||
@@ -7,7 +7,10 @@ import newChatIcon from '../assets/openNewChat.svg';
|
||||
import ShareIcon from '../assets/share.svg';
|
||||
import { useMediaQuery } from '../hooks';
|
||||
import { ShareConversationModal } from '../modals/ShareConversationModal';
|
||||
import { selectConversationId } from '../preferences/preferenceSlice';
|
||||
import {
|
||||
selectConversationId,
|
||||
selectToken,
|
||||
} from '../preferences/preferenceSlice';
|
||||
import { AppDispatch } from '../store';
|
||||
import { handleSendFeedback } from './conversationHandlers';
|
||||
import { FEEDBACK, Query } from './conversationModels';
|
||||
@@ -27,6 +30,7 @@ import ConversationMessages from './ConversationMessages';
|
||||
import MessageInput from '../components/MessageInput';
|
||||
|
||||
export default function Conversation() {
|
||||
const token = useSelector(selectToken);
|
||||
const queries = useSelector(selectQueries);
|
||||
const status = useSelector(selectStatus);
|
||||
const conversationId = useSelector(selectConversationId);
|
||||
@@ -118,6 +122,7 @@ export default function Conversation() {
|
||||
feedback,
|
||||
conversationId as string,
|
||||
index,
|
||||
token,
|
||||
).catch(() =>
|
||||
handleSendFeedback(
|
||||
query.prompt,
|
||||
@@ -125,6 +130,7 @@ export default function Conversation() {
|
||||
feedback,
|
||||
conversationId as string,
|
||||
index,
|
||||
token,
|
||||
).catch(() =>
|
||||
dispatch(updateQuery({ index, query: { feedback: prevFeedback } })),
|
||||
),
|
||||
|
||||
@@ -1,35 +1,34 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import ConversationMessages from './ConversationMessages';
|
||||
import MessageInput from '../components/MessageInput';
|
||||
|
||||
import conversationService from '../api/services/conversationService';
|
||||
import MessageInput from '../components/MessageInput';
|
||||
import { selectToken } from '../preferences/preferenceSlice';
|
||||
import { AppDispatch } from '../store';
|
||||
import { formatDate } from '../utils/dateTimeUtils';
|
||||
import ConversationMessages from './ConversationMessages';
|
||||
import {
|
||||
selectClientAPIKey,
|
||||
setClientApiKey,
|
||||
updateQuery,
|
||||
addQuery,
|
||||
fetchSharedAnswer,
|
||||
selectStatus,
|
||||
} from './sharedConversationSlice';
|
||||
import { setIdentifier, setFetchedData } from './sharedConversationSlice';
|
||||
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { AppDispatch } from '../store';
|
||||
|
||||
import {
|
||||
selectClientAPIKey,
|
||||
selectDate,
|
||||
selectTitle,
|
||||
selectQueries,
|
||||
selectStatus,
|
||||
selectTitle,
|
||||
setClientApiKey,
|
||||
setFetchedData,
|
||||
setIdentifier,
|
||||
updateQuery,
|
||||
} from './sharedConversationSlice';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import { formatDate } from '../utils/dateTimeUtils';
|
||||
|
||||
export const SharedConversation = () => {
|
||||
const navigate = useNavigate();
|
||||
const { identifier } = useParams(); //identifier is a uuid, not conversationId
|
||||
|
||||
const token = useSelector(selectToken);
|
||||
const queries = useSelector(selectQueries);
|
||||
const title = useSelector(selectTitle);
|
||||
const date = useSelector(selectDate);
|
||||
@@ -56,7 +55,7 @@ export const SharedConversation = () => {
|
||||
const fetchQueries = () => {
|
||||
identifier &&
|
||||
conversationService
|
||||
.getSharedConversation(identifier || '')
|
||||
.getSharedConversation(identifier || '', token)
|
||||
.then((res) => {
|
||||
if (res.status === 404 || res.status === 400)
|
||||
navigate('/pagenotfound');
|
||||
|
||||
@@ -6,6 +6,7 @@ import { ToolCallsType } from './types';
|
||||
export function handleFetchAnswer(
|
||||
question: string,
|
||||
signal: AbortSignal,
|
||||
token: string | null,
|
||||
selectedDocs: Doc | null,
|
||||
history: Array<any> = [],
|
||||
conversationId: string | null,
|
||||
@@ -52,7 +53,7 @@ export function handleFetchAnswer(
|
||||
}
|
||||
payload.retriever = selectedDocs?.retriever as string;
|
||||
return conversationService
|
||||
.answer(payload, signal)
|
||||
.answer(payload, token, signal)
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
@@ -76,6 +77,7 @@ export function handleFetchAnswer(
|
||||
export function handleFetchAnswerSteaming(
|
||||
question: string,
|
||||
signal: AbortSignal,
|
||||
token: string | null,
|
||||
selectedDocs: Doc | null,
|
||||
history: Array<any> = [],
|
||||
conversationId: string | null,
|
||||
@@ -109,7 +111,7 @@ export function handleFetchAnswerSteaming(
|
||||
|
||||
return new Promise<Answer>((resolve, reject) => {
|
||||
conversationService
|
||||
.answerStream(payload, signal)
|
||||
.answerStream(payload, token, signal)
|
||||
.then((response) => {
|
||||
if (!response.body) throw Error('No response body');
|
||||
|
||||
@@ -160,6 +162,7 @@ export function handleFetchAnswerSteaming(
|
||||
|
||||
export function handleSearch(
|
||||
question: string,
|
||||
token: string | null,
|
||||
selectedDocs: Doc | null,
|
||||
conversation_id: string | null,
|
||||
history: Array<any> = [],
|
||||
@@ -185,7 +188,7 @@ export function handleSearch(
|
||||
payload.active_docs = selectedDocs.id as string;
|
||||
payload.retriever = selectedDocs?.retriever as string;
|
||||
return conversationService
|
||||
.search(payload)
|
||||
.search(payload, token)
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
return data;
|
||||
@@ -206,11 +209,14 @@ export function handleSearchViaApiKey(
|
||||
};
|
||||
});
|
||||
return conversationService
|
||||
.search({
|
||||
question: question,
|
||||
history: JSON.stringify(history),
|
||||
api_key: api_key,
|
||||
})
|
||||
.search(
|
||||
{
|
||||
question: question,
|
||||
history: JSON.stringify(history),
|
||||
api_key: api_key,
|
||||
},
|
||||
null,
|
||||
)
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
return data;
|
||||
@@ -224,15 +230,19 @@ export function handleSendFeedback(
|
||||
feedback: FEEDBACK,
|
||||
conversation_id: string,
|
||||
prompt_index: number,
|
||||
token: string | null,
|
||||
) {
|
||||
return conversationService
|
||||
.feedback({
|
||||
question: prompt,
|
||||
answer: response,
|
||||
feedback: feedback,
|
||||
conversation_id: conversation_id,
|
||||
question_index: prompt_index,
|
||||
})
|
||||
.feedback(
|
||||
{
|
||||
question: prompt,
|
||||
answer: response,
|
||||
feedback: feedback,
|
||||
conversation_id: conversation_id,
|
||||
question_index: prompt_index,
|
||||
},
|
||||
token,
|
||||
)
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
return Promise.resolve();
|
||||
@@ -265,7 +275,7 @@ export function handleFetchSharedAnswerStreaming( //for shared conversations
|
||||
save_conversation: false,
|
||||
};
|
||||
conversationService
|
||||
.answerStream(payload, signal)
|
||||
.answerStream(payload, null, signal)
|
||||
.then((response) => {
|
||||
if (!response.body) throw Error('No response body');
|
||||
|
||||
@@ -339,6 +349,7 @@ export function handleFetchSharedAnswer(
|
||||
question: question,
|
||||
api_key: apiKey,
|
||||
},
|
||||
null,
|
||||
signal,
|
||||
)
|
||||
.then((response) => {
|
||||
|
||||
@@ -42,6 +42,7 @@ export const fetchAnswer = createAsyncThunk<
|
||||
await handleFetchAnswerSteaming(
|
||||
question,
|
||||
signal,
|
||||
state.preference.token,
|
||||
state.preference.selectedDocs!,
|
||||
state.conversation.queries,
|
||||
state.conversation.conversationId,
|
||||
@@ -53,7 +54,7 @@ export const fetchAnswer = createAsyncThunk<
|
||||
|
||||
if (data.type === 'end') {
|
||||
dispatch(conversationSlice.actions.setStatus('idle'));
|
||||
getConversations()
|
||||
getConversations(state.preference.token)
|
||||
.then((fetchedConversations) => {
|
||||
dispatch(setConversations(fetchedConversations));
|
||||
})
|
||||
@@ -114,6 +115,7 @@ export const fetchAnswer = createAsyncThunk<
|
||||
const answer = await handleFetchAnswer(
|
||||
question,
|
||||
signal,
|
||||
state.preference.token,
|
||||
state.preference.selectedDocs!,
|
||||
state.conversation.queries,
|
||||
state.conversation.conversationId,
|
||||
@@ -150,7 +152,7 @@ export const fetchAnswer = createAsyncThunk<
|
||||
}),
|
||||
);
|
||||
dispatch(conversationSlice.actions.setStatus('idle'));
|
||||
getConversations()
|
||||
getConversations(state.preference.token)
|
||||
.then((fetchedConversations) => {
|
||||
dispatch(setConversations(fetchedConversations));
|
||||
})
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
import React from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import { getDocs } from '../preferences/preferenceApi';
|
||||
import { Doc } from '../models/misc';
|
||||
import { getDocs } from '../preferences/preferenceApi';
|
||||
import {
|
||||
selectSelectedDocs,
|
||||
selectToken,
|
||||
setSelectedDocs,
|
||||
setSourceDocs,
|
||||
} from '../preferences/preferenceSlice';
|
||||
|
||||
export default function useDefaultDocument() {
|
||||
const dispatch = useDispatch();
|
||||
const token = useSelector(selectToken);
|
||||
const selectedDoc = useSelector(selectSelectedDocs);
|
||||
|
||||
const fetchDocs = () => {
|
||||
getDocs().then((data) => {
|
||||
getDocs(token).then((data) => {
|
||||
dispatch(setSourceDocs(data));
|
||||
if (!selectedDoc)
|
||||
Array.isArray(data) &&
|
||||
|
||||
55
frontend/src/hooks/useTokenAuth.ts
Normal file
55
frontend/src/hooks/useTokenAuth.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import userService from '../api/services/userService';
|
||||
import { selectToken, setToken } from '../preferences/preferenceSlice';
|
||||
|
||||
export default function useAuth() {
|
||||
const dispatch = useDispatch();
|
||||
const token = useSelector(selectToken);
|
||||
const [authType, setAuthType] = useState(null);
|
||||
const [showTokenModal, setShowTokenModal] = useState(false);
|
||||
const [isAuthLoading, setIsAuthLoading] = useState(true);
|
||||
const isGeneratingToken = useRef(false);
|
||||
|
||||
const generateNewToken = async () => {
|
||||
if (isGeneratingToken.current) return;
|
||||
isGeneratingToken.current = true;
|
||||
const response = await userService.getNewToken();
|
||||
const { token: newToken } = await response.json();
|
||||
localStorage.setItem('authToken', newToken);
|
||||
dispatch(setToken(newToken));
|
||||
setIsAuthLoading(false);
|
||||
return newToken;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const initializeAuth = async () => {
|
||||
try {
|
||||
const configRes = await userService.getConfig();
|
||||
const config = await configRes.json();
|
||||
setAuthType(config.auth_type);
|
||||
|
||||
if (config.auth_type === 'session_jwt' && !token) {
|
||||
await generateNewToken();
|
||||
} else if (config.auth_type === 'simple_jwt' && !token) {
|
||||
setShowTokenModal(true);
|
||||
setIsAuthLoading(false);
|
||||
} else {
|
||||
setIsAuthLoading(false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Auth initialization failed:', error);
|
||||
setIsAuthLoading(false);
|
||||
}
|
||||
};
|
||||
initializeAuth();
|
||||
}, []);
|
||||
|
||||
const handleTokenSubmit = (enteredToken: string) => {
|
||||
localStorage.setItem('authToken', enteredToken);
|
||||
dispatch(setToken(enteredToken));
|
||||
setShowTokenModal(false);
|
||||
};
|
||||
return { authType, showTokenModal, isAuthLoading, token, handleTokenSubmit };
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
import React, { useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import userService from '../api/services/userService';
|
||||
import Spinner from '../components/Spinner';
|
||||
import { useOutsideAlerter } from '../hooks';
|
||||
import { ActiveState } from '../models/misc';
|
||||
import { selectToken } from '../preferences/preferenceSlice';
|
||||
import ConfigToolModal from './ConfigToolModal';
|
||||
import { AvailableToolType } from './types';
|
||||
import Spinner from '../components/Spinner';
|
||||
import WrapperComponent from './WrapperModal';
|
||||
|
||||
export default function AddToolModal({
|
||||
@@ -23,6 +25,7 @@ export default function AddToolModal({
|
||||
onToolAdded: (toolId: string) => void;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const token = useSelector(selectToken);
|
||||
const modalRef = useRef<HTMLDivElement>(null);
|
||||
const [availableTools, setAvailableTools] = React.useState<
|
||||
AvailableToolType[]
|
||||
@@ -42,7 +45,7 @@ export default function AddToolModal({
|
||||
const getAvailableTools = () => {
|
||||
setLoading(true);
|
||||
userService
|
||||
.getAvailableTools()
|
||||
.getAvailableTools(token)
|
||||
.then((res) => {
|
||||
return res.json();
|
||||
})
|
||||
@@ -55,14 +58,17 @@ export default function AddToolModal({
|
||||
const handleAddTool = (tool: AvailableToolType) => {
|
||||
if (Object.keys(tool.configRequirements).length === 0) {
|
||||
userService
|
||||
.createTool({
|
||||
name: tool.name,
|
||||
displayName: tool.displayName,
|
||||
description: tool.description,
|
||||
config: {},
|
||||
actions: tool.actions,
|
||||
status: true,
|
||||
})
|
||||
.createTool(
|
||||
{
|
||||
name: tool.name,
|
||||
displayName: tool.displayName,
|
||||
description: tool.description,
|
||||
config: {},
|
||||
actions: tool.actions,
|
||||
status: true,
|
||||
},
|
||||
token,
|
||||
)
|
||||
.then((res) => {
|
||||
if (res.status === 200) {
|
||||
return res.json();
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import WrapperModal from './WrapperModal';
|
||||
import userService from '../api/services/userService';
|
||||
import Input from '../components/Input';
|
||||
import { ActiveState } from '../models/misc';
|
||||
import { selectToken } from '../preferences/preferenceSlice';
|
||||
import { AvailableToolType } from './types';
|
||||
import userService from '../api/services/userService';
|
||||
import WrapperModal from './WrapperModal';
|
||||
|
||||
interface ConfigToolModalProps {
|
||||
modalState: ActiveState;
|
||||
@@ -21,18 +23,22 @@ export default function ConfigToolModal({
|
||||
getUserTools,
|
||||
}: ConfigToolModalProps) {
|
||||
const { t } = useTranslation();
|
||||
const token = useSelector(selectToken);
|
||||
const [authKey, setAuthKey] = React.useState<string>('');
|
||||
|
||||
const handleAddTool = (tool: AvailableToolType) => {
|
||||
userService
|
||||
.createTool({
|
||||
name: tool.name,
|
||||
displayName: tool.displayName,
|
||||
description: tool.description,
|
||||
config: { token: authKey },
|
||||
actions: tool.actions,
|
||||
status: true,
|
||||
})
|
||||
.createTool(
|
||||
{
|
||||
name: tool.name,
|
||||
displayName: tool.displayName,
|
||||
description: tool.description,
|
||||
config: { token: authKey },
|
||||
actions: tool.actions,
|
||||
status: true,
|
||||
},
|
||||
token,
|
||||
)
|
||||
.then(() => {
|
||||
setModalState('INACTIVE');
|
||||
getUserTools();
|
||||
|
||||
@@ -6,7 +6,7 @@ import userService from '../api/services/userService';
|
||||
import Dropdown from '../components/Dropdown';
|
||||
import Input from '../components/Input';
|
||||
import { CreateAPIKeyModalProps, Doc } from '../models/misc';
|
||||
import { selectSourceDocs } from '../preferences/preferenceSlice';
|
||||
import { selectSourceDocs, selectToken } from '../preferences/preferenceSlice';
|
||||
import WrapperModal from './WrapperModal';
|
||||
|
||||
const embeddingsName =
|
||||
@@ -18,6 +18,7 @@ export default function CreateAPIKeyModal({
|
||||
createAPIKey,
|
||||
}: CreateAPIKeyModalProps) {
|
||||
const { t } = useTranslation();
|
||||
const token = useSelector(selectToken);
|
||||
const docs = useSelector(selectSourceDocs);
|
||||
|
||||
const [APIKeyName, setAPIKeyName] = React.useState<string>('');
|
||||
@@ -60,7 +61,7 @@ export default function CreateAPIKeyModal({
|
||||
React.useEffect(() => {
|
||||
const handleFetchPrompts = async () => {
|
||||
try {
|
||||
const response = await userService.getPrompts();
|
||||
const response = await userService.getPrompts(token);
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch prompts');
|
||||
}
|
||||
|
||||
47
frontend/src/modals/JWTModal.tsx
Normal file
47
frontend/src/modals/JWTModal.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
import Input from '../components/Input';
|
||||
import { ActiveState } from '../models/misc';
|
||||
import WrapperModal from './WrapperModal';
|
||||
|
||||
type JWTModalProps = {
|
||||
modalState: ActiveState;
|
||||
handleTokenSubmit: (enteredToken: string) => void;
|
||||
};
|
||||
|
||||
export default function JWTModal({
|
||||
modalState,
|
||||
handleTokenSubmit,
|
||||
}: JWTModalProps) {
|
||||
const [jwtToken, setJwtToken] = useState<string>('');
|
||||
|
||||
if (modalState !== 'ACTIVE') return null;
|
||||
|
||||
return (
|
||||
<WrapperModal className="p-4" isPerformingTask={true} close={() => {}}>
|
||||
<div className="mb-6">
|
||||
<span className="text-lg text-jet dark:text-bright-gray">
|
||||
Add JWT Token
|
||||
</span>
|
||||
</div>
|
||||
<div className="relative mt-5 mb-4">
|
||||
<Input
|
||||
name="JWT Token"
|
||||
type="text"
|
||||
className="rounded-md"
|
||||
value={jwtToken}
|
||||
onChange={(e) => setJwtToken(e.target.value)}
|
||||
borderVariant="thin"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
disabled={jwtToken.length === 0}
|
||||
onClick={handleTokenSubmit.bind(null, jwtToken)}
|
||||
className="float-right mt-4 rounded-full bg-purple-30 px-5 py-2 text-sm text-white hover:bg-[#6F3FD1] disabled:opacity-50"
|
||||
>
|
||||
Save Token
|
||||
</button>
|
||||
</WrapperModal>
|
||||
);
|
||||
}
|
||||
@@ -1,16 +1,21 @@
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSelector } from 'react-redux';
|
||||
import {
|
||||
selectSourceDocs,
|
||||
selectSelectedDocs,
|
||||
selectChunks,
|
||||
selectPrompt,
|
||||
} from '../preferences/preferenceSlice';
|
||||
|
||||
import conversationService from '../api/services/conversationService';
|
||||
import Spinner from '../assets/spinner.svg';
|
||||
import Dropdown from '../components/Dropdown';
|
||||
import ToggleSwitch from '../components/ToggleSwitch';
|
||||
import { Doc } from '../models/misc';
|
||||
import Spinner from '../assets/spinner.svg';
|
||||
import {
|
||||
selectChunks,
|
||||
selectPrompt,
|
||||
selectSelectedDocs,
|
||||
selectSourceDocs,
|
||||
selectToken,
|
||||
} from '../preferences/preferenceSlice';
|
||||
import WrapperModal from './WrapperModal';
|
||||
|
||||
const apiHost = import.meta.env.VITE_API_HOST || 'https://docsapi.arc53.com';
|
||||
const embeddingsName =
|
||||
import.meta.env.VITE_EMBEDDINGS_NAME ||
|
||||
@@ -18,9 +23,6 @@ const embeddingsName =
|
||||
|
||||
type StatusType = 'loading' | 'idle' | 'fetched' | 'failed';
|
||||
|
||||
import conversationService from '../api/services/conversationService';
|
||||
import WrapperModal from './WrapperModal';
|
||||
|
||||
export const ShareConversationModal = ({
|
||||
close,
|
||||
conversationId,
|
||||
@@ -29,6 +31,7 @@ export const ShareConversationModal = ({
|
||||
conversationId: string;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const token = useSelector(selectToken);
|
||||
|
||||
const domain = window.location.origin;
|
||||
|
||||
@@ -86,7 +89,7 @@ export const ShareConversationModal = ({
|
||||
sourcePath && (payload.source = sourcePath.value);
|
||||
}
|
||||
conversationService
|
||||
.shareConversation(isPromptable, payload)
|
||||
.shareConversation(isPromptable, payload, token)
|
||||
.then((res) => {
|
||||
return res.json();
|
||||
})
|
||||
|
||||
@@ -3,9 +3,9 @@ import userService from '../api/services/userService';
|
||||
import { Doc, GetDocsResponse } from '../models/misc';
|
||||
|
||||
//Fetches all JSON objects from the source. We only use the objects with the "model" property in SelectDocsModal.tsx. Hopefully can clean up the source file later.
|
||||
export async function getDocs(): Promise<Doc[] | null> {
|
||||
export async function getDocs(token: string | null): Promise<Doc[] | null> {
|
||||
try {
|
||||
const response = await userService.getDocs();
|
||||
const response = await userService.getDocs(token);
|
||||
const data = await response.json();
|
||||
|
||||
const docs: Doc[] = [];
|
||||
@@ -26,10 +26,11 @@ export async function getDocsWithPagination(
|
||||
pageNumber = 1,
|
||||
rowsPerPage = 10,
|
||||
searchTerm = '',
|
||||
token: string | null,
|
||||
): Promise<GetDocsResponse | null> {
|
||||
try {
|
||||
const query = `sort=${sort}&order=${order}&page=${pageNumber}&rows=${rowsPerPage}&search=${searchTerm}`;
|
||||
const response = await userService.getDocsWithPagination(query);
|
||||
const response = await userService.getDocsWithPagination(query, token);
|
||||
const data = await response.json();
|
||||
const docs: Doc[] = [];
|
||||
Array.isArray(data.paginated) &&
|
||||
@@ -48,12 +49,12 @@ export async function getDocsWithPagination(
|
||||
}
|
||||
}
|
||||
|
||||
export async function getConversations(): Promise<{
|
||||
export async function getConversations(token: string | null): Promise<{
|
||||
data: { name: string; id: string }[] | null;
|
||||
loading: boolean;
|
||||
}> {
|
||||
try {
|
||||
const response = await conversationService.getConversations();
|
||||
const response = await conversationService.getConversations(token);
|
||||
const data = await response.json();
|
||||
|
||||
const conversations: { name: string; id: string }[] = [];
|
||||
@@ -100,8 +101,11 @@ export function setLocalRecentDocs(doc: Doc | null): void {
|
||||
docPath = 'local' + '/' + doc.name + '/';
|
||||
}
|
||||
userService
|
||||
.checkDocs({
|
||||
docs: docPath,
|
||||
})
|
||||
.checkDocs(
|
||||
{
|
||||
docs: docPath,
|
||||
},
|
||||
null,
|
||||
)
|
||||
.then((response) => response.json());
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ export interface Preference {
|
||||
data: { name: string; id: string }[] | null;
|
||||
loading: boolean;
|
||||
};
|
||||
token: string | null;
|
||||
modalState: ActiveState;
|
||||
paginatedDocuments: Doc[] | null;
|
||||
}
|
||||
@@ -42,6 +43,7 @@ const initialState: Preference = {
|
||||
data: null,
|
||||
loading: false,
|
||||
},
|
||||
token: localStorage.getItem('authToken') || null,
|
||||
modalState: 'INACTIVE',
|
||||
paginatedDocuments: null,
|
||||
};
|
||||
@@ -65,6 +67,9 @@ export const prefSlice = createSlice({
|
||||
setConversations: (state, action) => {
|
||||
state.conversations = action.payload;
|
||||
},
|
||||
setToken: (state, action) => {
|
||||
state.token = action.payload;
|
||||
},
|
||||
setPrompt: (state, action) => {
|
||||
state.prompt = action.payload;
|
||||
},
|
||||
@@ -85,6 +90,7 @@ export const {
|
||||
setSelectedDocs,
|
||||
setSourceDocs,
|
||||
setConversations,
|
||||
setToken,
|
||||
setPrompt,
|
||||
setChunks,
|
||||
setTokenLimit,
|
||||
@@ -157,6 +163,7 @@ export const selectConversations = (state: RootState) =>
|
||||
state.preference.conversations;
|
||||
export const selectConversationId = (state: RootState) =>
|
||||
state.conversation.conversationId;
|
||||
export const selectToken = (state: RootState) => state.preference.token;
|
||||
export const selectPrompt = (state: RootState) => state.preference.prompt;
|
||||
export const selectChunks = (state: RootState) => state.preference.chunks;
|
||||
export const selectTokenLimit = (state: RootState) =>
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import userService from '../api/services/userService';
|
||||
import Trash from '../assets/trash.svg';
|
||||
import CreateAPIKeyModal from '../modals/CreateAPIKeyModal';
|
||||
import SaveAPIKeyModal from '../modals/SaveAPIKeyModal';
|
||||
import ConfirmationModal from '../modals/ConfirmationModal';
|
||||
import { APIKeyData } from './types';
|
||||
import SkeletonLoader from '../components/SkeletonLoader';
|
||||
import { useLoaderState } from '../hooks';
|
||||
import ConfirmationModal from '../modals/ConfirmationModal';
|
||||
import CreateAPIKeyModal from '../modals/CreateAPIKeyModal';
|
||||
import SaveAPIKeyModal from '../modals/SaveAPIKeyModal';
|
||||
import { selectToken } from '../preferences/preferenceSlice';
|
||||
import { APIKeyData } from './types';
|
||||
|
||||
export default function APIKeys() {
|
||||
const { t } = useTranslation();
|
||||
const token = useSelector(selectToken);
|
||||
const [isCreateModalOpen, setCreateModal] = useState(false);
|
||||
const [isSaveKeyModalOpen, setSaveKeyModal] = useState(false);
|
||||
const [newKey, setNewKey] = useState('');
|
||||
@@ -25,7 +28,7 @@ export default function APIKeys() {
|
||||
const handleFetchKeys = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const response = await userService.getAPIKeys();
|
||||
const response = await userService.getAPIKeys(token);
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch API Keys');
|
||||
}
|
||||
@@ -41,7 +44,7 @@ export default function APIKeys() {
|
||||
const handleDeleteKey = (id: string) => {
|
||||
setLoading(true);
|
||||
userService
|
||||
.deleteAPIKey({ id })
|
||||
.deleteAPIKey({ id }, token)
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to delete API Key');
|
||||
@@ -71,7 +74,7 @@ export default function APIKeys() {
|
||||
}) => {
|
||||
setLoading(true);
|
||||
userService
|
||||
.createAPIKey(payload)
|
||||
.createAPIKey(payload, token)
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to create API Key');
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
BarElement,
|
||||
CategoryScale,
|
||||
@@ -9,18 +7,21 @@ import {
|
||||
Title,
|
||||
Tooltip,
|
||||
} from 'chart.js';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Bar } from 'react-chartjs-2';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import userService from '../api/services/userService';
|
||||
import Dropdown from '../components/Dropdown';
|
||||
import SkeletonLoader from '../components/SkeletonLoader';
|
||||
import { useLoaderState } from '../hooks';
|
||||
import { selectToken } from '../preferences/preferenceSlice';
|
||||
import { htmlLegendPlugin } from '../utils/chartUtils';
|
||||
import { formatDate } from '../utils/dateTimeUtils';
|
||||
import { APIKeyData } from './types';
|
||||
import { useLoaderState } from '../hooks';
|
||||
|
||||
import type { ChartData } from 'chart.js';
|
||||
import SkeletonLoader from '../components/SkeletonLoader';
|
||||
|
||||
ChartJS.register(
|
||||
CategoryScale,
|
||||
LinearScale,
|
||||
@@ -32,6 +33,7 @@ ChartJS.register(
|
||||
|
||||
export default function Analytics() {
|
||||
const { t } = useTranslation();
|
||||
const token = useSelector(selectToken);
|
||||
|
||||
const filterOptions = [
|
||||
{ label: t('settings.analytics.filterOptions.hour'), value: 'last_hour' },
|
||||
@@ -97,7 +99,7 @@ export default function Analytics() {
|
||||
const fetchChatbots = async () => {
|
||||
setLoadingChatbots(true);
|
||||
try {
|
||||
const response = await userService.getAPIKeys();
|
||||
const response = await userService.getAPIKeys(token);
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch Chatbots');
|
||||
}
|
||||
@@ -113,10 +115,13 @@ export default function Analytics() {
|
||||
const fetchMessagesData = async (chatbot_id?: string, filter?: string) => {
|
||||
setLoadingMessages(true);
|
||||
try {
|
||||
const response = await userService.getMessageAnalytics({
|
||||
api_key_id: chatbot_id,
|
||||
filter_option: filter,
|
||||
});
|
||||
const response = await userService.getMessageAnalytics(
|
||||
{
|
||||
api_key_id: chatbot_id,
|
||||
filter_option: filter,
|
||||
},
|
||||
token,
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch analytics data');
|
||||
}
|
||||
@@ -132,10 +137,13 @@ export default function Analytics() {
|
||||
const fetchTokenData = async (chatbot_id?: string, filter?: string) => {
|
||||
setLoadingTokens(true);
|
||||
try {
|
||||
const response = await userService.getTokenAnalytics({
|
||||
api_key_id: chatbot_id,
|
||||
filter_option: filter,
|
||||
});
|
||||
const response = await userService.getTokenAnalytics(
|
||||
{
|
||||
api_key_id: chatbot_id,
|
||||
filter_option: filter,
|
||||
},
|
||||
token,
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch analytics data');
|
||||
}
|
||||
@@ -151,10 +159,13 @@ export default function Analytics() {
|
||||
const fetchFeedbackData = async (chatbot_id?: string, filter?: string) => {
|
||||
setLoadingFeedback(true);
|
||||
try {
|
||||
const response = await userService.getFeedbackAnalytics({
|
||||
api_key_id: chatbot_id,
|
||||
filter_option: filter,
|
||||
});
|
||||
const response = await userService.getFeedbackAnalytics(
|
||||
{
|
||||
api_key_id: chatbot_id,
|
||||
filter_option: filter,
|
||||
},
|
||||
token,
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch analytics data');
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import userService from '../api/services/userService';
|
||||
import ArrowLeft from '../assets/arrow-left.svg';
|
||||
@@ -22,6 +22,7 @@ import ConfirmationModal from '../modals/ConfirmationModal';
|
||||
import { ActiveState, Doc, DocumentsProps } from '../models/misc';
|
||||
import { getDocs, getDocsWithPagination } from '../preferences/preferenceApi';
|
||||
import {
|
||||
selectToken,
|
||||
setPaginatedDocuments,
|
||||
setSourceDocs,
|
||||
} from '../preferences/preferenceSlice';
|
||||
@@ -53,6 +54,7 @@ export default function Documents({
|
||||
}: DocumentsProps) {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
const token = useSelector(selectToken);
|
||||
|
||||
const [searchTerm, setSearchTerm] = useState<string>('');
|
||||
const [modalState, setModalState] = useState<ActiveState>('INACTIVE');
|
||||
@@ -163,6 +165,7 @@ export default function Documents({
|
||||
page,
|
||||
rowsPerPg,
|
||||
searchTerm,
|
||||
token,
|
||||
)
|
||||
.then((data) => {
|
||||
dispatch(setPaginatedDocuments(data ? data.docs : []));
|
||||
@@ -179,9 +182,9 @@ export default function Documents({
|
||||
const handleManageSync = (doc: Doc, sync_frequency: string) => {
|
||||
setLoading(true);
|
||||
userService
|
||||
.manageSync({ source_id: doc.id, sync_frequency })
|
||||
.manageSync({ source_id: doc.id, sync_frequency }, token)
|
||||
.then(() => {
|
||||
return getDocs();
|
||||
return getDocs(token);
|
||||
})
|
||||
.then((data) => {
|
||||
dispatch(setSourceDocs(data));
|
||||
@@ -190,6 +193,8 @@ export default function Documents({
|
||||
sortOrder,
|
||||
currentPage,
|
||||
rowsPerPage,
|
||||
searchTerm,
|
||||
token,
|
||||
);
|
||||
})
|
||||
.then((paginatedData) => {
|
||||
@@ -519,6 +524,7 @@ function DocumentChunks({
|
||||
handleGoBack: () => void;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const token = useSelector(selectToken);
|
||||
const [isDarkTheme] = useDarkTheme();
|
||||
const [paginatedChunks, setPaginatedChunks] = useState<ChunkType[]>([]);
|
||||
const [page, setPage] = useState(1);
|
||||
@@ -536,7 +542,7 @@ function DocumentChunks({
|
||||
setLoading(true);
|
||||
try {
|
||||
userService
|
||||
.getDocumentChunks(document.id ?? '', page, perPage)
|
||||
.getDocumentChunks(document.id ?? '', page, perPage, token)
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
setLoading(false);
|
||||
@@ -561,13 +567,16 @@ function DocumentChunks({
|
||||
const handleAddChunk = (title: string, text: string) => {
|
||||
try {
|
||||
userService
|
||||
.addChunk({
|
||||
id: document.id ?? '',
|
||||
text: text,
|
||||
metadata: {
|
||||
title: title,
|
||||
.addChunk(
|
||||
{
|
||||
id: document.id ?? '',
|
||||
text: text,
|
||||
metadata: {
|
||||
title: title,
|
||||
},
|
||||
},
|
||||
})
|
||||
token,
|
||||
)
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to add chunk');
|
||||
@@ -582,14 +591,17 @@ function DocumentChunks({
|
||||
const handleUpdateChunk = (title: string, text: string, chunk: ChunkType) => {
|
||||
try {
|
||||
userService
|
||||
.updateChunk({
|
||||
id: document.id ?? '',
|
||||
chunk_id: chunk.doc_id,
|
||||
text: text,
|
||||
metadata: {
|
||||
title: title,
|
||||
.updateChunk(
|
||||
{
|
||||
id: document.id ?? '',
|
||||
chunk_id: chunk.doc_id,
|
||||
text: text,
|
||||
metadata: {
|
||||
title: title,
|
||||
},
|
||||
},
|
||||
})
|
||||
token,
|
||||
)
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to update chunk');
|
||||
@@ -604,7 +616,7 @@ function DocumentChunks({
|
||||
const handleDeleteChunk = (chunk: ChunkType) => {
|
||||
try {
|
||||
userService
|
||||
.deleteChunk(document.id ?? '', chunk.doc_id)
|
||||
.deleteChunk(document.id ?? '', chunk.doc_id, token)
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to delete chunk');
|
||||
|
||||
@@ -8,6 +8,7 @@ import { useDarkTheme } from '../hooks';
|
||||
import {
|
||||
selectChunks,
|
||||
selectPrompt,
|
||||
selectToken,
|
||||
selectTokenLimit,
|
||||
setChunks,
|
||||
setModalStateDeleteConv,
|
||||
@@ -21,6 +22,7 @@ export default function General() {
|
||||
t,
|
||||
i18n: { changeLanguage },
|
||||
} = useTranslation();
|
||||
const token = useSelector(selectToken);
|
||||
const themes = [
|
||||
{ value: 'Light', label: t('settings.general.light') },
|
||||
{ value: 'Dark', label: t('settings.general.dark') },
|
||||
@@ -64,7 +66,7 @@ export default function General() {
|
||||
React.useEffect(() => {
|
||||
const handleFetchPrompts = async () => {
|
||||
try {
|
||||
const response = await userService.getPrompts();
|
||||
const response = await userService.getPrompts(token);
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch prompts');
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useState, useEffect, useRef, useCallback } from 'react';
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import userService from '../api/services/userService';
|
||||
import ChevronRight from '../assets/chevron-right.svg';
|
||||
@@ -7,10 +8,12 @@ import CopyButton from '../components/CopyButton';
|
||||
import Dropdown from '../components/Dropdown';
|
||||
import SkeletonLoader from '../components/SkeletonLoader';
|
||||
import { useLoaderState } from '../hooks';
|
||||
import { selectToken } from '../preferences/preferenceSlice';
|
||||
import { APIKeyData, LogData } from './types';
|
||||
|
||||
export default function Logs() {
|
||||
const { t } = useTranslation();
|
||||
const token = useSelector(selectToken);
|
||||
const [chatbots, setChatbots] = useState<APIKeyData[]>([]);
|
||||
const [selectedChatbot, setSelectedChatbot] = useState<APIKeyData | null>();
|
||||
const [logs, setLogs] = useState<LogData[]>([]);
|
||||
@@ -22,7 +25,7 @@ export default function Logs() {
|
||||
const fetchChatbots = async () => {
|
||||
setLoadingChatbots(true);
|
||||
try {
|
||||
const response = await userService.getAPIKeys();
|
||||
const response = await userService.getAPIKeys(token);
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch Chatbots');
|
||||
}
|
||||
@@ -38,11 +41,14 @@ export default function Logs() {
|
||||
const fetchLogs = async () => {
|
||||
setLoadingLogs(true);
|
||||
try {
|
||||
const response = await userService.getLogs({
|
||||
page: page,
|
||||
api_key_id: selectedChatbot?.id,
|
||||
page_size: 10,
|
||||
});
|
||||
const response = await userService.getLogs(
|
||||
{
|
||||
page: page,
|
||||
api_key_id: selectedChatbot?.id,
|
||||
page_size: 10,
|
||||
},
|
||||
token,
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch logs');
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import userService from '../api/services/userService';
|
||||
import Dropdown from '../components/Dropdown';
|
||||
import { ActiveState, PromptProps } from '../models/misc';
|
||||
import { selectToken } from '../preferences/preferenceSlice';
|
||||
import PromptsModal from '../preferences/PromptsModal';
|
||||
|
||||
export default function Prompts({
|
||||
@@ -24,6 +26,7 @@ export default function Prompts({
|
||||
setEditPromptName(name);
|
||||
onSelectPrompt(name, id, type);
|
||||
};
|
||||
const token = useSelector(selectToken);
|
||||
const [newPromptName, setNewPromptName] = React.useState('');
|
||||
const [newPromptContent, setNewPromptContent] = React.useState('');
|
||||
const [editPromptName, setEditPromptName] = React.useState('');
|
||||
@@ -39,10 +42,13 @@ export default function Prompts({
|
||||
|
||||
const handleAddPrompt = async () => {
|
||||
try {
|
||||
const response = await userService.createPrompt({
|
||||
name: newPromptName,
|
||||
content: newPromptContent,
|
||||
});
|
||||
const response = await userService.createPrompt(
|
||||
{
|
||||
name: newPromptName,
|
||||
content: newPromptContent,
|
||||
},
|
||||
token,
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to add prompt');
|
||||
}
|
||||
@@ -65,7 +71,7 @@ export default function Prompts({
|
||||
const handleDeletePrompt = (id: string) => {
|
||||
setPrompts(prompts.filter((prompt) => prompt.id !== id));
|
||||
userService
|
||||
.deletePrompt({ id })
|
||||
.deletePrompt({ id }, token)
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to delete prompt');
|
||||
@@ -81,7 +87,7 @@ export default function Prompts({
|
||||
|
||||
const handleFetchPromptContent = async (id: string) => {
|
||||
try {
|
||||
const response = await userService.getSinglePrompt(id);
|
||||
const response = await userService.getSinglePrompt(id, token);
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch prompt content');
|
||||
}
|
||||
@@ -94,11 +100,14 @@ export default function Prompts({
|
||||
|
||||
const handleSaveChanges = (id: string, type: string) => {
|
||||
userService
|
||||
.updatePrompt({
|
||||
id: id,
|
||||
name: editPromptName,
|
||||
content: editPromptContent,
|
||||
})
|
||||
.updatePrompt(
|
||||
{
|
||||
id: id,
|
||||
name: editPromptName,
|
||||
content: editPromptContent,
|
||||
},
|
||||
token,
|
||||
)
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to update prompt');
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import React from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import userService from '../api/services/userService';
|
||||
import ArrowLeft from '../assets/arrow-left.svg';
|
||||
import CircleCheck from '../assets/circle-check.svg';
|
||||
@@ -9,6 +11,7 @@ import Input from '../components/Input';
|
||||
import ToggleSwitch from '../components/ToggleSwitch';
|
||||
import AddActionModal from '../modals/AddActionModal';
|
||||
import { ActiveState } from '../models/misc';
|
||||
import { selectToken } from '../preferences/preferenceSlice';
|
||||
import { APIActionType, APIToolType, UserToolType } from './types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@@ -21,6 +24,7 @@ export default function ToolConfig({
|
||||
setTool: (tool: UserToolType | APIToolType) => void;
|
||||
handleGoBack: () => void;
|
||||
}) {
|
||||
const token = useSelector(selectToken);
|
||||
const [authKey, setAuthKey] = React.useState<string>(
|
||||
'token' in tool.config ? tool.config.token : '',
|
||||
);
|
||||
@@ -57,22 +61,25 @@ export default function ToolConfig({
|
||||
|
||||
const handleSaveChanges = () => {
|
||||
userService
|
||||
.updateTool({
|
||||
id: tool.id,
|
||||
name: tool.name,
|
||||
displayName: tool.displayName,
|
||||
description: tool.description,
|
||||
config: tool.name === 'api_tool' ? tool.config : { token: authKey },
|
||||
actions: 'actions' in tool ? tool.actions : [],
|
||||
status: tool.status,
|
||||
})
|
||||
.updateTool(
|
||||
{
|
||||
id: tool.id,
|
||||
name: tool.name,
|
||||
displayName: tool.displayName,
|
||||
description: tool.description,
|
||||
config: tool.name === 'api_tool' ? tool.config : { token: authKey },
|
||||
actions: 'actions' in tool ? tool.actions : [],
|
||||
status: tool.status,
|
||||
},
|
||||
token,
|
||||
)
|
||||
.then(() => {
|
||||
handleGoBack();
|
||||
});
|
||||
};
|
||||
|
||||
const handleDelete = () => {
|
||||
userService.deleteTool({ id: tool.id }).then(() => {
|
||||
userService.deleteTool({ id: tool.id }, token).then(() => {
|
||||
handleGoBack();
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import userService from '../api/services/userService';
|
||||
import CogwheelIcon from '../assets/cogwheel.svg';
|
||||
import Input from '../components/Input';
|
||||
import Spinner from '../components/Spinner';
|
||||
import ToggleSwitch from '../components/ToggleSwitch';
|
||||
import AddToolModal from '../modals/AddToolModal';
|
||||
import { ActiveState } from '../models/misc';
|
||||
import { selectToken } from '../preferences/preferenceSlice';
|
||||
import ToolConfig from './ToolConfig';
|
||||
import { APIToolType, UserToolType } from './types';
|
||||
import ToggleSwitch from '../components/ToggleSwitch';
|
||||
|
||||
export default function Tools() {
|
||||
const { t } = useTranslation();
|
||||
const token = useSelector(selectToken);
|
||||
|
||||
const [searchTerm, setSearchTerm] = React.useState('');
|
||||
const [addToolModalState, setAddToolModalState] =
|
||||
React.useState<ActiveState>('INACTIVE');
|
||||
@@ -25,7 +29,7 @@ export default function Tools() {
|
||||
const getUserTools = () => {
|
||||
setLoading(true);
|
||||
userService
|
||||
.getUserTools()
|
||||
.getUserTools(token)
|
||||
.then((res) => {
|
||||
return res.json();
|
||||
})
|
||||
@@ -41,7 +45,7 @@ export default function Tools() {
|
||||
|
||||
const updateToolStatus = (toolId: string, newStatus: boolean) => {
|
||||
userService
|
||||
.updateToolStatus({ id: toolId, status: newStatus })
|
||||
.updateToolStatus({ id: toolId, status: newStatus }, token)
|
||||
.then(() => {
|
||||
setUserTools((prevTools) =>
|
||||
prevTools.map((tool) =>
|
||||
@@ -65,7 +69,7 @@ export default function Tools() {
|
||||
|
||||
const handleToolAdded = (toolId: string) => {
|
||||
userService
|
||||
.getUserTools()
|
||||
.getUserTools(token)
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
const newTool = data.tools.find(
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
selectSourceDocs,
|
||||
setPaginatedDocuments,
|
||||
setSourceDocs,
|
||||
selectToken,
|
||||
} from '../preferences/preferenceSlice';
|
||||
import Analytics from './Analytics';
|
||||
import APIKeys from './APIKeys';
|
||||
@@ -28,6 +29,7 @@ export default function Settings() {
|
||||
null,
|
||||
);
|
||||
|
||||
const token = useSelector(selectToken);
|
||||
const documents = useSelector(selectSourceDocs);
|
||||
const paginatedDocuments = useSelector(selectPaginatedDocuments);
|
||||
const updateWidgetScreenshot = (screenshot: File | null) => {
|
||||
@@ -41,7 +43,7 @@ export default function Settings() {
|
||||
|
||||
const handleDeleteClick = (index: number, doc: Doc) => {
|
||||
userService
|
||||
.deletePath(doc.id ?? '')
|
||||
.deletePath(doc.id ?? '', token)
|
||||
.then((response) => {
|
||||
if (response.ok && documents) {
|
||||
if (paginatedDocuments) {
|
||||
|
||||
@@ -16,6 +16,7 @@ const doc = localStorage.getItem('DocsGPTRecentDocs');
|
||||
const preloadedState: { preference: Preference } = {
|
||||
preference: {
|
||||
apiKey: key ?? '',
|
||||
token: localStorage.getItem('authToken') ?? null,
|
||||
prompt:
|
||||
prompt !== null
|
||||
? JSON.parse(prompt)
|
||||
|
||||
@@ -9,21 +9,22 @@ import WebsiteCollect from '../assets/website_collect.svg';
|
||||
import Dropdown from '../components/Dropdown';
|
||||
import Input from '../components/Input';
|
||||
import ToggleSwitch from '../components/ToggleSwitch';
|
||||
import WrapperModal from '../modals/WrapperModal';
|
||||
import { ActiveState, Doc } from '../models/misc';
|
||||
import { getDocs } from '../preferences/preferenceApi';
|
||||
import {
|
||||
selectSourceDocs,
|
||||
selectToken,
|
||||
setSelectedDocs,
|
||||
setSourceDocs,
|
||||
selectSourceDocs,
|
||||
} from '../preferences/preferenceSlice';
|
||||
import WrapperModal from '../modals/WrapperModal';
|
||||
import { IngestorDefaultConfigs } from '../upload/types/ingestor';
|
||||
import {
|
||||
IngestorType,
|
||||
FormField,
|
||||
IngestorConfig,
|
||||
IngestorFormSchemas,
|
||||
FormField,
|
||||
IngestorType,
|
||||
} from './types/ingestor';
|
||||
import { IngestorDefaultConfigs } from '../upload/types/ingestor';
|
||||
|
||||
function Upload({
|
||||
receivedFile = [],
|
||||
@@ -40,6 +41,7 @@ function Upload({
|
||||
close: () => void;
|
||||
onSuccessfulUpload?: () => void;
|
||||
}) {
|
||||
const token = useSelector(selectToken);
|
||||
const [docName, setDocName] = useState(receivedFile[0]?.name);
|
||||
const [remoteName, setRemoteName] = useState('');
|
||||
const [files, setfiles] = useState<File[]>(receivedFile);
|
||||
@@ -297,12 +299,12 @@ function Upload({
|
||||
if ((progress?.percentage ?? 0) < 100) {
|
||||
timeoutID = setTimeout(() => {
|
||||
userService
|
||||
.getTaskStatus(progress?.taskId as string)
|
||||
.getTaskStatus(progress?.taskId as string, null)
|
||||
.then((data) => data.json())
|
||||
.then((data) => {
|
||||
if (data.status == 'SUCCESS') {
|
||||
if (data.result.limited === true) {
|
||||
getDocs().then((data) => {
|
||||
getDocs(token).then((data) => {
|
||||
dispatch(setSourceDocs(data));
|
||||
dispatch(
|
||||
setSelectedDocs(
|
||||
@@ -322,7 +324,7 @@ function Upload({
|
||||
},
|
||||
);
|
||||
} else {
|
||||
getDocs().then((data) => {
|
||||
getDocs(token).then((data) => {
|
||||
dispatch(setSourceDocs(data));
|
||||
const docIds = new Set(
|
||||
(Array.isArray(sourceDocs) &&
|
||||
@@ -413,6 +415,7 @@ function Upload({
|
||||
}, 3000);
|
||||
};
|
||||
xhr.open('POST', `${apiHost + '/api/upload'}`);
|
||||
xhr.setRequestHeader('Authorization', `Bearer ${token}`);
|
||||
xhr.send(formData);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user