Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: newsletter #522

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
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
3 changes: 3 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -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=
30 changes: 30 additions & 0 deletions assets/components/Layout/AppFollow.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<Follow
newsletter={{
buttonProps: {
linkProps: {
...routes.newsletter_subscribe().link,
},
},
}}
/>
);
};

export default memo(AppFollow);
2 changes: 2 additions & 0 deletions assets/components/Layout/AppLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -90,6 +91,7 @@ const AppLayout: FC<PropsWithChildren<AppLayoutProps>> = ({ children, navItems,
{children}
</div>
</main>
<AppFollow />
<AppFooter />
<SnackbarMessage />
</>
Expand Down
14 changes: 13 additions & 1 deletion assets/i18n/Breadcrumb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down
4 changes: 4 additions & 0 deletions assets/modules/entrepot/breadcrumbs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ const getBreadcrumb = (route: Route<typeof routes>, 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":
Expand Down
134 changes: 128 additions & 6 deletions assets/pages/footer/PersonalData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,126 @@ import { fr } from "@codegouvfr/react-dsfr";

import AppLayout from "../../components/Layout/AppLayout";

import Summary from "@codegouvfr/react-dsfr/Summary";

const PersonalData = () => {
return (
<AppLayout documentTitle="Données à caractère personnel">
<div className={fr.cx("fr-grid-row")}>
<div className={fr.cx("fr-col-12", "fr-col-md-8")}>
<h1>Données à caractère personnel</h1>

<h2>Inscriptions aux événements</h2>
<Summary
links={[
{
text: "Inscription à la lettre d’information",
linkProps: {
href: "#lettre-information",
},
},
{
text: "Inscriptions aux événements",
linkProps: {
href: "#evenements",
},
},
{
text: "Accès à certaines API par un fournisseur d’identité",
linkProps: {
href: "#fournisseurs-identite",
},
},
{
text: "Création d’un compte personnel",
linkProps: {
href: "#creation-compte",
},
},
{
text: "Prise de contact via le formulaire de contact",
linkProps: {
href: "#contact",
},
},
{
text: "Participation à une enquête utilisateur",
linkProps: {
href: "#enquete",
},
},
{
text: "Inscription aux communautés d’utilisateurs",
linkProps: {
href: "#communautes",
},
},
]}
/>

<h2 id="lettre-information" tabIndex={-1}>
Inscription à la lettre d’information
</h2>

<p>
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&nbsp;:
</p>

<h3>Quels sont les objectifs du recueil de ces données (finalités)&nbsp;?</h3>
<ul>
<li>
Gestion de l’envoi de la lettre d’information
<ul>
<li>Gestion des abonnements à la lettre d’information</li>
<li>Gestion des envois électroniques</li>
</ul>
</li>
</ul>
<h3>
Quelles sont les données personnelles collectées <a href="#footnote1">(i)</a>&nbsp;?{" "}
</h3>
<p>Catégories de données traitées&nbsp;:</p>
<ul>
<li>
<strong>Adresse email</strong>
</li>
</ul>
<p>Source des données&nbsp;:</p>
<ul>
<li>Personnes concernées</li>
<li>Prestataire en charge de la gestion des abonnements et des envois de la lettre d’information</li>
</ul>
<p>Caractère obligatoire du recueil des données&nbsp;:</p>
<ul>
<li>Le recueil de l’adresse email est obligatoire pour l’envoi de la lettre d’information</li>
</ul>
<h3>Quelle est la base juridique du traitement&nbsp;?</h3>
<ul>
<li>
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.
</li>
</ul>
<h3>Quelles sont les personnes concernées&nbsp;?</h3>
<ul>
<li>Le traitement de données concerne les personnes qui souhaitent s’abonner ou se désabonner de la lettre d’information.</li>
</ul>
<h3>Qui pourra prendre en connaissance (destinataires)&nbsp;?</h3>
<ul>
<li>Service de l’IGN en charge de gérer la lettre d’information,</li>
<li>Le prestataire en charge de l’abonnement e des envois de la lettre d’information</li>
</ul>
<h3>Quelle est la durée de conservation des données&nbsp;?</h3>
<ul>
<li>
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).
</li>
</ul>

<h2 id="evenements" tabIndex={-1}>
Inscriptions aux événements
</h2>

<p>
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
Expand All @@ -31,7 +143,9 @@ const PersonalData = () => {
sur le site du partenaire organisateur de cet événement.
</p>

<h2>Accès à certaines API par un fournisseur d’identité</h2>
<h2 id="fournisseurs-identite" tabIndex={-1}>
Accès à certaines API par un fournisseur d’identité
</h2>

<p>Certaines API sont accessibles et utilisables après authentification auprès de l’un des fournisseurs d’identité suivants&nbsp;:</p>
<ul>
Expand All @@ -41,7 +155,9 @@ const PersonalData = () => {

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

<h2>Création d’un compte personnel</h2>
<h2 id="creation-compte" tabIndex={-1}>
Création d’un compte personnel
</h2>

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

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

<h2>Prise de contact via le formulaire de contact</h2>
<h2 id="contact" tabIndex={-1}>
Prise de contact via le formulaire de contact
</h2>

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

<p>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</p>

<h2>Participation à une enquête utilisateur</h2>
<h2 id="enquete" tabIndex={-1}>
Participation à une enquête utilisateur
</h2>

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

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

<h2>Inscription aux communautés d’utilisateurs</h2>
<h2 id="communautes" tabIndex={-1}>
Inscription aux communautés d’utilisateurs
</h2>

<p>
L’inscription aux communautés d’utilisateurs IGN donne lieu à la collecte, au stockage et au traitement de données à caractère personnel
Expand Down
26 changes: 26 additions & 0 deletions assets/pages/newsletter/NewsletterConfirmEmail.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<AppLayout documentTitle="S’inscrire à la lettre d’information">
<div className={fr.cx("fr-grid-row")}>
<div className={fr.cx("fr-col-12", "fr-col-md-8")}>
<h1>S’inscrire à la lettre d’information</h1>

<p>Veuillez consultez vos emails pour confirmer votre inscription.</p>

<div className={fr.cx("fr-mt-10v")}>
<Button linkProps={routes.home().link}>{Translator.trans("pursue")}</Button>
</div>
</div>
</div>
</AppLayout>
);
};

export default NewsletterConfirmEmail;
27 changes: 27 additions & 0 deletions assets/pages/newsletter/NewsletterError.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<AppLayout documentTitle="S’inscrire à la lettre d’information">
<div className={fr.cx("fr-grid-row")}>
<div className={fr.cx("fr-col-12", "fr-col-md-8")}>
<h1>S’inscrire à la lettre d’information</h1>

<Alert title="Votre inscription à la lettre d’information a échoué" severity="error" />

<div className={fr.cx("fr-mt-10v")}>
<Button linkProps={routes.home().link}>{Translator.trans("pursue")}</Button>
</div>
</div>
</div>
</AppLayout>
);
};

export default NewsletterError;
48 changes: 48 additions & 0 deletions assets/pages/newsletter/NewsletterSubscribe.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<AppLayout documentTitle="S’inscrire à la lettre d’information">
<div className={fr.cx("fr-grid-row")}>
<div className={fr.cx("fr-col-12", "fr-col-md-8")}>
<h1>S’inscrire à la lettre d’information</h1>
<p>Pour être alerté des dernières actualités...</p>
{newsletterSubscribeAction === null ? (
<p>Le formulaire d’inscription n’est pas disponible</p>
) : (
<>
<form action={newsletterSubscribeAction} name="form" method="post">
<Input
state="default"
label="Votre adresse électronique"
hintText="ex. : [email protected]"
nativeInputProps={{
placeholder: "Votre adresse électronique (ex. : [email protected])",
type: "email",
autoComplete: "email",
id: "contact_email",
name: "contact_email",
}}
/>
<Button id="newsletter-button" type="submit" title="S’abonner à notre lettre d’information">
S’abonner
</Button>
</form>
<p>
<a {...routes.personal_data().link}>En savoir plus sur la gestion des données à caractère personnel</a>
</p>
</>
)}
</div>
</div>
</AppLayout>
);
};

export default NewsletterSubscribe;
Loading
Loading