From c8676422351fe9fd615394492184b56b72794e66 Mon Sep 17 00:00:00 2001 From: folland87 Date: Tue, 26 Mar 2024 16:40:54 +0100 Subject: [PATCH 01/21] add translations for share component --- client/locales.md | 2 +- client/src/components/share/index.tsx | 267 +++++++++++--------- client/src/components/share/locales/en.json | 10 + client/src/components/share/locales/fr.json | 10 + 4 files changed, 164 insertions(+), 125 deletions(-) create mode 100644 client/src/components/share/locales/en.json diff --git a/client/locales.md b/client/locales.md index a287b058..1124ae9a 100644 --- a/client/locales.md +++ b/client/locales.md @@ -25,4 +25,4 @@ | /components/truncate | OK | FRED | FR,EN,ES,DE | | /components/websites | OK | FRED | FR,EN | | /components/wiki | OK | FRED | FR,EN | -| /components/share | TODO | FRED | FR,EN | +| /components/share | OK | FRED | FR,EN | diff --git a/client/src/components/share/index.tsx b/client/src/components/share/index.tsx index f102995e..ff0a8bc3 100644 --- a/client/src/components/share/index.tsx +++ b/client/src/components/share/index.tsx @@ -1,46 +1,21 @@ -import { Link } from "@dataesr/dsfr-plus"; +import { Link, useDSFRConfig } from "@dataesr/dsfr-plus"; import useConsent from "../../hooks/useConsent"; import useCopyToClipboard from "../../hooks/useCopyToClipboard"; +import { RawIntlProvider, createIntl } from "react-intl"; -const onClickFacebook = (e: { preventDefault: () => void }) => { - e.preventDefault(); - window.open( - "https://www.facebook.com/sharer.php", - "Partager sur Facebook", - "toolbar=no,location=yes,status=no,menubar=no,scrollbars=yes,resizable=yes,width=600,height=450" - ); -}; - -const onClickTwitter = (e: { preventDefault: () => void }) => { - e.preventDefault(); - const currentURL = window.location.href; - const text = "#dataEsr #scanR"; - const twitterShareURL = `https://twitter.com/intent/tweet?url=${encodeURIComponent( - currentURL - )}&text=${encodeURIComponent(text)}`; - - window.open( - twitterShareURL, - "Partager sur Twitter", - "toolbar=no,location=yes,status=no,menubar=no,scrollbars=yes,resizable=yes,width=600,height=420" - ); -}; +const modules = import.meta.glob('./locales/*.json', { eager: true, import: 'default' }) +const messages = Object.keys(modules).reduce((acc, key) => { + const locale = key.match(/\.\/locales\/(.+)\.json$/)?.[1]; + if (locale) { + return { ...acc, [locale]: modules[key] } + } + return acc; +}, {}); -const onClickLinkedin = (e) => { - e.preventDefault(); - const currentURL = encodeURIComponent("www.google.fr"); - const text = "#dataEsr #scanR"; - const linkedinShareURL = `https://www.linkedin.com/sharing/share-offsite/?url=${currentURL}&text=${encodeURIComponent( - text - )}`; - window.open( - linkedinShareURL, - "Partager sur LinkedIn", - "toolbar=no,location=yes,status=no,menubar=no,scrollbars=yes,resizable=yes,width=600,height=420" - ); -}; export default function Share() { + const { locale } = useDSFRConfig(); + const intl = createIntl({ locale, messages: messages[locale] }); const url = window.location.href; const { consent, dialogId } = useConsent(); const { copy } = useCopyToClipboard(); @@ -50,93 +25,137 @@ export default function Share() { url )}`; + const formating = { + authorize: (chunks: any) => ( + + {chunks} + + ), + }; + + const onClickFacebook = (e: { preventDefault: () => void }) => { + e.preventDefault(); + window.open( + "https://www.facebook.com/sharer.php", + intl.formatMessage({ id: "share.facebook" }), + "toolbar=no,location=yes,status=no,menubar=no,scrollbars=yes,resizable=yes,width=600,height=450" + ); + }; + + const onClickTwitter = (e: { preventDefault: () => void }) => { + e.preventDefault(); + const currentURL = window.location.href; + const text = "#dataEsr #scanR"; + const twitterShareURL = `https://twitter.com/intent/tweet?url=${encodeURIComponent( + currentURL + )}&text=${encodeURIComponent(text)}`; + + window.open( + twitterShareURL, + intl.formatMessage({ id: "share.twitter" }), + "toolbar=no,location=yes,status=no,menubar=no,scrollbars=yes,resizable=yes,width=600,height=420" + ); + }; + + const onClickLinkedin = (e) => { + e.preventDefault(); + const currentURL = encodeURIComponent("www.google.fr"); + const text = "#dataEsr #scanR"; + const linkedinShareURL = `https://www.linkedin.com/sharing/share-offsite/?url=${currentURL}&text=${encodeURIComponent( + text + )}`; + window.open( + linkedinShareURL, + intl.formatMessage({ id: "share.linkedin" }), + "toolbar=no,location=yes,status=no,menubar=no,scrollbars=yes,resizable=yes,width=600,height=420" + ); + }; + return ( -
- {(!twitter || !facebook || !linkedin) && ( -

- Veuillez{" "} - - autoriser le dépot de cookies - {" "} - pour partager sur Facebook, Twitter et LinkedIn. -

- )} - -
+ +
+ {(!twitter || !facebook || !linkedin) && ( +

+ {intl.formatMessage({ id: "share.cookies.personalize" }, formating)} +

+ )} + +
+
); } diff --git a/client/src/components/share/locales/en.json b/client/src/components/share/locales/en.json new file mode 100644 index 00000000..32d3ebb2 --- /dev/null +++ b/client/src/components/share/locales/en.json @@ -0,0 +1,10 @@ +{ + "share.facebook": "Share on Facebook", + "share.twitter": "Share on Twitter", + "share.linkedin": "Share on LinkedIn", + "share.email": "Share via email", + "share.copy": "Copy to clipboard", + "share.inactive": "- inactive", + "share.cookies": "Customize cookies", + "share.cookies.personalize": "Please authorize the use of cookies to share on Facebook, Twitter, and LinkedIn." +} \ No newline at end of file diff --git a/client/src/components/share/locales/fr.json b/client/src/components/share/locales/fr.json index e69de29b..49bcb74c 100644 --- a/client/src/components/share/locales/fr.json +++ b/client/src/components/share/locales/fr.json @@ -0,0 +1,10 @@ +{ + "share.facebook": "Partager sur Facebook", + "share.twitter": "Partager sur Twitter", + "share.linkedin": "Partager sur LinkedIn", + "share.email": "Partager par email", + "share.copy": "Copier dans le presse-papier", + "share.inactive": "- désactivé", + "share.cookies": "Personnaliser les cookies", + "share.cookies.personalize": "Veuillez autoriser le dépot de cookies pour partager sur Facebook, Twitter et LinkedIn." +} \ No newline at end of file From 943fe290b3112708e923ae720b55aa13d87aeabe Mon Sep 17 00:00:00 2001 From: folland87 Date: Tue, 26 Mar 2024 16:47:40 +0100 Subject: [PATCH 02/21] add translations for he breadcrumb --- client/src/pages/search/he.tsx | 4 ++-- client/src/pages/search/locales/de.json | 1 + client/src/pages/search/locales/en.json | 1 + client/src/pages/search/locales/es.json | 1 + client/src/pages/search/locales/fr.json | 1 + 5 files changed, 6 insertions(+), 2 deletions(-) diff --git a/client/src/pages/search/he.tsx b/client/src/pages/search/he.tsx index 2e61639e..f07869cf 100644 --- a/client/src/pages/search/he.tsx +++ b/client/src/pages/search/he.tsx @@ -129,10 +129,10 @@ export default function HEPartners() { - + - + {heData?.title} diff --git a/client/src/pages/search/locales/de.json b/client/src/pages/search/locales/de.json index 7e6cdba4..a0f771c3 100644 --- a/client/src/pages/search/locales/de.json +++ b/client/src/pages/search/locales/de.json @@ -1,5 +1,6 @@ { "search.top.breadcrumb.home": "Startseite", + "search.top.breadcrumb.find-partners": "Partner finden", "search.top.breadcrumb.publications": "Suche nach Veröffentlichungen", "search.top.breadcrumb.authors": "Suche nach Autoren", "search.top.breadcrumb.projects": "Suche nach Finanzierung", diff --git a/client/src/pages/search/locales/en.json b/client/src/pages/search/locales/en.json index 93d08784..cfd61a07 100644 --- a/client/src/pages/search/locales/en.json +++ b/client/src/pages/search/locales/en.json @@ -1,5 +1,6 @@ { "search.top.breadcrumb.home": "Home", + "search.top.breadcrumb.find-partners": "Find partners", "search.top.breadcrumb.publications": "Search Publications", "search.top.breadcrumb.authors": "Search Authors", "search.top.breadcrumb.projects": "Search Funding", diff --git a/client/src/pages/search/locales/es.json b/client/src/pages/search/locales/es.json index 2463a8de..62ac7d14 100644 --- a/client/src/pages/search/locales/es.json +++ b/client/src/pages/search/locales/es.json @@ -1,5 +1,6 @@ { "search.top.breadcrumb.home": "Inicio", + "search.top.breadcrumb.find-partners": "Buscar socios", "search.top.breadcrumb.publications": "Buscar Publicaciones", "search.top.breadcrumb.authors": "Buscar Autores", "search.top.breadcrumb.projects": "Buscar Financiamiento", diff --git a/client/src/pages/search/locales/fr.json b/client/src/pages/search/locales/fr.json index 74c8c2c0..a61fcd4c 100644 --- a/client/src/pages/search/locales/fr.json +++ b/client/src/pages/search/locales/fr.json @@ -1,5 +1,6 @@ { "search.top.breadcrumb.home": "Accueil", + "search.top.breadcrumb.find-partners": "Trouver des partenaires", "search.top.breadcrumb.publications": "Rechercher des publications", "search.top.breadcrumb.authors": "Rechercher des auteurs", "search.top.breadcrumb.projects": "Rechercher des financements", From ff0781d9cc2d0a6f1f0c6655df4ff3a2d0348535 Mon Sep 17 00:00:00 2001 From: folland87 Date: Tue, 26 Mar 2024 16:55:20 +0100 Subject: [PATCH 03/21] publications/projects translations --- client/locales.md | 4 +- .../src/pages/projects/[id]/locales/de.json | 32 ++++++++++++++++ .../src/pages/projects/[id]/locales/en.json | 32 ++++++++++++++++ .../src/pages/projects/[id]/locales/es.json | 32 ++++++++++++++++ .../pages/publications/[id]/locales/de.json | 37 +++++++++++++++++++ .../pages/publications/[id]/locales/en.json | 37 +++++++++++++++++++ .../pages/publications/[id]/locales/es.json | 37 +++++++++++++++++++ 7 files changed, 209 insertions(+), 2 deletions(-) create mode 100644 client/src/pages/projects/[id]/locales/de.json create mode 100644 client/src/pages/projects/[id]/locales/en.json create mode 100644 client/src/pages/projects/[id]/locales/es.json create mode 100644 client/src/pages/publications/[id]/locales/de.json create mode 100644 client/src/pages/publications/[id]/locales/en.json create mode 100644 client/src/pages/publications/[id]/locales/es.json diff --git a/client/locales.md b/client/locales.md index 1124ae9a..2b1ea805 100644 --- a/client/locales.md +++ b/client/locales.md @@ -12,8 +12,8 @@ | /pages/bugs | OK | Mihoub | FR,EN,ES,DE | | /pages/home | OK | Mihoub | FR,EN,ES,DE | | /pages/organization | OK | Mihoub | FR,EN,ES,DE | -| /pages/projects | TODO | Mihoub | FR,EN,ES,DE | -| /pages/publications | TODO | Mihoub | FR,EN,ES,DE | +| /pages/projects | OK | FRED | FR,EN,ES,DE | +| /pages/publications | OK | FRED | FR,EN,ES,DE | | /components/api-deprecation-banner | OK | FRED | FR,EN | | /components/contact-form | OK | FRED | FR,EN | | /components/copy | OK | FRED | FR,EN | diff --git a/client/src/pages/projects/[id]/locales/de.json b/client/src/pages/projects/[id]/locales/de.json new file mode 100644 index 00000000..5ba34a60 --- /dev/null +++ b/client/src/pages/projects/[id]/locales/de.json @@ -0,0 +1,32 @@ +{ + "projects.breadcrumb.home": "Startseite", + "projects.breadcrumb.search": "Suche", + "projects.section.identifiers.title": "Projekt-Identifikatoren", + "projects.section.identifiers.desc": "Klicken Sie, um die Kennung in die Zwischenablage zu kopieren", + "projects.section.share.title": "Teilen Sie die Seite", + "projects.section.contribute.title": "Beitragen", + "projects.section.contribute.bugs": "Einen Fehler melden", + "projects.section.programs.tool": "Förderungstool", + "projects.section.programs.call": "Projektaufruf", + "projects.section.programs.topics": "Themen", + "projects.section.programs.priorities": "Prioritäten", + "projects.section.programs": "Informationen", + "projects.section.website.title": "Im Web", + "projects.section.website.name": "Projekt-Website", + "projects.section.coordinator.title": "Projektkoordinator", + "projects.section.funding.title": "Projektfinanzierung", + "projects.section.funding.no-data": "Keine Informationen verfügbar", + "projects.section.funding.global-budget": "Gesamtbudget: ", + "projects.section.funding.contributed-budget": "Beigesteuertes Budget: ", + "projects.section.funding.financed-at": "Finanziert bei ", + "projects.section.participants": "{count, plural, one {Teilnehmer (#)} other {Teilnehmer (#)}}", + "projects.section.participants.french": "Französische Teilnehmer", + "projects.section.participants.foreign": "Ausländische Teilnehmer", + "projects.section.participants.undefined": "Nicht definierte Teilnehmer", + "projects.section.participants.map": "Karte der Teilnehmer anzeigen", + "projects.section.participants.map-title": "Teilnehmerkarte", + "projects.section.participants.financed": "Mit {funding} € finanziert", + "projects.section.publications": "{count, plural, one {# Veröffentlichung} other {Neueste Veröffentlichungen (#)}}", + "projects.section.publications.open-modal-button": "Alle Veröffentlichungen anzeigen", + "projects.section.more-like-this": "Ähnliche Förderungen" +} \ No newline at end of file diff --git a/client/src/pages/projects/[id]/locales/en.json b/client/src/pages/projects/[id]/locales/en.json new file mode 100644 index 00000000..8265d57f --- /dev/null +++ b/client/src/pages/projects/[id]/locales/en.json @@ -0,0 +1,32 @@ +{ + "projects.breadcrumb.home": "Home", + "projects.breadcrumb.search": "Search", + "projects.section.identifiers.title": "Project Identifiers", + "projects.section.identifiers.desc": "Click to copy the identifier to clipboard", + "projects.section.share.title": "Share the page", + "projects.section.contribute.title": "Contribute", + "projects.section.contribute.bugs": "Report a bug", + "projects.section.programs.tool": "Funding Tool", + "projects.section.programs.call": "Call for Projects", + "projects.section.programs.topics": "Topics", + "projects.section.programs.priorities": "Priorities", + "projects.section.programs": "Information", + "projects.section.website.title": "On the Web", + "projects.section.website.name": "Project Website", + "projects.section.coordinator.title": "Project Coordinator", + "projects.section.funding.title": "Project Funding", + "projects.section.funding.no-data": "No information available", + "projects.section.funding.global-budget": "Global Budget: ", + "projects.section.funding.contributed-budget": "Contributed Budget: ", + "projects.section.funding.financed-at": "Financed at ", + "projects.section.participants": "{count, plural, one {Participant (#)} other {Participants (#)}}", + "projects.section.participants.french": "French Participants", + "projects.section.participants.foreign": "Foreign Participants", + "projects.section.participants.undefined": "Undefined Participants", + "projects.section.participants.map": "View a map of participants", + "projects.section.participants.map-title": "Participants Map", + "projects.section.participants.financed": "Financed with {funding} €", + "projects.section.publications": "{count, plural, one {# publication} other {Latest Publications (#)}}", + "projects.section.publications.open-modal-button": "View all publications", + "projects.section.more-like-this": "Similar Funding" +} \ No newline at end of file diff --git a/client/src/pages/projects/[id]/locales/es.json b/client/src/pages/projects/[id]/locales/es.json new file mode 100644 index 00000000..306802f9 --- /dev/null +++ b/client/src/pages/projects/[id]/locales/es.json @@ -0,0 +1,32 @@ +{ + "projects.breadcrumb.home": "Inicio", + "projects.breadcrumb.search": "Buscar", + "projects.section.identifiers.title": "Identificadores del Proyecto", + "projects.section.identifiers.desc": "Haz clic para copiar el identificador al portapapeles", + "projects.section.share.title": "Compartir la página", + "projects.section.contribute.title": "Contribuir", + "projects.section.contribute.bugs": "Informar un error", + "projects.section.programs.tool": "Herramienta de Financiamiento", + "projects.section.programs.call": "Convocatoria de Proyectos", + "projects.section.programs.topics": "Temas", + "projects.section.programs.priorities": "Prioridades", + "projects.section.programs": "Información", + "projects.section.website.title": "En la Web", + "projects.section.website.name": "Sitio Web del Proyecto", + "projects.section.coordinator.title": "Coordinador del Proyecto", + "projects.section.funding.title": "Financiamiento del Proyecto", + "projects.section.funding.no-data": "No hay información disponible", + "projects.section.funding.global-budget": "Presupuesto Global: ", + "projects.section.funding.contributed-budget": "Presupuesto Contribuido: ", + "projects.section.funding.financed-at": "Financiado en ", + "projects.section.participants": "{count, plural, one {Participante (#)} other {Participantes (#)}}", + "projects.section.participants.french": "Participantes Franceses", + "projects.section.participants.foreign": "Participantes Extranjeros", + "projects.section.participants.undefined": "Participantes Indefinidos", + "projects.section.participants.map": "Ver un mapa de participantes", + "projects.section.participants.map-title": "Mapa de Participantes", + "projects.section.participants.financed": "Financiado con {funding} €", + "projects.section.publications": "{count, plural, one {# publicación} other {Últimas Publicaciones (#)}}", + "projects.section.publications.open-modal-button": "Ver todas las publicaciones", + "projects.section.more-like-this": "Financiamiento Similar" +} \ No newline at end of file diff --git a/client/src/pages/publications/[id]/locales/de.json b/client/src/pages/publications/[id]/locales/de.json new file mode 100644 index 00000000..e42616dd --- /dev/null +++ b/client/src/pages/publications/[id]/locales/de.json @@ -0,0 +1,37 @@ +{ + "publications.breadcrumb.home": "Startseite", + "publications.breadcrumb.search": "Veröffentlichungen", + "publications.section.author": "Thesis-Autor", + "publications.section.affiliations": "Autoren-Affiliationen", + "publications.section.affiliations.map": "Affiliationen auf einer Karte anzeigen", + "publications.section.affiliations.map-title": "Karte der Autoren-Affiliationen", + "publications.section.fundings": "Finanzierungen", + "publications.section.more-like-this": "Ähnliche Veröffentlichungen", + "publications.section.access": "Zugriff auf Veröffentlichung", + "publications.section.access.download": "Veröffentlichung herunterladen", + "publications.section.access.visit": "Auf der Website des Verlags anzeigen", + "publications.section.access.download-thesis": "Thesis herunterladen", + "publications.section.access.visit-thesis": "Auf theses.fr anzeigen", + "publications.section.identifiers": "Veröffentlichungs-Identifikatoren", + "publications.section.identifiers-description": "Zum Kopieren klicken", + "publications.section.wikis": "Wikipedia-Konzepte", + "publications.section.share": "Seite teilen", + "publications.section.contribute": "Beitragen", + "publications.section.jury": "Zusammensetzung der Jury", + "publications.section.jury.directeurthese": "Thesis-Betreuer", + "publications.section.jury.presidentjury": "Jury-Präsident", + "publications.section.jury.rapporteur": "Rapporteur", + "publications.section.jury.membrejury": "Jury-Mitglied", + "publications.header.thesis.by": "von ", + "publications.header.thesis.and": " und ", + "publications.header.thesis.directed": " unter der Betreuung von ", + "publications.header.thesis.date": "verteidigt am {date}", + "publications.header.thesis.year": "verteidigt im Jahr {year}", + "publications.header.summary": "Zusammenfassung", + "publications.header.no-summary": "Keine Zusammenfassung verfügbar", + "publications.header.oa.true": "Open Access", + "publications.header.oa.false": "Geschlossener Zugriff", + "publications.signals.author": "Einen Autor identifizieren", + "publications.signals.fundings": "Finanzierung hinzufügen", + "publications.signals.bug": "Einen Fehler melden" +} \ No newline at end of file diff --git a/client/src/pages/publications/[id]/locales/en.json b/client/src/pages/publications/[id]/locales/en.json new file mode 100644 index 00000000..d25a35e9 --- /dev/null +++ b/client/src/pages/publications/[id]/locales/en.json @@ -0,0 +1,37 @@ +{ + "publications.breadcrumb.home": "Home", + "publications.breadcrumb.search": "Publications", + "publications.section.author": "Thesis Author", + "publications.section.affiliations": "Author Affiliations", + "publications.section.affiliations.map": "Show affiliations on a map", + "publications.section.affiliations.map-title": "Map of author affiliations", + "publications.section.fundings": "Fundings", + "publications.section.more-like-this": "Similar Publications", + "publications.section.access": "Access Publication", + "publications.section.access.download": "Download Publication", + "publications.section.access.visit": "View on Publisher's Website", + "publications.section.access.download-thesis": "Download Thesis", + "publications.section.access.visit-thesis": "View on theses.fr", + "publications.section.identifiers": "Publication Identifiers", + "publications.section.identifiers-description": "Click to copy to clipboard", + "publications.section.wikis": "Wikipedia Concepts", + "publications.section.share": "Share Page", + "publications.section.contribute": "Contribute", + "publications.section.jury": "Jury Composition", + "publications.section.jury.directeurthese": "Thesis Supervisor", + "publications.section.jury.presidentjury": "Jury President", + "publications.section.jury.rapporteur": "Rapporteur", + "publications.section.jury.membrejury": "Jury Member", + "publications.header.thesis.by": "by ", + "publications.header.thesis.and": " and ", + "publications.header.thesis.directed": " under the supervision of ", + "publications.header.thesis.date": "defended on {date}", + "publications.header.thesis.year": "defended in {year}", + "publications.header.summary": "Summary", + "publications.header.no-summary": "No summary available", + "publications.header.oa.true": "Open Access", + "publications.header.oa.false": "Closed Access", + "publications.signals.author": "Identify an author", + "publications.signals.fundings": "Add funding", + "publications.signals.bug": "Report an error" +} \ No newline at end of file diff --git a/client/src/pages/publications/[id]/locales/es.json b/client/src/pages/publications/[id]/locales/es.json new file mode 100644 index 00000000..99d57f35 --- /dev/null +++ b/client/src/pages/publications/[id]/locales/es.json @@ -0,0 +1,37 @@ +{ + "publications.breadcrumb.home": "Inicio", + "publications.breadcrumb.search": "Publicaciones", + "publications.section.author": "Autor de la Tesis", + "publications.section.affiliations": "Afiliaciones del Autor", + "publications.section.affiliations.map": "Mostrar afiliaciones en un mapa", + "publications.section.affiliations.map-title": "Mapa de afiliaciones del autor", + "publications.section.fundings": "Financiamientos", + "publications.section.more-like-this": "Publicaciones Similares", + "publications.section.access": "Acceso a la Publicación", + "publications.section.access.download": "Descargar Publicación", + "publications.section.access.visit": "Ver en el Sitio del Editor", + "publications.section.access.download-thesis": "Descargar Tesis", + "publications.section.access.visit-thesis": "Ver en theses.fr", + "publications.section.identifiers": "Identificadores de la Publicación", + "publications.section.identifiers-description": "Haz clic para copiar al portapapeles", + "publications.section.wikis": "Conceptos de Wikipedia", + "publications.section.share": "Compartir Página", + "publications.section.contribute": "Contribuir", + "publications.section.jury": "Composición del Jurado", + "publications.section.jury.directeurthese": "Supervisor de la Tesis", + "publications.section.jury.presidentjury": "Presidente del Jurado", + "publications.section.jury.rapporteur": "Rapporteur", + "publications.section.jury.membrejury": "Miembro del Jurado", + "publications.header.thesis.by": "por ", + "publications.header.thesis.and": " y ", + "publications.header.thesis.directed": " bajo la supervisión de ", + "publications.header.thesis.date": "defendida el {date}", + "publications.header.thesis.year": "defendida en {year}", + "publications.header.summary": "Resumen", + "publications.header.no-summary": "No hay resumen disponible", + "publications.header.oa.true": "Acceso Abierto", + "publications.header.oa.false": "Acceso Restringido", + "publications.signals.author": "Identificar un autor", + "publications.signals.fundings": "Agregar financiamiento", + "publications.signals.bug": "Reportar un error" +} \ No newline at end of file From 212cf9c4ffe0c4d00b55ba7cc7140600638981a9 Mon Sep 17 00:00:00 2001 From: folland87 Date: Wed, 27 Mar 2024 07:26:02 +0100 Subject: [PATCH 04/21] layout translations and rework --- client/locales.md | 1 + client/src/components/footer/index.tsx | 209 +----------- client/src/components/switch-theme.tsx | 77 ----- client/src/layout/Footer.tsx | 94 ------ .../consent/index.tsx} | 117 +++++-- .../layout/components/consent/locales/en.json | 19 ++ .../layout/components/consent/locales/fr.json | 19 ++ client/src/layout/components/footer/index.tsx | 302 ++++++++++++++++++ .../layout/components/footer/locales/en.json | 18 ++ .../layout/components/footer/locales/fr.json | 18 ++ .../components/footer/styles.module.scss | 11 + .../header/index.tsx} | 35 +- .../layout/components/header/locales/en.json | 12 + .../layout/components/header/locales/fr.json | 12 + .../layout/components/switch-theme/index.tsx | 97 ++++++ .../components/switch-theme/locales/en.json | 9 + .../components/switch-theme/locales/fr.json | 9 + client/src/layout/index.tsx | 23 +- client/src/layout/locales/fr.json | 21 -- client/tsconfig.node.json | 6 +- 20 files changed, 656 insertions(+), 453 deletions(-) delete mode 100644 client/src/components/switch-theme.tsx delete mode 100644 client/src/layout/Footer.tsx rename client/src/layout/{consent.tsx => components/consent/index.tsx} (73%) create mode 100644 client/src/layout/components/consent/locales/en.json create mode 100644 client/src/layout/components/consent/locales/fr.json create mode 100644 client/src/layout/components/footer/index.tsx create mode 100644 client/src/layout/components/footer/locales/en.json create mode 100644 client/src/layout/components/footer/locales/fr.json create mode 100644 client/src/layout/components/footer/styles.module.scss rename client/src/layout/{Header.tsx => components/header/index.tsx} (75%) create mode 100644 client/src/layout/components/header/locales/en.json create mode 100644 client/src/layout/components/header/locales/fr.json create mode 100644 client/src/layout/components/switch-theme/index.tsx create mode 100644 client/src/layout/components/switch-theme/locales/en.json create mode 100644 client/src/layout/components/switch-theme/locales/fr.json delete mode 100644 client/src/layout/locales/fr.json diff --git a/client/locales.md b/client/locales.md index 2b1ea805..4af3a6d1 100644 --- a/client/locales.md +++ b/client/locales.md @@ -26,3 +26,4 @@ | /components/websites | OK | FRED | FR,EN | | /components/wiki | OK | FRED | FR,EN | | /components/share | OK | FRED | FR,EN | +| /layout/* | OK | FRED | FR,EN | diff --git a/client/src/components/footer/index.tsx b/client/src/components/footer/index.tsx index c5071117..02f2cbce 100644 --- a/client/src/components/footer/index.tsx +++ b/client/src/components/footer/index.tsx @@ -1,8 +1,6 @@ import React from "react"; -import cn from "classnames"; -import { Col, Container, Link, Logo, Row, Title } from "@dataesr/dsfr-plus"; -import { IntlProvider, createIntl } from "react-intl"; -import styles from "./styles.module.scss"; +import { Container, Link, Logo } from "@dataesr/dsfr-plus"; +import { IntlProvider } from "react-intl"; const modules = import.meta.glob("./locales/*.json", { eager: true, @@ -16,8 +14,9 @@ const messages = Object.keys(modules).reduce((acc, key) => { return acc; }, {}); -const locale = "fr"; -const intl = createIntl({ locale, messages: messages[locale] }); +export function FooterTop({ children }: { children?: React.ReactNode }) { + return
{children}
; +} export function Footer({ children, @@ -26,203 +25,9 @@ export function Footer({ children?: React.ReactNode; fluid?: boolean; }) { - const version = import.meta.env?.VITE_VERSION; return (
-
- - - - -
- - {intl.formatMessage({ - id: "layout.footer.top.about.help", - })} - -
    -
  • - - {intl.formatMessage({ - id: "layout.footer.top.about.faq", - })} - -
  • -
  • - - {intl.formatMessage({ - id: "layout.footer.top.about.team", - })} - -
  • -
  • - - {intl.formatMessage({ - id: "layout.footer.top.about.resources", - })} - -
  • - {/*
  • - - {intl.formatMessage({ - id: "layout.footer.top.about.tutorial", - })} - -
  • */} - {/*
  • - - {intl.formatMessage({ - id: "layout.footer.top.about.glossary", - })} - -
  • */} -
  • - - {intl.formatMessage({ - id: "layout.footer.top.about.contact", - })} - -
  • -
-
-
- - - -
- - {intl.formatMessage({ - id: "layout.footer.top.about.follow", - })} - -
    -
  • - - X - -
  • -
  • - - Linkedin - -
  • -
  • - - Facebook - -
  • -
-
-
- - - -
- - {intl.formatMessage({ - id: "layout.footer.top.about.also", - })} - -
    -
  • - - GitHub - {version && ` – v${version}`} - -
  • -
  • - - CurieXplore - -
  • -
  • - - Baromètre de la Science Ouverte - -
  • -
  • - - #dataESR - -
  • -
  • - - Plateforme Open Data - -
  • -
-
-
- -
-
-
{children}
@@ -238,7 +43,7 @@ export function FooterBottom({ }) { const childs = React.Children.toArray(children); return ( -
+
    {childs.map((child, i) => (
  • @@ -270,7 +75,7 @@ export function FooterBody({ )?.[0]; return ( -
    +
    {logo ? (
    {logo}
    ) : null} diff --git a/client/src/components/switch-theme.tsx b/client/src/components/switch-theme.tsx deleted file mode 100644 index d39c01e6..00000000 --- a/client/src/components/switch-theme.tsx +++ /dev/null @@ -1,77 +0,0 @@ -export default function SwitchTheme() { - return ( - -
    -
    -
    -
    -
    - -
    -
    -

    - Paramètres d’affichage -

    -
    -
    - - Choisissez un thème pour personnaliser l’apparence du site. - -
    -
    - - -
    - -
    -
    -
    -
    -
    - - -
    - -
    -
    -
    -
    -
    - - -
    - -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    - ) -} \ No newline at end of file diff --git a/client/src/layout/Footer.tsx b/client/src/layout/Footer.tsx deleted file mode 100644 index 99f3bdc9..00000000 --- a/client/src/layout/Footer.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { Link, Logo } from "@dataesr/dsfr-plus"; -import { Footer, FooterBody, FooterBottom } from "../components/footer"; -import { useIntl } from "react-intl"; -import SwitchTheme from "../components/switch-theme"; -import useConsent from "../hooks/useConsent"; - -export default function MainFooter() { - const intl = useIntl(); - const { dialogId } = useConsent(); - return ( -
    - - - - legifrance.gouv.fr - - - gouvernement.fr - - - service-public.fr - - - data.gouv.fr - - - - - {intl.formatMessage({ - id: "layout.footer.legal-notice", - })} - - - {intl.formatMessage({ - id: "layout.footer.personal-data", - })} - - - {intl.formatMessage({ - id: "layout.footer.accessibility", - })} - - - - - -
    - ); -} diff --git a/client/src/layout/consent.tsx b/client/src/layout/components/consent/index.tsx similarity index 73% rename from client/src/layout/consent.tsx rename to client/src/layout/components/consent/index.tsx index 30cdee99..f07ead48 100644 --- a/client/src/layout/consent.tsx +++ b/client/src/layout/components/consent/index.tsx @@ -1,14 +1,31 @@ -import useConsent from "../hooks/useConsent"; +import { RawIntlProvider, createIntl } from "react-intl"; +import useConsent from "../../../hooks/useConsent"; +import { useDSFRConfig } from "@dataesr/dsfr-plus"; + +const modules = import.meta.glob('./locales/*.json', { eager: true, import: 'default' }) +const messages = Object.keys(modules).reduce((acc, key) => { + const locale = key.match(/\.\/locales\/(.+)\.json$/)?.[1]; + if (locale) { + return { ...acc, [locale]: modules[key] } + } + return acc; +}, {}); export default function Consent() { + const { locale } = useDSFRConfig(); + const intl = createIntl({ locale, messages: messages[locale] }); const { dialogId, consent, setConsent, set } = useConsent({ twitter: 0, matomo: 0, youtube: 0, facebook: 0, linkedin: 0 }); return ( - <> + {!set &&
    -

    À propos des cookies sur scanr.enseignementsup-recherche.gouv.fr

    +

    + {intl.formatMessage({ id: "layout.consent.title" })} +

    -

    Bienvenue ! Nous utilisons des cookies pour améliorer votre expérience et les services disponibles sur ce site. Pour en savoir plus, visitez la page Données personnelles et cookies. Vous pouvez, à tout moment, avoir le contrôle sur les cookies que vous souhaitez activer.

    +

    + {intl.formatMessage({ id: "layout.consent.content" })} +

    • @@ -17,7 +34,7 @@ export default function Consent() { title="Autoriser tous les cookies" onClick={() => setConsent({ twitter: 1, matomo: 1, youtube: 1, facebook: 1, linkedin: 1 })} > - Tout accepter + {intl.formatMessage({ id: "layout.consent.accept-all" })}
    • @@ -26,7 +43,7 @@ export default function Consent() { title="Refuser tous les cookies" onClick={() => setConsent({ twitter: 0, matomo: 0, youtube: 0, facebook: 0, linkedin: 0 })} > - Tout refuser + {intl.formatMessage({ id: "layout.consent.refuse-all" })}
    • @@ -36,7 +53,7 @@ export default function Consent() { aria-controls={dialogId} title="Personnaliser les cookies" > - Personnaliser + {intl.formatMessage({ id: "layout.consent.customize" })}
    @@ -49,17 +66,18 @@ export default function Consent() {

    - Panneau de gestion des cookies + {intl.formatMessage({ id: "layout.consent.cookies" })}

    - Préférences pour tous les services. Données personnelles et cookies + + {intl.formatMessage({ id: "layout.consent.cookies.preferences" })}
    @@ -77,7 +95,7 @@ export default function Consent() { }} />
    @@ -95,7 +113,7 @@ export default function Consent() { }} />
    @@ -103,7 +121,9 @@ export default function Consent() {
    - Statistique + + {intl.formatMessage({ id: "layout.consent.cookies.finality.stats" })} +
    { consent.matomo = 1 }} />
    @@ -126,18 +146,20 @@ export default function Consent() { onChange={() => { consent.matomo = 0 }} />

    - Les cookies statistiques aident, par la collecte d'informations anonymisées, à comprendre comment les visiteurs interagissent avec scanR. + {intl.formatMessage({ id: "layout.consent.cookies.finality.stats.desc" })}

    - Partage + + {intl.formatMessage({ id: "layout.consent.cookies.finality.share" })} +
    @@ -169,20 +191,57 @@ export default function Consent() { }} />

    - Afin de pouvoir partager les pages de scanR, il est nécessaire d'accepter les cookies de partage des réseaux sociaux. + {intl.formatMessage({ id: "layout.consent.cookies.finality.share.desc" })}

    - +
    - Facebook + + Youtube + +
    +
    + { consent.youtube = 1 }} + /> + +
    +
    + { consent.youtube = 0 }} + /> + +
    +
    +
    +
    +
    +
    + + Facebook +
    { consent.facebook = 1 }} />
    @@ -205,7 +264,7 @@ export default function Consent() { onChange={() => { consent.facebook = 0 }} />
    @@ -226,7 +285,7 @@ export default function Consent() { onChange={() => { consent.twitter = 1 }} />
    @@ -238,7 +297,7 @@ export default function Consent() { onChange={() => { consent.twitter = 0 }} />
    @@ -258,7 +317,7 @@ export default function Consent() { onChange={() => { consent.linkedin = 1 }} />
    @@ -270,7 +329,7 @@ export default function Consent() { onChange={() => { consent.linkedin = 0 }} />
    @@ -301,6 +360,6 @@ export default function Consent() {
    - + ) } \ No newline at end of file diff --git a/client/src/layout/components/consent/locales/en.json b/client/src/layout/components/consent/locales/en.json new file mode 100644 index 00000000..9f8ed995 --- /dev/null +++ b/client/src/layout/components/consent/locales/en.json @@ -0,0 +1,19 @@ +{ + "layout.consent.title": "About cookies on scanr.enseignementsup-recherche.gouv.fr", + "layout.consent.content": "Welcome! We use cookies to enhance your experience and the services available on this site. You can have control over the cookies you wish to enable at any time.", + "layout.consent.accept-all": "Accept All", + "layout.consent.refuse-all": "Refuse All", + "layout.consent.customize": "Customize", + "layout.consent.confirm": "Confirm My Choices", + "layout.consent.cookies.close": "Close", + "layout.consent.cookies": "Cookie Management Panel", + "layout.consent.cookies.preferences": "Preferences for all services.", + "layout.consent.cookies.all.desc": "To learn more, visit the Personal Data and Cookies page.", + "layout.consent.cookies.finality.stats": "Statistics", + "layout.consent.cookies.finality.stats.desc": "Statistical cookies help understand how visitors interact with scanR by collecting anonymized information.", + "layout.consent.cookies.finality.share": "Sharing", + "layout.consent.cookies.finality.share.desc": "To be able to share scanR pages, it is necessary to accept social media sharing cookies.", + "layout.consent.cookies.accept": "Accept", + "layout.consent.cookies.refuse": "Refuse", + "layout.consent.cookies.finality.toggle": "See more details" +} \ No newline at end of file diff --git a/client/src/layout/components/consent/locales/fr.json b/client/src/layout/components/consent/locales/fr.json new file mode 100644 index 00000000..c28ec566 --- /dev/null +++ b/client/src/layout/components/consent/locales/fr.json @@ -0,0 +1,19 @@ +{ + "layout.consent.title": "À propos des cookies sur scanr.enseignementsup-recherche.gouv.fr", + "layout.consent.content": "Bienvenue ! Nous utilisons des cookies pour améliorer votre expérience et les services disponibles sur ce site. Vous pouvez, à tout moment, avoir le contrôle sur les cookies que vous souhaitez activer.", + "layout.consent.accept-all": "Tout accepter", + "layout.consent.refuse-all": "Tout refuser", + "layout.consent.customize": "Personnaliser", + "layout.consent.confirm": "Confirmer mes choix", + "layout.consent.cookies.close": "Fermer", + "layout.consent.cookies": "Panneau de gestion des cookies", + "layout.consent.cookies.preferences": "Préférences pour tous les services.", + "layout.consent.cookies.all.desc": "Pour en savoir plus, visitez la page Données personnelles et cookies.", + "layout.consent.cookies.finality.stats": "Statistique", + "layout.consent.cookies.finality.stats.desc": "Les cookies statistiques aident, par la collecte d'informations anonymisées, à comprendre comment les visiteurs interagissent avec scanR.", + "layout.consent.cookies.finality.share": "Partage", + "layout.consent.cookies.finality.share.desc": "Afin de pouvoir partager les pages de scanR, il est nécessaire d'accepter les cookies de partage des réseaux sociaux.", + "layout.consent.cookies.accept": "Accepter", + "layout.consent.cookies.refuse": "Refuser", + "layout.consent.cookies.finality.toggle": "Voir plus de détails" +} \ No newline at end of file diff --git a/client/src/layout/components/footer/index.tsx b/client/src/layout/components/footer/index.tsx new file mode 100644 index 00000000..4a46835f --- /dev/null +++ b/client/src/layout/components/footer/index.tsx @@ -0,0 +1,302 @@ +import cn from "classnames"; +import { Col, Container, Link, Logo, Row, Title, useDSFRConfig } from "@dataesr/dsfr-plus"; +import { Footer, FooterBody, FooterBottom, FooterTop } from "../../../components/footer"; +import { RawIntlProvider, createIntl } from "react-intl"; +import SwitchTheme from "../switch-theme"; +import useConsent from "../../../hooks/useConsent"; +import { version } from "react"; +import styles from "./styles.module.scss"; + +const modules = import.meta.glob('./locales/*.json', { eager: true, import: 'default' }) +const messages = Object.keys(modules).reduce((acc, key) => { + const locale = key.match(/\.\/locales\/(.+)\.json$/)?.[1]; + if (locale) { + return { ...acc, [locale]: modules[key] } + } + return acc; +}, {}); + +export default function MainFooter() { + const { locale } = useDSFRConfig(); + const intl = createIntl({ locale, messages: messages[locale] }); + const { dialogId } = useConsent(); + return ( + +
    + + + + + +
    + + {intl.formatMessage({ + id: "layout.footer.top.about.help", + })} + +
      +
    • + + {intl.formatMessage({ + id: "layout.footer.top.about.faq", + })} + +
    • +
    • + + {intl.formatMessage({ + id: "layout.footer.top.about.team", + })} + +
    • +
    • + + {intl.formatMessage({ + id: "layout.footer.top.about.resources", + })} + +
    • + {/*
    • + + {intl.formatMessage({ + id: "layout.footer.top.about.tutorial", + })} + +
    • */} + {/*
    • + + {intl.formatMessage({ + id: "layout.footer.top.about.glossary", + })} + +
    • */} +
    • + + {intl.formatMessage({ + id: "layout.footer.top.about.contact", + })} + +
    • +
    +
    +
    + + + +
    + + {intl.formatMessage({ + id: "layout.footer.top.about.follow", + })} + +
      +
    • + + X + +
    • +
    • + + Linkedin + +
    • +
    • + + Facebook + +
    • +
    +
    +
    + + + +
    + + {intl.formatMessage({ + id: "layout.footer.top.about.also", + })} + +
      +
    • + + GitHub + {version && ` – v${version}`} + +
    • +
    • + + CurieXplore + +
    • +
    • + + Baromètre de la Science Ouverte + +
    • +
    • + + #dataESR + +
    • +
    • + + Plateforme Open Data + +
    • +
    +
    +
    + +
    +
    +
    + + + + legifrance.gouv.fr + + + gouvernement.fr + + + service-public.fr + + + data.gouv.fr + + + + + {intl.formatMessage({ + id: "layout.footer.legal-notice", + })} + + + {intl.formatMessage({ + id: "layout.footer.personal-data", + })} + + + {intl.formatMessage({ + id: "layout.footer.accessibility", + })} + + + + + +
    +
    + ); +} diff --git a/client/src/layout/components/footer/locales/en.json b/client/src/layout/components/footer/locales/en.json new file mode 100644 index 00000000..3ed1c1fd --- /dev/null +++ b/client/src/layout/components/footer/locales/en.json @@ -0,0 +1,18 @@ +{ + "layout.footer.top.about": "About", + "layout.footer.top.about.faq": "FAQ", + "layout.footer.top.about.team": "Team", + "layout.footer.top.about.help": "Help", + "layout.footer.top.about.also": "See also", + "layout.footer.top.about.follow": "Follow us", + "layout.footer.top.about.resources": "Data sources", + "layout.footer.top.about.tutorial": "Tutorial", + "layout.footer.top.about.glossary": "Glossary", + "layout.footer.top.about.contact": "Contact", + "layout.footer.tagline": "Explore the world of French Research and Innovation with scanR", + "layout.footer.legal-notice": "Legal Notice", + "layout.footer.personal-data": "Personal Data", + "layout.footer.cookies": "Cookies", + "layout.footer.accessibility": "Accessibility", + "layout.footer.switch-theme": "Theme" +} \ No newline at end of file diff --git a/client/src/layout/components/footer/locales/fr.json b/client/src/layout/components/footer/locales/fr.json new file mode 100644 index 00000000..b05681e8 --- /dev/null +++ b/client/src/layout/components/footer/locales/fr.json @@ -0,0 +1,18 @@ +{ + "layout.footer.top.about": "A propos", + "layout.footer.top.about.faq": "FAQ", + "layout.footer.top.about.team": "L'équipe", + "layout.footer.top.about.help": "Aide", + "layout.footer.top.about.also": "Voir aussi", + "layout.footer.top.about.follow": "Nous suivre", + "layout.footer.top.about.resources": "Sources de données", + "layout.footer.top.about.tutorial": "Tutoriel", + "layout.footer.top.about.glossary": "Glossaire", + "layout.footer.top.about.contact": "Contact", + "layout.footer.tagline": "Explorez le monde de la Recherche et de l'Innovation française avec scanR", + "layout.footer.legal-notice": "Mentions légales", + "layout.footer.personal-data": "Données personnelles", + "layout.footer.cookies": "Cookies", + "layout.footer.accessibility": "Accessibilité", + "layout.footer.switch-theme": "Thème" +} \ No newline at end of file diff --git a/client/src/layout/components/footer/styles.module.scss b/client/src/layout/components/footer/styles.module.scss new file mode 100644 index 00000000..0f01013c --- /dev/null +++ b/client/src/layout/components/footer/styles.module.scss @@ -0,0 +1,11 @@ +.text-right { + text-align: right; +} + +.text-left { + text-align: left; +} + +.text-center { + text-align: center; +} \ No newline at end of file diff --git a/client/src/layout/Header.tsx b/client/src/layout/components/header/index.tsx similarity index 75% rename from client/src/layout/Header.tsx rename to client/src/layout/components/header/index.tsx index 44f29e57..d0aaca02 100644 --- a/client/src/layout/Header.tsx +++ b/client/src/layout/components/header/index.tsx @@ -9,17 +9,28 @@ import { Nav, FastAccess, Button, + useDSFRConfig, // Autocomplete, // AutocompleteItem, // useAutocompleteList, // useDSFRConfig, } from '@dataesr/dsfr-plus'; -import { FormattedMessage, useIntl } from 'react-intl'; -import SwitchLanguage from '../components/switch-language'; +import { createIntl } from 'react-intl'; +import SwitchLanguage from '../../../components/switch-language'; // import { autocompleteOrganizations } from '../api/organizations/autocomplete'; // import { LightOrganization } from '../types/organization'; // import getLangFieldValue from '../utils/lang'; +const modules = import.meta.glob('./locales/*.json', { eager: true, import: 'default' }) +const messages = Object.keys(modules).reduce((acc, key) => { + const locale = key.match(/\.\/locales\/(.+)\.json$/)?.[1]; + if (locale) { + return { ...acc, [locale]: modules[key] } + } + return acc; +}, {}); + + const languages = [ { shortName: 'FR', fullName: 'Français', key: 'fr' }, { shortName: 'EN', fullName: 'English', key: 'en' }, @@ -29,9 +40,9 @@ const languages = [ ]; export default function Header() { - // const { locale } = useDSFRConfig(); + const { locale } = useDSFRConfig(); + const intl = createIntl({ locale, messages: messages[locale] }); const { pathname } = useLocation(); - const intl = useIntl(); // const authorsAutocompletedList = useAutocompleteList({ // async load({ filterText }) { @@ -49,7 +60,7 @@ export default function Header() { @@ -77,25 +88,27 @@ export default function Header() { )} */}
    {logoUrl && (
    @@ -220,9 +224,13 @@ export default function ProjectPresentation({ data }: { data: Project }) { - + {accomplishment && (
    - Filtres + {intl.formatMessage({ id: "search.filters.current.title" })}
    {Object.keys(currentFilters)?.length ? ( diff --git a/client/src/pages/search/components/projects/project-item.tsx b/client/src/pages/search/components/projects/project-item/index.tsx similarity index 71% rename from client/src/pages/search/components/projects/project-item.tsx rename to client/src/pages/search/components/projects/project-item/index.tsx index 777df0dd..38e37374 100644 --- a/client/src/pages/search/components/projects/project-item.tsx +++ b/client/src/pages/search/components/projects/project-item/index.tsx @@ -7,10 +7,23 @@ import { Badge, useDSFRConfig, } from "@dataesr/dsfr-plus"; -import { ItemProps } from "../../types"; -import { LightProject } from "../../../../types/project"; -import { getProjectById } from "../../../../api/projects/[id]"; -import getLangFieldValue from "../../../../utils/lang"; +import { ItemProps } from "../../../types"; +import { LightProject } from "../../../../../types/project"; +import { getProjectById } from "../../../../../api/projects/[id]"; +import getLangFieldValue from "../../../../../utils/lang"; +import { RawIntlProvider, createIntl } from "react-intl"; + +const modules = import.meta.glob("./locales/*.json", { + eager: true, + import: "default", +}); +const messages = Object.keys(modules).reduce((acc, key) => { + const locale = key.match(/\.\/locales\/(.+)\.json$/)?.[1]; + if (locale) { + return { ...acc, [locale]: modules[key] }; + } + return acc; +}, {}); export default function ProjectItem({ data: project, @@ -18,6 +31,7 @@ export default function ProjectItem({ }: ItemProps) { const queryClient = useQueryClient(); const { locale } = useDSFRConfig(); + const intl = createIntl({ locale, messages: messages[locale] }); function prefetchAuthor(id: string) { queryClient.prefetchQuery({ @@ -37,7 +51,7 @@ export default function ProjectItem({ : project?.participants; return ( - +
    @@ -52,8 +66,10 @@ export default function ProjectItem({ - {shouldFilterParticipants && - `${project.participants?.length} participants dont ${frenchParticipants?.length} français`} + {shouldFilterParticipants && intl.formatMessage( + { id: "project.item.participants.filtered" }, + { total: project.participants?.length, french: frenchParticipants?.length } + )} {shouldFilterParticipants &&
    } {participants?.map((p, k) => ( @@ -75,6 +91,6 @@ export default function ProjectItem({
    ))}
    -
    + ); } diff --git a/client/src/pages/search/components/projects/project-item/locales/en.json b/client/src/pages/search/components/projects/project-item/locales/en.json new file mode 100644 index 00000000..e27cfae7 --- /dev/null +++ b/client/src/pages/search/components/projects/project-item/locales/en.json @@ -0,0 +1,3 @@ +{ + "project.item.participants.filtered": "{total} participants, {french} french" +} \ No newline at end of file diff --git a/client/src/pages/search/components/projects/project-item/locales/fr.json b/client/src/pages/search/components/projects/project-item/locales/fr.json new file mode 100644 index 00000000..3d4be0b2 --- /dev/null +++ b/client/src/pages/search/components/projects/project-item/locales/fr.json @@ -0,0 +1,3 @@ +{ + "project.item.participants.filtered": "{total} participants dont ${french} français" +} \ No newline at end of file diff --git a/client/src/pages/search/locales/de.json b/client/src/pages/search/locales/de.json index a0f771c3..bf059482 100644 --- a/client/src/pages/search/locales/de.json +++ b/client/src/pages/search/locales/de.json @@ -95,6 +95,7 @@ "search.organizations.analytics.by-fundings.title": "Nach Finanzierungstypen", "search.filters.add": "Filter hinzufügen", "search.filters.clear": "Filter zurücksetzen", + "search.filters.current.title": "Filter", "search.filters.current.no-filter": "Kein aktiver Filter", "search.filters.current.organizations.kind": "Branche", "search.filters.current.organizations.level": "Organisationstyp", diff --git a/client/src/pages/search/locales/en.json b/client/src/pages/search/locales/en.json index cfd61a07..efd53cb4 100644 --- a/client/src/pages/search/locales/en.json +++ b/client/src/pages/search/locales/en.json @@ -95,6 +95,7 @@ "search.organizations.analytics.by-fundings.title": "By Funding Type", "search.filters.add": "Add Filters", "search.filters.clear": "Reset Filters", + "search.filters.current.title": "Filters", "search.filters.current.no-filter": "No active filters", "search.filters.current.organizations.kind": "Sector", "search.filters.current.organizations.level": "Organization Type", diff --git a/client/src/pages/search/locales/es.json b/client/src/pages/search/locales/es.json index 62ac7d14..a9905e82 100644 --- a/client/src/pages/search/locales/es.json +++ b/client/src/pages/search/locales/es.json @@ -95,6 +95,7 @@ "search.organizations.analytics.by-fundings.title": "Por Tipo de Financiamiento", "search.filters.add": "Agregar Filtros", "search.filters.clear": "Restablecer Filtros", + "search.filters.current.title": "Filtros", "search.filters.current.no-filter": "Sin filtros activos", "search.filters.current.organizations.kind": "Sector", "search.filters.current.organizations.level": "Tipo de Organización", diff --git a/client/src/pages/search/locales/fr.json b/client/src/pages/search/locales/fr.json index a61fcd4c..dcc52b1c 100644 --- a/client/src/pages/search/locales/fr.json +++ b/client/src/pages/search/locales/fr.json @@ -95,6 +95,7 @@ "search.organizations.analytics.by-fundings.title": "Par type de financement", "search.filters.add": "Ajouter des filtres", "search.filters.clear": "Réinitialiser les filtres", + "search.filters.current.title": "Filtres", "search.filters.current.no-filter": "Aucun filtre actif", "search.filters.current.organizations.kind": "Secteur", "search.filters.current.organizations.level": "Type d'organisme", From 69a1f710ef6e559ad5433947fb5ad1be32bc9f69 Mon Sep 17 00:00:00 2001 From: folland87 Date: Wed, 27 Mar 2024 08:37:33 +0100 Subject: [PATCH 06/21] analytics graph translations --- client/locales.md | 2 +- .../src/components/analytics-graph/index.tsx | 159 ++++++++++-------- .../analytics-graph/locales/en.json | 7 + .../analytics-graph/locales/fr.json | 7 + 4 files changed, 106 insertions(+), 69 deletions(-) create mode 100644 client/src/components/analytics-graph/locales/en.json create mode 100644 client/src/components/analytics-graph/locales/fr.json diff --git a/client/locales.md b/client/locales.md index 456e536b..dededf63 100644 --- a/client/locales.md +++ b/client/locales.md @@ -26,5 +26,5 @@ | /components/websites | OK | FRED | FR,EN | | /components/wiki | OK | FRED | FR,EN | | /components/share | OK | FRED | FR,EN | -| /components/analytics-graph | TODO | FRED | FR,EN | +| /components/analytics-graph | OK | FRED | FR,EN | | /layout/* | OK | FRED | FR,EN | \ No newline at end of file diff --git a/client/src/components/analytics-graph/index.tsx b/client/src/components/analytics-graph/index.tsx index 231a61d9..d17b28af 100644 --- a/client/src/components/analytics-graph/index.tsx +++ b/client/src/components/analytics-graph/index.tsx @@ -1,8 +1,17 @@ -import { Title, MenuButton, MenuSection, MenuItem, Modal, ModalTitle, ModalContent } from "@dataesr/dsfr-plus" +import { Title, MenuButton, MenuSection, MenuItem, Modal, ModalTitle, ModalContent, useDSFRConfig } from "@dataesr/dsfr-plus" import HighchartsReact, { HighchartsReactProps } from "highcharts-react-official"; import React, { useId, useRef, useState } from "react"; import Highcharts from "./highcharts"; +import { RawIntlProvider, createIntl } from 'react-intl'; +const modules = import.meta.glob('./locales/*.json', { eager: true, import: 'default' }) +const messages = Object.keys(modules).reduce((acc, key) => { + const locale = key.match(/\.\/locales\/(.+)\.json$/)?.[1]; + if (locale) { + return { ...acc, [locale]: modules[key] } + } + return acc; +}, {}); export type AnalyticsGraphProps = { title: string, description?: React.ReactNode, @@ -12,6 +21,8 @@ export type AnalyticsGraphProps = { export default function AnalyticsGraph({ title, description, comment, options }: AnalyticsGraphProps) { + const { locale } = useDSFRConfig(); + const intl = createIntl({ locale, messages: messages[locale] }); const descriptionId = useId(); const titleId = useId(); const chartRef = useRef(null); @@ -33,74 +44,86 @@ export default function AnalyticsGraph({ title, description, comment, options }: } return ( -
    -
    -
    - - {title} - - {description &&

    {description}

    } -
    -
    - - - } - > - Plein écran - - } - > - {showTable ? "Masquer" : "Voir"} les données - - - - } - > - Exporter une image png - - } - > - PDF - - - - } - > - Télécharger les données en csv - - - + +
    +
    +
    + + {title} + + {description &&

    {description}

    } +
    +
    + + + } + > + + {intl.formatMessage({ id: "analytics.graph.fullscreen" })} + + + } + > + + {intl.formatMessage({ id: "analytics.graph.view.table" })} + + + + + } + > + + {intl.formatMessage({ id: "analytics.graph.export.png" })} + + + } + > + + {intl.formatMessage({ id: "analytics.graph.export.pdf" })} + + + + + } + > + + {intl.formatMessage({ id: "analytics.graph.download.csv" })} + + + + +
    + + {comment &&

    {comment}

    } + setShowTable(false)}> + {title} + +
    + +
    - - {comment &&

    {comment}

    } - setShowTable(false)}> - {title} - -
    - - -
    + ) } \ No newline at end of file diff --git a/client/src/components/analytics-graph/locales/en.json b/client/src/components/analytics-graph/locales/en.json new file mode 100644 index 00000000..42452869 --- /dev/null +++ b/client/src/components/analytics-graph/locales/en.json @@ -0,0 +1,7 @@ +{ + "analytics.graph.fullscreen": "Full screen", + "analytics.graph.view.table": "View data", + "analytics.graph.export.png": "Export as PNG", + "analytics.graph.export.pdf": "Export as PDF", + "analytics.graph.download.csv": "Download data as CSV" +} \ No newline at end of file diff --git a/client/src/components/analytics-graph/locales/fr.json b/client/src/components/analytics-graph/locales/fr.json new file mode 100644 index 00000000..d448538e --- /dev/null +++ b/client/src/components/analytics-graph/locales/fr.json @@ -0,0 +1,7 @@ +{ + "analytics.graph.fullscreen": "Plein écran", + "analytics.graph.view.table": "Voir les données", + "analytics.graph.export.png": "Exporter en PNG", + "analytics.graph.export.pdf": "Exporter en PDF", + "analytics.graph.download.csv": "Télécharger les données en CSV" +} \ No newline at end of file From 32aaee79ccda2b62c9c0c1b541308fb86097f2ba Mon Sep 17 00:00:00 2001 From: Mihoub Debache Date: Wed, 27 Mar 2024 10:06:33 +0100 Subject: [PATCH 07/21] fix(locales): check bugs and replace simple wording by locales --- client/package-lock.json | 40 ++--- .../pages/authors/[id]/components/author.tsx | 154 +++++++++++++----- client/src/pages/authors/[id]/locales/de.json | 1 + client/src/pages/authors/[id]/locales/en.json | 1 + client/src/pages/authors/[id]/locales/es.json | 1 + client/src/pages/authors/[id]/locales/fr.json | 1 + .../search/components/authors/author-item.tsx | 51 ++++-- client/src/pages/search/locales/de.json | 1 + client/src/pages/search/locales/en.json | 1 + client/src/pages/search/locales/es.json | 1 + client/src/pages/search/locales/fr.json | 1 + 11 files changed, 170 insertions(+), 83 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 0dad4dbc..30dd6dee 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -2778,9 +2778,9 @@ } }, "node_modules/@tanstack/query-core": { - "version": "5.28.8", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.28.8.tgz", - "integrity": "sha512-cx64XHeB0kvKxFt22ibvegPeOxnaWVFUbAuhXoIrb7+XePEexHWoB9Kq5n9qroNPkRwQZwgFAP9HNbQz5ohoIg==", + "version": "5.28.9", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.28.9.tgz", + "integrity": "sha512-hNlfCiqZevr3GRVPXS3MhaGW5hjcxvCsIQ4q6ff7EPlvFwYZaS+0d9EIIgofnegDaU2BbCDlyURoYfRl5rmzow==", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" @@ -2796,11 +2796,11 @@ } }, "node_modules/@tanstack/react-query": { - "version": "5.28.8", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.28.8.tgz", - "integrity": "sha512-4XYhoRmcThqziB32HsyiBLNXJcukaeGfYwAQ+fZqUUE3ZP4oB/Zy41UJdql+TUg98+vsezfbixxAwAbGHfc5Hg==", + "version": "5.28.9", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.28.9.tgz", + "integrity": "sha512-vwifBkGXsydsLxFOBMe3+f8kvtDoqDRDwUNjPHVDDt+FoBetCbOWAUHgZn4k+CVeZgLmy7bx6aKeDbe3e8koOQ==", "dependencies": { - "@tanstack/query-core": "5.28.8" + "@tanstack/query-core": "5.28.9" }, "funding": { "type": "github", @@ -2811,9 +2811,9 @@ } }, "node_modules/@tanstack/react-query-devtools": { - "version": "5.28.8", - "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.28.8.tgz", - "integrity": "sha512-NorR2ueGlGdB5PTvt1WynzjfNI/OJwiisB1r0UAwgi0Em2UalZpMltwvoIrGhJ0T2V+8b0MV5wD+cmf0PPdHGA==", + "version": "5.28.9", + "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.28.9.tgz", + "integrity": "sha512-GHbJDJIhAak2B+7NJvSfT+jfajxMf/CEwbVn4Z+JSVLUZ21/TITwQWaihN1WKKj/nMbizUu6U2O9MTNHW4YPqg==", "dependencies": { "@tanstack/query-devtools": "5.28.6" }, @@ -2822,7 +2822,7 @@ "url": "https://github.com/sponsors/tannerlinsley" }, "peerDependencies": { - "@tanstack/react-query": "^5.28.8", + "@tanstack/react-query": "^5.28.9", "react": "^18.0.0" } }, @@ -2894,12 +2894,11 @@ "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" }, "node_modules/@types/react": { - "version": "18.2.71", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.71.tgz", - "integrity": "sha512-PxEsB9OjmQeYGffoWnYAd/r5FiJuUw2niFQHPc2v2idwh8wGPkkYzOHuinNJJY6NZqfoTCiOIizDOz38gYNsyw==", + "version": "18.2.72", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.72.tgz", + "integrity": "sha512-/e7GWxGzXQF7OJAua7UAYqYi/4VpXEfbGtmYQcAQwP3SjjjAXfybTf/JK5S+SaetB/ChXl8Y2g1hCsj7jDXxcg==", "dependencies": { "@types/prop-types": "*", - "@types/scheduler": "*", "csstype": "^3.0.2" } }, @@ -2912,11 +2911,6 @@ "@types/react": "*" } }, - "node_modules/@types/scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-YIoDCTH3Af6XM5VuwGG/QL/CJqga1Zm3NkU3HZ4ZHK2fRMPYP1VczsTUqtsf43PH/iJNVlPHAo2oWX7BSdB2Hw==" - }, "node_modules/@types/semver": { "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", @@ -5450,9 +5444,9 @@ } }, "node_modules/react-intl": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-6.6.3.tgz", - "integrity": "sha512-vLKI0f+Q3pXD5szmCUPikTY7CJDPtxCBMG5YABQZ3IGEKzNB47zlvXyasUFfT25zpgQXeOfhRCdx4q6ubuR6bA==", + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-6.6.4.tgz", + "integrity": "sha512-bD+7hVTX3zBFI3z/ffIVZrNkCVK0/sQguQ/DqW5uZ6JFWsuiwOieVcLnmtFiUgMQZLdmwNl2Ur5c10RaO7NWBQ==", "dependencies": { "@formatjs/ecma402-abstract": "1.18.2", "@formatjs/icu-messageformat-parser": "2.7.6", diff --git a/client/src/pages/authors/[id]/components/author.tsx b/client/src/pages/authors/[id]/components/author.tsx index 3e14f86e..938af28d 100644 --- a/client/src/pages/authors/[id]/components/author.tsx +++ b/client/src/pages/authors/[id]/components/author.tsx @@ -1,4 +1,13 @@ -import { Badge, BadgeGroup, Button, ButtonGroup, Col, Container, Row, Title } from "@dataesr/dsfr-plus"; +import { + Badge, + BadgeGroup, + Button, + ButtonGroup, + Col, + Container, + Row, + Title, +} from "@dataesr/dsfr-plus"; import Share from "../../../../components/share"; import BarLink from "../../../../components/bar-link"; import { PageContent, PageSection } from "../../../../components/page-content"; @@ -11,40 +20,50 @@ import AuthorAwards from "./awards"; import Identifiers from "../../../../components/identifiers"; import { Author } from "../../../../types/author"; import RecentAffiliations from "./recent-affiliations"; -import NetworksNotice from "../../../../components/networks-notice" -import { stringifySearchFiltersForURL } from "../../../search/hooks/useUrl" +import NetworksNotice from "../../../../components/networks-notice"; +import { stringifySearchFiltersForURL } from "../../../search/hooks/useUrl"; import MoreLikeThis from "../../../../components/more-like-this"; function getOaInfo(publi) { - const oaCount = publi?.filter((publi) => publi.isOa)?.length - const oaTotal = publi?.length - return { oaPercent: Math.ceil((oaCount / oaTotal) * 100), oaCount, oaTotal } + const oaCount = publi?.filter((publi) => publi.isOa)?.length; + const oaTotal = publi?.length; + return { oaPercent: Math.ceil((oaCount / oaTotal) * 100), oaCount, oaTotal }; } export default function AuthorPage({ data }: { data: Author }) { - const intl = useIntl() - const { publications: publicationsObject, awards } = data - const { wikis, coAuthors, reviews, byYear, publications } = publicationsObject + const intl = useIntl(); + const { publications: publicationsObject, awards } = data; + const { wikis, coAuthors, reviews, byYear, publications } = + publicationsObject; - const maxCommonPublications = coAuthors && Math.max(...coAuthors.map((el) => el.count)) - const maxReviews = reviews && Math.max(...reviews.map((el) => el.count)) + const maxCommonPublications = + coAuthors && Math.max(...coAuthors.map((el) => el.count)); + const maxReviews = reviews && Math.max(...reviews.map((el) => el.count)); const thesis = publications?.filter((publi) => { - return publi.type === "thesis" && publi.authors.find((author) => author.person === data.id)?.role === "author" - }) + return ( + publi.type === "thesis" && + publi.authors.find((author) => author.person === data.id)?.role === + "author" + ); + }); const thesisParticipations = publications?.filter((publi) => { - return publi.type === "thesis" && publi.authors.find((author) => author.person === data.id)?.role !== "author" - }) - const others = publications?.filter((publi) => publi.type !== "thesis") + return ( + publi.type === "thesis" && + publi.authors.find((author) => author.person === data.id)?.role !== + "author" + ); + }); + const others = publications?.filter((publi) => publi.type !== "thesis"); const networkFilter = stringifySearchFiltersForURL({ "authors.person": { type: "terms", values: [{ value: data?.id, label: data?.fullName }], }, - }) - const networkUrl = `/networks?q=*&tab=authors&filters=${networkFilter}` + }); + const networkUrl = `/networks?q=*&tab=authors&filters=${networkFilter}`; - const { oaPercent } = getOaInfo(publications) + const { oaPercent } = getOaInfo(publications); return ( @@ -54,7 +73,7 @@ export default function AuthorPage({ data }: { data: Author }) { - Auteur + {intl.formatMessage({ id: "authors.section.author" })} @@ -67,15 +86,21 @@ export default function AuthorPage({ data }: { data: Author }) { size="lead" show={!!wikis?.length} title={intl.formatMessage({ id: "authors.section.wiki.title" })} - description={intl.formatMessage({ id: "authors.section.wiki.desc" })} + description={intl.formatMessage({ + id: "authors.section.wiki.desc", + })} > <TagCloud data={wikis} order="random" /> </PageSection> <PageSection size="lead" show={!!data.recentAffiliations?.length} - title={intl.formatMessage({ id: "authors.section.recent-affiliations.title" })} - description={intl.formatMessage({ id: "authors.section.recent-affiliations.description" })} + title={intl.formatMessage({ + id: "authors.section.recent-affiliations.title", + })} + description={intl.formatMessage({ + id: "authors.section.recent-affiliations.description", + })} > <RecentAffiliations data={data.recentAffiliations} /> </PageSection> @@ -91,17 +116,29 @@ export default function AuthorPage({ data }: { data: Author }) { icon="article-line" size="lead" show={!!thesis?.length} - title={intl.formatMessage({ id: "authors.section.activity.thesis" }, { count: thesis.length })} + title={intl.formatMessage( + { id: "authors.section.activity.thesis" }, + { count: thesis.length } + )} > - <AuthorsPublications data={thesis} titleKey="authors.section.activity.thesis" /> + <AuthorsPublications + data={thesis} + titleKey="authors.section.activity.thesis" + /> </PageSection> <PageSection size="lead" show={!!others?.length} - title={intl.formatMessage({ id: "authors.section.activity.publications" }, { count: others.length })} + title={intl.formatMessage( + { id: "authors.section.activity.publications" }, + { count: others.length } + )} icon="heart-pulse-line" > - <AuthorsPublications data={others} titleKey="authors.section.activity.publications" /> + <AuthorsPublications + data={others} + titleKey="authors.section.activity.publications" + /> {data?.publications?.coAuthors?.length > 2 && ( <div className="fr-mt-2w"> <NetworksNotice url={networkUrl} /> @@ -117,7 +154,10 @@ export default function AuthorPage({ data }: { data: Author }) { { count: thesisParticipations.length } )} > - <AuthorsPublications data={thesisParticipations} titleKey="authors.section.activity.thesis-participations" /> + <AuthorsPublications + data={thesisParticipations} + titleKey="authors.section.activity.thesis-participations" + /> </PageSection> <PageSection size="lead" @@ -129,7 +169,11 @@ export default function AuthorPage({ data }: { data: Author }) { > <MoreLikeThis id={data._id} api="authors" /> </PageSection> - <PageSection title="Data JSON" description="" show={import.meta.env.DEV}> + <PageSection + title="Data JSON" + description="" + show={import.meta.env.DEV} + > <div> <pre>{JSON.stringify(data || "", null, 2)}</pre> </div> @@ -141,15 +185,23 @@ export default function AuthorPage({ data }: { data: Author }) { <PageContent> <PageSection show - title={intl.formatMessage({ id: "authors.section.identifiers.title" })} - description={intl.formatMessage({ id: "authors.section.identifiers.desc" })} + title={intl.formatMessage({ + id: "authors.section.identifiers.title", + })} + description={intl.formatMessage({ + id: "authors.section.identifiers.desc", + })} > <Identifiers data={data.externalIds} /> </PageSection> <PageSection show={!!byYear?.length} - title={intl.formatMessage({ id: "authors.section.by-year.title" })} - description={intl.formatMessage({ id: "authors.section.by-year.desc" })} + title={intl.formatMessage({ + id: "authors.section.by-year.title", + })} + description={intl.formatMessage({ + id: "authors.section.by-year.desc", + })} > <YearBars name="Publications" @@ -160,14 +212,20 @@ export default function AuthorPage({ data }: { data: Author }) { <PageSection show={!!oaPercent} title={intl.formatMessage({ id: "authors.section.oa.title" })} - description={intl.formatMessage({ id: "authors.section.oa.desc" })} + description={intl.formatMessage({ + id: "authors.section.oa.desc", + })} > <OpenAccessDonut percentage={oaPercent} /> </PageSection> <PageSection show={!!coAuthors?.length} - title={intl.formatMessage({ id: "authors.section.co-authors.title" })} - description={intl.formatMessage({ id: "authors.section.co-authors.desc" })} + title={intl.formatMessage({ + id: "authors.section.co-authors.title", + })} + description={intl.formatMessage({ + id: "authors.section.co-authors.desc", + })} > {coAuthors?.slice(0, 6)?.map((coAuthor, i) => ( <BarLink @@ -181,8 +239,12 @@ export default function AuthorPage({ data }: { data: Author }) { </PageSection> <PageSection show={!!reviews?.length} - title={intl.formatMessage({ id: "authors.section.reviews.title" })} - description={intl.formatMessage({ id: "authors.section.reviews.desc" })} + title={intl.formatMessage({ + id: "authors.section.reviews.title", + })} + description={intl.formatMessage({ + id: "authors.section.reviews.desc", + })} > {reviews?.slice(0, 6)?.map((review, i) => ( <BarLink @@ -194,10 +256,18 @@ export default function AuthorPage({ data }: { data: Author }) { /> ))} </PageSection> - <PageSection show title={intl.formatMessage({ id: "authors.section.share" })}> + <PageSection + show + title={intl.formatMessage({ id: "authors.section.share" })} + > <Share /> </PageSection> - <PageSection title={intl.formatMessage({ id: "authors.section.contribute.title" })} show> + <PageSection + title={intl.formatMessage({ + id: "authors.section.contribute.title", + })} + show + > <ButtonGroup> <Button as="a" @@ -224,5 +294,5 @@ export default function AuthorPage({ data }: { data: Author }) { </Col> </Row> </Container> - ) -} \ No newline at end of file + ); +} diff --git a/client/src/pages/authors/[id]/locales/de.json b/client/src/pages/authors/[id]/locales/de.json index 3db16cea..6e33fec3 100644 --- a/client/src/pages/authors/[id]/locales/de.json +++ b/client/src/pages/authors/[id]/locales/de.json @@ -2,6 +2,7 @@ "authors.breadcrumb.home": "Startseite", "authors.breadcrumb.search": "Autoren", "authors.section.wiki.title": "Wikipedia-Konzepte", + "authors.section.author": "Autor", "authors.section.wiki.desc": "In den Veröffentlichungen des Autors identifiziert. Klicken Sie hier, um nach weiteren Veröffentlichungen zu suchen, die das Stichwort enthalten.", "authors.section.prizes": "Preise und Auszeichnungen", "authors.section.activity": "Forschungsaktivität", diff --git a/client/src/pages/authors/[id]/locales/en.json b/client/src/pages/authors/[id]/locales/en.json index c6e68f8f..a8f6d2c3 100644 --- a/client/src/pages/authors/[id]/locales/en.json +++ b/client/src/pages/authors/[id]/locales/en.json @@ -2,6 +2,7 @@ "authors.breadcrumb.home": "Home", "authors.breadcrumb.search": "Authors", "authors.section.wiki.title": "Wikipedia Concepts", + "authors.section.author": "Author", "authors.section.wiki.desc": "Identified in the author's publications. Click to search for other publications containing the keyword.", "authors.section.prizes": "Awards and Distinctions", "authors.section.activity": "Research Activity", diff --git a/client/src/pages/authors/[id]/locales/es.json b/client/src/pages/authors/[id]/locales/es.json index cc74cba1..2a1f10c3 100644 --- a/client/src/pages/authors/[id]/locales/es.json +++ b/client/src/pages/authors/[id]/locales/es.json @@ -2,6 +2,7 @@ "authors.breadcrumb.home": "Inicio", "authors.breadcrumb.search": "Autores", "authors.section.wiki.title": "Conceptos de Wikipedia", + "authors.section.author": "Autor", "authors.section.wiki.desc": "Identificados en las publicaciones del autor. Haz clic para buscar otras publicaciones que contengan la palabra clave", "authors.section.prizes": "Premios y distinciones", "authors.section.activity": "Actividad de investigación", diff --git a/client/src/pages/authors/[id]/locales/fr.json b/client/src/pages/authors/[id]/locales/fr.json index 5d26854a..5fcc8825 100644 --- a/client/src/pages/authors/[id]/locales/fr.json +++ b/client/src/pages/authors/[id]/locales/fr.json @@ -2,6 +2,7 @@ "authors.breadcrumb.home": "Accueil", "authors.breadcrumb.search": "Auteurs", "authors.section.wiki.title": "Concepts Wikipédia", + "authors.section.author": "Auteur", "authors.section.wiki.desc": "Repérés dans les publications de l'auteur. Cliquez pour rechercher d'autres publications contenant le mot-clé", "authors.section.prizes": "Prix et distinctions", "authors.section.activity": "Activité de recherche", diff --git a/client/src/pages/search/components/authors/author-item.tsx b/client/src/pages/search/components/authors/author-item.tsx index 71388f5b..dea22553 100644 --- a/client/src/pages/search/components/authors/author-item.tsx +++ b/client/src/pages/search/components/authors/author-item.tsx @@ -6,48 +6,63 @@ import { LightAuthor } from "../../../../types/author"; import { getAuthorById } from "../../../../api/authors/[id]"; import { ItemProps } from "../../types"; import CopyBadge from "../../../../components/copy/copy-badge"; +import { useIntl } from "react-intl"; +export default function AuthorItem({ + data: author, + highlight, +}: ItemProps<LightAuthor>) { + const intl = useIntl(); -export default function AuthorItem({ data: author, highlight }: ItemProps<LightAuthor>) { const queryClient = useQueryClient(); function prefetchAuthor(id: string) { queryClient.prefetchQuery({ - queryKey: ['author', id], + queryKey: ["author", id], queryFn: () => getAuthorById(id), - }) + }); } return ( <Fragment key={author.id}> <div className="result-item" key={author.id}> <BadgeGroup className="structure-badge-list fr-mt-1v"> - <Badge size="sm" color='orange-terre-battue'>Auteur</Badge> + <Badge size="sm" color="orange-terre-battue"> + {intl.formatMessage({ id: "search.section.author.badge" })} + </Badge> </BadgeGroup> - <span onMouseEnter={() => prefetchAuthor(author.id)}><Link href={`/authors/${author.id}`} className="fr-link"> - {author.fullName} - </Link> + <span onMouseEnter={() => prefetchAuthor(author.id)}> + <Link href={`/authors/${author.id}`} className="fr-link"> + {author.fullName} + </Link> </span> <Text bold size="sm" className="fr-mb-0"> {author?.domains - ?.filter((domain) => (domain.type === "wikidata")) + ?.filter((domain) => domain.type === "wikidata") ?.slice(0, 8) .map((domain, k) => ( <Fragment key={k}> - {(k > 0) ? ', ' : ''} - <Link href={`/search/authors?q="${encode(domain?.label.default)}"`}>#{domain?.label.default}</Link> + {k > 0 ? ", " : ""} + <Link + href={`/search/authors?q="${encode(domain?.label.default)}"`} + > + #{domain?.label.default} + </Link> </Fragment> - ) - )} + ))} </Text> <div className="fr-mt-1w fr-badge-group"> {[ { id: author.id.replace("idref", ""), type: "idref" }, - { id: author.orcid, type: 'orcid' }, - { id: author.id_hal, type: 'idhal' }] + { id: author.orcid, type: "orcid" }, + { id: author.id_hal, type: "idhal" }, + ] .filter((identifier) => identifier.id) - .map(({ id, type }) => <CopyBadge key={id} size="sm" copyText={id}>{type} : {id}</CopyBadge>) - } + .map(({ id, type }) => ( + <CopyBadge key={id} size="sm" copyText={id}> + {type} : {id} + </CopyBadge> + ))} </div> {Object.values(highlight || {}).map((value, i) => ( <Text key={i} size="sm" className="fr-mb-0"> @@ -56,5 +71,5 @@ export default function AuthorItem({ data: author, highlight }: ItemProps<LightA ))} </div> </Fragment> - ) -} \ No newline at end of file + ); +} diff --git a/client/src/pages/search/locales/de.json b/client/src/pages/search/locales/de.json index bf059482..cd91223a 100644 --- a/client/src/pages/search/locales/de.json +++ b/client/src/pages/search/locales/de.json @@ -7,6 +7,7 @@ "search.top.breadcrumb.patents": "Suche nach Patenten", "search.top.breadcrumb.organizations": "Suche nach Organisationen", "search.top.main-search-bar": "Suche", + "search.section.author.badge": "Autor", "search.top.patent.family.badge": "Patentfamilie", "search.top.filters-button-label": "Filter hinzufügen", "search.top.filters.clear": "Filter löschen", diff --git a/client/src/pages/search/locales/en.json b/client/src/pages/search/locales/en.json index efd53cb4..3e826816 100644 --- a/client/src/pages/search/locales/en.json +++ b/client/src/pages/search/locales/en.json @@ -7,6 +7,7 @@ "search.top.breadcrumb.patents": "Search Patents", "search.top.breadcrumb.organizations": "Search Organizations", "search.top.main-search-bar": "Search", + "search.section.author.badge": "Author", "search.top.patent.family.badge": "Patent Family", "search.top.filters-button-label": "Add Filters", "search.top.filters.clear": "Clear Filters", diff --git a/client/src/pages/search/locales/es.json b/client/src/pages/search/locales/es.json index a9905e82..3d8df4ad 100644 --- a/client/src/pages/search/locales/es.json +++ b/client/src/pages/search/locales/es.json @@ -7,6 +7,7 @@ "search.top.breadcrumb.patents": "Buscar Patentes", "search.top.breadcrumb.organizations": "Buscar Organizaciones", "search.top.main-search-bar": "Buscar", + "search.section.author.badge": "Autor", "search.top.patent.family.badge": "Familia de Patentes", "search.top.filters-button-label": "Agregar Filtros", "search.top.filters.clear": "Limpiar Filtros", diff --git a/client/src/pages/search/locales/fr.json b/client/src/pages/search/locales/fr.json index dcc52b1c..f3da9ca9 100644 --- a/client/src/pages/search/locales/fr.json +++ b/client/src/pages/search/locales/fr.json @@ -7,6 +7,7 @@ "search.top.breadcrumb.patents": "Rechercher des brevets", "search.top.breadcrumb.organizations": "Rechercher des structures", "search.top.main-search-bar": "Rechercher", + "search.section.author.badge": "Auteur", "search.top.patent.family.badge": "Famille de brevet", "search.top.filters-button-label": "Ajouter des filtres", "search.top.filters.clear": "Réintitialiser les filtres", From 7a5d0277dc6dfd99363b4073a82750b3a4655d94 Mon Sep 17 00:00:00 2001 From: folland87 <frederic@olland.me> Date: Wed, 27 Mar 2024 10:57:37 +0100 Subject: [PATCH 08/21] feat(publications): Add a software mention section on publication page when softwares have been detected --- client/src/api/publications/[id]/index.ts | 2 +- .../[id]/components/publication.tsx | 10 +++ .../[id]/components/softwares/index.tsx | 87 +++++++++++++++++++ .../pages/publications/[id]/locales/de.json | 4 +- .../pages/publications/[id]/locales/en.json | 4 +- .../pages/publications/[id]/locales/es.json | 4 +- .../pages/publications/[id]/locales/fr.json | 4 +- client/src/types/publication.ts | 8 ++ 8 files changed, 118 insertions(+), 5 deletions(-) create mode 100644 client/src/pages/publications/[id]/components/softwares/index.tsx diff --git a/client/src/api/publications/[id]/index.ts b/client/src/api/publications/[id]/index.ts index 2128e27f..5244336a 100644 --- a/client/src/api/publications/[id]/index.ts +++ b/client/src/api/publications/[id]/index.ts @@ -7,7 +7,7 @@ export async function getPublicationById(id: string): Promise<Publication> { _source: [ "title", "summary", "authors.fullName", "authors.person", "authors.role", "authors.affiliations", "domains", "affiliations", "source", "isOa", 'type', 'id', "year", "oaEvidence", "projects", "externalIds", - "pdfUrl", "landingPage" + "pdfUrl", "landingPage", "softwares", ], query: { bool: { diff --git a/client/src/pages/publications/[id]/components/publication.tsx b/client/src/pages/publications/[id]/components/publication.tsx index a38f61f4..35483dbd 100644 --- a/client/src/pages/publications/[id]/components/publication.tsx +++ b/client/src/pages/publications/[id]/components/publication.tsx @@ -10,6 +10,7 @@ import Identifiers from "../../../../components/identifiers"; import MoreLikeThis from "../../../../components/more-like-this"; import { Publication } from "../../../../types/publication"; import { encode } from "../../../../utils/string"; +import Softwares from "./softwares"; export default function PublicationPage({ data }: { data: Publication }) { @@ -84,6 +85,15 @@ export default function PublicationPage({ data }: { data: Publication }) { ))} </div> </PageSection> + <PageSection + size="lead" + icon="code-s-slash-line" + title={intl.formatMessage({ id: "publications.section.softwares.title" })} + description={intl.formatMessage({ id: "publications.section.softwares.legend" })} + show={!!data?.softwares?.length} + > + <Softwares softwares={data?.softwares} /> + </PageSection> <PageSection size="lead" title={intl.formatMessage({ id: "publications.section.more-like-this" })} diff --git a/client/src/pages/publications/[id]/components/softwares/index.tsx b/client/src/pages/publications/[id]/components/softwares/index.tsx new file mode 100644 index 00000000..b04abbb4 --- /dev/null +++ b/client/src/pages/publications/[id]/components/softwares/index.tsx @@ -0,0 +1,87 @@ +import { Row, Col, Text, useDSFRConfig, Link } from "@dataesr/dsfr-plus"; +import { SoftwareMention } from "../../../../../types/publication"; +import { getWikidataPreviews } from "../../../../../components/wiki/api"; +import { useQuery } from "@tanstack/react-query"; +import { WikipediaResult } from "../../../../../components/wiki/types"; +import { Fragment } from "react/jsx-runtime"; + +export default function Softwares({ softwares }: { softwares: SoftwareMention[] }) { + const { locale } = useDSFRConfig(); + + const codes = softwares + .map((software) => software.wikidata) + .filter((wikidata) => !!wikidata) + .map((wikidata) => ({ code: wikidata })); + + const { data: wikis } = useQuery<WikipediaResult[]>({ + queryKey: ["wikidatas", codes.map(c => c.code), locale], + queryFn: () => getWikidataPreviews(codes, locale), + enabled: !!codes?.length, + }); + + const getSoftwareContexts = (softwareName: string, contexts?: string[]) => { + if (!contexts.length) return null; + const newContexts = contexts.map((context) => { + const regexp = new RegExp(softwareName, "ig") + const newContext = context.replace(regexp, `<strong>${softwareName}</strong>`); + return newContext; + }); + const stringContexts = newContexts.reduce((acc, cur) => { + if (acc.length === 0) return cur; + if (acc.length > 300) return acc; + return `${acc} ... ${cur}`; + }, ""); + + return <span dangerouslySetInnerHTML={{ __html: stringContexts }} /> + } + + const _softwares = softwares.map((software) => { + const wiki = wikis?.find((w) => w.code === software.wikidata); + return { ...software, wiki }; + }) + + + if (!softwares.length) return null; + return ( + <Row gutters> + <Col xs="12"> + {_softwares.map((software) => ( + <div key={software.id_name}> + <Text size="lg" className="fr-mb-0" bold> + {software.softwareName} + {software?.wiki?.code && <button className="fr-btn--tooltip fr-ml-1v" aria-describedby={`software-${software.wiki.code}`}>Wikipedia</button>} + </Text> + {software?.wiki?.code && ( + <Fragment key={software.wiki.code}> + <span className="fr-tooltip fr-placement" id={`software-${software.wiki.code}`} role="tooltip" aria-hidden="true"> + <div className="fr-p-2w"> + <div className="wiki-text"> + <Text bold size="lg"> + {software.wiki?.title} + </Text> + <Text size="sm"> + {software.wiki?.extract} + </Text> + </div> + {software.wiki?.image && ( + <img style={{ objectFit: "cover" }} width="100%" height="100px" src={software.wiki.image} aria-hidden /> + )} + <hr className="fr-my-1w" /> + <Link href={software.wiki.url} target="_blank"> + Wikipedia + </Link> + </div> + </span> + </Fragment> + )} + {!!software?.contexts?.length && ( + <Text className="fr-text-mention--grey fr-text--sm"> + {getSoftwareContexts(software.softwareName, software.contexts)} + </Text> + )} + </div> + ))} + </Col> + </Row> + ); +} \ No newline at end of file diff --git a/client/src/pages/publications/[id]/locales/de.json b/client/src/pages/publications/[id]/locales/de.json index e42616dd..2f9d78f5 100644 --- a/client/src/pages/publications/[id]/locales/de.json +++ b/client/src/pages/publications/[id]/locales/de.json @@ -33,5 +33,7 @@ "publications.header.oa.false": "Geschlossener Zugriff", "publications.signals.author": "Einen Autor identifizieren", "publications.signals.fundings": "Finanzierung hinzufügen", - "publications.signals.bug": "Einen Fehler melden" + "publications.signals.bug": "Einen Fehler melden", + "publications.section.softwares.title": "Softwareerwähnungen", + "publications.section.softwares.legend": "Softwareerwähnungen, die von scanR in der Veröffentlichung gefunden wurden." } \ No newline at end of file diff --git a/client/src/pages/publications/[id]/locales/en.json b/client/src/pages/publications/[id]/locales/en.json index 371c6f29..e2ef5f9c 100644 --- a/client/src/pages/publications/[id]/locales/en.json +++ b/client/src/pages/publications/[id]/locales/en.json @@ -33,5 +33,7 @@ "publications.header.oa.false": "Closed access", "publications.signals.author": "Identify an author", "publications.signals.fundings": "Add funding", - "publications.signals.bug": "Report an error" + "publications.signals.bug": "Report an error", + "publications.section.softwares.title": "Software Mentions", + "publications.section.softwares.legend": "Software mentions found by scanR in the publication." } \ No newline at end of file diff --git a/client/src/pages/publications/[id]/locales/es.json b/client/src/pages/publications/[id]/locales/es.json index 99d57f35..03bf514a 100644 --- a/client/src/pages/publications/[id]/locales/es.json +++ b/client/src/pages/publications/[id]/locales/es.json @@ -33,5 +33,7 @@ "publications.header.oa.false": "Acceso Restringido", "publications.signals.author": "Identificar un autor", "publications.signals.fundings": "Agregar financiamiento", - "publications.signals.bug": "Reportar un error" + "publications.signals.bug": "Reportar un error", + "publications.section.softwares.title": "Menciones de Software", + "publications.section.softwares.legend": "Menciones de software encontradas por scanR en la publicación." } \ No newline at end of file diff --git a/client/src/pages/publications/[id]/locales/fr.json b/client/src/pages/publications/[id]/locales/fr.json index 4afeb754..1a1e0281 100644 --- a/client/src/pages/publications/[id]/locales/fr.json +++ b/client/src/pages/publications/[id]/locales/fr.json @@ -33,5 +33,7 @@ "publications.header.oa.false": "Accès fermé", "publications.signals.author": "Identifier un auteur", "publications.signals.fundings": "Ajouter un financement", - "publications.signals.bug": "Signaler une erreur" + "publications.signals.bug": "Signaler une erreur", + "publications.section.softwares.title": "Mentions de logiciels", + "publications.section.softwares.legend": "Les mentions de logiciels retrouvées par scanR dans la publication." } \ No newline at end of file diff --git a/client/src/types/publication.ts b/client/src/types/publication.ts index 8822df6a..e8dfd9fe 100644 --- a/client/src/types/publication.ts +++ b/client/src/types/publication.ts @@ -38,6 +38,13 @@ type BasePublication = { year: number; }; +export type SoftwareMention = { + softwareName: string; + contexts: string[]; + id_name: string; + wikidata?: string; +} + export type LightPublication = BasePublication & { authors: { fullName: string; @@ -50,6 +57,7 @@ export type Publication = BasePublication & { _id: string; summary: LangField; domains: DomainsData[]; + softwares: SoftwareMention[]; landingPage?: string; pdfUrl?: string; affiliations: { From 758a4abec4b58a27fc19dbe8a6c1c795cac5dd9b Mon Sep 17 00:00:00 2001 From: victor barbier <victor.barbier@recherche.gouv.fr> Date: Wed, 27 Mar 2024 11:37:14 +0100 Subject: [PATCH 09/21] feat(networks): merge branch develop_networks --- .../src/api/networks/network/communities.ts | 32 ++--- client/src/api/networks/network/config.ts | 7 +- client/src/api/networks/network/network.ts | 16 ++- client/src/api/networks/network/openai.ts | 7 +- client/src/api/networks/search/search.ts | 15 +-- .../pages/networks/components/charts/years.ts | 4 - .../src/pages/networks/components/table.tsx | 7 +- client/src/pages/networks/locales/fr.json | 1 + client/src/types/network.ts | 110 ++++++++++++------ 9 files changed, 119 insertions(+), 80 deletions(-) diff --git a/client/src/api/networks/network/communities.ts b/client/src/api/networks/network/communities.ts index a5323f5a..9198757d 100644 --- a/client/src/api/networks/network/communities.ts +++ b/client/src/api/networks/network/communities.ts @@ -2,19 +2,19 @@ import Graph from "graphology-types" import louvain from "graphology-communities-louvain" import { arrayPush, labelClean } from "../_utils/functions" import { networkSearchHits } from "../search/search" -import { ElasticHits } from "../../../types/network" +import { ElasticHits, NetworkCommunities, NetworkFilters } from "../../../types/network" import { openAiLabeledClusters } from "./openai" import { vosColors } from "../_utils/constants" import { GetColorName } from "hex-color-to-color-name" -const communityGetAttribute = (graph: Graph, community: number, name: string): Array<any> => +const communityGetAttribute = (graph: Graph, community: number, name: string): Array<string> | Array<number> => graph.reduceNodes( (acc, _, attr) => (attr.community === community && attr?.[name] ? (acc = arrayPush(acc, attr[name])) : acc), [] ) const communityGetLinks = (graph: Graph, community: number): Array<string> => [ - ...new Set(communityGetAttribute(graph, community, "links").flat(1)), + ...new Set(communityGetAttribute(graph, community, "links").flat(1).map(String)), ] const communityGetIds = (graph: Graph, community: number): Array<string> => @@ -24,10 +24,10 @@ const communityGetSize = (graph: Graph, community: number): number => graph.filterNodes((_, attr) => attr?.community === community).length const communityGetMaxYear = (graph: Graph, community: number): number => - Math.max(...communityGetAttribute(graph, community, "maxYear")) + Math.max(...communityGetAttribute(graph, community, "maxYear").map(Number)) const communityGetMaxWeightNodes = (graph: Graph, community: number): Array<string> => { - const maxWeight = Math.max(...communityGetAttribute(graph, community, "weight")) + const maxWeight = Math.max(...communityGetAttribute(graph, community, "weight").map(Number)) const labels = graph.reduceNodes( (acc, _, attr) => (acc = attr?.community === community && attr?.weight === maxWeight ? [...acc, attr.label] : acc), [] @@ -35,7 +35,7 @@ const communityGetMaxWeightNodes = (graph: Graph, community: number): Array<stri return labels } -const communityGetYears = (hits: ElasticHits) => +const communityGetYears = (hits: ElasticHits): Record<string, number> => hits.reduce((acc, hit) => { const year = hit.year acc[year] = acc[year] ? acc[year] + 1 : 1 @@ -44,7 +44,7 @@ const communityGetYears = (hits: ElasticHits) => // const communityGetPublications = (hits: ElasticHits): Array<string> => hits.map((hit) => hit.title.default) -const communityGetDomains = (hits: ElasticHits): any => +const communityGetDomains = (hits: ElasticHits): Record<string, number> => hits.reduce((acc, hit) => { if (hit?.domains) { hit.domains.forEach(({ label, count }) => { @@ -58,9 +58,10 @@ const communityGetDomains = (hits: ElasticHits): any => const communityGetOaPercent = (hits: ElasticHits): number => (hits.map((hit) => hit.isOa).filter(Boolean).length / hits.length) * 100 -export default async function communitiesCreate(graph: Graph, computeClusters: boolean): Promise<any> { - const query = graph.getAttribute("query") - const model = graph.getAttribute("model") +export default async function communitiesCreate(graph: Graph, computeClusters: boolean): Promise<NetworkCommunities> { + const query: string = graph.getAttribute("query") + const model: string = graph.getAttribute("model") + const filters: NetworkFilters = graph.getAttribute("filters") // Assign communities louvain.assign(graph) @@ -74,21 +75,22 @@ export default async function communitiesCreate(graph: Graph, computeClusters: b // Create communities array const communities = Promise.all( Array.from({ length: count }, async (_, index) => { - const hits = await networkSearchHits(query, model, communityGetLinks(graph, index)) + // Get elastic publications + const hits = await networkSearchHits({ model, query, filters, links: communityGetLinks(graph, index) }) const community = { - index: index, + cluster: index, label: vosColors?.[index] ? GetColorName(vosColors[index]) : `Unnamed ${index + 1}`, color: vosColors?.[index] ?? "#e2e2e2", - ids: communityGetIds(graph, index), size: communityGetSize(graph, index), + ids: communityGetIds(graph, index), maxYear: communityGetMaxYear(graph, index), maxWeightNodes: communityGetMaxWeightNodes(graph, index), ...(hits && { - domains: communityGetDomains(hits), - oaPercent: communityGetOaPercent(hits), hits: hits.length, years: communityGetYears(hits), + domains: communityGetDomains(hits), + oaPercent: communityGetOaPercent(hits), }), } return community diff --git a/client/src/api/networks/network/config.ts b/client/src/api/networks/network/config.ts index 0448a56f..c892024d 100644 --- a/client/src/api/networks/network/config.ts +++ b/client/src/api/networks/network/config.ts @@ -1,3 +1,4 @@ +import { Attributes } from "graphology-types" import { NetworkConfig } from "../../../types/network" const CONFIG = { @@ -41,7 +42,7 @@ const CONFIG = { }, }, domains: { - url: (_: string, attr: any) => `/search/publications?q="${attr.label.replace(/ /g, "+")}"`, + url: (_: string, attr: Attributes) => `/search/publications?q="${attr.label.replace(/ /g, "+")}"`, terminology: { item: "domain", items: "domains", @@ -54,7 +55,7 @@ const CONFIG = { }, }, software: { - url: (_: string, attr: any) => `/search/publications?q="${attr.label.replace(/ /g, "+")}"`, + url: (_: string, attr: Attributes) => `/search/publications?q="${attr.label.replace(/ /g, "+")}"`, terminology: { item: "software", items: "software", @@ -73,7 +74,7 @@ const configGetItemDescription = () => const configGetLinkDescription = (model: string) => `<div class='description_heading'>Co-${model} link</div><div class='description_label'>` -export function configGetItemUrl(model: string, key: string, attr: any): string { +export function configGetItemUrl(model: string, key: string, attr: Attributes): string { const targetUrl = CONFIG?.[model]?.url(key, attr) ?? "" const baseUrl = window?.location?.href?.split("/networks")[0] ?? "" return baseUrl + targetUrl diff --git a/client/src/api/networks/network/network.ts b/client/src/api/networks/network/network.ts index 197dd66b..000157c7 100644 --- a/client/src/api/networks/network/network.ts +++ b/client/src/api/networks/network/network.ts @@ -3,7 +3,7 @@ import subgraph from "graphology-operators/subgraph" import { connectedComponents } from "graphology-components" import random from "graphology-layout/random" import forceAtlas2 from "graphology-layout-forceatlas2" -import { NetworkData } from "../../../types/network" +import { ElasticBuckets, NetworkFilters, NetworkData } from "../../../types/network" import communitiesCreate from "./communities" import { configGetItemUrl } from "./config" @@ -15,13 +15,15 @@ const nodeConcatMaxYear = (nodeMaxYear: number, maxYear: number) => (nodeMaxYear export default async function networkCreate( query: string, model: string, - aggregation: Array<any>, + filters: NetworkFilters, + aggregation: ElasticBuckets, computeClusters: boolean ): Promise<NetworkData> { // Create Graph object let graph = new UndirectedGraph() graph.setAttribute("query", query) graph.setAttribute("model", model) + graph.setAttribute("filters", filters) aggregation.forEach((item) => { const { key, doc_count: count } = item @@ -88,7 +90,7 @@ export default async function networkCreate( console.log("Graph nodes", Array.from(graph.nodeEntries())) // Create network - const network = { + const network: NetworkData = { items: graph.mapNodes((key, attr) => ({ id: key, x: attr.x, @@ -102,15 +104,11 @@ export default async function networkCreate( links: graph.mapEdges((_, attr, source, target) => ({ source_id: source, target_id: target, - strength: attr?.weight, - })), - clusters: communities.map((community) => ({ - ...community, - cluster: community.index + 1, + strength: attr.weight, })), + clusters: communities, } console.log("network", network) - return network } diff --git a/client/src/api/networks/network/openai.ts b/client/src/api/networks/network/openai.ts index 9c3b9139..144bcadb 100644 --- a/client/src/api/networks/network/openai.ts +++ b/client/src/api/networks/network/openai.ts @@ -1,8 +1,9 @@ import MistralClient, { ResponseFormats } from "@mistralai/mistralai" +import { NetworkCommunities } from "../../../types/network" const ENABLED = false -async function mistralLabelsFromDomains(domains: any): Promise<string> { +async function mistralLabelsFromDomains(domains: string): Promise<string> { const { VITE_MISTRAL_API_KEY } = import.meta.env if (!VITE_MISTRAL_API_KEY) { @@ -35,7 +36,7 @@ async function mistralLabelsFromDomains(domains: any): Promise<string> { return answer } -export async function openAiLabeledClusters(clusters: Array<any>) { +export async function openAiLabeledClusters(clusters: NetworkCommunities): Promise<NetworkCommunities> { if (!ENABLED) return clusters const prefix = "list" @@ -50,7 +51,7 @@ export async function openAiLabeledClusters(clusters: Array<any>) { acc = acc + `${prefix}${index + 1} = [${topDomains}], ` } return acc - }, "") + }, "") as string console.log("domains", domains) if (!domains) return clusters diff --git a/client/src/api/networks/search/search.ts b/client/src/api/networks/search/search.ts index c3001a84..da332598 100644 --- a/client/src/api/networks/search/search.ts +++ b/client/src/api/networks/search/search.ts @@ -1,5 +1,5 @@ import { publicationsIndex, postHeaders } from "../../../config/api" -import { Network, NetworkSearchBody, NetworkSearchArgs, ElasticHits } from "../../../types/network" +import { Network, NetworkSearchBody, NetworkSearchArgs, ElasticHits, NetworkSearchHitsArgs } from "../../../types/network" import networkCreate from "../network/network" import configCreate from "../network/config" import infoCreate from "../network/info" @@ -43,7 +43,7 @@ export async function networkSearch({ model, query, options, filters }: NetworkS headers: postHeaders, }) if (res.status !== 200) { - throw new Error(`Elasticsearch error: ${res.status}`); + throw new Error(`Elasticsearch error: ${res.status}`) } const json = await res.json() console.log("endOfSearch", json) @@ -54,7 +54,7 @@ export async function networkSearch({ model, query, options, filters }: NetworkS } const computeClusters = options?.computeClusters ?? false - const network = await networkCreate(query, model, aggregation, computeClusters) + const network = await networkCreate(query, model, filters, aggregation, computeClusters) const config = configCreate(model) const info = infoCreate(query, model) @@ -72,7 +72,8 @@ export async function networkSearch({ model, query, options, filters }: NetworkS return data } -export async function networkSearchHits(query: string, model: string, links: Array<string>): Promise<ElasticHits> { +export async function networkSearchHits({ model, query, filters, links }: NetworkSearchHitsArgs): Promise<ElasticHits> { + const linksFilter = { terms: { [`co_${model}.keyword`]: links } } const body = { size: DEFAULT_SIZE, _source: HIT_FIELDS, @@ -86,11 +87,7 @@ export async function networkSearchHits(query: string, model: string, links: Arr }, }, ], - filter: { - terms: { - [`co_${model}.keyword`]: links, - }, - }, + filter: filters.concat(linksFilter), }, }, } diff --git a/client/src/pages/networks/components/charts/years.ts b/client/src/pages/networks/components/charts/years.ts index a81f89e2..63b4c3cf 100644 --- a/client/src/pages/networks/components/charts/years.ts +++ b/client/src/pages/networks/components/charts/years.ts @@ -5,10 +5,6 @@ export default function getYearsChartOptions({ data, height = "250px", title = " const maxValue = Math.max(..._data.flatMap((d) => Object.values(d.years))) const range = [...Array(maxYear - minYear + 1).keys()].map((y) => y + minYear) - console.log("years", minYear, maxYear) - console.log("range", range) - console.log("maxValue", maxValue) - return { chart: { type: "spline", diff --git a/client/src/pages/networks/components/table.tsx b/client/src/pages/networks/components/table.tsx index b4ec4464..f9d735dd 100644 --- a/client/src/pages/networks/components/table.tsx +++ b/client/src/pages/networks/components/table.tsx @@ -1,8 +1,9 @@ import { useMemo } from "react" -import { Container, Spinner } from "@dataesr/dsfr-plus" +import { Container } from "@dataesr/dsfr-plus" import { NetworkData } from "../../../types/network" import useSearchData from "../hooks/useSearchData" import useUrl from "../../search/hooks/useUrl" +import BaseSkeleton from "../../../components/skeleton/base-skeleton" export default function ClustersTable({ currentTab, enabled }: { currentTab: string; enabled: boolean }) { const { currentQuery, currentFilters } = useUrl() @@ -16,7 +17,7 @@ export default function ClustersTable({ currentTab, enabled }: { currentTab: str if (!enabled) return null - if (search.isFetching) return <Spinner /> + if (search.isFetching) return <BaseSkeleton width="100%" height="30rem" className="fr-my-1v" /> return ( <Container className="fr-mt-5w" key={key}> @@ -38,7 +39,7 @@ export default function ClustersTable({ currentTab, enabled }: { currentTab: str <td> {community?.domains ? Object.entries(community.domains) - .sort((a: [string, number], b: [string, number]) => b[1] - a[1]) + .sort((a, b) => b[1] - a[1]) .slice(0, 5) .map(([domain]) => `${domain}`) .join(", ") diff --git a/client/src/pages/networks/locales/fr.json b/client/src/pages/networks/locales/fr.json index 5bddaa9f..beb61b5b 100644 --- a/client/src/pages/networks/locales/fr.json +++ b/client/src/pages/networks/locales/fr.json @@ -47,6 +47,7 @@ "search.filters.publications.by-author": "Filtrer par auteur", "search.filters.publications.by-author-description": "Sélectionnez un ou plusieurs auteurs", "search.filters.publications.by-is-oa": "Accès ouvert", + "search.filters.publications.by-is-oa-label": "Afficher uniquement les publications en accès ouvert", "search.filters.publications.by-organization": "Filtrer par affiliation", "search.filters.publications.by-organization-description": "Sélectionnez une ou plusieurs affiliations", "search.top.publications.filters.result-count": "{count, plural, =0 {# publication} one {# publication} other {# publications}}", diff --git a/client/src/types/network.ts b/client/src/types/network.ts index c2969306..4747068d 100644 --- a/client/src/types/network.ts +++ b/client/src/types/network.ts @@ -3,67 +3,110 @@ import { LangField } from "./commons" export type Network = { network: NetworkData config?: NetworkConfig + info?: NetworkInfo } export type NetworkData = { - items: Array<any> - links: Array<any> - clusters?: Array<any> + items: NetworkItems + links: NetworkLinks + clusters?: NetworkCommunities +} +export type NetworkItems = Array<NetworkItem> +export type NetworkItem = { + id: string + label: string + x: number + y: number + cluster: number + weights: Record<string, number> + scores: Record<string, number> + page?: string +} +export type NetworkLinks = Array<NetworkLink> +export type NetworkLink = { + source_id: string + target_id: string + strength: number +} +export type NetworkCommunities = Array<NetworkCommunity> +export type NetworkCommunity = { + cluster: number + label: string + size: number + color: string + ids?: Array<string> + maxYear?: number + maxWeightNodes?: Array<string> + hits?: number + years?: Record<string, number> + domains?: Record<string, number> + oaPercent?: number } export type NetworkConfig = { - terminology?: object - color_schemes?: object - templates?: object - styles?: object + terminology?: Record<string, unknown> + color_schemes?: Record<string, unknown> + templates?: Record<string, unknown> + styles?: Record<string, unknown> } export type NetworkInfo = { - title: string - description: string + title?: string + description?: string } export type NetworkSearchBody = { size: number - query: any - aggs: any + query: { + bool?: { + must?: Array<Record<string, unknown>> + filter?: Array<Record<string, unknown>> + } + function_score?: Record<string, unknown> + } + aggs?: Record<string, unknown> } export type NetworkSearchArgs = { model: string query?: string + filters?: NetworkFilters options?: { computeClusters?: boolean } - filters?: Record<string, unknown>[] -} -export type NetworkHitsBody = { - size: number - query: any - _source: Array<string> } - -export type Community = { - index: number - label: string - ids: Array<string> - size: number - maxYear?: number - maxWeightNodes?: Array<string> - domains?: any +export type NetworkSearchHitsArgs = { + model: string + query?: string + filters?: NetworkFilters + links?: Array<string> } -export type Communities = Array<Community> +export type NetworkHits = Array<NetworkHit> export type NetworkHit = { id: string - title: string - type: string - isOa: boolean - domains: any + title?: string + type?: string + isOa?: boolean + year?: number + domains?: Record<string, unknown> } -export type NetworkHits = Array<NetworkHit> +export type NetworkFilters = Array<NetworkFilter> +export type NetworkFilter = Record<string, unknown> + +export type ElasticBuckets = Array<ElasticBucket> +export type ElasticBucket = { + key: string + doc_count: number + max_year?: { + value: number + } +} + +export type ElasticDomains = Array<ElasticDomain> export type ElasticDomain = { label: LangField count: number } -export type ElasticDomains = Array<ElasticDomain> + +export type ElasticHits = Array<ElasticHit> export type ElasticHit = { id: string title?: LangField @@ -72,4 +115,3 @@ export type ElasticHit = { domains?: ElasticDomains year?: number } -export type ElasticHits = Array<ElasticHit> From efe8348ee0d8ee61859f656daf400b2d3148ab27 Mon Sep 17 00:00:00 2001 From: Mihoub Debache <debache.mihoub@gmail.com> Date: Wed, 27 Mar 2024 11:49:39 +0100 Subject: [PATCH 10/21] fix(locales): update locales --- client/src/pages/authors/[id]/locales/de.json | 5 +- client/src/pages/authors/[id]/locales/en.json | 5 +- client/src/pages/authors/[id]/locales/es.json | 5 +- client/src/pages/authors/[id]/locales/fr.json | 5 +- .../publications/publication-item.tsx | 89 ++++++++++----- client/src/pages/search/locales/de.json | 3 + client/src/pages/search/locales/en.json | 3 + client/src/pages/search/locales/es.json | 3 + client/src/pages/search/locales/fr.json | 3 + client/src/pages/suggest/item.tsx | 105 +++++++++++++----- 10 files changed, 168 insertions(+), 58 deletions(-) diff --git a/client/src/pages/authors/[id]/locales/de.json b/client/src/pages/authors/[id]/locales/de.json index 6e33fec3..eca9ef4f 100644 --- a/client/src/pages/authors/[id]/locales/de.json +++ b/client/src/pages/authors/[id]/locales/de.json @@ -28,5 +28,8 @@ "authors.section.recent-affiliations.between": "zwischen {min} und {max}", "authors.section.recent-affiliations.title": "Aktuelle Zugehörigkeiten", "authors.section.recent-affiliations.description": "Die hier angezeigten aktuellen Zugehörigkeiten basieren auf den in scanR aufgeführten Veröffentlichungen. Sie sind nicht erschöpfend.", - "authors.section.more-like-this": "Ähnliche Autoren" + "authors.section.more-like-this": "Ähnliche Autoren", + "search.publications.openAccess": "Offener Zugang", + "search.publications.closedAccess": "Geschlossener Zugang", + "search.publications.other": "Andere" } \ No newline at end of file diff --git a/client/src/pages/authors/[id]/locales/en.json b/client/src/pages/authors/[id]/locales/en.json index a8f6d2c3..aad02cbf 100644 --- a/client/src/pages/authors/[id]/locales/en.json +++ b/client/src/pages/authors/[id]/locales/en.json @@ -28,5 +28,8 @@ "authors.section.recent-affiliations.between": "between {min} and {max}", "authors.section.recent-affiliations.title": "Recent Affiliations", "authors.section.recent-affiliations.description": "The recent affiliations presented here are based on publications listed in scanR. They are not exhaustive.", - "authors.section.more-like-this": "Similar Authors" + "authors.section.more-like-this": "Similar Authors", + "search.publications.openAccess": "Open access", + "search.publications.closedAccess": "Closed access", + "search.publications.other": "Other" } \ No newline at end of file diff --git a/client/src/pages/authors/[id]/locales/es.json b/client/src/pages/authors/[id]/locales/es.json index 2a1f10c3..a87d780c 100644 --- a/client/src/pages/authors/[id]/locales/es.json +++ b/client/src/pages/authors/[id]/locales/es.json @@ -28,5 +28,8 @@ "authors.section.recent-affiliations.between": "entre {min} y {max}", "authors.section.recent-affiliations.title": "Afiliaciones recientes", "authors.section.recent-affiliations.description": "Las afiliaciones recientes mostradas aquí se basan en las publicaciones listadas en scanR. No son exhaustivas.", - "authors.section.more-like-this": "Autores similares" + "authors.section.more-like-this": "Autores similares", + "search.publications.openAccess": "Acceso abierto", + "search.publications.closedAccess": "Acceso cerrado", + "search.publications.other": "Otro" } \ No newline at end of file diff --git a/client/src/pages/authors/[id]/locales/fr.json b/client/src/pages/authors/[id]/locales/fr.json index 5fcc8825..732682eb 100644 --- a/client/src/pages/authors/[id]/locales/fr.json +++ b/client/src/pages/authors/[id]/locales/fr.json @@ -28,5 +28,8 @@ "authors.section.recent-affiliations.between": "entre {min} et {max}", "authors.section.recent-affiliations.title": "Affiliations récentes", "authors.section.recent-affiliations.description": "Les affiliations récentes présentées ici sont basées sur les publications répertoriées dans scanR. Elles ne sont pas exhaustives.", - "authors.section.more-like-this": "Auteurs similaires" + "authors.section.more-like-this": "Auteurs similaires", + "search.publications.openAccess": "Accés ouvert", + "search.publications.closedAccess": "Accés fermé", + "search.publications.other": "Autre" } \ No newline at end of file diff --git a/client/src/pages/search/components/publications/publication-item.tsx b/client/src/pages/search/components/publications/publication-item.tsx index 4ee27d2a..d04d6696 100644 --- a/client/src/pages/search/components/publications/publication-item.tsx +++ b/client/src/pages/search/components/publications/publication-item.tsx @@ -5,50 +5,87 @@ import { publicationTypeMapping, encode } from "../../../../utils/string"; import { getPublicationById } from "../../../../api/publications/[id]"; import { LightPublication } from "../../../../types/publication"; import { ItemProps } from "../../types"; +import { useIntl } from "react-intl"; - -export default function PublicationItem({ data: publication, highlight }: ItemProps<LightPublication>) { +export default function PublicationItem({ + data: publication, + highlight, +}: ItemProps<LightPublication>) { const queryClient = useQueryClient(); + const intl = useIntl(); function prefetch(id: string) { if (!id) return; queryClient.prefetchQuery({ - queryKey: ['publication', id], + queryKey: ["publication", id], queryFn: () => getPublicationById(id), - }) + }); } + return ( <Fragment key={publication.id}> - <div className="result-item" key={publication.id}> + <div className="result-item"> <BadgeGroup className="fr-mt-1v"> - <Badge size="sm" color="purple-glycine" noIcon>{publicationTypeMapping[publication.type] || "Autre"}</Badge> - <Badge size="sm" color={publication.isOa ? 'green-emeraude' : 'pink-macaron'} icon={publication.isOa ? 'lock-unlock-fill' : 'lock-fill'}> - {publication.isOa ? 'Accès ouvert' : 'Accès fermé'} + <Badge size="sm" color="purple-glycine" noIcon> + {publicationTypeMapping[publication.type] || + intl.formatMessage({ id: "search.publications.other" })} + </Badge> + <Badge + size="sm" + color={publication.isOa ? "green-emeraude" : "pink-macaron"} + icon={publication.isOa ? "lock-unlock-fill" : "lock-fill"} + > + {publication.isOa + ? intl.formatMessage({ id: "search.publications.openAccess" }) + : intl.formatMessage({ id: "search.publications.closedAccess" })} </Badge> </BadgeGroup> - <span onMouseEnter={() => prefetch(publication.id)}><Link href={`/publications/${encode(publication.id)}`} className="fr-link"> - {highlight?.["title.default"] - ? (<span dangerouslySetInnerHTML={{ __html: highlight?.["title.default"] }} />) - : publication.title.default || publication.title?.fr || publication.title?.en} - </Link> + <span onMouseEnter={() => prefetch(publication.id)}> + <Link + href={`/publications/${encode(publication.id)}`} + className="fr-link" + > + {highlight?.["title.default"] ? ( + <span + dangerouslySetInnerHTML={{ + __html: highlight["title.default"], + }} + /> + ) : ( + publication.title.default || + publication.title?.fr || + publication.title?.en + )} + </Link> </span> <Text bold size="sm" className="fr-mb-0"> - {publication?.authors?.slice(0, 5).map((author, k) => ( - <Fragment key={k}> - {(k > 0) ? ', ' : ''} - {(author?.person) ? <Link href={`/authors/${encode(author.person)}`}>{author.fullName}</Link> : author.fullName} + {publication.authors.slice(0, 5).map((author, index) => ( + <Fragment key={index}> + {index > 0 && ", "} + {author.person ? ( + <Link href={`/authors/${encode(author.person)}`}> + {author.fullName} + </Link> + ) : ( + author.fullName + )} </Fragment> ))} - {publication?.authors?.length > 5 && <Text bold as="span"><i>{' '}et al.</i></Text>} + {publication.authors.length > 5 && ( + <Text bold as="span"> + <i> et al.</i> + </Text> + )} </Text> <Text size="sm" className="fr-card__detail fr-mb-0"> <i> - {publication?.source?.title && `${publication?.source?.title}`} - {publication?.source?.volume && `, ${publication.source?.volume}`} - {publication?.source?.issue && ` (${publication.source?.issue})`} - {(publication?.year && publication?.source?.title) && ", "} - {publication?.year && `${publication.year}`} - {publication?.source?.publisher && `, ${publication?.source?.publisher}`} + {publication.source?.title && `${publication.source?.title}`} + {publication.source?.volume && `, ${publication.source?.volume}`} + {publication.source?.issue && ` (${publication.source?.issue})`} + {publication.year && publication.source?.title && ", "} + {publication.year && `${publication.year}`} + {publication.source?.publisher && + `, ${publication.source?.publisher}`} </i> </Text> {Object.values(highlight || {}).map((value, i) => ( @@ -58,5 +95,5 @@ export default function PublicationItem({ data: publication, highlight }: ItemPr ))} </div> </Fragment> - ) -} \ No newline at end of file + ); +} diff --git a/client/src/pages/search/locales/de.json b/client/src/pages/search/locales/de.json index cd91223a..3a56bf6c 100644 --- a/client/src/pages/search/locales/de.json +++ b/client/src/pages/search/locales/de.json @@ -39,6 +39,9 @@ "search.filters.publications.by-type-description": "Einen oder mehrere Publikationstypen auswählen", "search.filters.publications.filters-modal-title": "Filter", "search.filters.publications.by-author": "Nach Autor filtern", + "search.publications.openAccess": "Offener Zugang", + "search.publications.closedAccess": "Geschlossener Zugang", + "search.publications.other": "Andere", "search.filters.publications.by-author-description": "Einen oder mehrere Autoren auswählen", "search.filters.publications.by-is-oa": "Open Access", "search.filters.publications.by-is-oa-label": "Nur Open-Access-Veröffentlichungen anzeigen", diff --git a/client/src/pages/search/locales/en.json b/client/src/pages/search/locales/en.json index 3e826816..c63724e2 100644 --- a/client/src/pages/search/locales/en.json +++ b/client/src/pages/search/locales/en.json @@ -39,6 +39,9 @@ "search.filters.publications.by-type-description": "Select one or more publication types", "search.filters.publications.filters-modal-title": "Filters", "search.filters.publications.by-author": "Filter by Author", + "search.publications.openAccess": "Open access", + "search.publications.closedAccess": "Closed access", + "search.publications.other": "Other", "search.filters.publications.by-author-description": "Select one or more authors", "search.filters.publications.by-is-oa": "Open Access", "search.filters.publications.by-is-oa-label": "Show only open access publications", diff --git a/client/src/pages/search/locales/es.json b/client/src/pages/search/locales/es.json index 3d8df4ad..8870b95b 100644 --- a/client/src/pages/search/locales/es.json +++ b/client/src/pages/search/locales/es.json @@ -39,6 +39,9 @@ "search.filters.publications.by-type-description": "Selecciona uno o más tipos de publicación", "search.filters.publications.filters-modal-title": "Filtros", "search.filters.publications.by-author": "Filtrar por Autor", + "search.publications.openAccess": "Acceso abierto", + "search.publications.closedAccess": "Acceso cerrado", + "search.publications.other": "Otro", "search.filters.publications.by-author-description": "Selecciona uno o más autores", "search.filters.publications.by-is-oa": "Acceso Abierto", "search.filters.publications.by-is-oa-label": "Mostrar solo publicaciones de acceso abierto", diff --git a/client/src/pages/search/locales/fr.json b/client/src/pages/search/locales/fr.json index f3da9ca9..b08efab6 100644 --- a/client/src/pages/search/locales/fr.json +++ b/client/src/pages/search/locales/fr.json @@ -39,6 +39,9 @@ "search.filters.publications.by-type-description": "Sélectionnez un ou plusieurs types de publications", "search.filters.publications.filters-modal-title": "Filtres", "search.filters.publications.by-author": "Filtrer par auteur", + "search.publications.openAccess": "Accès ouvert", + "search.publications.closedAccess": "Accès fermé", + "search.publications.other": "Autre", "search.filters.publications.by-author-description": "Sélectionnez un ou plusieurs auteurs", "search.filters.publications.by-is-oa": "Accès ouvert", "search.filters.publications.by-is-oa-label": "Afficher uniquement les publications en accès ouvert", diff --git a/client/src/pages/suggest/item.tsx b/client/src/pages/suggest/item.tsx index 883afd0b..017c9f80 100644 --- a/client/src/pages/suggest/item.tsx +++ b/client/src/pages/suggest/item.tsx @@ -1,5 +1,12 @@ import { Fragment } from "react"; -import { BadgeGroup, Badge, Text, Link, ButtonGroup, Button } from "@dataesr/dsfr-plus"; +import { + BadgeGroup, + Badge, + Text, + Link, + ButtonGroup, + Button, +} from "@dataesr/dsfr-plus"; import { publicationTypeMapping, encode } from "../../utils/string"; import { LightPublication } from "../../types/publication"; import { useIntl } from "react-intl"; @@ -9,55 +16,81 @@ export type AddItemProps<T> = { highlight?: Record<string, string[]>; addItem?: (item: T) => void; disabled: boolean; -} +}; export type RemoveItemProps<T> = { data: T; removeItem?: (item: T) => void; -} +}; -export function SuggestionAddItem({ data: publication, highlight, addItem, disabled }: AddItemProps<LightPublication>) { +export function SuggestionAddItem({ + data: publication, + highlight, + addItem, + disabled, +}: AddItemProps<LightPublication>) { const intl = useIntl(); return ( <div className="result-item" key={publication.id}> <BadgeGroup className="fr-mt-1v"> - <Badge size="sm" color="purple-glycine" noIcon>{publicationTypeMapping[publication.type] || "Autre"}</Badge> - <Badge size="sm" color={publication.isOa ? 'green-emeraude' : 'pink-macaron'} icon={publication.isOa ? 'lock-unlock-fill' : 'lock-fill'}> - {publication.isOa ? 'Accès ouvert' : 'Accès fermé'} + <Badge size="sm" color="purple-glycine" noIcon> + {publicationTypeMapping[publication.type] || + intl.formatMessage({ id: "search.publications.other" })} + </Badge> + <Badge + size="sm" + color={publication.isOa ? "green-emeraude" : "pink-macaron"} + icon={publication.isOa ? "lock-unlock-fill" : "lock-fill"} + > + {publication.isOa + ? intl.formatMessage({ id: "search.publications.openAccess" }) + : intl.formatMessage({ id: "search.publications.closedAccess" })} </Badge> </BadgeGroup> <Text bold className="fr-mb-0"> - {publication.title.default || publication.title?.fr || publication.title?.en} + {publication.title.default || + publication.title?.fr || + publication.title?.en} </Text> <Text bold size="sm" className="fr-mb-0"> {publication?.authors?.slice(0, 5).map((author, k) => ( <Fragment key={k}> - {(k > 0) ? ', ' : ''} + {k > 0 ? ", " : ""} {author.fullName} </Fragment> ))} - {publication?.authors?.length > 5 && <Text bold as="span"><i>{' '}et al.</i></Text>} + {publication?.authors?.length > 5 && ( + <Text bold as="span"> + <i> et al.</i> + </Text> + )} </Text> <Text size="sm" className="fr-card__detail fr-mb-0"> <i> {publication?.source?.title && `${publication?.source?.title}`} {publication?.source?.volume && `, ${publication.source?.volume}`} {publication?.source?.issue && ` (${publication.source?.issue})`} - {(publication?.year && publication?.source?.title) && ", "} + {publication?.year && publication?.source?.title && ", "} {publication?.year && `${publication.year}`} - {publication?.source?.publisher && `, ${publication?.source?.publisher}`} + {publication?.source?.publisher && + `, ${publication?.source?.publisher}`} </i> </Text> {highlight?.["domains.label.default"] && ( <Text size="sm" className="fr-mb-0"> - Mots clés: - {' '} - <span dangerouslySetInnerHTML={{ __html: highlight?.["domains.label.default"] }} /> + Mots clés:{" "} + <span + dangerouslySetInnerHTML={{ + __html: highlight?.["domains.label.default"], + }} + /> </Text> )} {highlight?.["summary.default"] && ( <Text size="sm" className="fr-mb-0"> ... - <span dangerouslySetInnerHTML={{ __html: highlight?.["summary.default"] }} /> + <span + dangerouslySetInnerHTML={{ __html: highlight?.["summary.default"] }} + /> ... </Text> )} @@ -69,37 +102,53 @@ export function SuggestionAddItem({ data: publication, highlight, addItem, disab iconPosition="right" disabled={disabled} > - {intl.formatMessage({ id: 'suggest.items.add' })} + {intl.formatMessage({ id: "suggest.items.add" })} </Button> </ButtonGroup> </div> - ) + ); } -export function SuggestionRemoveItem({ data: publication, removeItem }: RemoveItemProps<LightPublication>) { +export function SuggestionRemoveItem({ + data: publication, + removeItem, +}: RemoveItemProps<LightPublication>) { const intl = useIntl(); return ( <div> <div className="result-item" key={publication.id}> <Text bold className="fr-mb-1w"> - {publication.title.default || publication.title?.fr || publication.title?.en} + {publication.title.default || + publication.title?.fr || + publication.title?.en} </Text> <Text bold size="sm" className="fr-mb-0"> {publication?.authors?.slice(0, 5).map((author, k) => ( <Fragment key={k}> - {(k > 0) ? ', ' : ''} - {(author?.person) ? <Link href={`/authors/${encode(author.person)}`}>{author.fullName}</Link> : author.fullName} + {k > 0 ? ", " : ""} + {author?.person ? ( + <Link href={`/authors/${encode(author.person)}`}> + {author.fullName} + </Link> + ) : ( + author.fullName + )} </Fragment> ))} - {publication?.authors?.length > 5 && <Text bold as="span"><i>{' '}et al.</i></Text>} + {publication?.authors?.length > 5 && ( + <Text bold as="span"> + <i> et al.</i> + </Text> + )} </Text> <Text size="sm" className="fr-card__detail fr-mb-0"> <i> {publication?.source?.title && `${publication?.source?.title}`} {publication?.source?.volume && `, ${publication.source?.volume}`} {publication?.source?.issue && ` (${publication.source?.issue})`} - {(publication?.year && publication?.source?.title) && ", "} + {publication?.year && publication?.source?.title && ", "} {publication?.year && `${publication.year}`} - {publication?.source?.publisher && `, ${publication?.source?.publisher}`} + {publication?.source?.publisher && + `, ${publication?.source?.publisher}`} </i> </Text> </div> @@ -111,9 +160,9 @@ export function SuggestionRemoveItem({ data: publication, removeItem }: RemoveIt icon="delete-bin-line" iconPosition="right" > - {intl.formatMessage({ id: 'suggest.items.remove' })} + {intl.formatMessage({ id: "suggest.items.remove" })} </Button> </ButtonGroup> </div> - ) -} \ No newline at end of file + ); +} From d1a46f0138c978a3fbc2f339f2a50aa536756481 Mon Sep 17 00:00:00 2001 From: folland87 <frederic@olland.me> Date: Wed, 27 Mar 2024 11:40:55 +0100 Subject: [PATCH 11/21] add domains.label to morePublicationsLikethis query --- client/src/api/publications/more-like-this/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/api/publications/more-like-this/index.ts b/client/src/api/publications/more-like-this/index.ts index b2515a78..9791eb1b 100644 --- a/client/src/api/publications/more-like-this/index.ts +++ b/client/src/api/publications/more-like-this/index.ts @@ -8,7 +8,7 @@ export async function getMorePublicationsLikeThis(id: string) { size: 3, query: { more_like_this: { - fields: ["title.default"], + fields: ["title.default", "domains.label.*"], like: [{ _id: id }], min_term_freq: 1, max_query_terms: 12, From 69d4cbfb1345aa1071bf6e771311798476b9e5ab Mon Sep 17 00:00:00 2001 From: folland87 <frederic@olland.me> Date: Wed, 27 Mar 2024 11:41:11 +0100 Subject: [PATCH 12/21] tooltip fix on softwares --- .../src/pages/publications/[id]/components/softwares/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/pages/publications/[id]/components/softwares/index.tsx b/client/src/pages/publications/[id]/components/softwares/index.tsx index b04abbb4..c4cae6ed 100644 --- a/client/src/pages/publications/[id]/components/softwares/index.tsx +++ b/client/src/pages/publications/[id]/components/softwares/index.tsx @@ -49,7 +49,7 @@ export default function Softwares({ softwares }: { softwares: SoftwareMention[] <div key={software.id_name}> <Text size="lg" className="fr-mb-0" bold> {software.softwareName} - {software?.wiki?.code && <button className="fr-btn--tooltip fr-ml-1v" aria-describedby={`software-${software.wiki.code}`}>Wikipedia</button>} + {software?.wiki?.code && <span className="pointer fr-icon-information-line fr-text-default--info fr-icon--sm fr-ml-1v fr-text-mention--grey" aria-describedby={`software-${software.wiki.code}`} />} </Text> {software?.wiki?.code && ( <Fragment key={software.wiki.code}> From fd49cd7e0ad1aea40dacd003261322d1ba640c27 Mon Sep 17 00:00:00 2001 From: Mihoub Debache <debache.mihoub@gmail.com> Date: Wed, 27 Mar 2024 12:05:46 +0100 Subject: [PATCH 13/21] typo and hide empty pages from footer --- client/src/layout/components/footer/index.tsx | 28 +++++++++++++++---- client/src/pages/authors/[id]/locales/de.json | 3 +- client/src/pages/authors/[id]/locales/en.json | 3 +- client/src/pages/authors/[id]/locales/es.json | 3 +- client/src/pages/authors/[id]/locales/fr.json | 1 + .../components/authors/filters/awards.tsx | 1 + 6 files changed, 30 insertions(+), 9 deletions(-) diff --git a/client/src/layout/components/footer/index.tsx b/client/src/layout/components/footer/index.tsx index 4a46835f..8758a1e3 100644 --- a/client/src/layout/components/footer/index.tsx +++ b/client/src/layout/components/footer/index.tsx @@ -1,17 +1,33 @@ import cn from "classnames"; -import { Col, Container, Link, Logo, Row, Title, useDSFRConfig } from "@dataesr/dsfr-plus"; -import { Footer, FooterBody, FooterBottom, FooterTop } from "../../../components/footer"; +import { + Col, + Container, + Link, + Logo, + Row, + Title, + useDSFRConfig, +} from "@dataesr/dsfr-plus"; +import { + Footer, + FooterBody, + FooterBottom, + FooterTop, +} from "../../../components/footer"; import { RawIntlProvider, createIntl } from "react-intl"; import SwitchTheme from "../switch-theme"; import useConsent from "../../../hooks/useConsent"; import { version } from "react"; import styles from "./styles.module.scss"; -const modules = import.meta.glob('./locales/*.json', { eager: true, import: 'default' }) +const modules = import.meta.glob("./locales/*.json", { + eager: true, + import: "default", +}); const messages = Object.keys(modules).reduce((acc, key) => { const locale = key.match(/\.\/locales\/(.+)\.json$/)?.[1]; if (locale) { - return { ...acc, [locale]: modules[key] } + return { ...acc, [locale]: modules[key] }; } return acc; }, {}); @@ -261,7 +277,7 @@ export default function MainFooter() { </Link> </FooterBody> <FooterBottom> - <Link className="fr-footer__bottom-link" href="#"> + {/* <Link className="fr-footer__bottom-link" href="#"> {intl.formatMessage({ id: "layout.footer.legal-notice", })} @@ -275,7 +291,7 @@ export default function MainFooter() { {intl.formatMessage({ id: "layout.footer.accessibility", })} - </Link> + </Link> */} <button className="fr-footer__bottom-link" data-fr-opened="false" diff --git a/client/src/pages/authors/[id]/locales/de.json b/client/src/pages/authors/[id]/locales/de.json index eca9ef4f..ae47227d 100644 --- a/client/src/pages/authors/[id]/locales/de.json +++ b/client/src/pages/authors/[id]/locales/de.json @@ -31,5 +31,6 @@ "authors.section.more-like-this": "Ähnliche Autoren", "search.publications.openAccess": "Offener Zugang", "search.publications.closedAccess": "Geschlossener Zugang", - "search.publications.other": "Andere" + "search.publications.other": "Andere", + "search.section.author.badge": "Autor" } \ No newline at end of file diff --git a/client/src/pages/authors/[id]/locales/en.json b/client/src/pages/authors/[id]/locales/en.json index aad02cbf..ca86acf0 100644 --- a/client/src/pages/authors/[id]/locales/en.json +++ b/client/src/pages/authors/[id]/locales/en.json @@ -31,5 +31,6 @@ "authors.section.more-like-this": "Similar Authors", "search.publications.openAccess": "Open access", "search.publications.closedAccess": "Closed access", - "search.publications.other": "Other" + "search.publications.other": "Other", + "search.section.author.badge": "Author" } \ No newline at end of file diff --git a/client/src/pages/authors/[id]/locales/es.json b/client/src/pages/authors/[id]/locales/es.json index a87d780c..1f9f51fb 100644 --- a/client/src/pages/authors/[id]/locales/es.json +++ b/client/src/pages/authors/[id]/locales/es.json @@ -31,5 +31,6 @@ "authors.section.more-like-this": "Autores similares", "search.publications.openAccess": "Acceso abierto", "search.publications.closedAccess": "Acceso cerrado", - "search.publications.other": "Otro" + "search.publications.other": "Otro", + "search.section.author.badge": "Autor" } \ No newline at end of file diff --git a/client/src/pages/authors/[id]/locales/fr.json b/client/src/pages/authors/[id]/locales/fr.json index 732682eb..98afd487 100644 --- a/client/src/pages/authors/[id]/locales/fr.json +++ b/client/src/pages/authors/[id]/locales/fr.json @@ -23,6 +23,7 @@ "authors.section.reviews.title": "Principales revues", "authors.section.reviews.desc": "Cliquez pour rechercher des publications de la revue", "authors.section.share": "Partager la page", + "search.section.author.badge": "Auteur", "authors.section.contribute.title": "Contribuer", "authors.section.recent-affiliations.publication-count": "{count, plural, one {# publication} other {# publications}}", "authors.section.recent-affiliations.between": "entre {min} et {max}", diff --git a/client/src/pages/search/components/authors/filters/awards.tsx b/client/src/pages/search/components/authors/filters/awards.tsx index e7d047ab..28576fe5 100644 --- a/client/src/pages/search/components/authors/filters/awards.tsx +++ b/client/src/pages/search/components/authors/filters/awards.tsx @@ -48,6 +48,7 @@ export default function AuthorAwardsFilter() { /> </div> <TextInput + disableAutoValidation value={searchInput} onChange={(e) => setSearchInput(e.target.value)} placeholder={intl.formatMessage({ id: "search.filters.search-tags" })} From eba50df454730509fa6aa9504ecf5174dad385ec Mon Sep 17 00:00:00 2001 From: Mihoub Debache <debache.mihoub@gmail.com> Date: Wed, 27 Mar 2024 14:14:51 +0100 Subject: [PATCH 14/21] typo --- client/src/pages/publications/[id]/locales/fr.json | 3 +++ .../pages/search/components/publications/publication-item.tsx | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/client/src/pages/publications/[id]/locales/fr.json b/client/src/pages/publications/[id]/locales/fr.json index 1a1e0281..ad8ce030 100644 --- a/client/src/pages/publications/[id]/locales/fr.json +++ b/client/src/pages/publications/[id]/locales/fr.json @@ -24,6 +24,9 @@ "publications.section.jury.membrejury": "Membre du jury", "publications.header.thesis.by": "par ", "publications.header.thesis.and": " et ", + "search.publications.openAccess": "Accès ouvert", + "search.publications.closedAccess": "Accès fermé", + "search.publications.other": "Autre", "publications.header.thesis.directed": " sous la direction de ", "publications.header.thesis.date": "soutenue le {date}", "publications.header.thesis.year": "soutenue en {year}", diff --git a/client/src/pages/search/components/publications/publication-item.tsx b/client/src/pages/search/components/publications/publication-item.tsx index d04d6696..9aa42cb7 100644 --- a/client/src/pages/search/components/publications/publication-item.tsx +++ b/client/src/pages/search/components/publications/publication-item.tsx @@ -59,7 +59,7 @@ export default function PublicationItem({ </Link> </span> <Text bold size="sm" className="fr-mb-0"> - {publication.authors.slice(0, 5).map((author, index) => ( + {publication?.authors?.slice(0, 5).map((author, index) => ( <Fragment key={index}> {index > 0 && ", "} {author.person ? ( @@ -71,7 +71,7 @@ export default function PublicationItem({ )} </Fragment> ))} - {publication.authors.length > 5 && ( + {publication?.authors?.length > 5 && ( <Text bold as="span"> <i> et al.</i> </Text> From d19028f767cc65d1ab97e2a73e249a21e5eebd75 Mon Sep 17 00:00:00 2001 From: Mihoub Debache <debache.mihoub@gmail.com> Date: Wed, 27 Mar 2024 14:16:26 +0100 Subject: [PATCH 15/21] typo --- client/src/pages/authors/[id]/locales/fr.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/pages/authors/[id]/locales/fr.json b/client/src/pages/authors/[id]/locales/fr.json index 98afd487..620436dc 100644 --- a/client/src/pages/authors/[id]/locales/fr.json +++ b/client/src/pages/authors/[id]/locales/fr.json @@ -30,7 +30,7 @@ "authors.section.recent-affiliations.title": "Affiliations récentes", "authors.section.recent-affiliations.description": "Les affiliations récentes présentées ici sont basées sur les publications répertoriées dans scanR. Elles ne sont pas exhaustives.", "authors.section.more-like-this": "Auteurs similaires", - "search.publications.openAccess": "Accés ouvert", - "search.publications.closedAccess": "Accés fermé", + "search.publications.openAccess": "Accès ouvert", + "search.publications.closedAccess": "Accès fermé", "search.publications.other": "Autre" } \ No newline at end of file From bf09cfd9c8a6614a07cc3565d04c9db3e42703e9 Mon Sep 17 00:00:00 2001 From: Mihoub Debache <debache.mihoub@gmail.com> Date: Wed, 27 Mar 2024 14:17:35 +0100 Subject: [PATCH 16/21] typo --- client/src/components/share/locales/fr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/share/locales/fr.json b/client/src/components/share/locales/fr.json index 49bcb74c..11470864 100644 --- a/client/src/components/share/locales/fr.json +++ b/client/src/components/share/locales/fr.json @@ -6,5 +6,5 @@ "share.copy": "Copier dans le presse-papier", "share.inactive": "- désactivé", "share.cookies": "Personnaliser les cookies", - "share.cookies.personalize": "Veuillez <authorize>autoriser le dépot de cookies</authorize> pour partager sur Facebook, Twitter et LinkedIn." + "share.cookies.personalize": "Veuillez <authorize>autoriser le dépôt de cookies</authorize> pour partager sur Facebook, Twitter et LinkedIn." } \ No newline at end of file From d0c087342b94e144de68a360639b2378a615c715 Mon Sep 17 00:00:00 2001 From: folland87 <frederic@olland.me> Date: Wed, 27 Mar 2024 14:45:32 +0100 Subject: [PATCH 17/21] typos --- client/src/pages/authors/[id]/locales/fr.json | 2 +- client/src/pages/search/index.tsx | 6 +++++- client/src/pages/search/locales/de.json | 11 ++++++----- client/src/pages/search/locales/en.json | 11 ++++++----- client/src/pages/search/locales/es.json | 11 ++++++----- client/src/pages/search/locales/fr.json | 11 ++++++----- 6 files changed, 30 insertions(+), 22 deletions(-) diff --git a/client/src/pages/authors/[id]/locales/fr.json b/client/src/pages/authors/[id]/locales/fr.json index 620436dc..e9a4aac9 100644 --- a/client/src/pages/authors/[id]/locales/fr.json +++ b/client/src/pages/authors/[id]/locales/fr.json @@ -7,7 +7,7 @@ "authors.section.prizes": "Prix et distinctions", "authors.section.activity": "Activité de recherche", "authors.section.activity.thesis": "{count, plural, one {Thèse} other {# Thèses}} de l'auteur", - "authors.section.activity.thesis-participations": "Participation{count, plural, one { à un} other {s à des}} jury de thèse{count, plural, one {} other { (#)}}", + "authors.section.activity.thesis-participations": "Participation{count, plural, one { à un jury} other {s à des jurys}} de thèse{count, plural, one {} other { (#)}}", "authors.section.activity.publications": "{count, plural, one {# publication} other {Dernières publications (#)}}", "authors.section.activity.open-modal-button": "Voir la liste complète", "authors.signals.publications": "Lier des publications", diff --git a/client/src/pages/search/index.tsx b/client/src/pages/search/index.tsx index 1ef9f696..43bdceb2 100644 --- a/client/src/pages/search/index.tsx +++ b/client/src/pages/search/index.tsx @@ -168,7 +168,11 @@ export default function Search() { <Text as="span" size="xs" className="fr-text-mention--grey"> {intl.formatMessage( { id: `search.top.${api}.result` }, - { count: total, query: currentQuery } + { count: total } + )} + {currentQuery && intl.formatMessage( + { id: "search.top.result-for-query" }, + { query: currentQuery } )} </Text> ) : isFetchingNextPage ? ( diff --git a/client/src/pages/search/locales/de.json b/client/src/pages/search/locales/de.json index 3a56bf6c..8df6c66c 100644 --- a/client/src/pages/search/locales/de.json +++ b/client/src/pages/search/locales/de.json @@ -20,11 +20,12 @@ "search.filters.publications.active-filter-title": "Aktive Filter", "search.filters.publications.active-filter-empty": "Keine aktiven Filter", "search.top.result-more-than": "Mehr als ", - "search.top.publications.result": "{count, plural, =0 {# Veröffentlichung} one {# Veröffentlichung} other {# Veröffentlichungen}} für Suchbegriff « {query} »", - "search.top.authors.result": "{count, plural, =0 {# Autor} one {# Autor} other {# Autoren}} für Suchbegriff « {query} »", - "search.top.organizations.result": "{count, plural, =0 {# Organisation} one {# Organisation} other {# Organisationen}} für Suchbegriff « {query} »", - "search.top.projects.result": "{count, plural, =0 {# Finanzierung} one {# Finanzierung} other {# Finanzierungen}} für Suchbegriff « {query} »", - "search.top.patents.result": "{count, plural, =0 {# Patent} one {# Patent} other {# Patente}} für Suchbegriff « {query} »", + "search.top.result-for-query": " für Suchbegriff « {query} »", + "search.top.publications.result": "{count, plural, =0 {# Veröffentlichung} one {# Veröffentlichung} other {# Veröffentlichungen}}", + "search.top.authors.result": "{count, plural, =0 {# Autor} one {# Autor} other {# Autoren}}", + "search.top.organizations.result": "{count, plural, =0 {# Organisation} one {# Organisation} other {# Organisationen}}", + "search.top.projects.result": "{count, plural, =0 {# Finanzierung} one {# Finanzierung} other {# Finanzierungen}}", + "search.top.patents.result": "{count, plural, =0 {# Patent} one {# Patent} other {# Patente}}", "search.top.publications.filters.result-count": "{count, plural, =0 {# Veröffentlichung} one {# Veröffentlichung} other {# Veröffentlichungen}}", "search.top.organizations.filters.result-count": "{count, plural, =0 {# Organisationen} one {# Organisation} other {# Organisationen}}", "search.top.projects.filters.result-count": "{count, plural, =0 {# Finanzierungen} one {# Finanzierung} other {# Finanzierungen}}", diff --git a/client/src/pages/search/locales/en.json b/client/src/pages/search/locales/en.json index c63724e2..85bbd824 100644 --- a/client/src/pages/search/locales/en.json +++ b/client/src/pages/search/locales/en.json @@ -20,11 +20,12 @@ "search.filters.publications.active-filter-title": "Active Filters", "search.filters.publications.active-filter-empty": "No active filters", "search.top.result-more-than": "More than ", - "search.top.publications.result": "{count, plural, =0 {# publication} one {# publication} other {# publications}} for search term « {query} »", - "search.top.authors.result": "{count, plural, =0 {# author} one {# author} other {# authors}} for search term « {query} »", - "search.top.organizations.result": "{count, plural, =0 {# organization} one {# organization} other {# organizations}} for search term « {query} »", - "search.top.projects.result": "{count, plural, =0 {# funding} one {# funding} other {# fundings}} for search term « {query} »", - "search.top.patents.result": "{count, plural, =0 {# patent} one {# patent} other {# patents}} for search term « {query} »", + "search.top.result-for-query": " for search term « {query} »", + "search.top.publications.result": "{count, plural, =0 {# publication} one {# publication} other {# publications}}", + "search.top.authors.result": "{count, plural, =0 {# author} one {# author} other {# authors}}", + "search.top.organizations.result": "{count, plural, =0 {# organization} one {# organization} other {# organizations}}", + "search.top.projects.result": "{count, plural, =0 {# funding} one {# funding} other {# fundings}}", + "search.top.patents.result": "{count, plural, =0 {# patent} one {# patent} other {# patents}}", "search.top.publications.filters.result-count": "{count, plural, =0 {# publication} one {# publication} other {# publications}}", "search.top.organizations.filters.result-count": "{count, plural, =0 {# organizations} one {# organization} other {# organizations}}", "search.top.projects.filters.result-count": "{count, plural, =0 {# fundings} one {# funding} other {# fundings}}", diff --git a/client/src/pages/search/locales/es.json b/client/src/pages/search/locales/es.json index 8870b95b..45420331 100644 --- a/client/src/pages/search/locales/es.json +++ b/client/src/pages/search/locales/es.json @@ -20,11 +20,12 @@ "search.filters.publications.active-filter-title": "Filtros Activos", "search.filters.publications.active-filter-empty": "Sin filtros activos", "search.top.result-more-than": "Más de ", - "search.top.publications.result": "{count, plural, =0 {# publicación} one {# publicación} other {# publicaciones}} para el término de búsqueda « {query} »", - "search.top.authors.result": "{count, plural, =0 {# autor} one {# autor} other {# autores}} para el término de búsqueda « {query} »", - "search.top.organizations.result": "{count, plural, =0 {# organización} one {# organización} other {# organizaciones}} para el término de búsqueda « {query} »", - "search.top.projects.result": "{count, plural, =0 {# financiamiento} one {# financiamiento} other {# financiamientos}} para el término de búsqueda « {query} »", - "search.top.patents.result": "{count, plural, =0 {# patente} one {# patente} other {# patentes}} para el término de búsqueda « {query} »", + "search.top.result-for-query": " para el término de búsqueda « {query} »", + "search.top.publications.result": "{count, plural, =0 {# publicación} one {# publicación} other {# publicaciones}}", + "search.top.authors.result": "{count, plural, =0 {# autor} one {# autor} other {# autores}}", + "search.top.organizations.result": "{count, plural, =0 {# organización} one {# organización} other {# organizaciones}}", + "search.top.projects.result": "{count, plural, =0 {# financiamiento} one {# financiamiento} other {# financiamientos}}", + "search.top.patents.result": "{count, plural, =0 {# patente} one {# patente} other {# patentes}}", "search.top.publications.filters.result-count": "{count, plural, =0 {# publicación} one {# publicación} other {# publicaciones}}", "search.top.organizations.filters.result-count": "{count, plural, =0 {# organizaciones} one {# organización} other {# organizaciones}}", "search.top.projects.filters.result-count": "{count, plural, =0 {# financiamientos} one {# financiamiento} other {# financiamientos}}", diff --git a/client/src/pages/search/locales/fr.json b/client/src/pages/search/locales/fr.json index b08efab6..da0f8e41 100644 --- a/client/src/pages/search/locales/fr.json +++ b/client/src/pages/search/locales/fr.json @@ -20,11 +20,12 @@ "search.filters.publications.active-filter-title": "Filtres actifs", "search.filters.publications.active-filter-empty": "Aucun filtre actif", "search.top.result-more-than": "Plus de ", - "search.top.publications.result": "{count, plural, =0 {# publication} one {# publication} other {# publications}} pour la recherche « {query} »", - "search.top.authors.result": "{count, plural, =0 {# auteur} one {# auteur} other {# auteurs}} pour la recherche « {query} »", - "search.top.organizations.result": "{count, plural, =0 {# structure} one {# structure} other {# structures}} pour la recherche « {query} »", - "search.top.projects.result": "{count, plural, =0 {# financements} one {# financement} other {# financements}} pour la recherche « {query} »", - "search.top.patents.result": "{count, plural, =0 {# brevets} one {# brevet} other {# brevets}} pour la recherche « {query} »", + "search.top.result-for-query": " pour la recherche « {query} »", + "search.top.publications.result": "{count, plural, =0 {# publication} one {# publication} other {# publications}}", + "search.top.authors.result": "{count, plural, =0 {# auteur} one {# auteur} other {# auteurs}}", + "search.top.organizations.result": "{count, plural, =0 {# structure} one {# structure} other {# structures}}", + "search.top.projects.result": "{count, plural, =0 {# financements} one {# financement} other {# financements}}", + "search.top.patents.result": "{count, plural, =0 {# brevets} one {# brevet} other {# brevets}}", "search.top.publications.filters.result-count": "{count, plural, =0 {# publication} one {# publication} other {# publications}}", "search.top.organizations.filters.result-count": "{count, plural, =0 {# structures} one {# structure} other {# structures}}", "search.top.projects.filters.result-count": "{count, plural, =0 {# financements} one {# financements} other {# financements}}", From 417ecd4f602fce2d79481aa7a47bf71da2179688 Mon Sep 17 00:00:00 2001 From: folland87 <frederic@olland.me> Date: Wed, 27 Mar 2024 15:18:39 +0100 Subject: [PATCH 18/21] typo --- client/src/components/contact-form/locales/fr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/contact-form/locales/fr.json b/client/src/components/contact-form/locales/fr.json index 39fde7cb..fcc3990c 100644 --- a/client/src/components/contact-form/locales/fr.json +++ b/client/src/components/contact-form/locales/fr.json @@ -6,7 +6,7 @@ "contact.error.retry": "Réessayer", "contact.form.name": "Votre nom et prénom", "contact.form.email": "Renseignez votre email", - "contact.form.email.hint": "Cet email sera utilisé que pour vous informer de la prise en compte de votre contribution.", + "contact.form.email.hint": "Cet email ne sera utilisé que pour vous informer de la prise en compte de votre contribution.", "contact.form.organization": "Votre organisation", "contact.form.fonction": "Votre fonction", "contact.form.position": "Votre fonction", From cf10ec981d1e672cfe9a655716221867d18e205f Mon Sep 17 00:00:00 2001 From: folland87 <frederic@olland.me> Date: Wed, 27 Mar 2024 15:37:28 +0100 Subject: [PATCH 19/21] more typos --- client/src/layout/components/footer/locales/fr.json | 2 +- client/src/layout/components/header/locales/fr.json | 2 +- client/src/pages/home/index.tsx | 8 ++++++++ client/src/pages/home/locales/fr.json | 2 +- client/src/pages/search/locales/de.json | 2 +- client/src/pages/search/locales/en.json | 2 +- client/src/pages/search/locales/es.json | 2 +- client/src/pages/search/locales/fr.json | 10 +++++----- 8 files changed, 19 insertions(+), 11 deletions(-) diff --git a/client/src/layout/components/footer/locales/fr.json b/client/src/layout/components/footer/locales/fr.json index b05681e8..87f24d5b 100644 --- a/client/src/layout/components/footer/locales/fr.json +++ b/client/src/layout/components/footer/locales/fr.json @@ -9,7 +9,7 @@ "layout.footer.top.about.tutorial": "Tutoriel", "layout.footer.top.about.glossary": "Glossaire", "layout.footer.top.about.contact": "Contact", - "layout.footer.tagline": "Explorez le monde de la Recherche et de l'Innovation française avec scanR", + "layout.footer.tagline": "Explorez le monde de la Recherche et de l'Innovation françaises", "layout.footer.legal-notice": "Mentions légales", "layout.footer.personal-data": "Données personnelles", "layout.footer.cookies": "Cookies", diff --git a/client/src/layout/components/header/locales/fr.json b/client/src/layout/components/header/locales/fr.json index 983d23d9..8af52d92 100644 --- a/client/src/layout/components/header/locales/fr.json +++ b/client/src/layout/components/header/locales/fr.json @@ -1,6 +1,6 @@ { "layout.header.nav.home": "Accueil", - "layout.header.tagline": "Explorer le monde de la Recherche et de l'Innovation française", + "layout.header.tagline": "Explorer le monde de la Recherche et de l'Innovation françaises", "layout.header.switch-theme": "Paramètres d'affichage", "layout.header.nav.search": "Rechercher", "layout.header.nav.search.organizations": "Structures", diff --git a/client/src/pages/home/index.tsx b/client/src/pages/home/index.tsx index 6b005288..66b13122 100644 --- a/client/src/pages/home/index.tsx +++ b/client/src/pages/home/index.tsx @@ -317,6 +317,8 @@ function ServicesBanner() { as="a" variant="secondary" href="https://barometredelascienceouverte.esr.gouv.fr/" + target="_blank" + rel="noreferrer noopener" > {intl.formatMessage({ id: "home.services.barometre.link", @@ -355,6 +357,8 @@ function ServicesBanner() { as="a" variant="secondary" href="https://curiexplore.enseignementsup-recherche.gouv.fr/" + target="_blank" + rel="noreferrer noopener" > {intl.formatMessage({ id: "home.services.curie.link" })} </Button> @@ -393,6 +397,8 @@ function ServicesBanner() { as="a" variant="secondary" href="https://data.esr.gouv.fr/FR/" + target="_blank" + rel="noreferrer noopener" > {intl.formatMessage({ id: "home.services.dataesr.link" })} </Button> @@ -424,6 +430,8 @@ function OpendataBanner() { as="a" variant="secondary" href="https://data.esr.gouv.fr/FR/" + target="_blank" + rel="noreferrer noopener" > {intl.formatMessage({ id: "home.opendata.link" })} </Button> diff --git a/client/src/pages/home/locales/fr.json b/client/src/pages/home/locales/fr.json index 43f73424..cea6080a 100644 --- a/client/src/pages/home/locales/fr.json +++ b/client/src/pages/home/locales/fr.json @@ -1,5 +1,5 @@ { - "home.title": "Explorez le monde de la Recherche <br></br> et de l'Innovation française avec scanR", + "home.title": "Explorez le monde de la Recherche <br></br> et de l'Innovation françaises avec scanR", "home.objects.title": "Explorer les données publiques de la recherche et de l'innovation françaises...", "home.objects.organizations": "Structures", "home.objects.publications": "Publications", diff --git a/client/src/pages/search/locales/de.json b/client/src/pages/search/locales/de.json index 8df6c66c..e8b32006 100644 --- a/client/src/pages/search/locales/de.json +++ b/client/src/pages/search/locales/de.json @@ -132,7 +132,7 @@ "search.results.pagination.next": "Weitere Ergebnisse anzeigen", "search.results.pagination.end": "Keine weiteren Ergebnisse für die Suche « {query} »", "search.exports.title": "Ergebnisse exportieren", - "search.exports.description": "Aus Leistungsgründen exportiert scanr maximal 1000 Ergebnisse. Sie können Ihre Suche verfeinern, um einen umfassenderen Export zu erhalten.", + "search.exports.description": "Aus Leistungsgründen exportiert scanR maximal 1000 Ergebnisse. Sie können Ihre Suche verfeinern, um einen umfassenderen Export zu erhalten.", "search.exports.is-exporting": "Daten werden heruntergeladen, bitte warten...", "search.exports.csv.title": "CSV", "search.exports.csv.description": "Ergebnisse im CSV-Format exportieren", diff --git a/client/src/pages/search/locales/en.json b/client/src/pages/search/locales/en.json index 85bbd824..bc85ecd4 100644 --- a/client/src/pages/search/locales/en.json +++ b/client/src/pages/search/locales/en.json @@ -132,7 +132,7 @@ "search.results.pagination.next": "Show More Results", "search.results.pagination.end": "No additional results for search term « {query} »", "search.exports.title": "Export Results", - "search.exports.description": "For performance reasons, scanr only exports a maximum of 1000 results. You can refine your search to get a more complete export.", + "search.exports.description": "For performance reasons, scanR only exports a maximum of 1000 results. You can refine your search to get a more complete export.", "search.exports.is-exporting": "Downloading data, please wait...", "search.exports.csv.title": "CSV", "search.exports.csv.description": "Export results in CSV format", diff --git a/client/src/pages/search/locales/es.json b/client/src/pages/search/locales/es.json index 45420331..64b97b8e 100644 --- a/client/src/pages/search/locales/es.json +++ b/client/src/pages/search/locales/es.json @@ -132,7 +132,7 @@ "search.results.pagination.next": "Mostrar Más Resultados", "search.results.pagination.end": "No hay resultados adicionales para el término de búsqueda « {query} »", "search.exports.title": "Exportar Resultados", - "search.exports.description": "Por razones de rendimiento, scanr solo exporta un máximo de 1000 resultados. Puedes refinar tu búsqueda para obtener una exportación más completa.", + "search.exports.description": "Por razones de rendimiento, scanR solo exporta un máximo de 1000 resultados. Puedes refinar tu búsqueda para obtener una exportación más completa.", "search.exports.is-exporting": "Descargando datos, por favor espera...", "search.exports.csv.title": "CSV", "search.exports.csv.description": "Exportar resultados en formato CSV", diff --git a/client/src/pages/search/locales/fr.json b/client/src/pages/search/locales/fr.json index da0f8e41..1a4f857a 100644 --- a/client/src/pages/search/locales/fr.json +++ b/client/src/pages/search/locales/fr.json @@ -34,8 +34,8 @@ "search.filters.publications.by-year": "Filtrer par année", "search.filters.publications.by-year-description": "Période sélectionnée {min} - {max}", "search.filters.publications.by-year-tooltip": "Publications en {year}", - "search.filters.publications.by-project": "Filtrer par type de financements", - "search.filters.publications.by-project-description": "Sélectionnez un ou plusieurs types de financements", + "search.filters.publications.by-project": "Filtrer par type de financement", + "search.filters.publications.by-project-description": "Sélectionnez un ou plusieurs types de financement", "search.filters.publications.by-type": "Filtrer par type de publication", "search.filters.publications.by-type-description": "Sélectionnez un ou plusieurs types de publications", "search.filters.publications.filters-modal-title": "Filtres", @@ -48,8 +48,8 @@ "search.filters.publications.by-is-oa-label": "Afficher uniquement les publications en accès ouvert", "search.filters.publications.by-organization": "Filtrer par affiliation", "search.filters.publications.by-organization-description": "Sélectionnez une ou plusieurs affiliations", - "search.filters.organizations.by-project": "Filtrer par type de financements", - "search.filters.organizations.by-project-description": "Sélectionnez un ou plusieurs types de financements", + "search.filters.organizations.by-project": "Filtrer par type de financement", + "search.filters.organizations.by-project-description": "Sélectionnez un ou plusieurs types de financement", "search.filters.organizations.by-kind": "Filtrer par secteur", "search.filters.organizations.by-kind-description": "Sélectionnez un ou plusieurs secteurs", "search.filters.organizations.by-level": "Filtrer par type d'organisme", @@ -132,7 +132,7 @@ "search.results.pagination.next": "Afficher plus de résultats", "search.results.pagination.end": "Pas de résultats supplémentaires pour la recherche « {query} »", "search.exports.title": "Exporter les résultats", - "search.exports.description": "Pour des raisons de performance, scanr n'exporte qu'un maximum de 1000 résultats. Vous pouvez affiner votre recherche pour obtenir un export plus complet.", + "search.exports.description": "Pour des raisons de performance, scanR n'exporte qu'un maximum de 1000 résultats. Vous pouvez affiner votre recherche pour obtenir un export plus complet.", "search.exports.is-exporting": "Téléchargement des données en cours, veuillez patienter...", "search.exports.csv.title": "CSV", "search.exports.csv.description": "Exporter les résultats au format CSV", From cf7c381c09a5367a5cc23d01cd2d2d8ef5950b9c Mon Sep 17 00:00:00 2001 From: folland87 <frederic@olland.me> Date: Wed, 27 Mar 2024 16:22:01 +0100 Subject: [PATCH 20/21] patents: change timeline ordering --- client/src/pages/patents/[id]/components/timeline/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/pages/patents/[id]/components/timeline/index.tsx b/client/src/pages/patents/[id]/components/timeline/index.tsx index bd81a2ba..5ac5a7ed 100644 --- a/client/src/pages/patents/[id]/components/timeline/index.tsx +++ b/client/src/pages/patents/[id]/components/timeline/index.tsx @@ -22,7 +22,7 @@ export default function PatentTimeline({ patents }: { patents: PatentsData[] }) return [...acc, application, publication, grant] }, []) .filter((element) => element.date) - .sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()) + .sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()) .map((element, i, arr) => { const hasBullet = i === 0 || arr?.[i - 1]?.date !== element.date; return { ...element, hasBullet } From 6b10863a71afad8236246f5a6697d1bedbb28d13 Mon Sep 17 00:00:00 2001 From: Mihoub Debache <debache.mihoub@gmail.com> Date: Wed, 27 Mar 2024 16:42:24 +0100 Subject: [PATCH 21/21] typo --- client/src/pages/patents/[id]/locales/fr.json | 4 +- .../organizations/filters/localisation.tsx | 73 +++++++++++++------ client/src/pages/search/index.tsx | 12 +-- client/src/pages/search/locales/fr.json | 2 +- 4 files changed, 59 insertions(+), 32 deletions(-) diff --git a/client/src/pages/patents/[id]/locales/fr.json b/client/src/pages/patents/[id]/locales/fr.json index e161f92c..166566f1 100644 --- a/client/src/pages/patents/[id]/locales/fr.json +++ b/client/src/pages/patents/[id]/locales/fr.json @@ -6,7 +6,7 @@ "patents.section.cpc.title": "Classification CPC", "patents.section.cpc.description": "Liste des codes CPC, passez le curseur sur un code CPC pour visualiser le nom", "patents.section.website.title": "Sur le web", - "patents.section.website.description": "Explorer les brevets de la famille sur Espacenet et/ou le dépot en france sur le site de l'INPI", + "patents.section.website.description": "Explorer les brevets de la famille sur Espacenet et/ou le dépôt en France sur le site de l'INPI", "patents.id.title": "Identifiant de la famille de brevet", "patents.detail.badge.count": "{count, plural, one {# dépôt} other {# dépôts}} de brevet", "patents.copy": "Cliquez pour copier dans le presse-papier", @@ -20,7 +20,7 @@ "patents.section.timeline.publication": "Publié ", "patents.section.timeline.grant": "Délivré ", "patents.section.timeline.title": "Calendrier d'évenements", - "patents.section.timeline.description": "Calendrier des dépots, publications et délivrances des brevets composants la famille.", + "patents.section.timeline.description": "Calendrier des dépôts, publications et délivrances des brevets composants la famille.", "patents.section.timeline.priority": "Prioritaire", "patents.section.map.title": "Carte des dépôts de brevets", "patents.section.map.description": "Carte des brevets de la famille permettant de voir où les brevets ont été déposés, publiés et délivrés.", diff --git a/client/src/pages/search/components/organizations/filters/localisation.tsx b/client/src/pages/search/components/organizations/filters/localisation.tsx index a8514914..74715520 100644 --- a/client/src/pages/search/components/organizations/filters/localisation.tsx +++ b/client/src/pages/search/components/organizations/filters/localisation.tsx @@ -1,25 +1,36 @@ -import { Autocomplete, AutocompleteItem, DissmissibleTag, TagGroup, Text, useAutocompleteList } from "@dataesr/dsfr-plus"; +import { + Autocomplete, + AutocompleteItem, + DissmissibleTag, + TagGroup, + Text, + useAutocompleteList, +} from "@dataesr/dsfr-plus"; import { FormattedMessage } from "react-intl"; import useUrl from "../../../hooks/useUrl"; -import { LocalisationAutocomplete, autocompleteLocalisations } from "../../../../../api/localisations"; +import { + LocalisationAutocomplete, + autocompleteLocalisations, +} from "../../../../../api/localisations"; import OperatorButton from "../../../../../components/operator-button"; export default function OrganizationLocalisationsFilter() { - const { currentFilters, handleFilterChange, setOperator } = useUrl() + const { currentFilters, handleFilterChange, setOperator } = useUrl(); - const localisationAutocompletedList = useAutocompleteList<LocalisationAutocomplete>({ - async load({ filterText }) { - if (!filterText) { - return { items: [] }; - } - const res = await autocompleteLocalisations({ query: filterText }) + const localisationAutocompletedList = + useAutocompleteList<LocalisationAutocomplete>({ + async load({ filterText }) { + if (!filterText) { + return { items: [] }; + } + const res = await autocompleteLocalisations({ query: filterText }); - return { items: res.data?.map((org) => org._source) }; - } - }); + return { items: res.data?.map((org) => org._source) }; + }, + }); - const filter = currentFilters?.['address.localisationSuggestions'] - const operator = filter?.operator || 'or' + const filter = currentFilters?.["address.localisationSuggestions"]; + const operator = filter?.operator || "or"; return ( <> @@ -32,11 +43,21 @@ export default function OrganizationLocalisationsFilter() { <FormattedMessage id="search.filters.organizations.by-localisation-description" /> </Text> </div> - <OperatorButton operator={operator} setOperator={(key) => setOperator('address.localisationSuggestions', (key === 'and') ? 'and' : 'or')} /> + <OperatorButton + operator={operator} + setOperator={(key) => + setOperator( + "address.localisationSuggestions", + key === "and" ? "and" : "or" + ) + } + /> </div> - {filter ? (<Text bold size="sm" className="fr-mb-1v"> - Sélectionnées: - </Text>) : null} + {filter ? ( + <Text bold size="sm" className="fr-mb-1v"> + Sélectionnées: + </Text> + ) : null} <TagGroup> {filter?.values?.map(({ value, label }) => ( <DissmissibleTag @@ -45,7 +66,10 @@ export default function OrganizationLocalisationsFilter() { color="orange-terre-battue" onClick={(e) => { e.preventDefault(); - handleFilterChange({ field: 'address.localisationSuggestions', value }) + handleFilterChange({ + field: "address.localisationSuggestions", + value, + }); }} > {label || value} @@ -58,12 +82,15 @@ export default function OrganizationLocalisationsFilter() { inputValue={localisationAutocompletedList.filterText} onInputChange={localisationAutocompletedList.setFilterText} loadingState={localisationAutocompletedList.loadingState} - placeholder="Ex: Ile de france, Bas-Rhin, Lyon..." + placeholder="Ex: Ile de France, Bas-Rhin, Lyon..." // menuTrigger="focus" size="md" onSelectionChange={(item) => { if (!item) return; - handleFilterChange({ field: 'address.localisationSuggestions', value: item }) + handleFilterChange({ + field: "address.localisationSuggestions", + value: item, + }); }} > {({ autocompleted }) => ( @@ -73,5 +100,5 @@ export default function OrganizationLocalisationsFilter() { )} </Autocomplete> </> - ) -} \ No newline at end of file + ); +} diff --git a/client/src/pages/search/index.tsx b/client/src/pages/search/index.tsx index 43bdceb2..c9e23915 100644 --- a/client/src/pages/search/index.tsx +++ b/client/src/pages/search/index.tsx @@ -183,12 +183,12 @@ export default function Search() { <div className="result-list"> {data?.length ? data.map(({ _source: data, highlight }) => ( - <ItemComponent - data={data} - highlight={highlight} - key={data.id} - /> - )) + <ItemComponent + data={data} + highlight={highlight} + key={data.id} + /> + )) : null} </div> </Container> diff --git a/client/src/pages/search/locales/fr.json b/client/src/pages/search/locales/fr.json index 1a4f857a..ac6c0ffd 100644 --- a/client/src/pages/search/locales/fr.json +++ b/client/src/pages/search/locales/fr.json @@ -79,7 +79,7 @@ "search.filters.projects.by-type": "Filtrer par type de financement", "search.filters.projects.by-type-description": "Sélectionnez un ou plusieurs types de financements", "search.filters.projects.by-year": "Filtrer par année", - "search.filters.patents.by-year": "Filtrer par date de dépot", + "search.filters.patents.by-year": "Filtrer par date de dépôt", "search.filters.current.patents.year": "Années de publication du brevet", "search.filters.patent.by-year-description": "Sélectionnez une période", "search.filters.patents.regions": "Caractéristiques de la famille de brevet",