From ca66427efdf5d18cc172e4325281ff5cf25d352c Mon Sep 17 00:00:00 2001 From: Clement AUGER Date: Wed, 12 Jul 2023 16:12:39 +0200 Subject: [PATCH 01/54] fix: margin for icons in persona cards --- source/components/emoji.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/components/emoji.tsx b/source/components/emoji.tsx index ccca0b5148..edf376d2a9 100644 --- a/source/components/emoji.tsx +++ b/source/components/emoji.tsx @@ -77,7 +77,7 @@ export const Emoji = ({ children, ...props }) => { return children } -export default (text: string, label: string) => { +export default (text: string, label?: string) => { return } From 6d391db5296de774112740b5225fb14bf3cdaa60 Mon Sep 17 00:00:00 2001 From: Clement AUGER Date: Wed, 12 Jul 2023 16:12:53 +0200 Subject: [PATCH 02/54] fix: label is an optionnal props of emoji function --- source/sites/publicodes/Personas.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index 25bd716dfc..befed99fdd 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -251,6 +251,9 @@ export const PersonaGrid = ({ ${nom === persona ? 'border: 2px solid var(--color) !important' : ''}; + img { + margin-bottom: 0.5rem; + } `} onClick={() => warningIfSituationExists && hasSituation From 2bff20eda1b36f44b23c17bfcb14721f4393a5ca Mon Sep 17 00:00:00 2001 From: Clement AUGER Date: Wed, 12 Jul 2023 16:13:10 +0200 Subject: [PATCH 03/54] fix: props of PersonaGrid --- source/sites/publicodes/Personas.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index befed99fdd..c3fde35c0d 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -93,7 +93,7 @@ export default ({}) => { )} - +

Les personas nous permettront de prendre le parti d'une diversité @@ -132,10 +132,7 @@ export default ({}) => { ) } -export const PersonaGrid = ({ - additionnalOnClick, - warningIfSituationExists, -}) => { +export const PersonaGrid = ({ warningIfSituationExists }) => { const { i18n } = useTranslation() const dispatch = useDispatch(), objectif = 'bilan' From 67b923544acb702d6c6585e95de26357c72cb456 Mon Sep 17 00:00:00 2001 From: Clement AUGER Date: Wed, 12 Jul 2023 17:01:09 +0200 Subject: [PATCH 04/54] ajout titres choix de visualisation + css --- nosgestesclimat | 2 +- source/sites/publicodes/Personas.tsx | 107 ++++++++++++++++----------- 2 files changed, 66 insertions(+), 43 deletions(-) diff --git a/nosgestesclimat b/nosgestesclimat index b636ba3a79..8a1f1dc9ab 160000 --- a/nosgestesclimat +++ b/nosgestesclimat @@ -1 +1 @@ -Subproject commit b636ba3a79b009e8ebdbcc0ce5b12c4bb04639c1 +Subproject commit 8a1f1dc9aba90c3afda057b78a0f1a5e7c095903 diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index c3fde35c0d..8841e1f887 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -19,15 +19,17 @@ import FinShareButton from './fin/FinShareButton' import { CardGrid } from './ListeActionPlus' const Nothing = () => null -const visualisationChoices = { - ravijen: RavijenChart, - budget: Budget, - 'sous-catégories': GridChart, - emojis: () => , - - action: ActionSlide, - aucun: Nothing, +const visualisationChoices = { + ravijen: { titre: 'Graphe Bilan', composant: RavijenChart }, + budget: { titre: 'Page de fin - Budget', composant: Budget }, + 'sous-catégories': { titre: 'Page de fin - Grille', composant: GridChart }, + action: { titre: 'Page de fin - Top 3 actions', composant: ActionSlide }, + emojis: { + titre: 'Partage RS', + composant: () => , + }, + aucun: { titre: 'Aucun', composant: Nothing }, } export default ({}) => { @@ -37,7 +39,9 @@ export default ({}) => { }) const visualisationParam = searchParams.get('visualisation') - const Visualisation = visualisationChoices[`${visualisationParam}`] + + const VisualisationComponent = + visualisationChoices[`${visualisationParam}`]?.composant const engine = useEngine() @@ -50,47 +54,66 @@ export default ({}) => {

Personas</Trans>} /> - <p> - <Trans> - Cette page vous permet de naviguer les parcours Nos Gestes Climat - comme si vous étiez l'un des profils types que nous avons listés. - </Trans> - </p> - <p> - ➡️{' '} - <em> - <Trans> - Sélectionnez un persona et éventuellement un graphique à afficher. - </Trans> - </em> - </p> - <form> - 🧮 - {Object.keys(visualisationChoices).map((name) => ( - <label key={name}> - <input - onChange={() => setSearchParams({ visualisation: name })} - type="radio" - value={name} - checked={searchParams.get('visualisation') === name} - /> - {name} - </label> - ))} - </form> + <div + css={` + display: flex; + flex-direction: row; + align-items: center; + margin-bottom: 1rem; + `} + > + <div> + <p> + <Trans> + Cette page vous permet de naviguer les parcours Nos Gestes Climat + comme si vous étiez l'un des profils types que nous avons listés. + </Trans> + </p> + <p> + ➡️{' '} + <em> + <Trans> + Sélectionnez un persona et éventuellement un graphique à + afficher. + </Trans> + </em> + </p> + </div> + <div + className="ui__ card box" + css={` + min-width: 16rem; + align-items: flex-start !important; + text-align: left !important; + `} + > + {Object.entries(visualisationChoices).map(([id, elt]) => ( + <label key={id}> + <input + onChange={() => setSearchParams({ visualisation: id })} + type="radio" + value={id} + checked={searchParams.get('visualisation') === id} + /> + {elt.titre} + </label> + ))} + </div> + </div> {persona && ( <div css={` max-width: 35rem; margin: 0 auto; + display: flex; + justify-content: center; ${visualisationParam === 'ravijen' && ` height: 45rem; - max-width: none; - `} + `}; `} > - <Visualisation {...slideProps} /> + <VisualisationComponent {...slideProps} /> </div> )} <PersonaGrid warningIfSituationExists={false} /> @@ -242,9 +265,9 @@ export const PersonaGrid = ({ warningIfSituationExists }) => { selectedPersona === persona.nom ? 'selected' : '' }`} css={` - width: 11rem !important; + width: 13rem !important; height: 15rem !important; - padding: 1rem 0.75rem 1rem 0.75rem !important; + padding: 0.75rem 0.5rem 0.75rem 0.5rem !important; ${nom === persona ? 'border: 2px solid var(--color) !important' : ''}; From 909e435bce16e8fa2aaf27e2a79ada363ecb0276 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Wed, 12 Jul 2023 18:53:05 +0200 Subject: [PATCH 05/54] add: type persona + fix types --- source/sites/publicodes/Personas.tsx | 67 +++++++++++++++++----------- 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index 8841e1f887..83c33ca24c 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -18,6 +18,16 @@ import Budget from './fin/Budget' import FinShareButton from './fin/FinShareButton' import { CardGrid } from './ListeActionPlus' +export type Persona = { + nom: string + icônes: string + data: Situation + description: string + résumé: string +} + +export type Personas = Array<Persona> + const Nothing = () => null const visualisationChoices = { @@ -32,8 +42,11 @@ const visualisationChoices = { aucun: { titre: 'Aucun', composant: Nothing }, } -export default ({}) => { - const persona = useSelector((state) => state.simulation?.persona) +export default () => { + const selectedPersona = useSelector( + (state: AppState) => state.simulation?.persona + ) + const [searchParams, setSearchParams] = useSearchParams({ visualisation: 'aucun', }) @@ -100,7 +113,7 @@ export default ({}) => { ))} </div> </div> - {persona && ( + {selectedPersona && ( <div css={` max-width: 35rem; @@ -116,7 +129,10 @@ export default ({}) => { <VisualisationComponent {...slideProps} /> </div> )} - <PersonaGrid warningIfSituationExists={false} /> + <PersonaGrid + selectedPersona={selectedPersona} + warningIfSituationExists={false} + /> <p> <Trans i18nKey={'publicodes.Personas.description'}> Les personas nous permettront de prendre le parti d'une diversité @@ -155,11 +171,10 @@ export default ({}) => { ) } -export const PersonaGrid = ({ warningIfSituationExists }) => { +export const PersonaGrid = ({ selectedPersona, warningIfSituationExists }) => { const { i18n } = useTranslation() const dispatch = useDispatch(), objectif = 'bilan' - const selectedPersona = useSelector((state) => state.simulation?.persona) const situation = useSelector(situationSelector) const [data, setData] = useState() @@ -197,29 +212,31 @@ export const PersonaGrid = ({ warningIfSituationExists }) => { if (!data) return null - const personasRules = Object.values(data) + const personasRules: Personas = Object.values(data) - const setPersona = (persona) => { + const setPersona = (persona: Persona) => { engine.setSituation({}) // Engine should be updated on simulation reset but not working here, useEngine to be investigated - const { nom, icônes, data, description } = persona const missingVariables = engine.evaluate(objectif).missingVariables ?? {} const defaultMissingVariables = Object.keys(missingVariables) - dispatch( - setDifferentSituation({ - config: { objectifs: [objectif] }, - url: '/simulateur/bilan', - // the schema of peronas is not fixed yet - situation: data.situation || data, - persona: nom, - // If not specified, act as if all questions were answered : all that is not in - // the situation object is a validated default value - foldedSteps: defaultMissingVariables, - }) - ) + const newSimulation: Simulation = { + config: { objectifs: [objectif] }, + url: '/simulateur/bilan', + // the schema of personas is not fixed yet + situation: persona.data.situation || persona.data, + persona: persona.nom, + // If not specified, act as if all questions were answered : all that is not in + // the situation object is a validated default value + foldedSteps: defaultMissingVariables, + } + + dispatch(setDifferentSituation(newSimulation)) + if (redirect) navigate(redirect) } + const hasSituation = Object.keys(situation).length + if (warning) return ( <IllustratedMessage @@ -253,24 +270,20 @@ export const PersonaGrid = ({ warningIfSituationExists }) => { } /> ) - return ( <CardGrid css="padding: 0; justify-content: center"> {personasRules.map((persona) => { - const { nom, icônes, data, description, résumé } = persona + const { nom, icônes, description, résumé } = persona return ( <li key={nom}> <button className={`ui__ card box interactive light-border ${ - selectedPersona === persona.nom ? 'selected' : '' + selectedPersona === nom ? 'selected' : '' }`} css={` width: 13rem !important; height: 15rem !important; padding: 0.75rem 0.5rem 0.75rem 0.5rem !important; - ${nom === persona - ? 'border: 2px solid var(--color) !important' - : ''}; img { margin-bottom: 0.5rem; } From 224cac6a1214c4a4d95ac178120939d1900020a4 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Wed, 12 Jul 2023 18:53:50 +0200 Subject: [PATCH 06/54] add: type FinShareButton --- source/sites/publicodes/fin/FinShareButton.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/source/sites/publicodes/fin/FinShareButton.tsx b/source/sites/publicodes/fin/FinShareButton.tsx index 3573fd7c2b..d7d71a8c21 100644 --- a/source/sites/publicodes/fin/FinShareButton.tsx +++ b/source/sites/publicodes/fin/FinShareButton.tsx @@ -5,7 +5,15 @@ import ShareButton from '../../../components/ShareButton' import { useEngine } from '../../../components/utils/EngineContext' import { range } from '../../../utils' -export default ({ textColor, showResult, label }) => { +export default ({ + textColor, + showResult, + label, +}: { + textColor?: string + showResult?: boolean + label?: string +}) => { const rules = useSelector((state) => state.rules) const engine = useEngine() const categories = extractCategories(rules, engine).map((category) => ({ From 52515980190b4135411eb7a12653f9c3b6aaeaea Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Wed, 12 Jul 2023 19:00:30 +0200 Subject: [PATCH 07/54] delete persona warning logic if situation --- source/sites/publicodes/Personas.tsx | 56 +++------------------------- 1 file changed, 5 insertions(+), 51 deletions(-) diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index 83c33ca24c..b76fc8d459 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -1,16 +1,14 @@ -import { resetSimulation } from '@/actions/actions' import Title from '@/components/groupe/Title' +import { AppState, Simulation, Situation } from '@/reducers/rootReducer' import { useEffect, useState } from 'react' import emoji from 'react-easy-emoji' import { Trans, useTranslation } from 'react-i18next' import { useDispatch, useSelector } from 'react-redux' -import { Link, useNavigate, useSearchParams } from 'react-router-dom' +import { useNavigate, useSearchParams } from 'react-router-dom' import { setDifferentSituation } from '../../actions/actions' -import IllustratedMessage from '../../components/ui/IllustratedMessage' import useBranchData from '../../components/useBranchData' import { useEngine } from '../../components/utils/EngineContext' import { ScrollToTop } from '../../components/utils/Scroll' -import { situationSelector } from '../../selectors/simulationSelectors' import GridChart from './chart/GridChart' import RavijenChart from './chart/RavijenChart' import ActionSlide from './fin/ActionSlide' @@ -129,10 +127,7 @@ export default () => { <VisualisationComponent {...slideProps} /> </div> )} - <PersonaGrid - selectedPersona={selectedPersona} - warningIfSituationExists={false} - /> + <PersonaGrid selectedPersona={selectedPersona} /> <p> <Trans i18nKey={'publicodes.Personas.description'}> Les personas nous permettront de prendre le parti d'une diversité @@ -171,14 +166,12 @@ export default () => { ) } -export const PersonaGrid = ({ selectedPersona, warningIfSituationExists }) => { +export const PersonaGrid = ({ selectedPersona }) => { const { i18n } = useTranslation() const dispatch = useDispatch(), objectif = 'bilan' - const situation = useSelector(situationSelector) const [data, setData] = useState() - const [warning, setWarning] = useState(false) const engine = useEngine() const branchData = useBranchData() @@ -235,41 +228,6 @@ export const PersonaGrid = ({ selectedPersona, warningIfSituationExists }) => { if (redirect) navigate(redirect) } - const hasSituation = Object.keys(situation).length - - if (warning) - return ( - <IllustratedMessage - emoji="ℹ️" - message={ - <div> - <p> - <Trans i18nKey={'publicodes.Personas.warningMsg'}> - Sélectionner un persona releguera votre simulation en cours dans - votre historique de simulations, accessible en bas de votre{' '} - <Link to="/profil">page profil</Link>. - </Trans> - </p> - <button - className="ui__ button simple" - onClick={() => { - dispatch(resetSimulation()) - setPersona(warning) - setWarning(false) - }} - > - <Trans>J'ai compris</Trans> - </button> - <button - className="ui__ button simple" - onClick={() => setWarning(false)} - > - <Trans>Annuler</Trans> - </button> - </div> - } - /> - ) return ( <CardGrid css="padding: 0; justify-content: center"> {personasRules.map((persona) => { @@ -288,11 +246,7 @@ export const PersonaGrid = ({ selectedPersona, warningIfSituationExists }) => { margin-bottom: 0.5rem; } `} - onClick={() => - warningIfSituationExists && hasSituation - ? setWarning(persona) - : setPersona(persona) - } + onClick={() => setPersona(persona)} > <div css={` From a650862858631d192d06e54b95462377745f31f1 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Thu, 13 Jul 2023 09:09:53 +0200 Subject: [PATCH 08/54] fix: naming + type --- source/sites/publicodes/Personas.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index b76fc8d459..97737c205f 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -171,7 +171,7 @@ export const PersonaGrid = ({ selectedPersona }) => { const dispatch = useDispatch(), objectif = 'bilan' - const [data, setData] = useState() + const [personasList, setPersonasList] = useState<Personas>() const engine = useEngine() const branchData = useBranchData() @@ -187,14 +187,16 @@ export const PersonaGrid = ({ selectedPersona }) => { if (process.env.NODE_ENV === 'development') { const json = require('../../../nosgestesclimat/public' + fileName) - setData(json) + const jsonValues: Personas = Object.values(json) + setPersonasList(jsonValues) } else { fetch(branchData.deployURL + fileName, { mode: 'cors', }) .then((response) => response.json()) .then((json) => { - setData(json) + const jsonValues: Personas = Object.values(json) + setPersonasList(jsonValues) }) .catch((err) => { console.log('url:', branchData.deployURL + `/personas-${lang}.json`) @@ -203,9 +205,7 @@ export const PersonaGrid = ({ selectedPersona }) => { } }, [branchData.deployURL, branchData.loaded, lang]) - if (!data) return null - - const personasRules: Personas = Object.values(data) + if (!personasList) return null const setPersona = (persona: Persona) => { engine.setSituation({}) // Engine should be updated on simulation reset but not working here, useEngine to be investigated @@ -230,7 +230,7 @@ export const PersonaGrid = ({ selectedPersona }) => { return ( <CardGrid css="padding: 0; justify-content: center"> - {personasRules.map((persona) => { + {personasList.map((persona) => { const { nom, icônes, description, résumé } = persona return ( <li key={nom}> From e8204878505975b475cc24ddf77db934546986de Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Thu, 13 Jul 2023 09:13:45 +0200 Subject: [PATCH 09/54] fix: type component PersonaGrid --- source/sites/publicodes/Personas.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index 97737c205f..8840ed3c06 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -41,7 +41,7 @@ const visualisationChoices = { } export default () => { - const selectedPersona = useSelector( + const selectedPersona: string | undefined = useSelector( (state: AppState) => state.simulation?.persona ) @@ -166,7 +166,11 @@ export default () => { ) } -export const PersonaGrid = ({ selectedPersona }) => { +export const PersonaGrid = ({ + selectedPersona, +}: { + selectedPersona: string | undefined +}) => { const { i18n } = useTranslation() const dispatch = useDispatch(), objectif = 'bilan' From 51703e65e59bf9cfda2893ee95b42a739652e46d Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Thu, 13 Jul 2023 09:27:13 +0200 Subject: [PATCH 10/54] =?UTF-8?q?feat:=20d=C3=A9tails=20des=20r=C3=A9ponse?= =?UTF-8?q?s=20profil=20dans=20la=20page=20personas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/sites/publicodes/Personas.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index 8840ed3c06..881078b92f 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -1,3 +1,4 @@ +import AnswerList from '@/components/conversation/AnswerList' import Title from '@/components/groupe/Title' import { AppState, Simulation, Situation } from '@/reducers/rootReducer' import { useEffect, useState } from 'react' @@ -29,6 +30,7 @@ export type Personas = Array<Persona> const Nothing = () => null const visualisationChoices = { + profil: { titre: 'Détail Réponses', composant: AnswerList }, ravijen: { titre: 'Graphe Bilan', composant: RavijenChart }, budget: { titre: 'Page de fin - Budget', composant: Budget }, 'sous-catégories': { titre: 'Page de fin - Grille', composant: GridChart }, From 3d8690a0500d7f56a171504e9031c9b39c4fda4d Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Thu, 13 Jul 2023 11:04:36 +0200 Subject: [PATCH 11/54] fix: css simulation list --- source/sites/publicodes/SimulationList.tsx | 84 ++++++++++++++-------- 1 file changed, 54 insertions(+), 30 deletions(-) diff --git a/source/sites/publicodes/SimulationList.tsx b/source/sites/publicodes/SimulationList.tsx index 5e33297e2e..fbad704024 100644 --- a/source/sites/publicodes/SimulationList.tsx +++ b/source/sites/publicodes/SimulationList.tsx @@ -15,8 +15,60 @@ export default ({ dispatch, list, currentSimulationId }) => { simulation.date !== undefined ? new Date(simulation.date) : new Date() return ( <li key={simulation.id} css="list-style-type: none"> - <details css="display: inline-block;"> - <summary>{dateSimu.toLocaleDateString()}</summary> + <details> + <summary> + <div + css={` + display: inline-flex; + `} + > + <span>{dateSimu.toLocaleDateString()}</span> + <span + css={` + margin-left: 0.25rem; + width: 8rem; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + @media (max-width: 800px) { + display: none; + } + `} + > + - {simulation.id} + </span> + {currentSimulationId === simulation.id ? ( + <span css="margin: 0 1rem"> + ✅ <Trans>Chargée</Trans> + </span> + ) : ( + <span> + <button + className={'ui__ button simple small'} + css="margin: 0 1rem" + onClick={() => { + dispatch(setCurrentSimulation(simulation)) + dispatch(setActionsChoices(simulation.actionChoices)) + dispatch( + setAllStoredTrajets(simulation.storedTrajets) + ) + }} + > + <Trans>Charger</Trans> + </button> + <button + className={'ui__ button simple small'} + css="margin: 0 1rem" + onClick={() => { + dispatch(deleteSimulationById(simulation.id)) + }} + > + <Trans>supprimer</Trans> + </button> + </span> + )} + </div> + </summary> <ul> <li> Date complète : {dateSimu.toLocaleDateString()}{' '} @@ -25,34 +77,6 @@ export default ({ dispatch, list, currentSimulationId }) => { <li>Identifiant : {simulation.id}.</li> </ul> </details> - {currentSimulationId === simulation.id ? ( - <span css="margin: 0 1rem"> - ✅ <Trans>Chargée</Trans> - </span> - ) : ( - <span> - <button - className={'ui__ button simple small'} - css="margin: 0 1rem" - onClick={() => { - dispatch(setCurrentSimulation(simulation)) - dispatch(setActionsChoices(simulation.actionChoices)) - dispatch(setAllStoredTrajets(simulation.storedTrajets)) - }} - > - <Trans>Charger</Trans> - </button> - <button - className={'ui__ button simple small'} - css="margin: 0 1rem" - onClick={() => { - dispatch(deleteSimulationById(simulation.id)) - }} - > - <Trans>supprimer</Trans> - </button> - </span> - )} </li> ) })} From 77f8d27d2bfacf512d7bc9955a2d0ce76cc26bb1 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Thu, 13 Jul 2023 11:43:35 +0200 Subject: [PATCH 12/54] =?UTF-8?q?feat:=20g=C3=A9n=C3=A9ralise=20le=20type?= =?UTF-8?q?=20Persona?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/components/SessionBar.tsx | 2 +- source/reducers/rootReducer.ts | 2 +- source/selectors/simulationSelectors.ts | 2 +- source/selectors/storageSelectors.ts | 8 +++++--- source/sites/publicodes/Personas.tsx | 8 ++++---- source/sites/publicodes/Profil.tsx | 2 +- source/types/simulation.ts | 3 ++- 7 files changed, 15 insertions(+), 12 deletions(-) diff --git a/source/components/SessionBar.tsx b/source/components/SessionBar.tsx index 11a7062b1b..dd3719429d 100644 --- a/source/components/SessionBar.tsx +++ b/source/components/SessionBar.tsx @@ -212,7 +212,7 @@ export default function SessionBar({}) { border-radius: 0.3rem; `} > - {persona} + {persona.nom} </span> )} </Button> diff --git a/source/reducers/rootReducer.ts b/source/reducers/rootReducer.ts index 4e3dbc7abd..11ffaa8679 100644 --- a/source/reducers/rootReducer.ts +++ b/source/reducers/rootReducer.ts @@ -113,7 +113,7 @@ function simulation( foldedSteps: action.foldedSteps ?? state?.foldedSteps ?? [], unfoldedStep: null, persona: action.persona, - id: action.persona ?? state?.id ?? generateSimulationId(), // Unique identifier of the simulation, used for the 'currentSimulationId' pointer. + id: action.persona?.nom ?? state?.id ?? generateSimulationId(), // Unique identifier of the simulation, used for the 'currentSimulationId' pointer. date: !action.persona && state?.date ? state?.date : new Date(), eventsSent: state?.eventsSent ?? {}, } diff --git a/source/selectors/simulationSelectors.ts b/source/selectors/simulationSelectors.ts index 96b9fd4d90..b8535ac687 100644 --- a/source/selectors/simulationSelectors.ts +++ b/source/selectors/simulationSelectors.ts @@ -126,7 +126,7 @@ export const useSimulationData = () => { } export const isPersonaSelector = createSelector( [currentSimulationSelector], - (simulation) => simulation?.persona != null + (simulation) => simulation?.persona != undefined ) export const hasSubscribedToNewsletterSelector = (state: AppState) => { diff --git a/source/selectors/storageSelectors.ts b/source/selectors/storageSelectors.ts index cb44da70a0..6816670a4d 100644 --- a/source/selectors/storageSelectors.ts +++ b/source/selectors/storageSelectors.ts @@ -1,6 +1,9 @@ import { DottedName } from '@/components/publicodesUtils' import { Lang } from '@/locales/translation' -import { AppState } from '@/reducers/rootReducer' +import { AppState, Simulation, SimulationConfig } from '@/reducers/rootReducer' +import { Persona } from '@/sites/publicodes/Personas' + +export type Rating = 0 | 1 | 2 | 3 | 'no_display' | 'display' | 'refuse' export type Enquête = { userID: string @@ -9,13 +12,12 @@ export type Enquête = { import { Group } from '@/types/groups' import { Rating } from '@/types/rating' -import { Simulation, SimulationConfig } from '@/types/simulation' export type SavedSimulation = { situation: Simulation['situation'] foldedSteps?: Array<DottedName> actionChoices: Object - persona?: string + persona?: Persona storedTrajets: Object storedAmortissementAvion: { [key: string]: number } conference: { room: string } | null diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index 881078b92f..a2d7f3121f 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -43,7 +43,7 @@ const visualisationChoices = { } export default () => { - const selectedPersona: string | undefined = useSelector( + const selectedPersona = useSelector( (state: AppState) => state.simulation?.persona ) @@ -171,7 +171,7 @@ export default () => { export const PersonaGrid = ({ selectedPersona, }: { - selectedPersona: string | undefined + selectedPersona: Persona | undefined }) => { const { i18n } = useTranslation() const dispatch = useDispatch(), @@ -223,7 +223,7 @@ export const PersonaGrid = ({ url: '/simulateur/bilan', // the schema of personas is not fixed yet situation: persona.data.situation || persona.data, - persona: persona.nom, + persona: persona, // If not specified, act as if all questions were answered : all that is not in // the situation object is a validated default value foldedSteps: defaultMissingVariables, @@ -242,7 +242,7 @@ export const PersonaGrid = ({ <li key={nom}> <button className={`ui__ card box interactive light-border ${ - selectedPersona === nom ? 'selected' : '' + selectedPersona?.nom === nom ? 'selected' : '' }`} css={` width: 13rem !important; diff --git a/source/sites/publicodes/Profil.tsx b/source/sites/publicodes/Profil.tsx index dd482bf023..23ee710673 100644 --- a/source/sites/publicodes/Profil.tsx +++ b/source/sites/publicodes/Profil.tsx @@ -88,7 +88,7 @@ export default () => { <p> <em> <Trans>👤 Vous utilisez actuellement le persona</Trans>{' '} - <code>{persona}</code> + <code>{persona.nom}</code> </em> </p> )} diff --git a/source/types/simulation.ts b/source/types/simulation.ts index 812bea7664..0dfb6737ac 100644 --- a/source/types/simulation.ts +++ b/source/types/simulation.ts @@ -1,4 +1,5 @@ import { DottedName } from '@/components/publicodesUtils' +import { Persona } from '@/sites/publicodes/Personas' export type Situation = Record<DottedName, any> @@ -33,7 +34,7 @@ export type Simulation = { targetUnit?: string foldedSteps?: Array<DottedName> unfoldedStep?: DottedName | null - persona?: string + persona?: Persona date?: Date id?: string eventsSent?: Record<string, boolean> From 5969e0ae0a78d93a4780b9c7bf9db1040bc8effb Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Thu, 13 Jul 2023 11:48:40 +0200 Subject: [PATCH 13/54] feat: ajout description dans la page personas --- source/sites/publicodes/Personas.tsx | 7 +++++-- source/sites/publicodes/personas/Summary.tsx | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 source/sites/publicodes/personas/Summary.tsx diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index a2d7f3121f..cd2f6c3e95 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -16,6 +16,7 @@ import ActionSlide from './fin/ActionSlide' import Budget from './fin/Budget' import FinShareButton from './fin/FinShareButton' import { CardGrid } from './ListeActionPlus' +import Summary from './personas/Summary' export type Persona = { nom: string @@ -30,6 +31,7 @@ export type Personas = Array<Persona> const Nothing = () => null const visualisationChoices = { + summary: { titre: 'Description', composant: Summary }, profil: { titre: 'Détail Réponses', composant: AnswerList }, ravijen: { titre: 'Graphe Bilan', composant: RavijenChart }, budget: { titre: 'Page de fin - Budget', composant: Budget }, @@ -58,9 +60,10 @@ export default () => { const engine = useEngine() - const slideProps = { + const visualisationComponentProps = { score: engine.evaluate('bilan').nodeValue, headlessMode: true, + summary: selectedPersona?.description, } return ( @@ -126,7 +129,7 @@ export default () => { `}; `} > - <VisualisationComponent {...slideProps} /> + <VisualisationComponent {...visualisationComponentProps} /> </div> )} <PersonaGrid selectedPersona={selectedPersona} /> diff --git a/source/sites/publicodes/personas/Summary.tsx b/source/sites/publicodes/personas/Summary.tsx new file mode 100644 index 0000000000..40fd0726b6 --- /dev/null +++ b/source/sites/publicodes/personas/Summary.tsx @@ -0,0 +1,14 @@ +import { Markdown } from '@/components/utils/markdown' +import { Trans } from 'react-i18next' +import { Persona } from '../Personas' + +export default ({ persona }: { persona: Persona }) => { + return ( + <div> + <h2> + <Trans>Description:</Trans> + </h2> + <Markdown children={persona?.description} /> + </div> + ) +} From 292d1132a3d29ce67b0cf6781f1c9f9256b9e8d6 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Thu, 13 Jul 2023 13:15:50 +0200 Subject: [PATCH 14/54] extract getFormattedActionValue function --- source/sites/publicodes/ActionVignette.tsx | 36 ++++++++++++++++------ 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/source/sites/publicodes/ActionVignette.tsx b/source/sites/publicodes/ActionVignette.tsx index afd358747a..8386a74805 100644 --- a/source/sites/publicodes/ActionVignette.tsx +++ b/source/sites/publicodes/ActionVignette.tsx @@ -313,6 +313,26 @@ export const ActionGameCard = ({ evaluation, total, rule }) => { </Link> ) } + +export const getFormattedActionValue = ({ t, i18n }, dottedName, engine) => { + const correctedValue = correctValue(engine.evaluate(dottedName)) + + if (correctedValue == undefined) { + return {} + } + + const [stringValue, unit] = humanWeight( + { t, i18n }, + correctedValue, + false, + true + ) + + const sign = correctedValue > 0 ? '-' : '+' + + return { correctedValue, stringValue, unit, sign } +} + export const ActionValue = ({ total, disabled, @@ -321,20 +341,18 @@ export const ActionValue = ({ engine, }) => { const { t, i18n } = useTranslation() - const correctedValue = correctValue(engine.evaluate(dottedName)) + + const { correctedValue, stringValue, unit, sign } = getFormattedActionValue( + { t, i18n }, + dottedName, + engine + ) if (correctedValue == undefined) { - return null + return } - const [stringValue, unit] = humanWeight( - { t, i18n }, - correctedValue, - false, - true - ) const relativeValue = Math.round(100 * (correctedValue / total)) - const sign = correctedValue > 0 ? '-' : '+' return ( <div From 18fdb2223a9342e71e029f71e5d035fe9981f7c8 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Thu, 13 Jul 2023 13:16:13 +0200 Subject: [PATCH 15/54] feat: V0 raw action list --- source/sites/publicodes/Personas.tsx | 5 +- .../publicodes/personas/RawActionsList.tsx | 74 +++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 source/sites/publicodes/personas/RawActionsList.tsx diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index cd2f6c3e95..ba7dd7f769 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -16,6 +16,7 @@ import ActionSlide from './fin/ActionSlide' import Budget from './fin/Budget' import FinShareButton from './fin/FinShareButton' import { CardGrid } from './ListeActionPlus' +import RawActionsList from './personas/RawActionsList' import Summary from './personas/Summary' export type Persona = { @@ -32,6 +33,7 @@ const Nothing = () => null const visualisationChoices = { summary: { titre: 'Description', composant: Summary }, + actionList: { titre: 'Actions associées', composant: RawActionsList }, profil: { titre: 'Détail Réponses', composant: AnswerList }, ravijen: { titre: 'Graphe Bilan', composant: RavijenChart }, budget: { titre: 'Page de fin - Budget', composant: Budget }, @@ -63,7 +65,8 @@ export default () => { const visualisationComponentProps = { score: engine.evaluate('bilan').nodeValue, headlessMode: true, - summary: selectedPersona?.description, + engine: engine, + persona: selectedPersona, } return ( diff --git a/source/sites/publicodes/personas/RawActionsList.tsx b/source/sites/publicodes/personas/RawActionsList.tsx new file mode 100644 index 0000000000..5f993e4bf8 --- /dev/null +++ b/source/sites/publicodes/personas/RawActionsList.tsx @@ -0,0 +1,74 @@ +import { useEngine } from '@/components/utils/EngineContext' +import { AppState } from '@/reducers/rootReducer' +import { Trans, useTranslation } from 'react-i18next' +import { useSelector } from 'react-redux' +import { getFormattedActionValue } from '../ActionVignette' +import { humanWeight } from '../HumanWeight' +import useActions from '../useActions' + +export default () => { + const { t, i18n } = useTranslation() + const engine = useEngine() + const rules = useSelector((state: AppState) => state.rules) + const { interestingActions: actionResultsRaw } = useActions({ + focusedAction: null, + rules, + radical: true, + engine, + metric: null, + }) + + const actionsList = actionResultsRaw.map((action) => { + const { dottedName, title } = action + const { correctedValue, stringValue, unit, sign } = getFormattedActionValue( + { t, i18n }, + dottedName, + engine + ) + return { dottedName, title, correctedValue, stringValue, unit, sign } + }) + + const numberOfActions = actionsList.length + const rawTotalReduction = actionsList.reduce( + (acc, { correctedValue, sign }) => { + if (correctedValue) { + return sign === '+' ? acc + correctedValue : acc - correctedValue + } else return acc + }, + 0 + ) + const [totalReduction, unit] = humanWeight( + { t, i18n }, + rawTotalReduction, + false, + true + ) + + return ( + <div> + <h2> + <Trans>Les actions associées:</Trans> + </h2> + <p> + <strong> + {numberOfActions} <Trans>actions</Trans> + </strong>{' '} + <Trans> + proposées au total pour un empreinte de réduction cumulée de{' '} + </Trans> + <strong> + {totalReduction} {unit} + </strong> + . + </p> + <ul> + {actionsList.map(({ dottedName, title, stringValue, unit, sign }) => ( + <li key={dottedName}> + {dottedName} | {title} |{' '} + {stringValue ? `${sign} ${stringValue} ${unit}` : 'Non quantifiée'} + </li> + ))} + </ul> + </div> + ) +} From ae9cafff5f29a27d5906f9de1f43caf3ab76b415 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Thu, 13 Jul 2023 16:09:23 +0200 Subject: [PATCH 16/54] =?UTF-8?q?feat:=20liste=20actions=20par=20cat=C3=A9?= =?UTF-8?q?gorie=20+=20type?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../publicodes/personas/RawActionsList.tsx | 87 ++++++++++++++++--- 1 file changed, 76 insertions(+), 11 deletions(-) diff --git a/source/sites/publicodes/personas/RawActionsList.tsx b/source/sites/publicodes/personas/RawActionsList.tsx index 5f993e4bf8..5f7bffe8cc 100644 --- a/source/sites/publicodes/personas/RawActionsList.tsx +++ b/source/sites/publicodes/personas/RawActionsList.tsx @@ -1,3 +1,9 @@ +import { + Category, + DottedName, + extractCategoriesNamespaces, + splitName, +} from '@/components/publicodesUtils' import { useEngine } from '@/components/utils/EngineContext' import { AppState } from '@/reducers/rootReducer' import { Trans, useTranslation } from 'react-i18next' @@ -18,16 +24,61 @@ export default () => { metric: null, }) - const actionsList = actionResultsRaw.map((action) => { - const { dottedName, title } = action + type CustomAction = { + correctedValue: number + dottedName: DottedName + sign: string + stringValue: string + title: string + unit: string + } + + type ActionsList = Array<CustomAction> + + type ActionsListByCategory = Array< + Category & { + actions?: ActionsList + } + > + + const actionsList: ActionsList = actionResultsRaw.map((actionRule) => { + const { dottedName, title }: { dottedName: DottedName; title: string } = + actionRule const { correctedValue, stringValue, unit, sign } = getFormattedActionValue( { t, i18n }, dottedName, engine ) - return { dottedName, title, correctedValue, stringValue, unit, sign } + return { + dottedName, + title, + correctedValue, + stringValue, + unit, + sign, + } }) + const categories = extractCategoriesNamespaces(rules, engine).reduce( + (obj, category) => { + obj[category.dottedName] = category + return obj + }, + {} as Array<Category> + ) + + const actionsListByCategory: ActionsListByCategory = actionsList.reduce( + (obj, action) => { + const category = splitName(action.dottedName)[0] + obj[category].actions = { + ...obj[category].actions, + [action.dottedName]: action, + } + return obj + }, + categories + ) + const numberOfActions = actionsList.length const rawTotalReduction = actionsList.reduce( (acc, { correctedValue, sign }) => { @@ -61,14 +112,28 @@ export default () => { </strong> . </p> - <ul> - {actionsList.map(({ dottedName, title, stringValue, unit, sign }) => ( - <li key={dottedName}> - {dottedName} | {title} |{' '} - {stringValue ? `${sign} ${stringValue} ${unit}` : 'Non quantifiée'} - </li> - ))} - </ul> + {Object.values(actionsListByCategory).map( + (category) => + category?.actions && ( + <details key={category.dottedName}> + <summary> + {category.title} ({Object.values(category.actions).length}) + </summary> + <ul> + {Object.values(category.actions).map( + ({ dottedName, title, stringValue, unit, sign }) => ( + <li key={dottedName}> + {title} :{' '} + {stringValue + ? `${sign} ${stringValue} ${unit}` + : 'Non quantifiée'} + </li> + ) + )} + </ul> + </details> + ) + )} </div> ) } From 7a34a1dc203708bc45c5a45f4c9ea1cdfda9f571 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Mon, 17 Jul 2023 14:35:43 +0200 Subject: [PATCH 17/54] =?UTF-8?q?feat:=20info=20suppl=C3=A9mentaire=20sur?= =?UTF-8?q?=20le=20nombre=20d'actions=20=C3=A0=20impact?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/locales/ui/ui-en-us.yaml | 6 +++++ source/locales/ui/ui-fr.yaml | 6 +++++ .../publicodes/personas/RawActionsList.tsx | 24 +++++++++++++++++-- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/source/locales/ui/ui-en-us.yaml b/source/locales/ui/ui-en-us.yaml index cf179b051d..bbdaedd835 100644 --- a/source/locales/ui/ui-en-us.yaml +++ b/source/locales/ui/ui-en-us.yaml @@ -869,3 +869,9 @@ entries: Votre bilan climat personnel: Your personal climate report Personas: Personas Les questions du modèle Nos Gestes Climat: Nos Gestes Climat model questions + 'Les actions associées:': 'Associated actions:' + actions: actions + 'Description:': 'Description:' + 'proposées au total pour un empreinte de réduction cumulée de ': 'for a cumulative reduction footprint of ' + ' présentent un impact de plus de 1 tonne de CO2e,': ' have an impact of more than 1 tonne of CO2e,' + plus de 100 kgCO2e: more than 100 kgCO2e diff --git a/source/locales/ui/ui-fr.yaml b/source/locales/ui/ui-fr.yaml index 98cfc10349..35a059010d 100644 --- a/source/locales/ui/ui-fr.yaml +++ b/source/locales/ui/ui-fr.yaml @@ -669,3 +669,9 @@ entries: Les questions du modèle Nos Gestes Climat: Les questions du modèle Nos Gestes Climat Personas: Personas Votre bilan climat personnel: Votre bilan climat personnel + ' présentent un impact de plus de 1 tonne de CO2e,': ' présentent un impact de plus de 1 tonne de CO2e,' + actions: actions + 'Description:': 'Description:' + 'Les actions associées:': 'Les actions associées:' + plus de 100 kgCO2e: plus de 100 kgCO2e + 'proposées au total pour un empreinte de réduction cumulée de ': 'proposées au total pour un empreinte de réduction cumulée de ' diff --git a/source/sites/publicodes/personas/RawActionsList.tsx b/source/sites/publicodes/personas/RawActionsList.tsx index 5f7bffe8cc..8b5a3f75dc 100644 --- a/source/sites/publicodes/personas/RawActionsList.tsx +++ b/source/sites/publicodes/personas/RawActionsList.tsx @@ -80,14 +80,31 @@ export default () => { ) const numberOfActions = actionsList.length + + const numberOfActionsWithImpact = actionsList.reduce( + (obj, { correctedValue, sign }) => { + if (correctedValue > 1000 && sign === '-') { + obj['> 1 tonne'] += 1 + return obj + } else if (correctedValue > 100 && sign === '-') { + obj['> 100 kgCO2e'] += 1 + return obj + } else { + return obj + } + }, + { '> 100 kgCO2e': 0, '> 1 tonne': 0 } + ) + const rawTotalReduction = actionsList.reduce( (acc, { correctedValue, sign }) => { if (correctedValue) { - return sign === '+' ? acc + correctedValue : acc - correctedValue + return sign === '+' ? acc - correctedValue : acc + correctedValue } else return acc }, 0 ) + const [totalReduction, unit] = humanWeight( { t, i18n }, rawTotalReduction, @@ -110,7 +127,10 @@ export default () => { <strong> {totalReduction} {unit} </strong> - . + . {numberOfActionsWithImpact['> 1 tonne']} + <Trans> présentent un impact de plus de 1 tonne de CO2e,</Trans>{' '} + {numberOfActionsWithImpact['> 100 kgCO2e']}{' '} + <Trans>plus de 100 kgCO2e</Trans>. </p> {Object.values(actionsListByCategory).map( (category) => From 5beaab553685893dd09a11942ebefeb91bd30fe6 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Mon, 17 Jul 2023 14:36:06 +0200 Subject: [PATCH 18/54] fix: ordre liste --- source/sites/publicodes/Personas.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index ba7dd7f769..251799c5e5 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -32,6 +32,7 @@ export type Personas = Array<Persona> const Nothing = () => null const visualisationChoices = { + aucun: { titre: 'Aucun', composant: Nothing }, summary: { titre: 'Description', composant: Summary }, actionList: { titre: 'Actions associées', composant: RawActionsList }, profil: { titre: 'Détail Réponses', composant: AnswerList }, @@ -43,7 +44,6 @@ const visualisationChoices = { titre: 'Partage RS', composant: () => <FinShareButton showResult />, }, - aucun: { titre: 'Aucun', composant: Nothing }, } export default () => { From a24b1031dacae9844ce3a7626fa70a8bd4172668 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Mon, 17 Jul 2023 18:49:59 +0200 Subject: [PATCH 19/54] [WIP] feat: ajout de la liste des questions personas exhaustive --- source/sites/publicodes/Personas.tsx | 35 +++++++++++++ .../sites/publicodes/pages/QuestionList.tsx | 52 ++++++++++++++----- 2 files changed, 74 insertions(+), 13 deletions(-) diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index 251799c5e5..9740ab8ca4 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -16,6 +16,7 @@ import ActionSlide from './fin/ActionSlide' import Budget from './fin/Budget' import FinShareButton from './fin/FinShareButton' import { CardGrid } from './ListeActionPlus' +import { getQuestionList } from './pages/QuestionList' import RawActionsList from './personas/RawActionsList' import Summary from './personas/Summary' @@ -61,6 +62,16 @@ export default () => { visualisationChoices[`${visualisationParam}`]?.composant const engine = useEngine() + const rules = useSelector((state: AppState) => state.rules) + const rawQuestionList = getQuestionList(engine, rules) + const personasQuestionList = rawQuestionList.reduce((acc, rule) => { + if (rule.type !== '🪟 Mosaïque de type nombre') { + acc.push(rule.dottedName) + } + return acc + }, []) + + console.log(JSON.stringify(personasQuestionList)) const visualisationComponentProps = { score: engine.evaluate('bilan').nodeValue, @@ -170,6 +181,30 @@ export default () => { </Trans> . </p> + <h2> + <Trans>Liste des questions du modèle</Trans> + </h2> + <p> + <Trans i18nKey={'publicodes.Personas.listeQuestions'}> + La liste des questions du modèle est accessible sur la page{' '} + <a href="/questions">/questions</a> + </Trans> + . La liste exhaustive de toutes les règles pour définir un persona est : + </p> + <textarea + value={JSON.stringify(personasQuestionList)} + css={` + width: 90%; + `} + /> + <button + className="ui__ button small" + onClick={() => { + navigator.clipboard.writeText(JSON.stringify(personasQuestionList)) + }} + > + Copier le JSON + </button> </div> ) } diff --git a/source/sites/publicodes/pages/QuestionList.tsx b/source/sites/publicodes/pages/QuestionList.tsx index 2e39a9c4d0..b289fe55f7 100644 --- a/source/sites/publicodes/pages/QuestionList.tsx +++ b/source/sites/publicodes/pages/QuestionList.tsx @@ -1,5 +1,6 @@ import Title from '@/components/groupe/Title' import { + DottedName, getRelatedMosaicInfosIfExists, NGCRuleNode, NGCRulesNodes, @@ -21,19 +22,8 @@ export default () => { .map(([dottedName, v]) => ({ ...v, dottedName })) .filter((el) => el && el.question) - const jsonList = questionRules.map((rule) => { - const { type, mosaic } = getQuestionType(rules, rule) - const dependenciesData = computeDependencies(engine, rule) + const jsonList = getQuestionList(engine, rules) - return { - dottedName: rule.dottedName, - question: rule.question, - type, - catégorie: questionCategoryName(rule.dottedName), - 'dans mosaïque': mosaic != null, - dépendances: dependenciesData.map(([k, v]) => k), - } - }) const header = [ 'dottedName', 'question', @@ -43,6 +33,7 @@ export default () => { 'dépendances', ] const csv = toCSV(header, jsonList) + return ( <div> <Title title={<Trans>Les questions du modèle Nos Gestes Climat</Trans>} /> @@ -92,6 +83,37 @@ export default () => { ) } +type QuestionList = Array<{ + dottedName: DottedName + question: string + type: string + catégorie: string + 'dans mosaïque': boolean + dépendances: Array<any> +}> + +export const getQuestionList = (engine, rules) => { + const questionRules = Object.entries(rules) + .map(([dottedName, v]) => ({ ...v, dottedName })) + .filter((el) => el && el.question) + + const jsonList: QuestionList = questionRules.map((rule) => { + const { type, mosaic } = getQuestionType(rules, rule) + const dependenciesData = computeDependencies(engine, rule) + + return { + dottedName: rule.dottedName, + question: rule.question, + type, + catégorie: questionCategoryName(rule.dottedName), + 'dans mosaïque': mosaic != null, + dépendances: dependenciesData.map(([k, v]) => k), + } + }) + + return jsonList +} + const getQuestionType = (rules: NGCRulesNodes, rule: NGCRuleNode) => { const ruleMosaicInfos = getRelatedMosaicInfosIfExists(rules, rule.dottedName) const mosaicType = ruleMosaicInfos && ruleMosaicInfos[1].type @@ -180,7 +202,11 @@ const QuestionDescription = ({ engine, rule, rules }) => { <MissingVariables data={dependenciesData} /> </div> </summary> - <FriendlyObjectViewer data={rule} options={{ capitalise0: false }} /> + <FriendlyObjectViewer + data={rule} + context={false} + options={{ capitalise0: false }} + /> </details> </li> ) From 9e91077e3466a519f3301157192d5276176b1598 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Tue, 18 Jul 2023 08:58:27 +0200 Subject: [PATCH 20/54] feat: ajout de la liste des questions personas exhaustive --- source/sites/publicodes/Personas.tsx | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index 9740ab8ca4..487a16797e 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -6,6 +6,7 @@ import emoji from 'react-easy-emoji' import { Trans, useTranslation } from 'react-i18next' import { useDispatch, useSelector } from 'react-redux' import { useNavigate, useSearchParams } from 'react-router-dom' +import yaml from 'yaml' import { setDifferentSituation } from '../../actions/actions' import useBranchData from '../../components/useBranchData' import { useEngine } from '../../components/utils/EngineContext' @@ -64,14 +65,12 @@ export default () => { const engine = useEngine() const rules = useSelector((state: AppState) => state.rules) const rawQuestionList = getQuestionList(engine, rules) - const personasQuestionList = rawQuestionList.reduce((acc, rule) => { - if (rule.type !== '🪟 Mosaïque de type nombre') { - acc.push(rule.dottedName) + const personasQuestionList = rawQuestionList.reduce((obj, rule) => { + if (!rule.type.includes('Mosaïque')) { + obj[rule.dottedName] = '' } - return acc - }, []) - - console.log(JSON.stringify(personasQuestionList)) + return obj + }, {}) const visualisationComponentProps = { score: engine.evaluate('bilan').nodeValue, @@ -191,19 +190,22 @@ export default () => { </Trans> . La liste exhaustive de toutes les règles pour définir un persona est : </p> - <textarea - value={JSON.stringify(personasQuestionList)} + <pre + className="ui__ code" css={` - width: 90%; + font-size: 90%; + height: 10rem; `} - /> + > + <code>{yaml.stringify(personasQuestionList)}</code> + </pre> <button className="ui__ button small" onClick={() => { navigator.clipboard.writeText(JSON.stringify(personasQuestionList)) }} > - Copier le JSON + <Trans>Copier le YAML</Trans> </button> </div> ) From 31612b17f9b41c0a09a881128c9785a87760951c Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Tue, 18 Jul 2023 08:58:51 +0200 Subject: [PATCH 21/54] feat: ajout composant RulesCompletion --- source/sites/publicodes/Personas.tsx | 6 ++ .../publicodes/personas/RulesCompletion.tsx | 94 +++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 source/sites/publicodes/personas/RulesCompletion.tsx diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index 487a16797e..beaf914812 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -19,6 +19,7 @@ import FinShareButton from './fin/FinShareButton' import { CardGrid } from './ListeActionPlus' import { getQuestionList } from './pages/QuestionList' import RawActionsList from './personas/RawActionsList' +import RulesCompletion from './personas/RulesCompletion' import Summary from './personas/Summary' export type Persona = { @@ -37,6 +38,10 @@ const visualisationChoices = { aucun: { titre: 'Aucun', composant: Nothing }, summary: { titre: 'Description', composant: Summary }, actionList: { titre: 'Actions associées', composant: RawActionsList }, + exhaustivite: { + titre: 'Exhaustivité des règles', + composant: RulesCompletion, + }, profil: { titre: 'Détail Réponses', composant: AnswerList }, ravijen: { titre: 'Graphe Bilan', composant: RavijenChart }, budget: { titre: 'Page de fin - Budget', composant: Budget }, @@ -76,6 +81,7 @@ export default () => { score: engine.evaluate('bilan').nodeValue, headlessMode: true, engine: engine, + rules: rules, persona: selectedPersona, } diff --git a/source/sites/publicodes/personas/RulesCompletion.tsx b/source/sites/publicodes/personas/RulesCompletion.tsx new file mode 100644 index 0000000000..1531357bb8 --- /dev/null +++ b/source/sites/publicodes/personas/RulesCompletion.tsx @@ -0,0 +1,94 @@ +import { NGCRules } from '@/components/publicodesUtils' +import Engine from 'publicodes' +import { Trans } from 'react-i18next' +import { getQuestionList } from '../pages/QuestionList' +import { Persona } from '../Personas' + +export default ({ + engine, + rules, + persona, +}: { + engine: Engine + rules: NGCRules + persona: Persona +}) => { + const rawQuestionList = getQuestionList(engine, rules) + const completeQuestionList = rawQuestionList.reduce((arr, rule) => { + if (!rule.type.includes('Mosaïque')) { + arr.push(rule.dottedName) + } + return arr + }, []) + + const intersectListToExclude = Object.keys(persona?.data).filter( + (dottedName) => !completeQuestionList.includes(dottedName) + ) + const intersectListToInclude = completeQuestionList.filter( + (dottedName) => !Object.keys(persona?.data).includes(dottedName) + ) + + return ( + <div> + <h2> + <Trans>Complétude des règles du personas:</Trans> + </h2> + {Object.keys(persona?.data).length === 0 ? ( + <p> + <Trans>C'est le persona par défaut.</Trans> + </p> + ) : ( + <div> + {intersectListToInclude.length === 0 ? ( + <p> + <Trans>✅ Aucune règle du modèle est absente du persona.</Trans> + </p> + ) : ( + <details> + <summary> + {intersectListToInclude.length}{' '} + {intersectListToInclude.length === 1 ? ( + <Trans>règle est absente du persona</Trans> + ) : ( + <Trans>règles sont absentes du persona</Trans> + )} + </summary> + <ul> + {intersectListToInclude.map((dottedName) => ( + <li key={dottedName}>{dottedName}</li> + ))} + </ul> + </details> + )} + {intersectListToExclude.length === 0 ? ( + <p> + <Trans>✅ Aucune règle du persona n'est absente du modèle.</Trans> + </p> + ) : ( + <details> + <summary> + {intersectListToExclude.length}{' '} + {intersectListToExclude.length === 1 ? ( + <Trans> + règle a été définie dans le persona mais est absente du + modèle + </Trans> + ) : ( + <Trans> + règles ont été définies dans le persona mais sont absentes + du modèle + </Trans> + )} + </summary> + <ul> + {intersectListToExclude.map((dottedName) => ( + <li key={dottedName}>{dottedName}</li> + ))} + </ul> + </details> + )} + </div> + )} + </div> + ) +} From d6ac9f5b91b98d6eda54689b5d070424663cc35a Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Tue, 18 Jul 2023 08:59:13 +0200 Subject: [PATCH 22/54] feat: rules dans les props de RawActionsList --- source/sites/publicodes/personas/RawActionsList.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/source/sites/publicodes/personas/RawActionsList.tsx b/source/sites/publicodes/personas/RawActionsList.tsx index 8b5a3f75dc..d3c6f2fe53 100644 --- a/source/sites/publicodes/personas/RawActionsList.tsx +++ b/source/sites/publicodes/personas/RawActionsList.tsx @@ -2,20 +2,18 @@ import { Category, DottedName, extractCategoriesNamespaces, + NGCRules, splitName, } from '@/components/publicodesUtils' import { useEngine } from '@/components/utils/EngineContext' -import { AppState } from '@/reducers/rootReducer' import { Trans, useTranslation } from 'react-i18next' -import { useSelector } from 'react-redux' import { getFormattedActionValue } from '../ActionVignette' import { humanWeight } from '../HumanWeight' import useActions from '../useActions' -export default () => { +export default ({ rules }: { rules: NGCRules }) => { const { t, i18n } = useTranslation() const engine = useEngine() - const rules = useSelector((state: AppState) => state.rules) const { interestingActions: actionResultsRaw } = useActions({ focusedAction: null, rules, From e6569495da6a1ca56cc66c063a2bd957d9f6d84b Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Tue, 18 Jul 2023 12:03:33 +0200 Subject: [PATCH 23/54] feat: ajout explications personas --- source/sites/publicodes/Personas.tsx | 226 +++++++++++++++++++-------- 1 file changed, 165 insertions(+), 61 deletions(-) diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index beaf914812..6fe4f605a5 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -152,67 +152,7 @@ export default () => { </div> )} <PersonaGrid selectedPersona={selectedPersona} /> - <p> - <Trans i18nKey={'publicodes.Personas.description'}> - Les personas nous permettront de prendre le parti d'une diversité - d'utilisateurs quand ils voient notamment notre écran "passer à - l'action". - </Trans> - </p> - <h2> - <Trans>Comment créer un persona ?</Trans> - </h2> - <p> - <Trans>C'est dans le fichier</Trans>{' '} - <a href="https://github.com/datagir/nosgestesclimat-site/blob/master/source/sites/publicodes/personas.yaml"> - personas.yaml - </a>{' '} - <Trans i18nKey={'publicodes.Personas.tuto'}> - que ça se passe. On peut soit copier coller les données d'un autre - persona et les modifier, soit en créer un de zéro depuis la - simulation. Une fois la simulation satisfaisante, cliquer sur - "Modifier mes réponses" puis taper Ctrl-C, ouvrir la console du - navigateur (F12), vérifiez bien que vous êtes dans l'onglet "Console", - allez tout en bas de la console (elle est un peu chargée...), puis - copier le JSON affiché, le coller dans{' '} - <a href="https://www.json2yaml.com">cet outil</a> pour générer un - YAML, puis l'insérer dans personas.yaml. - </Trans> - </p> - <p> - <Trans i18nKey={'publicodes.Personas.lienGenerateur'}> - Pour les prénoms, on peut utiliser{' '} - <a href="https://lorraine-hipseau.me">ce générateur</a> - </Trans> - . - </p> - <h2> - <Trans>Liste des questions du modèle</Trans> - </h2> - <p> - <Trans i18nKey={'publicodes.Personas.listeQuestions'}> - La liste des questions du modèle est accessible sur la page{' '} - <a href="/questions">/questions</a> - </Trans> - . La liste exhaustive de toutes les règles pour définir un persona est : - </p> - <pre - className="ui__ code" - css={` - font-size: 90%; - height: 10rem; - `} - > - <code>{yaml.stringify(personasQuestionList)}</code> - </pre> - <button - className="ui__ button small" - onClick={() => { - navigator.clipboard.writeText(JSON.stringify(personasQuestionList)) - }} - > - <Trans>Copier le YAML</Trans> - </button> + <PersonaExplanations personasQuestionList={personasQuestionList} /> </div> ) } @@ -323,3 +263,167 @@ export const PersonaGrid = ({ </CardGrid> ) } + +export const PersonaExplanations = (personasQuestionList) => { + return ( + <div + css={` + h2 { + display: inline; + } + details { + padding-bottom: 1rem; + } + `} + > + <details> + <summary> + <h2> + <Trans>Qui sont-ils ?</Trans> + </h2> + </summary> + <div> + <Trans i18nKey={'publicodes.Personas.description'}> + Nous les avons définis pour qu’ils représentent la diversité des cas + d’usage du simulateur.{' '} + <i> + Toute ressemblance avec une personne existant ou ayant existé + serait purement fortuite ! + </i>{' '} + En aucune mesure, on ne peut dire qu’ils sont représentatifs de la + distribution de la population française : il ne s’agit pas de coller + aux statistiques de la population, mais de retrouver parmi nos dix + personas au moins un qui représente chaque usage majeur et + différenciant pour le simulateur. Ainsi, nous avons fait varier pour + chacun d’entre eux : + <ul> + <li> + Leur genre : même s’il n’influe pas sur l’empreinte, il serait + étonnant de n’avoir que des personas “femmes”. + </li>{' '} + <li> + Leur âge et situation personnelle / professionnelle : au moins + un étudiant, un retraité, un adulte au foyer + </li>{' '} + <li> + La taille de leur foyer : de 1 personne à famille nombreuse + </li>{' '} + <li> + Leur lieu de vie : de l’urbain, du rural et du péri-urbain, dans + le nord, dans le sud, les plaines, la montagne et sur une île + </li>{' '} + <li> + Leur logement : de l’appartement à la maison, du neuf à l’ancien + </li> + <li> + Leurs modes de transport : de la marche à la voiture en passant + par le ferry et l’avion + </li>{' '} + <li> + Leur régime alimentaire : au moins un végétalien, un végétarien, + une personne ne mangeant que du poisson, et un amateur de viande + rouge + </li>{' '} + <li> + Leur tendance à l’achat : du tout occasion au tout neuf, de + l’acheteur compulsif à celui ou celle qui n’achète presque rien + </li>{' '} + <li> + Leur façon de partir en vacances : mode de transport, + hébergement, on trouve de tout + </li>{' '} + <li>Leurs loisirs : de la culture, du sport, du bien-être…</li> + </ul> + </Trans> + </div> + </details> + <details> + <summary> + <h2> + <Trans>Comment créer un persona ?</Trans> + </h2> + </summary> + <div> + <Trans>C'est dans le fichier</Trans>{' '} + <a href="https://github.com/datagir/nosgestesclimat-site/blob/master/source/sites/publicodes/personas.yaml"> + personas.yaml + </a>{' '} + <Trans i18nKey={'publicodes.Personas.tuto'}> + que ça se passe. On peut soit copier coller les données d'un autre + persona et les modifier, soit en créer un de zéro depuis la + simulation. Une fois la simulation satisfaisante, cliquer sur + "Modifier mes réponses" puis taper Ctrl-C, ouvrir la console du + navigateur (F12), vérifiez bien que vous êtes dans l'onglet + "Console", allez tout en bas de la console (elle est un peu + chargée...), puis copier le JSON affiché, le coller dans{' '} + <a href="https://www.json2yaml.com">cet outil</a> pour générer un + YAML, puis l'insérer dans personas.yaml. + </Trans> + </div> + <p> + <Trans i18nKey={'publicodes.Personas.lienGenerateur'}> + Pour les prénoms, on peut utiliser{' '} + <a href="https://lorraine-hipseau.me">ce générateur</a> + </Trans> + . + </p> + </details> + <details> + <summary> + <h2> + <Trans>Quelle est la liste des questions du modèle ?</Trans> + </h2> + </summary> + <div> + <Trans i18nKey={'publicodes.Personas.listeQuestions'}> + La liste des questions du modèle est accessible sur la page{' '} + <a href="/questions">/questions</a> + </Trans> + . La liste exhaustive de toutes les règles pour définir un persona est + : + </div> + <pre + className="ui__ code" + css={` + font-size: 90%; + height: 10rem; + `} + > + <code>{yaml.stringify(personasQuestionList)}</code> + </pre> + <button + className="ui__ button small" + onClick={() => { + navigator.clipboard.writeText(JSON.stringify(personasQuestionList)) + }} + > + <Trans>Copier le YAML</Trans> + </button> + </details> + <details> + <summary> + <h2> + <Trans>Comment les mettons-nous à jour ?</Trans> + </h2> + </summary> + <div> + <Trans> + Pour qu’ils ou elles continuent de représenter la diversité des cas + d’usage du simulateur d’empreinte carbone, nous les éditons à chaque + ajout ou modification de ce dernier, en respectant les règles + suivantes : + <ul> + <li> + Chaque réponse possible est attribuée à au moins un persona + </li>{' '} + <li> + Au moins un persona ne répond rien à la question (il lui est + donc attribué la valeur par défaut donnée dans le simulateur). + </li> + </ul> + </Trans> + </div> + </details> + </div> + ) +} From b1a9a54d35e1f9dee1acb833df8cd96160bb3a02 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Tue, 18 Jul 2023 12:03:47 +0200 Subject: [PATCH 24/54] fix: affichage mobile --- source/sites/publicodes/Personas.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index 6fe4f605a5..aacabb5bf3 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -95,6 +95,9 @@ export default () => { flex-direction: row; align-items: center; margin-bottom: 1rem; + @media (max-width: 800px) { + flex-direction: column; + } `} > <div> From 3ee428e6844f2d1085175412f09eb489242279a8 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Tue, 18 Jul 2023 12:03:56 +0200 Subject: [PATCH 25/54] feat: ajout intro --- source/sites/publicodes/Personas.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index aacabb5bf3..a2c4d8d3c6 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -101,6 +101,17 @@ export default () => { `} > <div> + <p> + <Trans> + Les personas nous servent à tester le simulateur sous toutes ses + coutures, et à vérifier qu’il s’adapte bien à toutes les + situations de vie des citoyens métropolitains. De par leur + présence, ils nous forcent à penser à tous les cas d’usage, pour + nous projeter dans différentes réalités, et inclure ces réalités + dans nos refontes du parcours de test et des actions proposées à + la fin de ce dernier.{' '} + </Trans> + </p> <p> <Trans> Cette page vous permet de naviguer les parcours Nos Gestes Climat From 81232541654d6ca2145b30987b18e63d03c7a684 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Tue, 18 Jul 2023 12:04:18 +0200 Subject: [PATCH 26/54] fix: css grille personas --- source/sites/publicodes/Personas.tsx | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index a2c4d8d3c6..1a2a11a700 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -238,7 +238,15 @@ export const PersonaGrid = ({ } return ( - <CardGrid css="padding: 0; justify-content: center"> + <CardGrid + css={` + padding: 0; + justify-content: center; + li { + margin: 0.4rem; + } + `} + > {personasList.map((persona) => { const { nom, icônes, description, résumé } = persona return ( @@ -248,9 +256,10 @@ export const PersonaGrid = ({ selectedPersona?.nom === nom ? 'selected' : '' }`} css={` - width: 13rem !important; - height: 15rem !important; - padding: 0.75rem 0.5rem 0.75rem 0.5rem !important; + width: 11rem !important; + height: 13rem !important; + padding: 0.5rem 0.25rem 0.5rem 0.25rem !important; + margin: 0 !important; img { margin-bottom: 0.5rem; } @@ -261,7 +270,7 @@ export const PersonaGrid = ({ css={` text-transform: uppercase; color: var(--color); - font-size: 90%; + font-size: 80%; `} > <div>{emoji(icônes || '👥')}</div> From 9dbfd31fff1a586e96992f03c564daf59a604bda Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Tue, 18 Jul 2023 12:18:13 +0200 Subject: [PATCH 27/54] fix: traduction --- source/locales/ui/ui-en-us.yaml | 22 ++++++++++++++++++++-- source/locales/ui/ui-fr.yaml | 18 +++++++++++++++++- source/sites/publicodes/Personas.tsx | 2 +- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/source/locales/ui/ui-en-us.yaml b/source/locales/ui/ui-en-us.yaml index bbdaedd835..9e423ef9ab 100644 --- a/source/locales/ui/ui-en-us.yaml +++ b/source/locales/ui/ui-en-us.yaml @@ -456,8 +456,8 @@ entries: publicodes.Landing.question.lock: Connaissez-vous votre empreinte sur le climat ? publicodes.LandingExplanations.question: Do you know your climate footprint? publicodes.LandingExplanations.question.lock: Connaissez-vous votre empreinte sur le climat ? - publicodes.Personas.description: Personas will allow us to take the side of a diversity of users when they see our "take action" screen. - publicodes.Personas.description.lock: Les personas nous permettront de prendre le parti d'une diversité d'utilisateurs quand ils voient notamment notre écran "passer à l'action". + publicodes.Personas.description: 'We''ve defined them to represent the diversity of simulator use cases. <2>Any resemblance to an existing or former person is purely coincidental!</2> In no way can we say that they are representative of the distribution of the French population: the aim is not to stick to population statistics, but to find among our ten personas at least one that represents each major and differentiating use for the simulator. So, for each of them, we varied..:<5><0>Their gender: even if it has no influence on the footprint, it would be surprising to have only "female" personas.</0> <2>Age and personal/professional situation: at least one student, one retired person, one stay-at-home adult</2> <4>Household size: from 1 person to large families</4> <6>Where they live: urban, rural and suburban, in the north, south, plains, mountains and on an island</6> <8>Where they live: from apartments to houses, from new to old buildings</8><9>Means of transport: from walking to driving, from ferries to planes</9> <11>Diet: at least one vegan, one vegetarian, one fish-eater and one red meat lover</11> <13>Their buying habits: from second-hand to brand-new, from the compulsive shopper to the person who buys next to nothing</13> <15>The way they go on vacation: transport, accommodation, you name it, we''ve got it</15> <17>Their hobbies: culture, sport, well-being..</17></5>' + publicodes.Personas.description.lock: 'Nous les avons définis pour qu’ils représentent la diversité des cas d’usage du simulateur. <2>Toute ressemblance avec une personne existant ou ayant existé serait purement fortuite !</2> En aucune mesure, on ne peut dire qu’ils sont représentatifs de la distribution de la population française : il ne s’agit pas de coller aux statistiques de la population, mais de retrouver parmi nos dix personas au moins un qui représente chaque usage majeur et différenciant pour le simulateur. Ainsi, nous avons fait varier pour chacun d’entre eux :<5><0>Leur genre : même s’il n’influe pas sur l’empreinte, il serait étonnant de n’avoir que des personas “femmes”.</0> <2>Leur âge et situation personnelle / professionnelle : au moins un étudiant, un retraité, un adulte au foyer</2> <4>La taille de leur foyer : de 1 personne à famille nombreuse</4> <6>Leur lieu de vie : de l’urbain, du rural et du péri-urbain, dans le nord, dans le sud, les plaines, la montagne et sur une île</6> <8>Leur logement : de l’appartement à la maison, du neuf à l’ancien</8><9>Leurs modes de transport : de la marche à la voiture en passant par le ferry et l’avion</9> <11>Leur régime alimentaire : au moins un végétalien, un végétarien, une personne ne mangeant que du poisson, et un amateur de viande rouge</11> <13>Leur tendance à l’achat : du tout occasion au tout neuf, de l’acheteur compulsif à celui ou celle qui n’achète presque rien</13> <15>Leur façon de partir en vacances : mode de transport, hébergement, on trouve de tout</15> <17>Leurs loisirs : de la culture, du sport, du bien-être…</17></5>' publicodes.Personas.lienGenerateur: For the first names, you can use <2>this generator</2> publicodes.Personas.lienGenerateur.lock: Pour les prénoms, on peut utiliser <2>ce générateur</2> publicodes.Personas.tuto: that it happens. You can either copy and paste data from another persona and modify it, or create one from scratch from the simulation. Once the simulation is satisfactory, click on "Modify my answers" then type Ctrl-C, open the browser console (F12), make sure you are in the "Console" tab, go to the very bottom of the console (it is a bit busy...), then copy the JSON displayed, paste it into <2>this tool</2> to generate a YAML, then insert it into personas.yaml. @@ -875,3 +875,21 @@ entries: 'proposées au total pour un empreinte de réduction cumulée de ': 'for a cumulative reduction footprint of ' ' présentent un impact de plus de 1 tonne de CO2e,': ' have an impact of more than 1 tonne of CO2e,' plus de 100 kgCO2e: more than 100 kgCO2e + Qui sont-ils ?: Who are they? + C'est le persona par défaut.: It's the default persona. + règle est absente du persona: rule is absent from the persona + ✅ Aucune règle du persona n'est absente du modèle.: ✅ No persona rules are missing from the model. + Liste des questions du modèle: List of template questions + publicodes.Personas.listeQuestions: The list of questions in the template is available on the <2>/questions</2> page + publicodes.Personas.listeQuestions.lock: La liste des questions du modèle est accessible sur la page <2>/questions</2> + Copier le YAML: Copy YAML + 'Complétude des règles du personas:': 'Completeness of personas rules:' + règles sont absentes du persona: rules are absent from the persona + règles ont été définies dans le persona mais sont absentes du modèle: rules have been defined in the persona but are absent from the model + règle a été définie dans le persona mais est absente du modèle: rule has been defined in the persona but is absent from the model + ✅ Aucune règle du modèle est absente du persona.: ✅ No model rule is missing from the persona. + Comment les mettons-nous à jour ?: How do we update them? + Quelle est la liste des questions du modèle ?: What is the list of questions in the template? + 'Les personas nous servent à tester le simulateur sous toutes ses coutures, et à vérifier qu’il s’adapte bien à toutes les situations de vie des citoyens métropolitains. De par leur présence, ils nous forcent à penser à tous les cas d’usage, pour nous projeter dans différentes réalités, et inclure ces réalités dans nos refontes du parcours de test et des actions proposées à la fin de ce dernier. ': 'The personas help us to test the simulator from every angle, and to check that it can be adapted to all the life situations of metropolitan citizens. By their very presence, they force us to think of all possible use cases, to project ourselves into different realities, and to include these realities in our redesigns of the test path and the actions proposed at the end of it. ' + publicodes.Personas.maj: To ensure that they continue to represent the diversity of the carbon footprint simulator's use cases, we edit them each time the simulator is added or modified, in accordance with the following rules:<1><0>Each possible answer is assigned to at least one persona</0> <2>At least one persona gives no answer to the question (and is therefore assigned the default value given in the simulator).</2></1> + publicodes.Personas.maj.lock: Pour qu’ils ou elles continuent de représenter la diversité des cas d’usage du simulateur d’empreinte carbone, nous les éditons à chaque ajout ou modification de ce dernier, en respectant les règles suivantes :<1><0>Chaque réponse possible est attribuée à au moins un persona</0> <2>Au moins un persona ne répond rien à la question (il lui est donc attribué la valeur par défaut donnée dans le simulateur).</2></1> diff --git a/source/locales/ui/ui-fr.yaml b/source/locales/ui/ui-fr.yaml index 35a059010d..35e9e46058 100644 --- a/source/locales/ui/ui-fr.yaml +++ b/source/locales/ui/ui-fr.yaml @@ -378,7 +378,7 @@ entries: publicodes.Contribution.translationWikiInvite: 'Suivez notre guide complet pour contribuer directement à la traduction du site : <2>rendez-vous sur notre wiki</2>.' publicodes.Landing.question: Connaissez-vous votre empreinte sur le climat ? publicodes.LandingExplanations.question: Connaissez-vous votre empreinte sur le climat ? - publicodes.Personas.description: Les personas nous permettront de prendre le parti d'une diversité d'utilisateurs quand ils voient notamment notre écran "passer à l'action". + publicodes.Personas.description: 'Nous les avons définis pour qu’ils représentent la diversité des cas d’usage du simulateur. <2>Toute ressemblance avec une personne existant ou ayant existé serait purement fortuite !</2> En aucune mesure, on ne peut dire qu’ils sont représentatifs de la distribution de la population française : il ne s’agit pas de coller aux statistiques de la population, mais de retrouver parmi nos dix personas au moins un qui représente chaque usage majeur et différenciant pour le simulateur. Ainsi, nous avons fait varier pour chacun d’entre eux :<5><0>Leur genre : même s’il n’influe pas sur l’empreinte, il serait étonnant de n’avoir que des personas “femmes”.</0> <2>Leur âge et situation personnelle / professionnelle : au moins un étudiant, un retraité, un adulte au foyer</2> <4>La taille de leur foyer : de 1 personne à famille nombreuse</4> <6>Leur lieu de vie : de l’urbain, du rural et du péri-urbain, dans le nord, dans le sud, les plaines, la montagne et sur une île</6> <8>Leur logement : de l’appartement à la maison, du neuf à l’ancien</8><9>Leurs modes de transport : de la marche à la voiture en passant par le ferry et l’avion</9> <11>Leur régime alimentaire : au moins un végétalien, un végétarien, une personne ne mangeant que du poisson, et un amateur de viande rouge</11> <13>Leur tendance à l’achat : du tout occasion au tout neuf, de l’acheteur compulsif à celui ou celle qui n’achète presque rien</13> <15>Leur façon de partir en vacances : mode de transport, hébergement, on trouve de tout</15> <17>Leurs loisirs : de la culture, du sport, du bien-être…</17></5>' publicodes.Personas.lienGenerateur: Pour les prénoms, on peut utiliser <2>ce générateur</2> publicodes.Personas.tuto: que ça se passe. On peut soit copier coller les données d'un autre persona et les modifier, soit en créer un de zéro depuis la simulation. Une fois la simulation satisfaisante, cliquer sur "Modifier mes réponses" puis taper Ctrl-C, ouvrir la console du navigateur (F12), vérifiez bien que vous êtes dans l'onglet "Console", allez tout en bas de la console (elle est un peu chargée...), puis copier le JSON affiché, le coller dans <2>cet outil</2> pour générer un YAML, puis l'insérer dans personas.yaml. publicodes.Personas.warningMsg: Sélectionner un persona releguera votre simulation en cours dans votre historique de simulations, accessible en bas de votre <2>page profil</2>. @@ -675,3 +675,19 @@ entries: 'Les actions associées:': 'Les actions associées:' plus de 100 kgCO2e: plus de 100 kgCO2e 'proposées au total pour un empreinte de réduction cumulée de ': 'proposées au total pour un empreinte de réduction cumulée de ' + ✅ Aucune règle du modèle est absente du persona.: ✅ Aucune règle du modèle est absente du persona. + ✅ Aucune règle du persona n'est absente du modèle.: ✅ Aucune règle du persona n'est absente du modèle. + C'est le persona par défaut.: C'est le persona par défaut. + 'Complétude des règles du personas:': 'Complétude des règles du personas:' + Copier le YAML: Copier le YAML + Liste des questions du modèle: Liste des questions du modèle + publicodes.Personas.listeQuestions: La liste des questions du modèle est accessible sur la page <2>/questions</2> + Qui sont-ils ?: Qui sont-ils ? + règle a été définie dans le persona mais est absente du modèle: règle a été définie dans le persona mais est absente du modèle + règle est absente du persona: règle est absente du persona + règles ont été définies dans le persona mais sont absentes du modèle: règles ont été définies dans le persona mais sont absentes du modèle + règles sont absentes du persona: règles sont absentes du persona + Comment les mettons-nous à jour ?: Comment les mettons-nous à jour ? + 'Les personas nous servent à tester le simulateur sous toutes ses coutures, et à vérifier qu’il s’adapte bien à toutes les situations de vie des citoyens métropolitains. De par leur présence, ils nous forcent à penser à tous les cas d’usage, pour nous projeter dans différentes réalités, et inclure ces réalités dans nos refontes du parcours de test et des actions proposées à la fin de ce dernier. ': 'Les personas nous servent à tester le simulateur sous toutes ses coutures, et à vérifier qu’il s’adapte bien à toutes les situations de vie des citoyens métropolitains. De par leur présence, ils nous forcent à penser à tous les cas d’usage, pour nous projeter dans différentes réalités, et inclure ces réalités dans nos refontes du parcours de test et des actions proposées à la fin de ce dernier. ' + publicodes.Personas.maj: Pour qu’ils ou elles continuent de représenter la diversité des cas d’usage du simulateur d’empreinte carbone, nous les éditons à chaque ajout ou modification de ce dernier, en respectant les règles suivantes :<1><0>Chaque réponse possible est attribuée à au moins un persona</0> <2>Au moins un persona ne répond rien à la question (il lui est donc attribué la valeur par défaut donnée dans le simulateur).</2></1> + Quelle est la liste des questions du modèle ?: Quelle est la liste des questions du modèle ? diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index 1a2a11a700..34606de001 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -430,7 +430,7 @@ export const PersonaExplanations = (personasQuestionList) => { </h2> </summary> <div> - <Trans> + <Trans i18nKey={'publicodes.Personas.maj'}> Pour qu’ils ou elles continuent de représenter la diversité des cas d’usage du simulateur d’empreinte carbone, nous les éditons à chaque ajout ou modification de ce dernier, en respectant les règles From fc44334c4091faf12419852a146571a9551bc409 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Tue, 18 Jul 2023 14:29:58 +0200 Subject: [PATCH 28/54] fix: passing props --- source/sites/publicodes/Personas.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index 34606de001..fde9d29bd8 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -287,7 +287,7 @@ export const PersonaGrid = ({ ) } -export const PersonaExplanations = (personasQuestionList) => { +export const PersonaExplanations = ({ personasQuestionList }) => { return ( <div css={` From dbfe4cb2c0e1929f4fba79ed781b88b1c44610bf Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Tue, 18 Jul 2023 16:09:03 +0200 Subject: [PATCH 29/54] fix: wrong imports --- source/sites/publicodes/Personas.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index fde9d29bd8..8f43231143 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -1,6 +1,7 @@ import AnswerList from '@/components/conversation/AnswerList' import Title from '@/components/groupe/Title' -import { AppState, Simulation, Situation } from '@/reducers/rootReducer' +import { AppState } from '@/reducers/rootReducer' +import { Simulation, Situation } from '@/types/simulation' import { useEffect, useState } from 'react' import emoji from 'react-easy-emoji' import { Trans, useTranslation } from 'react-i18next' From ccd7e486510a2e55d9d22924c4813f56bda33567 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Tue, 18 Jul 2023 16:19:04 +0200 Subject: [PATCH 30/54] =?UTF-8?q?feat:=20suppression=20du=20block=20"Comme?= =?UTF-8?q?nt=20cr=C3=A9er=20un=20persona"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/locales/ui/ui-en-us.yaml | 4 +- source/locales/ui/ui-fr.yaml | 2 +- source/sites/publicodes/Personas.tsx | 80 +++++++++------------------- 3 files changed, 29 insertions(+), 57 deletions(-) diff --git a/source/locales/ui/ui-en-us.yaml b/source/locales/ui/ui-en-us.yaml index 9e423ef9ab..41cbff1aaa 100644 --- a/source/locales/ui/ui-en-us.yaml +++ b/source/locales/ui/ui-en-us.yaml @@ -880,8 +880,8 @@ entries: règle est absente du persona: rule is absent from the persona ✅ Aucune règle du persona n'est absente du modèle.: ✅ No persona rules are missing from the model. Liste des questions du modèle: List of template questions - publicodes.Personas.listeQuestions: The list of questions in the template is available on the <2>/questions</2> page - publicodes.Personas.listeQuestions.lock: La liste des questions du modèle est accessible sur la page <2>/questions</2> + publicodes.Personas.listeQuestions: 'The list of template questions is available on the <2>/questions</2> page. The exhaustive list of all the rules for defining a persona is :' + publicodes.Personas.listeQuestions.lock: 'La liste des questions du modèle est accessible sur la page <2>/questions</2>. La liste exhaustive de toutes les règles pour définir un persona est :' Copier le YAML: Copy YAML 'Complétude des règles du personas:': 'Completeness of personas rules:' règles sont absentes du persona: rules are absent from the persona diff --git a/source/locales/ui/ui-fr.yaml b/source/locales/ui/ui-fr.yaml index 35e9e46058..ba65fd0d4a 100644 --- a/source/locales/ui/ui-fr.yaml +++ b/source/locales/ui/ui-fr.yaml @@ -681,7 +681,7 @@ entries: 'Complétude des règles du personas:': 'Complétude des règles du personas:' Copier le YAML: Copier le YAML Liste des questions du modèle: Liste des questions du modèle - publicodes.Personas.listeQuestions: La liste des questions du modèle est accessible sur la page <2>/questions</2> + publicodes.Personas.listeQuestions: 'La liste des questions du modèle est accessible sur la page <2>/questions</2>. La liste exhaustive de toutes les règles pour définir un persona est :' Qui sont-ils ?: Qui sont-ils ? règle a été définie dans le persona mais est absente du modèle: règle a été définie dans le persona mais est absente du modèle règle est absente du persona: règle est absente du persona diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index 8f43231143..3830ec44f3 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -361,37 +361,6 @@ export const PersonaExplanations = ({ personasQuestionList }) => { </Trans> </div> </details> - <details> - <summary> - <h2> - <Trans>Comment créer un persona ?</Trans> - </h2> - </summary> - <div> - <Trans>C'est dans le fichier</Trans>{' '} - <a href="https://github.com/datagir/nosgestesclimat-site/blob/master/source/sites/publicodes/personas.yaml"> - personas.yaml - </a>{' '} - <Trans i18nKey={'publicodes.Personas.tuto'}> - que ça se passe. On peut soit copier coller les données d'un autre - persona et les modifier, soit en créer un de zéro depuis la - simulation. Une fois la simulation satisfaisante, cliquer sur - "Modifier mes réponses" puis taper Ctrl-C, ouvrir la console du - navigateur (F12), vérifiez bien que vous êtes dans l'onglet - "Console", allez tout en bas de la console (elle est un peu - chargée...), puis copier le JSON affiché, le coller dans{' '} - <a href="https://www.json2yaml.com">cet outil</a> pour générer un - YAML, puis l'insérer dans personas.yaml. - </Trans> - </div> - <p> - <Trans i18nKey={'publicodes.Personas.lienGenerateur'}> - Pour les prénoms, on peut utiliser{' '} - <a href="https://lorraine-hipseau.me">ce générateur</a> - </Trans> - . - </p> - </details> <details> <summary> <h2> @@ -399,30 +368,33 @@ export const PersonaExplanations = ({ personasQuestionList }) => { </h2> </summary> <div> - <Trans i18nKey={'publicodes.Personas.listeQuestions'}> - La liste des questions du modèle est accessible sur la page{' '} - <a href="/questions">/questions</a> - </Trans> - . La liste exhaustive de toutes les règles pour définir un persona est - : + <p> + <Trans i18nKey={'publicodes.Personas.listeQuestions'}> + La liste des questions du modèle est accessible sur la page{' '} + <a href="/questions">/questions</a>. La liste exhaustive de toutes + les règles pour définir un persona est : + </Trans> + </p> + <pre + className="ui__ code" + css={` + font-size: 90%; + height: 10rem; + `} + > + <code>{yaml.stringify(personasQuestionList)}</code> + </pre> + <button + className="ui__ button small" + onClick={() => { + navigator.clipboard.writeText( + JSON.stringify(personasQuestionList) + ) + }} + > + <Trans>Copier le YAML</Trans> + </button> </div> - <pre - className="ui__ code" - css={` - font-size: 90%; - height: 10rem; - `} - > - <code>{yaml.stringify(personasQuestionList)}</code> - </pre> - <button - className="ui__ button small" - onClick={() => { - navigator.clipboard.writeText(JSON.stringify(personasQuestionList)) - }} - > - <Trans>Copier le YAML</Trans> - </button> </details> <details> <summary> From 3e6bbdbdcc3a00cec4e2e456d7a810ef1e505a42 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Tue, 18 Jul 2023 18:12:08 +0200 Subject: [PATCH 31/54] =?UTF-8?q?feat:=20ajout=20des=20r=C3=A8gles=20manqu?= =?UTF-8?q?antes=20r=C3=A9pondues=20par=20d=C3=A9faut?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nosgestesclimat | 2 +- source/locales/ui/ui-fr.yaml | 8 +++ .../publicodes/personas/RulesCompletion.tsx | 66 ++++++++++++++----- 3 files changed, 58 insertions(+), 18 deletions(-) diff --git a/nosgestesclimat b/nosgestesclimat index 8a1f1dc9ab..1a4bb68cc3 160000 --- a/nosgestesclimat +++ b/nosgestesclimat @@ -1 +1 @@ -Subproject commit 8a1f1dc9aba90c3afda057b78a0f1a5e7c095903 +Subproject commit 1a4bb68cc33503d521f1a46edcb5f9ca8a679a74 diff --git a/source/locales/ui/ui-fr.yaml b/source/locales/ui/ui-fr.yaml index ba65fd0d4a..3f66b4009b 100644 --- a/source/locales/ui/ui-fr.yaml +++ b/source/locales/ui/ui-fr.yaml @@ -691,3 +691,11 @@ entries: 'Les personas nous servent à tester le simulateur sous toutes ses coutures, et à vérifier qu’il s’adapte bien à toutes les situations de vie des citoyens métropolitains. De par leur présence, ils nous forcent à penser à tous les cas d’usage, pour nous projeter dans différentes réalités, et inclure ces réalités dans nos refontes du parcours de test et des actions proposées à la fin de ce dernier. ': 'Les personas nous servent à tester le simulateur sous toutes ses coutures, et à vérifier qu’il s’adapte bien à toutes les situations de vie des citoyens métropolitains. De par leur présence, ils nous forcent à penser à tous les cas d’usage, pour nous projeter dans différentes réalités, et inclure ces réalités dans nos refontes du parcours de test et des actions proposées à la fin de ce dernier. ' publicodes.Personas.maj: Pour qu’ils ou elles continuent de représenter la diversité des cas d’usage du simulateur d’empreinte carbone, nous les éditons à chaque ajout ou modification de ce dernier, en respectant les règles suivantes :<1><0>Chaque réponse possible est attribuée à au moins un persona</0> <2>Au moins un persona ne répond rien à la question (il lui est donc attribué la valeur par défaut donnée dans le simulateur).</2></1> Quelle est la liste des questions du modèle ?: Quelle est la liste des questions du modèle ? + ✅ Aucune règle nécessitant un réponse n'a été répondue par défaut.: ✅ Aucune règle nécessitant un réponse n'a été répondue par défaut. + C'est le persona par défaut. Toutes les règles ont été répondues par défaut.: C'est le persona par défaut. Toutes les règles ont été répondues par défaut. + règle a été définie dans le persona mais est absente du modèle.: règle a été définie dans le persona mais est absente du modèle. + règle est absente du persona.: règle est absente du persona. + règle nécessitant une réponse a été répondue par défaut.: règle nécessitant une réponse a été répondue par défaut. + règles nécessitant une réponse ont été répondues par défaut.: règles nécessitant une réponse ont été répondues par défaut. + règles ont été définies dans le persona mais sont absentes du modèle.: règles ont été définies dans le persona mais sont absentes du modèle. + règles sont absentes du persona.: règles sont absentes du persona. diff --git a/source/sites/publicodes/personas/RulesCompletion.tsx b/source/sites/publicodes/personas/RulesCompletion.tsx index 1531357bb8..d66db36bfe 100644 --- a/source/sites/publicodes/personas/RulesCompletion.tsx +++ b/source/sites/publicodes/personas/RulesCompletion.tsx @@ -1,18 +1,13 @@ import { NGCRules } from '@/components/publicodesUtils' -import Engine from 'publicodes' +import { EngineContext } from '@/components/utils/EngineContext' +import { useContext } from 'react' import { Trans } from 'react-i18next' import { getQuestionList } from '../pages/QuestionList' import { Persona } from '../Personas' -export default ({ - engine, - rules, - persona, -}: { - engine: Engine - rules: NGCRules - persona: Persona -}) => { +export default ({ rules, persona }: { rules: NGCRules; persona: Persona }) => { + const engine = useContext(EngineContext) + const rawQuestionList = getQuestionList(engine, rules) const completeQuestionList = rawQuestionList.reduce((arr, rule) => { if (!rule.type.includes('Mosaïque')) { @@ -21,11 +16,17 @@ export default ({ return arr }, []) + const intersectListToInclude = completeQuestionList.filter( + (dottedName) => !Object.keys(persona?.data).includes(dottedName) + ) + const intersectListToExclude = Object.keys(persona?.data).filter( (dottedName) => !completeQuestionList.includes(dottedName) ) - const intersectListToInclude = completeQuestionList.filter( - (dottedName) => !Object.keys(persona?.data).includes(dottedName) + + const { missingVariables } = engine.evaluate('bilan') + const missingRules = Object.keys(missingVariables).filter((dottedName) => + completeQuestionList.includes(dottedName) ) return ( @@ -35,10 +36,41 @@ export default ({ </h2> {Object.keys(persona?.data).length === 0 ? ( <p> - <Trans>C'est le persona par défaut.</Trans> + <Trans> + C'est le persona par défaut. Toutes les règles ont été répondues par + défaut. + </Trans> </p> ) : ( <div> + {missingRules.length === 0 ? ( + <p> + <Trans> + ✅ Aucune règle nécessitant un réponse n'a été répondue par + défaut. + </Trans> + </p> + ) : ( + <details> + <summary> + {missingRules.length}{' '} + {missingRules.length === 1 ? ( + <Trans> + règle nécessitant une réponse a été répondue par défaut. + </Trans> + ) : ( + <Trans> + règles nécessitant une réponse ont été répondues par défaut. + </Trans> + )} + </summary> + <ul> + {missingRules.map((dottedName) => ( + <li key={dottedName}>{dottedName}</li> + ))} + </ul> + </details> + )} {intersectListToInclude.length === 0 ? ( <p> <Trans>✅ Aucune règle du modèle est absente du persona.</Trans> @@ -48,9 +80,9 @@ export default ({ <summary> {intersectListToInclude.length}{' '} {intersectListToInclude.length === 1 ? ( - <Trans>règle est absente du persona</Trans> + <Trans>règle est absente du persona.</Trans> ) : ( - <Trans>règles sont absentes du persona</Trans> + <Trans>règles sont absentes du persona.</Trans> )} </summary> <ul> @@ -71,12 +103,12 @@ export default ({ {intersectListToExclude.length === 1 ? ( <Trans> règle a été définie dans le persona mais est absente du - modèle + modèle. </Trans> ) : ( <Trans> règles ont été définies dans le persona mais sont absentes - du modèle + du modèle. </Trans> )} </summary> From 5d76f26223e88ffadc7ac1217744778f33602faf Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Tue, 18 Jul 2023 18:29:33 +0200 Subject: [PATCH 32/54] =?UTF-8?q?feat:=20ajout=20du=20nombre=20de=20r?= =?UTF-8?q?=C3=A8gles=20r=C3=A9pondues?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/locales/ui/ui-fr.yaml | 2 ++ source/sites/publicodes/personas/RulesCompletion.tsx | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/source/locales/ui/ui-fr.yaml b/source/locales/ui/ui-fr.yaml index 3f66b4009b..a7939b874d 100644 --- a/source/locales/ui/ui-fr.yaml +++ b/source/locales/ui/ui-fr.yaml @@ -699,3 +699,5 @@ entries: règles nécessitant une réponse ont été répondues par défaut.: règles nécessitant une réponse ont été répondues par défaut. règles ont été définies dans le persona mais sont absentes du modèle.: règles ont été définies dans le persona mais sont absentes du modèle. règles sont absentes du persona.: règles sont absentes du persona. + 'a répondu à ': 'a répondu à ' + questions: questions diff --git a/source/sites/publicodes/personas/RulesCompletion.tsx b/source/sites/publicodes/personas/RulesCompletion.tsx index d66db36bfe..1169935727 100644 --- a/source/sites/publicodes/personas/RulesCompletion.tsx +++ b/source/sites/publicodes/personas/RulesCompletion.tsx @@ -38,11 +38,16 @@ export default ({ rules, persona }: { rules: NGCRules; persona: Persona }) => { <p> <Trans> C'est le persona par défaut. Toutes les règles ont été répondues par - défaut. - </Trans> + défaut + </Trans>{' '} + ({completeQuestionList.length}). </p> ) : ( <div> + <p> + {persona?.nom} <Trans>a répondu à </Trans>{' '} + {Object.keys(persona?.data).length} <Trans>questions</Trans>. + </p> {missingRules.length === 0 ? ( <p> <Trans> From bdac32e1ff4d79e1951501ee1dde0587fbba2887 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Tue, 18 Jul 2023 18:45:32 +0200 Subject: [PATCH 33/54] feat: l'attribut `data` devient `situation` --- nosgestesclimat | 2 +- source/sites/publicodes/Personas.tsx | 4 ++-- source/sites/publicodes/personas/RulesCompletion.tsx | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/nosgestesclimat b/nosgestesclimat index 1a4bb68cc3..c05f94e93b 160000 --- a/nosgestesclimat +++ b/nosgestesclimat @@ -1 +1 @@ -Subproject commit 1a4bb68cc33503d521f1a46edcb5f9ca8a679a74 +Subproject commit c05f94e93bb5e74b0961e1aa9260fe17e1ad70c7 diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index 3830ec44f3..913fcbf4f9 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -26,7 +26,7 @@ import Summary from './personas/Summary' export type Persona = { nom: string icônes: string - data: Situation + situation: Situation description: string résumé: string } @@ -226,7 +226,7 @@ export const PersonaGrid = ({ config: { objectifs: [objectif] }, url: '/simulateur/bilan', // the schema of personas is not fixed yet - situation: persona.data.situation || persona.data, + situation: persona.situation, persona: persona, // If not specified, act as if all questions were answered : all that is not in // the situation object is a validated default value diff --git a/source/sites/publicodes/personas/RulesCompletion.tsx b/source/sites/publicodes/personas/RulesCompletion.tsx index 1169935727..e8b6a427f1 100644 --- a/source/sites/publicodes/personas/RulesCompletion.tsx +++ b/source/sites/publicodes/personas/RulesCompletion.tsx @@ -17,10 +17,10 @@ export default ({ rules, persona }: { rules: NGCRules; persona: Persona }) => { }, []) const intersectListToInclude = completeQuestionList.filter( - (dottedName) => !Object.keys(persona?.data).includes(dottedName) + (dottedName) => !Object.keys(persona?.situation).includes(dottedName) ) - const intersectListToExclude = Object.keys(persona?.data).filter( + const intersectListToExclude = Object.keys(persona?.situation).filter( (dottedName) => !completeQuestionList.includes(dottedName) ) @@ -34,7 +34,7 @@ export default ({ rules, persona }: { rules: NGCRules; persona: Persona }) => { <h2> <Trans>Complétude des règles du personas:</Trans> </h2> - {Object.keys(persona?.data).length === 0 ? ( + {Object.keys(persona?.situation).length === 0 ? ( <p> <Trans> C'est le persona par défaut. Toutes les règles ont été répondues par @@ -46,7 +46,7 @@ export default ({ rules, persona }: { rules: NGCRules; persona: Persona }) => { <div> <p> {persona?.nom} <Trans>a répondu à </Trans>{' '} - {Object.keys(persona?.data).length} <Trans>questions</Trans>. + {Object.keys(persona?.situation).length} <Trans>questions</Trans>. </p> {missingRules.length === 0 ? ( <p> From dc80cc6dc3015676438b361864ed7d0d7215d7eb Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Tue, 18 Jul 2023 19:04:49 +0200 Subject: [PATCH 34/54] fix: typos --- nosgestesclimat | 2 +- source/locales/ui/ui-en-us.yaml | 16 ++++++++++++++-- source/locales/ui/ui-fr.yaml | 4 +++- source/sites/publicodes/Personas.tsx | 9 +++++---- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/nosgestesclimat b/nosgestesclimat index c05f94e93b..4d7dcf5877 160000 --- a/nosgestesclimat +++ b/nosgestesclimat @@ -1 +1 @@ -Subproject commit c05f94e93bb5e74b0961e1aa9260fe17e1ad70c7 +Subproject commit 4d7dcf587722d17c151486a5cb24cc646775e384 diff --git a/source/locales/ui/ui-en-us.yaml b/source/locales/ui/ui-en-us.yaml index 41cbff1aaa..a2795f5991 100644 --- a/source/locales/ui/ui-en-us.yaml +++ b/source/locales/ui/ui-en-us.yaml @@ -456,8 +456,8 @@ entries: publicodes.Landing.question.lock: Connaissez-vous votre empreinte sur le climat ? publicodes.LandingExplanations.question: Do you know your climate footprint? publicodes.LandingExplanations.question.lock: Connaissez-vous votre empreinte sur le climat ? - publicodes.Personas.description: 'We''ve defined them to represent the diversity of simulator use cases. <2>Any resemblance to an existing or former person is purely coincidental!</2> In no way can we say that they are representative of the distribution of the French population: the aim is not to stick to population statistics, but to find among our ten personas at least one that represents each major and differentiating use for the simulator. So, for each of them, we varied..:<5><0>Their gender: even if it has no influence on the footprint, it would be surprising to have only "female" personas.</0> <2>Age and personal/professional situation: at least one student, one retired person, one stay-at-home adult</2> <4>Household size: from 1 person to large families</4> <6>Where they live: urban, rural and suburban, in the north, south, plains, mountains and on an island</6> <8>Where they live: from apartments to houses, from new to old buildings</8><9>Means of transport: from walking to driving, from ferries to planes</9> <11>Diet: at least one vegan, one vegetarian, one fish-eater and one red meat lover</11> <13>Their buying habits: from second-hand to brand-new, from the compulsive shopper to the person who buys next to nothing</13> <15>The way they go on vacation: transport, accommodation, you name it, we''ve got it</15> <17>Their hobbies: culture, sport, well-being..</17></5>' - publicodes.Personas.description.lock: 'Nous les avons définis pour qu’ils représentent la diversité des cas d’usage du simulateur. <2>Toute ressemblance avec une personne existant ou ayant existé serait purement fortuite !</2> En aucune mesure, on ne peut dire qu’ils sont représentatifs de la distribution de la population française : il ne s’agit pas de coller aux statistiques de la population, mais de retrouver parmi nos dix personas au moins un qui représente chaque usage majeur et différenciant pour le simulateur. Ainsi, nous avons fait varier pour chacun d’entre eux :<5><0>Leur genre : même s’il n’influe pas sur l’empreinte, il serait étonnant de n’avoir que des personas “femmes”.</0> <2>Leur âge et situation personnelle / professionnelle : au moins un étudiant, un retraité, un adulte au foyer</2> <4>La taille de leur foyer : de 1 personne à famille nombreuse</4> <6>Leur lieu de vie : de l’urbain, du rural et du péri-urbain, dans le nord, dans le sud, les plaines, la montagne et sur une île</6> <8>Leur logement : de l’appartement à la maison, du neuf à l’ancien</8><9>Leurs modes de transport : de la marche à la voiture en passant par le ferry et l’avion</9> <11>Leur régime alimentaire : au moins un végétalien, un végétarien, une personne ne mangeant que du poisson, et un amateur de viande rouge</11> <13>Leur tendance à l’achat : du tout occasion au tout neuf, de l’acheteur compulsif à celui ou celle qui n’achète presque rien</13> <15>Leur façon de partir en vacances : mode de transport, hébergement, on trouve de tout</15> <17>Leurs loisirs : de la culture, du sport, du bien-être…</17></5>' + publicodes.Personas.description: 'We''ve defined them to represent the diversity of simulator use cases. <2>Any resemblance to an existing or former person is purely coincidental!</2> In no way can we say that they are representative of the distribution of the French population: the aim is not to stick to population statistics, but to find among our ten personas at least one that represents each major and differentiating use for the simulator. So, for each of them, we varied..:<5><0>Their gender: even if it has no influence on the footprint, it would be surprising to have only "female" personas</0> <2>Age and personal/professional situation: at least one student, one retired person, one homemaker, one working person</2> <4>Household size: from 1 person to a large family</4> <6>Where they live: urban, rural and suburban, in the north, south, plains, mountains and on an island</6> <8>Where they live: from apartments to houses, from new to old buildings</8><9>Means of transport: from walking to driving, from ferries to planes</9> <11>Diet: at least one vegan, one vegetarian, one fish-eater and one red meat lover</11> <13>Their buying habits: from second-hand to brand-new, from the compulsive shopper to the person who buys next to nothing</13> <15>The way they go on vacation: transport, accommodation, you name it, we''ve got it</15> <17>Their hobbies: culture, sport, well-being..</17></5>' + publicodes.Personas.description.lock: 'Nous les avons définis pour qu’ils représentent la diversité des cas d’usage du simulateur. <2>Toute ressemblance avec une personne existant ou ayant existé serait purement fortuite !</2> En aucune mesure, on ne peut dire qu’ils sont représentatifs de la distribution de la population française : il ne s’agit pas de coller aux statistiques de la population, mais de retrouver parmi nos dix personas au moins un qui représente chaque usage majeur et différenciant pour le simulateur. Ainsi, nous avons fait varier pour chacun d’entre eux :<5><0>Leur genre : même s’il n’influe pas sur l’empreinte, il serait étonnant de n’avoir que des personas “femmes”</0> <2>Leur âge et situation personnelle / professionnelle : au moins un étudiant, un retraité, un adulte au foyer, un actif</2> <4>La taille de leur foyer : de 1 personne à famille nombreuse</4> <6>Leur lieu de vie : de l’urbain, du rural et du péri-urbain, dans le nord, dans le sud, les plaines, la montagne et sur une île</6> <8>Leur logement : de l’appartement à la maison, du neuf à l’ancien</8><9>Leurs modes de transport : de la marche à la voiture en passant par le ferry et l’avion</9> <11>Leur régime alimentaire : au moins un végétalien, un végétarien, une personne ne mangeant que du poisson, et un amateur de viande rouge</11> <13>Leur tendance à l’achat : du tout occasion au tout neuf, de l’acheteur compulsif à celui ou celle qui n’achète presque rien</13> <15>Leur façon de partir en vacances : mode de transport, hébergement, on trouve de tout</15> <17>Leurs loisirs : de la culture, du sport, du bien-être…</17></5>' publicodes.Personas.lienGenerateur: For the first names, you can use <2>this generator</2> publicodes.Personas.lienGenerateur.lock: Pour les prénoms, on peut utiliser <2>ce générateur</2> publicodes.Personas.tuto: that it happens. You can either copy and paste data from another persona and modify it, or create one from scratch from the simulation. Once the simulation is satisfactory, click on "Modify my answers" then type Ctrl-C, open the browser console (F12), make sure you are in the "Console" tab, go to the very bottom of the console (it is a bit busy...), then copy the JSON displayed, paste it into <2>this tool</2> to generate a YAML, then insert it into personas.yaml. @@ -893,3 +893,15 @@ entries: 'Les personas nous servent à tester le simulateur sous toutes ses coutures, et à vérifier qu’il s’adapte bien à toutes les situations de vie des citoyens métropolitains. De par leur présence, ils nous forcent à penser à tous les cas d’usage, pour nous projeter dans différentes réalités, et inclure ces réalités dans nos refontes du parcours de test et des actions proposées à la fin de ce dernier. ': 'The personas help us to test the simulator from every angle, and to check that it can be adapted to all the life situations of metropolitan citizens. By their very presence, they force us to think of all possible use cases, to project ourselves into different realities, and to include these realities in our redesigns of the test path and the actions proposed at the end of it. ' publicodes.Personas.maj: To ensure that they continue to represent the diversity of the carbon footprint simulator's use cases, we edit them each time the simulator is added or modified, in accordance with the following rules:<1><0>Each possible answer is assigned to at least one persona</0> <2>At least one persona gives no answer to the question (and is therefore assigned the default value given in the simulator).</2></1> publicodes.Personas.maj.lock: Pour qu’ils ou elles continuent de représenter la diversité des cas d’usage du simulateur d’empreinte carbone, nous les éditons à chaque ajout ou modification de ce dernier, en respectant les règles suivantes :<1><0>Chaque réponse possible est attribuée à au moins un persona</0> <2>Au moins un persona ne répond rien à la question (il lui est donc attribué la valeur par défaut donnée dans le simulateur).</2></1> + questions: questions + 'a répondu à ': 'responded to ' + règle nécessitant une réponse a été répondue par défaut.: rule requiring a response has been answered by default. + règles sont absentes du persona.: rules are absent from the persona. + C'est le persona par défaut. Toutes les règles ont été répondues par défaut: This is the default persona. All rules have been answered by default + C'est le persona par défaut. Toutes les règles ont été répondues par défaut.: This is the default persona. All rules have been answered by default. + règles nécessitant une réponse ont été répondues par défaut.: rules requiring a response were answered by default. + ✅ Aucune règle nécessitant un réponse n'a été répondue par défaut.: ✅ No rules requiring a response have been answered by default. + règle a été définie dans le persona mais est absente du modèle.: rule has been defined in the persona but is absent from the model. + règles ont été définies dans le persona mais sont absentes du modèle.: rules have been defined in the persona but are absent from the model. + règle est absente du persona.: rule is absent from the persona. + Cette page vous permet de naviguer dans les parcours Nos Gestes Climat comme si vous étiez l'un des profils types que nous avons listés.: This page lets you navigate through the Nos Gestes Climat paths as if you were one of the profiles we've listed. diff --git a/source/locales/ui/ui-fr.yaml b/source/locales/ui/ui-fr.yaml index a7939b874d..b8685b560c 100644 --- a/source/locales/ui/ui-fr.yaml +++ b/source/locales/ui/ui-fr.yaml @@ -378,7 +378,7 @@ entries: publicodes.Contribution.translationWikiInvite: 'Suivez notre guide complet pour contribuer directement à la traduction du site : <2>rendez-vous sur notre wiki</2>.' publicodes.Landing.question: Connaissez-vous votre empreinte sur le climat ? publicodes.LandingExplanations.question: Connaissez-vous votre empreinte sur le climat ? - publicodes.Personas.description: 'Nous les avons définis pour qu’ils représentent la diversité des cas d’usage du simulateur. <2>Toute ressemblance avec une personne existant ou ayant existé serait purement fortuite !</2> En aucune mesure, on ne peut dire qu’ils sont représentatifs de la distribution de la population française : il ne s’agit pas de coller aux statistiques de la population, mais de retrouver parmi nos dix personas au moins un qui représente chaque usage majeur et différenciant pour le simulateur. Ainsi, nous avons fait varier pour chacun d’entre eux :<5><0>Leur genre : même s’il n’influe pas sur l’empreinte, il serait étonnant de n’avoir que des personas “femmes”.</0> <2>Leur âge et situation personnelle / professionnelle : au moins un étudiant, un retraité, un adulte au foyer</2> <4>La taille de leur foyer : de 1 personne à famille nombreuse</4> <6>Leur lieu de vie : de l’urbain, du rural et du péri-urbain, dans le nord, dans le sud, les plaines, la montagne et sur une île</6> <8>Leur logement : de l’appartement à la maison, du neuf à l’ancien</8><9>Leurs modes de transport : de la marche à la voiture en passant par le ferry et l’avion</9> <11>Leur régime alimentaire : au moins un végétalien, un végétarien, une personne ne mangeant que du poisson, et un amateur de viande rouge</11> <13>Leur tendance à l’achat : du tout occasion au tout neuf, de l’acheteur compulsif à celui ou celle qui n’achète presque rien</13> <15>Leur façon de partir en vacances : mode de transport, hébergement, on trouve de tout</15> <17>Leurs loisirs : de la culture, du sport, du bien-être…</17></5>' + publicodes.Personas.description: 'Nous les avons définis pour qu’ils représentent la diversité des cas d’usage du simulateur. <2>Toute ressemblance avec une personne existant ou ayant existé serait purement fortuite !</2> En aucune mesure, on ne peut dire qu’ils sont représentatifs de la distribution de la population française : il ne s’agit pas de coller aux statistiques de la population, mais de retrouver parmi nos dix personas au moins un qui représente chaque usage majeur et différenciant pour le simulateur. Ainsi, nous avons fait varier pour chacun d’entre eux :<5><0>Leur genre : même s’il n’influe pas sur l’empreinte, il serait étonnant de n’avoir que des personas “femmes”</0> <2>Leur âge et situation personnelle / professionnelle : au moins un étudiant, un retraité, un adulte au foyer, un actif</2> <4>La taille de leur foyer : de 1 personne à famille nombreuse</4> <6>Leur lieu de vie : de l’urbain, du rural et du péri-urbain, dans le nord, dans le sud, les plaines, la montagne et sur une île</6> <8>Leur logement : de l’appartement à la maison, du neuf à l’ancien</8><9>Leurs modes de transport : de la marche à la voiture en passant par le ferry et l’avion</9> <11>Leur régime alimentaire : au moins un végétalien, un végétarien, une personne ne mangeant que du poisson, et un amateur de viande rouge</11> <13>Leur tendance à l’achat : du tout occasion au tout neuf, de l’acheteur compulsif à celui ou celle qui n’achète presque rien</13> <15>Leur façon de partir en vacances : mode de transport, hébergement, on trouve de tout</15> <17>Leurs loisirs : de la culture, du sport, du bien-être…</17></5>' publicodes.Personas.lienGenerateur: Pour les prénoms, on peut utiliser <2>ce générateur</2> publicodes.Personas.tuto: que ça se passe. On peut soit copier coller les données d'un autre persona et les modifier, soit en créer un de zéro depuis la simulation. Une fois la simulation satisfaisante, cliquer sur "Modifier mes réponses" puis taper Ctrl-C, ouvrir la console du navigateur (F12), vérifiez bien que vous êtes dans l'onglet "Console", allez tout en bas de la console (elle est un peu chargée...), puis copier le JSON affiché, le coller dans <2>cet outil</2> pour générer un YAML, puis l'insérer dans personas.yaml. publicodes.Personas.warningMsg: Sélectionner un persona releguera votre simulation en cours dans votre historique de simulations, accessible en bas de votre <2>page profil</2>. @@ -701,3 +701,5 @@ entries: règles sont absentes du persona.: règles sont absentes du persona. 'a répondu à ': 'a répondu à ' questions: questions + C'est le persona par défaut. Toutes les règles ont été répondues par défaut: C'est le persona par défaut. Toutes les règles ont été répondues par défaut + Cette page vous permet de naviguer dans les parcours Nos Gestes Climat comme si vous étiez l'un des profils types que nous avons listés.: Cette page vous permet de naviguer dans les parcours Nos Gestes Climat comme si vous étiez l'un des profils types que nous avons listés. diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index 913fcbf4f9..fc1c078cc9 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -115,8 +115,9 @@ export default () => { </p> <p> <Trans> - Cette page vous permet de naviguer les parcours Nos Gestes Climat - comme si vous étiez l'un des profils types que nous avons listés. + Cette page vous permet de naviguer dans les parcours Nos Gestes + Climat comme si vous étiez l'un des profils types que nous avons + listés. </Trans> </p> <p> @@ -323,11 +324,11 @@ export const PersonaExplanations = ({ personasQuestionList }) => { <ul> <li> Leur genre : même s’il n’influe pas sur l’empreinte, il serait - étonnant de n’avoir que des personas “femmes”. + étonnant de n’avoir que des personas “femmes” </li>{' '} <li> Leur âge et situation personnelle / professionnelle : au moins - un étudiant, un retraité, un adulte au foyer + un étudiant, un retraité, un adulte au foyer, un actif </li>{' '} <li> La taille de leur foyer : de 1 personne à famille nombreuse From 7a8f2248171ce15b0bbfe3fafe81a97b1aeb3c67 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Wed, 19 Jul 2023 09:13:28 +0200 Subject: [PATCH 35/54] =?UTF-8?q?feat:=20l'empreinte=20affich=C3=A9e=20est?= =?UTF-8?q?=20bien=20l'empreinte=20de=20r=C3=A9duction=20maximale?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/locales/ui/ui-en-us.yaml | 1 + source/locales/ui/ui-fr.yaml | 1 + source/sites/publicodes/ActionVignette.tsx | 6 +++++- .../sites/publicodes/personas/RawActionsList.tsx | 14 ++++++++------ 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/source/locales/ui/ui-en-us.yaml b/source/locales/ui/ui-en-us.yaml index a2795f5991..8fd6a212b2 100644 --- a/source/locales/ui/ui-en-us.yaml +++ b/source/locales/ui/ui-en-us.yaml @@ -905,3 +905,4 @@ entries: règles ont été définies dans le persona mais sont absentes du modèle.: rules have been defined in the persona but are absent from the model. règle est absente du persona.: rule is absent from the persona. Cette page vous permet de naviguer dans les parcours Nos Gestes Climat comme si vous étiez l'un des profils types que nous avons listés.: This page lets you navigate through the Nos Gestes Climat paths as if you were one of the profiles we've listed. + 'proposées au total pour un potentiel de réduction de ': 'proposed for a total reduction potential of ' diff --git a/source/locales/ui/ui-fr.yaml b/source/locales/ui/ui-fr.yaml index b8685b560c..3ba21e2435 100644 --- a/source/locales/ui/ui-fr.yaml +++ b/source/locales/ui/ui-fr.yaml @@ -703,3 +703,4 @@ entries: questions: questions C'est le persona par défaut. Toutes les règles ont été répondues par défaut: C'est le persona par défaut. Toutes les règles ont été répondues par défaut Cette page vous permet de naviguer dans les parcours Nos Gestes Climat comme si vous étiez l'un des profils types que nous avons listés.: Cette page vous permet de naviguer dans les parcours Nos Gestes Climat comme si vous étiez l'un des profils types que nous avons listés. + 'proposées au total pour un potentiel de réduction de ': 'proposées au total pour un potentiel de réduction de ' diff --git a/source/sites/publicodes/ActionVignette.tsx b/source/sites/publicodes/ActionVignette.tsx index 8386a74805..bdde0b900a 100644 --- a/source/sites/publicodes/ActionVignette.tsx +++ b/source/sites/publicodes/ActionVignette.tsx @@ -34,7 +34,11 @@ export const supersededAction = (dottedName, rules, actionChoices) => { return ( Object.entries(rules).find(([key, r]) => { const supersedes = r?.action?.dépasse - return supersedes && supersedes.includes(dottedName) && actionChoices[key] + return ( + supersedes && + supersedes.includes(dottedName) && + (actionChoices ? actionChoices[key] : true) + ) }) != null ) } diff --git a/source/sites/publicodes/personas/RawActionsList.tsx b/source/sites/publicodes/personas/RawActionsList.tsx index d3c6f2fe53..20e5947d55 100644 --- a/source/sites/publicodes/personas/RawActionsList.tsx +++ b/source/sites/publicodes/personas/RawActionsList.tsx @@ -7,7 +7,7 @@ import { } from '@/components/publicodesUtils' import { useEngine } from '@/components/utils/EngineContext' import { Trans, useTranslation } from 'react-i18next' -import { getFormattedActionValue } from '../ActionVignette' +import { getFormattedActionValue, supersededAction } from '../ActionVignette' import { humanWeight } from '../HumanWeight' import useActions from '../useActions' @@ -29,6 +29,7 @@ export default ({ rules }: { rules: NGCRules }) => { stringValue: string title: string unit: string + isSurpassed: boolean } type ActionsList = Array<CustomAction> @@ -47,6 +48,8 @@ export default ({ rules }: { rules: NGCRules }) => { dottedName, engine ) + const isSurpassed = supersededAction(dottedName, rules, null) + return { dottedName, title, @@ -54,6 +57,7 @@ export default ({ rules }: { rules: NGCRules }) => { stringValue, unit, sign, + isSurpassed, } }) @@ -95,8 +99,8 @@ export default ({ rules }: { rules: NGCRules }) => { ) const rawTotalReduction = actionsList.reduce( - (acc, { correctedValue, sign }) => { - if (correctedValue) { + (acc, { correctedValue, sign, isSurpassed }) => { + if (correctedValue && !isSurpassed) { return sign === '+' ? acc - correctedValue : acc + correctedValue } else return acc }, @@ -119,9 +123,7 @@ export default ({ rules }: { rules: NGCRules }) => { <strong> {numberOfActions} <Trans>actions</Trans> </strong>{' '} - <Trans> - proposées au total pour un empreinte de réduction cumulée de{' '} - </Trans> + <Trans>proposées au total pour un potentiel de réduction de </Trans> <strong> {totalReduction} {unit} </strong> From 7ea81f9550464d0e781f359f9d5b4cba6c2d7f69 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Wed, 19 Jul 2023 09:25:33 +0200 Subject: [PATCH 36/54] =?UTF-8?q?feat:=20la=20visualisation=20par=20d?= =?UTF-8?q?=C3=A9faut=20devient=20description?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/sites/publicodes/Personas.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index fc1c078cc9..72ecaa92df 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -33,10 +33,7 @@ export type Persona = { export type Personas = Array<Persona> -const Nothing = () => null - const visualisationChoices = { - aucun: { titre: 'Aucun', composant: Nothing }, summary: { titre: 'Description', composant: Summary }, actionList: { titre: 'Actions associées', composant: RawActionsList }, exhaustivite: { @@ -60,7 +57,7 @@ export default () => { ) const [searchParams, setSearchParams] = useSearchParams({ - visualisation: 'aucun', + visualisation: 'summary', }) const visualisationParam = searchParams.get('visualisation') From 778b6b260a6b8ffff5900bb4dfea1e7e2b130160 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Wed, 19 Jul 2023 09:45:25 +0200 Subject: [PATCH 37/54] fix: state simulation id --- source/reducers/rootReducer.ts | 2 +- source/sites/publicodes/SimulationList.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/reducers/rootReducer.ts b/source/reducers/rootReducer.ts index 11ffaa8679..858a2edb54 100644 --- a/source/reducers/rootReducer.ts +++ b/source/reducers/rootReducer.ts @@ -80,7 +80,7 @@ function simulation( foldedSteps: action.foldedSteps || state?.foldedSteps || [], unfoldedStep: null, persona: action.persona, - id: action.persona || state?.id || generateSimulationId(), // Unique identifier of the simulation, used for the 'currentSimulationId' pointer. + id: action.persona?.nom || state?.id || generateSimulationId(), // Unique identifier of the simulation, used for the 'currentSimulationId' pointer. date: !action.persona && state?.date ? state?.date : new Date(), eventsSent: state?.eventsSent || {}, } diff --git a/source/sites/publicodes/SimulationList.tsx b/source/sites/publicodes/SimulationList.tsx index fbad704024..7a2596b3c1 100644 --- a/source/sites/publicodes/SimulationList.tsx +++ b/source/sites/publicodes/SimulationList.tsx @@ -4,7 +4,7 @@ import { setAllStoredTrajets, setCurrentSimulation, } from '@/actions/actions' -import { Simulation } from '@/reducers/rootReducer' +import { Simulation } from '@/types/simulation' import { Trans } from 'react-i18next' export default ({ dispatch, list, currentSimulationId }) => { From 45bb5824b6abac931b3cc252a06efa10fd4095a9 Mon Sep 17 00:00:00 2001 From: Emile Rolley <emile.rolley@tuta.io> Date: Wed, 19 Jul 2023 12:35:37 +0200 Subject: [PATCH 38/54] refactor: use personasUtils for commons functions and types --- source/sites/publicodes/Personas.tsx | 68 +++++++++---------- .../publicodes/personas/personasUtils.ts | 28 ++++++++ 2 files changed, 60 insertions(+), 36 deletions(-) create mode 100644 source/sites/publicodes/personas/personasUtils.ts diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index 72ecaa92df..9741e48214 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -1,37 +1,31 @@ +import { setDifferentSituation } from '@/actions/actions' import AnswerList from '@/components/conversation/AnswerList' import Title from '@/components/groupe/Title' +import useBranchData from '@/components/useBranchData' +import { useEngine } from '@/components/utils/EngineContext' +import { ScrollToTop } from '@/components/utils/Scroll' import { AppState } from '@/reducers/rootReducer' -import { Simulation, Situation } from '@/types/simulation' +import GridChart from '@/sites/publicodes/chart/GridChart' +import RavijenChart from '@/sites/publicodes/chart/RavijenChart' +import ActionSlide from '@/sites/publicodes/fin/ActionSlide' +import Budget from '@/sites/publicodes/fin/Budget' +import FinShareButton from '@/sites/publicodes/fin/FinShareButton' +import { CardGrid } from '@/sites/publicodes/ListeActionPlus' +import { getQuestionsInRules } from '@/sites/publicodes/pages/QuestionList' +import { + parsePersonasFromJSON, + Persona, +} from '@/sites/publicodes/personas/personasUtils' +import RawActionsList from '@/sites/publicodes/personas/RawActionsList' +import RulesCompletion from '@/sites/publicodes/personas/RulesCompletion' +import Summary from '@/sites/publicodes/personas/Summary' +import { Simulation } from '@/types/simulation' import { useEffect, useState } from 'react' import emoji from 'react-easy-emoji' import { Trans, useTranslation } from 'react-i18next' import { useDispatch, useSelector } from 'react-redux' import { useNavigate, useSearchParams } from 'react-router-dom' import yaml from 'yaml' -import { setDifferentSituation } from '../../actions/actions' -import useBranchData from '../../components/useBranchData' -import { useEngine } from '../../components/utils/EngineContext' -import { ScrollToTop } from '../../components/utils/Scroll' -import GridChart from './chart/GridChart' -import RavijenChart from './chart/RavijenChart' -import ActionSlide from './fin/ActionSlide' -import Budget from './fin/Budget' -import FinShareButton from './fin/FinShareButton' -import { CardGrid } from './ListeActionPlus' -import { getQuestionList } from './pages/QuestionList' -import RawActionsList from './personas/RawActionsList' -import RulesCompletion from './personas/RulesCompletion' -import Summary from './personas/Summary' - -export type Persona = { - nom: string - icônes: string - situation: Situation - description: string - résumé: string -} - -export type Personas = Array<Persona> const visualisationChoices = { summary: { titre: 'Description', composant: Summary }, @@ -67,7 +61,7 @@ export default () => { const engine = useEngine() const rules = useSelector((state: AppState) => state.rules) - const rawQuestionList = getQuestionList(engine, rules) + const rawQuestionList = getQuestionsInRules(engine, rules) const personasQuestionList = rawQuestionList.reduce((obj, rule) => { if (!rule.type.includes('Mosaïque')) { obj[rule.dottedName] = '' @@ -179,7 +173,7 @@ export const PersonaGrid = ({ const dispatch = useDispatch(), objectif = 'bilan' - const [personasList, setPersonasList] = useState<Personas>() + const [availablePersonas, setAvailablePersonas] = useState<Persona[]>([]) const engine = useEngine() const branchData = useBranchData() @@ -194,17 +188,17 @@ export const PersonaGrid = ({ const fileName = `/personas-${lang}.json` if (process.env.NODE_ENV === 'development') { - const json = require('../../../nosgestesclimat/public' + fileName) - const jsonValues: Personas = Object.values(json) - setPersonasList(jsonValues) + const json: object = require('../../../nosgestesclimat/public' + fileName) + const personas: Persona[] = parsePersonasFromJSON(json) + setAvailablePersonas(personas) } else { fetch(branchData.deployURL + fileName, { mode: 'cors', }) .then((response) => response.json()) .then((json) => { - const jsonValues: Personas = Object.values(json) - setPersonasList(jsonValues) + const personas: Persona[] = parsePersonasFromJSON(json) + setAvailablePersonas(personas) }) .catch((err) => { console.log('url:', branchData.deployURL + `/personas-${lang}.json`) @@ -213,7 +207,9 @@ export const PersonaGrid = ({ } }, [branchData.deployURL, branchData.loaded, lang]) - if (!personasList) return null + if (availablePersonas.length === 0) { + return null + } const setPersona = (persona: Persona) => { engine.setSituation({}) // Engine should be updated on simulation reset but not working here, useEngine to be investigated @@ -246,7 +242,7 @@ export const PersonaGrid = ({ } `} > - {personasList.map((persona) => { + {availablePersonas.map((persona) => { const { nom, icônes, description, résumé } = persona return ( <li key={nom}> @@ -272,11 +268,11 @@ export const PersonaGrid = ({ font-size: 80%; `} > - <div>{emoji(icônes || '👥')}</div> + <div>{emoji(icônes ?? '👥')}</div> <div>{nom}</div> </div> <p> - <small>{résumé || description}</small> + <small>{résumé ?? description}</small> </p> </button> </li> diff --git a/source/sites/publicodes/personas/personasUtils.ts b/source/sites/publicodes/personas/personasUtils.ts new file mode 100644 index 0000000000..b3b9b01277 --- /dev/null +++ b/source/sites/publicodes/personas/personasUtils.ts @@ -0,0 +1,28 @@ +import { Situation } from '@/types/simulation' + +export type Persona = { + nom: string + icônes: string + situation: Situation + description?: string + résumé: string +} + +export function parsePersonasFromJSON(json: object): Persona[] { + const personas: Persona[] = [] + + Object.values(json).forEach((persona) => { + if ( + 'nom' in persona && + 'icônes' in persona && + 'data' in persona && + ('description' in persona || 'résumé' in persona) + ) { + personas.push({ ...persona, situation: persona.data }) + } else { + console.warn('Persona invalide :', persona) + } + }) + + return personas +} From b5b5af50d95ef85f83a9be0baed6e9d5bef2e6f0 Mon Sep 17 00:00:00 2001 From: Emile Rolley <emile.rolley@tuta.io> Date: Wed, 19 Jul 2023 12:35:53 +0200 Subject: [PATCH 39/54] refactor: improve Profile.tsx typing --- source/sites/publicodes/Profil.tsx | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/source/sites/publicodes/Profil.tsx b/source/sites/publicodes/Profil.tsx index 23ee710673..6acc9cc443 100644 --- a/source/sites/publicodes/Profil.tsx +++ b/source/sites/publicodes/Profil.tsx @@ -15,7 +15,7 @@ import { useEngine } from '@/components/utils/EngineContext' import Meta from '@/components/utils/Meta' import { ScrollToTop } from '@/components/utils/Scroll' import { getNextQuestions } from '@/hooks/useNextQuestion' -import { RootState } from '@/reducers/rootReducer' +import { AppState } from '@/reducers/rootReducer' import { answeredQuestionsSelector, situationSelector, @@ -29,7 +29,7 @@ export const useProfileData = () => { const answeredQuestions = useSelector(answeredQuestionsSelector) const answeredQuestionsLength = answeredQuestions.length - const tutorials = useSelector((state: RootState) => state.tutorials) + const tutorials = useSelector((state: AppState) => state.tutorials) const hasData = answeredQuestionsLength > 0 return { hasData, tutorials, answeredQuestionsLength, answeredQuestions } @@ -38,20 +38,22 @@ export const useProfileData = () => { export default () => { const { t } = useTranslation() const dispatch = useDispatch() - const persona = useSelector((state) => state.simulation?.persona) - const currentSimulationId = useSelector((state) => state.currentSimulationId) + const persona = useSelector((state: AppState) => state.simulation?.persona) + const currentSimulationId = useSelector( + (state: AppState) => state.currentSimulationId + ) - const simulationList = useSelector((state) => state.simulations) + const simulationList = useSelector((state: AppState) => state.simulations) const { hasData, answeredQuestionsLength, tutorials, answeredQuestions } = useProfileData() const navigate = useNavigate() const actionChoicesLength = Object.keys( - useSelector((state) => state.actionChoices) - ).length, - situation = useSelector(situationSelector) - const engine = useEngine(), - bilan = engine.evaluate('bilan') + useSelector((state: AppState) => state.actionChoices) + ).length + const situation = useSelector(situationSelector) + const engine = useEngine() + const bilan = engine.evaluate('bilan') const engineNextQuestions = getNextQuestions( [bilan.missingVariables], {}, @@ -73,6 +75,7 @@ export default () => { answeredQuestionsLength && answeredQuestionsLength > 0 && percentFinished < 100 + return ( <div> <Meta From 1b594e7251e2e915a0f58043c3a43ac1dfe6a5db Mon Sep 17 00:00:00 2001 From: Emile Rolley <emile.rolley@tuta.io> Date: Wed, 19 Jul 2023 12:58:55 +0200 Subject: [PATCH 40/54] refactor(types): add a type definition for BranchData --- source/components/useBranchData.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/source/components/useBranchData.ts b/source/components/useBranchData.ts index d804f674de..7462b21d40 100644 --- a/source/components/useBranchData.ts +++ b/source/components/useBranchData.ts @@ -1,13 +1,22 @@ +import { AppState } from '@/reducers/rootReducer' import { useEffect } from 'react' import { useDispatch, useSelector } from 'react-redux' +export type BranchData = { + deployURL: string + pullRequestNumber?: string + loaded: boolean +} + export default () => { const dispatch = useDispatch() const urlParams = new URLSearchParams(window.location.search) const searchPR = urlParams.get('PR') - const pullRequestNumber = useSelector((state) => state.pullRequestNumber) + const pullRequestNumber = useSelector( + (state: AppState) => state.pullRequestNumber + ) const setPullRequestNumber = (number) => dispatch({ type: 'SET_PULL_REQUEST_NUMBER', number }) From 2f42b44c6ccbb9d9b3b9e8bbceb4800599ad782b Mon Sep 17 00:00:00 2001 From: Emile Rolley <emile.rolley@tuta.io> Date: Wed, 19 Jul 2023 13:00:01 +0200 Subject: [PATCH 41/54] refactor: refactoring pass of Personas.tsx --- source/sites/publicodes/Personas.tsx | 46 ++++++------------- .../publicodes/personas/RulesCompletion.tsx | 4 +- .../publicodes/personas/personasUtils.ts | 27 +++++++++++ 3 files changed, 43 insertions(+), 34 deletions(-) diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index 9741e48214..6c54335483 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -1,7 +1,7 @@ import { setDifferentSituation } from '@/actions/actions' import AnswerList from '@/components/conversation/AnswerList' import Title from '@/components/groupe/Title' -import useBranchData from '@/components/useBranchData' +import useBranchData, { BranchData } from '@/components/useBranchData' import { useEngine } from '@/components/utils/EngineContext' import { ScrollToTop } from '@/components/utils/Scroll' import { AppState } from '@/reducers/rootReducer' @@ -13,7 +13,7 @@ import FinShareButton from '@/sites/publicodes/fin/FinShareButton' import { CardGrid } from '@/sites/publicodes/ListeActionPlus' import { getQuestionsInRules } from '@/sites/publicodes/pages/QuestionList' import { - parsePersonasFromJSON, + fetchAndSetAvailablePersonas, Persona, } from '@/sites/publicodes/personas/personasUtils' import RawActionsList from '@/sites/publicodes/personas/RawActionsList' @@ -61,13 +61,9 @@ export default () => { const engine = useEngine() const rules = useSelector((state: AppState) => state.rules) - const rawQuestionList = getQuestionsInRules(engine, rules) - const personasQuestionList = rawQuestionList.reduce((obj, rule) => { - if (!rule.type.includes('Mosaïque')) { - obj[rule.dottedName] = '' - } - return obj - }, {}) + const personasQuestions = getQuestionsInRules(engine, rules).filter( + ({ type }) => !type.includes('Mosaïque') + ) const visualisationComponentProps = { score: engine.evaluate('bilan').nodeValue, @@ -159,7 +155,7 @@ export default () => { </div> )} <PersonaGrid selectedPersona={selectedPersona} /> - <PersonaExplanations personasQuestionList={personasQuestionList} /> + <PersonaExplanations personasQuestionList={personasQuestions} /> </div> ) } @@ -176,7 +172,7 @@ export const PersonaGrid = ({ const [availablePersonas, setAvailablePersonas] = useState<Persona[]>([]) const engine = useEngine() - const branchData = useBranchData() + const branchData: BranchData = useBranchData() const lang = i18n.language === 'en' ? 'en-us' : i18n.language const navigate = useNavigate() @@ -184,28 +180,14 @@ export const PersonaGrid = ({ const redirect = params.get('redirect') useEffect(() => { - if (!branchData.loaded) return - const fileName = `/personas-${lang}.json` - - if (process.env.NODE_ENV === 'development') { - const json: object = require('../../../nosgestesclimat/public' + fileName) - const personas: Persona[] = parsePersonasFromJSON(json) - setAvailablePersonas(personas) - } else { - fetch(branchData.deployURL + fileName, { - mode: 'cors', - }) - .then((response) => response.json()) - .then((json) => { - const personas: Persona[] = parsePersonasFromJSON(json) - setAvailablePersonas(personas) - }) - .catch((err) => { - console.log('url:', branchData.deployURL + `/personas-${lang}.json`) - console.log('err:', err) - }) + if (branchData.loaded) { + fetchAndSetAvailablePersonas( + `/personas-${lang}.json`, + branchData, + setAvailablePersonas + ) } - }, [branchData.deployURL, branchData.loaded, lang]) + }, [branchData, lang]) if (availablePersonas.length === 0) { return null diff --git a/source/sites/publicodes/personas/RulesCompletion.tsx b/source/sites/publicodes/personas/RulesCompletion.tsx index e8b6a427f1..2fe8c48928 100644 --- a/source/sites/publicodes/personas/RulesCompletion.tsx +++ b/source/sites/publicodes/personas/RulesCompletion.tsx @@ -2,13 +2,13 @@ import { NGCRules } from '@/components/publicodesUtils' import { EngineContext } from '@/components/utils/EngineContext' import { useContext } from 'react' import { Trans } from 'react-i18next' -import { getQuestionList } from '../pages/QuestionList' +import { getQuestionsInRules } from '../pages/QuestionList' import { Persona } from '../Personas' export default ({ rules, persona }: { rules: NGCRules; persona: Persona }) => { const engine = useContext(EngineContext) - const rawQuestionList = getQuestionList(engine, rules) + const rawQuestionList = getQuestionsInRules(engine, rules) const completeQuestionList = rawQuestionList.reduce((arr, rule) => { if (!rule.type.includes('Mosaïque')) { arr.push(rule.dottedName) diff --git a/source/sites/publicodes/personas/personasUtils.ts b/source/sites/publicodes/personas/personasUtils.ts index b3b9b01277..917e98ba26 100644 --- a/source/sites/publicodes/personas/personasUtils.ts +++ b/source/sites/publicodes/personas/personasUtils.ts @@ -1,3 +1,4 @@ +import { BranchData } from '@/components/useBranchData' import { Situation } from '@/types/simulation' export type Persona = { @@ -26,3 +27,29 @@ export function parsePersonasFromJSON(json: object): Persona[] { return personas } + +export function fetchAndSetAvailablePersonas( + fileName: string, + branchData: BranchData, + setAvailablePersonas: (personas: Persona[]) => void +) { + if (process.env.NODE_ENV === 'development') { + const json: object = require('../../../../nosgestesclimat/public' + + fileName) + const personas: Persona[] = parsePersonasFromJSON(json) + setAvailablePersonas(personas) + } else { + fetch(branchData.deployURL + fileName, { + mode: 'cors', + }) + .then((response) => response.json()) + .then((json) => { + const personas: Persona[] = parsePersonasFromJSON(json) + setAvailablePersonas(personas) + }) + .catch((err) => { + console.log('url:', branchData.deployURL + fileName) + console.log('err:', err) + }) + } +} From fae6d93e78cac893bdafcb6539de33ddf7c06fe3 Mon Sep 17 00:00:00 2001 From: Emile Rolley <emile.rolley@tuta.io> Date: Wed, 19 Jul 2023 13:00:14 +0200 Subject: [PATCH 42/54] refactor: refactoring pass on QuestionList.tsx --- .../sites/publicodes/pages/QuestionList.tsx | 46 +++++++++++-------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/source/sites/publicodes/pages/QuestionList.tsx b/source/sites/publicodes/pages/QuestionList.tsx index b289fe55f7..b6101a73cf 100644 --- a/source/sites/publicodes/pages/QuestionList.tsx +++ b/source/sites/publicodes/pages/QuestionList.tsx @@ -2,7 +2,8 @@ import Title from '@/components/groupe/Title' import { DottedName, getRelatedMosaicInfosIfExists, - NGCRuleNode, + NGCRule, + NGCRules, NGCRulesNodes, parentName, questionCategoryName, @@ -10,19 +11,20 @@ import { import { useEngine } from '@/components/utils/EngineContext' import toCSV from '@/components/utils/toCSV' import { AppState } from '@/reducers/rootReducer' +import { assert } from '@/utils' import Engine from 'publicodes' import { Trans } from 'react-i18next' import { useSelector } from 'react-redux' import FriendlyObjectViewer from './FriendlyObjectViewer' export default () => { - const rules: NGCRulesNodes = useSelector((state: AppState) => state.rules) + const rules = useSelector((state: AppState) => state.rules) const engine = useEngine() const questionRules = Object.entries(rules) .map(([dottedName, v]) => ({ ...v, dottedName })) .filter((el) => el && el.question) - const jsonList = getQuestionList(engine, rules) + const jsonList = getQuestionsInRules(engine, rules) const header = [ 'dottedName', @@ -83,40 +85,46 @@ export default () => { ) } -type QuestionList = Array<{ +export type Question = { dottedName: DottedName question: string type: string catégorie: string 'dans mosaïque': boolean - dépendances: Array<any> -}> + dépendances: DottedName[] +} -export const getQuestionList = (engine, rules) => { +export function getQuestionsInRules( + engine: Engine, + rules: NGCRules +): Question[] { + const rulesNodes = engine.getParsedRules() as NGCRulesNodes const questionRules = Object.entries(rules) .map(([dottedName, v]) => ({ ...v, dottedName })) .filter((el) => el && el.question) - const jsonList: QuestionList = questionRules.map((rule) => { - const { type, mosaic } = getQuestionType(rules, rule) - const dependenciesData = computeDependencies(engine, rule) + const questions = questionRules.map((rule) => { + const { type, mosaic } = getQuestionType(rulesNodes, rule) + const dependenciesData = computeDependencies(engine, rule.dottedName) + + assert(rule.question !== undefined, 'question is defined') return { dottedName: rule.dottedName, question: rule.question, type, catégorie: questionCategoryName(rule.dottedName), - 'dans mosaïque': mosaic != null, - dépendances: dependenciesData.map(([k, v]) => k), + 'dans mosaïque': mosaic != undefined, + dépendances: dependenciesData.map(([k, _]) => k), } }) - return jsonList + return questions } -const getQuestionType = (rules: NGCRulesNodes, rule: NGCRuleNode) => { - const ruleMosaicInfos = getRelatedMosaicInfosIfExists(rules, rule.dottedName) - const mosaicType = ruleMosaicInfos && ruleMosaicInfos[1].type +const getQuestionType = (rules: NGCRulesNodes, rule: NGCRule) => { + const ruleMosaicInfos = getRelatedMosaicInfosIfExists(rules, rule.nom) + const mosaicType = ruleMosaicInfos && ruleMosaicInfos[1]?.type const type = rule.mosaique ? `🪟 Mosaïque de type ${rule.mosaique.type}` @@ -130,10 +138,10 @@ const getQuestionType = (rules: NGCRulesNodes, rule: NGCRuleNode) => { return { type, mosaic: ruleMosaicInfos } } -const computeDependencies = (engine: Engine, rule: NGCRuleNode) => { - const { missingVariables } = engine.evaluate(rule.dottedName) +const computeDependencies = (engine: Engine, ruleName: DottedName) => { + const { missingVariables } = engine.evaluate(ruleName) const entries = Object.entries(missingVariables).filter( - ([k]) => k !== rule.dottedName + ([k]) => k !== ruleName ) return entries } From 67f5a2dfe90aeda59b21ccbdacca1c906de0f512 Mon Sep 17 00:00:00 2001 From: Emile Rolley <emile.rolley@tuta.io> Date: Wed, 19 Jul 2023 13:06:11 +0200 Subject: [PATCH 43/54] refactor: nitpicks in RawActionsList.tsx --- .../publicodes/personas/RawActionsList.tsx | 36 +++++++++---------- source/sites/publicodes/useActions.tsx | 20 +++++------ 2 files changed, 25 insertions(+), 31 deletions(-) diff --git a/source/sites/publicodes/personas/RawActionsList.tsx b/source/sites/publicodes/personas/RawActionsList.tsx index 20e5947d55..1be0ca8e9e 100644 --- a/source/sites/publicodes/personas/RawActionsList.tsx +++ b/source/sites/publicodes/personas/RawActionsList.tsx @@ -11,6 +11,22 @@ import { getFormattedActionValue, supersededAction } from '../ActionVignette' import { humanWeight } from '../HumanWeight' import useActions from '../useActions' +type CustomAction = { + correctedValue: number + dottedName: DottedName + sign: string + stringValue: string + title: string + unit: string + isSurpassed: boolean +} + +type ActionsListByCategory = Array< + Category & { + actions?: CustomAction[] + } +> + export default ({ rules }: { rules: NGCRules }) => { const { t, i18n } = useTranslation() const engine = useEngine() @@ -22,25 +38,7 @@ export default ({ rules }: { rules: NGCRules }) => { metric: null, }) - type CustomAction = { - correctedValue: number - dottedName: DottedName - sign: string - stringValue: string - title: string - unit: string - isSurpassed: boolean - } - - type ActionsList = Array<CustomAction> - - type ActionsListByCategory = Array< - Category & { - actions?: ActionsList - } - > - - const actionsList: ActionsList = actionResultsRaw.map((actionRule) => { + const actionsList: CustomAction[] = actionResultsRaw.map((actionRule) => { const { dottedName, title }: { dottedName: DottedName; title: string } = actionRule const { correctedValue, stringValue, unit, sign } = getFormattedActionValue( diff --git a/source/sites/publicodes/useActions.tsx b/source/sites/publicodes/useActions.tsx index 56d4312baa..13438ffa12 100644 --- a/source/sites/publicodes/useActions.tsx +++ b/source/sites/publicodes/useActions.tsx @@ -11,17 +11,13 @@ export default ({ focusedAction, rules, radical, engine, metric }) => { const targets = objectifs.map((o) => engine.evaluate(o)) const actions = targets.filter((t) => t.dottedName !== 'bilan') const sortedActionsByImpact = sortBy( - (a) => (radical ? 1 : -1) * correctValue(a) - )(actions), - interestingActions = sortedActionsByImpact.filter((action) => { - const flatRule = rules[action.dottedName] - const superseded = supersededAction( - action.dottedName, - rules, - actionChoices - ) - const disabled = disabledAction(flatRule, action.nodeValue) - return !superseded && (action.dottedName === focusedAction || !disabled) - }) + (a) => (radical ? 1 : -1) * correctValue(a) + )(actions) + const interestingActions = sortedActionsByImpact.filter((action) => { + const flatRule = rules[action.dottedName] + const superseded = supersededAction(action.dottedName, rules, actionChoices) + const disabled = disabledAction(flatRule, action.nodeValue) + return !superseded && (action.dottedName === focusedAction || !disabled) + }) return { interestingActions, targets, rawActionsList: actions } } From 659e70f84d20d17f9a1c29d4bc31a10b8fc81913 Mon Sep 17 00:00:00 2001 From: Emile Rolley <emile.rolley@tuta.io> Date: Wed, 19 Jul 2023 13:10:44 +0200 Subject: [PATCH 44/54] fix: types errors in RulesCompletion.tsx --- .../publicodes/personas/RulesCompletion.tsx | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/source/sites/publicodes/personas/RulesCompletion.tsx b/source/sites/publicodes/personas/RulesCompletion.tsx index 2fe8c48928..fd20fadd0f 100644 --- a/source/sites/publicodes/personas/RulesCompletion.tsx +++ b/source/sites/publicodes/personas/RulesCompletion.tsx @@ -1,32 +1,29 @@ -import { NGCRules } from '@/components/publicodesUtils' +import { MODEL_ROOT_RULE_NAME, NGCRules } from '@/components/publicodesUtils' import { EngineContext } from '@/components/utils/EngineContext' +import { getQuestionsInRules } from '@/sites/publicodes/pages/QuestionList' +import { Persona } from '@/sites/publicodes/personas/personasUtils' import { useContext } from 'react' import { Trans } from 'react-i18next' -import { getQuestionsInRules } from '../pages/QuestionList' -import { Persona } from '../Personas' export default ({ rules, persona }: { rules: NGCRules; persona: Persona }) => { const engine = useContext(EngineContext) - const rawQuestionList = getQuestionsInRules(engine, rules) - const completeQuestionList = rawQuestionList.reduce((arr, rule) => { - if (!rule.type.includes('Mosaïque')) { - arr.push(rule.dottedName) - } - return arr - }, []) + const completeQuestionList = getQuestionsInRules(engine, rules).filter( + ({ type }) => !type.includes('Mosaïque') + ) const intersectListToInclude = completeQuestionList.filter( - (dottedName) => !Object.keys(persona?.situation).includes(dottedName) + ({ dottedName }) => !Object.keys(persona?.situation).includes(dottedName) ) const intersectListToExclude = Object.keys(persona?.situation).filter( - (dottedName) => !completeQuestionList.includes(dottedName) + (dottedName) => + !completeQuestionList.find(({ dottedName: d }) => d === dottedName) ) - const { missingVariables } = engine.evaluate('bilan') + const { missingVariables } = engine.evaluate(MODEL_ROOT_RULE_NAME) const missingRules = Object.keys(missingVariables).filter((dottedName) => - completeQuestionList.includes(dottedName) + completeQuestionList.find(({ dottedName: d }) => d === dottedName) ) return ( @@ -91,7 +88,7 @@ export default ({ rules, persona }: { rules: NGCRules; persona: Persona }) => { )} </summary> <ul> - {intersectListToInclude.map((dottedName) => ( + {intersectListToInclude.map(({ dottedName }) => ( <li key={dottedName}>{dottedName}</li> ))} </ul> From 6713b8d7f875060240569dafce14dd5805d489f8 Mon Sep 17 00:00:00 2001 From: Emile Rolley <emile.rolley@tuta.io> Date: Wed, 19 Jul 2023 13:13:22 +0200 Subject: [PATCH 45/54] fix: check for undefined in Summary.tsx --- source/sites/publicodes/personas/Summary.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/source/sites/publicodes/personas/Summary.tsx b/source/sites/publicodes/personas/Summary.tsx index 40fd0726b6..fdeb7851dd 100644 --- a/source/sites/publicodes/personas/Summary.tsx +++ b/source/sites/publicodes/personas/Summary.tsx @@ -1,14 +1,15 @@ import { Markdown } from '@/components/utils/markdown' +import { Persona } from '@/sites/publicodes/personas/personasUtils' import { Trans } from 'react-i18next' -import { Persona } from '../Personas' export default ({ persona }: { persona: Persona }) => { - return ( + return persona.description !== undefined ? ( <div> <h2> - <Trans>Description:</Trans> + <Trans>Description</Trans> + {':'} </h2> - <Markdown children={persona?.description} /> + <Markdown>{persona.description}</Markdown> </div> - ) + ) : null } From c96541aee324a6eb8bfb3ee999dd3de6ed1174e1 Mon Sep 17 00:00:00 2001 From: Emile Rolley <emile.rolley@tuta.io> Date: Wed, 19 Jul 2023 13:16:27 +0200 Subject: [PATCH 46/54] fix: update imports --- source/selectors/storageSelectors.ts | 14 ++++++-------- source/types/simulation.ts | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/source/selectors/storageSelectors.ts b/source/selectors/storageSelectors.ts index 6816670a4d..60088d0008 100644 --- a/source/selectors/storageSelectors.ts +++ b/source/selectors/storageSelectors.ts @@ -1,20 +1,18 @@ import { DottedName } from '@/components/publicodesUtils' import { Lang } from '@/locales/translation' -import { AppState, Simulation, SimulationConfig } from '@/reducers/rootReducer' -import { Persona } from '@/sites/publicodes/Personas' - -export type Rating = 0 | 1 | 2 | 3 | 'no_display' | 'display' | 'refuse' +import { AppState } from '@/reducers/rootReducer' +import { Persona } from '@/sites/publicodes/personas/personasUtils' +import { Group } from '@/types/groups' +import { Rating } from '@/types/rating' +import { SimulationConfig, Situation } from '@/types/simulation' export type Enquête = { userID: string date: string } -import { Group } from '@/types/groups' -import { Rating } from '@/types/rating' - export type SavedSimulation = { - situation: Simulation['situation'] + situation: Situation foldedSteps?: Array<DottedName> actionChoices: Object persona?: Persona diff --git a/source/types/simulation.ts b/source/types/simulation.ts index 0dfb6737ac..4a5abe8e84 100644 --- a/source/types/simulation.ts +++ b/source/types/simulation.ts @@ -1,5 +1,5 @@ import { DottedName } from '@/components/publicodesUtils' -import { Persona } from '@/sites/publicodes/Personas' +import { Persona } from '@/sites/publicodes/personas/personasUtils' export type Situation = Record<DottedName, any> From 24bf5c7ae455078e9a320e2845dcff0b7fddfb0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment?= <55186402+Clemog@users.noreply.github.com> Date: Wed, 19 Jul 2023 15:17:17 +0200 Subject: [PATCH 47/54] fix: add type getFormattedActionValue Co-authored-by: Emile Rolley <44124798+EmileRolley@users.noreply.github.com> --- source/sites/publicodes/ActionVignette.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/sites/publicodes/ActionVignette.tsx b/source/sites/publicodes/ActionVignette.tsx index bdde0b900a..13fb04159e 100644 --- a/source/sites/publicodes/ActionVignette.tsx +++ b/source/sites/publicodes/ActionVignette.tsx @@ -318,7 +318,7 @@ export const ActionGameCard = ({ evaluation, total, rule }) => { ) } -export const getFormattedActionValue = ({ t, i18n }, dottedName, engine) => { +export const getFormattedActionValue = ({ t, i18n }, ruleName: DottedName, engine: Engine) => { const correctedValue = correctValue(engine.evaluate(dottedName)) if (correctedValue == undefined) { From 1e51bae926dfc45b97c330b4ff0e6a10c846f887 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Wed, 19 Jul 2023 15:48:44 +0200 Subject: [PATCH 48/54] fix: types --- nosgestesclimat | 2 +- source/components/publicodesUtils.tsx | 1 + source/sites/publicodes/ActionVignette.tsx | 22 ++++++++++++++++--- .../sites/publicodes/pages/QuestionList.tsx | 16 ++++++++++---- 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/nosgestesclimat b/nosgestesclimat index 4d7dcf5877..1c45cc6b26 160000 --- a/nosgestesclimat +++ b/nosgestesclimat @@ -1 +1 @@ -Subproject commit 4d7dcf587722d17c151486a5cb24cc646775e384 +Subproject commit 1c45cc6b265d9bef0ad769d86c8e48ce259b6ac5 diff --git a/source/components/publicodesUtils.tsx b/source/components/publicodesUtils.tsx index 4c53ddb0c6..10e62876c2 100644 --- a/source/components/publicodesUtils.tsx +++ b/source/components/publicodesUtils.tsx @@ -65,6 +65,7 @@ export type NGCRule = Rule & { mosaique?: MosaiqueNode type?: 'notification' sévérité?: 'avertissement' | 'information' | 'invalide' + action?: { dépasse: DottedName[] } // NOTE(@EmileRolley): used in Action.tsx but I don't if it is really needed.. plus?: boolean } diff --git a/source/sites/publicodes/ActionVignette.tsx b/source/sites/publicodes/ActionVignette.tsx index 13fb04159e..f7e84339cf 100644 --- a/source/sites/publicodes/ActionVignette.tsx +++ b/source/sites/publicodes/ActionVignette.tsx @@ -6,7 +6,9 @@ import { import NotificationBubble from '@/components/NotificationBubble' import { correctValue, + DottedName, extractCategoriesNamespaces, + NGCRules, splitName, } from '@/components/publicodesUtils' import { useEngine } from '@/components/utils/EngineContext' @@ -17,7 +19,7 @@ import { answeredQuestionsSelector, situationSelector, } from '@/selectors/simulationSelectors' -import { utils } from 'publicodes' +import Engine, { utils } from 'publicodes' import emoji from 'react-easy-emoji' import { Trans, useTranslation } from 'react-i18next' import { useDispatch, useSelector } from 'react-redux' @@ -30,7 +32,11 @@ export const disabledAction = (flatRule, nodeValue) => ? false : nodeValue === 0 || nodeValue === false || nodeValue === null -export const supersededAction = (dottedName, rules, actionChoices) => { +export const supersededAction = ( + dottedName: DottedName, + rules: NGCRules, + actionChoices: DottedName[] | null +) => { return ( Object.entries(rules).find(([key, r]) => { const supersedes = r?.action?.dépasse @@ -318,7 +324,11 @@ export const ActionGameCard = ({ evaluation, total, rule }) => { ) } -export const getFormattedActionValue = ({ t, i18n }, ruleName: DottedName, engine: Engine) => { +export const getFormattedActionValue = ( + { t, i18n }, + dottedName: DottedName, + engine: Engine +) => { const correctedValue = correctValue(engine.evaluate(dottedName)) if (correctedValue == undefined) { @@ -343,6 +353,12 @@ export const ActionValue = ({ noFormula, dottedName, engine, +}: { + total: number + disabled: boolean + noFormula: string | null + dottedName: DottedName + engine: Engine }) => { const { t, i18n } = useTranslation() diff --git a/source/sites/publicodes/pages/QuestionList.tsx b/source/sites/publicodes/pages/QuestionList.tsx index b6101a73cf..4c48867751 100644 --- a/source/sites/publicodes/pages/QuestionList.tsx +++ b/source/sites/publicodes/pages/QuestionList.tsx @@ -146,12 +146,20 @@ const computeDependencies = (engine: Engine, ruleName: DottedName) => { return entries } -const QuestionDescription = ({ engine, rule, rules }) => { +const QuestionDescription = ({ + engine, + rule, + rules, +}: { + engine: Engine + rule: NGCRule + rules: NGCRulesNodes +}) => { const { type, mosaic } = getQuestionType(rules, rule) - const category = rules[parentName(rule.dottedName, undefined, 0, -1)], - categoryLetter = category.titre[0] + const category = rules[parentName(rule.dottedName, undefined, 0, -1)] + const categoryLetter = category.titre[0] - const dependenciesData = computeDependencies(engine, rule) + const dependenciesData = computeDependencies(engine, rule.dottedName) return ( <li css={` From ef541571bd79efee2c04b367e95656be61ea45de Mon Sep 17 00:00:00 2001 From: Emile Rolley <emile.rolley@tuta.io> Date: Wed, 19 Jul 2023 16:12:04 +0200 Subject: [PATCH 49/54] fix: add dependencies in useState of Persona avoiding infinite call --- source/sites/publicodes/Personas.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/sites/publicodes/Personas.tsx b/source/sites/publicodes/Personas.tsx index 6c54335483..5a0de9c10e 100644 --- a/source/sites/publicodes/Personas.tsx +++ b/source/sites/publicodes/Personas.tsx @@ -187,7 +187,7 @@ export const PersonaGrid = ({ setAvailablePersonas ) } - }, [branchData, lang]) + }, [branchData.loaded, branchData.deployURL, lang]) if (availablePersonas.length === 0) { return null From 464bd0558557db645dfec3c0a4328e230c75f294 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Wed, 19 Jul 2023 16:14:54 +0200 Subject: [PATCH 50/54] fix: persona contains only `situation` --- source/sites/publicodes/personas/personasUtils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/sites/publicodes/personas/personasUtils.ts b/source/sites/publicodes/personas/personasUtils.ts index 917e98ba26..e2273858bd 100644 --- a/source/sites/publicodes/personas/personasUtils.ts +++ b/source/sites/publicodes/personas/personasUtils.ts @@ -16,10 +16,10 @@ export function parsePersonasFromJSON(json: object): Persona[] { if ( 'nom' in persona && 'icônes' in persona && - 'data' in persona && + 'situation' in persona && ('description' in persona || 'résumé' in persona) ) { - personas.push({ ...persona, situation: persona.data }) + personas.push({ ...persona }) } else { console.warn('Persona invalide :', persona) } From 08e78d37c6a504714caaea0970c675294559a008 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Wed, 19 Jul 2023 16:14:54 +0200 Subject: [PATCH 51/54] fix: persona contains only `situation` --- nosgestesclimat | 2 +- source/sites/publicodes/personas/personasUtils.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/nosgestesclimat b/nosgestesclimat index 1c45cc6b26..ccc8c63d26 160000 --- a/nosgestesclimat +++ b/nosgestesclimat @@ -1 +1 @@ -Subproject commit 1c45cc6b265d9bef0ad769d86c8e48ce259b6ac5 +Subproject commit ccc8c63d26578713750417c82e9cc7a0976684c5 diff --git a/source/sites/publicodes/personas/personasUtils.ts b/source/sites/publicodes/personas/personasUtils.ts index 917e98ba26..d17b4f0792 100644 --- a/source/sites/publicodes/personas/personasUtils.ts +++ b/source/sites/publicodes/personas/personasUtils.ts @@ -16,10 +16,10 @@ export function parsePersonasFromJSON(json: object): Persona[] { if ( 'nom' in persona && 'icônes' in persona && - 'data' in persona && - ('description' in persona || 'résumé' in persona) + ('description' in persona || 'résumé' in persona) && + 'situation' in persona ) { - personas.push({ ...persona, situation: persona.data }) + personas.push(persona) } else { console.warn('Persona invalide :', persona) } From a1d679909e67774a44352ace1c31c23be34cec14 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Wed, 19 Jul 2023 16:32:03 +0200 Subject: [PATCH 52/54] =?UTF-8?q?fix:=20plus=20de=20redirection=20vers=20l?= =?UTF-8?q?'=C3=A9cran=20"Agir"=20depuis=20la=20page=20personas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/sites/publicodes/SimulationMissing.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/sites/publicodes/SimulationMissing.tsx b/source/sites/publicodes/SimulationMissing.tsx index 27d98f385e..3072f1429e 100644 --- a/source/sites/publicodes/SimulationMissing.tsx +++ b/source/sites/publicodes/SimulationMissing.tsx @@ -1,7 +1,7 @@ import { Trans } from 'react-i18next' import { Link } from 'react-router-dom' -export default ({}) => { +export default () => { return ( <div className="ui__ card light colored content" @@ -30,7 +30,7 @@ export default ({}) => { <small> <Trans i18nKey={'publicodes.SimulationMissing.personnas'}> Vous pouvez aussi continuer avec un{' '} - <Link to={'/personas?redirect=/actions'}>profil type</Link>. + <Link to={'/personas'}>profil type</Link>. </Trans> </small> </p> From 2977bc53b923603c16d67389159d22c9aa86b928 Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Wed, 19 Jul 2023 16:42:07 +0200 Subject: [PATCH 53/54] =?UTF-8?q?fix:=20les=20r=C3=A8gles=20inactifs=20ne?= =?UTF-8?q?=20sont=20plus=20prises=20en=20compte?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/components/publicodesUtils.tsx | 1 + source/sites/publicodes/pages/QuestionList.tsx | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/source/components/publicodesUtils.tsx b/source/components/publicodesUtils.tsx index 10e62876c2..1427d1d7bf 100644 --- a/source/components/publicodesUtils.tsx +++ b/source/components/publicodesUtils.tsx @@ -66,6 +66,7 @@ export type NGCRule = Rule & { type?: 'notification' sévérité?: 'avertissement' | 'information' | 'invalide' action?: { dépasse: DottedName[] } + inactif?: 'oui' // NOTE(@EmileRolley): used in Action.tsx but I don't if it is really needed.. plus?: boolean } diff --git a/source/sites/publicodes/pages/QuestionList.tsx b/source/sites/publicodes/pages/QuestionList.tsx index 4c48867751..e9ad5479a7 100644 --- a/source/sites/publicodes/pages/QuestionList.tsx +++ b/source/sites/publicodes/pages/QuestionList.tsx @@ -22,7 +22,7 @@ export default () => { const engine = useEngine() const questionRules = Object.entries(rules) .map(([dottedName, v]) => ({ ...v, dottedName })) - .filter((el) => el && el.question) + .filter((el) => el && el.question && !el.inactif) const jsonList = getQuestionsInRules(engine, rules) @@ -101,7 +101,7 @@ export function getQuestionsInRules( const rulesNodes = engine.getParsedRules() as NGCRulesNodes const questionRules = Object.entries(rules) .map(([dottedName, v]) => ({ ...v, dottedName })) - .filter((el) => el && el.question) + .filter((el) => el && el.question && !el.inactif) const questions = questionRules.map((rule) => { const { type, mosaic } = getQuestionType(rulesNodes, rule) From 780a59aaeab2b21902046bff5eaec07a869264da Mon Sep 17 00:00:00 2001 From: Clement AUGER <clem.auger@hotmail.fr> Date: Wed, 19 Jul 2023 16:48:12 +0200 Subject: [PATCH 54/54] =?UTF-8?q?Revert=20"fix:=20les=20r=C3=A8gles=20inac?= =?UTF-8?q?tifs=20ne=20sont=20plus=20prises=20en=20compte"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 2977bc53b923603c16d67389159d22c9aa86b928. --- source/components/publicodesUtils.tsx | 1 - source/sites/publicodes/pages/QuestionList.tsx | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/source/components/publicodesUtils.tsx b/source/components/publicodesUtils.tsx index 1427d1d7bf..10e62876c2 100644 --- a/source/components/publicodesUtils.tsx +++ b/source/components/publicodesUtils.tsx @@ -66,7 +66,6 @@ export type NGCRule = Rule & { type?: 'notification' sévérité?: 'avertissement' | 'information' | 'invalide' action?: { dépasse: DottedName[] } - inactif?: 'oui' // NOTE(@EmileRolley): used in Action.tsx but I don't if it is really needed.. plus?: boolean } diff --git a/source/sites/publicodes/pages/QuestionList.tsx b/source/sites/publicodes/pages/QuestionList.tsx index e9ad5479a7..4c48867751 100644 --- a/source/sites/publicodes/pages/QuestionList.tsx +++ b/source/sites/publicodes/pages/QuestionList.tsx @@ -22,7 +22,7 @@ export default () => { const engine = useEngine() const questionRules = Object.entries(rules) .map(([dottedName, v]) => ({ ...v, dottedName })) - .filter((el) => el && el.question && !el.inactif) + .filter((el) => el && el.question) const jsonList = getQuestionsInRules(engine, rules) @@ -101,7 +101,7 @@ export function getQuestionsInRules( const rulesNodes = engine.getParsedRules() as NGCRulesNodes const questionRules = Object.entries(rules) .map(([dottedName, v]) => ({ ...v, dottedName })) - .filter((el) => el && el.question && !el.inactif) + .filter((el) => el && el.question) const questions = questionRules.map((rule) => { const { type, mosaic } = getQuestionType(rulesNodes, rule)