From 7e2d9ed60fee8e4f9d323e86cbd3f150d97ff60d Mon Sep 17 00:00:00 2001 From: lukaw3d Date: Wed, 13 Mar 2024 01:50:47 +0100 Subject: [PATCH 1/2] Show instructions if analytics is adblocked and clicks privacy settings --- .changelog/1294.feature.md | 2 +- .changelog/1325.feature.md | 1 + .../AnalyticsConsent/AnalyticsIsBlocked.tsx | 70 +++++++++++++++++++ src/app/components/AnalyticsConsent/index.tsx | 38 ++++++---- src/locales/en/translation.json | 5 +- 5 files changed, 102 insertions(+), 14 deletions(-) create mode 100644 .changelog/1325.feature.md create mode 100644 src/app/components/AnalyticsConsent/AnalyticsIsBlocked.tsx diff --git a/.changelog/1294.feature.md b/.changelog/1294.feature.md index 67ee11315..e65ff7892 100644 --- a/.changelog/1294.feature.md +++ b/.changelog/1294.feature.md @@ -1 +1 @@ -Analytics: integrate matomo with UI (using matomo cookies for storage) +Integrate matomo analytics diff --git a/.changelog/1325.feature.md b/.changelog/1325.feature.md new file mode 100644 index 000000000..e65ff7892 --- /dev/null +++ b/.changelog/1325.feature.md @@ -0,0 +1 @@ +Integrate matomo analytics diff --git a/src/app/components/AnalyticsConsent/AnalyticsIsBlocked.tsx b/src/app/components/AnalyticsConsent/AnalyticsIsBlocked.tsx new file mode 100644 index 000000000..880460e36 --- /dev/null +++ b/src/app/components/AnalyticsConsent/AnalyticsIsBlocked.tsx @@ -0,0 +1,70 @@ +import Snackbar from '@mui/material/Snackbar' +import Typography from '@mui/material/Typography' +import { styled } from '@mui/material/styles' +import Button from '@mui/material/Button' +import Link from '@mui/material/Link' +import { Trans, useTranslation } from 'react-i18next' +import Card from '@mui/material/Card' +import CardContent from '@mui/material/CardContent' +import CardActions from '@mui/material/CardActions' +import { useScreenSize } from 'app/hooks/useScreensize' +import { legalDocuments } from '../../utils/externalLinks' + +const StyledButton = styled(Button)(({ theme }) => ({ + paddingLeft: theme.spacing(5), + paddingRight: theme.spacing(5), +})) + +export const AnalyticsIsBlocked = (props: { isOpen: boolean; onReload: () => void; onClose: () => void }) => { + const { t } = useTranslation() + const { isMobile } = useScreenSize() + return ( + <> + + + + + + ), + }} + /> + + + + props.onReload()} color="secondary" variant="outlined"> + {t('analyticsConsent.reloadButtonLabel')} + + props.onClose()} color="secondary" variant="outlined"> + {t('analyticsConsent.closeButtonLabel')} + + + + + + ) +} diff --git a/src/app/components/AnalyticsConsent/index.tsx b/src/app/components/AnalyticsConsent/index.tsx index cd7401821..99e33a5bf 100644 --- a/src/app/components/AnalyticsConsent/index.tsx +++ b/src/app/components/AnalyticsConsent/index.tsx @@ -15,6 +15,7 @@ import * as matomo from './initializeMatomo' import { legalDocuments } from '../../utils/externalLinks' import { ThemeByNetwork } from '../ThemeByNetwork' import { Network } from '../../../types/network' +import { AnalyticsIsBlocked } from './AnalyticsIsBlocked' const AnalyticsContext = createContext<{ reopenAnalyticsConsent: () => void @@ -23,7 +24,9 @@ const AnalyticsContext = createContext<{ export const AnalyticsConsentProvider = (props: { children: React.ReactNode }) => { if (process.env.REACT_APP_ENABLE_OASIS_MATOMO_ANALYTICS !== 'true') return <>{props.children} - const [hasAccepted, setHasAccepted] = useState('timed_out_matomo_not_loaded') + const [hasAccepted, setHasAccepted] = useState< + matomo.HasAccepted | 'loading' | 'timed_out_matomo_not_loaded_force_open' + >('loading') useEffect(() => { matomo.addMatomo() @@ -53,7 +56,17 @@ export const AnalyticsConsentProvider = (props: { children: React.ReactNode }) = }, [location.key, hasAccepted]) return ( - setHasAccepted('not-chosen') }}> + { + if (hasAccepted === 'timed_out_matomo_not_loaded' || hasAccepted === 'loading') { + setHasAccepted('timed_out_matomo_not_loaded_force_open') + } else { + setHasAccepted('not-chosen') + } + }, + }} + > {props.children} {/* Theme is needed because AnalyticsConsentProvider is outside network-themed routes */} @@ -68,6 +81,11 @@ export const AnalyticsConsentProvider = (props: { children: React.ReactNode }) = setHasAccepted(await matomo.hasAccepted({ timeout: 10_000 })) }} /> + window.location.reload()} + onClose={() => setHasAccepted('timed_out_matomo_not_loaded')} + /> ) @@ -86,12 +104,7 @@ export const ReopenAnalyticsConsentButton = () => { ) } -const AcceptCookiesButton = styled(Button)(({ theme }) => ({ - paddingLeft: theme.spacing(5), - paddingRight: theme.spacing(5), -})) - -const DeclineCookiesButton = styled(Button)(({ theme }) => ({ +const StyledButton = styled(Button)(({ theme }) => ({ paddingLeft: theme.spacing(5), paddingRight: theme.spacing(5), })) @@ -118,6 +131,7 @@ export const AnalyticsConsentView = (props: { - props.onAccept()} color="primary" variant="contained"> + props.onAccept()} color="primary" variant="contained"> {t('analyticsConsent.acceptButtonLabel')} - - props.onDecline()} color="secondary" variant="outlined"> + + props.onDecline()} color="secondary" variant="outlined"> {t('analyticsConsent.declineButtonLabel')} - + diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 18dde2369..222152981 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -33,8 +33,11 @@ "analyticsConsent": { "settings": "Privacy settings", "text": "At Oasis Foundation we believe in your privacy, so you can choose to browse our site without any tracking or by clicking “{{acceptButtonLabel}}”, you help us to improve our site and help us grow our ecosystem. View our Privacy Policy for more information.", + "blockedText": "Our analytics tracking failed to load. Therefore, you will continue using the site with user tracking disabled. If you are willing to accept tracking please pause your adblocker and reload the page to accept tracking. View our Privacy Policy for more information.", "acceptButtonLabel": "Accept", - "declineButtonLabel": "Decline" + "declineButtonLabel": "Decline", + "reloadButtonLabel": "Reload page", + "closeButtonLabel": "Close" }, "blocks": { "latest": "Latest Blocks", From 6f779fdf433181ebc95ba249a934b430802dfd01 Mon Sep 17 00:00:00 2001 From: lukaw3d Date: Wed, 13 Mar 2024 22:19:05 +0100 Subject: [PATCH 2/2] Extract AnalyticsDialogLayout into a component --- .../AnalyticsDialogLayout.tsx | 46 ++++++++++ .../AnalyticsConsent/AnalyticsIsBlocked.tsx | 81 +++++++----------- src/app/components/AnalyticsConsent/index.tsx | 83 +++++++------------ 3 files changed, 103 insertions(+), 107 deletions(-) create mode 100644 src/app/components/AnalyticsConsent/AnalyticsDialogLayout.tsx diff --git a/src/app/components/AnalyticsConsent/AnalyticsDialogLayout.tsx b/src/app/components/AnalyticsConsent/AnalyticsDialogLayout.tsx new file mode 100644 index 000000000..7000c2ee9 --- /dev/null +++ b/src/app/components/AnalyticsConsent/AnalyticsDialogLayout.tsx @@ -0,0 +1,46 @@ +import Snackbar from '@mui/material/Snackbar' +import Typography from '@mui/material/Typography' +import Card from '@mui/material/Card' +import CardContent from '@mui/material/CardContent' +import CardActions from '@mui/material/CardActions' +import { useScreenSize } from 'app/hooks/useScreensize' + +export const AnalyticsDialogLayout = (props: { + isOpen: boolean + message: React.ReactNode + actions: React.ReactNode +}) => { + const { isMobile } = useScreenSize() + return ( + <> + + + + + {props.message} + + + + {props.actions} + + + + + ) +} diff --git a/src/app/components/AnalyticsConsent/AnalyticsIsBlocked.tsx b/src/app/components/AnalyticsConsent/AnalyticsIsBlocked.tsx index 880460e36..e68c54c3e 100644 --- a/src/app/components/AnalyticsConsent/AnalyticsIsBlocked.tsx +++ b/src/app/components/AnalyticsConsent/AnalyticsIsBlocked.tsx @@ -1,14 +1,9 @@ -import Snackbar from '@mui/material/Snackbar' -import Typography from '@mui/material/Typography' import { styled } from '@mui/material/styles' import Button from '@mui/material/Button' import Link from '@mui/material/Link' import { Trans, useTranslation } from 'react-i18next' -import Card from '@mui/material/Card' -import CardContent from '@mui/material/CardContent' -import CardActions from '@mui/material/CardActions' -import { useScreenSize } from 'app/hooks/useScreensize' import { legalDocuments } from '../../utils/externalLinks' +import { AnalyticsDialogLayout } from './AnalyticsDialogLayout' const StyledButton = styled(Button)(({ theme }) => ({ paddingLeft: theme.spacing(5), @@ -17,54 +12,34 @@ const StyledButton = styled(Button)(({ theme }) => ({ export const AnalyticsIsBlocked = (props: { isOpen: boolean; onReload: () => void; onClose: () => void }) => { const { t } = useTranslation() - const { isMobile } = useScreenSize() return ( - <> - - - - - - ), - }} + - - - - props.onReload()} color="secondary" variant="outlined"> - {t('analyticsConsent.reloadButtonLabel')} - - props.onClose()} color="secondary" variant="outlined"> - {t('analyticsConsent.closeButtonLabel')} - - - - - + ), + }} + /> + } + actions={ + <> + props.onReload()} color="secondary" variant="outlined"> + {t('analyticsConsent.reloadButtonLabel')} + + props.onClose()} color="secondary" variant="outlined"> + {t('analyticsConsent.closeButtonLabel')} + + + } + /> ) } diff --git a/src/app/components/AnalyticsConsent/index.tsx b/src/app/components/AnalyticsConsent/index.tsx index 99e33a5bf..4ba791f3a 100644 --- a/src/app/components/AnalyticsConsent/index.tsx +++ b/src/app/components/AnalyticsConsent/index.tsx @@ -1,21 +1,16 @@ /* eslint-disable react-hooks/rules-of-hooks -- REACT_APP_ENABLE_OASIS_MATOMO_ANALYTICS can't change in runtime */ import { createContext, useContext, useEffect, useState } from 'react' import { useLocation } from 'react-router-dom' -import Snackbar from '@mui/material/Snackbar' -import Typography from '@mui/material/Typography' import { styled } from '@mui/material/styles' import Button from '@mui/material/Button' import Link from '@mui/material/Link' import { Trans, useTranslation } from 'react-i18next' -import Card from '@mui/material/Card' -import CardContent from '@mui/material/CardContent' -import CardActions from '@mui/material/CardActions' -import { useScreenSize } from 'app/hooks/useScreensize' import * as matomo from './initializeMatomo' import { legalDocuments } from '../../utils/externalLinks' import { ThemeByNetwork } from '../ThemeByNetwork' import { Network } from '../../../types/network' import { AnalyticsIsBlocked } from './AnalyticsIsBlocked' +import { AnalyticsDialogLayout } from './AnalyticsDialogLayout' const AnalyticsContext = createContext<{ reopenAnalyticsConsent: () => void @@ -115,55 +110,35 @@ export const AnalyticsConsentView = (props: { onDecline: () => void }) => { const { t } = useTranslation() - const { isMobile } = useScreenSize() return ( - <> - - - - - - ), - }} - values={{ acceptButtonLabel: t('analyticsConsent.acceptButtonLabel') }} + - - - - props.onAccept()} color="primary" variant="contained"> - {t('analyticsConsent.acceptButtonLabel')} - - props.onDecline()} color="secondary" variant="outlined"> - {t('analyticsConsent.declineButtonLabel')} - - - - - + ), + }} + values={{ acceptButtonLabel: t('analyticsConsent.acceptButtonLabel') }} + /> + } + actions={ + <> + props.onAccept()} color="primary" variant="contained"> + {t('analyticsConsent.acceptButtonLabel')} + + props.onDecline()} color="secondary" variant="outlined"> + {t('analyticsConsent.declineButtonLabel')} + + + } + /> ) }