From bb57eebff84925388f46e0221d5e06e562e2f926 Mon Sep 17 00:00:00 2001 From: carolineBda Date: Tue, 15 Oct 2024 16:08:36 +0200 Subject: [PATCH] =?UTF-8?q?feat(dsfr):=20migration=20de=20la=20page=20mod?= =?UTF-8?q?=C3=A8le=20de=20document?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/modeles-de-courriers/[slug]/page.tsx | 49 +++++++ .../modeles-de-courriers/[id]/page.tsx | 28 ++++ .../code-du-travail-frontend/package.json | 2 +- .../pages/modeles-de-courriers/[slug].tsx | 64 --------- .../widgets/modeles-de-courriers/[id].tsx | 82 ----------- .../img/modeles-de-courriers-download.svg | 1 + .../src/modeles/index.ts | 2 - .../src/modeles/modeles.tsx | 129 ------------------ .../__tests__/modeles.test.tsx | 8 +- .../__tests__/queries.es.test.ts | 47 ++++++- .../components/CopyButton.tsx | 54 ++++++++ .../components/DownloadTile.tsx | 30 ++++ .../components/LetterModelContent.tsx | 85 ++++++++++++ .../modeles-de-courriers}/helpers.ts | 0 .../src/modules/modeles-de-courriers/index.ts | 3 + .../modules/modeles-de-courriers/modeles.tsx | 93 +++++++++++++ .../modules/modeles-de-courriers/queries.ts | 45 +++++- .../src/modules/modeles-de-courriers/type.ts | 7 + .../widgets/WidgetWithIframeResizer.tsx | 13 ++ yarn.lock | 10 +- 20 files changed, 459 insertions(+), 293 deletions(-) create mode 100644 packages/code-du-travail-frontend/app/modeles-de-courriers/[slug]/page.tsx create mode 100644 packages/code-du-travail-frontend/app/widgets/modeles-de-courriers/[id]/page.tsx delete mode 100644 packages/code-du-travail-frontend/pages/modeles-de-courriers/[slug].tsx delete mode 100644 packages/code-du-travail-frontend/pages/widgets/modeles-de-courriers/[id].tsx create mode 100644 packages/code-du-travail-frontend/public/static/assets/img/modeles-de-courriers-download.svg delete mode 100644 packages/code-du-travail-frontend/src/modeles/index.ts delete mode 100644 packages/code-du-travail-frontend/src/modeles/modeles.tsx rename packages/code-du-travail-frontend/src/{modeles => modules/modeles-de-courriers}/__tests__/modeles.test.tsx (90%) create mode 100644 packages/code-du-travail-frontend/src/modules/modeles-de-courriers/components/CopyButton.tsx create mode 100644 packages/code-du-travail-frontend/src/modules/modeles-de-courriers/components/DownloadTile.tsx create mode 100644 packages/code-du-travail-frontend/src/modules/modeles-de-courriers/components/LetterModelContent.tsx rename packages/code-du-travail-frontend/src/{modeles => modules/modeles-de-courriers}/helpers.ts (100%) create mode 100644 packages/code-du-travail-frontend/src/modules/modeles-de-courriers/modeles.tsx create mode 100644 packages/code-du-travail-frontend/src/modules/modeles-de-courriers/type.ts create mode 100644 packages/code-du-travail-frontend/src/modules/widgets/WidgetWithIframeResizer.tsx diff --git a/packages/code-du-travail-frontend/app/modeles-de-courriers/[slug]/page.tsx b/packages/code-du-travail-frontend/app/modeles-de-courriers/[slug]/page.tsx new file mode 100644 index 0000000000..fe69eaf5c4 --- /dev/null +++ b/packages/code-du-travail-frontend/app/modeles-de-courriers/[slug]/page.tsx @@ -0,0 +1,49 @@ +import React from "react"; +import { DsfrLayout } from "../../../src/modules/layout"; +import { generateDefaultMetadata } from "../../../src/modules/common/metas"; +import { + fetchModel, + getTitle, + LetterModel, +} from "../../../src/modules/modeles-de-courriers"; +import { notFound } from "next/navigation"; +import { fetchRelatedItems } from "../../../src/modules/documents"; + +export async function generateMetadata({ params }) { + const { title, type, metaDescription, meta_title } = await getModel( + params.slug + ); + const category = `Modèle ${type !== "fichier" ? `de ${type}` : "à télécharger"}`; + + return generateDefaultMetadata({ + title: `${category} : ${meta_title ?? title}`, + description: metaDescription, + path: `/modeles-de-courriers/${params.slug}`, + }); +} + +async function ModeleCourrier({ params }) { + const { title, ...model } = await getModel(params.slug); + + const relatedItems = await fetchRelatedItems({ _id: model._id }, params.slug); + + return ( + + + + ); +} + +const getModel = async (slug: string) => { + const model = await fetchModel(slug); + + if (!model) { + return notFound(); + } + return model; +}; +export default ModeleCourrier; diff --git a/packages/code-du-travail-frontend/app/widgets/modeles-de-courriers/[id]/page.tsx b/packages/code-du-travail-frontend/app/widgets/modeles-de-courriers/[id]/page.tsx new file mode 100644 index 0000000000..20296320be --- /dev/null +++ b/packages/code-du-travail-frontend/app/widgets/modeles-de-courriers/[id]/page.tsx @@ -0,0 +1,28 @@ +import { + fetchModelById, + getTitle, +} from "../../../../src/modules/modeles-de-courriers"; +import { notFound } from "next/navigation"; +import { LetterModelContent } from "../../../../src/modules/modeles-de-courriers/components/LetterModelContent"; +import { WidgetWithIframeResizer } from "../../../../src/modules/widgets/WidgetWithIframeResizer"; // import { useIframeResizer } from "../../../../src/common/hooks"; + +async function WidgetModel({ params }) { + const { title, ...model } = await getModel(params.id); + + return ( + + + + ); +} + +export const getModel = async (id: string) => { + const modele = await fetchModelById(id); + + if (!modele) { + return notFound(); + } + return modele; +}; + +export default WidgetModel; diff --git a/packages/code-du-travail-frontend/package.json b/packages/code-du-travail-frontend/package.json index f7722b30fa..72f76a64f1 100644 --- a/packages/code-du-travail-frontend/package.json +++ b/packages/code-du-travail-frontend/package.json @@ -33,7 +33,7 @@ "format:check": "prettier --check \"**/*.{js,ts,tsx,jsx,json,md}\"" }, "dependencies": { - "@codegouvfr/react-dsfr": "^1.13.4", + "@codegouvfr/react-dsfr": "^1.13.9", "@elastic/elasticsearch": "^8.13.1", "@matejmazur/react-katex": "^3.1.3", "@opentelemetry/instrumentation-generic-pool": "^0.37.0", diff --git a/packages/code-du-travail-frontend/pages/modeles-de-courriers/[slug].tsx b/packages/code-du-travail-frontend/pages/modeles-de-courriers/[slug].tsx deleted file mode 100644 index 39719725c4..0000000000 --- a/packages/code-du-travail-frontend/pages/modeles-de-courriers/[slug].tsx +++ /dev/null @@ -1,64 +0,0 @@ -import React from "react"; -import { Badge } from "@socialgouv/cdtn-ui"; - -import Metas from "../../src/common/Metas"; -import { Layout } from "../../src/layout/Layout"; -import { LetterModel, LetterModelProps, getTitle } from "../../src/modeles"; -import Answer from "../../src/common/Answer"; -import { getBySourceAndSlugItems } from "../../src/api"; -import { MailTemplate } from "@socialgouv/cdtn-types"; - -function ModeleCourrier(props: LetterModelProps): JSX.Element { - const { - intro = "", - metaDescription, - title, - meta_title, - type, - relatedItems, - date, - breadcrumbs, - slug, - } = props; - const category = `Modèle ${type !== "fichier" ? `de ${type}` : "à télécharger"}`; - return ( - - - - - - - - ); -} - -export const getServerSideProps = async ({ query }) => { - const data = await getBySourceAndSlugItems( - "modeles_de_courriers", - query.slug - ); - if (!data?._source) { - return { - notFound: true, - }; - } - return { - props: { - relatedItems: data.relatedItems, - ...data._source, - slug: query.slug, - }, - }; -}; -export default ModeleCourrier; diff --git a/packages/code-du-travail-frontend/pages/widgets/modeles-de-courriers/[id].tsx b/packages/code-du-travail-frontend/pages/widgets/modeles-de-courriers/[id].tsx deleted file mode 100644 index c60d9e8d8f..0000000000 --- a/packages/code-du-travail-frontend/pages/widgets/modeles-de-courriers/[id].tsx +++ /dev/null @@ -1,82 +0,0 @@ -import Metas from "../../../src/common/Metas"; -import { useIframeResizer } from "../../../src/common/hooks"; -import { SITE_URL } from "../../../src/config"; -import { LetterModel, LetterModelProps } from "../../../src/modeles"; -import styled from "styled-components"; -import { theme, Paragraph, Wrapper, PageTitle } from "@socialgouv/cdtn-ui"; -import { LogoLink } from "../../../src/widgets"; -import Html from "../../../src/common/Html"; -import { isHTML } from "../../../src/lib"; -import { getByIdsModeles } from "../../../src/api"; - -function Widgets(props: LetterModelProps): JSX.Element { - useIframeResizer(); - - return ( - <> - - - - {props.title} - - - - - {isHTML(props.intro) ? ( - {props.intro} - ) : ( - {props.intro} - )} - - - - ); -} - -export const getServerSideProps = async ({ query }) => { - const modeles = await getByIdsModeles([query.id]); - if (!modeles.length) { - return { - notFound: true, - }; - } - return { props: { relatedItems: [], ...(modeles.length ? modeles[0] : {}) } }; -}; - -export default Widgets; - -const { spacings, fonts } = theme; - -const IntroWrapper = styled(Wrapper)` - margin: ${spacings.base} auto; - - & div > *:first-child { - margin-top: 0; - } - - & div > *:last-child { - margin-bottom: 0; - } -`; - -const StyledHeader = styled.div` - display: flex; - align-items: center; - justify-content: center; - - header { - margin: 0; - } -`; - -const StyledTitle = styled(PageTitle)` - flex: 1; - - h1 { - font-size: ${fonts.sizes.headings.xmedium}; - } -`; diff --git a/packages/code-du-travail-frontend/public/static/assets/img/modeles-de-courriers-download.svg b/packages/code-du-travail-frontend/public/static/assets/img/modeles-de-courriers-download.svg new file mode 100644 index 0000000000..05cb1af8f2 --- /dev/null +++ b/packages/code-du-travail-frontend/public/static/assets/img/modeles-de-courriers-download.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/code-du-travail-frontend/src/modeles/index.ts b/packages/code-du-travail-frontend/src/modeles/index.ts deleted file mode 100644 index a1a16042e7..0000000000 --- a/packages/code-du-travail-frontend/src/modeles/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./modeles"; -export * from "./helpers"; diff --git a/packages/code-du-travail-frontend/src/modeles/modeles.tsx b/packages/code-du-travail-frontend/src/modeles/modeles.tsx deleted file mode 100644 index fc8b731d75..0000000000 --- a/packages/code-du-travail-frontend/src/modeles/modeles.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import { - Button, - icons, - ScreenReaderOnly, - Section, - theme, - Wrapper, -} from "@socialgouv/cdtn-ui"; -import React, { useCallback, useEffect } from "react"; -import styled from "styled-components"; -import { Breadcrumb } from "@socialgouv/cdtn-types"; - -import Html from "../../src/common/Html"; -import { MatomoActionEvent, MatomoBaseEvent, toUrl } from "../lib"; -import { getDisclaimer } from "./helpers"; -import { push as matopush } from "@socialgouv/matomo-next"; - -export interface LetterModelProps { - breadcrumbs: Breadcrumb[]; - date: string; - intro: string; - title: string; - relatedItems: Array; - metaDescription: string; - filesize: any; - filename: string; - html: any; - meta_title: string; - type: any; - slug: string; -} - -export const LetterModel = ({ - filename, - filesize, - html, - slug, -}: LetterModelProps) => { - const trackCopy = useCallback(() => { - matopush([ - MatomoBaseEvent.TRACK_EVENT, - MatomoBaseEvent.PAGE_MODELS, - MatomoActionEvent.TYPE_CTRL_C, - slug, - ]); - }, []); - - useEffect(() => { - document.addEventListener("copy", trackCopy); - return () => { - document.removeEventListener("copy", trackCopy); - }; - }, [trackCopy]); - - const filesizeFormated = Math.round((filesize / 1000) * 100) / 100; - const [, extension] = filename.split(/\.([a-z]{2,4})$/); - return ( - <> -
- - - - - {html} - -
- - Type: Modèle de document - Format: {extension} - Taille:{" "} - {filesizeFormated} - Ko{" "} - - - {getDisclaimer(slug)} - - - - - ); -}; - -const { spacings, fonts } = theme; - -const FloatWrapper = styled.div` - position: absolute; - top: -1rem; - right: 2rem; -`; - -const LightWrapper = styled(Wrapper).attrs(() => ({ variant: "light" }))` - position: relative; - padding-top: ${spacings.large}; -`; -const Disclaimer = styled(Wrapper).attrs(() => ({ variant: "dark" }))` - margin-top: ${spacings.medium}; - margin-bottom: ${spacings.large}; -`; - -const Download = styled(icons.Download)` - width: 3rem; -`; - -const Notice = styled.p` - margin-top: -2rem; - font-size: ${fonts.sizes.small}; -`; - -const Centered = styled.p` - display: flex; - justify-content: center; -`; diff --git a/packages/code-du-travail-frontend/src/modeles/__tests__/modeles.test.tsx b/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/__tests__/modeles.test.tsx similarity index 90% rename from packages/code-du-travail-frontend/src/modeles/__tests__/modeles.test.tsx rename to packages/code-du-travail-frontend/src/modules/modeles-de-courriers/__tests__/modeles.test.tsx index 73ec888d89..73c6748ef0 100644 --- a/packages/code-du-travail-frontend/src/modeles/__tests__/modeles.test.tsx +++ b/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/__tests__/modeles.test.tsx @@ -23,11 +23,9 @@ describe("", () => { intro={""} relatedItems={[]} metaDescription={""} - filesize={undefined} + filesize={10} filename={""} html={undefined} - meta_title={""} - type={undefined} /> ); @@ -50,11 +48,9 @@ describe("", () => { intro={""} relatedItems={[]} metaDescription={""} - filesize={undefined} + filesize={10} filename={""} html={undefined} - meta_title={""} - type={undefined} /> ); fireEvent.keyDown(container, { key: "c" }); diff --git a/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/__tests__/queries.es.test.ts b/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/__tests__/queries.es.test.ts index b7a563c40f..d334a63518 100644 --- a/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/__tests__/queries.es.test.ts +++ b/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/__tests__/queries.es.test.ts @@ -1,6 +1,6 @@ /** @jest-environment node */ -import { fetchAllModels } from "../queries"; +import { fetchAllModels, fetchModel } from "../queries"; describe("Modèles de courrier", () => { it("Récupération de tous les modèles de courrier", async () => { @@ -20,4 +20,49 @@ describe("Modèles de courrier", () => { }, ]); }); + + it("Récupération d'un modèle de courrier avec son slug", async () => { + const result = await fetchModel({ + slug: "demande-de-rendez-vous-en-vue-dune-rupture-conventionnelle", + }); + expect(result).toEqual({ + "_id": "15", + "author": "Ministère du Travail", + "breadcrumbs": [ + { + "label": "Départ de l’entreprise", + "position": 8, + "slug": "/themes/depart-de-lentreprise" + }, + { + "label": "Rupture conventionnelle", + "position": 3, + "slug": "/themes/rupture-conventionnelle" + }, + { + "label": "Rupture conventionnelle individuelle", + "position": 1, + "slug": "/themes/rupture-conventionnelle-individuelle" + } + ], + "date": "16/12/2019", + "description": "La rupture conventionnelle individuelle est une modalité de rupture spécifique du CDI. Elle nécessite le consentement de l’employeur et du salarié, et son homologation par l’administration. La rupture ouvre droit à une indemnité de rupture conventionnelle. Ce modèle permet d’initier la procédure de rupture par l’invitation à un premier entretien.", + "filename": "demande_rdv_rupture_conventionnelle.docx", + "filesize": 14535, + "html": "

« Prénom Nom du salarié »

« Adresse »

« Code postal + Ville »

« Tél : 00.00.00.00.00 »

« E-mail : …………@... »

« Société »

« Prénom Nom du représentant »

« Fonction (DRH, etc.) »

« Adresse »

« Code postal + Ville »

A « lieu », le « date »

Objet : Demande de rendez-vous en vue d’une éventuelle rupture conventionnelle

« Madame / Monsieur »,

Je sollicite un entretien afin de vous proposer que nous convenions ensemble, si vous en êtes d’accord, de la rupture de mon contrat de travail dans le cadre légal de la rupture conventionnelle.

A cette occasion, je vous présenterai les raisons de ma démarche et nous pourrons déterminer d’un commun accord les modalités de la rupture de mon contrat de travail.

Seriez-vous disponible pour un rendez-vous ce mois-ci, à la date qui vous convient ?

Vous pouvez me joindre aux coordonnées présentées ci-dessus.

Veuillez agréer, « Madame / Monsieur », l’expression de ma considération distinguée.

« Prénom Nom du salarié »

« Signature »

", + "metaDescription": "La rupture conventionnelle individuelle est une modalité de rupture spécifique du CDI. Elle nécessite le consentement de l’employeur et du salarié, et son homologation par l’administration. La rupture ouvre droit à une indemnité de rupture conventionnelle. Ce modèle permet d’initier la procédure de rupture par l’invitation à un premier entretien.", + "title": "Demande de rendez-vous en vue d’une rupture conventionnelle" + }); + }); + + it("Récupération d'un modèle de courrier retourne undefined s'il n'existe pas", async () => { + const result = await fetchModel({ slug: "wrong" }); + expect(result).toEqual(undefined); + }); + + it("Récupération d'un modèle de courrier avec son id", async () => { + const result = await fetchModel({ _id: "15" }); + expect(result?.title).toEqual("Demande de rendez-vous en vue d’une rupture conventionnelle"); + expect(result?._id).toEqual(15); + }); }); diff --git a/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/components/CopyButton.tsx b/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/components/CopyButton.tsx new file mode 100644 index 0000000000..3269a800f5 --- /dev/null +++ b/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/components/CopyButton.tsx @@ -0,0 +1,54 @@ +import { fr } from "@codegouvfr/react-dsfr"; +import { Button } from "@codegouvfr/react-dsfr/Button"; +import { useState } from "react"; +import { css } from "../../../../styled-system/css"; + +export const CopyButton = () => { + const [isCopied, setCopied] = useState(false); + + const copyContent = () => { + const elementsByClassName = document?.getElementById("content-to-copy"); + if (elementsByClassName) { + navigator?.clipboard?.writeText(elementsByClassName.innerText); + setCopied(true); + } + }; + + return ( + <> + +
+ {isCopied && ( +
+

+

+
+ )} +
+ + ); +}; + +const w100 = css({ + w: "100%!", + justifyContent: "center", + textAlign: "center", +}); + +const fixHeight = css({ + h: "48px", +}); diff --git a/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/components/DownloadTile.tsx b/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/components/DownloadTile.tsx new file mode 100644 index 0000000000..f79e1f3542 --- /dev/null +++ b/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/components/DownloadTile.tsx @@ -0,0 +1,30 @@ +import { Tile } from "@codegouvfr/react-dsfr/Tile"; +import { toUrl } from "../../../lib"; + +export const DownloadTile = ({ + filename, + filesize, + title, +}: { + filename: string, + filesize: number, + title: string, +}) => { + const filesizeFormated = Math.round((filesize / 1000) * 100) / 100; + const [, extension] = filename.split(/\.([a-z]{2,4})$/); + + return ( + + ); +}; diff --git a/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/components/LetterModelContent.tsx b/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/components/LetterModelContent.tsx new file mode 100644 index 0000000000..58dc026664 --- /dev/null +++ b/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/components/LetterModelContent.tsx @@ -0,0 +1,85 @@ +"use client"; + +import { fr } from "@codegouvfr/react-dsfr"; +import Html from "../../common/Html"; +import { css } from "../../../../styled-system/css"; +import { getDisclaimer } from "../helpers"; +import { Alert } from "@codegouvfr/react-dsfr/Alert"; +import { DownloadTile } from "./DownloadTile"; +import { CopyButton } from "./CopyButton"; + +export interface LetterModelProps { + date: string; + intro: string; + title: string; + filesize: any; + filename: string; + slug: string; + html: any; +} + +export const LetterModelContent = ({ + filename, + filesize, + html, + slug, + title, + intro, + date, +}: LetterModelProps) => { + return ( +
+

{title}

+

Mise à jour le : {date}

+ {intro && ( +
+ {intro} +
+ )} +
+
+ +
+ +
+
+ {html} +
+
+ +
+ + +
+ +
+
+ ); +}; + +const border = css({ + border: `1px solid`, + borderRadius: "8px", + borderColor: "var(--artwork-minor-blue-cumulus)", +}); +const maxWidth = css({ + maxWidth: "720px", + m: "auto" +}); diff --git a/packages/code-du-travail-frontend/src/modeles/helpers.ts b/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/helpers.ts similarity index 100% rename from packages/code-du-travail-frontend/src/modeles/helpers.ts rename to packages/code-du-travail-frontend/src/modules/modeles-de-courriers/helpers.ts diff --git a/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/index.ts b/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/index.ts index b69c251208..3440e1ad4b 100644 --- a/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/index.ts +++ b/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/index.ts @@ -1 +1,4 @@ export * from "./queries"; +export * from "./modeles"; +export * from "./helpers"; + diff --git a/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/modeles.tsx b/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/modeles.tsx new file mode 100644 index 0000000000..fe53987d15 --- /dev/null +++ b/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/modeles.tsx @@ -0,0 +1,93 @@ +"use client"; + +import React, { useCallback, useEffect } from "react"; +import { Breadcrumb } from "@socialgouv/cdtn-types"; +import { MatomoActionEvent, MatomoBaseEvent } from "../../lib"; +import { push as matopush } from "@socialgouv/matomo-next"; +import { Feedback } from "../layout/feedback"; +import { RelatedItems } from "../common/RelatedItems"; +import { Share } from "../common/Share"; +import { fr } from "@codegouvfr/react-dsfr"; +import { DownloadTile } from "./components/DownloadTile"; +import { CopyButton } from "./components/CopyButton"; +import { LetterModelContent } from "./components/LetterModelContent"; + +export interface LetterModelProps { + breadcrumbs: Breadcrumb[]; + date: string; + intro: string; + title: string; + relatedItems: Array; + metaDescription: string; + filesize: number; + filename: string; + html: any; + slug: string; +} + +export const LetterModel = ({ + filename, + filesize, + html, + slug, + relatedItems, + title, + metaDescription, + intro, + date, +}: LetterModelProps) => { + const trackCopy = useCallback(() => { + matopush([ + MatomoBaseEvent.TRACK_EVENT, + MatomoBaseEvent.PAGE_MODELS, + MatomoActionEvent.TYPE_CTRL_C, + slug, + ]); + }, []); + + useEffect(() => { + document.addEventListener("copy", trackCopy); + return () => { + document.removeEventListener("copy", trackCopy); + }; + }, [trackCopy]); + + return ( +
+
+ + +
+ +
+
+
+ +
+ +
+ + +
+
+ ); +}; diff --git a/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/queries.ts b/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/queries.ts index 792be3f62c..2739db4da6 100644 --- a/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/queries.ts +++ b/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/queries.ts @@ -4,6 +4,8 @@ import { } from "@socialgouv/cdtn-types"; import { elasticDocumentsIndex, elasticsearchClient } from "../../api/utils"; import { SOURCES } from "@socialgouv/cdtn-utils"; +import { DocumentElasticResult, fetchDocument } from "../documents"; +import { nonNullable } from "@socialgouv/modeles-social"; export const fetchAllModels = async < K extends keyof DocumentElasticWithSource, @@ -27,7 +29,44 @@ export const fetchAllModels = async < _source: fields, index: elasticDocumentsIndex, }); - return response.hits.hits - .map(({ _source }) => _source) - .filter((source) => source !== undefined); + return response.hits.hits.map(({ _source }) => _source).filter(nonNullable); +}; + +export const fetchModel = async ( + filter: Record +): Promise< + DocumentElasticResult> | undefined +> => { + return await fetchDocument< + DocumentElasticWithSource, + keyof DocumentElasticResult> + >( + [ + "breadcrumbs", + "title", + "meta_title", + "date", + "type", + "html", + "author", + "filename", + "filesize", + "intro", + "description", + "metaDescription", + "references", + ], + { + query: { + bool: { + filter: [ + { term: { source: SOURCES.LETTERS } }, + { term: filter}, + { term: { isPublished: true } }, + ], + }, + }, + size: 1, + } + ); }; diff --git a/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/type.ts b/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/type.ts new file mode 100644 index 0000000000..4332301cf0 --- /dev/null +++ b/packages/code-du-travail-frontend/src/modules/modeles-de-courriers/type.ts @@ -0,0 +1,7 @@ +import { + DocumentElasticWithSource, + MailTemplateDoc, +} from "@socialgouv/cdtn-types"; + +export type ElasticLaborMailTemplateDoc = + DocumentElasticWithSource; diff --git a/packages/code-du-travail-frontend/src/modules/widgets/WidgetWithIframeResizer.tsx b/packages/code-du-travail-frontend/src/modules/widgets/WidgetWithIframeResizer.tsx new file mode 100644 index 0000000000..dcb0a06dc3 --- /dev/null +++ b/packages/code-du-travail-frontend/src/modules/widgets/WidgetWithIframeResizer.tsx @@ -0,0 +1,13 @@ +"use client"; + +import { useIframeResizer } from "../../common/hooks"; + +export function WidgetWithIframeResizer({ + children, +}: { + children: React.ReactNode; +}) { + useIframeResizer(); + + return <>{children}; +} diff --git a/yarn.lock b/yarn.lock index 98fdac1feb..f975feca08 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1874,7 +1874,7 @@ __metadata: version: 0.0.0-use.local resolution: "@cdt/frontend@workspace:packages/code-du-travail-frontend" dependencies: - "@codegouvfr/react-dsfr": ^1.13.4 + "@codegouvfr/react-dsfr": ^1.13.9 "@elastic/elasticsearch": ^8.13.1 "@matejmazur/react-katex": ^3.1.3 "@opentelemetry/instrumentation-generic-pool": ^0.37.0 @@ -1985,9 +1985,9 @@ __metadata: languageName: node linkType: hard -"@codegouvfr/react-dsfr@npm:^1.13.4": - version: 1.13.4 - resolution: "@codegouvfr/react-dsfr@npm:1.13.4" +"@codegouvfr/react-dsfr@npm:^1.13.9": + version: 1.13.9 + resolution: "@codegouvfr/react-dsfr@npm:1.13.9" dependencies: tsafe: ^1.7.2 yargs-parser: ^21.1.1 @@ -2000,7 +2000,7 @@ __metadata: copy-dsfr-to-public: bin/copy-dsfr-to-public.js only-include-used-icons: bin/only-include-used-icons.js react-dsfr: bin/react-dsfr.js - checksum: 59691d2030df4b2273075081e6f9f770427ef4ef697801f04ec952b48045d6fc3107d7340dfabcdcffe059e14ab4e0d5b429b538a6cee32fadef887bc1f5c2c9 + checksum: 32914874809571944dc905a231d4bd968d0ca3ea2f1f49e21dad30e10e500dda884d1cb69ac1526f9af244d42bd8994081f4bcf71c71f37a5eb7b1aabb561a8b languageName: node linkType: hard