diff --git a/assets/@types/analytics.d.ts b/assets/@types/analytics.d.ts new file mode 100644 index 00000000..2103f324 --- /dev/null +++ b/assets/@types/analytics.d.ts @@ -0,0 +1,14 @@ +import analytics from "@codegouvfr/react-dsfr/dsfr/analytics"; + +declare global { + interface Window { + dsfr: { + // analytics: EulerianAnalyticsParams; // au début je croyais que c'était ça, mais en fait ce sont les params d'initialisation de l'instance analytics, mais après la classe analytics exportée est différente + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + // analytics: any; + + analytics: typeof analytics; // "analytics" est exporté comme "any", donc ne sert à rien + }; + } +} diff --git a/assets/components/Layout/AppFooter.tsx b/assets/components/Layout/AppFooter.tsx index e338ea45..1b3fad71 100644 --- a/assets/components/Layout/AppFooter.tsx +++ b/assets/components/Layout/AppFooter.tsx @@ -16,6 +16,7 @@ const AppFooter = () => { accessibility="partially compliant" accessibilityLinkProps={{ ...routes.accessibility().link, + id: "footer-accessibility-link", }} brandTop={ <> @@ -29,7 +30,10 @@ const AppFooter = () => { " bottomItems={[ { - linkProps: routes.terms_of_service().link, + linkProps: { + ...routes.terms_of_service().link, + id: "footer-terms-of-service-link", + }, text: "Conditions générales d’utilisation", }, , @@ -40,34 +44,53 @@ const AppFooter = () => { homeLinkProps={{ ...routes.home().link, title: "Accueil - cartes.gouv.fr", + id: "footer-home-link", }} termsLinkProps={{ ...routes.legal_notice().link, + id: "footer-legal-notice-link", }} websiteMapLinkProps={{ ...routes.sitemap().link, + id: "footer-sitemap-link", }} partnersLogos={{ sub: [ { alt: "IGN", - href: "https://www.ign.fr", imgUrl: logoIgn, + linkProps: { + id: "footer-ign-link", + title: "IGN", + href: "https://www.ign.fr", + }, }, { alt: "MINISTÈRE DE LA TRANSFORMATION ET DE LA FONCTION PUBLIQUES", - href: "https://www.transformation.gouv.fr/", imgUrl: logoMinistereTransformation, + linkProps: { + id: "footer-ministere-transformation-link", + title: "MINISTÈRE DE LA TRANSFORMATION ET DE LA FONCTION PUBLIQUES", + href: "https://www.transformation.gouv.fr/", + }, }, { alt: "MINISTÈRE DE LA TRANSITION ÉCOLOGIQUE ET DE LA COHÉSION DES TERRITOIRES", - href: "https://www.ecologie.gouv.fr/", imgUrl: logoMinistereEcologie, + linkProps: { + id: "footer-ministere-ecologie-link", + title: "MINISTÈRE DE LA TRANSITION ÉCOLOGIQUE ET DE LA COHÉSION DES TERRITOIRES", + href: "https://www.ecologie.gouv.fr/", + }, }, { alt: "Conseil National de l’Information Géolocalisée", - href: "https://cnig.gouv.fr/", imgUrl: logoCnig, + linkProps: { + id: "footer-cnig-link", + title: "Conseil National de l’Information Géolocalisée", + href: "https://cnig.gouv.fr/", + }, }, ], }} diff --git a/assets/components/Layout/AppHeader.tsx b/assets/components/Layout/AppHeader.tsx index 3917070a..2d4031d7 100644 --- a/assets/components/Layout/AppHeader.tsx +++ b/assets/components/Layout/AppHeader.tsx @@ -29,6 +29,7 @@ const AppHeader: FC = ({ navItems = [] }) => { target: "_blank", rel: "noreferrer", title: "Accéder au Géoportail - ouvre une nouvelle fenêtre", + id: "header-geoportail-link", }, text: "Accéder au Géoportail", }; @@ -41,6 +42,7 @@ const AppHeader: FC = ({ navItems = [] }) => { target: "_blank", rel: "noreferrer", title: "Catalogue - ouvre une nouvelle fenêtre", + id: "header-catalogue-link", }, text: "Catalogue", }; @@ -53,6 +55,7 @@ const AppHeader: FC = ({ navItems = [] }) => { iconId: "fr-icon-account-fill", linkProps: { href: SymfonyRouting.generate("cartesgouvfr_security_login"), + id: "header-login-link", }, text: "Se connecter", }); @@ -73,13 +76,17 @@ const AppHeader: FC = ({ navItems = [] }) => { quickAccessItems.push({ iconId: "fr-icon-account-fill", - linkProps: routes.dashboard_pro().link, + linkProps: { + ...routes.dashboard_pro().link, + id: "header-dashboard-link", + }, text: btnMyAccountText.trim(), }); quickAccessItems.push({ iconId: "fr-icon-logout-box-r-line", linkProps: { href: SymfonyRouting.generate("cartesgouvfr_security_logout"), + id: "header-logout-link", }, text: "Se déconnecter", }); @@ -99,6 +106,7 @@ const AppHeader: FC = ({ navItems = [] }) => { homeLinkProps={{ ...routes.home().link, title: "Accueil - cartes.gouv.fr", + id: "header-home-link", }} serviceTitle={ <> diff --git a/assets/components/Layout/AppLayout.tsx b/assets/components/Layout/AppLayout.tsx index b9e8101c..ed84baa9 100644 --- a/assets/components/Layout/AppLayout.tsx +++ b/assets/components/Layout/AppLayout.tsx @@ -31,6 +31,7 @@ const HiddenElements: FC = () => { { anchor: "#main", label: Translator.trans("site.go_to_content"), + id: "skip-to-content-link", }, ]} /> diff --git a/assets/config/consentManagement.tsx b/assets/config/consentManagement.tsx index 626a005d..15748e68 100644 --- a/assets/config/consentManagement.tsx +++ b/assets/config/consentManagement.tsx @@ -24,6 +24,7 @@ export const { ConsentBannerAndConsentManagement, FooterConsentManagementItem, F }), personalDataPolicyLinkProps: { href: routes.personal_data().href, + id: "footer-personal-data-policy-link", }, consentCallback: async ({ finalityConsent }) => { diff --git a/assets/entrepot/pages/dashboard/DashboardPro.tsx b/assets/entrepot/pages/dashboard/DashboardPro.tsx index 3499feb1..45a2a24c 100644 --- a/assets/entrepot/pages/dashboard/DashboardPro.tsx +++ b/assets/entrepot/pages/dashboard/DashboardPro.tsx @@ -17,7 +17,7 @@ import { CartesApiException } from "../../../modules/jsonFetch"; import { routes } from "../../../router/router"; import { useApiEspaceCoStore } from "../../../stores/ApiEspaceCoStore"; import { useAuthStore } from "../../../stores/AuthStore"; -import { getArrayRange } from "../../../utils"; +import { getArrayRange, hashStringSHA256 } from "../../../utils"; import api from "../../api"; import avatarSvgUrl from "@codegouvfr/react-dsfr/dsfr/artwork/pictograms/digital/avatar.svg"; @@ -54,6 +54,30 @@ const DashboardPro = () => { } }, [setUser, userQuery.data]); + useEffect(() => { + if (user) { + console.log(window.dsfr.analytics); + + hashStringSHA256(user.email) + .then((hashedEmail) => { + // window.dsfr = { + // analytics: { + // user: { + // uid: user.id, + // status: "connected", + // }, + // }, + // }; + window.dsfr.analytics.user.connect(user.id, hashedEmail, false); + }) + .catch((error) => { + console.log("Email hash error", error); + }); + + console.log(window.dsfr.analytics); + } + }, [user]); + const { mutate } = useMutation({ mutationFn: () => { return api.user.addToSandbox(); @@ -73,6 +97,7 @@ const DashboardPro = () => { target="_blank" rel="noreferrer" title="Questionnaire sur la fonctionnalité alimentation et diffusion - Ouvre une nouvelle fenêtre" + id="questionnaire-alimentation-diffusion-link" > Participer diff --git a/assets/pages/Home.tsx b/assets/pages/Home.tsx index b3e78527..73e633e0 100644 --- a/assets/pages/Home.tsx +++ b/assets/pages/Home.tsx @@ -42,6 +42,7 @@ const Home = () => { target="_blank" rel="noreferrer" title="Formulaire d’inscription à des ateliers cartes.gouv.fr - Ouvre une nouvelle fenêtre" + id="home-info-banner-link" > Inscrivez-vous diff --git a/assets/utils.ts b/assets/utils.ts index 6e1e0e33..39940ed0 100644 --- a/assets/utils.ts +++ b/assets/utils.ts @@ -221,6 +221,20 @@ const trimObject = (obj: object): object => { return newObject; }; +async function hashStringSHA256(str: string): Promise { + // encodage chaîne en Uint8Array pour la fonction crypto.subtle.digest + const encoder = new TextEncoder(); + const data = encoder.encode(str); + + const hashBuffer = await crypto.subtle.digest("SHA-256", data); + + // convertir le hash du binaire en chaîne hexadécimal + const hashArray = Array.from(new Uint8Array(hashBuffer)); + const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join(""); + + return hashHex; +} + export { getInspireKeywords, getLanguages, @@ -237,4 +251,5 @@ export { formatDateWithoutTimeFromISO, getArrayRange, trimObject, + hashStringSHA256, }; diff --git a/codegouvfr-react-dsfr-v1.14.10x.tgz b/codegouvfr-react-dsfr-v1.14.10x.tgz new file mode 100644 index 00000000..2e70b599 Binary files /dev/null and b/codegouvfr-react-dsfr-v1.14.10x.tgz differ diff --git a/package.json b/package.json index 73cb1ad5..7433da3b 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "node": ">=20.0.0" }, "dependencies": { - "@codegouvfr/react-dsfr": "^1.10.11", + "@codegouvfr/react-dsfr": "./codegouvfr-react-dsfr-v1.14.10x.tgz", "@emotion/react": "^11.13.0", "@emotion/styled": "^11.11.0", "@fvilers/disable-react-devtools": "^1.3.0", diff --git a/yarn.lock b/yarn.lock index ac0a549a..c1dbf5a9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1081,12 +1081,11 @@ "@babel/helper-validator-identifier" "^7.24.7" to-fast-properties "^2.0.0" -"@codegouvfr/react-dsfr@^1.10.11": - version "1.14.1" - resolved "https://registry.yarnpkg.com/@codegouvfr/react-dsfr/-/react-dsfr-1.14.1.tgz#0983346795fdfd1e1bdf14dedc9412acf782d1e8" - integrity sha512-ncoVbN6PSQVXbyu/KgkRSOfKiHxOLEEfJW9Z8rdVBBDnQuYpYCE91NVlRC27YdrXy1Kklf0MTYWEoO7hgpE7VQ== +"@codegouvfr/react-dsfr@./codegouvfr-react-dsfr-v1.14.10x.tgz": + version "1.14.10" + resolved "./codegouvfr-react-dsfr-v1.14.10x.tgz#b59e9b35cdf996a925fb4dd439ad39d46189a26a" dependencies: - tsafe "^1.7.2" + tsafe "^1.8.5" yargs-parser "^21.1.1" "@colors/colors@1.5.0": @@ -8055,6 +8054,11 @@ tsafe@^1.6.5, tsafe@^1.6.6, tsafe@^1.7.2, tsafe@^1.7.5: resolved "https://registry.yarnpkg.com/tsafe/-/tsafe-1.7.5.tgz#0d3a31202b5ef87c7ba997e66e03fd80801278ef" integrity sha512-tbNyyBSbwfbilFfiuXkSOj82a6++ovgANwcoqBAcO9/REPoZMEQoE8kWPeO0dy5A2D/2Lajr8Ohue5T0ifIvLQ== +tsafe@^1.8.5: + version "1.8.5" + resolved "https://registry.yarnpkg.com/tsafe/-/tsafe-1.8.5.tgz#cdf9fa3111974ac480d7ee519f8241815e5d22ea" + integrity sha512-LFWTWQrW6rwSY+IBNFl2ridGfUzVsPwrZ26T4KUJww/py8rzaQ/SY+MIz6YROozpUCaRcuISqagmlwub9YT9kw== + tslib@^2.1.0: version "2.6.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0"