Skip to content

Commit

Permalink
Merge pull request #614 from etn-ccis/feature/5866-okta-login-full-sc…
Browse files Browse the repository at this point in the history
…reen

Feature/5866 okta login full screen
  • Loading branch information
shubham-eaton authored Aug 1, 2024
2 parents cbb790f + 692a496 commit 23a6efb
Show file tree
Hide file tree
Showing 11 changed files with 230 additions and 14 deletions.
1 change: 1 addition & 0 deletions login-workflow/src/contexts/SharedDictionaries/chinese.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const resources: CommonTranslationsFile = {
DONE: '完成',
CONTINUE: '继续',
LOG_IN: '登录',
OKTA_LOG_IN: '使用 Okta 登录',
LOG_OUT: '登出',
CLICK_BUTTON: '点击按钮',
UPDATE_REDUX: '点击按钮以更新redux中存的值',
Expand Down
1 change: 1 addition & 0 deletions login-workflow/src/contexts/SharedDictionaries/english.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const resources: CommonTranslationsFile = {
CONTINUE: 'Continue',
DONE: 'Done',
LOG_IN: 'Log In',
OKTA_LOG_IN: 'Sign In With Okta',
LOG_OUT: 'Log Out',
CLICK_BUTTON: 'Click the button',
UPDATE_REDUX: 'Click the button to update the redux store value!',
Expand Down
1 change: 1 addition & 0 deletions login-workflow/src/contexts/SharedDictionaries/french.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const resources: CommonTranslationsFile = {
CONTINUE: 'Continuer',
DONE: 'Terminé',
LOG_IN: "S'identifier",
OKTA_LOG_IN: 'Se connecter avec Okta',
LOG_OUT: 'Se déconnecter',
CLICK_BUTTON: 'Cliquez sur le bouton',
UPDATE_REDUX: 'Cliquez sur le bouton pour mettre à jour la valeur du magasin redux!',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const resources: CommonTranslationsFile = {
CONTINUE: 'Continuar',
DONE: 'Concluir',
LOG_IN: 'Iniciar Sessão',
OKTA_LOG_IN: 'Iniciar Sessão com Okta',
LOG_OUT: 'Terminar Sessão',
CLICK_BUTTON: 'Clique no botão',
UPDATE_REDUX: 'Clique no botão para atualizar o valor de armazenamento redux!',
Expand Down
1 change: 1 addition & 0 deletions login-workflow/src/contexts/SharedDictionaries/spanish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const resources: CommonTranslationsFile = {
CONTINUE: 'Seguir',
DONE: 'Hecho',
LOG_IN: 'Iniciar sesión',
OKTA_LOG_IN: 'Iniciar sesión con Okta',
LOG_OUT: 'Cerrar sesión',
CLICK_BUTTON: '¡Haga clic en el botón',
UPDATE_REDUX: '¡Haga clic en el botón para actualizar el valor de la tienda redux!',
Expand Down
1 change: 1 addition & 0 deletions login-workflow/src/contexts/SharedDictionaries/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export type CommonTranslations = {
CONTINUE: string;
DONE: string;
LOG_IN: string;
OKTA_LOG_IN: string;
LOG_OUT: string;
CLICK_BUTTON: string;
UPDATE_REDUX: string;
Expand Down
88 changes: 88 additions & 0 deletions login-workflow/src/screens/OktaLoginScreen/OktaLoginScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import React, { useEffect, useState } from 'react';
import { useOktaAuth } from '@okta/okta-react';
import { useTranslation } from 'react-i18next';
import { OktaLoginScreenBase } from './OktaLoginScreenBase';
import { OktaLoginScreenProps } from './types';
import { useAuthContext } from '../../contexts';
import { useErrorManager } from '../../contexts/ErrorContext/useErrorManager';

/**
* Component that renders an okta login screen.
*
* @param {OktaLoginScreenProps} props - props of OktaLoginScreen
*
* @category Component
*/

export const OktaLoginScreen: React.FC<OktaLoginScreenProps> = (props) => {
const { authState, oktaAuth } = useOktaAuth();
const [isLoading, setIsLoading] = useState(!authState);
const { triggerError, errorManagerConfig } = useErrorManager();
const { t } = useTranslation();
const auth = useAuthContext();
const { navigate, routeConfig } = auth;
const errorDisplayConfig = {
...errorManagerConfig,
...props.errorDisplayConfig,
onClose: (): void => {
if (props.errorDisplayConfig && props.errorDisplayConfig.onClose) props.errorDisplayConfig.onClose();
if (errorManagerConfig.onClose) errorManagerConfig?.onClose();
},
};
const {
loginButtonLabel = t('bluiCommon:ACTIONS.OKTA_LOG_IN'),
showForgotPassword = true,
forgotPasswordLabel = t('bluiCommon:LABELS.FORGOT_PASSWORD'),
onForgotPassword = (): void => navigate(routeConfig.FORGOT_PASSWORD as string),
showSelfRegistration = true,
selfRegisterInstructions = t('bluiCommon:LABELS.NEED_ACCOUNT'),
selfRegisterButtonLabel = t('bluiCommon:ACTIONS.CREATE_ACCOUNT'),
onSelfRegister = (): void => navigate(routeConfig.REGISTER_SELF as string),
showContactSupport = true,
contactSupportLabel = t('bluiCommon:MESSAGES.CONTACT'),
onContactSupport = (): void => navigate(routeConfig.SUPPORT as string),
showCyberSecurityBadge = true,
projectImage,
header,
footer,
} = props;

useEffect(() => {
setIsLoading(!authState);
}, [authState]);

const handleOnLogin = async (): Promise<void> => {
try {
setIsLoading(true);
await oktaAuth.signInWithRedirect();
await props.onLogin?.();
} catch (_error) {
triggerError(_error as Error);
} finally {
setIsLoading(false);
}
};

return (
<OktaLoginScreenBase
loading={isLoading}
loginButtonLabel={loginButtonLabel}
onLogin={handleOnLogin}
showForgotPassword={showForgotPassword}
forgotPasswordLabel={forgotPasswordLabel}
onForgotPassword={onForgotPassword}
showSelfRegistration={showSelfRegistration}
selfRegisterButtonLabel={selfRegisterButtonLabel}
selfRegisterInstructions={selfRegisterInstructions}
onSelfRegister={onSelfRegister}
showContactSupport={showContactSupport}
contactSupportLabel={contactSupportLabel}
onContactSupport={onContactSupport}
errorDisplayConfig={errorDisplayConfig}
showCyberSecurityBadge={showCyberSecurityBadge}
projectImage={projectImage}
header={header}
footer={footer}
/>
);
};
106 changes: 92 additions & 14 deletions login-workflow/src/screens/OktaLoginScreen/OktaLoginScreenBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@ const useUtilityClasses = (ownerState: OktaLoginScreenProps): Record<OktaLoginSc
const slots = {
root: ['root'],
projectImageWrapper: ['projectImageWrapper'],
loginButtonWrapper: ['loginButtonWrapper'],
loginButton: ['loginButton'],
forgotPasswordWrapper: ['forgotPasswordWrapper'],
forgotPasswordLabel: ['forgotPasswordLabel'],
selfRegisterWrapper: ['selfRegisterWrapper'],
selfRegisterInstructionLabel: ['selfRegisterInstructionLabel'],
selfRegisterLabel: ['selfRegisterLabel'],
contactSupportWrapper: ['contactSupportWrapper'],
contactSupportLabel: ['contactSupportLabel'],
cyberSecurityBadgeWrapper: ['cyberSecurityBadgeWrapper'],
Expand All @@ -42,8 +48,15 @@ export const OktaLoginScreenBase: React.FC<OktaLoginScreenProps> = (props) => {
errorDisplayConfig,
loginButtonLabel,
onLogin,
showForgotPassword,
forgotPasswordLabel,
onForgotPassword,
showContactSupport,
showCyberSecurityBadge,
showSelfRegistration,
selfRegisterButtonLabel,
selfRegisterInstructions,
onSelfRegister,
contactSupportLabel,
footer,
onContactSupport,
Expand All @@ -54,6 +67,14 @@ export const OktaLoginScreenBase: React.FC<OktaLoginScreenProps> = (props) => {
if (onLogin) await onLogin();
};

const handleForgotPassword = (): void => {
if (onForgotPassword) onForgotPassword();
};

const handleSelfRegister = (): void => {
if (onSelfRegister) onSelfRegister();
};

const handleContactSupport = (): void => {
if (onContactSupport) onContactSupport();
};
Expand All @@ -79,25 +100,82 @@ export const OktaLoginScreenBase: React.FC<OktaLoginScreenProps> = (props) => {
</Box>

<ErrorManager {...errorDisplayConfig}>
<Button
className={defaultClasses.loginButton}
data-testid={defaultClasses.loginButton}
onClick={(): void => {
void handleOnLogin();
}}
variant="contained"
color="primary"
<Box
sx={{
width: '100%',
my: 5,
}}
className={defaultClasses.loginButtonWrapper}
data-testid={defaultClasses.loginButtonWrapper}
>
{loginButtonLabel || 'Sign In With Okta'}
</Button>
<Button
className={defaultClasses.loginButton}
data-testid={defaultClasses.loginButton}
onClick={(): void => {
void handleOnLogin();
}}
variant="contained"
color="primary"
sx={{
width: '100%',
}}
>
{loginButtonLabel || 'Sign In With Okta'}
</Button>
</Box>
</ErrorManager>

{showForgotPassword && (
<Box
sx={{ display: 'flex', justifyContent: 'center', textAlign: 'center' }}
className={defaultClasses.forgotPasswordWrapper}
data-testid={defaultClasses.forgotPasswordWrapper}
>
<Typography
variant="body2"
sx={LinkStyles}
onClick={handleForgotPassword}
className={defaultClasses.forgotPasswordLabel}
data-testid={defaultClasses.forgotPasswordLabel}
>
{forgotPasswordLabel || 'Forgot your password?'}
</Typography>
</Box>
)}

{showSelfRegistration && (
<Box
sx={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'column',
textAlign: 'center',
}}
className={defaultClasses.selfRegisterWrapper}
data-testid={defaultClasses.selfRegisterWrapper}
>
<Typography
variant="body2"
className={defaultClasses.selfRegisterInstructionLabel}
data-testid={defaultClasses.selfRegisterInstructionLabel}
>
{selfRegisterInstructions || 'Need an account?'}
</Typography>
<Typography
variant="body2"
sx={LinkStyles}
onClick={handleSelfRegister}
className={defaultClasses.selfRegisterLabel}
data-testid={defaultClasses.selfRegisterLabel}
>
{selfRegisterButtonLabel || 'Register now!'}
</Typography>
</Box>
)}

{showContactSupport && (
<Box
sx={{ display: 'flex', justifyContent: 'center', marginTop: 4, textAlign: 'center' }}
sx={{ display: 'flex', justifyContent: 'center', textAlign: 'center' }}
className={defaultClasses.contactSupportWrapper}
data-testid={defaultClasses.contactSupportWrapper}
>
Expand All @@ -107,11 +185,11 @@ export const OktaLoginScreenBase: React.FC<OktaLoginScreenProps> = (props) => {
</Box>
)}

<Box sx={{ display: 'flex', justifyContent: 'center' }}>{footer}</Box>
{footer && <Box sx={{ display: 'flex', justifyContent: 'center' }}>{footer}</Box>}

{showCyberSecurityBadge && (
<Box
sx={{ display: 'flex', justifyContent: 'center', marginTop: 2 }}
sx={{ display: 'flex', justifyContent: 'center' }}
className={defaultClasses.cyberSecurityBadgeWrapper}
data-testid={defaultClasses.cyberSecurityBadgeWrapper}
>
Expand Down
1 change: 1 addition & 0 deletions login-workflow/src/screens/OktaLoginScreen/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './OktaLoginScreenBase';
export * from './OktaLoginScreen';
37 changes: 37 additions & 0 deletions login-workflow/src/screens/OktaLoginScreen/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,43 @@ export type OktaLoginScreenProps = WorkflowCardBaseProps & {
*/
onLogin?: () => Promise<void> | void;

/**
* whether or not to show the 'forgot password' link
*/
showForgotPassword?: boolean;

/**
* The label for the 'forgot password' link
*/
forgotPasswordLabel?: string;

/**
* The callback function that is called when the 'forgot password' link is clicked
* @returns void
*/
onForgotPassword?: () => void;

/**
* whether or not to show the 'self registration' link
*/
showSelfRegistration?: boolean;

/**
* The label for the 'self registration' link
*/
selfRegisterButtonLabel?: string;

/**
* The instructions for the 'self registration' link
*/
selfRegisterInstructions?: string;

/**
* The callback function that is called when the 'self registration' link is clicked
* @returns void
*/
onSelfRegister?: () => void;

/**
* whether or not to show the 'contact support' link
*/
Expand Down
6 changes: 6 additions & 0 deletions login-workflow/src/screens/OktaLoginScreen/utilityClasses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@ import generateUtilityClass from '@mui/material/generateUtilityClass';
export type OktaLoginScreenClasses = {
root?: string;
projectImageWrapper?: string;
loginButtonWrapper?: string;
loginButton?: string;
forgotPasswordWrapper?: string;
forgotPasswordLabel?: string;
selfRegisterWrapper?: string;
selfRegisterInstructionLabel?: string;
selfRegisterLabel?: string;
contactSupportWrapper?: string;
contactSupportLabel?: string;
cyberSecurityBadgeWrapper?: string;
Expand Down

0 comments on commit 23a6efb

Please sign in to comment.