diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 7224f2e9c0..8007b5ad13 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -120,6 +120,7 @@ export default function App() { {/* Onboarding Flow */} } /> + } /> diff --git a/frontend/src/components/EmbeddingSelection/AzureAiOptions/index.jsx b/frontend/src/components/EmbeddingSelection/AzureAiOptions/index.jsx index e7767900ae..c782c51f33 100644 --- a/frontend/src/components/EmbeddingSelection/AzureAiOptions/index.jsx +++ b/frontend/src/components/EmbeddingSelection/AzureAiOptions/index.jsx @@ -1,53 +1,55 @@ export default function AzureAiOptions({ settings }) { return ( - <> -
- - -
+
+
+
+ + +
-
- - -
+
+ + +
-
- - +
+ + +
- +
); } diff --git a/frontend/src/components/EmbeddingSelection/LocalAiOptions/index.jsx b/frontend/src/components/EmbeddingSelection/LocalAiOptions/index.jsx index 2b976e1428..6f81712c14 100644 --- a/frontend/src/components/EmbeddingSelection/LocalAiOptions/index.jsx +++ b/frontend/src/components/EmbeddingSelection/LocalAiOptions/index.jsx @@ -10,72 +10,72 @@ export default function LocalAiOptions({ settings }) { const [apiKey, setApiKey] = useState(settings?.LocalAiApiKey); return ( - <> +
-
- - setBasePathValue(e.target.value)} - onBlur={() => setBasePath(basePathValue)} - required={true} - autoComplete="off" - spellCheck={false} - /> -
- -
- - e.target.blur()} - defaultValue={settings?.EmbeddingModelMaxChunkLength} - required={false} - autoComplete="off" +
+
+ + setBasePathValue(e.target.value)} + onBlur={() => setBasePath(basePathValue)} + required={true} + autoComplete="off" + spellCheck={false} + /> +
+ -
-
-
-
-
-
+
+
+
+ +
- setApiKeyValue(e.target.value)} - onBlur={() => setApiKey(apiKeyValue)} - /> + setApiKeyValue(e.target.value)} + onBlur={() => setApiKey(apiKeyValue)} + /> +
- +
); } diff --git a/frontend/src/components/EmbeddingSelection/OpenAiOptions/index.jsx b/frontend/src/components/EmbeddingSelection/OpenAiOptions/index.jsx index f38f7c445e..dd00d67abd 100644 --- a/frontend/src/components/EmbeddingSelection/OpenAiOptions/index.jsx +++ b/frontend/src/components/EmbeddingSelection/OpenAiOptions/index.jsx @@ -1,34 +1,36 @@ export default function OpenAiOptions({ settings }) { return ( - <> -
- - +
+
+
+ + +
+
+ + +
-
- - -
- +
); } diff --git a/frontend/src/components/LLMSelection/AzureAiOptions/index.jsx b/frontend/src/components/LLMSelection/AzureAiOptions/index.jsx index 2978651016..ce54d3d60d 100644 --- a/frontend/src/components/LLMSelection/AzureAiOptions/index.jsx +++ b/frontend/src/components/LLMSelection/AzureAiOptions/index.jsx @@ -1,87 +1,92 @@ export default function AzureAiOptions({ settings }) { return ( - <> -
- - -
+
+
+
+ + +
-
- - -
+
+ + +
-
- - +
+ + +
-
- - -
+
+
+ + +
-
- - +
+ + +
+
- +
); } diff --git a/frontend/src/components/LLMSelection/OpenAiOptions/index.jsx b/frontend/src/components/LLMSelection/OpenAiOptions/index.jsx index fd2f876651..cbd83edb99 100644 --- a/frontend/src/components/LLMSelection/OpenAiOptions/index.jsx +++ b/frontend/src/components/LLMSelection/OpenAiOptions/index.jsx @@ -6,7 +6,7 @@ export default function OpenAiOptions({ settings }) { const [openAIKey, setOpenAIKey] = useState(settings?.OpenAiKey); return ( - <> +
- +
); } @@ -87,7 +87,7 @@ function OpenAIModelSelection({ apiKey, settings }) { @@ -102,7 +102,7 @@ function OpenAIModelSelection({ apiKey, settings }) { diff --git a/frontend/src/components/PrivateRoute/index.jsx b/frontend/src/components/PrivateRoute/index.jsx index 4640646321..165141bbb3 100644 --- a/frontend/src/components/PrivateRoute/index.jsx +++ b/frontend/src/components/PrivateRoute/index.jsx @@ -89,7 +89,7 @@ export function AdminRoute({ Component }) { if (isAuthd === null) return ; if (shouldRedirectToOnboarding) { - return ; + return ; } const user = userFromStorage(); @@ -110,7 +110,7 @@ export function ManagerRoute({ Component }) { if (isAuthd === null) return ; if (shouldRedirectToOnboarding) { - return ; + return ; } const user = userFromStorage(); diff --git a/frontend/src/components/VectorDBSelection/ChromaDBOptions/index.jsx b/frontend/src/components/VectorDBSelection/ChromaDBOptions/index.jsx new file mode 100644 index 0000000000..ae7af68fb8 --- /dev/null +++ b/frontend/src/components/VectorDBSelection/ChromaDBOptions/index.jsx @@ -0,0 +1,51 @@ +export default function ChromaDBOptions({ settings }) { + return ( +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ ); +} diff --git a/frontend/src/components/VectorDBSelection/LanceDBOptions/index.jsx b/frontend/src/components/VectorDBSelection/LanceDBOptions/index.jsx new file mode 100644 index 0000000000..942a3666da --- /dev/null +++ b/frontend/src/components/VectorDBSelection/LanceDBOptions/index.jsx @@ -0,0 +1,9 @@ +export default function LanceDBOptions() { + return ( +
+

+ There is no configuration needed for LanceDB. +

+
+ ); +} diff --git a/frontend/src/components/VectorDBSelection/PineconeDBOptions/index.jsx b/frontend/src/components/VectorDBSelection/PineconeDBOptions/index.jsx new file mode 100644 index 0000000000..5491f758c6 --- /dev/null +++ b/frontend/src/components/VectorDBSelection/PineconeDBOptions/index.jsx @@ -0,0 +1,55 @@ +export default function PineconeDBOptions({ settings }) { + return ( +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ ); +} diff --git a/frontend/src/components/VectorDBSelection/QDrantDBOptions/index.jsx b/frontend/src/components/VectorDBSelection/QDrantDBOptions/index.jsx new file mode 100644 index 0000000000..e1e9d90f68 --- /dev/null +++ b/frontend/src/components/VectorDBSelection/QDrantDBOptions/index.jsx @@ -0,0 +1,38 @@ +export default function QDrantDBOptions({ settings }) { + return ( +
+
+
+ + +
+ +
+ + +
+
+
+ ); +} diff --git a/frontend/src/components/VectorDBSelection/WeaviateDBOptions/index.jsx b/frontend/src/components/VectorDBSelection/WeaviateDBOptions/index.jsx new file mode 100644 index 0000000000..5d7494ed15 --- /dev/null +++ b/frontend/src/components/VectorDBSelection/WeaviateDBOptions/index.jsx @@ -0,0 +1,38 @@ +export default function WeaviateDBOptions({ settings }) { + return ( +
+
+
+ + +
+ +
+ + +
+
+
+ ); +} diff --git a/frontend/src/media/illustrations/create-workspace.png b/frontend/src/media/illustrations/create-workspace.png new file mode 100644 index 0000000000..8e31174e5d Binary files /dev/null and b/frontend/src/media/illustrations/create-workspace.png differ diff --git a/frontend/src/pages/OnboardingFlow/OnboardingModal/Steps/AppearanceSetup/index.jsx b/frontend/src/pages/OnboardingFlow/OnboardingModal/Steps/AppearanceSetup/index.jsx deleted file mode 100644 index 30e87b0ac6..0000000000 --- a/frontend/src/pages/OnboardingFlow/OnboardingModal/Steps/AppearanceSetup/index.jsx +++ /dev/null @@ -1,145 +0,0 @@ -import React, { memo, useEffect, useState } from "react"; -import System from "@/models/system"; -import AnythingLLM from "@/media/logo/anything-llm.png"; -import useLogo from "@/hooks/useLogo"; -import { Plus } from "@phosphor-icons/react"; -import showToast from "@/utils/toast"; - -function AppearanceSetup({ prevStep, nextStep }) { - const { logo: _initLogo, setLogo: _setLogo } = useLogo(); - const [logo, setLogo] = useState(""); - const [isDefaultLogo, setIsDefaultLogo] = useState(true); - - useEffect(() => { - async function logoInit() { - setLogo(_initLogo || ""); - const _isDefaultLogo = await System.isDefaultLogo(); - setIsDefaultLogo(_isDefaultLogo); - } - logoInit(); - }, [_initLogo]); - - const handleFileUpload = async (event) => { - const file = event.target.files[0]; - if (!file) return false; - - const objectURL = URL.createObjectURL(file); - setLogo(objectURL); - - const formData = new FormData(); - formData.append("logo", file); - const { success, error } = await System.uploadLogo(formData); - if (!success) { - showToast(`Failed to upload logo: ${error}`, "error"); - setLogo(_initLogo); - return; - } - - const logoURL = await System.fetchLogo(); - _setLogo(logoURL); - - showToast("Image uploaded successfully.", "success"); - setIsDefaultLogo(false); - }; - - const handleRemoveLogo = async () => { - setLogo(""); - setIsDefaultLogo(true); - - const { success, error } = await System.removeCustomLogo(); - if (!success) { - console.error("Failed to remove logo:", error); - showToast(`Failed to remove logo: ${error}`, "error"); - const logoURL = await System.fetchLogo(); - setLogo(logoURL); - setIsDefaultLogo(false); - return; - } - - const logoURL = await System.fetchLogo(); - _setLogo(logoURL); - - showToast("Image successfully removed.", "success"); - }; - - return ( -
-
-
-

Custom Logo

-

- Upload your custom logo to make your chatbot yours. -

-
-
- (e.target.src = AnythingLLM)} - /> -
- - -
-
-
-
- -
- - -
-
-
- ); -} -export default memo(AppearanceSetup); diff --git a/frontend/src/pages/OnboardingFlow/OnboardingModal/Steps/CreateFirstWorkspace/index.jsx b/frontend/src/pages/OnboardingFlow/OnboardingModal/Steps/CreateFirstWorkspace/index.jsx deleted file mode 100644 index d2624ef6a1..0000000000 --- a/frontend/src/pages/OnboardingFlow/OnboardingModal/Steps/CreateFirstWorkspace/index.jsx +++ /dev/null @@ -1,68 +0,0 @@ -import React, { memo } from "react"; -import { useNavigate } from "react-router-dom"; -import paths from "@/utils/paths"; -import Workspace from "@/models/workspace"; - -function CreateFirstWorkspace({ prevStep }) { - const navigate = useNavigate(); - - const handleCreate = async (e) => { - e.preventDefault(); - const form = new FormData(e.target); - const { workspace, error } = await Workspace.new({ - name: form.get("name"), - onboardingComplete: true, - }); - if (!!workspace) { - navigate(paths.home()); - } else { - alert(error); - } - }; - - return ( -
-
-
-
-
-
- - -
-
-
-
-
- - -
-
-
- ); -} -export default memo(CreateFirstWorkspace); diff --git a/frontend/src/pages/OnboardingFlow/OnboardingModal/Steps/EmbeddingSelection/index.jsx b/frontend/src/pages/OnboardingFlow/OnboardingModal/Steps/EmbeddingSelection/index.jsx deleted file mode 100644 index 98e1262a04..0000000000 --- a/frontend/src/pages/OnboardingFlow/OnboardingModal/Steps/EmbeddingSelection/index.jsx +++ /dev/null @@ -1,136 +0,0 @@ -import React, { memo, useEffect, useState } from "react"; -import AnythingLLMIcon from "@/media/logo/anything-llm-icon.png"; -import OpenAiLogo from "@/media/llmprovider/openai.png"; -import AzureOpenAiLogo from "@/media/llmprovider/azure.png"; -import LocalAiLogo from "@/media/llmprovider/localai.png"; -import System from "@/models/system"; -import PreLoader from "@/components/Preloader"; -import LLMProviderOption from "@/components/LLMSelection/LLMProviderOption"; -import OpenAiOptions from "@/components/EmbeddingSelection/OpenAiOptions"; -import AzureAiOptions from "@/components/EmbeddingSelection/AzureAiOptions"; -import LocalAiOptions from "@/components/EmbeddingSelection/LocalAiOptions"; -import NativeEmbeddingOptions from "@/components/EmbeddingSelection/NativeEmbeddingOptions"; - -function EmbeddingSelection({ nextStep, prevStep, currentStep }) { - const [embeddingChoice, setEmbeddingChoice] = useState("native"); - const [settings, setSettings] = useState(null); - const [loading, setLoading] = useState(true); - const updateChoice = (selection) => { - setEmbeddingChoice(selection); - }; - - useEffect(() => { - async function fetchKeys() { - const _settings = await System.keys(); - setSettings(_settings); - setEmbeddingChoice(_settings?.EmbeddingEngine || "native"); - setLoading(false); - } - fetchKeys(); - }, [currentStep]); - - const handleSubmit = async (e) => { - e.preventDefault(); - const form = e.target; - const data = {}; - const formData = new FormData(form); - for (var [key, value] of formData.entries()) data[key] = value; - const { error } = await System.updateSystem(data); - if (error) { - alert(`Failed to save LLM settings: ${error}`, "error"); - return; - } - nextStep("vector_database"); - return; - }; - - if (loading) - return ( -
- -
- ); - - return ( -
-
-
-
- Embedding Provider -
-
- - - - - -
-
- {embeddingChoice === "native" && } - {embeddingChoice === "openai" && ( - - )} - {embeddingChoice === "azure" && ( - - )} - {embeddingChoice === "localai" && ( - - )} -
-
-
- - -
-
-
- ); -} - -export default memo(EmbeddingSelection); diff --git a/frontend/src/pages/OnboardingFlow/OnboardingModal/Steps/LLMSelection/index.jsx b/frontend/src/pages/OnboardingFlow/OnboardingModal/Steps/LLMSelection/index.jsx deleted file mode 100644 index 850dea3c2e..0000000000 --- a/frontend/src/pages/OnboardingFlow/OnboardingModal/Steps/LLMSelection/index.jsx +++ /dev/null @@ -1,183 +0,0 @@ -import React, { memo, useEffect, useState } from "react"; -import AnythingLLMIcon from "@/media/logo/anything-llm-icon.png"; -import OpenAiLogo from "@/media/llmprovider/openai.png"; -import AzureOpenAiLogo from "@/media/llmprovider/azure.png"; -import AnthropicLogo from "@/media/llmprovider/anthropic.png"; -import GeminiLogo from "@/media/llmprovider/gemini.png"; -import OllamaLogo from "@/media/llmprovider/ollama.png"; -import LMStudioLogo from "@/media/llmprovider/lmstudio.png"; -import LocalAiLogo from "@/media/llmprovider/localai.png"; -import System from "@/models/system"; -import PreLoader from "@/components/Preloader"; -import LLMProviderOption from "@/components/LLMSelection/LLMProviderOption"; -import OpenAiOptions from "@/components/LLMSelection/OpenAiOptions"; -import AzureAiOptions from "@/components/LLMSelection/AzureAiOptions"; -import AnthropicAiOptions from "@/components/LLMSelection/AnthropicAiOptions"; -import LMStudioOptions from "@/components/LLMSelection/LMStudioOptions"; -import LocalAiOptions from "@/components/LLMSelection/LocalAiOptions"; -import NativeLLMOptions from "@/components/LLMSelection/NativeLLMOptions"; -import GeminiLLMOptions from "@/components/LLMSelection/GeminiLLMOptions"; -import OllamaLLMOptions from "@/components/LLMSelection/OllamaLLMOptions"; - -function LLMSelection({ nextStep, prevStep, currentStep }) { - const [llmChoice, setLLMChoice] = useState("openai"); - const [settings, setSettings] = useState(null); - const [loading, setLoading] = useState(true); - - const updateLLMChoice = (selection) => { - setLLMChoice(selection); - }; - - useEffect(() => { - async function fetchKeys() { - const _settings = await System.keys(); - setSettings(_settings); - setLLMChoice(_settings?.LLMProvider || "openai"); - setLoading(false); - } - - if (currentStep === "llm_preference") { - fetchKeys(); - } - }, []); - - const handleSubmit = async (e) => { - e.preventDefault(); - const form = e.target; - const data = {}; - const formData = new FormData(form); - for (var [key, value] of formData.entries()) data[key] = value; - const { error } = await System.updateSystem(data); - if (error) { - alert(`Failed to save LLM settings: ${error}`, "error"); - return; - } - nextStep("embedding_preferences"); - }; - - if (loading) - return ( -
- -
- ); - - return ( -
-
-
-
- LLM Providers -
-
- - - - - - - - - {!window.location.hostname.includes("useanything.com") && ( - - )} -
-
- {llmChoice === "openai" && } - {llmChoice === "azure" && } - {llmChoice === "anthropic" && ( - - )} - {llmChoice === "gemini" && } - {llmChoice === "lmstudio" && ( - - )} - {llmChoice === "localai" && } - {llmChoice === "ollama" && } - {llmChoice === "native" && } -
-
-
- - -
-
-
- ); -} - -export default memo(LLMSelection); diff --git a/frontend/src/pages/OnboardingFlow/OnboardingModal/Steps/MultiUserSetup/index.jsx b/frontend/src/pages/OnboardingFlow/OnboardingModal/Steps/MultiUserSetup/index.jsx deleted file mode 100644 index 71310abfca..0000000000 --- a/frontend/src/pages/OnboardingFlow/OnboardingModal/Steps/MultiUserSetup/index.jsx +++ /dev/null @@ -1,117 +0,0 @@ -import React, { useState, memo } from "react"; -import System from "@/models/system"; -import { AUTH_TIMESTAMP, AUTH_TOKEN, AUTH_USER } from "@/utils/constants"; -import debounce from "lodash.debounce"; - -// Multi-user mode step -function MultiUserSetup({ nextStep, prevStep }) { - const [username, setUsername] = useState(""); - const [password, setPassword] = useState(""); - - const handleSubmit = async (e) => { - e.preventDefault(); - const form = e.target; - const formData = new FormData(form); - const data = { - username: formData.get("username"), - password: formData.get("password"), - }; - const { success, error } = await System.setupMultiUser(data); - if (!success) { - alert(error); - return; - } - - // Auto-request token with credentials that was just set so they - // are not redirected to login after completion. - const { user, token } = await System.requestToken(data); - window.localStorage.setItem(AUTH_USER, JSON.stringify(user)); - window.localStorage.setItem(AUTH_TOKEN, token); - window.localStorage.removeItem(AUTH_TIMESTAMP); - - nextStep("data_handling"); - }; - - const setNewUsername = (e) => setUsername(e.target.value); - const setNewPassword = (e) => setPassword(e.target.value); - const handleUsernameChange = debounce(setNewUsername, 500); - const handlePasswordChange = debounce(setNewPassword, 500); - return ( -
-
-
-
-
-
- - -
-
- - -
-

- Username must be at least 6 characters long. Password must be at - least 8 characters long. -

-
-
-
-
-
- By default, you will be the only admin. As an admin you will need to - create accounts for all new users or admins. Do not lose your - password as only admins can reset passwords. -
-
- - -
-
-
-
- ); -} -export default memo(MultiUserSetup); diff --git a/frontend/src/pages/OnboardingFlow/OnboardingModal/Steps/PasswordProtection/index.jsx b/frontend/src/pages/OnboardingFlow/OnboardingModal/Steps/PasswordProtection/index.jsx deleted file mode 100644 index 4504288e6a..0000000000 --- a/frontend/src/pages/OnboardingFlow/OnboardingModal/Steps/PasswordProtection/index.jsx +++ /dev/null @@ -1,103 +0,0 @@ -import React, { memo, useState } from "react"; -import System from "@/models/system"; -import { AUTH_TIMESTAMP, AUTH_TOKEN, AUTH_USER } from "@/utils/constants"; -import debounce from "lodash.debounce"; - -function PasswordProtection({ nextStep, prevStep }) { - const [password, setPassword] = useState(""); - const handleSubmit = async (e) => { - e.preventDefault(); - const form = e.target; - const formData = new FormData(form); - const { error } = await System.updateSystemPassword({ - usePassword: true, - newPassword: formData.get("password"), - }); - - if (error) { - alert(`Failed to set password: ${error}`, "error"); - return; - } - - // Auto-request token with password that was just set so they - // are not redirected to login after completion. - const { token } = await System.requestToken({ - password: formData.get("password"), - }); - window.localStorage.removeItem(AUTH_USER); - window.localStorage.removeItem(AUTH_TIMESTAMP); - window.localStorage.setItem(AUTH_TOKEN, token); - - nextStep("data_handling"); - return; - }; - - const handleSkip = () => { - nextStep("data_handling"); - }; - - const setNewPassword = (e) => setPassword(e.target.value); - const handlePasswordChange = debounce(setNewPassword, 500); - return ( -
-
-
-
-
-
- -

- must be at least 8 characters. -

-
- -
-
-
-
- - -
- - -
-
-
-
- ); -} -export default memo(PasswordProtection); diff --git a/frontend/src/pages/OnboardingFlow/OnboardingModal/Steps/UserModeSelection/index.jsx b/frontend/src/pages/OnboardingFlow/OnboardingModal/Steps/UserModeSelection/index.jsx deleted file mode 100644 index b78c325330..0000000000 --- a/frontend/src/pages/OnboardingFlow/OnboardingModal/Steps/UserModeSelection/index.jsx +++ /dev/null @@ -1,47 +0,0 @@ -import React, { memo } from "react"; - -// How many people will be using your instance step -function UserModeSelection({ nextStep, prevStep }) { - const justMeClicked = () => { - nextStep("password_protection"); - }; - - const myTeamClicked = () => { - nextStep("multi_user_mode"); - }; - - return ( -
-
-
- How many people will be using your instance? -
-
- - -
-
-
- -
-
- ); -} - -export default memo(UserModeSelection); diff --git a/frontend/src/pages/OnboardingFlow/OnboardingModal/Steps/UserQuestionnaire/index.jsx b/frontend/src/pages/OnboardingFlow/OnboardingModal/Steps/UserQuestionnaire/index.jsx deleted file mode 100644 index a0cb97fd75..0000000000 --- a/frontend/src/pages/OnboardingFlow/OnboardingModal/Steps/UserQuestionnaire/index.jsx +++ /dev/null @@ -1,240 +0,0 @@ -import { COMPLETE_QUESTIONNAIRE } from "@/utils/constants"; -import paths from "@/utils/paths"; -import { CheckCircle, Circle } from "@phosphor-icons/react"; -import React, { memo } from "react"; - -async function sendQuestionnaire({ email, useCase, comment }) { - if (import.meta.env.DEV) return; - return fetch(`https://onboarding-wxich7363q-uc.a.run.app`, { - method: "POST", - body: JSON.stringify({ - email, - useCase, - comment, - sourceId: "0VRjqHh6Vukqi0x0Vd0n/m8JuT7k8nOz", - }), - }) - .then(() => { - window.localStorage.setItem(COMPLETE_QUESTIONNAIRE, true); - console.log(`✅ Questionnaire responses sent.`); - }) - .catch((error) => { - console.error(`sendQuestionnaire`, error.message); - }); -} - -function UserQuestionnaire({ nextStep, prevStep }) { - const handleSubmit = async (e) => { - e.preventDefault(); - const form = e.target; - const formData = new FormData(form); - nextStep("create_workspace"); - - await sendQuestionnaire({ - email: formData.get("email"), - useCase: formData.get("use_case") || "other", - comment: formData.get("comment") || null, - }); - return; - }; - - const handleSkip = () => { - nextStep("create_workspace"); - }; - - if (!!window?.localStorage?.getItem(COMPLETE_QUESTIONNAIRE)) { - return ( -
-
-
- -

Thank you for your feedback!

- - team@mintplexlabs.com - -
-
- -
- - -
- - -
-
-
- ); - } - - return ( -
-
-
-
-
-
- -
- -
-
- -
-
-
- -
- -
-
- - - -
-
- - - -
-
- - - -
-
-
-
- -
-
-
- -
-