From adcbd330bd6f1f061c94a03db85c79345ea4054e Mon Sep 17 00:00:00 2001 From: Johan Girod Date: Wed, 16 Dec 2020 18:45:45 +0100 Subject: [PATCH] :fire: Remplace UNSAFE_evaluateNode par de meilleurs abstractions --- .../source/components/Notifications.tsx | 17 ++-- .../source/components/TargetSelection.tsx | 98 +++++++++---------- .../AideDéclarationIndépendant/index.tsx | 35 ++++--- .../site/pages/Simulateurs/ChômagePartiel.tsx | 6 +- .../test/regressions/simulations.jest.js | 12 +-- publicodes/core/esm/index.js | 2 +- 6 files changed, 80 insertions(+), 90 deletions(-) diff --git a/mon-entreprise/source/components/Notifications.tsx b/mon-entreprise/source/components/Notifications.tsx index c01e9c687..f0a623326 100644 --- a/mon-entreprise/source/components/Notifications.tsx +++ b/mon-entreprise/source/components/Notifications.tsx @@ -1,11 +1,7 @@ import { hideNotification } from 'Actions/actions' import animate from 'Components/ui/animate' -import { - useInversionFail, - EngineContext, - useEngine, -} from 'Components/utils/EngineContext' -import { useContext } from 'react' +import { useEngine, useInversionFail } from 'Components/utils/EngineContext' +import Engine, { EvaluatedRule } from 'publicodes' import emoji from 'react-easy-emoji' import { useTranslation } from 'react-i18next' import { useDispatch, useSelector } from 'react-redux' @@ -13,7 +9,6 @@ import { RootState } from 'Reducers/rootReducer' import './Notifications.css' import { Markdown } from './utils/markdown' import { ScrollToElement } from './utils/Scroll' -import Engine, { EvaluatedRule, ASTNode, UNSAFE_evaluateRule } from 'publicodes' // To add a new notification to a simulator, you should create a publicode rule // with the "type: notification" attribute. The display can be customized with @@ -27,11 +22,11 @@ type Notification = Pick & { export function getNotifications(engine: Engine) { return Object.values(engine.getRules()) .filter( - (rule: ASTNode & { nodeKind: 'rule' }) => - rule.rawNode['type'] === 'notification' + (rule) => + rule.rawNode['type'] === 'notification' && + !!engine.evaluate(rule.dottedName).nodeValue ) - .map((node) => UNSAFE_evaluateRule(engine, node.dottedName)) - .filter((node) => !!node.nodeValue) + .map((node) => node.dottedName) } export default function Notifications() { const { t } = useTranslation() diff --git a/mon-entreprise/source/components/TargetSelection.tsx b/mon-entreprise/source/components/TargetSelection.tsx index 845894566..f01e4abbe 100644 --- a/mon-entreprise/source/components/TargetSelection.tsx +++ b/mon-entreprise/source/components/TargetSelection.tsx @@ -1,5 +1,6 @@ import { setActiveTarget, updateSituation } from 'Actions/actions' import InputSuggestions from 'Components/conversation/InputSuggestions' +import Value, { Condition } from 'Components/EngineValue' import PeriodSwitch from 'Components/PeriodSwitch' import RuleLink from 'Components/RuleLink' import Animate from 'Components/ui/animate' @@ -11,14 +12,9 @@ import { useInversionFail, } from 'Components/utils/EngineContext' import { SitePathsContext } from 'Components/utils/SitePathsContext' -import { - ASTNode, - EvaluatedNode, - EvaluatedRule, - UNSAFE_evaluateRule, - formatValue, - reduceAST, -} from 'publicodes' +import { DottedName } from 'modele-social' +import { Names } from 'modele-social/dist/names' +import { ASTNode, EvaluatedRule, formatValue, reduceAST } from 'publicodes' import { isNil } from 'ramda' import { Fragment, useCallback, useContext } from 'react' import emoji from 'react-easy-emoji' @@ -26,11 +22,9 @@ import { Trans, useTranslation } from 'react-i18next' import { useDispatch, useSelector } from 'react-redux' import { useLocation } from 'react-router-dom' import { RootState } from 'Reducers/rootReducer' -import { DottedName } from 'modele-social' import { targetUnitSelector } from 'Selectors/simulationSelectors' import CurrencyInput from './CurrencyInput/CurrencyInput' import './TargetSelection.css' -import { Names } from 'modele-social/dist/names' export default function TargetSelection({ showPeriodSwitch = true }) { const objectifs = useSelector( @@ -89,10 +83,13 @@ type TargetProps = { const Target = ({ dottedName }: TargetProps) => { const activeInput = useSelector((state: RootState) => state.activeTargetInput) const engine = useEngine() - const target = UNSAFE_evaluateRule(engine, dottedName, { + const rule = engine.getRule(dottedName) + const evaluation = engine.evaluate({ + valeur: dottedName, unité: useSelector(targetUnitSelector), arrondi: 'oui', }) + const target = { ...evaluation, ...rule.rawNode, ...rule } const dispatch = useDispatch() const onSuggestionClick = useCallback( (value) => { @@ -269,30 +266,26 @@ function TargetInputOrValue({ } function TitreRestaurant() { const targetUnit = useSelector(targetUnitSelector) - const { language } = useTranslation().i18n - - const titresRestaurant = UNSAFE_evaluateRule( - useEngine(), - 'contrat salarié . frais professionnels . titres-restaurant . montant', - { - unité: targetUnit, - arrondi: 'oui', - } - ) - - if (!titresRestaurant?.nodeValue) return null + const dottedName = + 'contrat salarié . frais professionnels . titres-restaurant . montant' return ( - -
- - +{' '} - - {formatValue(titresRestaurant, { displayedUnit: '€', language })} - {' '} - en titres-restaurant {emoji(' 🍽')} - -
-
+ + +
+ + +{' '} + + + {' '} + en titres-restaurant {emoji(' 🍽')} + +
+
+
) } function AidesGlimpse() { @@ -300,14 +293,7 @@ function AidesGlimpse() { const { language } = useTranslation().i18n const dottedName = 'contrat salarié . aides employeur' as Names const engine = useEngine() - const evaluation = engine.evaluate({ - valeur: dottedName, - unité: targetUnit, - arrondi: 'oui', - }) const aides = engine.getRule(dottedName) - if (!evaluation?.nodeValue) return null - // Dans le cas où il n'y a qu'une seule aide à l'embauche qui s'applique, nous // faisons un lien direct vers cette aide, plutôt qu'un lien vers la liste qui // est une somme des aides qui sont toutes nulle sauf l'aide active. @@ -329,18 +315,22 @@ function AidesGlimpse() { aides ) return ( - -
- - en incluant{' '} - - - {formatValue(evaluation, { displayedUnit: '€', language })} - - {' '} - d'aides {emoji(aides.rawNode.icônes ?? '')} - -
-
+ + +
+ + en incluant{' '} + + + {' '} + d'aides {emoji(aides.rawNode.icônes ?? '')} + +
+
+
) } diff --git a/mon-entreprise/source/site/pages/Gérer/AideDéclarationIndépendant/index.tsx b/mon-entreprise/source/site/pages/Gérer/AideDéclarationIndépendant/index.tsx index ce24f8186..1317a4e35 100644 --- a/mon-entreprise/source/site/pages/Gérer/AideDéclarationIndépendant/index.tsx +++ b/mon-entreprise/source/site/pages/Gérer/AideDéclarationIndépendant/index.tsx @@ -2,7 +2,7 @@ import { setSimulationConfig, updateSituation } from 'Actions/actions' import Aide from 'Components/conversation/Aide' import { Explicable, ExplicableRule } from 'Components/conversation/Explicable' import RuleInput from 'Components/conversation/RuleInput' -import { Condition } from 'Components/EngineValue' +import Value, { Condition } from 'Components/EngineValue' import RuleLink from 'Components/RuleLink' import 'Components/TargetSelection.css' import Animate from 'Components/ui/animate' @@ -344,7 +344,8 @@ type SimpleFieldProps = { function SimpleField({ dottedName, question, summary }: SimpleFieldProps) { const dispatch = useDispatch() const engine = useContext(EngineContext) - const evaluatedRule = UNSAFE_evaluateRule(engine, dottedName) + const evaluation = engine.evaluate(dottedName) + const rule = engine.getRule(dottedName) const situation = useSelector(situationSelector) const dispatchValue = useCallback( @@ -361,8 +362,8 @@ function SimpleField({ dottedName, question, summary }: SimpleFieldProps) { if ( !(dottedName in situation) && - evaluatedRule.nodeValue === false && - !(dottedName in evaluatedRule.missingVariables) + evaluation.nodeValue === false && + !(dottedName in evaluation.missingVariables) ) { return null } @@ -381,10 +382,10 @@ function SimpleField({ dottedName, question, summary }: SimpleFieldProps) { `} >

- {question ?? evaluatedRule.question} + {question ?? rule.rawNode.question}

-

{summary ?? evaluatedRule.résumé}

+

{summary ?? rule.rawNode.résumé}

@@ -395,8 +396,8 @@ function SimpleField({ dottedName, question, summary }: SimpleFieldProps) { function Results() { const engine = useEngine() - const results = (simulationConfig.objectifs as DottedName[]).map((objectif) => - UNSAFE_evaluateRule(engine, objectif, { unité: '€/an' }) + const rules = (simulationConfig.objectifs as DottedName[]).map((objectif) => + engine.getRule(objectif) ) return (
<> - {results.map((r) => ( + {rules.map((r) => (

- {r.title} {r.résumé} + {r.title} {r.rawNode.résumé}

- {r.description &&

{r.description}

} + {r.rawNode.description && ( +

{r.rawNode.description}

+ )}

- {formatValue(r, { - displayedUnit: '€', - precision: 0, - })} +

diff --git a/mon-entreprise/source/site/pages/Simulateurs/ChômagePartiel.tsx b/mon-entreprise/source/site/pages/Simulateurs/ChômagePartiel.tsx index f13849117..e8a1c7626 100644 --- a/mon-entreprise/source/site/pages/Simulateurs/ChômagePartiel.tsx +++ b/mon-entreprise/source/site/pages/Simulateurs/ChômagePartiel.tsx @@ -3,11 +3,11 @@ import Simulation from 'Components/Simulation' import Animate from 'Components/ui/animate' import Warning from 'Components/ui/WarningBlock' import { IsEmbeddedContext } from 'Components/utils/embeddedContext' -import { EngineContext, useEngine } from 'Components/utils/EngineContext' -import { EvaluatedRule, UNSAFE_evaluateRule, formatValue } from 'publicodes' +import { useEngine } from 'Components/utils/EngineContext' +import { DottedName } from 'modele-social' +import { formatValue } from 'publicodes' import React, { useContext, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' -import { DottedName } from 'modele-social' import styled from 'styled-components' declare global { diff --git a/mon-entreprise/test/regressions/simulations.jest.js b/mon-entreprise/test/regressions/simulations.jest.js index 5d3db5bf1..25ced65ba 100644 --- a/mon-entreprise/test/regressions/simulations.jest.js +++ b/mon-entreprise/test/regressions/simulations.jest.js @@ -6,7 +6,6 @@ // renamed the test configuration may be adapted but the persisted snapshot will remain unchanged). /* eslint-disable no-undef */ -import Engine, { UNSAFE_evaluateRule } from 'publicodes' import rules from 'modele-social' import artisteAuteurConfig from '../../source/site/pages/Simulateurs/configs/artiste-auteur.yaml' import autoentrepreneurConfig from '../../source/site/pages/Simulateurs/configs/auto-entrepreneur.yaml' @@ -17,11 +16,10 @@ import professionLibéraleConfig from '../../source/site/pages/Simulateurs/confi import aideDéclarationConfig from '../../source/site/pages/Gérer/AideDéclarationIndépendant/config.yaml' import artisteAuteurSituations from './simulations-artiste-auteur.yaml' import autoEntrepreneurSituations from './simulations-auto-entrepreneur.yaml' -import professionsLibéralesSituations from './simulations-professions-libérales.yaml' import independentSituations from './simulations-indépendant.yaml' +import professionsLibéralesSituations from './simulations-professions-libérales.yaml' import remunerationDirigeantSituations from './simulations-rémunération-dirigeant.yaml' import employeeSituations from './simulations-salarié.yaml' -import aideDéclarationIndépendantsSituations from './aide-déclaration-indépendants.yaml' const roundResult = (arr) => arr.map((x) => Math.round(x)) const engine = new Engine(rules) @@ -40,9 +38,11 @@ const runSimulations = (situations, targets, baseSituation = {}) => const res = targets.map((target) => engine.evaluate(target).nodeValue) const evaluatedNotifications = Object.values(engine.getRules()) - .filter((rule) => rule.rawNode['type'] === 'notification') - .map((node) => UNSAFE_evaluateRule(engine, node.dottedName)) - .filter((node) => !!node.nodeValue) + .filter( + (rule) => + rule.rawNode['type'] === 'notification' && + !!engine.evaluate(rule.dottedName).nodeValue + ) .map((node) => node.dottedName) const snapshotedDisplayedNotifications = evaluatedNotifications.length diff --git a/publicodes/core/esm/index.js b/publicodes/core/esm/index.js index e92815f78..cf4cc7dba 100644 --- a/publicodes/core/esm/index.js +++ b/publicodes/core/esm/index.js @@ -9,4 +9,4 @@ export const transformAST = publicodes.transformAST export const formatValue = publicodes.formatValue export const utils = publicodes.utils export const translateRules = publicodes.translateRules -export const UNSAFE_evaluateRule = publicodes.UNSAFE_evaluateRule +export const UNSAFE_isNotApplicable = publicodes.UNSAFE_isNotApplicable