mirror of
https://github.com/Mintplex-Labs/vector-admin.git
synced 2026-07-19 21:23:38 -04:00
WIP onboarding flow skeleton
This commit is contained in:
@@ -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={<PrivateRoute Component={DocumentView} />}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="/onboarding-setup"
|
||||
element={<PrivateRoute Component={OnboardingFlow} />}
|
||||
/>
|
||||
<Route
|
||||
path="/onboarding"
|
||||
element={<PrivateRoute Component={OnboardingHome} />}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 45 KiB |
@@ -0,0 +1,7 @@
|
||||
import React from 'react';
|
||||
|
||||
function ConnectVectorDB() {
|
||||
return <div>ConnectVectorDB</div>;
|
||||
}
|
||||
|
||||
export default ConnectVectorDB;
|
||||
@@ -0,0 +1,7 @@
|
||||
import React from 'react';
|
||||
|
||||
function CreateOrganization() {
|
||||
return <div>CreateOrganization</div>;
|
||||
}
|
||||
|
||||
export default CreateOrganization;
|
||||
@@ -0,0 +1,7 @@
|
||||
import React from 'react';
|
||||
|
||||
function CustomLogin() {
|
||||
return <div>CustomLogin</div>;
|
||||
}
|
||||
|
||||
export default CustomLogin;
|
||||
@@ -0,0 +1,7 @@
|
||||
import React from 'react';
|
||||
|
||||
function SecuritySettings() {
|
||||
return <div>SecuritySettings</div>;
|
||||
}
|
||||
|
||||
export default SecuritySettings;
|
||||
@@ -0,0 +1,7 @@
|
||||
import React from 'react';
|
||||
|
||||
function SyncVectorDB() {
|
||||
return <div>SyncVectorDB</div>;
|
||||
}
|
||||
|
||||
export default SyncVectorDB;
|
||||
@@ -0,0 +1,7 @@
|
||||
import React from 'react';
|
||||
|
||||
function Welcome() {
|
||||
return <div>Welcome</div>;
|
||||
}
|
||||
|
||||
export default Welcome;
|
||||
@@ -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<IStages>('ready');
|
||||
const [results, setResults] = useState<IResult>({
|
||||
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 (
|
||||
<DefaultLayout>
|
||||
<div className="">
|
||||
<div className="flex flex-wrap items-center">
|
||||
<div className="hidden w-full xl:block xl:w-1/2">
|
||||
<div>
|
||||
<img src={Onboarding} alt="Sign In" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full border-stroke xl:w-1/2">
|
||||
<div className="w-full p-4 sm:p-12.5 xl:p-17.5">
|
||||
{stage !== 'ready' ? (
|
||||
<ShowStatus
|
||||
stage={stage}
|
||||
results={results}
|
||||
resetForm={resetStage}
|
||||
/>
|
||||
) : (
|
||||
<LoginForm handleSubmit={handleSubmit} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</DefaultLayout>
|
||||
);
|
||||
};
|
||||
|
||||
function ShowStatus({
|
||||
stage,
|
||||
results,
|
||||
resetForm,
|
||||
}: {
|
||||
stage: IStages;
|
||||
results: IResult;
|
||||
resetForm: any;
|
||||
}) {
|
||||
if (stage === 'loading') {
|
||||
return (
|
||||
<div className="flex h-auto w-full flex-col items-center justify-center gap-y-2">
|
||||
<PreLoader />
|
||||
<p className="text-gray-500">logging you in...</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (stage === 'failed') {
|
||||
return (
|
||||
<div className="flex h-auto w-full flex-col items-center justify-center gap-y-2">
|
||||
<XCircle className="h-20 w-20 text-red-400" />
|
||||
<p className="text-red-500">
|
||||
We could not log you in - contact an admin.
|
||||
</p>
|
||||
<p className="text-xs text-red-500">{results?.error}</p>
|
||||
<button className="text-blue-400" onClick={resetForm}>
|
||||
Try Again →
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (stage === 'success') {
|
||||
return (
|
||||
<div className="flex h-auto w-full flex-col items-center justify-center gap-y-2">
|
||||
<CheckCircle className="h-20 w-20 text-green-400" />
|
||||
<p className="text-center text-green-500">Login was successful!</p>
|
||||
<p className="text-center text-xs text-gray-400">
|
||||
Redirecting you to the right place.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function LoginForm({ handleSubmit }: { handleSubmit: any }) {
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
style={{
|
||||
background: `
|
||||
radial-gradient(circle at center, transparent 40%, black 100%),
|
||||
linear-gradient(180deg, #85F8FF 0%, #65A6F2 100%)
|
||||
`,
|
||||
width: '575px',
|
||||
filter: 'blur(150px)',
|
||||
opacity: '0.5',
|
||||
}}
|
||||
className="absolute right-0 top-0 z-0 h-full w-full"
|
||||
/>
|
||||
{/* Render each step dynamically here */}
|
||||
{/* <div className="relative z-10 flex flex-col items-center">
|
||||
<div className="mb-3 flex justify-center gap-x-2 text-center">
|
||||
<span className="text-2xl font-bold text-white">Login to</span>
|
||||
<span className="text-2xl font-bold text-sky-300"> VectorAdmin</span>
|
||||
</div>
|
||||
<div className="mb-11 w-[308.65px] text-center">
|
||||
<span className="mt-3 text-sm text-white text-opacity-90">
|
||||
Welcome back, please login to your account.
|
||||
</span>
|
||||
</div>
|
||||
<form onSubmit={handleSubmit} className="z-10">
|
||||
<div className="mb-3.5">
|
||||
<div className="">
|
||||
<input
|
||||
required={true}
|
||||
type="email"
|
||||
name="email"
|
||||
placeholder="Enter your email"
|
||||
className="h-11 w-[300px] rounded-lg bg-neutral-800/60 p-2.5 text-white shadow-lg transition-all duration-300 focus:scale-105"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mb-9">
|
||||
<div className="">
|
||||
<input
|
||||
required={true}
|
||||
type="password"
|
||||
name="password"
|
||||
min={8}
|
||||
placeholder={`Your ${APP_NAME} password`}
|
||||
className="h-11 w-[300px] rounded-lg bg-neutral-800/60 p-2.5 text-white shadow-lg transition-all duration-300 focus:scale-105"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mb-5">
|
||||
<button
|
||||
type="submit"
|
||||
className="h-11
|
||||
w-[300px] items-center rounded-lg bg-white p-2 text-center text-sm font-bold leading-tight text-neutral-700 shadow-lg transition-all duration-300 hover:scale-105 hover:bg-opacity-90"
|
||||
>
|
||||
Sign In
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="mt-6 text-center text-sm text-white/90">
|
||||
<p>
|
||||
Don't have a {APP_NAME} account?{' '}
|
||||
<Link
|
||||
to={paths.signUp()}
|
||||
className="font-semibold transition-all duration-300 hover:underline"
|
||||
>
|
||||
Sign Up
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
</div> */}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default SignIn;
|
||||
Reference in New Issue
Block a user