+ Your email address is unverified. This may affect your ability to receive important notifications.
+
+
+
+
+ Other options
+
+
+ In some situations, schools or departments block email from external sites like ours, which may prevent you from receiving verification emails.
+ If this is the case, please contact your IT department to see if they can allow emails from {SITE_TITLE}.
+ We have a help page regarding our email setup that may be of use.
+
+
+ If your IT department is unable to assist, you can disable banner warnings on the site for this browser. We strongly recommend against this.
+ Unverified email addresses may lead to issues with account recovery and you may miss important security notifications from {SITE_TITLE}.
+
{
{(status == null || status == "NOT_VERIFIED") &&
- Your email address is not verified - please find our email in your inbox and follow the
- verification link. You can if necessary. To change your account email,
- go to My account.
+
+ Your email address is not verified - please find our email in your inbox and follow the
+ verification link. You can{" "}
+ {" "}
+ if necessary. To change your account email, go to My account.
-
+
-
: null;
+
;
};
diff --git a/src/app/services/userConsent.ts b/src/app/services/userConsent.ts
index a1cefa26bb..5b13c699d1 100644
--- a/src/app/services/userConsent.ts
+++ b/src/app/services/userConsent.ts
@@ -1,8 +1,8 @@
-import { InterstitialCookieState } from '../state';
+import { CookieConsentState } from '../state';
import { AppState, useAppSelector } from '../state';
interface UseUserConsentReturnType {
- cookieConsent: InterstitialCookieState;
+ cookieConsent: CookieConsentState;
openAIConsent: boolean;
}
@@ -14,4 +14,4 @@ export function useUserConsent(): UseUserConsentReturnType {
openAIConsent: !!databaseRecordedConsent?.OPENAI,
cookieConsent
};
-}
\ No newline at end of file
+}
diff --git a/src/app/state/reducers/index.ts b/src/app/state/reducers/index.ts
index c0315fa53a..ef644ccc83 100644
--- a/src/app/state/reducers/index.ts
+++ b/src/app/state/reducers/index.ts
@@ -24,7 +24,7 @@ import {
gameboardsSlice,
adminUserSearchSlice,
userSlice,
- interstitialCookieSlice,
+ cookieConsentSlice,
pageContextSlice,
topicSlice,
linkableSettingSlice,
@@ -50,7 +50,7 @@ export const rootReducer = combineReducers({
notifications,
// Cookies
- cookieConsent: interstitialCookieSlice.reducer,
+ cookieConsent: cookieConsentSlice.reducer,
// Static Content
glossaryTerms,
diff --git a/src/app/state/slices/cookies.ts b/src/app/state/slices/cookies.ts
index 7fbb373495..251d853f30 100644
--- a/src/app/state/slices/cookies.ts
+++ b/src/app/state/slices/cookies.ts
@@ -5,6 +5,7 @@ export const YOUTUBE_COOKIE = "youtubeCookiesAccepted";
export const ANVIL_COOKIE = "anvilCookiesAccepted";
export const DESMOS_COOKIE = "desmosCookiesAccepted";
export const GEOGEBRA_COOKIE = "geogebraCookiesAccepted";
+export const DISABLE_EMAIL_VERIFICATION_WARNING_COOKIE = "disableEmailVerificationWarningCookiesAccepted";
const isCookieSet = (name: string) => {
return Cookies.get(name) === "1";
@@ -14,38 +15,31 @@ const setCookie = (name: string) => {
Cookies.set(name, "1", { expires: 720 /* days*/, sameSite: "strict" });
};
-export type InterstitialCookieState = {
- youtubeCookieAccepted: boolean;
- anvilCookieAccepted: boolean;
- desmosCookieAccepted: boolean;
- geogebraCookieAccepted: boolean;
+export type CookieConsentState = {
+ youtubeCookiesAccepted: boolean;
+ anvilCookiesAccepted: boolean;
+ desmosCookiesAccepted: boolean;
+ geogebraCookiesAccepted: boolean;
+ disableEmailVerificationWarningCookiesAccepted: boolean;
} | null;
-export const interstitialCookieSlice = createSlice({
- name: 'interstitialCookie',
- initialState: null as InterstitialCookieState,
+export const cookieConsentSlice = createSlice({
+ name: 'cookieConsent',
+ initialState: {
+ youtubeCookiesAccepted: isCookieSet(YOUTUBE_COOKIE),
+ anvilCookiesAccepted: isCookieSet(ANVIL_COOKIE),
+ desmosCookiesAccepted: isCookieSet(DESMOS_COOKIE),
+ geogebraCookiesAccepted: isCookieSet(GEOGEBRA_COOKIE),
+ disableEmailVerificationWarningCookiesAccepted: isCookieSet(DISABLE_EMAIL_VERIFICATION_WARNING_COOKIE)
+ } as CookieConsentState,
reducers: {
- setDefault: () => ({
- youtubeCookieAccepted: isCookieSet(YOUTUBE_COOKIE),
- anvilCookieAccepted: isCookieSet(ANVIL_COOKIE),
- desmosCookieAccepted: isCookieSet(DESMOS_COOKIE),
- geogebraCookieAccepted: isCookieSet(GEOGEBRA_COOKIE)
- }),
- acceptYoutubeCookies: (state) => {
- if (state) state.youtubeCookieAccepted = true;
- setCookie(YOUTUBE_COOKIE);
+ acceptCookie: (state, action: {payload: keyof NonNullable}) => {
+ if (state) state[action.payload] = true;
+ setCookie(action.payload);
},
- acceptAnvilCookies: (state) => {
- if (state) state.anvilCookieAccepted = true;
- setCookie(ANVIL_COOKIE);
- },
- acceptDesmosCookies: (state) => {
- if (state) state.desmosCookieAccepted = true;
- setCookie(DESMOS_COOKIE);
- },
- acceptGeogebraCookies: (state) => {
- if (state) state.geogebraCookieAccepted = true;
- setCookie(GEOGEBRA_COOKIE);
+ removeCookie: (state, action: {payload: keyof NonNullable}) => {
+ if (state) state[action.payload] = false;
+ Cookies.remove(action.payload);
},
},
});
diff --git a/src/scss/phy/icons.scss b/src/scss/phy/icons.scss
index fc40cc33a9..b724d5f32b 100644
--- a/src/scss/phy/icons.scss
+++ b/src/scss/phy/icons.scss
@@ -33,7 +33,6 @@
}
.icon-person-active,
-.icon-warning,
.icon-help,
.icon-group-table-person
{
@@ -140,6 +139,10 @@
@include svg-icon('/assets/phy/icons/redesign/plus.svg', 12px, 12px, 100%);
}
+.icon-warning {
+ @include svg-icon('/assets/phy/icons/redesign/warning.svg', var(--icon-size), var(--icon-size), var(--mask-size, 60%));
+}
+
.icon-question {
@include svg-icon-layered(
@@ -367,6 +370,10 @@ i.icon.icon-color-white {
@include icon-color-override($color-neutral-white);
}
+i.icon.icon-color-alert {
+ @include icon-color-override(var(--bs-alert-color));
+}
+
i.icon.icon-color-black-hoverable {
--buttons-light-icon: #{$color-neutral-900};
}
diff --git a/src/test/state/reducers.test.tsx b/src/test/state/reducers.test.tsx
index ce0bc553d5..c0d9014703 100644
--- a/src/test/state/reducers.test.tsx
+++ b/src/test/state/reducers.test.tsx
@@ -33,12 +33,16 @@ function removeRTKProperties(state: AppState) {
describe("root reducer", () => {
+ // TODO why is this a requirement?? non-api-related initial states *can* be set on load...
+ // JB I'm leaving this test here as it's a good default to have, and we should follow this in most cases.
+ // Any exceptions must have thought put into them as to whether the initial state really is immediately calculable on page load.
it("has null as the initial state value for every property", () => {
const actualInitialState = removeRTKProperties(rootReducer(undefined, ignoredTestAction));
-
Object.entries(actualInitialState).map(([reducerName, actualInitialValue]) => {
if (reducerName === "adminUserSeach") {
expect(actualInitialValue).toHaveLength(0);
+ } else if (reducerName === "cookieConsent") {
+ expect(Object.values(actualInitialValue as object).every(v => v === false)).toBe(true);
} else {
expect(actualInitialValue).toBe(null);
}