⚙️ Ajout des explications de tous les mécanismes; possibilité d'écrire du markdown

pull/6/head
Mael Thomas 2017-03-28 18:52:01 +02:00
parent c6d1608b77
commit 096f48d3b2
7 changed files with 123 additions and 54 deletions

View File

@ -166,13 +166,29 @@
align-items: center;
}
.dictionaryPanel {
width: 35%;
width: 33%;
border: 1px dashed #aaa;
margin: 1em;
padding: .6em 1em;
padding: 0em 1.5em;
min-height: 6em;
border-radius: .3em;
}
.dictionaryPanel h3 {
color: #333350
}
.dictionaryPanel blockquote {
font-style: italic;
border-left: 4px solid #eee;
padding-left: 1em;
margin-left: 0;
}
.dictionaryPanel blockquote p {
color: #666;
}
.dictionaryPanel code {
border: 1px solid #aaa;
padding: .05em .3em;
border-radius: .3em;
}
#rule-rules section {
@ -200,6 +216,12 @@
font-weight: 600;
border-radius: .4em;
}
[data-term-definition] {
cursor: pointer;
}
[data-term-definition]:hover {
opacity: .8
}
.ruleProp > .nodeHead .name {
background: #df5320
}
@ -275,6 +297,7 @@
font-weight: 600;
font-size: 90%;
border: 1px solid rgba(51, 51, 80, 0.25);
white-space: nowrap
}

View File

@ -13,6 +13,7 @@ import destinataires from '../../règles/destinataires/destinataires.yaml'
import references from '../../règles/références/références.yaml'
import {capitalise0} from '../utils'
import knownMecanisms from '../engine/known-mecanisms.yaml'
import marked from '../engine/marked'
// situationGate function useful for testing :
let testingSituationGate = v => // eslint-disable-line no-unused-vars
@ -128,24 +129,27 @@ export default class Rule extends Component {
let AttachDictionary = dictionary => Decorated =>
class extends React.Component {
state = {
term: null,
explanation: null
}
explain = explanation =>
this.setState({explanation})
componentDidMount() {
let decoratedNode = ReactDOM.findDOMNode(this.decorated)
decoratedNode.addEventListener('click', e => {
let term = e.target.dataset['termDefinition']
this.explain(R.path([term, 'description'], dictionary))
let term = e.target.dataset['termDefinition'],
explanation = R.path([term, 'description'], dictionary)
this.setState({explanation, term})
})
}
renderExplanationMarkdown(explanation, term) {
return marked(`### Mécanisme: ${term}\n\n${explanation}`)
}
render(){
let {explanation, term} = this.state
return (
<div className="dictionaryWrapper">
<Decorated ref={decorated => this.decorated = decorated} {...this.props} explain={this.explain}/>
{this.state.explanation &&
<div className="dictionaryPanel">
{this.state.explanation}
{explanation &&
<div className="dictionaryPanel" dangerouslySetInnerHTML={{__html: this.renderExplanationMarkdown(explanation, term)}}>
</div>
}
</div>

View File

@ -1,20 +1,30 @@
# Liste et description des différents mécanismes compris par le moteur.
# La description peut être rédigée en markdown :-)
l'une de ces conditions:
description: |
C'est un 'ou' logique.
C'est un `ou` logique.
Contient une liste de conditions.
Renvoie vrai si l'une des conditions sont vraies.
Renvoie vrai si l'une des conditions est vraie.
toutes ces conditions:
description: |
C'est un 'et' logique.
C'est un `et` logique.
Contient une liste de conditions.
Renvoie vrai si toutes les conditions vraies.
logique numérique:
description: |
Contient une liste de couples condition-conséquence.
Un par un, si la condition est vraie, alors on choisit la conséquence.
Cette conséquence peut elle-même être un mécanisme "logique numérique" ou plus simplement un taux.
Si aucune condition n'est vraie, alors ce mécanisme renvoie implilcitement 'non applicable' (ce qui peut se traduire par la valeur 0 si nous sommes dans un contexte numérique).
Couple par couple, si la condition est vraie, alors on choisit la conséquence.
Cette conséquence peut elle-même être un mécanisme `logique numérique` ou plus simplement un `taux`.
Si aucune condition n'est vraie, alors ce mécanisme renvoie implicitement `non applicable` (ce qui peut se traduire par la valeur `0` si nous sommes dans un contexte numérique).
taux:
description: |
@ -23,22 +33,51 @@ taux:
multiplication:
description: |
C'est une multiplication un peu améliorée, très utile pour exprimer les cotisations, souvent linéaires.
Sa propriété 'assiette' est multipliée par un pourcentage, 'taux', ou par un 'facteur' quand ce nom est plus approprié.
La multiplication peut être plafonnée : ce plafond sépare l'assiette en deux, et la partie au-dessus du plafond est tout simplement ignorée.
Dans ce cas, elle se comporte comme une barème en taux marginaux à deux tranches, la deuxième au taux nul et allant de 'plafond' à l'infini.
Sa propriété `assiette` est multipliée par un pourcentage, `taux`, ou par un `facteur` quand ce nom est plus approprié.
La multiplication peut être plafonnée : ce plafond sépare l'assiette en deux, et la partie au-dessus du plafond est tout simplement ignorée. Dans ce cas, elle se comporte comme une barème en taux marginaux à deux tranches, la deuxième au taux nul et allant de `plafond` à l'infini.
le maximum de:
description: |
Calcule le maximum de la liste de propositions fournie.
Renvoie l'élément de la liste de propositions fournie qui la la plus grande valeur.
Ces propositions doivent avoir un mécanisme de calcul ou être une valeur numérique.
Il est conseillé de renseigner une description de chaque propositions par exemple quand elles représentent des méthodes de calcul alternatives parmi lesquelles il faut en choisir une.
Il est conseillé de renseigner une description de chaque proposition par exemple quand elles représentent des méthodes de calcul alternatives parmi lesquelles il faut en choisir une.
somme:
description: |
C'est tout simplement la somme de chaque terme de la liste.
##########################################
# Ce qu'on appelle aujourd'hui des RuleProp
# Et qui deviendront des mécanismes classiques normalement par la suite #TODO
formule:
description: |
C'est la formule de calcul d'une variable. Elle renvoie une valeur numérique ou un 'non', exprimant le fait que la variable n'est pas applicable, ce qui vaut implicitement 0.
Cette doit faire appel à fera appel à des mécanismes de calcul : par exemple `multiplication`, le plus commun pour les variables de type `Cotisation`.
non applicable si:
description: |
Si cette variable est vraie, c'est que la variable n'est pas applicable pour la situation saisie.
> Pour une cotisation sociale, cela signifie qu'elle ne me concerne pas, que je n'ai pas à la verser.
La formule est donc à ignorer.
# à venir
# barème:
# description: |

10
source/engine/marked.js Normal file
View File

@ -0,0 +1,10 @@
import marked from 'marked'
let customMarked = new marked.Renderer()
customMarked.link = ( href, title, text ) =>
`<a target="_blank" href="${ href }" title="${ title }">${ text }</a>`
marked.setOptions({
renderer: customMarked
})
export default marked

View File

@ -2,15 +2,7 @@
import rawRules from './load-rules'
import R from 'ramda'
import possibleVariableTypes from './possibleVariableTypes.yaml'
import marked from 'marked'
let customMarked = new marked.Renderer()
customMarked.link = ( href, title, text ) =>
`<a target="_blank" href="${ href }" title="${ title }">${ text }</a>`
marked.setOptions({
renderer: customMarked
})
import marked from './marked'
/***********************************
Méthodes agissant sur une règle */

View File

@ -3,42 +3,44 @@ import R from 'ramda'
import classNames from 'classnames'
let treatValue = data =>
data == null
? '?'
: R.is(Number)(data) ? Math.round(data) : data ? 'oui' : 'non'
data == null
? '?'
: R.is(Number)(data) ? Math.round(data) : data ? 'oui' : 'non'
let NodeValue = ({data}) => (
<span className={'situationValue ' + treatValue(data)}>
&nbsp;
{treatValue(data)}
</span>
<span className={'situationValue ' + treatValue(data)}>
&nbsp;
{treatValue(data)}
</span>
)
// Un élément du graphe de calcul qui a une valeur interprétée (à afficher)
export class Node extends React.Component {
render() {
let {classes, name, value, child, termDefinition} = this.props
let
{classes, name, value, child} = this.props,
termDefinition = R.contains('mecanism', classes) && name
return (
<div className={classNames(classes, 'node')}>
{name &&
<span className="nodeHead">
<span className="name" data-term-definition={termDefinition} >{name}</span>
<NodeValue data={value} />
</span>}
{child}
{!name && <NodeValue data={value} />}
</div>
<div className={classNames(classes, 'node')}>
{name &&
<span className="nodeHead">
<span className="name" data-term-definition={termDefinition} >{name}</span>
<NodeValue data={value} />
</span>}
{child}
{!name && <NodeValue data={value} />}
</div>
)
}
}
// Un élément du graphe de calcul qui a une valeur interprétée (à afficher)
export let Leaf = ({classes, name, value}) => (
<span className={classNames(classes, 'leaf')}>
{name &&
<span className="nodeHead">
<span className="name">{name}<NodeValue data={value} /></span>
</span>}
</span>
<span className={classNames(classes, 'leaf')}>
{name &&
<span className="nodeHead">
<span className="name">{name}<NodeValue data={value} /></span>
</span>}
</span>
)

View File

@ -248,7 +248,6 @@ let treat = (situationGate, rule) => rawNode => {
)(v)
return {...result,
jsx: <Node
termDefinition={result.name}
classes="mecanism list"
name={result.name}
value={result.nodeValue}