🐎 Enlève versement transport des pages de infrance"

pull/327/head
Johan Girod 2018-08-31 14:08:26 +02:00
parent 44312ef8be
commit d28af9f277
28 changed files with 1286514 additions and 156 deletions

View File

@ -35,6 +35,7 @@
"react-highlight-words": "^0.11.0",
"react-hot-loader": "^4.3.3",
"react-i18next": "^7.5.0",
"react-loadable": "^5.5.0",
"react-redux": "^5.0.7",
"react-router": "^4.2.0",
"react-router-dom": "^4.2.2",
@ -72,6 +73,7 @@
"@babel/plugin-proposal-decorators": "=7.0.0-beta.51",
"@babel/plugin-proposal-object-rest-spread": "=7.0.0-beta.51",
"@babel/plugin-syntax-decorators": "=7.0.0-beta.51",
"@babel/plugin-syntax-dynamic-import": "^7.0.0",
"@babel/polyfill": "=7.0.0-beta.51",
"@babel/preset-env": "=7.0.0-beta.51",
"@babel/preset-flow": "^7.0.0-beta.51",

View File

@ -7,7 +7,7 @@ import { compose } from 'ramda'
import React from 'react'
import { Trans, translate } from 'react-i18next'
import { connect } from 'react-redux'
import { noUserInputSelector } from 'Selectors/analyseSelectors'
import { noUserInputSelector } from 'Selectors/situationSelectors'
import { LinkButton } from 'Ui/Button'
import Banner from './Banner'
@ -33,7 +33,8 @@ const PreviousSimulationBanner = ({
<Trans i18nKey="previousSimulationBanner.retrieveButton">
Retrouver ma simulation
</Trans>
</LinkButton>.{' '}
</LinkButton>
.{' '}
<LinkButton onClick={deletePreviousSimulation}>
<Trans>Effacer</Trans>
</LinkButton>

View File

@ -12,10 +12,8 @@ import { Trans, translate } from 'react-i18next'
import { connect } from 'react-redux'
import { withRouter } from 'react-router'
import { Link, Redirect } from 'react-router-dom'
import {
flatRulesSelector,
noUserInputSelector
} from 'Selectors/analyseSelectors'
import { flatRulesSelector } from 'Selectors/analyseSelectors'
import { noUserInputSelector } from 'Selectors/situationSelectors'
import Namespace from './rule/Namespace'
import Rule from './rule/Rule'
import './RulePage.css'

View File

@ -8,9 +8,9 @@ import { Link } from 'react-router-dom'
import { animated, Spring } from 'react-spring'
import {
blockingInputControlsSelector,
nextStepsSelector,
noUserInputSelector
nextStepsSelector
} from 'Selectors/analyseSelectors'
import { noUserInputSelector } from 'Selectors/situationSelectors'
import * as Animate from 'Ui/animate'
import AnswerList from './AnswerList'
import Conversation from './conversation/Conversation'

View File

@ -3,10 +3,8 @@ import withTracker from 'Components/utils/withTracker'
import React, { Component } from 'react'
import { Trans, translate } from 'react-i18next'
import { connect } from 'react-redux'
import {
nextStepsSelector,
noUserInputSelector
} from 'Selectors/analyseSelectors'
import { nextStepsSelector } from 'Selectors/analyseSelectors'
import { noUserInputSelector } from 'Selectors/situationSelectors'
import Smiley from './SatisfactionSmiley'
@connect(state => ({

View File

@ -13,27 +13,16 @@ import { change, Field, formValueSelector, reduxForm } from 'redux-form'
import {
analysisWithDefaultsSelector,
blockingInputControlsSelector,
flatRulesSelector,
noUserInputSelector
flatRulesSelector
} from 'Selectors/analyseSelectors'
import { noUserInputSelector } from 'Selectors/situationSelectors'
import { displayedTargetNames } from '../config'
import AnimatedTargetValue from './AnimatedTargetValue'
import Controls from './Controls'
import CurrencyInput from './CurrencyInput/CurrencyInput'
import ProgressCircle from './ProgressCircle'
import './TargetSelection.css'
let salaries = [
'contrat salarié . salaire . total',
'contrat salarié . salaire . brut de base',
'contrat salarié . salaire . net à payer'
]
let displayedTargetNames = [...salaries, 'contrat salarié . aides employeur']
export let popularTargetNames = [
...displayedTargetNames,
'contrat salarié . salaire . net imposable'
]
@translate()
@reduxForm({
form: 'conversation',

View File

@ -14,9 +14,9 @@ import { Link } from 'react-router-dom'
import {
exampleAnalysisSelector,
flatRulesSelector,
noUserInputSelector,
ruleAnalysisSelector
} from 'Selectors/analyseSelectors'
import { noUserInputSelector } from 'Selectors/situationSelectors'
import Algorithm from './Algorithm'
import Examples from './Examples'
import RuleHeader from './Header'

View File

19
source/config.js Normal file
View File

@ -0,0 +1,19 @@
let salaries = [
'contrat salarié . salaire . total',
'contrat salarié . salaire . brut de base',
'contrat salarié . salaire . net à payer'
]
export let displayedTargetNames = [
...salaries,
'contrat salarié . aides employeur'
]
export let popularTargetNames = [
...displayedTargetNames,
'contrat salarié . salaire . net imposable'
]
export default {
popularTargetNames,
displayedTargetNames
}

View File

@ -0,0 +1,13 @@
import rawRules from 'Règles/base.yaml'
import translations from 'Règles/externalized.yaml'
// TODO - should be in UI, not engine
import taux_versement_transport from 'Règles/taux-versement-transport.json'
import { enrichRule, translateAll } from './rules'
// On enrichit la base de règles avec des propriétés dérivées de celles du YAML
export let rules = translateAll(translations, rawRules).map(rule =>
enrichRule(rule, { taux_versement_transport })
)
export let rulesFr = rawRules.map(rule =>
enrichRule(rule, { taux_versement_transport })
)

View File

@ -1,39 +1,34 @@
// Séparation artificielle, temporaire, entre ces deux types de règles
import rawRules from 'Règles/base.yaml'
import translations from 'Règles/externalized.yaml'
import formValueTypes from 'Components/conversation/formValueTypes'
import {
assoc,
mapObjIndexed,
chain,
has,
pipe,
toPairs,
map,
fromPairs,
split,
join,
dropLast,
take,
propEq,
reduce,
when,
is,
props,
fromPairs,
has,
identity,
path,
reject,
reduced,
range,
is,
join,
last,
trim
map,
mapObjIndexed,
path,
pipe,
propEq,
props,
range,
reduce,
reduced,
reject,
split,
take,
toPairs,
trim,
when
} from 'ramda'
import possibleVariableTypes from './possibleVariableTypes.yaml'
import marked from './marked'
import { capitalise0 } from '../utils'
import formValueTypes from 'Components/conversation/formValueTypes'
// TODO - should be in UI, not engine
import taux_versement_transport from 'Règles/taux-versement-transport.json'
import marked from './marked'
import possibleVariableTypes from './possibleVariableTypes.yaml'
// console.log('rawRules', rawRules.map(({espace, nom}) => espace + nom))
/***********************************
@ -84,8 +79,15 @@ export let hasKnownRuleType = rule => rule && enrichRule(rule).type
export let splitName = split(' . '),
joinName = join(' . ')
export let parentName = pipe(splitName, dropLast(1), joinName)
export let nameLeaf = pipe(splitName, last)
export let parentName = pipe(
splitName,
dropLast(1),
joinName
)
export let nameLeaf = pipe(
splitName,
last
)
export let encodeRuleName = name =>
name.replace(/\s\.\s/g, '--').replace(/\s/g, '-')
@ -137,18 +139,6 @@ export let findRuleByName = (allRules, query) =>
export let findRulesByName = (allRules, query) =>
allRules.filter(({ name }) => name === query)
export let searchRules = searchInput =>
rules
.filter(
rule =>
rule &&
hasKnownRuleType(rule) &&
JSON.stringify(rule)
.toLowerCase()
.indexOf(searchInput) > -1
)
.map(enrichRule)
export let findRuleByDottedName = (allRules, dottedName) => {
return allRules.find(rule => rule.dottedName == dottedName)
}
@ -244,11 +234,3 @@ export let translateAll = (translations, flatRules) => {
return map(translateRule('en', translations, targets), flatRules)
}
// On enrichit la base de règles avec des propriétés dérivées de celles du YAML
export let rules = translateAll(translations, rawRules).map(rule =>
enrichRule(rule, { taux_versement_transport })
)
export let rulesFr = rawRules.map(rule =>
enrichRule(rule, { taux_versement_transport })
)

View File

@ -2,13 +2,9 @@
// $FlowFixMe
import { actionTypes } from 'redux-form'
import {
currentQuestionSelector,
formattedSituationSelector
} from 'Selectors/analyseSelectors'
import { debounce } from '../utils'
import type { Tracker } from 'Components/utils/withTracker'
const analyseSelectors = import('Selectors/analyseSelectors')
export default (tracker: Tracker) => {
const debouncedUserInputTracking = debounce(1000, action =>
tracker.push(['trackEvent', 'input', action.meta.field, action.payload])
@ -19,22 +15,26 @@ export default (tracker: Tracker) => {
next(action)
const newState = getState()
if (action.type == 'STEP_ACTION' && action.name == 'fold') {
tracker.push([
'trackEvent',
'answer:' + action.source,
action.step,
formattedSituationSelector(newState)[action.step]
])
analyseSelectors.then(
({ formattedSituationSelector, currentQuestionSelector }) => {
tracker.push([
'trackEvent',
'answer:' + action.source,
action.step,
formattedSituationSelector(newState)[action.step]
])
if (!currentQuestionSelector(newState)) {
tracker.push([
'trackEvent',
'done',
'after ' +
newState.conversationSteps.foldedSteps.length +
' questions'
])
}
if (!currentQuestionSelector(newState)) {
tracker.push([
'trackEvent',
'done',
'after ' +
newState.conversationSteps.foldedSteps.length +
' questions'
])
}
}
)
}
if (action.type === 'SET_ACTIVE_TARGET_INPUT') {
tracker.push(['trackEvent', 'select', newState.activeTargetInput])

View File

@ -1,6 +1,5 @@
/* @flow */
import { popularTargetNames } from 'Components/TargetSelection'
import { defaultTo, without } from 'ramda'
// $FlowFixMe
import reduceReducers from 'reduce-reducers'
@ -8,6 +7,7 @@ import { combineReducers } from 'redux'
// $FlowFixMe
import { reducer as formReducer } from 'redux-form'
import computeThemeColours from 'Ui/themeColours'
import { popularTargetNames } from '../config'
import defaultLang from '../i18n'
import inFranceAppReducer from './inFranceAppReducer'
import storageReducer from './storageReducer'

View File

@ -7,17 +7,19 @@ import {
disambiguateExampleSituation,
findRuleByDottedName,
formatInputs,
nestedSituationToPathMap,
nestedSituationToPathMap
} from 'Engine/rules'
import {
rules as baseRulesEn,
rulesFr as baseRulesFr
} from 'Engine/rules'
} from 'Engine/ruleWithVersementTransport'
import { analyse, analyseMany, parseAll } from 'Engine/traverse'
import { equals, head, isEmpty, pick } from 'ramda'
import { getFormValues } from 'redux-form'
import { createSelector, createSelectorCreator, defaultMemoize } from 'reselect'
import { head, pick } from 'ramda'
import { createSelector } from 'reselect'
import { createDeepEqualSelector } from '../utils'
import { situationSelector, validatedStepsSelector } from './situationSelectors'
// create a "selector creator" that uses deep equal instead of ===
const createDeepEqualSelector = createSelectorCreator(defaultMemoize, equals)
/*
*
@ -42,29 +44,11 @@ let ruleDefaultsSelector = createSelector([flatRulesSelector], rules =>
let targetNamesSelector = state => state.targetNames
export let situationSelector = createDeepEqualSelector(
getFormValues('conversation'),
x => x
)
export let noUserInputSelector = createSelector(
[situationSelector],
situation => !situation || isEmpty(situation)
)
export let formattedSituationSelector = createSelector(
[flatRulesSelector, situationSelector],
(rules, situation) => formatInputs(rules, nestedSituationToPathMap(situation))
)
let validatedStepsSelector = createSelector(
[
state => state.conversationSteps.foldedSteps,
state => state.activeTargetInput
],
(foldedSteps, target) => [...foldedSteps, target]
)
export let validatedSituationSelector = createSelector(
[formattedSituationSelector, validatedStepsSelector],
(situation, validatedSteps) => pick(validatedSteps, situation)

View File

@ -2,10 +2,9 @@
import { createSelector, createStructuredSelector } from 'reselect'
import {
blockingInputControlsSelector,
nextStepsSelector,
noUserInputSelector
nextStepsSelector
} from 'Selectors/analyseSelectors'
import { noUserInputSelector } from 'Selectors/situationSelectors'
const STATUS_SELECTION_COEFFICIENT = 0.4
const NUMBER_MAX_QUESTION_COMPANY = 5
const companyProgressSelector = createSelector(

View File

@ -0,0 +1,22 @@
import { isEmpty } from 'ramda'
import { getFormValues } from 'redux-form'
import { createSelector } from 'reselect'
import { createDeepEqualSelector } from '../utils'
export let situationSelector = createDeepEqualSelector(
getFormValues('conversation'),
x => x
)
export let noUserInputSelector = createSelector(
[situationSelector],
situation => !situation || isEmpty(situation)
)
export let validatedStepsSelector = createSelector(
[
state => state.conversationSteps.foldedSteps,
state => state.activeTargetInput
],
(foldedSteps, target) => [...foldedSteps, target]
)

View File

@ -1,5 +1,6 @@
import TrackPageView from 'Components/utils/TrackPageView'
import React, { Component } from 'react'
import Loadable from 'react-loadable'
import { Route, Switch } from 'react-router-dom'
import 'Ui/index.css'
import Provider from '../../Provider'
@ -11,9 +12,14 @@ import './App.css'
import Landing from './Landing'
import CreateMyCompany from './pages/Company'
import Footer from './pages/Footer/Footer'
import StepsHeader from './pages/Header/StepsHeader'
import HiringProcess from './pages/HiringProcess'
import SocialSecurity from './pages/SocialSecurity'
const StepsHeader = Loadable({
loader: () => import('./pages/Header/StepsHeader'),
loading: () => null
})
class InFranceRoute extends Component {
componentDidMount() {
if (typeof sessionStorage !== 'undefined') {

View File

@ -1,27 +1,23 @@
/* @flow */
import { compose } from 'ramda'
import React, { Component } from 'react'
import Loadable from 'react-loadable'
import { connect } from 'react-redux'
import * as Animate from 'Ui/animate'
import type Simulateur from 'Components/Simu'
const Simulateur = Loadable({
loader: () => import('Components/Simu'),
loading() {
return null
}
})
type Props = {
hideText: boolean
}
type State = {
simulateur: ?Simulateur
}
class SocialSecurity extends Component<Props, State> {
state = {
simulateur: null
}
componentDidMount() {
import('Components/Simu').then(Simulateur =>
this.setState({ simulateur: Simulateur.default })
)
}
class SocialSecurity extends Component<Props, {}> {
render() {
const Simulateur = this.state.simulateur
return (
<>
<Animate.fromBottom>
@ -60,7 +56,7 @@ class SocialSecurity extends Component<Props, State> {
<h2>How much does it cost ?</h2>
</>
)}
{Simulateur && <Simulateur displayHiringProcedures />}
<Simulateur displayHiringProcedures />
</Animate.fromBottom>
</>
)

View File

@ -1,15 +1,19 @@
import RulePage from 'Components/RulePage'
import { ScrollToTop } from 'Components/utils/Scroll'
import React from 'react'
import Loadable from 'react-loadable'
import { Route, Switch } from 'react-router'
import Home from './Home'
const RulePage = Loadable({
loader: () => import('Components/RulePage'),
loading: () => null
})
const SocialSecurityRoutes = ({ match }) => (
<>
<ScrollToTop />
<Switch>
<Route path={`${match.path}/règle/:name`} component={RulePage} />
<Route path={`${match.path}`} component={Home} />
<Route path={`${match.path}/règle/:name`} component={RulePage} />
</Switch>
</>
)

View File

@ -1,5 +1,6 @@
/* @flow */
import { map } from 'ramda'
import { equals, map } from 'ramda'
import { createSelectorCreator, defaultMemoize } from 'reselect'
export let capitalise0 = (name: string) => name[0].toUpperCase() + name.slice(1)
@ -64,3 +65,8 @@ export function inIframe() {
return true
}
}
export const createDeepEqualSelector = createSelectorCreator(
defaultMemoize,
equals
)

431233
stats2.json Normal file

File diff suppressed because one or more lines are too long

422355
stats3.json Normal file

File diff suppressed because one or more lines are too long

432750
stats4.json Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,10 +1,11 @@
import { expect } from 'chai'
import { popularTargetNames } from 'Components/TargetSelection'
import dedent from 'dedent-js'
import { enrichRule, rulesFr as rules } from 'Engine/rules'
import { enrichRule } from 'Engine/rules'
import { rulesFr as rules } from 'Engine/ruleWithVersementTransport'
import yaml from 'js-yaml'
import { assocPath, merge } from 'ramda'
import reducers from 'Reducers/rootReducer'
import { popularTargetNames } from '../source/config'
import {
currentQuestionSelector,
nextStepsSelector

View File

@ -3,7 +3,8 @@ import {
collectMissingVariables,
getNextSteps
} from '../source/engine/generateQuestions'
import { enrichRule, rules as realRules } from '../source/engine/rules'
import { enrichRule } from '../source/engine/rules'
import { rules as realRules } from '../source/engine/ruleWithVersementTransport'
import { analyse, parseAll } from '../source/engine/traverse'
let stateSelector = () => null

View File

@ -2,7 +2,8 @@ import { expect } from 'chai'
import dedent from 'dedent-js'
import yaml from 'js-yaml'
import { collectMissingVariables } from '../source/engine/generateQuestions'
import { enrichRule, rules as realRules } from '../source/engine/rules'
import { enrichRule } from '../source/engine/rules'
import { rules as realRules } from '../source/engine/ruleWithVersementTransport'
import { analyse, analyseMany, parseAll } from '../source/engine/traverse'
describe('inversions', () => {

View File

@ -5,10 +5,10 @@
*/
import { AssertionError } from 'chai'
import { rules } from '../source/engine/rules'
import { parseAll } from '../source/engine/traverse'
import { exampleAnalysisSelector } from 'Selectors/analyseSelectors'
import { merge } from 'ramda'
import { exampleAnalysisSelector } from 'Selectors/analyseSelectors'
import { rules } from '../source/engine/ruleWithVersementTransport'
import { parseAll } from '../source/engine/traverse'
// les variables dans les tests peuvent être exprimées relativement à l'espace de nom de la règle,
// comme dans sa formule

View File

@ -1,13 +1,11 @@
import { map } from 'ramda'
import { expect } from 'chai'
import { map } from 'ramda'
import {
rules,
enrichRule,
translateAll,
nestedSituationToPathMap
nestedSituationToPathMap,
translateAll
} from '../source/engine/rules'
let stateSelector = (state, name) => null
import { rules } from '../source/engine/ruleWithVersementTransport'
describe('enrichRule', function() {
it('should extract the type of the rule', function() {