diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 41d81db..040e2d3 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -21,6 +21,10 @@ const SystemSetup = lazy(() => import('./pages/Authentication/SystemSetup')); const OnboardingSecuritySetup = lazy( () => import('./pages/Onboarding/security') ); + +// Onboarding v2 +const OnboardingFlow = lazy(() => import('./pages/OnboardingFlow')); + const OrganizationJobsView = lazy(() => import('./pages/Jobs')); const OrganizationToolsView = lazy(() => import('./pages/Tools')); const SystemSettingsView = lazy(() => import('./pages/SystemSettings')); @@ -75,6 +79,10 @@ function App() { element={} /> + } + /> } diff --git a/frontend/src/images/undraws/onboarding.png b/frontend/src/images/undraws/onboarding.png new file mode 100644 index 0000000..837a8b0 Binary files /dev/null and b/frontend/src/images/undraws/onboarding.png differ diff --git a/frontend/src/pages/OnboardingFlow/Steps/ConnectVectorDB/index.tsx b/frontend/src/pages/OnboardingFlow/Steps/ConnectVectorDB/index.tsx new file mode 100644 index 0000000..82e62a7 --- /dev/null +++ b/frontend/src/pages/OnboardingFlow/Steps/ConnectVectorDB/index.tsx @@ -0,0 +1,7 @@ +import React from 'react'; + +function ConnectVectorDB() { + return
ConnectVectorDB
; +} + +export default ConnectVectorDB; diff --git a/frontend/src/pages/OnboardingFlow/Steps/CreateOrganization/index.tsx b/frontend/src/pages/OnboardingFlow/Steps/CreateOrganization/index.tsx new file mode 100644 index 0000000..4eee811 --- /dev/null +++ b/frontend/src/pages/OnboardingFlow/Steps/CreateOrganization/index.tsx @@ -0,0 +1,7 @@ +import React from 'react'; + +function CreateOrganization() { + return
CreateOrganization
; +} + +export default CreateOrganization; diff --git a/frontend/src/pages/OnboardingFlow/Steps/CustomLogin/index.tsx b/frontend/src/pages/OnboardingFlow/Steps/CustomLogin/index.tsx new file mode 100644 index 0000000..104faa4 --- /dev/null +++ b/frontend/src/pages/OnboardingFlow/Steps/CustomLogin/index.tsx @@ -0,0 +1,7 @@ +import React from 'react'; + +function CustomLogin() { + return
CustomLogin
; +} + +export default CustomLogin; diff --git a/frontend/src/pages/OnboardingFlow/Steps/SecuritySettings/index.tsx b/frontend/src/pages/OnboardingFlow/Steps/SecuritySettings/index.tsx new file mode 100644 index 0000000..c56c234 --- /dev/null +++ b/frontend/src/pages/OnboardingFlow/Steps/SecuritySettings/index.tsx @@ -0,0 +1,7 @@ +import React from 'react'; + +function SecuritySettings() { + return
SecuritySettings
; +} + +export default SecuritySettings; diff --git a/frontend/src/pages/OnboardingFlow/Steps/SyncVectorDB/index.tsx b/frontend/src/pages/OnboardingFlow/Steps/SyncVectorDB/index.tsx new file mode 100644 index 0000000..3375b01 --- /dev/null +++ b/frontend/src/pages/OnboardingFlow/Steps/SyncVectorDB/index.tsx @@ -0,0 +1,7 @@ +import React from 'react'; + +function SyncVectorDB() { + return
SyncVectorDB
; +} + +export default SyncVectorDB; diff --git a/frontend/src/pages/OnboardingFlow/Steps/Welcome/index.tsx b/frontend/src/pages/OnboardingFlow/Steps/Welcome/index.tsx new file mode 100644 index 0000000..6a9f5fd --- /dev/null +++ b/frontend/src/pages/OnboardingFlow/Steps/Welcome/index.tsx @@ -0,0 +1,7 @@ +import React from 'react'; + +function Welcome() { + return
Welcome
; +} + +export default Welcome; diff --git a/frontend/src/pages/OnboardingFlow/index.tsx b/frontend/src/pages/OnboardingFlow/index.tsx new file mode 100644 index 0000000..4fd64d8 --- /dev/null +++ b/frontend/src/pages/OnboardingFlow/index.tsx @@ -0,0 +1,270 @@ +import { Link } from 'react-router-dom'; +import DefaultLayout from '../../layout/DefaultLayout'; +import Onboarding from '../../images/undraws/onboarding.png'; +import PreLoader from '../../components/Preloader'; +import { useEffect, useState } from 'react'; +import { CheckCircle, XCircle } from 'react-feather'; +import User from '../../models/user'; +import { APP_NAME, STORE_TOKEN, STORE_USER } from '../../utils/constants'; +import paths from '../../utils/paths'; +import validateSessionTokenForUser from '../../utils/session'; + +import CustomLogin from './Steps/CustomLogin'; +import SecuritySettings from './Steps/SecuritySettings'; +import CreateOrganization from './Steps/CreateOrganization'; +import ConnectVectorDB from './Steps/ConnectVectorDB'; +import SyncVectorDB from './Steps/SyncVectorDB'; + +type IStages = 'loading' | 'failed' | 'success' | 'ready'; +type FormTypes = { + target: { + email: { + value: string; + }; + password: { + value: string; + }; + }; +}; + +type IResult = { + user: any; + token: string | null; + error?: string | null; +}; + +const STEPS = { + custom_login: { + title: 'Create your custom login', + description: + 'This will be your account login information moving forward. The previous default login will become obsolete.', + component: CustomLogin, + }, + security_settings: { + title: 'Security Settings', + description: + 'You can limit your VectorAdmin installation to only allow sign ups from specific domains, or disable them totally and users must first be created by an admin user.', + component: SecuritySettings, + }, + create_organization: { + title: 'Create an organization', + description: + 'Organizations are where all your documents are stored. You can have multiple organizations, but you need at least one.', + component: CreateOrganization, + }, + connect_vector_db: { + title: 'Connect your vector database', + description: '', + component: ConnectVectorDB, + }, + sync_vector_db: { + title: 'Sync your vector database', + description: + 'VDMS can automatically sync existing information in your Pinecone namespaces so you can manage it easily. This process can take a long time to complete depending on how much data you already have embedded.', + component: SyncVectorDB, + }, +}; + +const SignIn = () => { + const [stage, setStage] = useState('ready'); + const [results, setResults] = useState({ + user: null, + token: null, + error: null, + }); + const resetStage = () => { + setResults({ user: null, token: null, error: null }); + setStage('ready'); + }; + const handleSubmit = async (e: React.FormEvent & FormTypes) => { + e.preventDefault(); + setStage('loading'); + const { user, token, error } = await User.login( + e.target.email.value, + e.target.password.value + ); + if (!token || !user) setStage('failed'); + if (!!token && !!user) setStage('success'); + setResults({ user, token, error }); + + if (!!token && !!user) { + window.localStorage.setItem(STORE_USER, JSON.stringify(user)); + window.localStorage.setItem(STORE_TOKEN, token); + window.location.replace( + user.role === 'root' ? paths.systemSetup() : paths.dashboard() + ); + } + }; + + // useEffect(() => { + // async function checkAuth() { + // const currentToken = window.localStorage.getItem(STORE_TOKEN); + // if (!currentToken) return false; + // const success = await validateSessionTokenForUser(); + // if (!success) { + // window.localStorage.removeItem(STORE_USER); + // window.localStorage.removeItem(STORE_TOKEN); + // return false; + // } + // window.location.replace(paths.dashboard()); + // } + // checkAuth(); + // }, []); + + return ( + +
+
+
+
+ Sign In +
+
+ +
+
+ {stage !== 'ready' ? ( + + ) : ( + + )} +
+
+
+
+
+ ); +}; + +function ShowStatus({ + stage, + results, + resetForm, +}: { + stage: IStages; + results: IResult; + resetForm: any; +}) { + if (stage === 'loading') { + return ( +
+ +

logging you in...

+
+ ); + } + + if (stage === 'failed') { + return ( +
+ +

+ We could not log you in - contact an admin. +

+

{results?.error}

+ +
+ ); + } + + if (stage === 'success') { + return ( +
+ +

Login was successful!

+

+ Redirecting you to the right place. +

+
+ ); + } + + return null; +} + +function LoginForm({ handleSubmit }: { handleSubmit: any }) { + return ( + <> +
+ {/* Render each step dynamically here */} + {/*
+
+ Login to + VectorAdmin +
+
+ + Welcome back, please login to your account. + +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+ +
+ +
+

+ Don't have a {APP_NAME} account?{' '} + + Sign Up + +

+
+
+
*/} + + ); +} + +export default SignIn;