Skip to content

Commit

Permalink
Merge pull request #1222 from PublicisSapient/dev/update-login-page
Browse files Browse the repository at this point in the history
Update login page and add copyright footer
  • Loading branch information
hirbabar committed Jul 23, 2024
2 parents ad19bb5 + b87b714 commit 9af6cb4
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 86 deletions.
3 changes: 2 additions & 1 deletion central-auth-service/central-login-ui-react/.env
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
REACT_APP_PSKnowHOW=
REACT_APP_DNS=
REACT_APP_SPEED_SUITE=
REACT_APP_SPEED_SUITE=
REACT_APP_LOGIN_BUTTON_TEXT=
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 5 additions & 2 deletions central-auth-service/central-login-ui-react/src/Routes.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React from "react";
import { Routes, Route, Navigate } from "react-router-dom";
import {Routes, Route, Navigate} from 'react-router-dom';
import { Img } from "./components/Img";
import StatusPage from './pages/status';
import FooterLayout from './components/FooterLayout';
const LoginPage = React.lazy(() => import("./pages/login"));
const ForgotPasswordPage = React.lazy(() => import('./pages/forgot-password'));
const ResetPasswordPage = React.lazy(() => import('./pages/reset-password'));
Expand All @@ -10,11 +11,12 @@ const ProjectRoutes = () => {
const search = window.location.href;
return (
<React.Suspense fallback={<div className="w-full h-screen text-center"><Img
src={`${process.env.PUBLIC_URL}/images/spinner-black.png`} height='20'
src={`${process.env.PUBLIC_URL}/images/spinner-black.png`} height="20"
className="spinner mb-px ml-2"
alt={`Spinner`}
/></div>}>
{/* <Router> */}
<FooterLayout>
<Routes>
<Route path="/forgot-password" element={<ForgotPasswordPage />} />
<Route path="/reset-password" element={< ResetPasswordPage />} />
Expand All @@ -23,6 +25,7 @@ const ProjectRoutes = () => {
<Route path="/" element={<LoginPage search={search}/>} />
<Route path="*" element={<Navigate to="/" />}></Route>
</Routes>
</FooterLayout>
{/* </Router> */}
</React.Suspense>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
footer {
color: #383838;
text-align: center;
padding: 1rem 0;
position: fixed;
bottom: 0;
width: 100%;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react';
import './index.css';

const _currentYear = new Date().getFullYear();

const Footer = () => {
return (
<footer>
<p>© {_currentYear} Publicis Sapient. All rights reserved.</p>
</footer>
);
};

export default Footer;
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';
import Footer from '../Footer';

const FooterLayout = ({ children }) => {
return (
<div>
<main>{children}</main>
<Footer />
</div>
);
};

export default FooterLayout;
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import BgItem from "../../components/BgItem";

const bg = ['KnowHOWGroup', 'RetrosGroup', 'APGroup'];
const bg = ['APGroup', 'KnowHOWGroup', 'RetrosGroup'];

const SuiteLogos = () => {
const speedSuite = process.env.NODE_ENV === 'production' ? window.env['REACT_APP_SPEED_SUITE'] : process.env.REACT_APP_SPEED_SUITE;
Expand Down
156 changes: 94 additions & 62 deletions central-auth-service/central-login-ui-react/src/pages/login/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ import '../../App.css';
import SuiteLogos from '../../components/SuiteLogos';
import PSLogo from '../../components/PSLogo';


const _loginButtonText = process.env.NODE_ENV === 'production' ? window.env.REACT_APP_LOGIN_BUTTON_TEXT : process.env.REACT_APP_LOGIN_BUTTON_TEXT;

const LoginPage = ({search}) => {

const [error, setError] = useState('');
const [showLoader, setShowLoader] = useState(false);
const [showSAMLLoader, setShowSAMLLoader] = useState(false);
const [showLoginWithCredentials, setShowLoginWithCredentials] = useState(false);
const methods = useForm({ mode: 'all' });
const userNamePattern = /^[A-Za-z0-9]+$/;

Expand All @@ -25,6 +26,10 @@ const LoginPage = ({search}) => {
window.location.href = apiProvider.handleSamlLogin;
}

const ShowLoginWithCredentials = () => {
setShowLoginWithCredentials(!showLoginWithCredentials);
}

const PerformCredentialLogin = (data) => {
setShowLoader(true);
apiProvider.handleUserStandardLogin({
Expand Down Expand Up @@ -84,9 +89,9 @@ const LoginPage = ({search}) => {
<div className="w-2/5 p-12 h-screen bg-white-A700">

<PSLogo/>
<div className='w-full mt-4 mb-2'>
<div className='w-full mt-8 mb-8'>
<Text
className="text-left text-lg"
className="text-center text-lg"
size="txtPoppinsBold44"
>
Welcome back!
Expand All @@ -110,69 +115,96 @@ const LoginPage = ({search}) => {
} clickFn={PerformSAMLLogin}
>
<Text className="text-white text-left">
Login with SSO
{_loginButtonText ? _loginButtonText : 'Login with SSO'}
</Text>
</Button>
<Text className='text-left mt-4' size='txtPoppinsRegular16'>Or login with credentials</Text>
<FormProvider {...methods}>
<form noValidate autoComplete='off'>
<FloatingInput type="text" placeHolder="User Name" id="userName" className={`mt-4 ${(methods.formState.errors['userName']) ? 'Invalid' : ''}`}
validationRules={{
"required": "Field is required",
"minLength": {
"value": 6,
"message": "Field should contain at least 6 characters"
},
"pattern": {
"value": userNamePattern,
"message": 'Username can only contain letters and numbers'
}
}}>
</FloatingInput>
{(methods.formState.errors['userName']) && <p className='errMsg'>{methods.formState.errors['userName'].message}</p>}
<FloatingInput type="password" placeHolder="Password" id="password" className={`mt-4 ${(methods.formState.errors['password']) ? 'Invalid' : ''}`}
validationRules={{
"required": "Field is required",
"minLength": {
"value": 6,
"message": "Field should contain at least 6 characters"
}
}}>
</FloatingInput>
{(methods.formState.errors['password']) && <p className='errMsg'>{methods.formState.errors['password'].message}</p>}

<Button
color='blue_80'
variant='fill'
className="cursor-pointer flex min-h-[36px] items-center justify-center ml-0.5 md:ml-[0] mt-[18px] w-full"
clickFn={methods.handleSubmit(PerformCredentialLogin)}
rightIcon={
<>
<Img
className="h-5 mb-px ml-2"
src="images/img_arrowright.svg"
alt="arrow_right"
/>
{showLoader && <Img
src={`${process.env.PUBLIC_URL}/images/spinner.png`} height='20'
className="spinner mb-px ml-2"
alt={`Spinner`}
/>}
</>
}
>
<Text className="text-white text-left">
Login
</Text>
</Button>
{error && error.length > 0 && <p className='errMsg'>{error}</p>}
<Button
color={showLoginWithCredentials ? 'blue_80' : 'blue_800'}
className="cursor-pointer flex min-h-[36px] items-center justify-center ml-0.5 md:ml-[0] mt-[18px] w-full"
rightIcon={
<>
<Img
className="h-5 mb-px ml-2"
src="images/img_arrowright.svg"
alt="arrow_right"
style={{ transform: showLoginWithCredentials ? 'rotate(90deg)' : 'none' }}
/>
</>
} clickFn={ShowLoginWithCredentials}
>
<Text className="text-white text-left">
Login with credentials
</Text>
</Button>
{
showLoginWithCredentials &&
<>
<FormProvider {...methods}>
<form noValidate autoComplete="off">
<FloatingInput type="text" placeHolder="User Name" id="userName"
className={`mt-4 ${(methods.formState.errors['userName']) ? 'Invalid' : ''}`}
validationRules={{
'required': 'Field is required',
'minLength': {
'value': 6,
'message': 'Field should contain at least 6 characters',
},
'pattern': {
'value': userNamePattern,
'message': 'Username can only contain letters and numbers',
},
}}>
</FloatingInput>
{(methods.formState.errors['userName']) &&
<p className="errMsg">{methods.formState.errors['userName'].message}</p>}
<FloatingInput type="password" placeHolder="Password" id="password"
className={`mt-4 ${(methods.formState.errors['password']) ? 'Invalid' : ''}`}
validationRules={{
'required': 'Field is required',
'minLength': {
'value': 6,
'message': 'Field should contain at least 6 characters',
},
}}>
</FloatingInput>
{(methods.formState.errors['password']) &&
<p className="errMsg">{methods.formState.errors['password'].message}</p>}

<Button
color="blue_80"
variant="fill"
className="cursor-pointer flex min-h-[36px] items-center justify-center ml-0.5 md:ml-[0] mt-[18px] w-full"
clickFn={methods.handleSubmit(PerformCredentialLogin)}
rightIcon={
<>
<Img
className="h-5 mb-px ml-2"
src="images/img_arrowright.svg"
alt="arrow_right"
/>
{showLoader && <Img
src={`${process.env.PUBLIC_URL}/images/spinner.png`} height="20"
className="spinner mb-px ml-2"
alt={`Spinner`}
/>}
</>
}
>
<Text className="text-white text-left">
Login
</Text>
</Button>
{error && error.length > 0 && <p className="errMsg">{error}</p>}
</form>
</FormProvider>
<div className="routeContainer mt-4">
<NavLink to="/forgot-password">Forgot Password?</NavLink><br />
<p className='inline'>Dont have an account? </p>
</FormProvider>
<div className="routeContainer mt-4">
<NavLink to="/forgot-password">Forgot Password?</NavLink><br/>
<p className="inline">Dont have an account? </p>
<NavLink to="/register">Sign up here.</NavLink>
</div>
</div>
</>

}
</div>
</div>
);
Expand Down

0 comments on commit 9af6cb4

Please sign in to comment.