From 916cdbccf8d0dfeaf2037c133314253fd5ac74fe Mon Sep 17 00:00:00 2001 From: Martial Maillot Date: Fri, 15 Dec 2023 11:19:58 +0100 Subject: [PATCH] =?UTF-8?q?feat(contribution):=20un=20message=20block=20pe?= =?UTF-8?q?ut=20=C3=AAtre=20vide=20(#5486)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ContributionMessageBlock.tsx | 3 + .../DisplayContentContribution.tsx | 88 +++++++++++-------- packages/code-du-travail-utils/src/types.ts | 2 +- 3 files changed, 56 insertions(+), 37 deletions(-) diff --git a/packages/code-du-travail-frontend/src/contributions/ContributionMessageBlock.tsx b/packages/code-du-travail-frontend/src/contributions/ContributionMessageBlock.tsx index 5bebbe7441..9ac5d4d0e7 100644 --- a/packages/code-du-travail-frontend/src/contributions/ContributionMessageBlock.tsx +++ b/packages/code-du-travail-frontend/src/contributions/ContributionMessageBlock.tsx @@ -15,6 +15,9 @@ type Props = { }; export const ContributionMessageBlock = ({ message }: Props) => { + if (!message) { + return <>; + } return ( diff --git a/packages/code-du-travail-frontend/src/contributions/DisplayContentContribution.tsx b/packages/code-du-travail-frontend/src/contributions/DisplayContentContribution.tsx index 1a14acb08b..8535c2dca1 100644 --- a/packages/code-du-travail-frontend/src/contributions/DisplayContentContribution.tsx +++ b/packages/code-du-travail-frontend/src/contributions/DisplayContentContribution.tsx @@ -1,8 +1,13 @@ -import { Accordion, Table as UITable, theme } from "@socialgouv/cdtn-ui"; +import { Accordion, Alert, Table as UITable, theme } from "@socialgouv/cdtn-ui"; import styled from "styled-components"; import { FicheServicePublic } from "../fiche-service-public"; -import parse, { domToReact } from "html-react-parser"; +import parse, { + DOMNode, + domToReact, + Element, + HTMLReactParserOptions, +} from "html-react-parser"; import { xssWrapper } from "../lib"; export const ContentSP = ({ raw }) => { @@ -17,9 +22,9 @@ export const ContentSP = ({ raw }) => { ); }; -const mapItem = (titleLevel, domNode, summary) => ({ - body: domToReact(domNode.children, options(titleLevel + 1)), - title: domToReact(summary.children, { +const mapItem = (titleLevel: number, domNode: Element, summary: Element) => ({ + body: domToReact(domNode.children as DOMNode[], options(titleLevel + 1)), + title: domToReact(summary.children as DOMNode[], { transform: (reactNode, domNode) => { // @ts-ignore if (domNode.children) { @@ -32,7 +37,7 @@ const mapItem = (titleLevel, domNode, summary) => ({ trim: true, }), }); -const mapToAccordion = (titleLevel, items) => ( +const mapToAccordion = (titleLevel: number, items) => ( ( /> ); -function getFirstElementChild(domNode) { +function getFirstElementChild(domNode: Element) { let child = domNode.children.shift(); while (child && child.type !== "tag") { child = domNode.children.shift(); @@ -48,7 +53,7 @@ function getFirstElementChild(domNode) { return child; } -function getNextFirstElement(domNode) { +function getNextFirstElement(domNode: Element) { let next = domNode.next; while (next && next.type !== "tag") { next = next.next; @@ -56,55 +61,66 @@ function getNextFirstElement(domNode) { return next; } -const mapTbody = (tbody) => { +const mapTbody = (tbody: Element) => { const tr = getFirstElementChild(tbody); return ( - {domToReact(tr.children, { trim: true })} - {domToReact(tbody.children, { trim: true })} + {tr && ( + {domToReact(tr.children as DOMNode[], { trim: true })} + )} + {domToReact(tbody.children as DOMNode[], { trim: true })} ); }; -function getItem(domNode, titleLevel) { +function getItem(domNode: Element, titleLevel: number) { const summary = getFirstElementChild(domNode); if (summary && summary.name === "summary") { return mapItem(titleLevel, domNode, summary); } } -const options = (titleLevel) => ({ +const options = (titleLevel: number): HTMLReactParserOptions => ({ replace(domNode) { - if (domNode.name === "h3") { - titleLevel = 4; - } - if (domNode.name === "details") { - const items: any[] = []; - const item = getItem(domNode, titleLevel); - if (item) { - items.push(item); + if (domNode instanceof Element) { + if (domNode.name === "h3") { + titleLevel = 4; } - let next = getNextFirstElement(domNode); - while (next && next.name === "details") { - const item = getItem(next, titleLevel); + if (domNode.name === "details") { + const items: any[] = []; + const item = getItem(domNode, titleLevel); if (item) { items.push(item); } - next = getNextFirstElement(next); + let next = getNextFirstElement(domNode); + while (next && next.name === "details") { + const item = getItem(next, titleLevel); + if (item) { + items.push(item); + } + next = getNextFirstElement(next); + } + return items.length ? mapToAccordion(titleLevel, items) : <>; } - return items.length ? mapToAccordion(titleLevel, items) : <>; - } - if (domNode.name === "table") { - const tableContent = getFirstElementChild(domNode); - if (tableContent.name === "tbody") { - return mapTbody(tableContent); - } else { - return domNode; + if (domNode.name === "table") { + const tableContent = getFirstElementChild(domNode); + if (tableContent?.name === "tbody") { + return mapTbody(tableContent); + } else { + return domNode; + } + } + if (domNode.name === "div" && domNode.attribs.class === "alert") { + return ( + + {domToReact(domNode.children as DOMNode[], { trim: true })} + + ); + } + if (domNode.name === "p" && !domNode.children.length) { + return <>; } - } - if (domNode.name === "p" && !domNode.children.length) { - return <>; } }, trim: true, diff --git a/packages/code-du-travail-utils/src/types.ts b/packages/code-du-travail-utils/src/types.ts index 31a3c50c5e..553c4c51b9 100644 --- a/packages/code-du-travail-utils/src/types.ts +++ b/packages/code-du-travail-utils/src/types.ts @@ -195,7 +195,7 @@ type ElasticSearchContributionBase = ElasticSearchItem & { linkedContent: ContributionLinkedContent[]; references: ContributionRef[]; idcc: string; - messageBlock: string; + messageBlock?: string; } & (ElasticSearchContributionFicheSp | ElasticSearchContributionContent); export type ElasticSearchContributionGeneric = ElasticSearchContributionBase & {