Export wins puts small files (known as 'cookies') onto your computer.
+
+ Cookies are used to measure how to use the website so it can be updated
+ and improved based on your needs.
+
+
+ Export Wins cookies never contain personally identifiable information.
+
+
Analytics cookies
+
+ We use Google Analytics software to collect information about how you use
+ Export Wins. We do this to help make sure the site is meeting the needs of
+ its users and to help us make improvements. Google Analytics stores
+ information about:
+
+
+
the pages you visit
+
how long you spend on each page
+
how you got to the site
+
what you click on while you're visiting the site
+
+
We don't allow Google to use or share our analytics data.
+
+
+)
+
+export default CookiePage
diff --git a/src/client/modules/ExportWins/Review/CookiePage/saga.js b/src/client/modules/ExportWins/Review/CookiePage/saga.js
new file mode 100644
index 00000000000..6ea9c9017da
--- /dev/null
+++ b/src/client/modules/ExportWins/Review/CookiePage/saga.js
@@ -0,0 +1,26 @@
+import { put, take } from 'redux-saga/effects'
+import { eventChannel } from 'redux-saga'
+
+const storageChannel = eventChannel((emit) => {
+ window.addEventListener('storage', emit)
+ return () => window.removeEventListener(emit)
+})
+
+/**
+ * This ensures that when the user sets their cookie preference
+ * in one browser tab, all the other tabs will pick up the change.
+ */
+// TODO: Once Redux state is persisted in session storage, this should not be needed
+export function* cookiePreferenceChangeSaga() {
+ while (true) {
+ const { key, newValue } = yield take(storageChannel)
+ if (key === 'cookie-consent') {
+ yield put({
+ type: 'RESOURCE',
+ name: 'load cookie preference',
+ id: 'cookieConsent',
+ result: newValue,
+ })
+ }
+ }
+}
diff --git a/src/client/modules/ExportWins/Review/CookiePage/tasks.js b/src/client/modules/ExportWins/Review/CookiePage/tasks.js
new file mode 100644
index 00000000000..e5d9c6b8f07
--- /dev/null
+++ b/src/client/modules/ExportWins/Review/CookiePage/tasks.js
@@ -0,0 +1,33 @@
+import Cookies from 'js-cookie'
+
+export const COOKIE_CONSENT_COOKIE_NAME = 'cookie-consent'
+export const GRANTED = 'granted'
+export const DENIED = 'denied'
+
+export const loadCookiePreference = () =>
+ localStorage.getItem(COOKIE_CONSENT_COOKIE_NAME)
+
+export const saveCookiePreference = (payload) => {
+ if (!window.gtag) {
+ throw Error(
+ 'window.gtag not defined, you probably forgot to set the GOOGLE_TAG_MANAGER_KEY env var.'
+ )
+ }
+ if (![GRANTED, DENIED].includes(payload)) {
+ throw Error('Payload must be "granted" or "denied"')
+ }
+
+ localStorage.setItem(COOKIE_CONSENT_COOKIE_NAME, payload)
+
+ window.gtag('consent', 'update', {
+ analytics_storage: payload,
+ })
+
+ if (payload === DENIED) {
+ for (const cookieName in Cookies.get()) {
+ Cookies.remove(cookieName)
+ }
+ }
+
+ return payload
+}
diff --git a/src/client/modules/ExportWins/Review/Layout.jsx b/src/client/modules/ExportWins/Review/Layout.jsx
index 3f2bd981c96..04712017aa7 100644
--- a/src/client/modules/ExportWins/Review/Layout.jsx
+++ b/src/client/modules/ExportWins/Review/Layout.jsx
@@ -1,17 +1,23 @@
import React from 'react'
import styled from 'styled-components'
-import { H1 } from 'govuk-react'
+import { Button, H1, H2, Link } from 'govuk-react'
import { FONT_SIZE, FONT_WEIGHTS, SPACING } from '@govuk-react/constants'
+import RecentTaskResult from '../../../components/Task/RecentResult'
+import { StyledStatusMessage } from './ThankYou'
+import { FormActions } from '../../../components'
import Footer from '../../../components/Footer'
-import { BLACK, WHITE, LIGHT_GREY } from '../../../utils/colours'
+import Task from '../../../components/Task'
+import Resource from '../../../components/Resource/Resource'
+import { BLACK, WHITE, LIGHT_GREY, GREEN } from '../../../utils/colours'
const Grid = styled.div({
minHeight: '100vh',
display: 'grid',
- gridTemplateRows: 'auto auto 1fr minmax(min-content, 30px)',
+ gridTemplateRows: 'auto auto auto 1fr minmax(min-content, 30px)',
gridTemplateColumns: `1fr min(100vw, calc(960px + ${SPACING.SCALE_3} * 2)) 1fr`,
gridTemplateAreas: `
+ ". cookie-banner ."
". main-bar ."
". header ."
". main ."
@@ -62,14 +68,87 @@ const Title = styled(H1)({
marginBottom: SPACING.SCALE_5,
})
+const CookieBannerBackground = styled.div({
+ gridRow: 'cookie-banner',
+ gridColumn: '1 / -1',
+ background: '#f3f2f1',
+})
+
+const CookieBanner = styled.div({
+ gridArea: 'cookie-banner',
+ paddingTop: SPACING.SCALE_3,
+})
+
+const CookieConsentConfirmation = () => (
+
+ {(consent) =>
+ consent && (
+
+ You've {consent === 'granted' ? 'accepted' : 'rejected'} additional
+ cookies. You can change your cookie settings at any time.
+
+ )
+ }
+
+)
+
const Layout = ({ children, title, supertitle, headingContent }) => (
+
+
+ {(persistedConsent) => (
+
+ {(updatedConsent) =>
+ !persistedConsent &&
+ !updatedConsent && (
+
+
Cookies
+
+ We’d like to use analytics cookies so we can understand how
+ you use Export Wins and make improvements.
+
+
+ We also use essential cookies to remember if you’ve accepted
+ analytics cookies.
+
+
+
+ {(getTask) => {
+ const setPreference = (value) =>
+ getTask(
+ 'save cookie preference',
+ 'cookieConsent'
+ ).start({
+ payload: value,
+ onSuccessDispatch: 'FORM__RESOLVED',
+ })
+ return (
+ <>
+
+
+ >
+ )
+ }}
+
+ View cookies
+
+
+ )
+ }
+
+ )}
+
- Department for Business & Trade
+ Department for Business and Trade