From 9e5823abc2a52737329079d9a9e2a06e4af620c2 Mon Sep 17 00:00:00 2001 From: Martial Maillot Date: Wed, 4 Sep 2024 12:02:21 +0200 Subject: [PATCH] feat(dsfr): migration de la page plan du site --- .../app/plan-du-site/page.tsx | 25 ++ .../light/plan-du-site/plan-du-site.spec.ts | 12 + .../code-du-travail-frontend/package.json | 4 +- .../pages/convention-collective/index.tsx | 10 +- .../pages/integration/[slug].tsx | 11 +- .../pages/modeles-de-courriers/index.tsx | 9 +- .../pages/plan-du-site.tsx | 220 -------------- .../pages/themes/index.tsx | 12 +- .../agreements/__tests__/service.test.ts | 5 +- .../src/api/modules/agreements/queries.ts | 11 +- .../src/api/modules/agreements/service.ts | 31 +- .../__snapshots__/service.test.ts.snap | 27 -- .../contributions/__tests__/service.test.ts | 8 - .../src/api/modules/contributions/fetch.ts | 18 +- .../src/api/modules/contributions/queries.ts | 1 - .../src/api/modules/contributions/service.ts | 36 +-- .../src/api/modules/home/service.ts | 10 +- .../src/api/modules/informations/queries.ts | 1 - .../src/api/modules/informations/service.ts | 29 +- .../modules/modeles/__tests__/service.test.ts | 9 +- .../src/api/modules/modeles/queries.ts | 8 - .../src/api/modules/modeles/service.ts | 21 +- .../modules/sitemap/__tests__/service.test.ts | 142 +++------ .../src/api/modules/sitemap/service.ts | 119 ++++++-- .../__snapshots__/service.test.ts.snap | 64 ----- .../modules/themes/__tests__/service.test.ts | 10 +- .../src/api/modules/themes/queries.ts | 4 +- .../src/api/modules/themes/service.ts | 86 ++---- .../__snapshots__/service.test.ts.snap | 3 - .../modules/tools/__tests__/service.test.ts | 2 +- .../src/api/modules/tools/queries.ts | 24 +- .../src/api/modules/tools/service.ts | 17 +- .../src/api/utils/sort.ts | 8 + .../__tests__/PlanDuSite.test.tsx | 38 +++ .../__snapshots__/PlanDuSite.test.tsx.snap | 269 ++++++++++++++++++ .../src/modules/plan-du-site/index.tsx | 126 ++++++++ packages/code-du-travail-modeles/package.json | 2 +- packages/code-du-travail-utils/package.json | 2 +- packages/react-ui/package.json | 2 +- yarn.lock | 34 +-- 40 files changed, 815 insertions(+), 655 deletions(-) create mode 100644 packages/code-du-travail-frontend/app/plan-du-site/page.tsx create mode 100644 packages/code-du-travail-frontend/cypress/integration/light/plan-du-site/plan-du-site.spec.ts delete mode 100644 packages/code-du-travail-frontend/pages/plan-du-site.tsx create mode 100644 packages/code-du-travail-frontend/src/api/utils/sort.ts create mode 100644 packages/code-du-travail-frontend/src/modules/plan-du-site/__tests__/PlanDuSite.test.tsx create mode 100644 packages/code-du-travail-frontend/src/modules/plan-du-site/__tests__/__snapshots__/PlanDuSite.test.tsx.snap create mode 100644 packages/code-du-travail-frontend/src/modules/plan-du-site/index.tsx diff --git a/packages/code-du-travail-frontend/app/plan-du-site/page.tsx b/packages/code-du-travail-frontend/app/plan-du-site/page.tsx new file mode 100644 index 0000000000..db72080e47 --- /dev/null +++ b/packages/code-du-travail-frontend/app/plan-du-site/page.tsx @@ -0,0 +1,25 @@ +import { Metadata } from "next"; +import { DsfrLayout } from "../../src/modules/layout"; +import { getSitemapData } from "../../src/api"; +import { SiteMap } from "../../src/modules/plan-du-site"; + +export const metadata: Metadata = { + title: "Plan du site", + description: "Plan du site du Code du travail numérique", +}; + +const getSiteMap = async () => { + return getSitemapData(); +}; + +async function Index() { + const data = await getSiteMap(); + + return ( + + + + ); +} + +export default Index; diff --git a/packages/code-du-travail-frontend/cypress/integration/light/plan-du-site/plan-du-site.spec.ts b/packages/code-du-travail-frontend/cypress/integration/light/plan-du-site/plan-du-site.spec.ts new file mode 100644 index 0000000000..377592ff92 --- /dev/null +++ b/packages/code-du-travail-frontend/cypress/integration/light/plan-du-site/plan-du-site.spec.ts @@ -0,0 +1,12 @@ +describe("Plan du site", () => { + it("je vois le plan du site", () => { + cy.visit("/"); + cy.get("a").contains("Plan du site").click(); + cy.findByRole("heading", { level: 1 }).should("have.text", "Plan du site"); + cy.contains("a", "Page d'accueil"); + cy.contains("a", "Boîte à outils"); + cy.contains("a", "Vos fiches pratiques"); + cy.contains("a", "Votre convention collective"); + cy.contains("a", "Thèmes"); + }); +}); diff --git a/packages/code-du-travail-frontend/package.json b/packages/code-du-travail-frontend/package.json index 1728555f4f..424aa8e3ec 100644 --- a/packages/code-du-travail-frontend/package.json +++ b/packages/code-du-travail-frontend/package.json @@ -40,7 +40,7 @@ "@sentry/nextjs": "^8.24.0", "@socialgouv/cdtn-elasticsearch": "^2.44.2", "@socialgouv/cdtn-logger": "^2.0.0", - "@socialgouv/cdtn-types": "^2.48.1", + "@socialgouv/cdtn-types": "^2.49.1", "@socialgouv/cdtn-ui": "workspace:^", "@socialgouv/cdtn-utils": "workspace:^", "@socialgouv/fiches-travail-data": "^4.241.0", @@ -116,7 +116,7 @@ "stylelint-processor-styled-components": "^1.10.0", "supertest": "^6.3.3", "testing-library-selector": "0.3.1", - "typescript": "^5.0.4", + "typescript": "^5.5.4", "xml2js": "^0.6.2" } } diff --git a/packages/code-du-travail-frontend/pages/convention-collective/index.tsx b/packages/code-du-travail-frontend/pages/convention-collective/index.tsx index be1b6cd1cb..243d520d41 100644 --- a/packages/code-du-travail-frontend/pages/convention-collective/index.tsx +++ b/packages/code-du-travail-frontend/pages/convention-collective/index.tsx @@ -81,7 +81,15 @@ export default Page; export async function getStaticProps() { try { - let data = await getAllAgreements(); + let data = await getAllAgreements([ + "title", + "shortTitle", + "description", + "url", + "slug", + "source", + "num", + ]); return { props: { ccs: data }, revalidate: REVALIDATE_TIME }; } catch (error) { console.error(error); diff --git a/packages/code-du-travail-frontend/pages/integration/[slug].tsx b/packages/code-du-travail-frontend/pages/integration/[slug].tsx index 1b6d094b22..f8a8638461 100644 --- a/packages/code-du-travail-frontend/pages/integration/[slug].tsx +++ b/packages/code-du-travail-frontend/pages/integration/[slug].tsx @@ -48,12 +48,12 @@ const IntegrationPage = (props): JSX.Element => { const keys = Object.keys(integrationData); const getModelesList = async () => { - const modeles = await getAllModeles(); + const modeles = await getAllModeles(["title", "cdtnId"]); return modeles .map((item) => { return { - label: item?.title ?? "", - value: item?.cdtnId ?? "", + label: item.title, + value: item.cdtnId, }; }) ?.sort((a, b) => a.label.localeCompare(b.label)); @@ -67,10 +67,7 @@ export const getServerSideProps = async ({ query, req }) => { }; } const { isModele } = integrationData[slug]; - let selectOptions; - if (isModele) { - selectOptions = await getModelesList(); - } + const selectOptions = isModele ? await getModelesList() : null; const hostname: string = req.headers.host; const [protocol] = req.headers["x-forwarded-proto"] diff --git a/packages/code-du-travail-frontend/pages/modeles-de-courriers/index.tsx b/packages/code-du-travail-frontend/pages/modeles-de-courriers/index.tsx index bab9c0963a..e91bffe609 100644 --- a/packages/code-du-travail-frontend/pages/modeles-de-courriers/index.tsx +++ b/packages/code-du-travail-frontend/pages/modeles-de-courriers/index.tsx @@ -105,7 +105,14 @@ function Modeles(props) { export async function getStaticProps() { try { - const data = await getAllModeles(); + const data = await getAllModeles([ + "title", + "slug", + "description", + "source", + "breadcrumbs", + "cdtnId", + ]); return { props: { data }, revalidate: REVALIDATE_TIME }; } catch (error) { console.error(error); diff --git a/packages/code-du-travail-frontend/pages/plan-du-site.tsx b/packages/code-du-travail-frontend/pages/plan-du-site.tsx deleted file mode 100644 index 2a90013ef9..0000000000 --- a/packages/code-du-travail-frontend/pages/plan-du-site.tsx +++ /dev/null @@ -1,220 +0,0 @@ -import { - Container, - PageTitle, - Section, - theme, - Wrapper, -} from "@socialgouv/cdtn-ui"; -import * as Sentry from "@sentry/nextjs"; -import React from "react"; -import Metas from "../src/common/Metas"; -import { Layout } from "../src/layout/Layout"; -import styled from "styled-components"; -import Link from "next/link"; -import { getSitemapData, GetSitemapPage } from "../src/api"; -import { getRouteBySource, SOURCES } from "@socialgouv/cdtn-utils"; -import { REVALIDATE_TIME } from "../src/config"; - -const PlanDuSite = ({ - tools, - modeles, - contributions, - agreements, - themes, - informations, -}: GetSitemapPage) => { - return ( - - -
- - Plan du site - - Page d'accueil - - Boîte à outils -
    - {tools.map((tool) => ( - - - {tool.title} - - - ))} -
-
- - Modèles de documents -
    - {modeles.map((modele) => ( - - - {modele?.title} - - - ))} -
-
- - Contenus éditoriaux -
    - {informations.map((information) => ( - - - {information.title} - - - ))} -
-
- - Vos fiches pratiques -
    - {contributions.map((contribution) => ( - - - {contribution.generic.title} - -
      - {contribution.agreements.map((c) => ( - - - {c.title} - - - ))} -
    -
    - ))} -
-
- - - Votre convention collective - -
    - {agreements.map((agreement) => ( - - - {agreement.title} - - - ))} -
-
- - Thèmes -
    - {themes.map((theme) => ( - - - {theme.title} - - {theme.children && theme.children.length > 0 && ( -
      - {theme.children.map((subTheme) => ( - - - {subTheme.label} - - {subTheme.children && - subTheme.children.length > 0 && ( -
        - {subTheme.children.map((item) => ( - - - {item.label} - - - ))} -
      - )} -
      - ))} -
    - )} -
    - ))} -
-
-
-
-
-
- ); -}; - -export async function getStaticProps() { - let data; - try { - data = await getSitemapData(); - } catch (e) { - console.error(e); - Sentry.captureException(e); - } - - return { - props: { - themes: data?.themes ?? [], - tools: data?.tools ?? [], - contributions: data?.contributions ?? [], - modeles: data?.modeles ?? [], - agreements: data?.agreements ?? [], - informations: data?.informations ?? [], - }, - revalidate: REVALIDATE_TIME, - }; -} - -export const StyledSection = styled.div` - margin-top: ${theme.spacings.base}; -`; - -export const StyledLi = styled.li` - font-size: ${theme.fonts.sizes.small}; - - a { - font-weight: 400; - display: block; - padding: 5px 0; - } -`; - -export default PlanDuSite; diff --git a/packages/code-du-travail-frontend/pages/themes/index.tsx b/packages/code-du-travail-frontend/pages/themes/index.tsx index 5b5e52f5f4..6840d64929 100644 --- a/packages/code-du-travail-frontend/pages/themes/index.tsx +++ b/packages/code-du-travail-frontend/pages/themes/index.tsx @@ -15,7 +15,7 @@ import Metas from "../../src/common/Metas"; import { REVALIDATE_TIME } from "../../src/config"; import { Layout } from "../../src/layout/Layout"; import { LinkedTile } from "../../src/common/tiles/LinkedTile"; -import { getAllThemes } from "../../src/api"; +import { getRootThemes } from "../../src/api"; const SubThemes = ({ children = [] }) => { return ( @@ -73,8 +73,14 @@ const ThemesPage = ({ children = [] }) => ( export async function getStaticProps() { try { - const data = await getAllThemes(); - return { props: { children: data.children }, revalidate: REVALIDATE_TIME }; + const data = await getRootThemes([ + "icon", + "children", + "title", + "slug", + "position", + ]); + return { props: { children: data }, revalidate: REVALIDATE_TIME }; } catch (error) { console.error(error); return { diff --git a/packages/code-du-travail-frontend/src/api/modules/agreements/__tests__/service.test.ts b/packages/code-du-travail-frontend/src/api/modules/agreements/__tests__/service.test.ts index 739f85a11a..803da95428 100644 --- a/packages/code-du-travail-frontend/src/api/modules/agreements/__tests__/service.test.ts +++ b/packages/code-du-travail-frontend/src/api/modules/agreements/__tests__/service.test.ts @@ -9,7 +9,10 @@ import { describe("Agreements", () => { it("getAllAgreements", async () => { - const result = await getAllAgreements(); + const result = await getAllAgreements( + ["title", "shortTitle", "description", "url", "slug", "source", "num"], + "shortTitle" + ); expect(result).toMatchSnapshot(); }); it("getBySlugsAgreements", async () => { diff --git a/packages/code-du-travail-frontend/src/api/modules/agreements/queries.ts b/packages/code-du-travail-frontend/src/api/modules/agreements/queries.ts index 126dac7822..aebaceccc4 100644 --- a/packages/code-du-travail-frontend/src/api/modules/agreements/queries.ts +++ b/packages/code-du-travail-frontend/src/api/modules/agreements/queries.ts @@ -1,16 +1,7 @@ import { SOURCES } from "@socialgouv/cdtn-utils"; -export const getAllAgreementsWithContributions = () => { +export const getAllAgreementsQuery = () => { return { - _source: [ - "title", - "shortTitle", - "description", - "url", - "slug", - "source", - "num", - ], query: { bool: { filter: [ diff --git a/packages/code-du-travail-frontend/src/api/modules/agreements/service.ts b/packages/code-du-travail-frontend/src/api/modules/agreements/service.ts index 1f2241bb0b..ac623df46f 100644 --- a/packages/code-du-travail-frontend/src/api/modules/agreements/service.ts +++ b/packages/code-du-travail-frontend/src/api/modules/agreements/service.ts @@ -3,24 +3,31 @@ import { getAgreementBySlug, getAgreementsByIds, getAgreementsBySlugs, - getAllAgreementsWithContributions, + getAllAgreementsQuery, } from "./queries"; import { ElasticSearchItem } from "../../types"; import { AgreementDoc, ElasticAgreement } from "@socialgouv/cdtn-types"; -import { nonNullable } from "@socialgouv/modeles-social"; +import {orderByAlpha} from "../../utils/sort"; -export const getAllAgreements = async (): Promise => { - const body = getAllAgreementsWithContributions(); +export const getAllAgreements = async ( + fields: K[], + sortBy?: K +): Promise[]> => { + const body = getAllAgreementsQuery(); - const response = await elasticsearchClient.search({ - body, + const response = await elasticsearchClient.search>({ + ...body, + _source: fields, index: elasticDocumentsIndex, }); - return response.hits.hits + const data = response.hits.hits .map(({ _source }) => _source) - .filter(nonNullable) - .sort(orderByAlpha); + .filter((item) => item !== undefined); + if (sortBy) { + data.sort((a, b) => orderByAlpha(a, b, sortBy)); + } + return data; }; export const getBySlugsAgreements = async ( @@ -62,9 +69,3 @@ export const getBySlugAgreements = async (slug: string) => { return { ...response.hits.hits[0]._source }; }; - -const orderByAlpha = (a, b) => { - return a.shortTitle.localeCompare(b.shortTitle, "fr", { - ignorePunctuation: true, - }); -}; diff --git a/packages/code-du-travail-frontend/src/api/modules/contributions/__tests__/__snapshots__/service.test.ts.snap b/packages/code-du-travail-frontend/src/api/modules/contributions/__tests__/__snapshots__/service.test.ts.snap index c99ba54fa1..c9334bac05 100644 --- a/packages/code-du-travail-frontend/src/api/modules/contributions/__tests__/__snapshots__/service.test.ts.snap +++ b/packages/code-du-travail-frontend/src/api/modules/contributions/__tests__/__snapshots__/service.test.ts.snap @@ -1,32 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Contributions getAllContributions 1`] = ` -[ - { - "agreements": [], - "generic": { - "idcc": "0000", - "slug": "les-conges-pour-evenements-familiaux", - "title": "Les congés pour événements familiaux", - }, - }, - { - "agreements": [ - { - "idcc": "0044", - "slug": "44-quand-le-salarie-a-t-il-droit-a-une-prime-danciennete-quel-est-son-montant", - "title": "Quand le salarié a-t-il droit à une prime d’ancienneté ? Quel est son montant ?", - }, - ], - "generic": { - "idcc": "0000", - "slug": "quand-le-salarie-a-t-il-droit-a-une-prime-danciennete-quel-est-son-montant", - "title": "Quand le salarié a-t-il droit à une prime d’ancienneté ? Quel est son montant ?", - }, - }, -] -`; - exports[`Contributions getByIdsContributions 1`] = ` [ { diff --git a/packages/code-du-travail-frontend/src/api/modules/contributions/__tests__/service.test.ts b/packages/code-du-travail-frontend/src/api/modules/contributions/__tests__/service.test.ts index 977a17c73c..08e2dd4741 100644 --- a/packages/code-du-travail-frontend/src/api/modules/contributions/__tests__/service.test.ts +++ b/packages/code-du-travail-frontend/src/api/modules/contributions/__tests__/service.test.ts @@ -1,11 +1,9 @@ /** @jest-environment node */ import { - getAllContributionsGroupByQuestion, getByIdsContributions, getGenericContributionsGroupByThemes, } from "../service"; -import { getAllAgreements } from "../../agreements"; describe("Contributions", () => { it("getGenericContributions", async () => { @@ -17,10 +15,4 @@ describe("Contributions", () => { const result = await getByIdsContributions(["eba7a4592f"]); expect(result).toMatchSnapshot(); }); - - it("getAllContributions", async () => { - const agreements = await getAllAgreements(); - const result = await getAllContributionsGroupByQuestion(agreements); - expect(result).toMatchSnapshot(); - }); }); diff --git a/packages/code-du-travail-frontend/src/api/modules/contributions/fetch.ts b/packages/code-du-travail-frontend/src/api/modules/contributions/fetch.ts index 0a06df0c78..b08e90c6d7 100644 --- a/packages/code-du-travail-frontend/src/api/modules/contributions/fetch.ts +++ b/packages/code-du-travail-frontend/src/api/modules/contributions/fetch.ts @@ -1,11 +1,23 @@ +import { ContributionElasticDocument } from "@socialgouv/cdtn-types"; import { elasticDocumentsIndex, elasticsearchClient } from "../../utils"; import { getAllContributions } from "./queries"; -export const fetchAllContributions = async () => { +export const fetchAllContributions = async < + K extends keyof ContributionElasticDocument +>( + fields: K[] +): Promise[]> => { const body = getAllContributions(); - return await elasticsearchClient.search({ - body, + const result = await elasticsearchClient.search< + Pick + >({ + ...body, + _source: fields, index: elasticDocumentsIndex, }); + + return result.hits.hits + .map(({ _source }) => _source) + .filter((source) => source !== undefined); }; diff --git a/packages/code-du-travail-frontend/src/api/modules/contributions/queries.ts b/packages/code-du-travail-frontend/src/api/modules/contributions/queries.ts index 73899674ab..88e2935fe0 100644 --- a/packages/code-du-travail-frontend/src/api/modules/contributions/queries.ts +++ b/packages/code-du-travail-frontend/src/api/modules/contributions/queries.ts @@ -2,7 +2,6 @@ import { SOURCES } from "@socialgouv/cdtn-utils"; export const getAllContributions = () => { return { - _source: ["title", "shortTitle", "slug", "idcc"], query: { bool: { filter: [ diff --git a/packages/code-du-travail-frontend/src/api/modules/contributions/service.ts b/packages/code-du-travail-frontend/src/api/modules/contributions/service.ts index 1793cff09f..045d7aadde 100644 --- a/packages/code-du-travail-frontend/src/api/modules/contributions/service.ts +++ b/packages/code-du-travail-frontend/src/api/modules/contributions/service.ts @@ -4,6 +4,7 @@ import { fetchAllContributions } from "./fetch"; import { ElasticSearchItem } from "../../types"; import { ElasticAgreement } from "@socialgouv/cdtn-types"; + export const getGenericContributionsGroupByThemes = async () => { const body = getAllGenericsContributions(); @@ -20,41 +21,6 @@ export const getGenericContributionsGroupByThemes = async () => { .reduce(groupByThemes, {}); }; -const isGeneric = (contrib) => contrib.idcc === "0000"; - -function getTitle(agreements: ElasticAgreement[], contrib) { - const idcc = contrib.idcc ?? contrib.slug.split("-")[0]; - const agreement = agreements.find((a) => a.num === parseInt(idcc)); - return agreement - ? `${contrib.title} - ${agreement.shortTitle}` - : contrib.title; -} - -export const getAllContributionsGroupByQuestion = async ( - agreements: ElasticAgreement[] -) => { - const response = await fetchAllContributions(); - const all = response.hits.hits.map(({ _source }) => _source); - const allGenerics = all - .filter(isGeneric) - .sort((a, b) => a.title.localeCompare(b.title)); - - return allGenerics.map((generic) => { - return { - generic: generic, - agreements: all - .filter((contrib) => { - return !isGeneric(contrib) && contrib.slug.includes(generic.slug); - }) - .map((contrib) => { - contrib.title = getTitle(agreements, contrib); - return contrib; - }) - .sort((a, b) => a.title.localeCompare(b.title)), - }; - }); -}; - export const getByIdsContributions = async ( ids: string[] ): Promise => { diff --git a/packages/code-du-travail-frontend/src/api/modules/home/service.ts b/packages/code-du-travail-frontend/src/api/modules/home/service.ts index bf0e4495fb..82682f1a8f 100644 --- a/packages/code-du-travail-frontend/src/api/modules/home/service.ts +++ b/packages/code-du-travail-frontend/src/api/modules/home/service.ts @@ -3,7 +3,7 @@ import { getByIdsAgreements } from "../agreements"; import { getByIdsContributions } from "../contributions"; import { getBySlugHighlights } from "../highlights"; import { getByIdsModeles } from "../modeles"; -import { getAllThemes } from "../themes"; +import { getRootThemes } from "../themes"; import { getToolsByIds } from "../tools"; export type GetHomePage = { @@ -16,7 +16,13 @@ export type GetHomePage = { }; export const getHomeData = async (): Promise => { - const themes = await getAllThemes(); + const themes = await getRootThemes([ + "icon", + "children", + "title", + "slug", + "position", + ]); const highlights = await getBySlugHighlights("homepage"); const tools = await getToolsByIds([ "d7ad36850a", // simulateur-embauche diff --git a/packages/code-du-travail-frontend/src/api/modules/informations/queries.ts b/packages/code-du-travail-frontend/src/api/modules/informations/queries.ts index 5de097f745..96cc87b94d 100644 --- a/packages/code-du-travail-frontend/src/api/modules/informations/queries.ts +++ b/packages/code-du-travail-frontend/src/api/modules/informations/queries.ts @@ -2,7 +2,6 @@ import { SOURCES } from "@socialgouv/cdtn-utils"; export const fetchInformations = () => { return { - _source: ["title", "slug"], query: { bool: { filter: [ diff --git a/packages/code-du-travail-frontend/src/api/modules/informations/service.ts b/packages/code-du-travail-frontend/src/api/modules/informations/service.ts index ef5ec5b96a..13a991db6c 100644 --- a/packages/code-du-travail-frontend/src/api/modules/informations/service.ts +++ b/packages/code-du-travail-frontend/src/api/modules/informations/service.ts @@ -1,18 +1,29 @@ +import { EditorialContentElasticDocument } from "@socialgouv/cdtn-types"; import { elasticDocumentsIndex, elasticsearchClient } from "../../utils"; import { fetchInformations } from "./queries"; +import { orderByAlpha } from "../../utils/sort"; -export const getAllInformations = async () => { +export const getAllInformations = async < + K extends keyof EditorialContentElasticDocument +>( + fields: K[], + sortBy?: K +): Promise[]> => { const body = fetchInformations(); - const response = await elasticsearchClient.search({ - body, + const response = await elasticsearchClient.search< + Pick + >({ + ...body, + _source: fields, index: elasticDocumentsIndex, }); - return response.hits.hits + + const data = response.hits.hits .map(({ _source }) => _source) - .sort((infoA, infoB) => { - return infoA.title.localeCompare(infoB.title, "fr", { - ignorePunctuation: true, - }); - }); + .filter((source) => source !== undefined); + if (sortBy) { + return data.sort((a, b) => orderByAlpha(a, b, sortBy)); + } + return data; }; diff --git a/packages/code-du-travail-frontend/src/api/modules/modeles/__tests__/service.test.ts b/packages/code-du-travail-frontend/src/api/modules/modeles/__tests__/service.test.ts index 8d671117fd..efe6867864 100644 --- a/packages/code-du-travail-frontend/src/api/modules/modeles/__tests__/service.test.ts +++ b/packages/code-du-travail-frontend/src/api/modules/modeles/__tests__/service.test.ts @@ -9,7 +9,14 @@ import { describe("Modeles", () => { it("getAllModeles", async () => { - const result = await getAllModeles(); + const result = await getAllModeles([ + "title", + "slug", + "description", + "source", + "breadcrumbs", + "cdtnId", + ]); expect(result).toMatchSnapshot(); }); it("getBySlugsModeles", async () => { diff --git a/packages/code-du-travail-frontend/src/api/modules/modeles/queries.ts b/packages/code-du-travail-frontend/src/api/modules/modeles/queries.ts index 4604b46a2b..27f9ff64f3 100644 --- a/packages/code-du-travail-frontend/src/api/modules/modeles/queries.ts +++ b/packages/code-du-travail-frontend/src/api/modules/modeles/queries.ts @@ -2,14 +2,6 @@ import { SOURCES } from "@socialgouv/cdtn-utils"; export function getModeles() { return { - _source: [ - "title", - "slug", - "description", - "source", - "breadcrumbs", - "cdtnId", - ], query: { bool: { filter: [ diff --git a/packages/code-du-travail-frontend/src/api/modules/modeles/service.ts b/packages/code-du-travail-frontend/src/api/modules/modeles/service.ts index a52c6e7086..35ecab239d 100644 --- a/packages/code-du-travail-frontend/src/api/modules/modeles/service.ts +++ b/packages/code-du-travail-frontend/src/api/modules/modeles/service.ts @@ -1,6 +1,6 @@ import { DocumentElasticWithSource, - MailTemplate, + MailTemplateDoc, } from "@socialgouv/cdtn-types"; import { ElasticSearchItem } from "../../types"; import { @@ -15,17 +15,24 @@ import { getModelesBySlugs, } from "./queries"; -export const getAllModeles = async () => { +export const getAllModeles = async < + K extends keyof DocumentElasticWithSource +>( + fields: K[] +): Promise, K>[]> => { const body = getModeles(); const response = await elasticsearchClient.search< - DocumentElasticWithSource + DocumentElasticWithSource< + Pick, K> + > >({ - body, + ...body, + _source: fields, index: elasticDocumentsIndex, }); - return response.hits.hits.length > 0 - ? response.hits.hits.map(({ _source }) => _source) - : []; + return response.hits.hits + .map(({ _source }) => _source) + .filter((source) => source !== undefined); }; export const getBySlugsModeles = async ( diff --git a/packages/code-du-travail-frontend/src/api/modules/sitemap/__tests__/service.test.ts b/packages/code-du-travail-frontend/src/api/modules/sitemap/__tests__/service.test.ts index 6fa608b989..dd00d2b817 100644 --- a/packages/code-du-travail-frontend/src/api/modules/sitemap/__tests__/service.test.ts +++ b/packages/code-du-travail-frontend/src/api/modules/sitemap/__tests__/service.test.ts @@ -4,73 +4,39 @@ import { getSitemapData } from "../service"; jest.mock("../../contributions/fetch", () => ({ fetchAllContributions: async () => { - return Promise.resolve({ - hits: { - total: 6, - hits: [ - { - _source: { - idcc: "0044", - type: "content", - content: "content1", - title: "title1", - source: "contribution", - slug: "44-slug-content1", - }, - }, - { - _source: { - idcc: "0000", - type: "content", - content: "content1", - title: "title1", - source: "contribution", - slug: "slug-content1", - }, - }, - { - _source: { - idcc: "0016", - type: "content", - content: "content1", - title: "title1", - source: "contribution", - slug: "16-slug-content1", - }, - }, - { - _source: { - idcc: "0000", - type: "content", - content: "content2", - title: "title2", - source: "contribution", - slug: "slug-content2", - }, - }, - { - _source: { - idcc: "0016", - type: "content", - content: "content2", - title: "title2", - source: "contribution", - slug: "16-slug-content2", - }, - }, - { - _source: { - idcc: "0000", - type: "content", - content: "content3", - title: "title3", - source: "contribution", - slug: "slug-content3", - }, - }, - ], + return Promise.resolve([ + { + idcc: "0044", + title: "title1", + slug: "44-slug-content1", }, - }); + { + idcc: "0000", + title: "title1", + slug: "slug-content1", + }, + { + idcc: "0016", + title: "title1", + slug: "16-slug-content1", + }, + { + idcc: "0000", + title: "title2", + slug: "slug-content2", + }, + { + idcc: "0016", + title: "title2", + slug: "16-slug-content2", + }, + + { + idcc: "0000", + title: "title3", + slug: "slug-content3", + }, + ]); }, })); @@ -86,69 +52,45 @@ describe("Sitemap", () => { "informations", ]); expect(result.tools[0]).toEqual({ - _id: "14", - displayTool: true, - slug: "indemnite-licenciement", - title: "Indemnité de licenciement", + root: { + slug: "indemnite-licenciement", + title: "Indemnité de licenciement", + }, }); expect(result.contributions).toEqual([ { - agreements: [ + children: [ { - content: "content1", - idcc: "0044", slug: "44-slug-content1", - source: "contribution", title: "title1", - type: "content", }, { - content: "content1", - idcc: "0016", slug: "16-slug-content1", - source: "contribution", title: "title1", - type: "content", }, ], - generic: { - content: "content1", - idcc: "0000", + root: { slug: "slug-content1", - source: "contribution", title: "title1", - type: "content", }, }, { - agreements: [ + children: [ { - content: "content2", - idcc: "0016", slug: "16-slug-content2", - source: "contribution", title: "title2", - type: "content", }, ], - generic: { - content: "content2", - idcc: "0000", + root: { slug: "slug-content2", - source: "contribution", title: "title2", - type: "content", }, }, { - agreements: [], - generic: { - content: "content3", - idcc: "0000", + children: [], + root: { slug: "slug-content3", - source: "contribution", title: "title3", - type: "content", }, }, ]); diff --git a/packages/code-du-travail-frontend/src/api/modules/sitemap/service.ts b/packages/code-du-travail-frontend/src/api/modules/sitemap/service.ts index 4d76b1df39..30a85738a9 100644 --- a/packages/code-du-travail-frontend/src/api/modules/sitemap/service.ts +++ b/packages/code-du-travail-frontend/src/api/modules/sitemap/service.ts @@ -1,47 +1,116 @@ import { - Tool, - EditorialContent, + ContributionElasticDocument, ElasticAgreement, - MailTemplate, - DocumentElasticWithSource, } from "@socialgouv/cdtn-types"; import { getAllAgreements } from "../agreements"; -import { getAllContributionsGroupByQuestion } from "../contributions"; import { getAllModeles } from "../modeles"; -import { getAllThemesAndSubThemes } from "../themes"; +import { getRootThemes } from "../themes"; import { getAllTools } from "../tools"; import { getAllInformations } from "../informations"; -import { ElasticSearchItem } from "../../types"; +import { fetchAllContributions } from "../contributions/fetch"; +import { orderByAlpha } from "../../utils/sort"; -type Information = Pick; +export type Document = { + root: DocumentInfo; + children?: DocumentInfo[]; +}; +export type DocumentInfo = { + slug: string; + title: string; +}; export type GetSitemapPage = { - themes: any; - tools: Tool[]; - modeles: (DocumentElasticWithSource | undefined)[]; - contributions: { - generic: ElasticSearchItem; - agreements: ElasticSearchItem[]; - }[]; - agreements: ElasticAgreement[]; - informations: Information[]; + themes: Document[]; + tools: Document[]; + modeles: Document[]; + contributions: Document[]; + agreements: Document[]; + informations: Document[]; }; export const getSitemapData = async () => { const themes = await getAllThemesAndSubThemes(); - const tools = await getAllTools(); - const modeles = await getAllModeles(); - const agreements = await getAllAgreements(); - const informations = await getAllInformations(); + const tools = await getAllTools(["slug", "title"]); + const modeles = await getAllModeles(["slug", "title"]); + const agreements = await getAllAgreements( + ["slug", "shortTitle", "num"], + "shortTitle" + ); + const informations = await getAllInformations(["slug", "title"], "title"); const contributions = await getAllContributionsGroupByQuestion(agreements); const response: GetSitemapPage = { themes, - tools, - modeles, + tools: tools.map((root) => ({ + root, + })), + modeles: modeles.map((root) => ({ + root, + })), contributions, - agreements, - informations, + agreements: agreements.map((agg) => ({ + root: { title: agg.shortTitle, slug: agg.slug }, + })), + informations: informations.map((root) => ({ + root, + })), }; return response; }; + +const getAllContributionsGroupByQuestion = async ( + agreements: Pick[] +) => { + const all = await fetchAllContributions(["idcc", "title", "slug"]); + const allGenerics = all + .filter(isGeneric) + .sort((a, b) => orderByAlpha(a, b, "title")); + + return allGenerics.map((generic) => { + return { + root: { + title: generic.title, + slug: generic.slug, + }, + children: all + .filter( + (contrib) => + !isGeneric(contrib) && contrib.slug.includes(generic.slug) + ) + .map((contrib) => ({ + slug: contrib.slug, + title: getTitle(agreements, contrib), + })) + .sort((a, b) => orderByAlpha(a, b, "title")), + }; + }); +}; + +const isGeneric = (contrib: { idcc: string }) => contrib.idcc === "0000"; + +const getTitle = ( + agreements: Pick[], + contrib: Pick +): string => { + const agreement = agreements.find((a) => a.num === parseInt(contrib.idcc)); + return agreement + ? `${contrib.title} - ${agreement.shortTitle}` + : contrib.title; +}; + +export const getAllThemesAndSubThemes = async (): Promise => { + const themes = await getRootThemes(["title", "children", "slug"]); + + return themes.map(({ slug, title, children }) => { + return { + root: { + slug, + title, + }, + children: children.map((child) => ({ + title: child.label, + slug: child.slug, + })), + }; + }); +}; diff --git a/packages/code-du-travail-frontend/src/api/modules/themes/__tests__/__snapshots__/service.test.ts.snap b/packages/code-du-travail-frontend/src/api/modules/themes/__tests__/__snapshots__/service.test.ts.snap index 71cecd7219..0d73fbb55d 100644 --- a/packages/code-du-travail-frontend/src/api/modules/themes/__tests__/__snapshots__/service.test.ts.snap +++ b/packages/code-du-travail-frontend/src/api/modules/themes/__tests__/__snapshots__/service.test.ts.snap @@ -1,65 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Themes getAllThemes 1`] = ` -{ - "children": [ - { - "children": [ - { - "label": "Embauche", - "slug": "embauche", - }, - { - "label": "Contrat de travail", - "slug": "contrat-de-travail", - }, - ], - "icon": "Contract", - "position": 1, - "slug": "embauche-et-contrat-de-travail", - "title": "Embauche et contrat de travail", - }, - { - "children": [ - { - "label": "Documents à remettre au salarié", - "slug": "documents-a-remettre-au-salarie", - }, - { - "label": "Démission", - "slug": "demission", - }, - { - "label": "Fin d’un CDD - CTT", - "slug": "fin-dun-cdd-ctt", - }, - { - "label": "Rupture conventionnelle", - "slug": "rupture-conventionnelle", - }, - { - "label": "Licenciement : droits des salariés et procédures", - "slug": "licenciement-droits-des-salaries-et-procedures", - }, - { - "label": "Retraite", - "slug": "retraite", - }, - { - "label": "Autres départs", - "slug": "autres-departs", - }, - ], - "icon": "Depart", - "position": 8, - "slug": "depart-de-lentreprise", - "title": "Départ de l’entreprise", - }, - ], -} -`; - -exports[`Themes getAllThemesAndSubThemes 1`] = ` [ { "children": [ @@ -72,8 +13,6 @@ exports[`Themes getAllThemesAndSubThemes 1`] = ` "slug": "contrat-de-travail", }, ], - "icon": "Contract", - "position": 1, "slug": "embauche-et-contrat-de-travail", "title": "Embauche et contrat de travail", }, @@ -86,7 +25,6 @@ exports[`Themes getAllThemesAndSubThemes 1`] = ` { "label": "Démission", "slug": "demission", - "title": "Démission", }, { "label": "Fin d’un CDD - CTT", @@ -109,8 +47,6 @@ exports[`Themes getAllThemesAndSubThemes 1`] = ` "slug": "autres-departs", }, ], - "icon": "Depart", - "position": 8, "slug": "depart-de-lentreprise", "title": "Départ de l’entreprise", }, diff --git a/packages/code-du-travail-frontend/src/api/modules/themes/__tests__/service.test.ts b/packages/code-du-travail-frontend/src/api/modules/themes/__tests__/service.test.ts index 678a1fd4f6..94a8711e13 100644 --- a/packages/code-du-travail-frontend/src/api/modules/themes/__tests__/service.test.ts +++ b/packages/code-du-travail-frontend/src/api/modules/themes/__tests__/service.test.ts @@ -1,19 +1,13 @@ /** @jest-environment node */ import { - getAllThemes, - getAllThemesAndSubThemes, + getRootThemes, getBySlugThemes, } from "../service"; describe("Themes", () => { it("getAllThemes", async () => { - const result = await getAllThemes(); - expect(result).toMatchSnapshot(); - }); - - it("getAllThemesAndSubThemes", async () => { - const result = await getAllThemesAndSubThemes(); + const result = await getRootThemes(["title", "slug", "children"]); expect(result).toMatchSnapshot(); }); diff --git a/packages/code-du-travail-frontend/src/api/modules/themes/queries.ts b/packages/code-du-travail-frontend/src/api/modules/themes/queries.ts index f941a24731..ffafbcb786 100644 --- a/packages/code-du-travail-frontend/src/api/modules/themes/queries.ts +++ b/packages/code-du-travail-frontend/src/api/modules/themes/queries.ts @@ -1,8 +1,7 @@ import { SOURCES } from "@socialgouv/cdtn-utils"; -export function getAllThemesQuery() { +export function getRootThemesQuery() { return { - _source: ["icon", "children", "title", "slug", "position"], query: { bool: { filter: [ @@ -42,7 +41,6 @@ export function getThemeBySlugQuery(slug: string) { export function getThemeBySlugsQuery(slugs: string[]) { return { - _source: ["title", "slug"], query: { bool: { filter: [ diff --git a/packages/code-du-travail-frontend/src/api/modules/themes/service.ts b/packages/code-du-travail-frontend/src/api/modules/themes/service.ts index 97cd155dc5..e418cf4f0f 100644 --- a/packages/code-du-travail-frontend/src/api/modules/themes/service.ts +++ b/packages/code-du-travail-frontend/src/api/modules/themes/service.ts @@ -1,53 +1,25 @@ +import { elasticDocumentsIndex, elasticsearchClient } from "../../utils"; import { - elasticsearchClient, - elasticDocumentsIndex, - NotFoundError, -} from "../../utils"; -import { - getAllThemesQuery, + getRootThemesQuery, getThemeBySlugQuery, getThemeBySlugsQuery, } from "./queries"; - -export const getAllThemes = async () => { - const body: any = getAllThemesQuery(); - const response = await elasticsearchClient.search({ - body, - index: elasticDocumentsIndex, - }); - return { - children: response.hits.hits.map((t) => t._source), - }; -}; - -export const getAllThemesAndSubThemes = async () => { - const body: any = getAllThemesQuery(); - const response = await elasticsearchClient.search({ - body, +import { ThemeElasticDocument } from "@socialgouv/cdtn-types/build/elastic/theme"; + +export const getRootThemes = async ( + fields: K[] +): Promise[]> => { + const body = getRootThemesQuery(); + const response = await elasticsearchClient.search< + Pick + >({ + ...body, + _source: fields, index: elasticDocumentsIndex, }); - const themes = response.hits.hits.map((t) => t._source); - // for each theme of themes, we need to get slug of children - const childrenSlugs = themes.flatMap((theme) => - theme.children.map((child) => child.slug) - ); - const data = await getBySlugsThemes(childrenSlugs).catch(() => { - return []; - }); - const themesWithChildren = themes.map((theme) => { - const children = theme.children.map((child) => { - const childWithContent = data.find((d: any) => d.slug === child.slug); - return { - ...child, - ...childWithContent, - }; - }); - return { - ...theme, - children, - }; - }); - return themesWithChildren; + return response.hits.hits + .map((t) => t._source) + .filter((item) => item !== undefined); }; export const getBySlugThemes = async (slug: string) => { @@ -69,23 +41,21 @@ export const getBySlugThemes = async (slug: string) => { }; }; -export const getBySlugsThemes = async (slugs: string[]) => { +export const getBySlugsThemes = async ( + slugs: string[], + fields: K[] +): Promise[]> => { const body: any = getThemeBySlugsQuery(slugs); - const response = await elasticsearchClient.search({ - body, + const response = await elasticsearchClient.search< + Pick + >({ + ...body, + _source: fields, index: elasticDocumentsIndex, }); - if (response.hits.hits.length === 0) { - throw new NotFoundError({ - message: `There is no theme that match ${slugs.join(",")}`, - name: "THEME_NOT_FOUND", - cause: null, - }); - } - - const themes = response.hits.hits.map(({ _source }) => _source); - - return themes; + return response.hits.hits + .map(({ _source }) => _source) + .filter((item) => item !== undefined); }; diff --git a/packages/code-du-travail-frontend/src/api/modules/tools/__tests__/__snapshots__/service.test.ts.snap b/packages/code-du-travail-frontend/src/api/modules/tools/__tests__/__snapshots__/service.test.ts.snap index 8cdb3ec6df..b7fa3a40ce 100644 --- a/packages/code-du-travail-frontend/src/api/modules/tools/__tests__/__snapshots__/service.test.ts.snap +++ b/packages/code-du-travail-frontend/src/api/modules/tools/__tests__/__snapshots__/service.test.ts.snap @@ -3,19 +3,16 @@ exports[`Tools getAllTools 1`] = ` [ { - "_id": "14", "displayTool": true, "slug": "indemnite-licenciement", "title": "Indemnité de licenciement", }, { - "_id": "13", "displayTool": true, "slug": "preavis-demission", "title": "Préavis de démission", }, { - "_id": "27", "displayTool": true, "slug": "heures-recherche-emploi", "title": "Heures d'absence pour rechercher un emploi", diff --git a/packages/code-du-travail-frontend/src/api/modules/tools/__tests__/service.test.ts b/packages/code-du-travail-frontend/src/api/modules/tools/__tests__/service.test.ts index b194e95a40..e66508c327 100644 --- a/packages/code-du-travail-frontend/src/api/modules/tools/__tests__/service.test.ts +++ b/packages/code-du-travail-frontend/src/api/modules/tools/__tests__/service.test.ts @@ -10,7 +10,7 @@ import { describe("Tools", () => { it("getAllTools", async () => { - const result = await getAllTools(); + const result = await getAllTools(["slug", "title", "displayTool"]); expect(result).toMatchSnapshot(); }); it("getToolsBySlugs", async () => { diff --git a/packages/code-du-travail-frontend/src/api/modules/tools/queries.ts b/packages/code-du-travail-frontend/src/api/modules/tools/queries.ts index 7de885a42f..bd7ba6a377 100644 --- a/packages/code-du-travail-frontend/src/api/modules/tools/queries.ts +++ b/packages/code-du-travail-frontend/src/api/modules/tools/queries.ts @@ -1,18 +1,34 @@ +import { Tool } from "@socialgouv/cdtn-types"; + export const getAllToolsQuery = () => { return { - _source: ["slug", "title", "displayTool"], query: { bool: { must: [ - { term: { isPublished: true } }, - { term: { source: "outils" } }, + { + term: { + isPublished: true, + }, + }, + { + term: { + source: "outils", + }, + }, + { + term: { + displayTool: true, + }, + }, ], }, }, size: 50, sort: [ { - order: "asc", + order: { + order: "asc", + }, }, ], }; diff --git a/packages/code-du-travail-frontend/src/api/modules/tools/service.ts b/packages/code-du-travail-frontend/src/api/modules/tools/service.ts index 7e425ffa6c..70976da8a8 100644 --- a/packages/code-du-travail-frontend/src/api/modules/tools/service.ts +++ b/packages/code-du-travail-frontend/src/api/modules/tools/service.ts @@ -1,16 +1,19 @@ import { Tool } from "@socialgouv/cdtn-types"; import { - elasticsearchClient, elasticDocumentsIndex, + elasticsearchClient, NotFoundError, } from "../../utils"; -import { getTools, getAllToolsQuery } from "./queries"; +import { getAllToolsQuery, getTools } from "./queries"; import { SearchHit } from "@elastic/elasticsearch/lib/api/types"; -export const getAllTools = async (): Promise => { +export const getAllTools = async ( + fields: K[] +): Promise[]> => { const body: any = getAllToolsQuery(); - const response = await elasticsearchClient.search({ - body, + const response = await elasticsearchClient.search>({ + ...body, + _source: fields, index: elasticDocumentsIndex, }); if (response.hits.hits.length === 0) { @@ -21,8 +24,8 @@ export const getAllTools = async (): Promise => { }); } return response.hits.hits - .map(({ _id, _source }) => ({ ..._source, _id })) - .filter((tool) => tool.displayTool); + .map(({ _source }) => _source) + .filter((source) => source !== undefined); }; export const getToolsByIdsAndSlugs = async ( diff --git a/packages/code-du-travail-frontend/src/api/utils/sort.ts b/packages/code-du-travail-frontend/src/api/utils/sort.ts new file mode 100644 index 0000000000..565f81da5a --- /dev/null +++ b/packages/code-du-travail-frontend/src/api/utils/sort.ts @@ -0,0 +1,8 @@ +export const orderByAlpha = (a: T, b: T, field: keyof T): number => { + const valueA = String(a[field]); + const valueB = String(b[field]); + + return valueA.localeCompare(valueB, "fr", { + ignorePunctuation: true, + }); +}; diff --git a/packages/code-du-travail-frontend/src/modules/plan-du-site/__tests__/PlanDuSite.test.tsx b/packages/code-du-travail-frontend/src/modules/plan-du-site/__tests__/PlanDuSite.test.tsx new file mode 100644 index 0000000000..b3079d05ae --- /dev/null +++ b/packages/code-du-travail-frontend/src/modules/plan-du-site/__tests__/PlanDuSite.test.tsx @@ -0,0 +1,38 @@ +import { render } from "@testing-library/react"; +import React from "react"; +import { SiteMap } from ".."; +import type { Document } from "../../../api"; + +describe("", () => { + it("should match snapshot", () => { + const sampleData: Document[] = [ + { + root: { + slug: "slug-test", + title: "Test title", + }, + children: [ + { + title: "Content 1", + slug: "content-1", + }, + { + title: "Content 2", + slug: "content-2", + }, + ], + }, + ]; + const { container } = render( + + ); + expect(container).toMatchSnapshot(); + }); +}); diff --git a/packages/code-du-travail-frontend/src/modules/plan-du-site/__tests__/__snapshots__/PlanDuSite.test.tsx.snap b/packages/code-du-travail-frontend/src/modules/plan-du-site/__tests__/__snapshots__/PlanDuSite.test.tsx.snap new file mode 100644 index 0000000000..b6717a98f0 --- /dev/null +++ b/packages/code-du-travail-frontend/src/modules/plan-du-site/__tests__/__snapshots__/PlanDuSite.test.tsx.snap @@ -0,0 +1,269 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` should match snapshot 1`] = ` + +`; diff --git a/packages/code-du-travail-frontend/src/modules/plan-du-site/index.tsx b/packages/code-du-travail-frontend/src/modules/plan-du-site/index.tsx new file mode 100644 index 0000000000..370dedd867 --- /dev/null +++ b/packages/code-du-travail-frontend/src/modules/plan-du-site/index.tsx @@ -0,0 +1,126 @@ +import { fr } from "@codegouvfr/react-dsfr"; +import { Document } from "../../api"; +import React from "react"; +import Link from "next/link"; +import { getRouteBySource, SourceKeys, SOURCES } from "@socialgouv/cdtn-utils"; +import { Container } from "../layout/Container"; + +type Props = { + themes: Document[]; + tools: Document[]; + modeles: Document[]; + contributions: Document[]; + agreements: Document[]; + informations: Document[]; +}; + +type SectionProps = { + title: string; + url?: string; + detail?: { + source: SourceKeys; + docs: Document[]; + }; +}; + +const SiteMapSection = ({ title, url, detail }: SectionProps) => ( +
+ {url ? ( + + {title} + + ) : ( + + {title} + + )} + + {detail && ( +
    + {detail.docs.map(({ root, children }) => ( +
  • + + {root.title} + + {children && ( +
      + {children.map((doc) => ( +
    • + + {doc.title} + +
    • + ))} +
    + )} +
  • + ))} +
+ )} +
+); + +export const SiteMap = ({ + tools, + modeles, + contributions, + agreements, + informations, + themes, +}: Props) => ( + +

+ Plan du site +

+ + + + + + + +
+); diff --git a/packages/code-du-travail-modeles/package.json b/packages/code-du-travail-modeles/package.json index 71693c0842..145b4f803a 100644 --- a/packages/code-du-travail-modeles/package.json +++ b/packages/code-du-travail-modeles/package.json @@ -28,7 +28,7 @@ "jest": "^29.7.0", "lint-staged": "^13.0.0", "nodemon": "^2.0.12", - "typescript": "^5.0.4", + "typescript": "^5.5.4", "typescript-eslint": "^8.0.0" }, "scripts": { diff --git a/packages/code-du-travail-utils/package.json b/packages/code-du-travail-utils/package.json index ce5a4e4657..c15fe0c79c 100644 --- a/packages/code-du-travail-utils/package.json +++ b/packages/code-du-travail-utils/package.json @@ -21,6 +21,6 @@ "@swc/core": "^1.3.36", "@swc/jest": "^0.2.36", "jest": "^29.7.0", - "typescript": "^5.0.4" + "typescript": "^5.5.4" } } diff --git a/packages/react-ui/package.json b/packages/react-ui/package.json index 92d1be2dfd..2a9a25323b 100644 --- a/packages/react-ui/package.json +++ b/packages/react-ui/package.json @@ -71,7 +71,7 @@ "stylelint-order": "^5.0.0", "stylelint-processor-styled-components": "^1.10.0", "svgo": "^2.3.1", - "typescript": "^5.0.4", + "typescript": "^5.5.4", "vite": "^4.3.9" }, "license": "MIT", diff --git a/yarn.lock b/yarn.lock index 3e2c049083..7e00b1eadf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1884,7 +1884,7 @@ __metadata: "@sentry/nextjs": ^8.24.0 "@socialgouv/cdtn-elasticsearch": ^2.44.2 "@socialgouv/cdtn-logger": ^2.0.0 - "@socialgouv/cdtn-types": ^2.48.1 + "@socialgouv/cdtn-types": ^2.49.1 "@socialgouv/cdtn-ui": "workspace:^" "@socialgouv/cdtn-utils": "workspace:^" "@socialgouv/fiches-travail-data": ^4.241.0 @@ -1954,7 +1954,7 @@ __metadata: stylelint-processor-styled-components: ^1.10.0 supertest: ^6.3.3 testing-library-selector: 0.3.1 - typescript: ^5.0.4 + typescript: ^5.5.4 uuid: ^9.0.0 xml2js: ^0.6.2 xss: ^1.0.10 @@ -6010,10 +6010,10 @@ __metadata: languageName: node linkType: hard -"@socialgouv/cdtn-types@npm:^2.48.1": - version: 2.48.1 - resolution: "@socialgouv/cdtn-types@npm:2.48.1" - checksum: 253c83ec90eeef3b2410440510d0ffac9011b2fe8c9707c37fe17c5c52a76bee3ffad31b1f3bd610e4958bc4c9a5ca75264a50a566b9475432c319de3c3da3fe +"@socialgouv/cdtn-types@npm:^2.49.1": + version: 2.49.1 + resolution: "@socialgouv/cdtn-types@npm:2.49.1" + checksum: 50e1ddebe988c24eedafc11ef75b3c29b8c6e047b0ac43d030bea8abb9e14f7651cc4bea18bc75490d93697d184d6353cb7abcd33efc34b7a0ebe58eaee5e987 languageName: node linkType: hard @@ -6061,7 +6061,7 @@ __metadata: stylelint-order: ^5.0.0 stylelint-processor-styled-components: ^1.10.0 svgo: ^2.3.1 - typescript: ^5.0.4 + typescript: ^5.5.4 use-onclickoutside: ^0.4.0 vite: ^4.3.9 languageName: unknown @@ -6074,7 +6074,7 @@ __metadata: "@swc/core": ^1.3.36 "@swc/jest": ^0.2.36 jest: ^29.7.0 - typescript: ^5.0.4 + typescript: ^5.5.4 languageName: unknown linkType: soft @@ -6140,7 +6140,7 @@ __metadata: lint-staged: ^13.0.0 nodemon: ^2.0.12 publicodes: 1.0.0-beta.60 - typescript: ^5.0.4 + typescript: ^5.5.4 typescript-eslint: ^8.0.0 yaml: ^2.0.0 languageName: unknown @@ -25128,13 +25128,13 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^5.0.4": - version: 5.1.3 - resolution: "typescript@npm:5.1.3" +"typescript@npm:^5.5.4": + version: 5.5.4 + resolution: "typescript@npm:5.5.4" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: d9d51862d98efa46534f2800a1071a613751b1585dc78884807d0c179bcd93d6e9d4012a508e276742f5f33c480adefc52ffcafaf9e0e00ab641a14cde9a31c7 + checksum: b309040f3a1cd91c68a5a58af6b9fdd4e849b8c42d837b2c2e73f9a4f96a98c4f1ed398a9aab576ee0a4748f5690cf594e6b99dbe61de7839da748c41e6d6ca8 languageName: node linkType: hard @@ -25158,13 +25158,13 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@^5.0.4#~builtin": - version: 5.1.3 - resolution: "typescript@patch:typescript@npm%3A5.1.3#~builtin::version=5.1.3&hash=5da071" +"typescript@patch:typescript@^5.5.4#~builtin": + version: 5.5.4 + resolution: "typescript@patch:typescript@npm%3A5.5.4#~builtin::version=5.5.4&hash=b45daf" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 6f0a9dca6bf4ce9dcaf4e282aade55ef4c56ecb5fb98d0a4a5c0113398815aea66d871b5611e83353e5953a19ed9ef103cf5a76ac0f276d550d1e7cd5344f61e + checksum: fc52962f31a5bcb716d4213bef516885e4f01f30cea797a831205fc9ef12b405a40561c40eae3127ab85ba1548e7df49df2bcdee6b84a94bfbe3a0d7eff16b14 languageName: node linkType: hard