Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .env.kesaseteli-employer.example
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,10 @@ NEXT_PUBLIC_SENTRY_DSN=https://74de630f51964d3296b858b73aaa65ad@sentry.test.hel.
NEXTJS_SENTRY_DEBUG=true
NEXTJS_SENTRY_TRACING=true
NEXT_PUBLIC_SENTRY_MAX_BREADCRUMBS=

# Configure Matomo tracking
NEXT_PUBLIC_MATOMO_URL=//webanalytics.digiaiiris.com/js/
NEXT_PUBLIC_MATOMO_SITE_ID=
NEXT_PUBLIC_MATOMO_JS_TRACKER_FILE=piwik.min.js
NEXT_PUBLIC_MATOMO_PHP_TRACKER_FILE=tracker.php
NEXT_PUBLIC_MATOMO_ENABLED=false
7 changes: 7 additions & 0 deletions .env.kesaseteli-youth.example
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,10 @@ NEXT_PUBLIC_SENTRY_DSN=https://74de630f51964d3296b858b73aaa65ad@sentry.test.hel.
NEXTJS_SENTRY_DEBUG=true
NEXTJS_SENTRY_TRACING=true
NEXT_PUBLIC_SENTRY_MAX_BREADCRUMBS=

# Configure Matomo tracking
NEXT_PUBLIC_MATOMO_URL=//webanalytics.digiaiiris.com/js/
NEXT_PUBLIC_MATOMO_SITE_ID=
NEXT_PUBLIC_MATOMO_JS_TRACKER_FILE=piwik.min.js
NEXT_PUBLIC_MATOMO_PHP_TRACKER_FILE=tracker.php
NEXT_PUBLIC_MATOMO_ENABLED=false
1 change: 1 addition & 0 deletions frontend/kesaseteli/employer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@frontend/shared": "*",
"@sentry/browser": "^7.16.0",
"@sentry/nextjs": "^7.16.0",
"@socialgouv/matomo-next": "^1.9.2",
"axios": "^0.30.2",
"dotenv": "^16.0.0",
"hds-design-tokens": "^3.11.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"appName": "Summer job voucher",
"cookieSettings": "Cookie settings",
"header": {
"loginLabel": "Sign in to the service",
"logoutLabel": "Log out",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"appName": "Kesäseteli",
"cookieSettings": "Evästeasetukset",
"header": {
"loginLabel": "Kirjaudu palveluun",
"logoutLabel": "Kirjaudu ulos",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"appName": "Sommarsedeln",
"cookieSettings": "Cookie-inställningar",
"header": {
"loginLabel": "Logga in i tjänsten",
"logoutLabel": "Logga ut",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ import { useTranslation } from 'next-i18next';
import React from 'react';

import { $FooterWrapper } from './Footer.sc';
import useLocale from 'shared/hooks/useLocale';

const FooterSection: React.FC = () => {
const { t } = useTranslation();
const locale = useLocale();

return (
<$FooterWrapper>
<Footer title={t('common:appName')} theme="dark">
Expand All @@ -31,6 +34,11 @@ const FooterSection: React.FC = () => {
href={t('common:footer.accessibilityStatementLink')}
label={t('common:footer.accessibilityStatement')}
/>
<Footer.Link
as="a"
href={`/${locale}/cookie-settings`}
label={t('common:cookieSettings')}
/>
</Footer.Base>
</Footer>
</$FooterWrapper>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import React from 'react';
import BaseHeader from 'shared/components/header/Header';
import { Language, SUPPORTED_LANGUAGES } from 'shared/i18n/i18n';
import { OptionType } from 'shared/types/common';
import useLocale from 'shared/hooks/useLocale';

const Header: React.FC = () => {
const { t } = useTranslation();
const locale = useLocale();
const router = useRouter();
const { asPath } = router;

Expand All @@ -32,14 +34,18 @@ const Header: React.FC = () => {
);

const login = useLogin();
const userQuery = useUserQuery();
const userQuery = useUserQuery({
// Allow cookie settings page to be accessed without login:
enabled: !asPath?.includes('/cookie-settings'),
});
const logout = useLogout();

const isLoginPage = asPath?.includes('/login');

return (
<BaseHeader
title={t('common:appName')}
titleUrl={`/${locale}`}
skipToContentLabel={t('common:header.linkSkipToContent')}
menuToggleAriaLabel={t('common:header.menuToggleAriaLabel')}
languages={languageOptions}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ import User from 'shared/types/user';
const useUserQuery = <T = User>({
refetchInterval,
select,
enabled = true,
}: UseQueryOptions<T> = {}): UseQueryResult<T> => {
const isRouting = useIsRouting();
const goToPage = useGoToPage();
return useQuery(BackendEndpoint.USER as QueryKey, {
enabled: !isRouting,
enabled: !!enabled && !isRouting,
onError: useErrorHandler({
onServerError: () => goToPage('/login?error=true'),
}),
Expand Down
31 changes: 23 additions & 8 deletions frontend/kesaseteli/employer/src/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,34 @@ import { getBackendDomain } from 'kesaseteli-shared/backend-api/backend-api';
import createQueryClient from 'kesaseteli-shared/query-client/create-query-client';
import { AppProps } from 'next/app';
import { appWithTranslation } from 'next-i18next';
import dynamic from 'next/dynamic';
import React from 'react';
import { QueryClientProvider } from 'react-query';
import BackendAPIProvider from 'shared/backend-api/BackendAPIProvider';
import BaseApp from 'shared/components/app/BaseApp';
import useMatomo from 'kesaseteli-shared/hooks/useMatomo';
import { COOKIE_CONSENT_SITE_NAME } from 'kesaseteli-shared/constants/cookie-consent';

const App: React.FC<AppProps> = (appProps) => (
<BackendAPIProvider baseURL={getBackendDomain()}>
<QueryClientProvider client={createQueryClient()}>
<AuthProvider>
<BaseApp header={<Header />} footer={<Footer />} {...appProps} />
</AuthProvider>
</QueryClientProvider>
</BackendAPIProvider>
const CookieConsent = dynamic(
() => import('kesaseteli-shared/components/cookieConsent/CookieConsent'),
{ ssr: false }
);

const App: React.FC<AppProps> = (appProps) => {
const isMatomoConfigured = useMatomo();

return (
<BackendAPIProvider baseURL={getBackendDomain()}>
<QueryClientProvider client={createQueryClient()}>
<AuthProvider>
{isMatomoConfigured && (
<CookieConsent siteName={COOKIE_CONSENT_SITE_NAME} />
)}
<BaseApp header={<Header />} footer={<Footer />} {...appProps} />
</AuthProvider>
</QueryClientProvider>
</BackendAPIProvider>
);
};

export default appWithTranslation(App);
21 changes: 21 additions & 0 deletions frontend/kesaseteli/employer/src/pages/cookie-settings.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { GetStaticProps, NextPage } from 'next';
import React from 'react';
import getServerSideTranslations from 'shared/i18n/get-server-side-translations';
import { useTranslation } from 'next-i18next';
import CookieSettings from 'kesaseteli-shared/components/cookieSettings/CookieSettings';

const CookieSettingsPage: NextPage = () => {
const { t } = useTranslation();

return (
<CookieSettings
title={`${t('common:appName')} - ${t('common:cookieSettings')}`}
siteName={t('common:appName')}
/>
);
};

export const getStaticProps: GetStaticProps =
getServerSideTranslations('common');

export default CookieSettingsPage;
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import useLocale from 'shared/hooks/useLocale';
import { useRouter } from 'next/router';
import React from 'react';
import { CookieModal, CookiePage } from 'hds-react';
import useCookieConsent from 'shared/hooks/useCookieConsent';
import { MAIN_CONTENT_ID } from 'shared/constants';

type CookieConsentProps = {
asPage?: boolean;
siteName: string;
};

const CookieConsent: React.FC<CookieConsentProps> = ({
asPage = false,
siteName,
}) => {
const locale = useLocale();
const router = useRouter();
const { pathname, asPath, query } = router;

const onLanguageChange = React.useCallback(
(newLanguage: string): void => {
void router.push({ pathname, query }, asPath, {
locale: newLanguage,
});
},
[router, pathname, query, asPath]
);

const { onAllConsentsGiven, onConsentsParsed, optionalCookies } =
useCookieConsent();

const contentSource = React.useMemo(
() => ({
siteName,
currentLanguage: locale,
optionalCookies,
language: { onLanguageChange },
onConsentsParsed,
onAllConsentsGiven,
focusTargetSelector: `#${MAIN_CONTENT_ID}`,
}),
[
siteName,
locale,
optionalCookies,
onLanguageChange,
onConsentsParsed,
onAllConsentsGiven,
]
);

return asPage ? (
<CookiePage contentSource={contentSource} />
) : (
<CookieModal contentSource={contentSource} />
);
};

export default CookieConsent;
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import dynamic from 'next/dynamic';
import Head from 'next/head';
import * as React from 'react';
import Container from 'shared/components/container/Container';

const CookieConsent = dynamic(
() => import('kesaseteli-shared/components/cookieConsent/CookieConsent'),
{ ssr: false }
);

export type CookieSettingsProps = {
title: string;
siteName: string;
};

const CookieSettings: React.FC<CookieSettingsProps> = ({
title,
siteName,
}: CookieSettingsProps) => (
<>
<Head>
<title>{title}</title>
</Head>

<Container>
<CookieConsent asPage siteName={siteName} />
</Container>
</>
);

export default CookieSettings;
3 changes: 3 additions & 0 deletions frontend/kesaseteli/shared/src/constants/cookie-consent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Non-localizable site name for cookie consent,
// does not use non-ascii characters for maximum compatibility.
export const COOKIE_CONSENT_SITE_NAME = 'Kesaseteli';
40 changes: 40 additions & 0 deletions frontend/kesaseteli/shared/src/hooks/useMatomo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { useEffect } from 'react';
import { init } from '@socialgouv/matomo-next';

const MATOMO_ENABLED = process.env.NEXT_PUBLIC_MATOMO_ENABLED === 'true';
const MATOMO_URL = process.env.NEXT_PUBLIC_MATOMO_URL;
const MATOMO_SITE_ID = process.env.NEXT_PUBLIC_MATOMO_SITE_ID;
const MATOMO_JS_TRACKER_FILE = process.env.NEXT_PUBLIC_MATOMO_JS_TRACKER_FILE;
const MATOMO_PHP_TRACKER_FILE = process.env.NEXT_PUBLIC_MATOMO_PHP_TRACKER_FILE;

export type UseMatomoProps = {
enabled?: boolean;
url?: string;
siteId?: string;
jsTrackerFile?: string;
phpTrackerFile?: string;
};

/**
* Use Matomo tracking
* @returns True if Matomo is enabled and has URL & site ID, false otherwise.
*/
const useMatomo = ({
enabled = MATOMO_ENABLED,
url = MATOMO_URL,
siteId = MATOMO_SITE_ID,
jsTrackerFile = MATOMO_JS_TRACKER_FILE,
phpTrackerFile = MATOMO_PHP_TRACKER_FILE,
}: UseMatomoProps = {}): boolean => {
const isMatomoConfigured = !!(enabled && url && siteId);

useEffect(() => {
if (isMatomoConfigured) {
init({ url, siteId, jsTrackerFile, phpTrackerFile });
}
}, [isMatomoConfigured, url, siteId, jsTrackerFile, phpTrackerFile]);

return isMatomoConfigured;
};

export default useMatomo;
1 change: 1 addition & 0 deletions frontend/kesaseteli/youth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@frontend/shared": "*",
"@sentry/browser": "^7.16.0",
"@sentry/nextjs": "^7.16.0",
"@socialgouv/matomo-next": "^1.9.2",
"axios": "^0.30.2",
"dotenv": "^16.0.0",
"finnish-ssn": "^2.1.2",
Expand Down
3 changes: 2 additions & 1 deletion frontend/kesaseteli/youth/public/locales/en/common.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"appName": "Summer Job Voucher for youth",
"cookieSettings": "Cookie settings",
"helsinkiLogo": "Helsinki logo",
"header": {
"linkSkipToContent": "Skip to content",
Expand Down Expand Up @@ -162,4 +163,4 @@
"goToFrontendPage": "Check your information and send the application for the Summer Job Voucher again."
}
}
}
}
3 changes: 2 additions & 1 deletion frontend/kesaseteli/youth/public/locales/fi/common.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"appName": "Nuorten kesäseteli",
"cookieSettings": "Evästeasetukset",
"helsinkiLogo": "Helsinki-logo",
"header": {
"linkSkipToContent": "Siirry sisältöön",
Expand Down Expand Up @@ -162,4 +163,4 @@
"goToFrontendPage": "Tarkista tiedot ja lähetä kesäsetelihakemus uudelleen"
}
}
}
}
3 changes: 2 additions & 1 deletion frontend/kesaseteli/youth/public/locales/sv/common.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"appName": "Sommarsedel för unga",
"cookieSettings": "Cookie-inställningar",
"helsinkiLogo": "Helsingfors logotyp",
"header": {
"linkSkipToContent": "Gå till innehållet",
Expand Down Expand Up @@ -162,4 +163,4 @@
"goToFrontendPage": "Kontrollera dina uppgifter och skicka registreringsblanketten på nytt"
}
}
}
}
5 changes: 5 additions & 0 deletions frontend/kesaseteli/youth/src/components/footer/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ const FooterSection: React.FC = () => {
href={t('common:footer.accessibilityStatementLink')}
label={t('common:footer.accessibilityStatement')}
/>
<Footer.Link
as="a"
href={`/${locale}/cookie-settings`}
label={t('common:cookieSettings')}
/>
</Footer.Base>
</Footer>
</$FooterWrapper>
Expand Down
Loading
Loading