diff --git a/src/api/api.ts b/src/api/api.ts index 8485f9967..6abf95343 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -74,9 +74,14 @@ export const fornyInnloggingFetch = (environment: Environment): Promise { - return adaptFulfilledSessionDataFromAPI(result); - }); + }) + .then((result: any) => { + return adaptFulfilledSessionDataFromAPI(result); + }) + .catch((e) => { + window.dispatchEvent(new Event('INVALID_SESSION')); + throw new Error(`Error refreshing session [error: ${e}]`); + }); }; export const hentVarslerFetch = (VARSEL_API_URL: string): Promise => { diff --git a/src/komponenter/header/logoutWarning/LogoutWarning.module.scss b/src/komponenter/header/logoutWarning/LogoutWarning.module.scss index 08ada3079..4f5cf6102 100644 --- a/src/komponenter/header/logoutWarning/LogoutWarning.module.scss +++ b/src/komponenter/header/logoutWarning/LogoutWarning.module.scss @@ -4,7 +4,7 @@ display: flex; flex-direction: column; padding: 1rem; - align-items: center; + align-items: flex-start; box-shadow: var(--a-shadow-large); justify-content: center; opacity: 0; diff --git a/src/komponenter/header/logoutWarning/LogoutWarning.tsx b/src/komponenter/header/logoutWarning/LogoutWarning.tsx index 7c23dc385..786137133 100644 --- a/src/komponenter/header/logoutWarning/LogoutWarning.tsx +++ b/src/komponenter/header/logoutWarning/LogoutWarning.tsx @@ -11,8 +11,15 @@ import { LangKey } from 'tekster/ledetekster'; import styles from './LogoutWarning.module.scss'; export const LogoutWarning = () => { - const { refreshTokenHandler, logoutHandler, isTokenExpiring, isSessionExpiring, secondsToSessionExpires } = - useLoginStatus(); + const { + refreshTokenHandler, + loginHandler, + logoutHandler, + isTokenExpiring, + isSessionExpiring, + secondsToSessionExpires, + hasAuthError, + } = useLoginStatus(); const [isOpen, setIsOpen] = React.useState(false); const { language } = useSelector((state: AppState) => state.language); @@ -34,8 +41,24 @@ export const LogoutWarning = () => { return null; } - const titleId: LangKey = isSessionExpiring ? 'snart-session-logget-ut-tittel' : 'snart-token-logget-ut-tittel'; - const textBodyId: LangKey = isSessionExpiring ? 'snart-session-logget-ut-body' : 'snart-token-logget-ut-body'; + const getTitleId = () => { + if (hasAuthError) { + return 'token-feilet-tittel'; + } + + return isSessionExpiring ? 'snart-session-logget-ut-tittel' : 'snart-token-logget-ut-tittel'; + }; + + const getBodyId = () => { + if (hasAuthError) { + return 'token-feilet-body'; + } + + return isSessionExpiring ? 'snart-session-logget-ut-body' : 'snart-token-logget-ut-body'; + }; + + const titleId: LangKey = getTitleId(); + const textBodyId: LangKey = getBodyId(); const minutesToSessionEnd = Math.ceil(secondsToSessionExpires / 60); @@ -53,19 +76,31 @@ export const LogoutWarning = () => { {finnTekst(textBodyId, language)}
- {isSessionExpiring && ( + {hasAuthError && ( + <> + + + + )} + {!hasAuthError && isSessionExpiring && ( )} - {!isSessionExpiring && isTokenExpiring && ( + {!hasAuthError && !isSessionExpiring && isTokenExpiring && ( )} - + {!hasAuthError && ( + + )}
diff --git a/src/tekster/ledetekster.ts b/src/tekster/ledetekster.ts index 05cf7efe5..c595d4978 100644 --- a/src/tekster/ledetekster.ts +++ b/src/tekster/ledetekster.ts @@ -39,6 +39,9 @@ export const ledetekster = { 'logg-inn-knapp': 'Logg inn', 'logg-inn-knapp-en': 'Log in', 'logg-inn-knapp-se': 'Sisačáliheapmi', + 'logg-inn-pa-nytt-knapp': 'Logg inn på nytt', + 'logg-inn-pa-nytt-knapp-en': 'Log in again', + 'logg-inn-pa-nytt-knapp-se': 'Logg inn på nytt', 'logg-ut-knapp': 'Logg ut', 'logg-ut-knapp-en': 'Log out', 'logg-ut-knapp-se': 'Olggosčáliheapmi', @@ -59,6 +62,15 @@ export const ledetekster = { 'snart-session-logget-ut-body': 'Avslutt det du jobber med og logg inn igjen.', 'snart-session-logget-ut-body-en': 'Please wrap up what you are doing and log in again.', 'snart-session-logget-ut-body-se': 'Avslutt det du jobber med og logg inn igjen.', + 'token-feilet-tittel': 'Det har skjedd en feil', + 'token-feilet-tittel-en': 'An error has happened', + 'token-feilet-tittel-se': 'Det har skjedd en feil', + 'token-feilet-body': 'Forsøket på å forlenge innloggingen din feilet, vi beklager.', + 'token-feilet-body-en': 'An attempt to extend your login period failed, we apologize.', + 'token-feilet-body-se': 'Forsøket på å forlenge innloggingen din feilet, vi beklager.', + 'token-feilet-avbryt': `Avbryt`, + 'token-feilet-avbryt-en': `Cancel`, + 'token-feilet-avbryt-se': `Avbryt`, ok: 'OK', 'ok-en': 'OK', 'ok-se': 'OK', diff --git a/src/utils/hooks/useLoginStatus.ts b/src/utils/hooks/useLoginStatus.ts index ecd84c90f..12fb2779c 100644 --- a/src/utils/hooks/useLoginStatus.ts +++ b/src/utils/hooks/useLoginStatus.ts @@ -2,21 +2,23 @@ import { useEffect, useRef, useState } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { AppState } from 'store/reducers'; import { hentInnloggingsstatus, fornyInnlogging } from 'store/reducers/innloggingsstatus-duck'; -import { getLogOutUrl } from 'utils/login'; +import { getLogOutUrl, getLoginUrl } from 'utils/login'; import { useLoginDebug } from './useLoginDebug'; const stateSelector = (state: AppState) => ({ innloggetStatus: state.innloggingsstatus.data, environment: state.environment, + arbeidsflate: state.arbeidsflate.status, }); let timeoutId: NodeJS.Timeout | null = null; export const useLoginStatus = () => { const dispatch = useDispatch(); - const { innloggetStatus, environment } = useSelector(stateSelector); + const { innloggetStatus, environment, arbeidsflate } = useSelector(stateSelector); const [isTokenExpiring, setIsTokenExpiring] = useState(null); const [isSessionExpiring, setIsSessionExpiring] = useState(null); + const [hasAuthError, setHasAuthError] = useState(false); const [secondsToSessionExpires, setSecondsToSessionExpires] = useState(0); useLoginDebug(); @@ -25,6 +27,12 @@ export const useLoginStatus = () => { const innloggetStatusRef = useRef(innloggetStatus); innloggetStatusRef.current = innloggetStatus; + useEffect(() => { + window.addEventListener('INVALID_SESSION', () => { + setHasAuthError(true); + }); + }, []); + const getExpirationInSeconds = ({ session, token }: { session: string | null; token: string | null }) => { if (!session || !token) return { secondsToTokenExpires: null, secondsToSessionExpires: null }; @@ -75,7 +83,11 @@ export const useLoginStatus = () => { window.location.href = getLogOutUrl(environment); }; - const onVisibilityChange = () => { + const loginHandler = () => { + window.location.href = getLoginUrl(environment, arbeidsflate); + }; + + const onWindowVisibility = () => { if (document.visibilityState === 'visible') { checkLoginAndRepeat(); hentInnloggingsstatus(environment)(dispatch); @@ -84,8 +96,22 @@ export const useLoginStatus = () => { useEffect(() => { checkLoginAndRepeat(); - window.addEventListener('visibilitychange', onVisibilityChange); + window.addEventListener('visibilitychange', onWindowVisibility); + window.addEventListener('focus', onWindowVisibility); + + return () => { + window.removeEventListener('visibilitychange', onWindowVisibility); + window.removeEventListener('focus', onWindowVisibility); + }; }, []); - return { isTokenExpiring, isSessionExpiring, refreshTokenHandler, logoutHandler, secondsToSessionExpires }; + return { + isTokenExpiring, + isSessionExpiring, + refreshTokenHandler, + logoutHandler, + loginHandler, + secondsToSessionExpires, + hasAuthError, + }; };