From 20e917eabf7afce117eab91632487db54edf9699 Mon Sep 17 00:00:00 2001 From: Joonas Nivala Date: Thu, 19 Jun 2025 16:14:55 +0300 Subject: [PATCH 01/19] add cookie data --- content/_data/constants.yml | 42 +++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/content/_data/constants.yml b/content/_data/constants.yml index c4e09698407d..4d400199d77b 100644 --- a/content/_data/constants.yml +++ b/content/_data/constants.yml @@ -233,3 +233,45 @@ header_nav: basis: "PRX, CZ" topology: "Square grid" device_id: "Q50" + +"/cookies/": + title: Cookie Policy + desc: |- + This is the cookie policy for FiQCI, accessible from https://fiqci.fi/cookies/ + + general: + - When you visit our website, cookies will save information about your stay. Cookies are small text files that are placed on your device. + There are two main types of cookies; session cookies and persistent cookies. Session cookies will be removed from your device as soon + as you close your browser. Persistent cookies will remain stored until they are deleted or expire. + + - The data collected by the cookies is used to track the trends in our site usage. No personal data is collected. + This way, we can improve the usability as well as identify the most interesting areas of our website. + + - Cookies help us get an overview of your visit to our website so we can get an idea of how many visitors we have, which pages are visited, + and how long visitors stay on our website. We use this information to improve our website and make it more user-friendly. + All data collected is anonymous and cannot be used to identify you as an individual. + + delete: + title: How to Delete Cookies + desc: |- + The cookies can be deleted by clearing your browser's cache and cookies. You can also manage your cookie preferences through + your browser settings. You can also simply refuse cookie consent through the cookie consent banner that appears when you first visit our website. + + change: + title: How to Change Consent + desc: |- + If you have already accepted/declined cookies, you can change your preferences at any time by clicking below. + + lifetime: + title: Cookie Lifetime + desc: |- + The length of time a cookie is stored on your devices and browsers varies.The lifetime is calculated according to your last visit + to the website. When a cookie expires, it is automatically deleted. All our cookies' lifetimes are specified in our cookie policy. + + cookies: + title: Cookies Used + types: + - name: "Analytics Cookies" + desc: |- + These cookies help us understand how visitors interact with our website by collecting and reporting information anonymously. + lifetime: 1 year \ No newline at end of file From f9980c2bc5a3c56cb55e041f1954ad3105d06203 Mon Sep 17 00:00:00 2001 From: Joonas Nivala Date: Thu, 19 Jun 2025 16:15:18 +0300 Subject: [PATCH 02/19] cookies page --- content/pages/about.md | 2 +- content/pages/cookies.md | 43 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 content/pages/cookies.md diff --git a/content/pages/about.md b/content/pages/about.md index e55c5bd14818..567d28713c92 100644 --- a/content/pages/about.md +++ b/content/pages/about.md @@ -7,7 +7,7 @@ react: true {% assign about_data = site.data.constants.["/about/"] %} -
+

About FiQCI

{{ about_data.desc }}

diff --git a/content/pages/cookies.md b/content/pages/cookies.md new file mode 100644 index 000000000000..4132e3632cff --- /dev/null +++ b/content/pages/cookies.md @@ -0,0 +1,43 @@ +--- +layout: page +title: Cookie Policy +subtitle: Cookie policy +react: true +--- + +{% assign cookie_data = site.data.constants.["/cookies/"] %} + +
+

{{ cookie_data.title }}

+ {% for i in cookie_data.general %} +

{{ i }}

+ {% endfor %} + +

{{ cookie_data.delete.title }}

+

{{ cookie_data.delete.desc }}

+ +

{{ cookie_data.change.title }}

+

{{ cookie_data.change.desc }}

+
+ {%- include react/root.html id='open-cookie-modal' -%} +
+ +

{{ cookie_data.lifetime.title }}

+

{{ cookie_data.lifetime.desc }}

+ +

{{ cookie_data.cookies.title }}

+ + {% for i in cookie_data.cookies.types %} +

{{ i.name }}

+
+
+

Description:

+

{{ i.desc }}

+
+
+

Lifetime:

+

{{ i.lifetime }}

+
+
+ {% endfor %} +
From ba2ac6e2ed9eacdcef4ec6ba6347e0f874398439 Mon Sep 17 00:00:00 2001 From: Joonas Nivala Date: Thu, 19 Jun 2025 16:15:31 +0300 Subject: [PATCH 03/19] cookie consent --- src/components/CookieConsent.jsx | 158 +++++++++++++++++++++++++++++++ src/pages/cookies.md.jsx | 28 ++++++ 2 files changed, 186 insertions(+) create mode 100644 src/components/CookieConsent.jsx create mode 100644 src/pages/cookies.md.jsx diff --git a/src/components/CookieConsent.jsx b/src/components/CookieConsent.jsx new file mode 100644 index 000000000000..efe07af54757 --- /dev/null +++ b/src/components/CookieConsent.jsx @@ -0,0 +1,158 @@ +import React, { useEffect, useState } from 'react' + +import { CModal, CCard, CCardTitle, CCardContent, CButton } from '@cscfi/csc-ui-react' + +export const CookieModal = () => { + const [isModalOpen, setIsModalOpen] = useState(false); + + useEffect(() => { + const cookieConsent = document.cookie + .split('; ') + .find(row => row.startsWith('cookie_consent=')); + + if (!cookieConsent) { + setIsModalOpen(true); + return; + } + + const consentValue = cookieConsent.split('=')[1]; + if (consentValue === 'true' || consentValue === 'false') { + setIsModalOpen(false); + } else { + setIsModalOpen(true); + } + }, []); + + // Unified close handler + const closeModal = () => setIsModalOpen(false); + + const handleAcceptCookies = () => { + closeModal(); + const expiryDate = new Date(); + expiryDate.setFullYear(expiryDate.getFullYear() + 1); + document.cookie = `cookie_consent=true; path=/; expires=${expiryDate.toUTCString()}`; + } + const handleDeclineCookies = () => { + closeModal(); + const cookies = document.cookie.split(';'); + for (const cookie of cookies) { + const eqPos = cookie.indexOf('='); + const name = eqPos > -1 ? cookie.substr(0, eqPos).trim() : cookie.trim(); + // Only delete cookies for the rahtiapp domain + if (name.endsWith('.rahtiapp.fi')) { + document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=.rahtiapp.fi`; + } + } + const expiryDate = new Date(); + expiryDate.setFullYear(expiryDate.getFullYear() + 1); + document.cookie = `cookie_consent=false; path=/; expires=${expiryDate.toUTCString()}`; + } + + return ( + closeModal()} + > + + Cookie consent + +

We use cookies

+

We value your privacy. The FiQCI webpages uses anonymous cookies to collect data about user behavior through Matomo. + This information helps us improve our services and provide a better user experience by telling us how users use the site. +

+

The data collected is non-identifiable and cannot be traced back to you.

+ + Cookie policy +
+ Decline + + Accept + +
+
+
+
+ ); +}; + +export const CookieModalManual = ({text}) => { + const [isModalOpen, setIsModalOpen] = useState(false); + + const closeModal = () => setIsModalOpen(false); + + const handleAcceptCookies = () => { + closeModal(); + const expiryDate = new Date(); + expiryDate.setFullYear(expiryDate.getFullYear() + 1); + document.cookie = `cookie_consent=true; path=/; expires=${expiryDate.toUTCString()}`; + } + const handleDeclineCookies = () => { + closeModal(); + const cookies = document.cookie.split(';'); + for (const cookie of cookies) { + const eqPos = cookie.indexOf('='); + const name = eqPos > -1 ? cookie.substr(0, eqPos).trim() : cookie.trim(); + // Only delete cookies for the rahtiapp domain + if (name.endsWith('.rahtiapp.fi')) { + document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=.rahtiapp.fi`; + } + } + const expiryDate = new Date(); + expiryDate.setFullYear(expiryDate.getFullYear() + 1); + document.cookie = `cookie_consent=false; path=/; expires=${expiryDate.toUTCString()}`; + } + + return ( +
+ setIsModalOpen(true)}>Open Cookie Consent popup + closeModal()} + > + + Cookie consent + +

We use cookies

+

We value your privacy. The FiQCI webpages uses anonymous cookies to collect data about user behavior through Matomo. + This information helps us improve our services and provide a better user experience by telling us how users use the site. +

+

The data collected is non-identifiable and cannot be traced back to you.

+ + Cookie policy +
+ Decline + + Accept + +
+
+
+
+
+ + ); +}; diff --git a/src/pages/cookies.md.jsx b/src/pages/cookies.md.jsx new file mode 100644 index 000000000000..80b79c584640 --- /dev/null +++ b/src/pages/cookies.md.jsx @@ -0,0 +1,28 @@ +import React from 'react' +import { createRoot } from 'react-dom/client' +import { createPortal } from 'react-dom' + +import { PageLayout } from '../layouts/page.html' + +import { useJsonApi } from '../hooks/useJsonApi' + +import { CookieModal, CookieModalManual } from '../components/CookieConsent' + + +const CookiesPage = () => { + const themeConstants = useJsonApi('api/theme/constants.json') + return <> + + + {createPortal( + , + document.getElementById('open-cookie-modal') + )} + +} + +document.addEventListener('DOMContentLoaded', () => { + const root = createRoot(document.getElementById('react-root')) + + root.render() +}) From 7a683eefcf3eccb38a1cbb6ffb4280e46aa7432d Mon Sep 17 00:00:00 2001 From: Joonas Nivala Date: Thu, 19 Jun 2025 16:15:43 +0300 Subject: [PATCH 04/19] dublicate id --- content/_layouts/home.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/_layouts/home.html b/content/_layouts/home.html index 3557a58d1660..0997aabcab94 100644 --- a/content/_layouts/home.html +++ b/content/_layouts/home.html @@ -72,7 +72,7 @@

FiQCI Mission

-

FiQCI Mission

+

FiQCI Mission

From 264caff303306e637f0e2aa6331155101d5cc7b4 Mon Sep 17 00:00:00 2001 From: Joonas Nivala Date: Thu, 19 Jun 2025 16:15:51 +0300 Subject: [PATCH 05/19] dublicate footer tag --- src/components/Footer.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Footer.jsx b/src/components/Footer.jsx index 7dc0bec4cbcb..02fb775e4473 100644 --- a/src/components/Footer.jsx +++ b/src/components/Footer.jsx @@ -19,7 +19,7 @@ export const Footer = (props) => { : <> return ( -
+
@@ -66,6 +66,6 @@ export const Footer = (props) => {
-
+
); }; From 583bd7653cacef46b7d90eb0cad9bb3464ce6c36 Mon Sep 17 00:00:00 2001 From: Joonas Nivala Date: Thu, 19 Jun 2025 16:16:07 +0300 Subject: [PATCH 06/19] cookie consent --- src/layouts/base.html.jsx | 42 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/layouts/base.html.jsx b/src/layouts/base.html.jsx index c2cb6de9afe0..487629e01120 100644 --- a/src/layouts/base.html.jsx +++ b/src/layouts/base.html.jsx @@ -1,4 +1,5 @@ -import React from 'react' +import React, { useEffect } from 'react' +import { useState } from 'react' import { createPortal } from 'react-dom' import { NavigationHeader } from '../components/NavigationHeader' @@ -6,6 +7,7 @@ import { Footer } from '../components/Footer' import { useMatomo } from '../hooks/useMatomo' +import { CookieModal } from '../components/CookieConsent' const Analytics = () => { const url = process.env.MATOMO_URL @@ -16,7 +18,11 @@ const Analytics = () => { return <> } + export const BaseLayout = props => { + + const [cookieConsentState, setCookieConsentState] = useState(null); + const headerProps = { logo: props.logo, nav: props.header_nav @@ -28,8 +34,40 @@ export const BaseLayout = props => { copyright: props.copyright } + useEffect(() => { + + const cookieConsent = document.cookie + .split('; ') + .find(row => row.startsWith('cookie_consent=')); + + if (!cookieConsent) { + setCookieConsentState(null); + return; + } + + const consentValue = cookieConsent.split('=')[1]; + if (consentValue === 'true' || consentValue === 'false') { + setCookieConsentState(consentValue === 'true'); + if (consentValue === 'false') { + const cookies = document.cookie.split(';'); + for (const cookie of cookies) { + const eqPos = cookie.indexOf('='); + const name = eqPos > -1 ? cookie.substr(0, eqPos).trim() : cookie.trim(); + // Only delete cookies for the rahtiapp domain + if (name.endsWith('.rahtiapp.fi')) { + document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=.rahtiapp.fi`; + } + } + } + } else { + setCookieConsentState(null); + } + }, []); + return <> - + + {cookieConsentState === true && } + {console.log('Cookie consent state:', cookieConsentState === true)} {createPortal( , document.getElementById('navigation-header') From b8767ad650492e67b7ad0d2137127ff5926ce2a2 Mon Sep 17 00:00:00 2001 From: Joonas Nivala Date: Thu, 19 Jun 2025 16:47:05 +0300 Subject: [PATCH 07/19] accessibility page --- content/_data/constants.yml | 38 ++++++++++++++++++++++++++++++++- content/pages/accessibility.md | 39 ++++++++++++++++++++++++++++++++++ src/pages/accessibility.md.jsx | 22 +++++++++++++++++++ 3 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 content/pages/accessibility.md create mode 100644 src/pages/accessibility.md.jsx diff --git a/content/_data/constants.yml b/content/_data/constants.yml index 4d400199d77b..900a3ccb1cd9 100644 --- a/content/_data/constants.yml +++ b/content/_data/constants.yml @@ -274,4 +274,40 @@ header_nav: - name: "Analytics Cookies" desc: |- These cookies help us understand how visitors interact with our website by collecting and reporting information anonymously. - lifetime: 1 year \ No newline at end of file + lifetime: 1 year + +"/accessibility/": + title: Accessibility Statement + desc: |- + This is the accessibility statement for FiQCI, accessible from https://fiqci.fi/accessibility/. + Updated on 19.6.2025 + + general: + - The FiQCI website is designed to be accessible to all users. + We strive to comply with the Web Content Accessibility Guidelines (WCAG) 2.1 Level AA standards. + + - If you encounter any accessibility issues while using our website, please contact us at + + status: + title: Compliance Status + desc: |- + Meets all critical accessibility requirements. + + complaint: + title: Reporting Accessibility Issues + desc: |- + If you notice accessibility problems on the website, start by giving feedback to us, that is, + the website administrator. Receiving a response may take 14 days. If you are not satisfied with + the response from us or if you do not receive any response within two weeks, you may file a report + with the Regional State Administrative Agency for Southern Finland (contact infomation below). + The agency website has detailed instructions (in Finnish and Swedish only) on how to file a + complaint and how the issue will be processed. + + contact: + title: Supervisory Authority Contact Information + info: + name: Liikenne- ja viestintävirasto Traficom + division: Digitaalisen esteettömyyden ja saavutettavuuden valvontayksikkö + web: www.saavutettavuusvaatimukset.fi + email: saavutettavuus@traficom.fi + phone: 029 534 5000 \ No newline at end of file diff --git a/content/pages/accessibility.md b/content/pages/accessibility.md new file mode 100644 index 000000000000..3c9904b054b0 --- /dev/null +++ b/content/pages/accessibility.md @@ -0,0 +1,39 @@ +--- +layout: page +title: Accessibility Statement +subtitle: Accessibility Statement +react: true +--- + +{% assign accessibility_data = site.data.constants.["/accessibility/"] %} + +
+

{{ accessibility_data.title }}

+

{{ accessibility_data.general }} {{ site.data.constants.feedback_email }}

+ +

{{ accessibility_data.status.title }}

+

{{ accessibility_data.status.desc }}

+ +

{{ accessibility_data.complaint.title }}

+

{{ accessibility_data.complaint.desc }}

+ +

{{ accessibility_data.complaint.contact.title }}

+ {% assign contact = accessibility_data.complaint.contact.info %} + {% assign contact_labels = "name:Name,division:Division,web:Website,email:Email,phone:Phone" | split: "," %} + {% for pair in contact_labels %} + {% assign parts = pair | split: ":" %} + {% assign key = parts[0] %} + {% assign label = parts[1] %} + {% if contact[key] %} +

{{ label }}: + {% if key == "web" %} + {{ contact[key] }} + {% elsif key == "email" %} + {{ contact[key] }} + {% else %} + {{ contact[key] }} + {% endif %} +

+ {% endif %} + {% endfor %} +
diff --git a/src/pages/accessibility.md.jsx b/src/pages/accessibility.md.jsx new file mode 100644 index 000000000000..ccedf32af77c --- /dev/null +++ b/src/pages/accessibility.md.jsx @@ -0,0 +1,22 @@ +import React from 'react' +import { createRoot } from 'react-dom/client' +import { createPortal } from 'react-dom' + +import { PageLayout } from '../layouts/page.html' + +import { useJsonApi } from '../hooks/useJsonApi' + + +const AccessibilityPage = () => { + const themeConstants = useJsonApi('api/theme/constants.json') + + return <> + + +} + +document.addEventListener('DOMContentLoaded', () => { + const root = createRoot(document.getElementById('react-root')) + + root.render() +}) From 45e78fbd1fd5f9f664577c76191832bd2720fa64 Mon Sep 17 00:00:00 2001 From: Joonas Nivala Date: Thu, 19 Jun 2025 16:52:52 +0300 Subject: [PATCH 08/19] fix links --- content/_data/constants.yml | 7 ++++--- content/pages/accessibility.md | 6 +++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/content/_data/constants.yml b/content/_data/constants.yml index 900a3ccb1cd9..13d96fc2300a 100644 --- a/content/_data/constants.yml +++ b/content/_data/constants.yml @@ -299,9 +299,10 @@ header_nav: If you notice accessibility problems on the website, start by giving feedback to us, that is, the website administrator. Receiving a response may take 14 days. If you are not satisfied with the response from us or if you do not receive any response within two weeks, you may file a report - with the Regional State Administrative Agency for Southern Finland (contact infomation below). - The agency website has detailed instructions (in Finnish and Swedish only) on how to file a - complaint and how the issue will be processed. + with the + link: + title: Regional State Administrative Agency for Southern Finland + href: https://www.saavutettavuusvaatimukset.fi/en/user-rights/submit-complaint-web-accessibility-or-request-clarification contact: title: Supervisory Authority Contact Information diff --git a/content/pages/accessibility.md b/content/pages/accessibility.md index 3c9904b054b0..dfb141ebab9c 100644 --- a/content/pages/accessibility.md +++ b/content/pages/accessibility.md @@ -15,7 +15,7 @@ react: true

{{ accessibility_data.status.desc }}

{{ accessibility_data.complaint.title }}

-

{{ accessibility_data.complaint.desc }}

+

{{ accessibility_data.complaint.desc }} {{ accessibility_data.complaint.link.title }}

{{ accessibility_data.complaint.contact.title }}

{% assign contact = accessibility_data.complaint.contact.info %} @@ -27,9 +27,9 @@ react: true {% if contact[key] %}

{{ label }}: {% if key == "web" %} - {{ contact[key] }} + {{ contact[key] }} {% elsif key == "email" %} - {{ contact[key] }} + {{ contact[key] }} {% else %} {{ contact[key] }} {% endif %} From 488ecfc60b479f8c63a2f8282bcb47baa118235d Mon Sep 17 00:00:00 2001 From: Joonas Nivala Date: Thu, 19 Jun 2025 16:54:12 +0300 Subject: [PATCH 09/19] fix link --- content/pages/accessibility.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/pages/accessibility.md b/content/pages/accessibility.md index dfb141ebab9c..d3a8b98855d7 100644 --- a/content/pages/accessibility.md +++ b/content/pages/accessibility.md @@ -9,7 +9,7 @@ react: true

{{ accessibility_data.title }}

-

{{ accessibility_data.general }} {{ site.data.constants.feedback_email }}

+

{{ accessibility_data.general }} {{ site.data.constants.feedback_email }}

{{ accessibility_data.status.title }}

{{ accessibility_data.status.desc }}

From f88f228fad47b0f6cb23307d460d9482c0b9cacf Mon Sep 17 00:00:00 2001 From: Joonas Nivala Date: Mon, 23 Jun 2025 12:21:47 +0300 Subject: [PATCH 10/19] edit layout --- content/pages/accessibility.md | 7 ++-- content/pages/cookies.md | 59 ++++++++++++++++++---------------- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/content/pages/accessibility.md b/content/pages/accessibility.md index d3a8b98855d7..80f2b7067def 100644 --- a/content/pages/accessibility.md +++ b/content/pages/accessibility.md @@ -7,7 +7,9 @@ react: true {% assign accessibility_data = site.data.constants.["/accessibility/"] %} -
+
+
+

{{ accessibility_data.title }}

{{ accessibility_data.general }} {{ site.data.constants.feedback_email }}

@@ -36,4 +38,5 @@ react: true

{% endif %} {% endfor %} -
+
+
\ No newline at end of file diff --git a/content/pages/cookies.md b/content/pages/cookies.md index 4132e3632cff..e1f4feb7cc41 100644 --- a/content/pages/cookies.md +++ b/content/pages/cookies.md @@ -7,37 +7,40 @@ react: true {% assign cookie_data = site.data.constants.["/cookies/"] %} -
-

{{ cookie_data.title }}

- {% for i in cookie_data.general %} -

{{ i }}

- {% endfor %} +
+
+
+

{{ cookie_data.title }}

+ {% for i in cookie_data.general %} +

{{ i }}

+ {% endfor %} -

{{ cookie_data.delete.title }}

-

{{ cookie_data.delete.desc }}

+

{{ cookie_data.delete.title }}

+

{{ cookie_data.delete.desc }}

-

{{ cookie_data.change.title }}

-

{{ cookie_data.change.desc }}

-
- {%- include react/root.html id='open-cookie-modal' -%} -
+

{{ cookie_data.change.title }}

+

{{ cookie_data.change.desc }}

+
+ {%- include react/root.html id='open-cookie-modal' -%} +
-

{{ cookie_data.lifetime.title }}

-

{{ cookie_data.lifetime.desc }}

+

{{ cookie_data.lifetime.title }}

+

{{ cookie_data.lifetime.desc }}

-

{{ cookie_data.cookies.title }}

- - {% for i in cookie_data.cookies.types %} -

{{ i.name }}

-
-
-

Description:

-

{{ i.desc }}

+

{{ cookie_data.cookies.title }}

+ + {% for i in cookie_data.cookies.types %} +

{{ i.name }}

+
+
+

Description:

+

{{ i.desc }}

+
+
+

Lifetime:

+

{{ i.lifetime }}

+
-
-

Lifetime:

-

{{ i.lifetime }}

-
-
- {% endfor %} + {% endfor %} +
From 0a527237dcf57c17467e8f6654135ced71381be5 Mon Sep 17 00:00:00 2001 From: Joonas Nivala Date: Mon, 23 Jun 2025 12:22:05 +0300 Subject: [PATCH 11/19] remove console log --- src/components/CookieConsent.jsx | 13 +++++++++++-- src/layouts/base.html.jsx | 1 - 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/components/CookieConsent.jsx b/src/components/CookieConsent.jsx index efe07af54757..93f15f939a04 100644 --- a/src/components/CookieConsent.jsx +++ b/src/components/CookieConsent.jsx @@ -26,6 +26,15 @@ export const CookieModal = () => { // Unified close handler const closeModal = () => setIsModalOpen(false); + const clickOutside = () => { + if (isModalOpen) { + closeModal(); + const expiryDate = new Date(); + expiryDate.setFullYear(expiryDate.getFullYear() + 1); + document.cookie = `cookie_consent=false; path=/; expires=${expiryDate.toUTCString()}`; + } + } + const handleAcceptCookies = () => { closeModal(); const expiryDate = new Date(); @@ -55,7 +64,7 @@ export const CookieModal = () => { className='!overflow-hidden' value={isModalOpen} dismissable - onChangeValue={() => closeModal()} + onChangeValue={() => clickOutside()} > Cookie consent @@ -87,7 +96,7 @@ export const CookieModal = () => { ); }; -export const CookieModalManual = ({text}) => { +export const CookieModalManual = ({ text }) => { const [isModalOpen, setIsModalOpen] = useState(false); const closeModal = () => setIsModalOpen(false); diff --git a/src/layouts/base.html.jsx b/src/layouts/base.html.jsx index 487629e01120..5a3517b1effe 100644 --- a/src/layouts/base.html.jsx +++ b/src/layouts/base.html.jsx @@ -67,7 +67,6 @@ export const BaseLayout = props => { return <> {cookieConsentState === true && } - {console.log('Cookie consent state:', cookieConsentState === true)} {createPortal( , document.getElementById('navigation-header') From dc0cb97b4034c8c96b26f043d6169e48a8ca1d48 Mon Sep 17 00:00:00 2001 From: Joonas Nivala Date: Mon, 23 Jun 2025 12:39:33 +0300 Subject: [PATCH 12/19] add functional cookie type --- content/_data/constants.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/content/_data/constants.yml b/content/_data/constants.yml index 1f5764e92cfa..6542ec6c4a13 100644 --- a/content/_data/constants.yml +++ b/content/_data/constants.yml @@ -271,6 +271,10 @@ header_nav: cookies: title: Cookies Used types: + - name: "Functional Cookies" + desc: |- + These cookies are necessary for the website to function properly. + lifetime: Session - name: "Analytics Cookies" desc: |- These cookies help us understand how visitors interact with our website by collecting and reporting information anonymously. From a51671a22d8eaaf2b59db09dcfa281f33847b36b Mon Sep 17 00:00:00 2001 From: Joonas Nivala Date: Mon, 23 Jun 2025 12:40:11 +0300 Subject: [PATCH 13/19] block pop up on cookie policy page --- src/layouts/base.html.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/layouts/base.html.jsx b/src/layouts/base.html.jsx index 5a3517b1effe..f8ee433928c2 100644 --- a/src/layouts/base.html.jsx +++ b/src/layouts/base.html.jsx @@ -62,10 +62,11 @@ export const BaseLayout = props => { } else { setCookieConsentState(null); } + console.log(window.location.pathname) }, []); return <> - + {window.location.pathname !== '/cookies/' && } {cookieConsentState === true && } {createPortal( , From f6dbad9959f2089a4b32819ba0b03104a26b37f3 Mon Sep 17 00:00:00 2001 From: Joonas Nivala Date: Mon, 23 Jun 2025 13:30:40 +0300 Subject: [PATCH 14/19] move cookie banner content to constants --- content/_data/constants.yml | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/content/_data/constants.yml b/content/_data/constants.yml index 6542ec6c4a13..2ba9a051a665 100644 --- a/content/_data/constants.yml +++ b/content/_data/constants.yml @@ -28,6 +28,15 @@ header_nav: - title: Search page: pages/search.md +cookie_consent: + title: We Use Cookies + chapters: + - text: |- + We value your privacy. The FiQCI webpage uses functional cookies and anonymous analytics cookies. + By clicking "Accept", you consent to the use of these cookies. + - text: |- + The data collected is non-identifiable and cannot be traced back to you. + #Following are constants per page. Can be accessed with page.url "/": hero: @@ -251,6 +260,14 @@ header_nav: and how long visitors stay on our website. We use this information to improve our website and make it more user-friendly. All data collected is anonymous and cannot be used to identify you as an individual. + - The FiQCI webpages uses anonymous cookies to collect data about user behavior through Matomo. + This information helps us improve our services and provide a better user experience by telling us how users use the site. + The data collected is non-identifiable and cannot be traced back to you. + + - Additionally we use mandatory functional cookies to ensure the website functions properly. + These cookies do not collect any information about you and only help the website function. + They are only valid for the current session and are deleted when you close your browser. + delete: title: How to Delete Cookies desc: |- @@ -291,7 +308,7 @@ header_nav: We strive to comply with the Web Content Accessibility Guidelines (WCAG) 2.1 Level AA standards. - If you encounter any accessibility issues while using our website, please contact us at - + status: title: Compliance Status desc: |- @@ -315,4 +332,4 @@ header_nav: division: Digitaalisen esteettömyyden ja saavutettavuuden valvontayksikkö web: www.saavutettavuusvaatimukset.fi email: saavutettavuus@traficom.fi - phone: 029 534 5000 \ No newline at end of file + phone: 029 534 5000 From fe5ef12faddd4a71e9b9d99fe54a7e9d873b2aee Mon Sep 17 00:00:00 2001 From: Joonas Nivala Date: Mon, 23 Jun 2025 13:31:03 +0300 Subject: [PATCH 15/19] use site for cookie banner constants --- src/components/CookieConsent.jsx | 37 ++++++++++++++++++-------------- src/layouts/base.html.jsx | 4 +--- src/pages/cookies.md.jsx | 3 ++- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/components/CookieConsent.jsx b/src/components/CookieConsent.jsx index 93f15f939a04..1a5dd070c5ed 100644 --- a/src/components/CookieConsent.jsx +++ b/src/components/CookieConsent.jsx @@ -2,9 +2,11 @@ import React, { useEffect, useState } from 'react' import { CModal, CCard, CCardTitle, CCardContent, CButton } from '@cscfi/csc-ui-react' -export const CookieModal = () => { +export const CookieModal = props => { const [isModalOpen, setIsModalOpen] = useState(false); + const chapters = props.chapters || []; + useEffect(() => { const cookieConsent = document.cookie .split('; ') @@ -66,14 +68,15 @@ export const CookieModal = () => { dismissable onChangeValue={() => clickOutside()} > - + Cookie consent -

We use cookies

-

We value your privacy. The FiQCI webpages uses anonymous cookies to collect data about user behavior through Matomo. - This information helps us improve our services and provide a better user experience by telling us how users use the site. -

-

The data collected is non-identifiable and cannot be traced back to you.

+

{props.title}

+ {chapters.map((chapter, index) => ( +
+

{chapter.text}

+
+ ))} Cookie policy
@@ -96,11 +99,13 @@ export const CookieModal = () => { ); }; -export const CookieModalManual = ({ text }) => { +export const CookieModalManual = props => { const [isModalOpen, setIsModalOpen] = useState(false); - + console.log(props); const closeModal = () => setIsModalOpen(false); + const chapters = props.chapters || []; + const handleAcceptCookies = () => { closeModal(); const expiryDate = new Date(); @@ -134,15 +139,15 @@ export const CookieModalManual = ({ text }) => { dismissable onChangeValue={() => closeModal()} > - + Cookie consent -

We use cookies

-

We value your privacy. The FiQCI webpages uses anonymous cookies to collect data about user behavior through Matomo. - This information helps us improve our services and provide a better user experience by telling us how users use the site. -

-

The data collected is non-identifiable and cannot be traced back to you.

- +

{props.title}

+ {chapters.map((chapter, index) => ( +
+

{chapter.text}

+
+ ))} Cookie policy
{ export const BaseLayout = props => { const [cookieConsentState, setCookieConsentState] = useState(null); - const headerProps = { logo: props.logo, nav: props.header_nav @@ -62,11 +61,10 @@ export const BaseLayout = props => { } else { setCookieConsentState(null); } - console.log(window.location.pathname) }, []); return <> - {window.location.pathname !== '/cookies/' && } + {window.location.pathname !== '/cookies/' && } {cookieConsentState === true && } {createPortal( , diff --git a/src/pages/cookies.md.jsx b/src/pages/cookies.md.jsx index 80b79c584640..3b5289c7c15b 100644 --- a/src/pages/cookies.md.jsx +++ b/src/pages/cookies.md.jsx @@ -11,11 +11,12 @@ import { CookieModal, CookieModalManual } from '../components/CookieConsent' const CookiesPage = () => { const themeConstants = useJsonApi('api/theme/constants.json') + const cookieConsentProps = themeConstants.cookie_consent return <> {createPortal( - , + , document.getElementById('open-cookie-modal') )} From 856b86c6e437c7bdeb24f9e02fef057a47422603 Mon Sep 17 00:00:00 2001 From: Joonas Nivala Date: Mon, 23 Jun 2025 13:31:12 +0300 Subject: [PATCH 16/19] remove console.log --- src/components/SiteSearch.jsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/SiteSearch.jsx b/src/components/SiteSearch.jsx index 191ceead8900..d73bb7dd0d99 100644 --- a/src/components/SiteSearch.jsx +++ b/src/components/SiteSearch.jsx @@ -345,9 +345,7 @@ export const SiteSearch = () => { // Try to load from localStorage on mount useEffect(() => { let params = new URLSearchParams(document.location.search); - console.log("URL params:", params); let initSearch = params.get("search"); - console.log("Initial search query:", initSearch); if (initSearch && initSearch.trim() !== "") { setQuery(initSearch); const searchResults = searchContent(initSearch, STORE); From e1f0600f3b0ad6058383ab0a54dfe2b2936d41e7 Mon Sep 17 00:00:00 2001 From: Joonas Nivala Date: Mon, 23 Jun 2025 13:46:49 +0300 Subject: [PATCH 17/19] remove console log --- src/components/CookieConsent.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/CookieConsent.jsx b/src/components/CookieConsent.jsx index 1a5dd070c5ed..39169545f3c8 100644 --- a/src/components/CookieConsent.jsx +++ b/src/components/CookieConsent.jsx @@ -101,7 +101,6 @@ export const CookieModal = props => { export const CookieModalManual = props => { const [isModalOpen, setIsModalOpen] = useState(false); - console.log(props); const closeModal = () => setIsModalOpen(false); const chapters = props.chapters || []; From 47dbd4ffa77d8dd8a12f7eb91097fab93b4d0fce Mon Sep 17 00:00:00 2001 From: Joonas Nivala Date: Mon, 23 Jun 2025 13:48:40 +0300 Subject: [PATCH 18/19] formatting --- content/_data/constants.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/content/_data/constants.yml b/content/_data/constants.yml index 2ba9a051a665..647bc8a7deed 100644 --- a/content/_data/constants.yml +++ b/content/_data/constants.yml @@ -263,7 +263,7 @@ cookie_consent: - The FiQCI webpages uses anonymous cookies to collect data about user behavior through Matomo. This information helps us improve our services and provide a better user experience by telling us how users use the site. The data collected is non-identifiable and cannot be traced back to you. - + - Additionally we use mandatory functional cookies to ensure the website functions properly. These cookies do not collect any information about you and only help the website function. They are only valid for the current session and are deleted when you close your browser. @@ -306,8 +306,7 @@ cookie_consent: general: - The FiQCI website is designed to be accessible to all users. We strive to comply with the Web Content Accessibility Guidelines (WCAG) 2.1 Level AA standards. - - - If you encounter any accessibility issues while using our website, please contact us at + If you encounter any accessibility issues while using our website, please contact us at status: title: Compliance Status From d436f1213ac06630e5b17994ced90691e080692d Mon Sep 17 00:00:00 2001 From: Joonas Nivala Date: Mon, 23 Jun 2025 13:52:07 +0300 Subject: [PATCH 19/19] fix scroll issue --- content/_layouts/post.html | 2 +- src/components/ReadNext.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/content/_layouts/post.html b/content/_layouts/post.html index 8ca962d171c2..59010c693d24 100644 --- a/content/_layouts/post.html +++ b/content/_layouts/post.html @@ -45,7 +45,7 @@

Give feedback!

{%- include react/root.html id='references-accordion' -%}
-
+
{%- include react/root.html id='read-next' -%}
diff --git a/src/components/ReadNext.jsx b/src/components/ReadNext.jsx index 6549c3561220..4f0648924109 100644 --- a/src/components/ReadNext.jsx +++ b/src/components/ReadNext.jsx @@ -15,7 +15,7 @@ export const ReadNext = ({ title, blogs }) => {
-
+

Read next:

{SITE.publications.filter((blog) => blog.title !== title).slice(-5).map((blog, index) => (