+
-
- {message_heading}
+
+ {alertHeading}
-
- {message_body}
-
+
+
+ {alertBody}
+
+
-
+
)
}
diff --git a/components/ErrorPage.tsx b/components/ErrorPage.tsx
index eef013be6..c80ad37f9 100644
--- a/components/ErrorPage.tsx
+++ b/components/ErrorPage.tsx
@@ -57,10 +57,9 @@ const ErrorPage = ({
id={'pageHead' + index + errType}
title={val === EN ? errorHeadingEN : errorHeadingFR}
/>
-
+
{val === EN ? errorTextEN : errorTextFR}
-
{val.errorPageNextText}
@@ -104,11 +103,9 @@ const ErrorPage = ({
-
-
{val.errorPageType} {errType}
diff --git a/components/ExitBeta.tsx b/components/ExitBeta.tsx
deleted file mode 100644
index f364b166a..000000000
--- a/components/ExitBeta.tsx
+++ /dev/null
@@ -1,82 +0,0 @@
-import { icon } from '../lib/loadIcons'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import Button from '../components/Button'
-
-interface PopupButton {
- id: string
- text: string
-}
-
-interface ExitBetaProps {
- closeModal: () => void
- closeModalAria: string
- continueLink: string
- popupId: string
- popupTitle: string
- popupDescription: string
- popupPrimaryBtn: PopupButton
- popupSecondaryBtn: PopupButton
- refPageAA: string
-}
-
-const ExitBeta = ({
- closeModal,
- closeModalAria,
- continueLink,
- popupId,
- popupTitle,
- popupDescription,
- popupPrimaryBtn,
- popupSecondaryBtn,
- refPageAA,
-}: ExitBetaProps) => {
- return (
-
- )
-}
-
-export default ExitBeta
diff --git a/components/Header.tsx b/components/Header.tsx
index 60e4ef21f..ec10ab212 100644
--- a/components/Header.tsx
+++ b/components/Header.tsx
@@ -45,7 +45,9 @@ interface HeaderProps {
menuProps: MenuProps
topnavProps: TopNavProps
breadCrumbItems: BreadcrumbItemProps[]
+ refPageAA: string
dataGcAnalyticsCustomClickInstitutionVariable: string
+ dataGcAnalyticsCustomClickMenuVariable: string
}
const Header = ({
@@ -54,8 +56,10 @@ const Header = ({
linkPath,
menuProps,
breadCrumbItems,
+ refPageAA,
topnavProps,
dataGcAnalyticsCustomClickInstitutionVariable,
+ dataGcAnalyticsCustomClickMenuVariable,
}: HeaderProps) => {
return (
@@ -112,12 +116,10 @@ const Header = ({
-
+
diff --git a/components/Heading.tsx b/components/Heading.tsx
index fc702021d..fc03e9b74 100644
--- a/components/Heading.tsx
+++ b/components/Heading.tsx
@@ -18,12 +18,13 @@ const Heading = ({
return (
<>
{title}
+
{fromLink && fromText && (
From:
diff --git a/components/IdleTimeout.tsx b/components/IdleTimeout.tsx
new file mode 100644
index 000000000..200808dcb
--- /dev/null
+++ b/components/IdleTimeout.tsx
@@ -0,0 +1,141 @@
+import { useCallback, useEffect, useId, useState } from 'react'
+import { useRouter } from 'next/router'
+import { IIdleTimerProps, useIdleTimer } from 'react-idle-timer'
+import Modal from 'react-modal'
+import { FocusOn } from 'react-focus-on'
+import Button from './Button'
+import en from '../locales/en'
+import fr from '../locales/fr'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import { icon } from '../lib/loadIcons'
+
+export interface IdleTimeoutProps
+ extends Pick,
+ Pick {
+ locale: string
+ refPageAA?: string
+}
+
+const IdleTimeout = ({
+ promptBeforeIdle,
+ timeout,
+ locale,
+ refPageAA,
+}: IdleTimeoutProps) => {
+ const router = useRouter()
+ const [modalOpen, setModalOpen] = useState(false)
+ const [timeRemaining, setTimeRemaining] = useState({
+ seconds: '0',
+ minutes: 0,
+ })
+ const t = locale === 'en' ? en : fr
+ const id = useId()
+
+ const handleOnIdle = () => {
+ router.push('/auth/logout')
+ }
+
+ const handleOnIdleContinueSession = () => {
+ setModalOpen(false)
+ reset()
+ }
+
+ const { reset, getRemainingTime } = useIdleTimer({
+ onIdle: handleOnIdle,
+ onPrompt: () => setModalOpen(true),
+ promptBeforeIdle: promptBeforeIdle ?? 5 * 60 * 1000, //5 minutes
+ timeout: timeout ?? 15 * 60 * 1000, //15 minutes
+ })
+
+ const tick = useCallback(() => {
+ const minutes = Math.floor(getRemainingTime() / 60000)
+ const seconds = Math.floor((getRemainingTime() / 1000) % 60).toFixed(0)
+ setTimeRemaining({ seconds, minutes })
+ }, [getRemainingTime])
+
+ useEffect(() => {
+ setInterval(tick, 1000)
+ }, [tick])
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{t.bannerContent.notActive}
+
+ {t.bannerContent.signOut} {timeRemaining.minutes}
+ {t.bannerMinutesAnd} {timeRemaining.seconds} {t.bannerSeconds}.
+
+
+
+
+
+
+
+
+
+ )
+
+
+ )
+}
+
+export default IdleTimeout
diff --git a/components/InfoMessage.tsx b/components/InfoMessage.tsx
new file mode 100644
index 000000000..505d4d709
--- /dev/null
+++ b/components/InfoMessage.tsx
@@ -0,0 +1,75 @@
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import { icon as loadIcon } from '../lib/loadIcons'
+
+interface InfoMessageProps {
+ label: string
+ messageText: string
+ messageLinkText: string
+ messageLinkHref: string
+ locale: string
+ icon?: string
+ refPageAA: string
+}
+
+const InfoMessage = ({
+ locale,
+ label,
+ messageText,
+ messageLinkText,
+ messageLinkHref,
+ icon,
+ refPageAA,
+}: InfoMessageProps) => {
+ return (
+
+ )
+}
+
+export default InfoMessage
diff --git a/components/Layout.js b/components/Layout.js
index 1cf618ea9..c31dbef64 100644
--- a/components/Layout.js
+++ b/components/Layout.js
@@ -1,19 +1,17 @@
import PropTypes from 'prop-types'
-import { useState, useCallback, useMemo, useEffect, cloneElement } from 'react'
+import { useState, useCallback, useMemo, useEffect } from 'react'
import Header from './Header'
import Footer from './Footer'
import MetaData from './MetaData'
-import PhaseBanner from './PhaseBanner'
import en from '../locales/en'
import fr from '../locales/fr'
-import MultiModal from './MultiModal'
import { lato, notoSans } from '../utils/fonts'
-import throttle from 'lodash.throttle'
import { useRouter } from 'next/router'
+import throttle from 'lodash.throttle'
+import IdleTimeout from './IdleTimeout'
import { signOut } from 'next-auth/react'
export default function Layout(props) {
- const display = props.display ?? {}
const t = props.locale === 'en' ? en : fr
const [response, setResponse] = useState()
const router = useRouter()
@@ -21,31 +19,6 @@ export default function Layout(props) {
const contactLink =
props.locale === 'en' ? '/en/contact-us' : '/fr/contactez-nous'
- const [openModalWithLink, setOpenModalWithLink] = useState({
- activeLink: '/',
- context: null,
- })
-
- const openModal = (link, context) => {
- setOpenModalWithLink(() => {
- return {
- isOpen: true,
- activeLink: link,
- context,
- }
- })
- }
-
- const closeModal = () => {
- setOpenModalWithLink(() => {
- return {
- isOpen: false,
- activeLink: '/',
- context: null,
- }
- })
- }
-
const validationResponse = useCallback(
async () => setResponse(await fetch('/api/refresh-msca')),
[],
@@ -65,7 +38,7 @@ export default function Layout(props) {
useEffect(() => {
window.addEventListener('visibilitychange', throttledVisiblityChangeEvent)
window.addEventListener('click', throttledOnClickEvent)
- //If validateSession call indicates an invalid MSCA session, redirect to logout
+ //If validateSession call indicates an invalid MSCA session, end next-auth session and redirect to login
if (response?.status === 401) {
signOut()
router.push(`/${props.locale}/auth/login`)
@@ -95,27 +68,6 @@ export default function Layout(props) {
}
`}
- {props.display.hideBanner ? (
- ''
- ) : (
-
- )}
- {cloneElement(props.children, { openModal, closeModal })}
+ {props.children}
-
+
+
{process.env.ENVIRONMENT === 'production' ? (