From 8ee2b9c53e2dec2bbe913af2755f939914766715 Mon Sep 17 00:00:00 2001 From: victor Date: Mon, 10 Jun 2024 12:18:44 +0200 Subject: [PATCH] refactor: review --- .../src/ingester/cdtnDocuments.ts | 18 ++++-- .../fetchContributionDocumentsToPublish.ts | 61 +++++++++++-------- .../documents/updateExportStatuses.ts | 33 ++++++---- .../src/ingester/ingest.ts | 12 ++-- .../src/workers/ingester-prod.ts | 3 +- .../contributions/answers/Answer.tsx | 15 ++--- .../contributions/answers/Comment.tsx | 5 +- .../questionList/QuestionList.tsx | 10 +-- .../questions/EditQuestionAnswerList.tsx | 22 ++----- .../contributions/status/Status.tsx | 16 +---- .../status/StatusPublication.tsx | 53 ++++++++++++++++ .../components/contributions/status/data.tsx | 18 ++++-- .../src/components/contributions/type.ts | 9 +-- 13 files changed, 169 insertions(+), 106 deletions(-) create mode 100644 targets/frontend/src/components/contributions/status/StatusPublication.tsx diff --git a/targets/export-elasticsearch/src/ingester/cdtnDocuments.ts b/targets/export-elasticsearch/src/ingester/cdtnDocuments.ts index 684ec694b..eb94c9ded 100644 --- a/targets/export-elasticsearch/src/ingester/cdtnDocuments.ts +++ b/targets/export-elasticsearch/src/ingester/cdtnDocuments.ts @@ -20,7 +20,10 @@ import { import { splitArticle } from "./fichesTravailSplitter"; import { createGlossaryTransform } from "./glossary"; import { getVersions } from "./versions"; -import { generateContributions } from "./contributions"; +import { + fetchContributionDocumentToPublish, + generateContributions, +} from "./contributions"; import { generateAgreements } from "./agreements"; import { getGlossary } from "./common/fetchGlossary"; import { fetchThemes } from "./themes/fetchThemes"; @@ -56,7 +59,8 @@ export async function getDuplicateSlugs(allDocuments: any) { } export async function cdtnDocumentsGen( - updateDocs: (source: string, documents: unknown[]) => Promise + updateDocs: (source: string, documents: unknown[]) => Promise, + isProd: boolean ) { let documentsCount: Partial = {}; @@ -190,12 +194,16 @@ export async function cdtnDocumentsGen( }; }), })); - logger.info(`Mapped ${fichesMTWithGlossary.length} fiches travail with glossary`); + logger.info( + `Mapped ${fichesMTWithGlossary.length} fiches travail with glossary` + ); documentsCount = { ...documentsCount, [SOURCES.SHEET_MT_PAGE]: fichesMTWithGlossary.length, }; + const contributionsToPublish = await fetchContributionDocumentToPublish(); + await updateDocs(SOURCES.SHEET_MT_PAGE, fichesMTWithGlossary); logger.info("=== Fiche MT ==="); @@ -332,7 +340,9 @@ export async function cdtnDocumentsGen( }, ]); - await updateExportStatuses(); + if (isProd && contributionsToPublish) { + await updateExportStatuses(contributionsToPublish); + } logger.info("=== Save the documents length ==="); documentsCount = { diff --git a/targets/export-elasticsearch/src/ingester/contributions/fetchContributionDocumentsToPublish.ts b/targets/export-elasticsearch/src/ingester/contributions/fetchContributionDocumentsToPublish.ts index aa19937bc..a94f9f1f6 100644 --- a/targets/export-elasticsearch/src/ingester/contributions/fetchContributionDocumentsToPublish.ts +++ b/targets/export-elasticsearch/src/ingester/contributions/fetchContributionDocumentsToPublish.ts @@ -1,11 +1,14 @@ -import { ContributionDocumentJson, DocumentElasticWithSource } from "@socialgouv/cdtn-types"; +import { + ContributionDocumentJson, + DocumentElasticWithSource, +} from "@socialgouv/cdtn-types"; import { context } from "../context"; import { gqlClient } from "@shared/utils"; export const fetchContributionDocumentsQuery = ` query fetchContributions { documents(where: {source: {_eq: "contributions"}}) { - cdtn_id + cdtnId: cdtn_id export { createdAt: created_at } @@ -22,30 +25,40 @@ query fetchContributions { `; interface HasuraReturn { - documents: [DocumentElasticWithSource] | undefined + documents: [DocumentElasticWithSource] | undefined; } -export function filterContributionDocumentsToPublish(contributionDocs: DocumentElasticWithSource[] | undefined): DocumentElasticWithSource[] | undefined { - return contributionDocs?.filter((doc) => { - const exportDate = doc.export?.createdAt ? new Date(doc.export?.createdAt).getTime() : 0; - const statusDate = doc.contribution?.statuses.length ? new Date(doc.contribution?.statuses[0].createdAt).getTime() : 0; - return statusDate > exportDate; - }) +export function filterContributionDocumentsToPublish( + contributionDocs: + | DocumentElasticWithSource[] + | undefined +): DocumentElasticWithSource[] | undefined { + return contributionDocs?.filter((doc) => { + const exportDate = doc.export?.createdAt + ? new Date(doc.export.createdAt).getTime() + : 0; + const statusDate = doc.contribution?.statuses?.length + ? new Date(doc.contribution.statuses[0].createdAt).getTime() + : 0; + return statusDate > exportDate; + }); } -export async function fetchContributionDocumentToPublish(): Promise[] | undefined> { - const HASURA_GRAPHQL_ENDPOINT = - context.get("cdtnAdminEndpoint") || "http://localhost:8080/v1/graphql"; - const HASURA_GRAPHQL_ENDPOINT_SECRET = - context.get("cdtnAdminEndpointSecret") || "admin1"; - const res = await gqlClient({ - graphqlEndpoint: HASURA_GRAPHQL_ENDPOINT, - adminSecret: HASURA_GRAPHQL_ENDPOINT_SECRET, - }) - .query(fetchContributionDocumentsQuery, {}) - .toPromise(); - if (res.error) { - throw res.error; - } - return filterContributionDocumentsToPublish(res.data?.documents); +export async function fetchContributionDocumentToPublish(): Promise< + DocumentElasticWithSource[] | undefined +> { + const HASURA_GRAPHQL_ENDPOINT = + context.get("cdtnAdminEndpoint") || "http://localhost:8080/v1/graphql"; + const HASURA_GRAPHQL_ENDPOINT_SECRET = + context.get("cdtnAdminEndpointSecret") || "admin1"; + const res = await gqlClient({ + graphqlEndpoint: HASURA_GRAPHQL_ENDPOINT, + adminSecret: HASURA_GRAPHQL_ENDPOINT_SECRET, + }) + .query(fetchContributionDocumentsQuery, {}) + .toPromise(); + if (res.error) { + throw res.error; + } + return filterContributionDocumentsToPublish(res.data?.documents); } diff --git a/targets/export-elasticsearch/src/ingester/documents/updateExportStatuses.ts b/targets/export-elasticsearch/src/ingester/documents/updateExportStatuses.ts index acd4b221a..89312c20e 100644 --- a/targets/export-elasticsearch/src/ingester/documents/updateExportStatuses.ts +++ b/targets/export-elasticsearch/src/ingester/documents/updateExportStatuses.ts @@ -1,7 +1,10 @@ -import {fetchContributionDocumentToPublish} from "../contributions"; -import {fetchLastExportStatus} from "./fetchLastExportStatus"; +import { fetchLastExportStatus } from "./fetchLastExportStatus"; import { gqlClient } from "@shared/utils"; import { context } from "../context"; +import { + ContributionDocumentJson, + DocumentElasticWithSource, +} from "@socialgouv/cdtn-types"; export const updateToLastExportStatusMutation = `mutation updateToLastExportStatus($cdtnIds: [String!], $exportId: uuid) { updateDocuments: update_documents( @@ -16,28 +19,32 @@ export const updateToLastExportStatusMutation = `mutation updateToLastExportStat } }`; -export async function updateExportStatuses() { - const HASURA_GRAPHQL_ENDPOINT = context.get("cdtnAdminEndpoint") || "http://localhost:8080/v1/graphql"; - const HASURA_GRAPHQL_ENDPOINT_SECRET = context.get("cdtnAdminEndpointSecret") || "admin1"; +export async function updateExportStatuses( + contributionsToPublish: DocumentElasticWithSource[] +) { + const HASURA_GRAPHQL_ENDPOINT = + context.get("cdtnAdminEndpoint") || "http://localhost:8080/v1/graphql"; + const HASURA_GRAPHQL_ENDPOINT_SECRET = + context.get("cdtnAdminEndpointSecret") || "admin1"; const exportStatus = await fetchLastExportStatus(); - const contributionsToPublish = await fetchContributionDocumentToPublish(); if (!exportStatus?.id) { return; } - const cdtnIds = contributionsToPublish?.map((contribution) => contribution.cdtn_id); - const {id: exportId} = exportStatus; + const cdtnIds = contributionsToPublish.map( + (contribution) => contribution.cdtnId + ); + const { id: exportId } = exportStatus; - if (cdtnIds?.length) { + if (cdtnIds.length) { const res = await gqlClient({ graphqlEndpoint: HASURA_GRAPHQL_ENDPOINT, adminSecret: HASURA_GRAPHQL_ENDPOINT_SECRET, }) - .mutation(updateToLastExportStatusMutation, { cdtnIds, exportId }) - .toPromise(); + .mutation(updateToLastExportStatusMutation, { cdtnIds, exportId }) + .toPromise(); if (res.error) { - throw res.error; + throw res.error; } } } - \ No newline at end of file diff --git a/targets/export-elasticsearch/src/ingester/ingest.ts b/targets/export-elasticsearch/src/ingester/ingest.ts index 401c7e00b..4297b03bf 100644 --- a/targets/export-elasticsearch/src/ingester/ingest.ts +++ b/targets/export-elasticsearch/src/ingester/ingest.ts @@ -17,6 +17,7 @@ import { cdtnDocumentsGen } from "./cdtnDocuments"; import { context } from "./context"; import { addCovisits, buildCovisitMap } from "./monolog"; import { populateSuggestions } from "./suggestion"; +import { Environment } from "@socialgouv/cdtn-types"; async function addVector(data: any) { const NLP_URL = context.get("nlpUrl"); @@ -64,7 +65,8 @@ export async function ingest( suggestIndexName: string | undefined, bufferSize: number | undefined, suggestFile: string | undefined, - disableGlossary: boolean | undefined + disableGlossary: boolean | undefined, + isProd = false ) { context.provide(); process.env.NLP_URL = nlpUrl; //pour setter la variable d'environment du package elasticsearch... @@ -80,7 +82,8 @@ export async function ingest( suggestIndexName, bufferSize, suggestFile, - disableGlossary + disableGlossary, + isProd ); } @@ -96,7 +99,8 @@ async function runIngester( suggestIndexName: string | undefined, bufferSize: number | undefined, suggestFile: string | undefined, - disableGlossary: boolean | undefined + disableGlossary: boolean | undefined, + isProd: boolean ) { const ES_INDEX_PREFIX = esIndexPrefix || "cdtn"; @@ -167,7 +171,7 @@ async function runIngester( size: 800, }); }; - await cdtnDocumentsGen(updateDocs); + await cdtnDocumentsGen(updateDocs, isProd); logger.info(`done in ${(Date.now() - t0) / 1000} s`); diff --git a/targets/export-elasticsearch/src/workers/ingester-prod.ts b/targets/export-elasticsearch/src/workers/ingester-prod.ts index 76159d274..7680e2fb6 100644 --- a/targets/export-elasticsearch/src/workers/ingester-prod.ts +++ b/targets/export-elasticsearch/src/workers/ingester-prod.ts @@ -18,7 +18,8 @@ const ingester = async (): Promise => { undefined, undefined, undefined, - false + false, + true ); resolve("Export elasticsearch completed successfully"); } catch (error: unknown) { diff --git a/targets/frontend/src/components/contributions/answers/Answer.tsx b/targets/frontend/src/components/contributions/answers/Answer.tsx index e2b4a00c9..a8e26de4c 100644 --- a/targets/frontend/src/components/contributions/answers/Answer.tsx +++ b/targets/frontend/src/components/contributions/answers/Answer.tsx @@ -23,6 +23,7 @@ import { fr } from "@codegouvfr/react-dsfr"; import { usePublishContributionMutation } from "./usePublishAnswer"; import { useGenericContributionAnswerQuery } from "./answerGeneric.query"; import { getLastPublicationDate } from "../publication"; +import { StatusPublicationContainer } from "../status/StatusPublication"; export type ContributionsAnswerProps = { id: string; @@ -127,20 +128,14 @@ export const ContributionsAnswer = ({ {answer?.status && ( -
- + + - {answer.publication - ? `dernière publication: ${getLastPublicationDate({ - status: answer.status, - exportStatus: answer.publication?.export, - })}` - : ""} -
+ )} diff --git a/targets/frontend/src/components/contributions/answers/Comment.tsx b/targets/frontend/src/components/contributions/answers/Comment.tsx index fe33ba3f0..d0b0d753a 100644 --- a/targets/frontend/src/components/contributions/answers/Comment.tsx +++ b/targets/frontend/src/components/contributions/answers/Comment.tsx @@ -33,6 +33,7 @@ export const Comment = ({ comment, onDelete }: Props) => { sx={{ border: "1px solid", borderColor: "grey.300", + minWidth: "300px", }} mt={1} mb={1} @@ -81,7 +82,9 @@ export const Comment = ({ comment, onDelete }: Props) => { }} > {" "} - {statusesMapping[comment.status].text === "Publié" ? "À Publier" : statusesMapping[comment.status].text} + {statusesMapping[comment.status].text === "Publié" + ? "À Publier" + : statusesMapping[comment.status].text} ); diff --git a/targets/frontend/src/components/contributions/questionList/QuestionList.tsx b/targets/frontend/src/components/contributions/questionList/QuestionList.tsx index c6961f6d3..de3aa741f 100644 --- a/targets/frontend/src/components/contributions/questionList/QuestionList.tsx +++ b/targets/frontend/src/components/contributions/questionList/QuestionList.tsx @@ -60,15 +60,7 @@ export const QuestionList = (): JSX.Element => { Questions ({rows.length}) - - - {statusesMapping.PUBLISHED.icon} - - + Publiées diff --git a/targets/frontend/src/components/contributions/questions/EditQuestionAnswerList.tsx b/targets/frontend/src/components/contributions/questions/EditQuestionAnswerList.tsx index 3f1814852..6988f5318 100644 --- a/targets/frontend/src/components/contributions/questions/EditQuestionAnswerList.tsx +++ b/targets/frontend/src/components/contributions/questions/EditQuestionAnswerList.tsx @@ -20,6 +20,7 @@ import { StatusContainer } from "../status"; import { useRouter } from "next/router"; import { fr } from "@codegouvfr/react-dsfr"; import { getLastPublicationDate } from "../publication"; +import { StatusPublicationContainer } from "../status/StatusPublication"; type EditQuestionAnswerListProps = { answers: Answer[]; @@ -201,11 +202,7 @@ export const QuestionAnswerList = ({ onClick={() => redirectToAnswer(answer.id)} > {answer.status && ( - + )} redirectToAnswer(answer.id)} > - {publicationDate ? ( - - ) : ( - - )} + ); diff --git a/targets/frontend/src/components/contributions/status/Status.tsx b/targets/frontend/src/components/contributions/status/Status.tsx index 0b4b39a4c..61bf2ea8b 100644 --- a/targets/frontend/src/components/contributions/status/Status.tsx +++ b/targets/frontend/src/components/contributions/status/Status.tsx @@ -1,32 +1,18 @@ -import { format, parseISO } from "date-fns"; import { Box, Stack, Tooltip } from "@mui/material"; import { Status } from "../type"; import { statusesMapping } from "./data"; -import { isPublished } from "../publication"; export const StatusContainer = ({ status, - statusDate, - exportDate, displayText = false, dataTestid, }: { status: Status; - statusDate?: string; - exportDate?: string; displayText?: boolean; dataTestid?: string; }) => { - let tooltipDate = exportDate - ? format(parseISO(exportDate), "dd/MM/yyyy HH:mm:ss") - : ""; - const tooltipTitle = !statusDate ? tooltipDate : statusesMapping[status].text; - if (statusDate && exportDate && status === "PUBLISHED") { - status = isPublished({ statusDate, exportDate }) - ? "PUBLISHED" - : "TO_PUBLISH"; - } + const tooltipTitle = statusesMapping[status].text; return ( { + let tooltipText: string | undefined; + let status: Status | undefined; + if (!exportDate || !statusDate) { + status = "NOT_PUBLISHED"; + tooltipText = statusesMapping[status].text; + } else { + if (isPublished({ statusDate, exportDate })) { + status = "PUBLISHED"; + tooltipText = `${statusesMapping[status].text} le ${format( + parseISO(exportDate), + "dd/MM/yyyy HH:mm:ss" + )}`; + } else { + status = "PUBLISHING"; + tooltipText = statusesMapping[status].text; + } + } + return ( + + + {statusesMapping[status].icon} + {displayText && {tooltipText}} + + + ); +}; diff --git a/targets/frontend/src/components/contributions/status/data.tsx b/targets/frontend/src/components/contributions/status/data.tsx index 6f8e16d08..7857055b7 100644 --- a/targets/frontend/src/components/contributions/status/data.tsx +++ b/targets/frontend/src/components/contributions/status/data.tsx @@ -4,6 +4,9 @@ import DescriptionIcon from "@mui/icons-material/Description"; import EditNoteIcon from "@mui/icons-material/EditNote"; import VisibilityIcon from "@mui/icons-material/Visibility"; import CloudDoneIcon from "@mui/icons-material/CloudDone"; +import CloudUploadIcon from "@mui/icons-material/CloudUpload"; +import CloudOffIcon from "@mui/icons-material/CloudOff"; +import TaskAltIcon from "@mui/icons-material/TaskAlt"; import { fr } from "@codegouvfr/react-dsfr"; export type StatusesMapping = { @@ -44,9 +47,14 @@ export const statusesMapping: StatusesMapping = { text: "Validé", }, TO_PUBLISH: { + color: fr.colors.decisions.text.default.success.default, + icon: , + text: "À Publier", + }, + PUBLISHING: { color: fr.colors.decisions.text.default.warning.default, - icon: , - text: "À publier", + icon: , + text: "En cours de publication", }, PUBLISHED: { color: fr.colors.decisions.text.default.success.default, @@ -54,8 +62,8 @@ export const statusesMapping: StatusesMapping = { text: "Publié", }, NOT_PUBLISHED: { - color: fr.colors.decisions.text.default.success.default, - icon: , - text: "Publié", + color: fr.colors.decisions.text.default.error.default, + icon: , + text: "Non Publié", }, }; diff --git a/targets/frontend/src/components/contributions/type.ts b/targets/frontend/src/components/contributions/type.ts index 11ef70fba..67039a510 100644 --- a/targets/frontend/src/components/contributions/type.ts +++ b/targets/frontend/src/components/contributions/type.ts @@ -23,8 +23,9 @@ export const statusSchema = z.enum([ "VALIDATING", "VALIDATED", "TO_PUBLISH", + "PUBLISHING", "PUBLISHED", - "NOT_PUBLISHED" + "NOT_PUBLISHED", ]); export type Status = z.infer; @@ -165,7 +166,7 @@ export const commentsSchema = z.object({ export type Comments = z.infer; export const exportStatus = z.object({ - createdAt: z.string() + createdAt: z.string(), }); export type ExportStatus = z.infer; @@ -181,8 +182,8 @@ export const answerRelationSchema = answerBaseSchema.extend({ question: questionBaseSchema, answerComments: z.array(commentsSchema), publication: z.object({ - export: exportStatus - }) + export: exportStatus, + }), }); export type Answer = z.infer;