L'exemple activé est gardé de /regle en /regle
Incontournable pour trouver pourquoi un exemple est rougepull/171/head
parent
94b31ac3e4
commit
054bb02873
|
@ -6,6 +6,10 @@ export function stepAction(name, step, source) {
|
|||
return { type: STEP_ACTION, name, step, source }
|
||||
}
|
||||
|
||||
export function setExample(name, situation) {
|
||||
return { type: 'SET_EXAMPLE', situation, name }
|
||||
}
|
||||
|
||||
export const START_CONVERSATION = 'START_CONVERSATION'
|
||||
|
||||
// Reset the form
|
||||
|
|
|
@ -6,6 +6,9 @@ import knownMecanisms from 'Engine/known-mecanisms.yaml'
|
|||
import { makeJsx } from 'Engine/evaluation'
|
||||
import './Algorithm.css'
|
||||
import { humanFigure } from '../../utils'
|
||||
import { head } from 'ramda'
|
||||
import { analyse } from 'Engine/traverse'
|
||||
import { exampleSituationGateWithDefaults } from './Examples'
|
||||
|
||||
let RuleWithoutFormula = () => (
|
||||
<p>
|
||||
|
@ -16,14 +19,21 @@ let RuleWithoutFormula = () => (
|
|||
|
||||
@AttachDictionary(knownMecanisms)
|
||||
export default class Algorithm extends React.Component {
|
||||
state = {
|
||||
showValues: true
|
||||
}
|
||||
render() {
|
||||
let { rule, showValues } = this.props,
|
||||
let { rule: displayedRule, showValues, currentExample, rules } = this.props,
|
||||
ruleWithoutFormula =
|
||||
!rule['formule'] ||
|
||||
path(['formule', 'explanation', 'une possibilité'], rule)
|
||||
!displayedRule['formule'] ||
|
||||
path(['formule', 'explanation', 'une possibilité'], displayedRule)
|
||||
|
||||
let rule = currentExample
|
||||
? head(
|
||||
analyse(rules, displayedRule.dottedName)(
|
||||
exampleSituationGateWithDefaults(currentExample.situation, rules)
|
||||
).targets
|
||||
)
|
||||
: displayedRule
|
||||
|
||||
console.log('didcomp')
|
||||
|
||||
return (
|
||||
<div id="algorithm">
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
import React, { Component } from 'react'
|
||||
import { evolve, path, isEmpty } from 'ramda'
|
||||
import { evolve, path, isEmpty, compose } from 'ramda'
|
||||
import classNames from 'classnames'
|
||||
import { connect } from 'react-redux'
|
||||
import { disambiguateExampleSituation, collectDefaults } from 'Engine/rules.js'
|
||||
import { analyse } from 'Engine/traverse'
|
||||
import './Examples.css'
|
||||
import { assume } from '../../reducers'
|
||||
import { setExample } from '../../actions'
|
||||
|
||||
export let exampleSituationGateWithDefaults = (situationObject, rules) =>
|
||||
assume(() => name => situationObject[name], collectDefaults(rules))()
|
||||
|
||||
// By luck this works as expected for both null and undefined, * but with different branches failing :O *
|
||||
export let isFloat = n => Number(n) === n && n % 1 !== 0
|
||||
|
@ -16,10 +20,8 @@ export let runExamples = (examples, rule, parsedRules) =>
|
|||
examples
|
||||
.map(evolve({ situation: disambiguateExampleSituation(parsedRules, rule) }))
|
||||
.map(ex => {
|
||||
let exampleSituationGate = () => name => ex.situation[name]
|
||||
|
||||
let runExample = analyse(parsedRules, rule.dottedName)(
|
||||
assume(exampleSituationGate, collectDefaults(parsedRules))()
|
||||
exampleSituationGateWithDefaults(ex.situation, parsedRules)
|
||||
),
|
||||
exampleValue = runExample.targets[0].nodeValue,
|
||||
goal = ex['valeur attendue'],
|
||||
|
@ -37,21 +39,25 @@ export let runExamples = (examples, rule, parsedRules) =>
|
|||
}
|
||||
})
|
||||
|
||||
@connect(state => ({
|
||||
situationGate: state.situationGate,
|
||||
parsedRules: state.parsedRules,
|
||||
colour: state.themeColours.colour
|
||||
}))
|
||||
@connect(
|
||||
state => ({
|
||||
situationGate: state.situationGate,
|
||||
parsedRules: state.parsedRules,
|
||||
colour: state.themeColours.colour
|
||||
}),
|
||||
dispatch => ({
|
||||
setExample: compose(dispatch, setExample)
|
||||
})
|
||||
)
|
||||
export default class Examples extends Component {
|
||||
render() {
|
||||
let focusedExample = path(['focusedExample', 'nom'])(this.props),
|
||||
{
|
||||
inject,
|
||||
let {
|
||||
situationExists,
|
||||
showValues,
|
||||
rule,
|
||||
parsedRules,
|
||||
colour
|
||||
colour,
|
||||
setExample,
|
||||
currentExample
|
||||
} = this.props,
|
||||
{ exemples = [] } = rule,
|
||||
examples = runExamples(exemples, rule, parsedRules)
|
||||
|
@ -70,46 +76,51 @@ export default class Examples extends Component {
|
|||
</p>
|
||||
) : (
|
||||
<ul>
|
||||
{examples.map(({ nom, ok, rule, 'valeur attendue': expected }) => (
|
||||
<li
|
||||
key={nom}
|
||||
className={classNames('example', {
|
||||
ok,
|
||||
selected: focusedExample == nom
|
||||
})}
|
||||
onClick={() => inject({ nom, ok, rule })}
|
||||
>
|
||||
<span>
|
||||
{' '}
|
||||
{ok ? (
|
||||
<i className="fa fa-check-circle" aria-hidden="true" />
|
||||
) : (
|
||||
<i className="fa fa-times" aria-hidden="true" />
|
||||
)}
|
||||
</span>
|
||||
<span className="name">{nom}</span>
|
||||
{!ok &&
|
||||
focusedExample == nom && (
|
||||
<div className="ko">
|
||||
Ce test ne passe pas
|
||||
{showValues && (
|
||||
{examples.map(
|
||||
({ nom, ok, rule, 'valeur attendue': expected, situation }) => (
|
||||
<li
|
||||
key={nom}
|
||||
className={classNames('example', {
|
||||
ok,
|
||||
selected: currentExample && currentExample.name == nom
|
||||
})}
|
||||
onClick={() =>
|
||||
currentExample
|
||||
? setExample(null)
|
||||
: setExample(nom, situation)
|
||||
}
|
||||
>
|
||||
<span>
|
||||
{' '}
|
||||
{ok ? (
|
||||
<i className="fa fa-check-circle" aria-hidden="true" />
|
||||
) : (
|
||||
<i className="fa fa-times" aria-hidden="true" />
|
||||
)}
|
||||
</span>
|
||||
<span className="name">{nom}</span>
|
||||
{!ok &&
|
||||
currentExample &&
|
||||
currentExample.name == nom && (
|
||||
<div className="ko">
|
||||
Ce test ne passe pas
|
||||
<span>
|
||||
: le résultat attendu était{' '}
|
||||
<span className="expected">{expected}</span>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</li>
|
||||
)
|
||||
)}
|
||||
</ul>
|
||||
)}
|
||||
{situationExists &&
|
||||
focusedExample && (
|
||||
currentExample && (
|
||||
<div>
|
||||
<button
|
||||
id="injectSituation"
|
||||
onClick={() => inject()}
|
||||
onClick={() => setExample(null)}
|
||||
style={{ background: colour }}
|
||||
>
|
||||
Revenir à votre situation
|
||||
|
|
|
@ -17,28 +17,16 @@ import SearchButton from 'Components/SearchButton'
|
|||
|
||||
@connect(state => ({
|
||||
form: state.form,
|
||||
rules: state.parsedRules
|
||||
rules: state.parsedRules,
|
||||
currentExample: state.currentExample
|
||||
}))
|
||||
export default class Rule extends Component {
|
||||
state = {
|
||||
example: null,
|
||||
showValues: true
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
let dn = path(['rule', 'dottedName'])
|
||||
if (dn(this.props) !== dn(this.nextProps)) {
|
||||
this.setState({ example: null })
|
||||
}
|
||||
}
|
||||
render() {
|
||||
let { form, rule } = this.props,
|
||||
conversationStarted = !isEmpty(form),
|
||||
situationExists = conversationStarted || this.state.example != null
|
||||
let { form, rule, currentExample, rules } = this.props,
|
||||
conversationStarted = !isEmpty(form)
|
||||
|
||||
let { type, name, title, description, question, ns } = rule,
|
||||
situationOrExampleRule = path(['example', 'rule'])(this.state) || rule,
|
||||
namespaceRules = findRuleByNamespace(this.props.rules, rule.dottedName)
|
||||
namespaceRules = findRuleByNamespace(rules, rule.dottedName)
|
||||
|
||||
return (
|
||||
<div id="rule">
|
||||
|
@ -60,8 +48,10 @@ export default class Rule extends Component {
|
|||
|
||||
<section id="rule-content">
|
||||
<Algorithm
|
||||
rule={situationOrExampleRule}
|
||||
showValues={situationExists}
|
||||
rules={rules}
|
||||
currentExample={currentExample}
|
||||
rule={rule}
|
||||
showValues={conversationStarted || currentExample}
|
||||
/>
|
||||
{rule.note && (
|
||||
<section id="notes">
|
||||
|
@ -70,15 +60,9 @@ export default class Rule extends Component {
|
|||
</section>
|
||||
)}
|
||||
<Examples
|
||||
currentExample={currentExample}
|
||||
situationExists={conversationStarted}
|
||||
rule={rule}
|
||||
focusedExample={this.state.example}
|
||||
showValues={this.state.showValues}
|
||||
inject={example =>
|
||||
this.state.example != null
|
||||
? this.setState({ example: null })
|
||||
: this.setState({ example, showValues: true })
|
||||
}
|
||||
/>
|
||||
{!isEmpty(namespaceRules) && (
|
||||
<NamespaceRulesList {...{ rule, namespaceRules }} />
|
||||
|
|
|
@ -1,4 +1,13 @@
|
|||
import { head, isEmpty, pathOr, reject, contains, without, concat, length } from 'ramda'
|
||||
import {
|
||||
head,
|
||||
isEmpty,
|
||||
pathOr,
|
||||
reject,
|
||||
contains,
|
||||
without,
|
||||
concat,
|
||||
length
|
||||
} from 'ramda'
|
||||
import { combineReducers } from 'redux'
|
||||
import reduceReducers from 'reduce-reducers'
|
||||
import { reducer as formReducer, formValueSelector } from 'redux-form'
|
||||
|
@ -116,7 +125,7 @@ export let reduceSteps = (tracker, flatRules, answerSource) => (
|
|||
if (action.type == STEP_ACTION && action.name == 'fold') {
|
||||
tracker.push([
|
||||
'trackEvent',
|
||||
'answer:'+action.source,
|
||||
'answer:' + action.source,
|
||||
action.step + ': ' + situationWithDefaults(state)(action.step)
|
||||
])
|
||||
|
||||
|
@ -124,7 +133,7 @@ export let reduceSteps = (tracker, flatRules, answerSource) => (
|
|||
tracker.push([
|
||||
'trackEvent',
|
||||
'done',
|
||||
'after'+length(newState.foldedSteps)+'questions'
|
||||
'after' + length(newState.foldedSteps) + 'questions'
|
||||
])
|
||||
}
|
||||
|
||||
|
@ -166,6 +175,15 @@ function explainedVariable(state = null, { type, variableName = null }) {
|
|||
}
|
||||
}
|
||||
|
||||
function currentExample(state = null, { type, situation, name }) {
|
||||
switch (type) {
|
||||
case 'SET_EXAMPLE':
|
||||
return name != null ? { name, situation } : null
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
export default reduceReducers(
|
||||
combineReducers({
|
||||
sessionId: (id = Math.floor(Math.random() * 1000000000000) + '') => id,
|
||||
|
@ -191,7 +209,9 @@ export default reduceReducers(
|
|||
|
||||
themeColours,
|
||||
|
||||
explainedVariable
|
||||
explainedVariable,
|
||||
|
||||
currentExample
|
||||
}),
|
||||
// cross-cutting concerns because here `state` is the whole state tree
|
||||
reduceSteps(ReactPiwik, rules, formatInputs(rules, formValueSelector))
|
||||
|
|
Loading…
Reference in New Issue