diff --git a/.env b/.env index f93476da..fec9ab6b 100644 --- a/.env +++ b/.env @@ -52,3 +52,6 @@ SANDBOX_PROC_CREATE_VECT_PYR= # URL de l'API espace collaboratif API_ESPACE_COLLABORATIF_URL= + +# URL d'abonnement à la newsletter +NEWSLETTER_SUBSCRIBE_ACTION= diff --git a/assets/components/Layout/AppFollow.tsx b/assets/components/Layout/AppFollow.tsx new file mode 100644 index 00000000..3c455fa6 --- /dev/null +++ b/assets/components/Layout/AppFollow.tsx @@ -0,0 +1,30 @@ +import { memo } from "react"; +import Follow from "@codegouvfr/react-dsfr/Follow"; +import { routes, useRoute } from "../../router/router"; + +const AppFollow = () => { + const newsletterSubscribeAction = (document.getElementById("app_env") as HTMLDivElement)?.dataset?.["newsletterSubscribeAction"] ?? null; + const route = useRoute(); + + if (newsletterSubscribeAction === null) { + return null; + } + + if (typeof route.name === "string" && /^newsletter_/.test(route.name)) { + return null; + } + + return ( + + ); +}; + +export default memo(AppFollow); diff --git a/assets/components/Layout/AppLayout.tsx b/assets/components/Layout/AppLayout.tsx index b9e8101c..ca3cc9d9 100644 --- a/assets/components/Layout/AppLayout.tsx +++ b/assets/components/Layout/AppLayout.tsx @@ -19,6 +19,7 @@ import SessionExpiredAlert from "../Utils/SessionExpiredAlert"; import SnackbarMessage from "../Utils/SnackbarMessage"; import AppFooter from "./AppFooter"; import AppHeader from "./AppHeader"; +import AppFollow from "./AppFollow"; const HiddenElements: FC = () => { return ( @@ -90,6 +91,7 @@ const AppLayout: FC> = ({ children, navItems, {children} + diff --git a/assets/i18n/Breadcrumb.tsx b/assets/i18n/Breadcrumb.tsx index e9f133a4..2ffedf90 100644 --- a/assets/i18n/Breadcrumb.tsx +++ b/assets/i18n/Breadcrumb.tsx @@ -15,6 +15,10 @@ export const { i18n } = declareComponentKeys< | "join" | "terms_of_service" | "service_status" + | "newsletter_subscribe" + | "newsletter_confirm_email" + | "newsletter_success" + | "newsletter_error" | "accesses_request" | "my_account" | "my_access_keys" @@ -57,6 +61,10 @@ export const BreadcrumbFrTranslations: Translations<"fr">["Breadcrumb"] = { join: "Nous rejoindre", terms_of_service: "Conditions générales d'utilisation", service_status: "Niveau de service", + newsletter_subscribe: "S’inscrire à la lettre d’information", + newsletter_confirm_email: "S’inscrire à la lettre d’information", + newsletter_success: "S’inscrire à la lettre d’information", + newsletter_error: "S’inscrire à la lettre d’information", accesses_request: "Demande d'accès à un service privé", my_account: "Mon compte", my_access_keys: "Mes clés d'accès", @@ -98,7 +106,11 @@ export const BreadcrumbEnTranslations: Translations<"en">["Breadcrumb"] = { offer: "Offer", join: "Join us", terms_of_service: "Terms of Service", - service_status: "TODO", + service_status: "Service Status", + newsletter_subscribe: "Newsletter subscription", + newsletter_confirm_email: "Newsletter subscription", + newsletter_success: "Newsletter subscription", + newsletter_error: "Newsletter subscription", accesses_request: "Request to private resources", my_account: "My account", my_access_keys: "My access keys", diff --git a/assets/modules/entrepot/breadcrumbs.ts b/assets/modules/entrepot/breadcrumbs.ts index acd87397..ec019bbd 100644 --- a/assets/modules/entrepot/breadcrumbs.ts +++ b/assets/modules/entrepot/breadcrumbs.ts @@ -27,6 +27,10 @@ const getBreadcrumb = (route: Route, datastore?: Datastore): Brea case "join": case "terms_of_service": case "service_status": + case "newsletter_subscribe": + case "newsletter_confirm_email": + case "newsletter_success": + case "newsletter_error": return { ...defaultProps, currentPageLabel: t(route.name) }; case "contact_thanks": diff --git a/assets/pages/footer/PersonalData.tsx b/assets/pages/footer/PersonalData.tsx index cc99303e..9d1da83d 100644 --- a/assets/pages/footer/PersonalData.tsx +++ b/assets/pages/footer/PersonalData.tsx @@ -2,6 +2,8 @@ import { fr } from "@codegouvfr/react-dsfr"; import AppLayout from "../../components/Layout/AppLayout"; +import Summary from "@codegouvfr/react-dsfr/Summary"; + const PersonalData = () => { return ( @@ -9,7 +11,117 @@ const PersonalData = () => {

Données à caractère personnel

-

Inscriptions aux événements

+ + +

+ Inscription à la lettre d’information +

+ +

+ L’inscription à la lettre d’information cartes.gouv.fr donne lieu à la collecte, au stockage et au traitement de données à caractère + personnel par l’IGN, responsable de traitement. Les traitements sont référencés ci-dessous : +

+ +

Quels sont les objectifs du recueil de ces données (finalités) ?

+
    +
  • + Gestion de l’envoi de la lettre d’information +
      +
    • Gestion des abonnements à la lettre d’information
    • +
    • Gestion des envois électroniques
    • +
    +
  • +
+

+ Quelles sont les données personnelles collectées (i) ?{" "} +

+

Catégories de données traitées :

+
    +
  • + Adresse email +
  • +
+

Source des données :

+
    +
  • Personnes concernées
  • +
  • Prestataire en charge de la gestion des abonnements et des envois de la lettre d’information
  • +
+

Caractère obligatoire du recueil des données :

+
    +
  • Le recueil de l’adresse email est obligatoire pour l’envoi de la lettre d’information
  • +
+

Quelle est la base juridique du traitement ?

+
    +
  • + Article 6 (1) e du RGPD : ce traitement de données relève d’une mission d’intérêt public dont est investi l’IGN en application du + RGPD et de la loi Informatique et Libertés modifiée. +
  • +
+

Quelles sont les personnes concernées ?

+
    +
  • Le traitement de données concerne les personnes qui souhaitent s’abonner ou se désabonner de la lettre d’information.
  • +
+

Qui pourra prendre en connaissance (destinataires) ?

+
    +
  • Service de l’IGN en charge de gérer la lettre d’information,
  • +
  • Le prestataire en charge de l’abonnement e des envois de la lettre d’information
  • +
+

Quelle est la durée de conservation des données ?

+
    +
  • + L’IGN conserve l’adresse email tant que la personne concernée ne se désinscrit pas (via le lien de désinscription intégré aux + newsletters). +
  • +
+ +

+ Inscriptions aux événements +

L’inscription aux événements (physique ou en ligne) sur le site cartes.gouv.fr donne lieu à la collecte, au stockage et au traitement de @@ -31,7 +143,9 @@ const PersonalData = () => { sur le site du partenaire organisateur de cet événement.

-

Accès à certaines API par un fournisseur d’identité

+

+ Accès à certaines API par un fournisseur d’identité +

Certaines API sont accessibles et utilisables après authentification auprès de l’un des fournisseurs d’identité suivants :

    @@ -41,7 +155,9 @@ const PersonalData = () => {

    Nous vous invitons à lire les politiques de protection des données personnelles de ces fournisseurs d’identité.

    -

    Création d’un compte personnel

    +

    + Création d’un compte personnel +

    Le site cartes.gouv.fr offre aux utilisateurs la possibilité de créer un compte personnel pour accéder à des fonctions particulières et @@ -105,7 +221,9 @@ const PersonalData = () => {

    2 ans à compter de la date de dernière connexion ou de la suppression du compte personnel ou du service

    -

    Prise de contact via le formulaire de contact

    +

    + Prise de contact via le formulaire de contact +

    La prise de contact via le formulaire de contact donne lieu à la collecte, au stockage et au traitement de données à caractère personnel @@ -147,7 +265,9 @@ const PersonalData = () => {

    La durée de conservation des données à caractère personnel est fixée par l’IGN à trois ans à compter de la dernière sollicitation

    -

    Participation à une enquête utilisateur

    +

    + Participation à une enquête utilisateur +

    La participation à une enquête utilisateur donne lieu à la collecte, au stockage et au traitement de données à caractère personnel par @@ -194,7 +314,9 @@ const PersonalData = () => {

    La durée de conservation des données est fixée à 5 ans à compter de la date de participation à une enquête utilisateur.

    -

    Inscription aux communautés d’utilisateurs

    +

    + Inscription aux communautés d’utilisateurs +

    L’inscription aux communautés d’utilisateurs IGN donne lieu à la collecte, au stockage et au traitement de données à caractère personnel diff --git a/assets/pages/newsletter/NewsletterConfirmEmail.tsx b/assets/pages/newsletter/NewsletterConfirmEmail.tsx new file mode 100644 index 00000000..bba0cdf2 --- /dev/null +++ b/assets/pages/newsletter/NewsletterConfirmEmail.tsx @@ -0,0 +1,26 @@ +import { fr } from "@codegouvfr/react-dsfr"; +import AppLayout from "../../components/Layout/AppLayout"; + +import { Button } from "@codegouvfr/react-dsfr/Button"; +import Translator from "../../modules/Translator"; +import { routes } from "../../router/router"; + +const NewsletterConfirmEmail = () => { + return ( + +

    +
    +

    S’inscrire à la lettre d’information

    + +

    Veuillez consultez vos emails pour confirmer votre inscription.

    + +
    + +
    +
    +
    + + ); +}; + +export default NewsletterConfirmEmail; diff --git a/assets/pages/newsletter/NewsletterError.tsx b/assets/pages/newsletter/NewsletterError.tsx new file mode 100644 index 00000000..225b22bb --- /dev/null +++ b/assets/pages/newsletter/NewsletterError.tsx @@ -0,0 +1,27 @@ +import { fr } from "@codegouvfr/react-dsfr"; +import AppLayout from "../../components/Layout/AppLayout"; + +import { Alert } from "@codegouvfr/react-dsfr/Alert"; +import { Button } from "@codegouvfr/react-dsfr/Button"; +import Translator from "../../modules/Translator"; +import { routes } from "../../router/router"; + +const NewsletterError = () => { + return ( + +
    +
    +

    S’inscrire à la lettre d’information

    + + + +
    + +
    +
    +
    +
    + ); +}; + +export default NewsletterError; diff --git a/assets/pages/newsletter/NewsletterSubscribe.tsx b/assets/pages/newsletter/NewsletterSubscribe.tsx new file mode 100644 index 00000000..b8562492 --- /dev/null +++ b/assets/pages/newsletter/NewsletterSubscribe.tsx @@ -0,0 +1,48 @@ +import { fr } from "@codegouvfr/react-dsfr"; +import AppLayout from "../../components/Layout/AppLayout"; +import Button from "@codegouvfr/react-dsfr/Button"; +import Input from "@codegouvfr/react-dsfr/Input"; +import { routes } from "../../router/router"; + +const NewsletterSubscribe = () => { + const newsletterSubscribeAction = (document.getElementById("app_env") as HTMLDivElement)?.dataset?.["newsletterSubscribeAction"] ?? null; + + return ( + +
    +
    +

    S’inscrire à la lettre d’information

    +

    Pour être alerté des dernières actualités...

    + {newsletterSubscribeAction === null ? ( +

    Le formulaire d’inscription n’est pas disponible

    + ) : ( + <> +
    + + +
    +

    + En savoir plus sur la gestion des données à caractère personnel +

    + + )} +
    +
    +
    + ); +}; + +export default NewsletterSubscribe; diff --git a/assets/pages/newsletter/NewsletterSuccess.tsx b/assets/pages/newsletter/NewsletterSuccess.tsx new file mode 100644 index 00000000..20da1802 --- /dev/null +++ b/assets/pages/newsletter/NewsletterSuccess.tsx @@ -0,0 +1,27 @@ +import { fr } from "@codegouvfr/react-dsfr"; +import AppLayout from "../../components/Layout/AppLayout"; + +import { Alert } from "@codegouvfr/react-dsfr/Alert"; +import { Button } from "@codegouvfr/react-dsfr/Button"; +import Translator from "../../modules/Translator"; +import { routes } from "../../router/router"; + +const NewsletterSuccess = () => { + return ( + +
    +
    +

    S’inscrire à la lettre d’information

    + + + +
    + +
    +
    +
    +
    + ); +}; + +export default NewsletterSuccess; diff --git a/assets/router/RouterRenderer.tsx b/assets/router/RouterRenderer.tsx index 8e3cdec7..db69d8a1 100644 --- a/assets/router/RouterRenderer.tsx +++ b/assets/router/RouterRenderer.tsx @@ -24,6 +24,10 @@ const Accessibility = lazy(() => import("../pages/footer/Accessibility")); const LegalNotice = lazy(() => import("../pages/footer/LegalNotice")); const PersonalData = lazy(() => import("../pages/footer/PersonalData")); const TermsOfService = lazy(() => import("../pages/footer/TermsOfService")); +const NewsletterSubscribe = lazy(() => import("../pages/newsletter/NewsletterSubscribe")); +const NewsletterConfirmEmail = lazy(() => import("../pages/newsletter/NewsletterConfirmEmail")); +const NewsletterSuccess = lazy(() => import("../pages/newsletter/NewsletterSuccess")); +const NewsletterError = lazy(() => import("../pages/newsletter/NewsletterError")); const LoginDisabled = lazy(() => import("../pages/LoginDisabled")); const Me = lazy(() => import("../entrepot/pages/users/Me")); @@ -109,6 +113,14 @@ const RouterRenderer: FC = () => { return ; case "service_status": return ; + case "newsletter_subscribe": + return ; + case "newsletter_confirm_email": + return ; + case "newsletter_success": + return ; + case "newsletter_error": + return ; case "login_disabled": return ; case "my_account": diff --git a/assets/router/router.ts b/assets/router/router.ts index b0063091..40971417 100644 --- a/assets/router/router.ts +++ b/assets/router/router.ts @@ -35,6 +35,10 @@ const routeDefs = { terms_of_service: defineRoute(`${appRoot}/cgu`), service_status: defineRoute(`${appRoot}/niveau-de-service`), login_disabled: defineRoute(`${appRoot}/connexion-desactivee`), + newsletter_subscribe: defineRoute(`${appRoot}/inscription-a-la-lettre`), + newsletter_confirm_email: defineRoute(`${appRoot}/inscription-a-la-lettre/confirmez-votre-inscription`), + newsletter_success: defineRoute(`${appRoot}/inscription-a-la-lettre/confirmation`), + newsletter_error: defineRoute(`${appRoot}/inscription-a-la-lettre/erreur`), // NOTE : routes protégées // utilisateur @@ -253,5 +257,9 @@ export const publicRoutes: typeof knownRoutes = [ "join", "terms_of_service", "service_status", + "newsletter_subscribe", + "newsletter_confirm_email", + "newsletter_success", + "newsletter_error", "login_disabled", ]; diff --git a/config/packages/twig.yaml b/config/packages/twig.yaml index 5c4dc5c4..47fa464a 100644 --- a/config/packages/twig.yaml +++ b/config/packages/twig.yaml @@ -3,6 +3,7 @@ twig: globals: api_espaceco_url: "%api_espaceco_url%" catalogue_url: "%catalogue_url%" + newsletter_subscribe_action: "%newsletter_subscribe_action%" when@test: twig: diff --git a/config/parameters.yaml b/config/parameters.yaml index 6ed7f0c1..180f6f96 100644 --- a/config/parameters.yaml +++ b/config/parameters.yaml @@ -43,4 +43,5 @@ parameters: api_espaceco_url: "%env(resolve:API_ESPACE_COLLABORATIF_URL)%" catalogue_url: "%env(resolve:CATALOGUE_URL)%" - # geonetwork_url: "%env(resolve:GEONETWORK_URL)%" + + newsletter_subscribe_action: "%env(resolve:NEWSLETTER_SUBSCRIBE_ACTION)%" diff --git a/templates/app.html.twig b/templates/app.html.twig index d729bcc5..c32000e0 100644 --- a/templates/app.html.twig +++ b/templates/app.html.twig @@ -7,6 +7,7 @@