💚 fix flow
Suppression des décorateurs. Problème : Les décorateurs que l'on utilisait correspondait à une ancienne version de la proposal tc39, encore en stage 1 (voir 0). La proposition a complètement évolué, pour ne plus du tout avoir la même forme que précédement. Au lieu de garder la version 'legacy', on choisit de se séparer des décorateur, étant donné que le nouveau use case n'a plus rien à voir, et que l'ancienne version peut être gérée de manière quasi équivalente avec des fonctions et des composepull/418/head
parent
05d1c20aa0
commit
1d69feafd6
|
@ -34,7 +34,7 @@
|
|||
"react-helmet": "^5.2.0",
|
||||
"react-highlight-words": "^0.11.0",
|
||||
"react-hot-loader": "^4.3.11",
|
||||
"react-i18next": "^7.13.0",
|
||||
"react-i18next": "^8.3.0",
|
||||
"react-redux": "^5.0.7",
|
||||
"react-router": "^4.2.0",
|
||||
"react-router-dom": "^4.2.2",
|
||||
|
@ -48,7 +48,7 @@
|
|||
"redux": "^3.7.2",
|
||||
"redux-form": "^7.4.2",
|
||||
"redux-thunk": "^2.3.0",
|
||||
"reselect": "^3.0.1",
|
||||
"reselect": "^4.0.0",
|
||||
"screenfull": "^3.3.2"
|
||||
},
|
||||
"scripts": {
|
||||
|
@ -71,10 +71,9 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.1.0",
|
||||
"@babel/plugin-proposal-decorators": "^7.1.0",
|
||||
"@babel/plugin-proposal-class-properties": "^7.1.0",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.0.0",
|
||||
"@babel/plugin-syntax-decorators": "^7.1.0",
|
||||
"@babel/polyfill": "^7.0.0",
|
||||
"@babel/preset-env": "^7.1.0",
|
||||
"@babel/preset-flow": "^7.0.0-beta.51",
|
||||
|
@ -84,8 +83,6 @@
|
|||
"babel-eslint": "^9.0.0",
|
||||
"babel-loader": "^8.0.2",
|
||||
"babel-plugin-syntax-dynamic-import": "^6.18.0",
|
||||
"babel-plugin-transform-class-properties": "^6.24.1",
|
||||
"babel-plugin-transform-decorators": "^6.24.1",
|
||||
"babel-plugin-transform-do-expressions": "^6.22.0",
|
||||
"babel-plugin-webpack-alias": "^2.1.2",
|
||||
"chai": "^4.1.2",
|
||||
|
|
|
@ -13,11 +13,10 @@
|
|||
"@babel/flow"
|
||||
],
|
||||
"plugins": [
|
||||
["@babel/plugin-proposal-decorators", { "legacy": true }],
|
||||
"transform-do-expressions",
|
||||
"@babel/plugin-proposal-class-properties",
|
||||
"@babel/plugin-proposal-optional-chaining",
|
||||
"@babel/plugin-proposal-object-rest-spread",
|
||||
"transform-class-properties",
|
||||
"transform-do-expressions",
|
||||
"syntax-dynamic-import",
|
||||
"react-hot-loader/babel",
|
||||
["webpack-alias", { "config": "./source/webpack.dev.js" }]
|
||||
|
|
|
@ -2,55 +2,60 @@ import { EXPLAIN_VARIABLE } from 'Actions/actions'
|
|||
import withColours from 'Components/utils/withColours'
|
||||
import marked from 'Engine/marked'
|
||||
import { findRuleByDottedName } from 'Engine/rules'
|
||||
import { compose } from 'ramda'
|
||||
import React, { Component } from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import { flatRulesSelector } from 'Selectors/analyseSelectors'
|
||||
import './Aide.css'
|
||||
import References from './rule/References'
|
||||
@connect(
|
||||
state => ({
|
||||
explained: state.explainedVariable,
|
||||
flatRules: flatRulesSelector(state)
|
||||
}),
|
||||
dispatch => ({
|
||||
stopExplaining: () => dispatch({ type: EXPLAIN_VARIABLE })
|
||||
})
|
||||
|
||||
export default compose(
|
||||
connect(
|
||||
state => ({
|
||||
explained: state.explainedVariable,
|
||||
flatRules: flatRulesSelector(state)
|
||||
}),
|
||||
dispatch => ({
|
||||
stopExplaining: () => dispatch({ type: EXPLAIN_VARIABLE })
|
||||
})
|
||||
),
|
||||
withColours
|
||||
)(
|
||||
class Aide extends Component {
|
||||
renderExplanationMarkdown(explanation, term) {
|
||||
return marked(`### ${term} \n\n${explanation}`)
|
||||
}
|
||||
render() {
|
||||
let { flatRules, explained, stopExplaining, colours } = this.props
|
||||
|
||||
if (!explained) return <section id="helpWrapper" />
|
||||
|
||||
let rule = findRuleByDottedName(flatRules, explained),
|
||||
text = rule.description,
|
||||
refs = rule.références
|
||||
|
||||
return (
|
||||
<div id="helpWrapper" className="active">
|
||||
<section id="help">
|
||||
<i
|
||||
className="fa fa-times-circle"
|
||||
onClick={stopExplaining}
|
||||
style={{ color: colours.colour }}
|
||||
/>
|
||||
<p
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: this.renderExplanationMarkdown(text, rule.title)
|
||||
}}
|
||||
/>
|
||||
{refs && (
|
||||
<div>
|
||||
<p>Pour en savoir plus: </p>
|
||||
<References refs={refs} />
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
@withColours
|
||||
export default class Aide extends Component {
|
||||
renderExplanationMarkdown(explanation, term) {
|
||||
return marked(`### ${term} \n\n${explanation}`)
|
||||
}
|
||||
render() {
|
||||
let { flatRules, explained, stopExplaining, colours } = this.props
|
||||
|
||||
if (!explained) return <section id="helpWrapper" />
|
||||
|
||||
let rule = findRuleByDottedName(flatRules, explained),
|
||||
text = rule.description,
|
||||
refs = rule.références
|
||||
|
||||
return (
|
||||
<div id="helpWrapper" className="active">
|
||||
<section id="help">
|
||||
<i
|
||||
className="fa fa-times-circle"
|
||||
onClick={stopExplaining}
|
||||
style={{ color: colours.colour }}
|
||||
/>
|
||||
<p
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: this.renderExplanationMarkdown(text, rule.title)
|
||||
}}
|
||||
/>
|
||||
{refs && (
|
||||
<div>
|
||||
<p>Pour en savoir plus: </p>
|
||||
<References refs={refs} />
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,34 +1,32 @@
|
|||
import React, { Component } from 'react'
|
||||
import withLanguage from 'Components/utils/withLanguage'
|
||||
|
||||
import './AnimatedTargetValue.css'
|
||||
import React, { Component } from 'react'
|
||||
import ReactCSSTransitionGroup from 'react-addons-css-transition-group'
|
||||
import './AnimatedTargetValue.css'
|
||||
|
||||
@withLanguage
|
||||
class AnimatedTargetValue extends Component {
|
||||
render() {
|
||||
let { value, language } = this.props
|
||||
let formattedValue =
|
||||
value == null
|
||||
? ''
|
||||
: Intl.NumberFormat(language, {
|
||||
style: 'currency',
|
||||
currency: 'EUR',
|
||||
maximumFractionDigits: 0,
|
||||
minimumFractionDigits: 0
|
||||
}).format(value)
|
||||
return (
|
||||
<ReactCSSTransitionGroup
|
||||
transitionName="flash"
|
||||
transitionEnterTimeout={100}
|
||||
transitionLeaveTimeout={100}>
|
||||
<span key={value} className="Rule-value">
|
||||
{' '}
|
||||
<span>{formattedValue}</span>
|
||||
</span>
|
||||
</ReactCSSTransitionGroup>
|
||||
)
|
||||
export default withLanguage(
|
||||
class AnimatedTargetValue extends Component {
|
||||
render() {
|
||||
let { value, language } = this.props
|
||||
let formattedValue =
|
||||
value == null
|
||||
? ''
|
||||
: Intl.NumberFormat(language, {
|
||||
style: 'currency',
|
||||
currency: 'EUR',
|
||||
maximumFractionDigits: 0,
|
||||
minimumFractionDigits: 0
|
||||
}).format(value)
|
||||
return (
|
||||
<ReactCSSTransitionGroup
|
||||
transitionName="flash"
|
||||
transitionEnterTimeout={100}
|
||||
transitionLeaveTimeout={100}>
|
||||
<span key={value} className="Rule-value">
|
||||
{' '}
|
||||
<span>{formattedValue}</span>
|
||||
</span>
|
||||
</ReactCSSTransitionGroup>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default AnimatedTargetValue
|
||||
)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import withTracker from 'Components/utils/withTracker'
|
||||
import React, { Component } from 'react'
|
||||
import { Trans, translate } from 'react-i18next'
|
||||
import { Trans, withI18n } from 'react-i18next'
|
||||
import { withRouter } from 'react-router-dom'
|
||||
import { compose } from 'redux'
|
||||
import safeLocalStorage from '../../storage/safeLocalStorage'
|
||||
|
@ -93,37 +93,36 @@ class PageFeedback extends Component<Props, State> {
|
|||
return (
|
||||
!this.props.blacklist.includes(this.props.location.pathname) && (
|
||||
<div className="feedback-page ui__ container notice">
|
||||
{!this.state.showForm &&
|
||||
!this.state.showThanks && (
|
||||
<>
|
||||
<div style={{ flex: 1 }}>
|
||||
{this.props.customMessage || (
|
||||
<Trans i18nKey="feedback.question">
|
||||
Cette page vous a-t-elle été utile ?
|
||||
</Trans>
|
||||
)}{' '}
|
||||
<button
|
||||
style={{ marginLeft: '0.4rem' }}
|
||||
className="ui__ link-button"
|
||||
onClick={() => this.handleFeedback({ useful: true })}>
|
||||
<Trans>Oui</Trans>
|
||||
</button>{' '}
|
||||
<button
|
||||
style={{ marginLeft: '0.4rem' }}
|
||||
className="ui__ link-button"
|
||||
onClick={() => this.handleFeedback({ useful: false })}>
|
||||
<Trans>Non</Trans>
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
className="ui__ link-button"
|
||||
onClick={this.handleErrorReporting}>
|
||||
<Trans i18nKey="feedback.reportError">
|
||||
Signaler une erreur
|
||||
{!this.state.showForm && !this.state.showThanks && (
|
||||
<>
|
||||
<div style={{ flex: 1 }}>
|
||||
{this.props.customMessage || (
|
||||
<Trans i18nKey="feedback.question">
|
||||
Cette page vous a-t-elle été utile ?
|
||||
</Trans>
|
||||
)}{' '}
|
||||
<button
|
||||
style={{ marginLeft: '0.4rem' }}
|
||||
className="ui__ link-button"
|
||||
onClick={() => this.handleFeedback({ useful: true })}>
|
||||
<Trans>Oui</Trans>
|
||||
</button>{' '}
|
||||
</>
|
||||
)}
|
||||
<button
|
||||
style={{ marginLeft: '0.4rem' }}
|
||||
className="ui__ link-button"
|
||||
onClick={() => this.handleFeedback({ useful: false })}>
|
||||
<Trans>Non</Trans>
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
className="ui__ link-button"
|
||||
onClick={this.handleErrorReporting}>
|
||||
<Trans i18nKey="feedback.reportError">
|
||||
Signaler une erreur
|
||||
</Trans>
|
||||
</button>{' '}
|
||||
</>
|
||||
)}
|
||||
{this.state.showThanks && (
|
||||
<div>
|
||||
<Trans i18nKey="feedback.thanks">
|
||||
|
@ -150,7 +149,7 @@ const PageFeedbackWithRouter = ({ location, ...props }) => (
|
|||
)
|
||||
|
||||
export default compose(
|
||||
translate(),
|
||||
withI18n(),
|
||||
withTracker,
|
||||
withRouter
|
||||
)(PageFeedbackWithRouter)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import PropTypes from 'prop-types'
|
||||
import { compose } from 'ramda'
|
||||
import React, { Component } from 'react'
|
||||
import emoji from 'react-easy-emoji'
|
||||
import { translate } from 'react-i18next'
|
||||
import { withI18n } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import { withRouter } from 'react-router'
|
||||
|
||||
|
@ -10,37 +10,38 @@ const languageCodeToEmoji = {
|
|||
fr: '🇫🇷'
|
||||
}
|
||||
|
||||
@withRouter
|
||||
@translate()
|
||||
@connect(
|
||||
null,
|
||||
dispatch => ({
|
||||
changeLanguage: lang => dispatch({ type: 'SWITCH_LANG', lang })
|
||||
})
|
||||
)
|
||||
export default class LangSwitcher extends Component {
|
||||
static contextTypes = {
|
||||
i18n: PropTypes.object.isRequired
|
||||
}
|
||||
getUnusedLanguageCode = () => {
|
||||
let languageCode = this.context.i18n.language
|
||||
return !languageCode || languageCode === 'fr' ? 'en' : 'fr'
|
||||
}
|
||||
export default compose(
|
||||
withRouter,
|
||||
withI18n(),
|
||||
connect(
|
||||
null,
|
||||
dispatch => ({
|
||||
changeLanguage: lang => dispatch({ type: 'SWITCH_LANG', lang })
|
||||
})
|
||||
)
|
||||
)(
|
||||
class LangSwitcher extends Component {
|
||||
getUnusedLanguageCode = () => {
|
||||
let languageCode = this.props.i18n.language
|
||||
return !languageCode || languageCode === 'fr' ? 'en' : 'fr'
|
||||
}
|
||||
|
||||
changeLanguage = () => {
|
||||
let nextLanguage = this.getUnusedLanguageCode()
|
||||
this.props.changeLanguage(nextLanguage)
|
||||
this.context.i18n.changeLanguage(nextLanguage)
|
||||
this.forceUpdate()
|
||||
changeLanguage = () => {
|
||||
let nextLanguage = this.getUnusedLanguageCode()
|
||||
this.props.changeLanguage(nextLanguage)
|
||||
this.props.i18n.changeLanguage(nextLanguage)
|
||||
this.forceUpdate()
|
||||
}
|
||||
render() {
|
||||
const languageCode = this.getUnusedLanguageCode()
|
||||
return (
|
||||
<button
|
||||
className={this.props.className || 'ui__ link-button'}
|
||||
onClick={this.changeLanguage}>
|
||||
{emoji(languageCodeToEmoji[languageCode])}{' '}
|
||||
{languageCode.toUpperCase()}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
}
|
||||
render() {
|
||||
const languageCode = this.getUnusedLanguageCode()
|
||||
return (
|
||||
<button
|
||||
className={this.props.className || 'ui__ link-button'}
|
||||
onClick={this.changeLanguage}>
|
||||
{emoji(languageCodeToEmoji[languageCode])} {languageCode.toUpperCase()}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import Overlay from 'Components/Overlay'
|
||||
import { ScrollToTop } from 'Components/utils/Scroll'
|
||||
import React, { Component } from 'react'
|
||||
import { Trans } from 'react-i18next'
|
||||
import translate from 'react-i18next/dist/commonjs/translate'
|
||||
import { Trans, withI18n } from 'react-i18next'
|
||||
|
||||
export const LegalNoticeContent = translate()(() => (
|
||||
export const LegalNoticeContent = withI18n()(() => (
|
||||
<>
|
||||
<h1>
|
||||
<Trans i18nKey="legalNotice.title">Mentions légales</Trans>
|
||||
|
|
|
@ -5,7 +5,7 @@ import {
|
|||
} from 'Actions/actions'
|
||||
import { compose } from 'ramda'
|
||||
import React from 'react'
|
||||
import { Trans, translate } from 'react-i18next'
|
||||
import { Trans, withI18n } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import { noUserInputSelector } from 'Selectors/analyseSelectors'
|
||||
import { LinkButton } from 'Ui/Button'
|
||||
|
@ -33,7 +33,8 @@ const PreviousSimulationBanner = ({
|
|||
<Trans i18nKey="previousSimulationBanner.retrieveButton">
|
||||
Retrouver ma simulation
|
||||
</Trans>
|
||||
</LinkButton>.{' '}
|
||||
</LinkButton>
|
||||
.{' '}
|
||||
<LinkButton onClick={deletePreviousSimulation}>
|
||||
<Trans>Effacer</Trans>
|
||||
</LinkButton>
|
||||
|
@ -41,7 +42,7 @@ const PreviousSimulationBanner = ({
|
|||
)
|
||||
|
||||
export default compose(
|
||||
translate(),
|
||||
withI18n(),
|
||||
connect(
|
||||
state => ({
|
||||
previousSimulation: state.previousSimulation,
|
||||
|
|
|
@ -4,27 +4,28 @@ import { connect } from 'react-redux'
|
|||
import { nextStepsSelector } from 'Selectors/analyseSelectors'
|
||||
import './ProgressTip.css'
|
||||
|
||||
@connect(state => ({
|
||||
export default connect(state => ({
|
||||
nextSteps: nextStepsSelector(state)
|
||||
}))
|
||||
export default class ProgressTip extends Component {
|
||||
render() {
|
||||
let { nextSteps } = this.props,
|
||||
nbQuestions = nextSteps.length
|
||||
if (nbQuestions === 0) return null
|
||||
}))(
|
||||
class ProgressTip extends Component {
|
||||
render() {
|
||||
let { nextSteps } = this.props,
|
||||
nbQuestions = nextSteps.length
|
||||
if (nbQuestions === 0) return null
|
||||
|
||||
return (
|
||||
<div className="progressTip">
|
||||
<p>
|
||||
{nbQuestions === 1 ? (
|
||||
<Trans i18nKey="lastQ">dernière question !</Trans>
|
||||
) : (
|
||||
<Trans i18nKey="questionsLeft" count={nbQuestions}>
|
||||
moins de {{ nbQuestions }} questions
|
||||
</Trans>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
return (
|
||||
<div className="progressTip">
|
||||
<p>
|
||||
{nbQuestions === 1 ? (
|
||||
<Trans i18nKey="lastQ">dernière question !</Trans>
|
||||
) : (
|
||||
<Trans i18nKey="questionsLeft" count={nbQuestions}>
|
||||
moins de {{ nbQuestions }} questions
|
||||
</Trans>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
} from 'Engine/rules.js'
|
||||
import { compose, head, path } from 'ramda'
|
||||
import React, { Component } from 'react'
|
||||
import { Trans, translate } from 'react-i18next'
|
||||
import { Trans, withI18n } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import { withRouter } from 'react-router'
|
||||
import { Link, Redirect } from 'react-router-dom'
|
||||
|
@ -20,80 +20,88 @@ import Namespace from './rule/Namespace'
|
|||
import Rule from './rule/Rule'
|
||||
import './RulePage.css'
|
||||
import SearchButton from './SearchButton'
|
||||
@connect(state => ({
|
||||
themeColours: state.themeColours,
|
||||
valuesToShow: !noUserInputSelector(state),
|
||||
flatRules: flatRulesSelector(state)
|
||||
}))
|
||||
@translate()
|
||||
class RulePage extends Component {
|
||||
render() {
|
||||
let { flatRules } = this.props,
|
||||
name = path(['match', 'params', 'name'], this.props),
|
||||
decodedRuleName = decodeRuleName(name)
|
||||
|
||||
if (decodedRuleName.includes(' . ')) {
|
||||
if (!findRuleByDottedName(flatRules, decodedRuleName))
|
||||
return <Redirect to="/404" />
|
||||
export default compose(
|
||||
connect(state => ({
|
||||
themeColours: state.themeColours,
|
||||
valuesToShow: !noUserInputSelector(state),
|
||||
flatRules: flatRulesSelector(state)
|
||||
})),
|
||||
withI18n()
|
||||
)(
|
||||
class RulePage extends Component {
|
||||
render() {
|
||||
let { flatRules } = this.props,
|
||||
name = path(['match', 'params', 'name'], this.props),
|
||||
decodedRuleName = decodeRuleName(name)
|
||||
|
||||
return this.renderRule(decodedRuleName)
|
||||
if (decodedRuleName.includes(' . ')) {
|
||||
if (!findRuleByDottedName(flatRules, decodedRuleName))
|
||||
return <Redirect to="/404" />
|
||||
|
||||
return this.renderRule(decodedRuleName)
|
||||
}
|
||||
|
||||
let rules = findRulesByName(flatRules, decodedRuleName)
|
||||
if (!rules.length) return <Redirect to="/404" />
|
||||
if (rules.length > 1)
|
||||
return <DisambiguateRuleQuery rules={rules} flatRules={flatRules} />
|
||||
let dottedName = head(rules).dottedName
|
||||
return this.renderRule(dottedName)
|
||||
}
|
||||
|
||||
let rules = findRulesByName(flatRules, decodedRuleName)
|
||||
if (!rules.length) return <Redirect to="/404" />
|
||||
if (rules.length > 1)
|
||||
return <DisambiguateRuleQuery rules={rules} flatRules={flatRules} />
|
||||
let dottedName = head(rules).dottedName
|
||||
return this.renderRule(dottedName)
|
||||
}
|
||||
renderRule(dottedName) {
|
||||
return (
|
||||
<div id="RulePage">
|
||||
<ScrollToTop />
|
||||
<div className="rule-page__header ui__ container">
|
||||
<BackToSimulation
|
||||
visible={this.props.valuesToShow}
|
||||
colour={this.props.themeColours.colour}
|
||||
/>
|
||||
<SearchButton
|
||||
className="rule-page__search"
|
||||
rulePageBasePath="../règle"
|
||||
/>
|
||||
renderRule(dottedName) {
|
||||
return (
|
||||
<div id="RulePage">
|
||||
<ScrollToTop />
|
||||
<div className="rule-page__header ui__ container">
|
||||
<BackToSimulation
|
||||
visible={this.props.valuesToShow}
|
||||
colour={this.props.themeColours.colour}
|
||||
/>
|
||||
<SearchButton
|
||||
className="rule-page__search"
|
||||
rulePageBasePath="../règle"
|
||||
/>
|
||||
</div>
|
||||
<Rule dottedName={dottedName} />
|
||||
</div>
|
||||
<Rule dottedName={dottedName} />
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@connect(
|
||||
null,
|
||||
dispatch => ({
|
||||
setExample: compose(
|
||||
dispatch,
|
||||
setExample
|
||||
)
|
||||
})
|
||||
)
|
||||
@withRouter
|
||||
@translate() // Triggers rerender when the language changes
|
||||
class BackToSimulation extends Component {
|
||||
render() {
|
||||
let { colour, setExample, visible } = this.props
|
||||
return (
|
||||
<Link
|
||||
id="toSimulation"
|
||||
to="../simulation"
|
||||
onClick={() => {
|
||||
setExample(null)
|
||||
}}
|
||||
style={{ color: colour, visibility: visible ? 'visible' : 'hidden' }}>
|
||||
<i className="fa fa-arrow-left" aria-hidden="true" />
|
||||
<Trans i18nKey="back">Reprendre la simulation</Trans>
|
||||
</Link>
|
||||
)
|
||||
|
||||
const BackToSimulation = compose(
|
||||
connect(
|
||||
null,
|
||||
dispatch => ({
|
||||
setExample: compose(
|
||||
dispatch,
|
||||
setExample
|
||||
)
|
||||
})
|
||||
),
|
||||
withRouter,
|
||||
withI18n()
|
||||
)(
|
||||
// Triggers rerender when the language changes
|
||||
class BackToSimulation extends Component {
|
||||
render() {
|
||||
let { colour, setExample, visible } = this.props
|
||||
return (
|
||||
<Link
|
||||
id="toSimulation"
|
||||
to="../simulation"
|
||||
onClick={() => {
|
||||
setExample(null)
|
||||
}}
|
||||
style={{ color: colour, visibility: visible ? 'visible' : 'hidden' }}>
|
||||
<i className="fa fa-arrow-left" aria-hidden="true" />
|
||||
<Trans i18nKey="back">Reprendre la simulation</Trans>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
let DisambiguateRuleQuery = ({ rules, flatRules }) => (
|
||||
<div className="centeredMessage">
|
||||
|
@ -112,5 +120,3 @@ let DisambiguateRuleQuery = ({ rules, flatRules }) => (
|
|||
</ul>
|
||||
</div>
|
||||
)
|
||||
|
||||
export default RulePage
|
||||
|
|
|
@ -4,14 +4,13 @@ import PropTypes from 'prop-types'
|
|||
import { pick } from 'ramda'
|
||||
import React from 'react'
|
||||
import Highlighter from 'react-highlight-words'
|
||||
import { translate } from 'react-i18next'
|
||||
import { withI18n } from 'react-i18next'
|
||||
import { Link, Redirect } from 'react-router-dom'
|
||||
import Select from 'react-select'
|
||||
import 'react-select/dist/react-select.css'
|
||||
import { capitalise0 } from '../utils'
|
||||
|
||||
@translate()
|
||||
export default class SearchBar extends React.Component {
|
||||
class SearchBar extends React.Component {
|
||||
static contextTypes = {
|
||||
i18n: PropTypes.object.isRequired
|
||||
}
|
||||
|
@ -99,24 +98,25 @@ export default class SearchBar extends React.Component {
|
|||
this.inputElement = el
|
||||
}}
|
||||
/>
|
||||
{this.props.showDefaultList &&
|
||||
!this.state.inputValue && (
|
||||
<ul>
|
||||
{rules.map(rule => (
|
||||
<li key={rule.dottedName}>
|
||||
<Link
|
||||
to={
|
||||
this.props.rulePagesBasePath +
|
||||
'/' +
|
||||
encodeRuleName(rule.name)
|
||||
}>
|
||||
{rule.title || capitalise0(rule.name)}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
{this.props.showDefaultList && !this.state.inputValue && (
|
||||
<ul>
|
||||
{rules.map(rule => (
|
||||
<li key={rule.dottedName}>
|
||||
<Link
|
||||
to={
|
||||
this.props.rulePagesBasePath +
|
||||
'/' +
|
||||
encodeRuleName(rule.name)
|
||||
}>
|
||||
{rule.title || capitalise0(rule.name)}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default withI18n()(SearchBar)
|
||||
|
|
|
@ -1,64 +1,68 @@
|
|||
import { compose } from 'ramda'
|
||||
import React, { Component } from 'react'
|
||||
import { Trans, translate } from 'react-i18next'
|
||||
import { Trans, withI18n } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import { flatRulesSelector } from 'Selectors/analyseSelectors'
|
||||
import { LinkButton } from 'Ui/Button'
|
||||
import Overlay from './Overlay'
|
||||
import SearchBar from './SearchBar'
|
||||
|
||||
@connect(state => ({
|
||||
flatRules: flatRulesSelector(state)
|
||||
}))
|
||||
@translate()
|
||||
export default class SearchButton extends Component {
|
||||
componentDidMount() {
|
||||
// removeEventListener will need the exact same function instance
|
||||
this.boundHandleKeyDown = this.handleKeyDown.bind(this)
|
||||
export default compose(
|
||||
connect(state => ({
|
||||
flatRules: flatRulesSelector(state)
|
||||
})),
|
||||
withI18n()
|
||||
)(
|
||||
class SearchButton extends Component {
|
||||
componentDidMount() {
|
||||
// removeEventListener will need the exact same function instance
|
||||
this.boundHandleKeyDown = this.handleKeyDown.bind(this)
|
||||
|
||||
window.addEventListener('keydown', this.boundHandleKeyDown)
|
||||
window.addEventListener('keydown', this.boundHandleKeyDown)
|
||||
}
|
||||
handleKeyDown(e) {
|
||||
if (!(e.ctrlKey && e.key === 'k')) return
|
||||
this.setState({ visible: true })
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
return false
|
||||
}
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('keydown', this.boundHandleKeyDown)
|
||||
}
|
||||
state = {
|
||||
visible: false
|
||||
}
|
||||
close = () => this.setState({ visible: false })
|
||||
render() {
|
||||
let { flatRules } = this.props
|
||||
return this.state.visible ? (
|
||||
<Overlay onClose={this.close}>
|
||||
<h2>
|
||||
<Trans>Chercher une règle</Trans>
|
||||
</h2>
|
||||
<SearchBar
|
||||
showDefaultList={false}
|
||||
finally={this.close}
|
||||
rules={flatRules}
|
||||
rulePagesBasePath={this.props.rulePagesBasePath}
|
||||
/>
|
||||
</Overlay>
|
||||
) : (
|
||||
<LinkButton
|
||||
onClick={() => this.setState({ visible: true })}
|
||||
className={this.props.className}
|
||||
style={this.props.style}>
|
||||
<i
|
||||
className="fa fa-search"
|
||||
aria-hidden="true"
|
||||
style={{ marginRight: '0.4em' }}
|
||||
/>
|
||||
<span>
|
||||
<Trans>Rechercher</Trans>
|
||||
</span>
|
||||
</LinkButton>
|
||||
)
|
||||
}
|
||||
}
|
||||
handleKeyDown(e) {
|
||||
if (!(e.ctrlKey && e.key === 'k')) return
|
||||
this.setState({ visible: true })
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
return false
|
||||
}
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('keydown', this.boundHandleKeyDown)
|
||||
}
|
||||
state = {
|
||||
visible: false
|
||||
}
|
||||
close = () => this.setState({ visible: false })
|
||||
render() {
|
||||
let { flatRules } = this.props
|
||||
return this.state.visible ? (
|
||||
<Overlay onClose={this.close}>
|
||||
<h2>
|
||||
<Trans>Chercher une règle</Trans>
|
||||
</h2>
|
||||
<SearchBar
|
||||
showDefaultList={false}
|
||||
finally={this.close}
|
||||
rules={flatRules}
|
||||
rulePagesBasePath={this.props.rulePagesBasePath}
|
||||
/>
|
||||
</Overlay>
|
||||
) : (
|
||||
<LinkButton
|
||||
onClick={() => this.setState({ visible: true })}
|
||||
className={this.props.className}
|
||||
style={this.props.style}>
|
||||
<i
|
||||
className="fa fa-search"
|
||||
aria-hidden="true"
|
||||
style={{ marginRight: '0.4em' }}
|
||||
/>
|
||||
<span>
|
||||
<Trans>Rechercher</Trans>
|
||||
</span>
|
||||
</LinkButton>
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -3,8 +3,9 @@ import AnswerList from 'Components/AnswerList'
|
|||
import { ScrollToTop } from 'Components/utils/Scroll'
|
||||
import withColours from 'Components/utils/withColours'
|
||||
import withLanguage from 'Components/utils/withLanguage'
|
||||
import { compose } from 'ramda'
|
||||
import React, { Component } from 'react'
|
||||
import { Trans, translate } from 'react-i18next'
|
||||
import { Trans, withI18n } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import { Redirect, withRouter } from 'react-router'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
@ -26,151 +27,153 @@ import ResultView from './ResultView'
|
|||
import './Simu.css'
|
||||
import TargetSelection from './TargetSelection'
|
||||
|
||||
@withRouter
|
||||
@withColours
|
||||
@translate() // Triggers rerender when the language changes
|
||||
@connect(
|
||||
state => ({
|
||||
blockingInputControls: blockingInputControlsSelector(state),
|
||||
conversationStarted: state.conversationStarted,
|
||||
validInputEntered: validInputEnteredSelector(state),
|
||||
arePreviousAnswers: state.conversationSteps.foldedSteps.length !== 0,
|
||||
nextSteps: state.conversationStarted && nextStepsSelector(state),
|
||||
userInput: noUserInputSelector(state)
|
||||
}),
|
||||
{
|
||||
startConversation
|
||||
}
|
||||
)
|
||||
@withLanguage
|
||||
class Simulation extends Component {
|
||||
state = {
|
||||
displayPreviousAnswers: false
|
||||
}
|
||||
render() {
|
||||
let {
|
||||
colours,
|
||||
conversationStarted,
|
||||
arePreviousAnswers,
|
||||
nextSteps,
|
||||
startConversation,
|
||||
blockingInputControls,
|
||||
match,
|
||||
validInputEntered,
|
||||
location
|
||||
} = this.props
|
||||
const displayConversation = conversationStarted && !blockingInputControls
|
||||
const simulationCompleted =
|
||||
!blockingInputControls && conversationStarted && !nextSteps.length
|
||||
const displayPreviousAnswers =
|
||||
arePreviousAnswers && this.state.displayPreviousAnswers
|
||||
const simulationHomePath = normalizeBasePath(match.path).replace(
|
||||
/\/simulation\/$/,
|
||||
''
|
||||
)
|
||||
return (
|
||||
<>
|
||||
<div id="simu">
|
||||
<QuickLink />
|
||||
{location.pathname.endsWith('/simulation') && (
|
||||
<>
|
||||
{!conversationStarted && <Redirect to={simulationHomePath} />}
|
||||
<Link to={simulationHomePath} style={{ position: 'absolute' }}>
|
||||
<i
|
||||
className="fa fa-arrow-left"
|
||||
aria-hidden="true"
|
||||
style={{ marginRight: '0.5rem' }}
|
||||
/>
|
||||
<Trans>Retour</Trans>
|
||||
</Link>
|
||||
export default compose(
|
||||
withRouter,
|
||||
withColours,
|
||||
withI18n(), // Triggers rerender when the language changes
|
||||
connect(
|
||||
state => ({
|
||||
blockingInputControls: blockingInputControlsSelector(state),
|
||||
conversationStarted: state.conversationStarted,
|
||||
validInputEntered: validInputEnteredSelector(state),
|
||||
arePreviousAnswers: state.conversationSteps.foldedSteps.length !== 0,
|
||||
nextSteps: state.conversationStarted && nextStepsSelector(state),
|
||||
userInput: noUserInputSelector(state)
|
||||
}),
|
||||
{
|
||||
startConversation
|
||||
}
|
||||
),
|
||||
withLanguage
|
||||
)(
|
||||
class Simulation extends Component {
|
||||
state = {
|
||||
displayPreviousAnswers: false
|
||||
}
|
||||
render() {
|
||||
let {
|
||||
colours,
|
||||
conversationStarted,
|
||||
arePreviousAnswers,
|
||||
nextSteps,
|
||||
startConversation,
|
||||
blockingInputControls,
|
||||
match,
|
||||
validInputEntered,
|
||||
location
|
||||
} = this.props
|
||||
const displayConversation = conversationStarted && !blockingInputControls
|
||||
const simulationCompleted =
|
||||
!blockingInputControls && conversationStarted && !nextSteps.length
|
||||
const displayPreviousAnswers =
|
||||
arePreviousAnswers && this.state.displayPreviousAnswers
|
||||
const simulationHomePath = normalizeBasePath(match.path).replace(
|
||||
/\/simulation\/$/,
|
||||
''
|
||||
)
|
||||
return (
|
||||
<>
|
||||
<div id="simu">
|
||||
<QuickLink />
|
||||
{location.pathname.endsWith('/simulation') && (
|
||||
<>
|
||||
{!conversationStarted && <Redirect to={simulationHomePath} />}
|
||||
<Link to={simulationHomePath} style={{ position: 'absolute' }}>
|
||||
<i
|
||||
className="fa fa-arrow-left"
|
||||
aria-hidden="true"
|
||||
style={{ marginRight: '0.5rem' }}
|
||||
/>
|
||||
<Trans>Retour</Trans>
|
||||
</Link>
|
||||
|
||||
<div
|
||||
className="change-answer-link"
|
||||
style={{
|
||||
visibility: arePreviousAnswers ? 'visible' : 'hidden'
|
||||
}}>
|
||||
<button
|
||||
className="ui__ link-button"
|
||||
onClick={() =>
|
||||
this.setState({ displayPreviousAnswers: true })
|
||||
}>
|
||||
<Trans>Modifier mes réponses</Trans>
|
||||
</button>
|
||||
</div>
|
||||
{displayPreviousAnswers && (
|
||||
<AnswerList
|
||||
onClose={() =>
|
||||
this.setState({ displayPreviousAnswers: false })
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{simulationCompleted && (
|
||||
<>
|
||||
<h1>
|
||||
<Trans i18nKey="simulation-end.title">
|
||||
Plus de questions !
|
||||
</Trans>
|
||||
</h1>
|
||||
<p>
|
||||
<Trans i18nKey="simulation-end.text">
|
||||
Vous avez atteint l'estimation la plus précise. Vous
|
||||
pouvez maintenant concrétiser votre projet d'embauche.
|
||||
</Trans>
|
||||
</p>
|
||||
{this.props.displayHiringProcedures && (
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<Link
|
||||
className="ui__ button"
|
||||
to={sitePaths().démarcheEmbauche}>
|
||||
<Trans i18nKey="simulation-end.cta">
|
||||
Connaître les démarches
|
||||
</Trans>
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
<br />
|
||||
</>
|
||||
)}
|
||||
{displayConversation && (
|
||||
<>
|
||||
<ScrollToTop />
|
||||
<Conversation textColourOnWhite={colours.textColourOnWhite} />
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<TargetSelection colours={colours} />
|
||||
{location.pathname.endsWith('/simulation') && (
|
||||
<>
|
||||
{conversationStarted && (
|
||||
<Animate.fromBottom>
|
||||
<ResultView />
|
||||
<div style={{ textAlign: 'center' }} />
|
||||
</Animate.fromBottom>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{validInputEntered && (
|
||||
<PageFeedback
|
||||
customMessage={
|
||||
<Trans i18nKey="feedback.simulator">
|
||||
Ce simulateur vous a plu ?
|
||||
</Trans>
|
||||
}
|
||||
customEventName="rate simulator"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{!location.pathname.endsWith('/simulation') &&
|
||||
validInputEntered && (
|
||||
<div
|
||||
className="change-answer-link"
|
||||
style={{
|
||||
visibility: arePreviousAnswers ? 'visible' : 'hidden'
|
||||
}}>
|
||||
<button
|
||||
className="ui__ link-button"
|
||||
onClick={() =>
|
||||
this.setState({ displayPreviousAnswers: true })
|
||||
}>
|
||||
<Trans>Modifier mes réponses</Trans>
|
||||
</button>
|
||||
</div>
|
||||
{displayPreviousAnswers && (
|
||||
<AnswerList
|
||||
onClose={() =>
|
||||
this.setState({ displayPreviousAnswers: false })
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{simulationCompleted && (
|
||||
<>
|
||||
<h1>
|
||||
<Trans i18nKey="simulation-end.title">
|
||||
Plus de questions !
|
||||
</Trans>
|
||||
</h1>
|
||||
<p>
|
||||
<Trans i18nKey="simulation-end.text">
|
||||
Vous avez atteint l'estimation la plus précise. Vous
|
||||
pouvez maintenant concrétiser votre projet d'embauche.
|
||||
</Trans>
|
||||
</p>
|
||||
{this.props.displayHiringProcedures && (
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<Link
|
||||
className="ui__ button"
|
||||
to={sitePaths().démarcheEmbauche}>
|
||||
<Trans i18nKey="simulation-end.cta">
|
||||
Connaître les démarches
|
||||
</Trans>
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
<br />
|
||||
</>
|
||||
)}
|
||||
{displayConversation && (
|
||||
<>
|
||||
<ScrollToTop />
|
||||
<Conversation
|
||||
textColourOnWhite={colours.textColourOnWhite}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<TargetSelection colours={colours} />
|
||||
{location.pathname.endsWith('/simulation') && (
|
||||
<>
|
||||
{conversationStarted && (
|
||||
<Animate.fromBottom>
|
||||
<ResultView />
|
||||
<div style={{ textAlign: 'center' }} />
|
||||
</Animate.fromBottom>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{validInputEntered && (
|
||||
<PageFeedback
|
||||
customMessage={
|
||||
<Trans i18nKey="feedback.simulator">
|
||||
Ce simulateur vous a plu ?
|
||||
</Trans>
|
||||
}
|
||||
customEventName="rate simulator"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{!location.pathname.endsWith('/simulation') && validInputEntered && (
|
||||
<Animate.fromBottom>
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
{arePreviousAnswers &&
|
||||
conversationStarted && (
|
||||
<button className="ui__ button" onClick={startConversation}>
|
||||
<Trans>Continuer la simulation</Trans>
|
||||
</button>
|
||||
)}
|
||||
{arePreviousAnswers && conversationStarted && (
|
||||
<button className="ui__ button" onClick={startConversation}>
|
||||
<Trans>Continuer la simulation</Trans>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<h2>
|
||||
<Trans>A quoi servent mes cotisations ?</Trans>
|
||||
|
@ -204,8 +207,8 @@ class Simulation extends Component {
|
|||
<PaySlip />
|
||||
</Animate.fromBottom>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
export default Simulation
|
||||
)
|
||||
|
|
|
@ -3,7 +3,7 @@ import InputSuggestions from 'Components/conversation/InputSuggestions'
|
|||
import withColours from 'Components/utils/withColours'
|
||||
import withLanguage from 'Components/utils/withLanguage'
|
||||
import { encodeRuleName, findRuleByDottedName } from 'Engine/rules'
|
||||
import { propEq } from 'ramda'
|
||||
import { compose, propEq } from 'ramda'
|
||||
import React, { Component } from 'react'
|
||||
import emoji from 'react-easy-emoji'
|
||||
import { Trans, translate } from 'react-i18next'
|
||||
|
@ -37,107 +37,109 @@ export let popularTargetNames = [
|
|||
'contrat salarié . rémunération . net imposable'
|
||||
]
|
||||
|
||||
@translate()
|
||||
@reduxForm({
|
||||
form: 'conversation',
|
||||
destroyOnUnmount: false
|
||||
})
|
||||
@withRouter
|
||||
@connect(
|
||||
state => ({
|
||||
getTargetValue: dottedName =>
|
||||
formValueSelector('conversation')(state, dottedName),
|
||||
analysis: analysisWithDefaultsSelector(state),
|
||||
blockingInputControls: blockingInputControlsSelector(state),
|
||||
flatRules: flatRulesSelector(state),
|
||||
noUserInput: noUserInputSelector(state),
|
||||
conversationStarted: state.conversationStarted,
|
||||
activeInput: state.activeTargetInput
|
||||
const TargetSelection = compose(
|
||||
translate(),
|
||||
reduxForm({
|
||||
form: 'conversation',
|
||||
destroyOnUnmount: false
|
||||
}),
|
||||
dispatch => ({
|
||||
setFormValue: (field, name) =>
|
||||
dispatch(change('conversation', field, name)),
|
||||
setActiveInput: name => dispatch({ type: 'SET_ACTIVE_TARGET_INPUT', name })
|
||||
})
|
||||
)
|
||||
class TargetSelection extends Component {
|
||||
render() {
|
||||
let {
|
||||
colours,
|
||||
noUserInput,
|
||||
blockingInputControls,
|
||||
analysis: { controls }
|
||||
} = this.props
|
||||
return (
|
||||
<div id="targetSelection">
|
||||
{noUserInput && (
|
||||
<p className="blockingControl">
|
||||
<Trans i18nKey="enterSalary">
|
||||
Entrez un salaire <b>mensuel</b>
|
||||
</Trans>
|
||||
</p>
|
||||
)}
|
||||
<Controls {...{ blockingInputControls, controls }} />
|
||||
<section
|
||||
id="targetsContainer"
|
||||
style={{
|
||||
color: colours.textColour,
|
||||
background: `linear-gradient(
|
||||
withRouter,
|
||||
connect(
|
||||
state => ({
|
||||
getTargetValue: dottedName =>
|
||||
formValueSelector('conversation')(state, dottedName),
|
||||
analysis: analysisWithDefaultsSelector(state),
|
||||
blockingInputControls: blockingInputControlsSelector(state),
|
||||
flatRules: flatRulesSelector(state),
|
||||
noUserInput: noUserInputSelector(state),
|
||||
conversationStarted: state.conversationStarted,
|
||||
activeInput: state.activeTargetInput
|
||||
}),
|
||||
dispatch => ({
|
||||
setFormValue: (field, name) =>
|
||||
dispatch(change('conversation', field, name)),
|
||||
setActiveInput: name =>
|
||||
dispatch({ type: 'SET_ACTIVE_TARGET_INPUT', name })
|
||||
})
|
||||
)
|
||||
)(
|
||||
class TargetSelection extends Component {
|
||||
render() {
|
||||
let {
|
||||
colours,
|
||||
noUserInput,
|
||||
blockingInputControls,
|
||||
analysis: { controls }
|
||||
} = this.props
|
||||
return (
|
||||
<div id="targetSelection">
|
||||
{noUserInput && (
|
||||
<p className="blockingControl">
|
||||
<Trans i18nKey="enterSalary">
|
||||
Entrez un salaire <b>mensuel</b>
|
||||
</Trans>
|
||||
</p>
|
||||
)}
|
||||
<Controls {...{ blockingInputControls, controls }} />
|
||||
<section
|
||||
id="targetsContainer"
|
||||
style={{
|
||||
color: colours.textColour,
|
||||
background: `linear-gradient(
|
||||
60deg,
|
||||
${colours.darkColour} 0%,
|
||||
${colours.colour} 100%
|
||||
)`
|
||||
}}>
|
||||
{this.renderOutputList()}
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}}>
|
||||
{this.renderOutputList()}
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
renderOutputList() {
|
||||
let displayedTargets = mainTargetNames.map(target =>
|
||||
findRuleByDottedName(this.props.flatRules, target)
|
||||
),
|
||||
{
|
||||
conversationStarted,
|
||||
activeInput,
|
||||
setActiveInput,
|
||||
analysis,
|
||||
noUserInput,
|
||||
blockingInputControls,
|
||||
match
|
||||
} = this.props,
|
||||
targets = analysis ? analysis.targets : []
|
||||
renderOutputList() {
|
||||
let displayedTargets = mainTargetNames.map(target =>
|
||||
findRuleByDottedName(this.props.flatRules, target)
|
||||
),
|
||||
{
|
||||
conversationStarted,
|
||||
activeInput,
|
||||
setActiveInput,
|
||||
analysis,
|
||||
noUserInput,
|
||||
blockingInputControls,
|
||||
match
|
||||
} = this.props,
|
||||
targets = analysis ? analysis.targets : []
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ul id="targets">
|
||||
{displayedTargets.map(target => (
|
||||
<li key={target.name}>
|
||||
<div className="main">
|
||||
<Header
|
||||
{...{
|
||||
match,
|
||||
target,
|
||||
conversationStarted,
|
||||
isActiveInput: activeInput === target.dottedName,
|
||||
blockingInputControls
|
||||
}}
|
||||
/>
|
||||
<TargetInputOrValue
|
||||
{...{
|
||||
target,
|
||||
targets,
|
||||
activeInput,
|
||||
setActiveInput,
|
||||
setFormValue: this.props.setFormValue,
|
||||
noUserInput,
|
||||
blockingInputControls
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{activeInput === target.dottedName &&
|
||||
!conversationStarted && (
|
||||
return (
|
||||
<div>
|
||||
<ul id="targets">
|
||||
{displayedTargets.map(target => (
|
||||
<li key={target.name}>
|
||||
<div className="main">
|
||||
<Header
|
||||
{...{
|
||||
match,
|
||||
target,
|
||||
conversationStarted,
|
||||
isActiveInput: activeInput === target.dottedName,
|
||||
blockingInputControls
|
||||
}}
|
||||
/>
|
||||
<TargetInputOrValue
|
||||
{...{
|
||||
target,
|
||||
targets,
|
||||
activeInput,
|
||||
setActiveInput,
|
||||
setFormValue: this.props.setFormValue,
|
||||
noUserInput,
|
||||
blockingInputControls
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{activeInput === target.dottedName && !conversationStarted && (
|
||||
<InputSuggestions
|
||||
suggestions={target.suggestions}
|
||||
onFirstClick={value =>
|
||||
|
@ -146,13 +148,14 @@ class TargetSelection extends Component {
|
|||
colouredBackground={true}
|
||||
/>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
let Header = ({
|
||||
target,
|
||||
|
@ -167,20 +170,18 @@ let Header = ({
|
|||
encodeRuleName(target.dottedName)
|
||||
return (
|
||||
<span className="header">
|
||||
{conversationStarted &&
|
||||
!blockingInputControls && (
|
||||
<ProgressCircle target={target} isActiveInput={isActiveInput} />
|
||||
)}
|
||||
{conversationStarted && !blockingInputControls && (
|
||||
<ProgressCircle target={target} isActiveInput={isActiveInput} />
|
||||
)}
|
||||
|
||||
<span className="texts">
|
||||
{!conversationStarted &&
|
||||
target.dottedName.includes('net après impôt') && (
|
||||
<div>
|
||||
<span id="labelNew">
|
||||
<Trans>Janvier 2019</Trans>
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{!conversationStarted && target.dottedName.includes('net après impôt') && (
|
||||
<div>
|
||||
<span id="labelNew">
|
||||
<Trans>Janvier 2019</Trans>
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<span className="optionTitle">
|
||||
<Link to={ruleLink}>{target.title || target.name}</Link>
|
||||
</span>
|
||||
|
@ -238,75 +239,83 @@ let TargetInputOrValue = withLanguage(
|
|||
</span>
|
||||
)
|
||||
)
|
||||
@connect(
|
||||
|
||||
const TargetValue = connect(
|
||||
null,
|
||||
dispatch => ({
|
||||
setFormValue: (field, name) => dispatch(change('conversation', field, name))
|
||||
})
|
||||
)
|
||||
class TargetValue extends Component {
|
||||
render() {
|
||||
let { targets, target, noUserInput, blockingInputControls } = this.props
|
||||
)(
|
||||
class TargetValue extends Component {
|
||||
render() {
|
||||
let { targets, target, noUserInput, blockingInputControls } = this.props
|
||||
|
||||
let targetWithValue =
|
||||
targets && targets.find(propEq('dottedName', target.dottedName)),
|
||||
value = targetWithValue && targetWithValue.nodeValue
|
||||
let targetWithValue =
|
||||
targets && targets.find(propEq('dottedName', target.dottedName)),
|
||||
value = targetWithValue && targetWithValue.nodeValue
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames({
|
||||
editable: target.question,
|
||||
attractClick:
|
||||
target.question && (noUserInput || blockingInputControls)
|
||||
})}
|
||||
tabIndex="0"
|
||||
onClick={this.showField(value)}
|
||||
onFocus={this.showField(value)}>
|
||||
<AnimatedTargetValue value={value} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
showField(value) {
|
||||
let { target, setFormValue, activeInput, setActiveInput } = this.props
|
||||
return () => {
|
||||
if (!target.question) return
|
||||
if (value != null) setFormValue(target.dottedName, Math.floor(value) + '')
|
||||
return (
|
||||
<div
|
||||
className={classNames({
|
||||
editable: target.question,
|
||||
attractClick:
|
||||
target.question && (noUserInput || blockingInputControls)
|
||||
})}
|
||||
tabIndex="0"
|
||||
onClick={this.showField(value)}
|
||||
onFocus={this.showField(value)}>
|
||||
<AnimatedTargetValue value={value} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
showField(value) {
|
||||
let { target, setFormValue, activeInput, setActiveInput } = this.props
|
||||
return () => {
|
||||
if (!target.question) return
|
||||
if (value != null)
|
||||
setFormValue(target.dottedName, Math.floor(value) + '')
|
||||
|
||||
if (activeInput) setFormValue(activeInput, '')
|
||||
setActiveInput(target.dottedName)
|
||||
if (activeInput) setFormValue(activeInput, '')
|
||||
setActiveInput(target.dottedName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
@withColours
|
||||
@withRouter
|
||||
@connect(state => ({ analysis: analysisWithDefaultsSelector(state) }))
|
||||
class AidesGlimpse extends Component {
|
||||
render() {
|
||||
let targets = this.props.analysis.targets,
|
||||
aides =
|
||||
targets &&
|
||||
targets.find(t => t.dottedName === 'contrat salarié . aides employeur')
|
||||
if (!aides || !aides.nodeValue) return null
|
||||
return (
|
||||
<div id="aidesGlimpse">
|
||||
{' '}
|
||||
- <AnimatedTargetValue value={aides.nodeValue} />{' '}
|
||||
<Link
|
||||
to={
|
||||
normalizeBasePath(this.props.match.path).replace(
|
||||
/simulation\/$/,
|
||||
''
|
||||
) +
|
||||
'règle/' +
|
||||
encodeRuleName('contrat salarié . aides employeur')
|
||||
}
|
||||
style={{ color: this.props.colours.textColour }}>
|
||||
<Trans>d'aides</Trans> {emoji(aides.icon)}
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
const AidesGlimpse = compose(
|
||||
withColours,
|
||||
withRouter,
|
||||
connect(state => ({ analysis: analysisWithDefaultsSelector(state) }))
|
||||
)(
|
||||
class AidesGlimpse extends Component {
|
||||
render() {
|
||||
let targets = this.props.analysis.targets,
|
||||
aides =
|
||||
targets &&
|
||||
targets.find(
|
||||
t => t.dottedName === 'contrat salarié . aides employeur'
|
||||
)
|
||||
if (!aides || !aides.nodeValue) return null
|
||||
return (
|
||||
<div id="aidesGlimpse">
|
||||
{' '}
|
||||
- <AnimatedTargetValue value={aides.nodeValue} />{' '}
|
||||
<Link
|
||||
to={
|
||||
normalizeBasePath(this.props.match.path).replace(
|
||||
/simulation\/$/,
|
||||
''
|
||||
) +
|
||||
'règle/' +
|
||||
encodeRuleName('contrat salarié . aides employeur')
|
||||
}
|
||||
style={{ color: this.props.colours.textColour }}>
|
||||
<Trans>d'aides</Trans> {emoji(aides.icon)}
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
export default TargetSelection
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import Scroll from 'Components/utils/Scroll'
|
||||
import { getInputComponent } from 'Engine/generateQuestions'
|
||||
import { compose } from 'ramda'
|
||||
import React, { Component } from 'react'
|
||||
import { translate } from 'react-i18next'
|
||||
import { withI18n } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import { reduxForm } from 'redux-form'
|
||||
import {
|
||||
|
@ -12,32 +13,35 @@ import * as Animate from 'Ui/animate'
|
|||
import Aide from '../Aide'
|
||||
import './conversation.css'
|
||||
|
||||
@reduxForm({
|
||||
form: 'conversation',
|
||||
destroyOnUnmount: false
|
||||
})
|
||||
@translate()
|
||||
@connect(state => ({
|
||||
conversationStarted: state.conversationStarted,
|
||||
themeColours: state.themeColours,
|
||||
flatRules: flatRulesSelector(state),
|
||||
currentQuestion: currentQuestionSelector(state)
|
||||
}))
|
||||
export default class Conversation extends Component {
|
||||
render() {
|
||||
let { currentQuestion, flatRules } = this.props
|
||||
return (
|
||||
<div className="conversationContainer">
|
||||
<Aide />
|
||||
<div id="currentQuestion">
|
||||
{currentQuestion && (
|
||||
<Animate.fadeIn>
|
||||
<Scroll.toElement onlyIfNotVisible />
|
||||
{getInputComponent(flatRules)(currentQuestion)}
|
||||
</Animate.fadeIn>
|
||||
)}
|
||||
export default compose(
|
||||
reduxForm({
|
||||
form: 'conversation',
|
||||
destroyOnUnmount: false
|
||||
}),
|
||||
withI18n(),
|
||||
connect(state => ({
|
||||
conversationStarted: state.conversationStarted,
|
||||
themeColours: state.themeColours,
|
||||
flatRules: flatRulesSelector(state),
|
||||
currentQuestion: currentQuestionSelector(state)
|
||||
}))
|
||||
)(
|
||||
class Conversation extends Component {
|
||||
render() {
|
||||
let { currentQuestion, flatRules } = this.props
|
||||
return (
|
||||
<div className="conversationContainer">
|
||||
<Aide />
|
||||
<div id="currentQuestion">
|
||||
{currentQuestion && (
|
||||
<Animate.fadeIn>
|
||||
<Scroll.toElement onlyIfNotVisible />
|
||||
{getInputComponent(flatRules)(currentQuestion)}
|
||||
</Animate.fadeIn>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -1,68 +1,73 @@
|
|||
import { EXPLAIN_VARIABLE } from 'Actions/actions'
|
||||
import classNames from 'classnames'
|
||||
import { findRuleByDottedName } from 'Engine/rules'
|
||||
import { compose } from 'ramda'
|
||||
import React from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import { flatRulesSelector } from 'Selectors/analyseSelectors'
|
||||
import withTracker from '../utils/withTracker'
|
||||
import './Explicable.css'
|
||||
|
||||
@connect(
|
||||
state => ({
|
||||
explained: state.explainedVariable,
|
||||
textColourOnWhite: state.themeColours.textColourOnWhite,
|
||||
flatRules: flatRulesSelector(state)
|
||||
}),
|
||||
dispatch => ({
|
||||
explain: variableName => dispatch({ type: EXPLAIN_VARIABLE, variableName })
|
||||
})
|
||||
)
|
||||
@withTracker
|
||||
export default class Explicable extends React.Component {
|
||||
render() {
|
||||
let {
|
||||
flatRules,
|
||||
dottedName,
|
||||
explain,
|
||||
explained,
|
||||
tracker,
|
||||
textColourOnWhite
|
||||
} = this.props
|
||||
export default compose(
|
||||
connect(
|
||||
state => ({
|
||||
explained: state.explainedVariable,
|
||||
textColourOnWhite: state.themeColours.textColourOnWhite,
|
||||
flatRules: flatRulesSelector(state)
|
||||
}),
|
||||
dispatch => ({
|
||||
explain: variableName =>
|
||||
dispatch({ type: EXPLAIN_VARIABLE, variableName })
|
||||
})
|
||||
),
|
||||
withTracker
|
||||
)(
|
||||
class Explicable extends React.Component {
|
||||
render() {
|
||||
let {
|
||||
flatRules,
|
||||
dottedName,
|
||||
explain,
|
||||
explained,
|
||||
tracker,
|
||||
textColourOnWhite
|
||||
} = this.props
|
||||
|
||||
// Rien à expliquer ici, ce n'est pas une règle
|
||||
if (dottedName == null) return null
|
||||
// Rien à expliquer ici, ce n'est pas une règle
|
||||
if (dottedName == null) return null
|
||||
|
||||
let rule = findRuleByDottedName(flatRules, dottedName)
|
||||
let rule = findRuleByDottedName(flatRules, dottedName)
|
||||
|
||||
if (rule.description == null) return null
|
||||
if (rule.description == null) return null
|
||||
|
||||
//TODO montrer les variables de type 'une possibilité'
|
||||
//TODO montrer les variables de type 'une possibilité'
|
||||
|
||||
return (
|
||||
<span
|
||||
className={classNames('explicable', {
|
||||
explained: dottedName === explained
|
||||
})}>
|
||||
return (
|
||||
<span
|
||||
className="icon"
|
||||
onClick={e => {
|
||||
tracker.push(['trackEvent', 'help', dottedName])
|
||||
explain(dottedName)
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
}}
|
||||
style={
|
||||
dottedName === explained
|
||||
? {
|
||||
opacity: 1,
|
||||
background: textColourOnWhite,
|
||||
color: 'white'
|
||||
}
|
||||
: { color: textColourOnWhite }
|
||||
}>
|
||||
<i className="fa fa-book" aria-hidden="true" />
|
||||
className={classNames('explicable', {
|
||||
explained: dottedName === explained
|
||||
})}>
|
||||
<span
|
||||
className="icon"
|
||||
onClick={e => {
|
||||
tracker.push(['trackEvent', 'help', dottedName])
|
||||
explain(dottedName)
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
}}
|
||||
style={
|
||||
dottedName === explained
|
||||
? {
|
||||
opacity: 1,
|
||||
background: textColourOnWhite,
|
||||
color: 'white'
|
||||
}
|
||||
: { color: textColourOnWhite }
|
||||
}>
|
||||
<i className="fa fa-book" aria-hidden="true" />
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { findRuleByDottedName } from 'Engine/rules'
|
||||
import { compose } from 'ramda'
|
||||
import React from 'react'
|
||||
import { Trans, translate } from 'react-i18next'
|
||||
import { Trans, withI18n } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import {
|
||||
flatRulesSelector,
|
||||
|
@ -9,40 +10,44 @@ import {
|
|||
import { LinkButton } from 'Ui/Button'
|
||||
import { capitalise0 } from '../../utils'
|
||||
|
||||
@translate()
|
||||
@connect(
|
||||
state => ({
|
||||
flatRules: flatRulesSelector(state),
|
||||
situation: validatedSituationSelector(state)
|
||||
}),
|
||||
dispatch => ({
|
||||
stepAction: (name, step, source) =>
|
||||
dispatch({ type: 'STEP_ACTION', name, step, source })
|
||||
})
|
||||
)
|
||||
export default class FoldedStep extends React.Component {
|
||||
render() {
|
||||
let { stepAction, dottedName, flatRules, t, situation } = this.props
|
||||
let { title } = findRuleByDottedName(flatRules, dottedName),
|
||||
answer = situation[dottedName],
|
||||
eventualEnumAnswerRule = findRuleByDottedName(
|
||||
flatRules,
|
||||
dottedName + ' . ' + answer
|
||||
),
|
||||
translatedAnswer =
|
||||
(eventualEnumAnswerRule && eventualEnumAnswerRule.title) || t(answer)
|
||||
export default compose(
|
||||
withI18n(),
|
||||
connect(
|
||||
state => ({
|
||||
flatRules: flatRulesSelector(state),
|
||||
situation: validatedSituationSelector(state)
|
||||
}),
|
||||
dispatch => ({
|
||||
stepAction: (name, step, source) =>
|
||||
dispatch({ type: 'STEP_ACTION', name, step, source })
|
||||
})
|
||||
)
|
||||
)(
|
||||
class FoldedStep extends React.Component {
|
||||
render() {
|
||||
let { stepAction, dottedName, flatRules, t, situation } = this.props
|
||||
let { title } = findRuleByDottedName(flatRules, dottedName),
|
||||
answer = situation[dottedName],
|
||||
eventualEnumAnswerRule = findRuleByDottedName(
|
||||
flatRules,
|
||||
dottedName + ' . ' + answer
|
||||
),
|
||||
translatedAnswer =
|
||||
(eventualEnumAnswerRule && eventualEnumAnswerRule.title) || t(answer)
|
||||
|
||||
return (
|
||||
<div className="foldedQuestion">
|
||||
<span className="borderWrapper">
|
||||
<span className="title">{capitalise0(title)}</span>
|
||||
<span className="answer">{translatedAnswer}</span>
|
||||
</span>
|
||||
<LinkButton onClick={() => stepAction('unfold', dottedName, 'unfold')}>
|
||||
<i className="fa fa-pencil" aria-hidden="true" />
|
||||
<Trans>Modifier</Trans>
|
||||
</LinkButton>
|
||||
</div>
|
||||
)
|
||||
return (
|
||||
<div className="foldedQuestion">
|
||||
<span className="borderWrapper">
|
||||
<span className="title">{capitalise0(title)}</span>
|
||||
<span className="answer">{translatedAnswer}</span>
|
||||
</span>
|
||||
<LinkButton
|
||||
onClick={() => stepAction('unfold', dottedName, 'unfold')}>
|
||||
<i className="fa fa-pencil" aria-hidden="true" />
|
||||
<Trans>Modifier</Trans>
|
||||
</LinkButton>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -9,7 +9,7 @@ import { LinkButton } from 'Ui/Button'
|
|||
import './conversation.css'
|
||||
import FoldedStep from './FoldedStep'
|
||||
|
||||
@connect(
|
||||
export default connect(
|
||||
state => ({
|
||||
foldedSteps: state.conversationSteps.foldedSteps,
|
||||
targetNames: state.targetNames,
|
||||
|
@ -19,28 +19,29 @@ import FoldedStep from './FoldedStep'
|
|||
resetSimulation,
|
||||
resetForm: () => reset('conversation')
|
||||
}
|
||||
)
|
||||
export default class FoldedSteps extends Component {
|
||||
handleSimulationReset = () => {
|
||||
this.props.resetSimulation()
|
||||
this.props.resetForm()
|
||||
}
|
||||
render() {
|
||||
let { foldedSteps } = this.props
|
||||
)(
|
||||
class FoldedSteps extends Component {
|
||||
handleSimulationReset = () => {
|
||||
this.props.resetSimulation()
|
||||
this.props.resetForm()
|
||||
}
|
||||
render() {
|
||||
let { foldedSteps } = this.props
|
||||
|
||||
if (isEmpty(foldedSteps || [])) return null
|
||||
return (
|
||||
<div id="foldedSteps">
|
||||
<div className="header">
|
||||
<LinkButton onClick={this.handleSimulationReset}>
|
||||
<i className="fa fa-trash" aria-hidden="true" />
|
||||
<Trans i18nKey="resetAll">Tout effacer</Trans>
|
||||
</LinkButton>
|
||||
if (isEmpty(foldedSteps || [])) return null
|
||||
return (
|
||||
<div id="foldedSteps">
|
||||
<div className="header">
|
||||
<LinkButton onClick={this.handleSimulationReset}>
|
||||
<i className="fa fa-trash" aria-hidden="true" />
|
||||
<Trans i18nKey="resetAll">Tout effacer</Trans>
|
||||
</LinkButton>
|
||||
</div>
|
||||
{foldedSteps.map(dottedName => (
|
||||
<FoldedStep key={dottedName} dottedName={dottedName} />
|
||||
))}
|
||||
</div>
|
||||
{foldedSteps.map(dottedName => (
|
||||
<FoldedStep key={dottedName} dottedName={dottedName} />
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import classNames from 'classnames'
|
||||
import Explicable from 'Components/conversation/Explicable'
|
||||
import { compose } from 'ramda'
|
||||
import React, { Component } from 'react'
|
||||
import { translate } from 'react-i18next'
|
||||
import { withI18n } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import { change, Field } from 'redux-form'
|
||||
import IgnoreStepButton from './IgnoreStepButton'
|
||||
|
@ -20,83 +21,86 @@ to understand those precious higher order components.
|
|||
*/
|
||||
|
||||
export var FormDecorator = formType => RenderField =>
|
||||
@connect(
|
||||
//... this helper directly to the redux state to avoid passing more props
|
||||
state => ({
|
||||
themeColours: state.themeColours,
|
||||
flatRules: state.flatRules
|
||||
}),
|
||||
dispatch => ({
|
||||
stepAction: (name, step, source) =>
|
||||
dispatch({ type: 'STEP_ACTION', name, step, source }),
|
||||
setFormValue: (field, value) =>
|
||||
dispatch(change('conversation', field, value))
|
||||
})
|
||||
)
|
||||
@translate()
|
||||
class extends Component {
|
||||
state = {
|
||||
helpVisible: false
|
||||
}
|
||||
render() {
|
||||
let {
|
||||
setFormValue,
|
||||
stepAction,
|
||||
subquestion,
|
||||
valueType,
|
||||
defaultValue,
|
||||
fieldName,
|
||||
inversion,
|
||||
themeColours
|
||||
} = this.props
|
||||
compose(
|
||||
connect(
|
||||
//... this helper directly to the redux state to avoid passing more props
|
||||
state => ({
|
||||
themeColours: state.themeColours,
|
||||
flatRules: state.flatRules
|
||||
}),
|
||||
dispatch => ({
|
||||
stepAction: (name, step, source) =>
|
||||
dispatch({ type: 'STEP_ACTION', name, step, source }),
|
||||
setFormValue: (field, value) =>
|
||||
dispatch(change('conversation', field, value))
|
||||
})
|
||||
),
|
||||
withI18n()
|
||||
)(
|
||||
class extends Component {
|
||||
state = {
|
||||
helpVisible: false
|
||||
}
|
||||
render() {
|
||||
let {
|
||||
setFormValue,
|
||||
stepAction,
|
||||
subquestion,
|
||||
valueType,
|
||||
defaultValue,
|
||||
fieldName,
|
||||
inversion,
|
||||
themeColours
|
||||
} = this.props
|
||||
|
||||
let validate = buildValidationFunction(valueType)
|
||||
let validate = buildValidationFunction(valueType)
|
||||
|
||||
let submit = cause => stepAction('fold', fieldName, cause),
|
||||
stepProps = {
|
||||
...this.props,
|
||||
submit,
|
||||
validate,
|
||||
setFormValue: (value, name = fieldName) => setFormValue(name, value)
|
||||
}
|
||||
let submit = cause => stepAction('fold', fieldName, cause),
|
||||
stepProps = {
|
||||
...this.props,
|
||||
submit,
|
||||
validate,
|
||||
setFormValue: (value, name = fieldName) => setFormValue(name, value)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classNames('step', formType)}>
|
||||
<div className="unfoldedHeader">
|
||||
<div className="step-question">
|
||||
<h1>
|
||||
{' '}
|
||||
{this.props.question}{' '}
|
||||
{!inversion && <Explicable dottedName={fieldName} />}
|
||||
</h1>
|
||||
<div
|
||||
className="step-subquestion"
|
||||
dangerouslySetInnerHTML={{ __html: subquestion }}
|
||||
/>
|
||||
return (
|
||||
<div className={classNames('step', formType)}>
|
||||
<div className="unfoldedHeader">
|
||||
<div className="step-question">
|
||||
<h1>
|
||||
{' '}
|
||||
{this.props.question}{' '}
|
||||
{!inversion && <Explicable dottedName={fieldName} />}
|
||||
</h1>
|
||||
<div
|
||||
className="step-subquestion"
|
||||
dangerouslySetInnerHTML={{ __html: subquestion }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{defaultValue != null && (
|
||||
<IgnoreStepButton
|
||||
action={() => {
|
||||
setFormValue(
|
||||
fieldName,
|
||||
typeof defaultValue == 'object'
|
||||
? JSON.stringify(defaultValue)
|
||||
: '' + defaultValue
|
||||
)
|
||||
submit('ignore')
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<fieldset>
|
||||
<Field
|
||||
component={RenderField}
|
||||
name={fieldName}
|
||||
{...stepProps}
|
||||
themeColours={themeColours}
|
||||
/>
|
||||
</fieldset>
|
||||
</div>
|
||||
{defaultValue != null && (
|
||||
<IgnoreStepButton
|
||||
action={() => {
|
||||
setFormValue(
|
||||
fieldName,
|
||||
typeof defaultValue == 'object'
|
||||
? JSON.stringify(defaultValue)
|
||||
: '' + defaultValue
|
||||
)
|
||||
submit('ignore')
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<fieldset>
|
||||
<Field
|
||||
component={RenderField}
|
||||
name={fieldName}
|
||||
{...stepProps}
|
||||
themeColours={themeColours}
|
||||
/>
|
||||
</fieldset>
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -1,35 +1,41 @@
|
|||
import HoverDecorator from 'Components/utils/HoverDecorator'
|
||||
import { compose } from 'ramda'
|
||||
import React, { Component } from 'react'
|
||||
import { Trans, translate } from 'react-i18next'
|
||||
import { Trans, withI18n } from 'react-i18next'
|
||||
import './IgnoreStepButton.css'
|
||||
|
||||
@HoverDecorator
|
||||
@translate()
|
||||
export default class IgnoreStepButton extends Component {
|
||||
componentDidMount() {
|
||||
// removeEventListener will need the exact same function instance
|
||||
this.boundHandleKeyDown = this.handleKeyDown.bind(this)
|
||||
export default compose(
|
||||
HoverDecorator,
|
||||
withI18n()
|
||||
)(
|
||||
class IgnoreStepButton extends Component {
|
||||
componentDidMount() {
|
||||
// removeEventListener will need the exact same function instance
|
||||
this.boundHandleKeyDown = this.handleKeyDown.bind(this)
|
||||
|
||||
window.addEventListener('keydown', this.boundHandleKeyDown)
|
||||
window.addEventListener('keydown', this.boundHandleKeyDown)
|
||||
}
|
||||
handleKeyDown({ key }) {
|
||||
if (key !== 'Escape') return
|
||||
document.activeElement.blur()
|
||||
this.props.action()
|
||||
}
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('keydown', this.boundHandleKeyDown)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div id="ignore">
|
||||
<a id="ignoreButton" onClick={this.props.action}>
|
||||
<Trans>passer</Trans>
|
||||
</a>
|
||||
<span
|
||||
className="keyIcon"
|
||||
style={{ opacity: this.props.hover ? 1 : 0 }}>
|
||||
<Trans>Échap</Trans>
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
handleKeyDown({ key }) {
|
||||
if (key !== 'Escape') return
|
||||
document.activeElement.blur()
|
||||
this.props.action()
|
||||
}
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('keydown', this.boundHandleKeyDown)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div id="ignore">
|
||||
<a id="ignoreButton" onClick={this.props.action}>
|
||||
<Trans>passer</Trans>
|
||||
</a>
|
||||
<span className="keyIcon" style={{ opacity: this.props.hover ? 1 : 0 }}>
|
||||
<Trans>Échap</Trans>
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -1,66 +1,70 @@
|
|||
import classnames from 'classnames'
|
||||
import withColours from 'Components/utils/withColours'
|
||||
import { compose } from 'ramda'
|
||||
import React, { Component } from 'react'
|
||||
import { translate } from 'react-i18next'
|
||||
import { withI18n } from 'react-i18next'
|
||||
import { FormDecorator } from './FormDecorator'
|
||||
import InputSuggestions from './InputSuggestions'
|
||||
import SendButton from './SendButton'
|
||||
|
||||
@FormDecorator('input')
|
||||
@translate()
|
||||
@withColours
|
||||
export default class Input extends Component {
|
||||
render() {
|
||||
let {
|
||||
input,
|
||||
dottedName,
|
||||
submit,
|
||||
valueType,
|
||||
meta: { dirty, error, active },
|
||||
t,
|
||||
colours
|
||||
} = this.props,
|
||||
answerSuffix = valueType.suffix,
|
||||
suffixed = answerSuffix != null,
|
||||
inputError = dirty && error,
|
||||
submitDisabled = !dirty || inputError
|
||||
export default compose(
|
||||
FormDecorator('input'),
|
||||
withI18n(),
|
||||
withColours
|
||||
)(
|
||||
class Input extends Component {
|
||||
render() {
|
||||
let {
|
||||
input,
|
||||
dottedName,
|
||||
submit,
|
||||
valueType,
|
||||
meta: { dirty, error, active },
|
||||
t,
|
||||
colours
|
||||
} = this.props,
|
||||
answerSuffix = valueType.suffix,
|
||||
suffixed = answerSuffix != null,
|
||||
inputError = dirty && error,
|
||||
submitDisabled = !dirty || inputError
|
||||
|
||||
return (
|
||||
<span>
|
||||
<div className="answer">
|
||||
<input
|
||||
ref={el => {
|
||||
this.inputElement = el
|
||||
}}
|
||||
type="text"
|
||||
{...input}
|
||||
className={classnames({ suffixed })}
|
||||
id={'step-' + dottedName}
|
||||
inputMode="numeric"
|
||||
placeholder={t('votre réponse')}
|
||||
style={
|
||||
!active
|
||||
? { border: '2px dashed #ddd' }
|
||||
: { border: `1px solid ${colours.textColourOnWhite}` }
|
||||
}
|
||||
return (
|
||||
<span>
|
||||
<div className="answer">
|
||||
<input
|
||||
ref={el => {
|
||||
this.inputElement = el
|
||||
}}
|
||||
type="text"
|
||||
{...input}
|
||||
className={classnames({ suffixed })}
|
||||
id={'step-' + dottedName}
|
||||
inputMode="numeric"
|
||||
placeholder={t('votre réponse')}
|
||||
style={
|
||||
!active
|
||||
? { border: '2px dashed #ddd' }
|
||||
: { border: `1px solid ${colours.textColourOnWhite}` }
|
||||
}
|
||||
/>
|
||||
{suffixed && (
|
||||
<label
|
||||
className="suffix"
|
||||
htmlFor={'step-' + dottedName}
|
||||
style={!active ? { color: '#888' } : { color: '#222' }}>
|
||||
{answerSuffix}
|
||||
</label>
|
||||
)}
|
||||
<SendButton {...{ disabled: submitDisabled, error, submit }} />
|
||||
</div>
|
||||
<InputSuggestions
|
||||
suggestions={this.props.suggestions}
|
||||
onFirstClick={value => this.props.setFormValue('' + value)}
|
||||
onSecondClick={() => this.props.submit('suggestion')}
|
||||
/>
|
||||
{suffixed && (
|
||||
<label
|
||||
className="suffix"
|
||||
htmlFor={'step-' + dottedName}
|
||||
style={!active ? { color: '#888' } : { color: '#222' }}>
|
||||
{answerSuffix}
|
||||
</label>
|
||||
)}
|
||||
<SendButton {...{ disabled: submitDisabled, error, submit }} />
|
||||
</div>
|
||||
<InputSuggestions
|
||||
suggestions={this.props.suggestions}
|
||||
onFirstClick={value => this.props.setFormValue('' + value)}
|
||||
onSecondClick={() => this.props.submit('suggestion')}
|
||||
/>
|
||||
{inputError && <span className="step-input-error">{error}</span>}
|
||||
</span>
|
||||
)
|
||||
{inputError && <span className="step-input-error">{error}</span>}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -1,49 +1,52 @@
|
|||
import withColours from 'Components/utils/withColours'
|
||||
import { toPairs } from 'ramda'
|
||||
import { compose, toPairs } from 'ramda'
|
||||
import React, { Component } from 'react'
|
||||
import { translate } from 'react-i18next'
|
||||
import { withI18n } from 'react-i18next'
|
||||
import './InputSuggestions.css'
|
||||
|
||||
@withColours
|
||||
@translate()
|
||||
export default class InputSuggestions extends Component {
|
||||
state = { suggestion: null }
|
||||
render() {
|
||||
let {
|
||||
suggestions,
|
||||
onSecondClick,
|
||||
onFirstClick,
|
||||
colouredBackground,
|
||||
colours,
|
||||
t
|
||||
} = this.props
|
||||
export default compose(
|
||||
withColours,
|
||||
withI18n()
|
||||
)(
|
||||
class InputSuggestions extends Component {
|
||||
state = { suggestion: null }
|
||||
render() {
|
||||
let {
|
||||
suggestions,
|
||||
onSecondClick,
|
||||
onFirstClick,
|
||||
colouredBackground,
|
||||
colours,
|
||||
t
|
||||
} = this.props
|
||||
|
||||
if (!suggestions) return null
|
||||
return (
|
||||
<div className="inputSuggestions">
|
||||
suggestions:
|
||||
<ul>
|
||||
{toPairs(suggestions).map(([text, value]) => (
|
||||
<li
|
||||
key={value}
|
||||
onClick={() => {
|
||||
onFirstClick(value)
|
||||
if (this.state.suggestion !== value)
|
||||
this.setState({ suggestion: value })
|
||||
else onSecondClick && onSecondClick(value)
|
||||
}}
|
||||
style={{
|
||||
color: colouredBackground
|
||||
? colours.textColour
|
||||
: colours.textColourOnWhite
|
||||
}}>
|
||||
<span title={t('cliquez pour insérer cette suggestion')}>
|
||||
{text}
|
||||
</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
if (!suggestions) return null
|
||||
return (
|
||||
<div className="inputSuggestions">
|
||||
suggestions:
|
||||
<ul>
|
||||
{toPairs(suggestions).map(([text, value]) => (
|
||||
<li
|
||||
key={value}
|
||||
onClick={() => {
|
||||
onFirstClick(value)
|
||||
if (this.state.suggestion !== value)
|
||||
this.setState({ suggestion: value })
|
||||
else onSecondClick && onSecondClick(value)
|
||||
}}
|
||||
style={{
|
||||
color: colouredBackground
|
||||
? colours.textColour
|
||||
: colours.textColourOnWhite
|
||||
}}>
|
||||
<span title={t('cliquez pour insérer cette suggestion')}>
|
||||
{text}
|
||||
</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
import HoverDecorator from 'Components/utils/HoverDecorator'
|
||||
import withColours from 'Components/utils/withColours'
|
||||
import { is } from 'ramda'
|
||||
import { compose, is } from 'ramda'
|
||||
import React, { Component } from 'react'
|
||||
import { Trans, translate } from 'react-i18next'
|
||||
import { Trans, withI18n } from 'react-i18next'
|
||||
import Explicable from './Explicable'
|
||||
import { FormDecorator } from './FormDecorator'
|
||||
import './Question.css'
|
||||
import SendButton from './SendButton'
|
||||
import { answer, answered } from './userAnswerButtonStyle'
|
||||
|
||||
/* Ceci est une saisie de type "radio" : l'utilisateur choisit une réponse dans une liste, ou une liste de listes.
|
||||
Les données @choices sont un arbre de type:
|
||||
- nom: motif CDD # La racine, unique, qui formera la Question. Ses enfants sont les choix possibles
|
||||
|
@ -26,87 +27,88 @@ import { answer, answered } from './userAnswerButtonStyle'
|
|||
|
||||
// FormDecorator permet de factoriser du code partagé par les différents types de saisie,
|
||||
// dont Question est un example
|
||||
@FormDecorator('question')
|
||||
@translate()
|
||||
@withColours
|
||||
export default class Question extends Component {
|
||||
render() {
|
||||
let {
|
||||
choices,
|
||||
submit,
|
||||
colours,
|
||||
meta: { pristine }
|
||||
} = this.props
|
||||
let choiceElements = is(Array)(choices)
|
||||
? this.renderBinaryQuestion()
|
||||
: this.renderChildren(choices)
|
||||
return (
|
||||
<>
|
||||
{choiceElements}
|
||||
<SendButton
|
||||
{...{
|
||||
disabled: pristine,
|
||||
colours,
|
||||
error: false,
|
||||
submit
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
renderBinaryQuestion() {
|
||||
let {
|
||||
input, // vient de redux-form
|
||||
submit,
|
||||
choices,
|
||||
setFormValue,
|
||||
colours
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
<ul className="binaryQuestionList">
|
||||
{choices.map(({ value, label }) => (
|
||||
<RadioLabel
|
||||
key={value}
|
||||
{...{ value, label, input, submit, colours, setFormValue }}
|
||||
export default compose(
|
||||
FormDecorator('question'),
|
||||
withI18n(),
|
||||
withColours
|
||||
)(
|
||||
class Question extends Component {
|
||||
render() {
|
||||
let {
|
||||
choices,
|
||||
submit,
|
||||
colours,
|
||||
meta: { pristine }
|
||||
} = this.props
|
||||
let choiceElements = is(Array)(choices)
|
||||
? this.renderBinaryQuestion()
|
||||
: this.renderChildren(choices)
|
||||
return (
|
||||
<>
|
||||
{choiceElements}
|
||||
<SendButton
|
||||
{...{
|
||||
disabled: pristine,
|
||||
colours,
|
||||
error: false,
|
||||
submit
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
renderChildren(choices) {
|
||||
let {
|
||||
</>
|
||||
)
|
||||
}
|
||||
renderBinaryQuestion() {
|
||||
let {
|
||||
input, // vient de redux-form
|
||||
submit,
|
||||
choices,
|
||||
setFormValue,
|
||||
colours
|
||||
} = this.props,
|
||||
{ name } = input,
|
||||
// seront stockées ainsi dans le state :
|
||||
// [parent object path]: dotted name relative to parent
|
||||
relativeDottedName = radioDottedName =>
|
||||
radioDottedName.split(name + ' . ')[1]
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
<ul>
|
||||
{choices.canGiveUp && (
|
||||
<li key="aucun" className="variantLeaf aucun">
|
||||
return (
|
||||
<ul className="binaryQuestionList">
|
||||
{choices.map(({ value, label }) => (
|
||||
<RadioLabel
|
||||
{...{
|
||||
value: 'non',
|
||||
label: 'Aucun',
|
||||
input,
|
||||
submit,
|
||||
colours,
|
||||
dottedName: null,
|
||||
setFormValue
|
||||
}}
|
||||
key={value}
|
||||
{...{ value, label, input, submit, colours, setFormValue }}
|
||||
/>
|
||||
</li>
|
||||
)}
|
||||
{choices.children &&
|
||||
choices.children.map(
|
||||
({ name, title, dottedName, children }) =>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
renderChildren(choices) {
|
||||
let {
|
||||
input, // vient de redux-form
|
||||
submit,
|
||||
setFormValue,
|
||||
colours
|
||||
} = this.props,
|
||||
{ name } = input,
|
||||
// seront stockées ainsi dans le state :
|
||||
// [parent object path]: dotted name relative to parent
|
||||
relativeDottedName = radioDottedName =>
|
||||
radioDottedName.split(name + ' . ')[1]
|
||||
|
||||
return (
|
||||
<ul>
|
||||
{choices.canGiveUp && (
|
||||
<li key="aucun" className="variantLeaf aucun">
|
||||
<RadioLabel
|
||||
{...{
|
||||
value: 'non',
|
||||
label: 'Aucun',
|
||||
input,
|
||||
submit,
|
||||
colours,
|
||||
dottedName: null,
|
||||
setFormValue
|
||||
}}
|
||||
/>
|
||||
</li>
|
||||
)}
|
||||
{choices.children &&
|
||||
choices.children.map(({ name, title, dottedName, children }) =>
|
||||
children ? (
|
||||
<li key={name} className="variant">
|
||||
<div>{title}</div>
|
||||
|
@ -127,11 +129,12 @@ export default class Question extends Component {
|
|||
/>
|
||||
</li>
|
||||
)
|
||||
)}
|
||||
</ul>
|
||||
)
|
||||
)}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
let RadioLabel = props => (
|
||||
<>
|
||||
|
@ -140,32 +143,35 @@ let RadioLabel = props => (
|
|||
</>
|
||||
)
|
||||
|
||||
@HoverDecorator
|
||||
@translate()
|
||||
@withColours
|
||||
class RadioLabelContent extends Component {
|
||||
click = value => () => {
|
||||
if (this.props.input.value == value) this.props.submit('dblClick')
|
||||
}
|
||||
render() {
|
||||
let { value, label, input, hover, colours } = this.props,
|
||||
// value = when(is(Object), prop('value'))(choice),
|
||||
labelStyle = Object.assign(
|
||||
value === input.value || hover ? answered(colours) : answer(colours),
|
||||
value === '_' ? { fontWeight: 'bold' } : null
|
||||
)
|
||||
const RadioLabelContent = compose(
|
||||
HoverDecorator,
|
||||
withI18n(),
|
||||
withColours
|
||||
)(
|
||||
class RadioLabelContent extends Component {
|
||||
click = value => () => {
|
||||
if (this.props.input.value == value) this.props.submit('dblClick')
|
||||
}
|
||||
render() {
|
||||
let { value, label, input, hover, colours } = this.props,
|
||||
// value = when(is(Object), prop('value'))(choice),
|
||||
labelStyle = Object.assign(
|
||||
value === input.value || hover ? answered(colours) : answer(colours),
|
||||
value === '_' ? { fontWeight: 'bold' } : null
|
||||
)
|
||||
|
||||
return (
|
||||
<label key={value} style={labelStyle} className="radio">
|
||||
<Trans i18nKey={`radio_${label}`}>{label}</Trans>
|
||||
<input
|
||||
type="radio"
|
||||
{...input}
|
||||
onClick={this.click(value)}
|
||||
value={value}
|
||||
checked={value === input.value ? 'checked' : ''}
|
||||
/>
|
||||
</label>
|
||||
)
|
||||
return (
|
||||
<label key={value} style={labelStyle} className="radio">
|
||||
<Trans i18nKey={`radio_${label}`}>{label}</Trans>
|
||||
<input
|
||||
type="radio"
|
||||
{...input}
|
||||
onClick={this.click(value)}
|
||||
value={value}
|
||||
checked={value === input.value ? 'checked' : ''}
|
||||
/>
|
||||
</label>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -1,23 +1,24 @@
|
|||
import FormDecorator from 'Components/conversation/FormDecorator'
|
||||
import React, { Component } from 'react'
|
||||
import { FormDecorator } from './FormDecorator'
|
||||
import { answer } from './userAnswerButtonStyle'
|
||||
|
||||
@FormDecorator('rhetorical-question')
|
||||
export default class RhetoricalQuestion extends Component {
|
||||
render() {
|
||||
let { input, submit, possibleChoice, themeColours } = this.props
|
||||
export default FormDecorator('rhetorical-question')(
|
||||
class RhetoricalQuestion extends Component {
|
||||
render() {
|
||||
let { input, submit, possibleChoice, themeColours } = this.props
|
||||
|
||||
if (!possibleChoice) return null // No action possible, don't render an answer
|
||||
if (!possibleChoice) return null // No action possible, don't render an answer
|
||||
|
||||
let { text, value } = possibleChoice
|
||||
let { text, value } = possibleChoice
|
||||
|
||||
return (
|
||||
<span className="answer">
|
||||
<label key={value} className="radio" style={answer(themeColours)}>
|
||||
<input type="radio" {...input} onClick={submit} value={value} />
|
||||
{text}
|
||||
</label>
|
||||
</span>
|
||||
)
|
||||
return (
|
||||
<span className="answer">
|
||||
<label key={value} className="radio" style={answer(themeColours)}>
|
||||
<input type="radio" {...input} onClick={submit} value={value} />
|
||||
{text}
|
||||
</label>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -1,51 +1,55 @@
|
|||
import HoverDecorator from 'Components/utils/HoverDecorator'
|
||||
import withColours from 'Components/utils/withColours'
|
||||
import { compose } from 'ramda'
|
||||
import React, { Component } from 'react'
|
||||
import { Trans, translate } from 'react-i18next'
|
||||
import { Trans, withI18n } from 'react-i18next'
|
||||
|
||||
@HoverDecorator
|
||||
@translate()
|
||||
@withColours
|
||||
export default class SendButton extends Component {
|
||||
getAction() {
|
||||
let { disabled, submit } = this.props
|
||||
return cause => (!disabled ? submit(cause) : null)
|
||||
}
|
||||
componentDidMount() {
|
||||
// removeEventListener will need the exact same function instance
|
||||
this.boundHandleKeyDown = this.handleKeyDown.bind(this)
|
||||
export default compose(
|
||||
HoverDecorator,
|
||||
withI18n(),
|
||||
withColours
|
||||
)(
|
||||
class SendButton extends Component {
|
||||
getAction() {
|
||||
let { disabled, submit } = this.props
|
||||
return cause => (!disabled ? submit(cause) : null)
|
||||
}
|
||||
componentDidMount() {
|
||||
// removeEventListener will need the exact same function instance
|
||||
this.boundHandleKeyDown = this.handleKeyDown.bind(this)
|
||||
|
||||
window.addEventListener('keydown', this.boundHandleKeyDown)
|
||||
}
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('keydown', this.boundHandleKeyDown)
|
||||
}
|
||||
handleKeyDown({ key }) {
|
||||
if (key !== 'Enter') return
|
||||
this.getAction()('enter')
|
||||
}
|
||||
render() {
|
||||
let { disabled, colours, hover } = this.props
|
||||
return (
|
||||
<span className="sendWrapper">
|
||||
<button
|
||||
className="send"
|
||||
disabled={disabled}
|
||||
style={{
|
||||
color: colours.textColour,
|
||||
background: colours.colour
|
||||
}}
|
||||
onClick={() => this.getAction()('accept')}>
|
||||
<span className="text">
|
||||
<Trans>valider</Trans> ✓
|
||||
window.addEventListener('keydown', this.boundHandleKeyDown)
|
||||
}
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('keydown', this.boundHandleKeyDown)
|
||||
}
|
||||
handleKeyDown({ key }) {
|
||||
if (key !== 'Enter') return
|
||||
this.getAction()('enter')
|
||||
}
|
||||
render() {
|
||||
let { disabled, colours, hover } = this.props
|
||||
return (
|
||||
<span className="sendWrapper">
|
||||
<button
|
||||
className="send"
|
||||
disabled={disabled}
|
||||
style={{
|
||||
color: colours.textColour,
|
||||
background: colours.colour
|
||||
}}
|
||||
onClick={() => this.getAction()('accept')}>
|
||||
<span className="text">
|
||||
<Trans>valider</Trans> ✓
|
||||
</span>
|
||||
</button>
|
||||
<span
|
||||
className="keyIcon"
|
||||
style={{ opacity: hover && !disabled ? 1 : 0 }}>
|
||||
<Trans>Entrée</Trans> ↵
|
||||
</span>
|
||||
</button>
|
||||
<span
|
||||
className="keyIcon"
|
||||
style={{ opacity: hover && !disabled ? 1 : 0 }}>
|
||||
<Trans>Entrée</Trans> ↵
|
||||
</span>
|
||||
</span>
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -1,52 +1,57 @@
|
|||
import { compose } from 'ramda'
|
||||
import React, { Component } from 'react'
|
||||
import { Trans, translate } from 'react-i18next'
|
||||
import { Trans, withI18n } from 'react-i18next'
|
||||
import { FormDecorator } from './FormDecorator'
|
||||
|
||||
@FormDecorator('text-area')
|
||||
@translate()
|
||||
export default class Input extends Component {
|
||||
render() {
|
||||
let {
|
||||
name,
|
||||
input,
|
||||
submit,
|
||||
attributes,
|
||||
meta: { touched, error },
|
||||
themeColours
|
||||
} = this.props,
|
||||
inputError = touched && error,
|
||||
sendButtonDisabled = !input.value || inputError
|
||||
export default compose(
|
||||
FormDecorator('text-area'),
|
||||
withI18n()
|
||||
)(
|
||||
class Input extends Component {
|
||||
render() {
|
||||
let {
|
||||
name,
|
||||
input,
|
||||
submit,
|
||||
attributes,
|
||||
meta: { touched, error },
|
||||
themeColours
|
||||
} = this.props,
|
||||
inputError = touched && error,
|
||||
sendButtonDisabled = !input.value || inputError
|
||||
|
||||
return (
|
||||
<span>
|
||||
<span className="answer">
|
||||
<textarea
|
||||
{...attributes}
|
||||
{...input}
|
||||
id={'step-' + name}
|
||||
onKeyDown={
|
||||
({ key, ctrlKey }) =>
|
||||
key == 'Enter' &&
|
||||
ctrlKey &&
|
||||
input.value &&
|
||||
(!error ? submit() : input.onBlur()) // blur will trigger the error
|
||||
}
|
||||
/>
|
||||
<button
|
||||
className="send"
|
||||
style={{
|
||||
visibility: sendButtonDisabled ? 'hidden' : 'visible',
|
||||
color: themeColours.textColour,
|
||||
background: themeColours.colour
|
||||
}}
|
||||
onClick={() => (!error ? submit() : null)}
|
||||
>
|
||||
<span className="text"><Trans>valider</Trans></span>
|
||||
<span className="icon">✓</span>
|
||||
</button>
|
||||
return (
|
||||
<span>
|
||||
<span className="answer">
|
||||
<textarea
|
||||
{...attributes}
|
||||
{...input}
|
||||
id={'step-' + name}
|
||||
onKeyDown={
|
||||
({ key, ctrlKey }) =>
|
||||
key == 'Enter' &&
|
||||
ctrlKey &&
|
||||
input.value &&
|
||||
(!error ? submit() : input.onBlur()) // blur will trigger the error
|
||||
}
|
||||
/>
|
||||
<button
|
||||
className="send"
|
||||
style={{
|
||||
visibility: sendButtonDisabled ? 'hidden' : 'visible',
|
||||
color: themeColours.textColour,
|
||||
background: themeColours.colour
|
||||
}}
|
||||
onClick={() => (!error ? submit() : null)}>
|
||||
<span className="text">
|
||||
<Trans>valider</Trans>
|
||||
</span>
|
||||
<span className="icon">✓</span>
|
||||
</button>
|
||||
</span>
|
||||
{inputError && <span className="step-input-error">{error}</span>}
|
||||
</span>
|
||||
{inputError && <span className="step-input-error">{error}</span>}
|
||||
</span>
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -24,39 +24,39 @@ let getOptions = input =>
|
|||
return { options: [] }
|
||||
})
|
||||
|
||||
@FormDecorator('select')
|
||||
class Select extends Component {
|
||||
render() {
|
||||
let {
|
||||
input: { onChange },
|
||||
submit
|
||||
} = this.props,
|
||||
submitOnChange = option => {
|
||||
// serialize to not mix our data schema and the API response's
|
||||
onChange(JSON.stringify(option))
|
||||
submit()
|
||||
}
|
||||
export default FormDecorator('select')(
|
||||
class Select extends Component {
|
||||
render() {
|
||||
let {
|
||||
input: { onChange },
|
||||
submit
|
||||
} = this.props,
|
||||
submitOnChange = option => {
|
||||
// serialize to not mix our data schema and the API response's
|
||||
onChange(JSON.stringify(option))
|
||||
submit()
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="select-answer commune">
|
||||
<ReactSelect.Async
|
||||
onChange={submitOnChange}
|
||||
labelKey="nom"
|
||||
optionRenderer={({ nom, departement }) =>
|
||||
nom + ` (${departement?.nom})`
|
||||
}
|
||||
filterOptions={options => {
|
||||
// Do no filtering, just return all options
|
||||
return options
|
||||
}}
|
||||
placeholder="Entrez le nom de commune"
|
||||
noResultsText="Nous n'avons trouvé aucune commune"
|
||||
searchPromptText={null}
|
||||
loadingPlaceholder="Recherche en cours..."
|
||||
loadOptions={getOptions}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
return (
|
||||
<div className="select-answer commune">
|
||||
<ReactSelect.Async
|
||||
onChange={submitOnChange}
|
||||
labelKey="nom"
|
||||
optionRenderer={({ nom, departement }) =>
|
||||
nom + ` (${departement?.nom})`
|
||||
}
|
||||
filterOptions={options => {
|
||||
// Do no filtering, just return all options
|
||||
return options
|
||||
}}
|
||||
placeholder="Entrez le nom de commune"
|
||||
noResultsText="Nous n'avons trouvé aucune commune"
|
||||
searchPromptText={null}
|
||||
loadingPlaceholder="Recherche en cours..."
|
||||
loadOptions={getOptions}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
export default Select
|
||||
)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import React, { Component } from 'react'
|
||||
import { FormDecorator } from '../FormDecorator'
|
||||
import ReactSelect from 'react-select'
|
||||
import SelectOption from './SelectOption.js'
|
||||
import 'react-select/dist/react-select.css'
|
||||
import { FormDecorator } from '../FormDecorator'
|
||||
import './Select.css'
|
||||
import SelectOption from './SelectOption.js'
|
||||
|
||||
class ReactSelectWrapper extends Component {
|
||||
render() {
|
||||
|
@ -42,8 +42,7 @@ class ReactSelectWrapper extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
@FormDecorator('select')
|
||||
export default class Select extends Component {
|
||||
class Select extends Component {
|
||||
state = {
|
||||
options: null
|
||||
}
|
||||
|
@ -80,3 +79,5 @@ export default class Select extends Component {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default FormDecorator('select')(Select)
|
||||
|
|
|
@ -1,34 +1,33 @@
|
|||
import classNames from 'classnames'
|
||||
import { makeJsx } from 'Engine/evaluation'
|
||||
import knownMecanisms from 'Engine/known-mecanisms.yaml'
|
||||
import classNames from 'classnames'
|
||||
import { path, values } from 'ramda'
|
||||
import { compose, path, values } from 'ramda'
|
||||
import React from 'react'
|
||||
import { Trans, translate } from 'react-i18next'
|
||||
import { Trans, withI18n } from 'react-i18next'
|
||||
import { AttachDictionary } from '../AttachDictionary'
|
||||
import './Algorithm.css'
|
||||
|
||||
// The showValues prop is passed as a context. It used to be delt in CSS (not(.showValues) display: none), both coexist right now
|
||||
import { ShowValuesProvider } from './ShowValuesContext'
|
||||
|
||||
@AttachDictionary(knownMecanisms)
|
||||
@translate()
|
||||
export default class Algorithm extends React.Component {
|
||||
render() {
|
||||
let { rule, showValues } = this.props,
|
||||
ruleWithoutFormula =
|
||||
!rule['formule'] ||
|
||||
path(['formule', 'explanation', 'une possibilité'], rule)
|
||||
|
||||
return (
|
||||
<div id="algorithm">
|
||||
<section id="rule-rules" className={classNames({ showValues })}>
|
||||
<ShowValuesProvider value={showValues}>
|
||||
{do {
|
||||
// TODO ce let est incompréhensible !
|
||||
let applicabilityMecanisms = values(rule).filter(
|
||||
v => v && v['rulePropType'] == 'cond'
|
||||
)
|
||||
applicabilityMecanisms.length > 0 && (
|
||||
export default compose(
|
||||
AttachDictionary(knownMecanisms),
|
||||
withI18n()
|
||||
)(
|
||||
class Algorithm extends React.Component {
|
||||
render() {
|
||||
let { rule, showValues } = this.props,
|
||||
ruleWithoutFormula =
|
||||
!rule['formule'] ||
|
||||
path(['formule', 'explanation', 'une possibilité'], rule)
|
||||
// TODO ce let est incompréhensible !
|
||||
let applicabilityMecanisms = values(rule).filter(
|
||||
v => v && v['rulePropType'] == 'cond'
|
||||
)
|
||||
return (
|
||||
<div id="algorithm">
|
||||
<section id="rule-rules" className={classNames({ showValues })}>
|
||||
<ShowValuesProvider value={showValues}>
|
||||
{applicabilityMecanisms.length > 0 && (
|
||||
<section id="declenchement">
|
||||
<h2>
|
||||
<Trans>Déclenchement</Trans>
|
||||
|
@ -39,19 +38,19 @@ export default class Algorithm extends React.Component {
|
|||
))}
|
||||
</ul>
|
||||
</section>
|
||||
)
|
||||
}}
|
||||
{!ruleWithoutFormula ? (
|
||||
<section id="formule">
|
||||
<h2>
|
||||
<Trans>Calcul</Trans>
|
||||
</h2>
|
||||
{makeJsx(rule['formule'])}
|
||||
</section>
|
||||
) : null}
|
||||
</ShowValuesProvider>
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
{!ruleWithoutFormula ? (
|
||||
<section id="formule">
|
||||
<h2>
|
||||
<Trans>Calcul</Trans>
|
||||
</h2>
|
||||
{makeJsx(rule['formule'])}
|
||||
</section>
|
||||
) : null}
|
||||
</ShowValuesProvider>
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -1,37 +1,38 @@
|
|||
import React, { Component } from 'react'
|
||||
import { Trans, translate } from 'react-i18next'
|
||||
import { Trans, withI18n } from 'react-i18next'
|
||||
import possiblesDestinataires from 'Règles/ressources/destinataires/destinataires.yaml'
|
||||
import './Destinataire.css'
|
||||
|
||||
@translate()
|
||||
export default class Rule extends Component {
|
||||
render() {
|
||||
let { destinataire } = this.props,
|
||||
destinataireData = possiblesDestinataires[destinataire]
|
||||
export default withI18n()(
|
||||
class Rule extends Component {
|
||||
render() {
|
||||
let { destinataire } = this.props,
|
||||
destinataireData = possiblesDestinataires[destinataire]
|
||||
|
||||
return destinataire && destinataireData ? (
|
||||
<div className="infobox__item" id="destinataire">
|
||||
<h4>
|
||||
<Trans>Destinataire</Trans>
|
||||
:
|
||||
</h4>
|
||||
<div>
|
||||
<a href={destinataireData.lien} target="_blank">
|
||||
{destinataireData.image && (
|
||||
<img
|
||||
src={require('Règles/ressources/destinataires/' +
|
||||
destinataireData.image)}
|
||||
/>
|
||||
return destinataire && destinataireData ? (
|
||||
<div className="infobox__item" id="destinataire">
|
||||
<h4>
|
||||
<Trans>Destinataire</Trans>
|
||||
:
|
||||
</h4>
|
||||
<div>
|
||||
<a href={destinataireData.lien} target="_blank">
|
||||
{destinataireData.image && (
|
||||
<img
|
||||
src={require('Règles/ressources/destinataires/' +
|
||||
destinataireData.image)}
|
||||
/>
|
||||
)}
|
||||
{!destinataireData.image && (
|
||||
<div id="calligraphy">{destinataire}</div>
|
||||
)}
|
||||
</a>
|
||||
{destinataireData.nom && (
|
||||
<div id="destinataireName">{destinataireData.nom}</div>
|
||||
)}
|
||||
{!destinataireData.image && (
|
||||
<div id="calligraphy">{destinataire}</div>
|
||||
)}
|
||||
</a>
|
||||
{destinataireData.nom && (
|
||||
<div id="destinataireName">{destinataireData.nom}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : null
|
||||
) : null
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -1,58 +1,59 @@
|
|||
import React, { Component } from 'react'
|
||||
import { Trans, translate } from 'react-i18next'
|
||||
import { compose } from 'ramda'
|
||||
import classNames from 'classnames'
|
||||
import { connect } from 'react-redux'
|
||||
import './Examples.css'
|
||||
import { setExample } from 'Actions/actions'
|
||||
import classNames from 'classnames'
|
||||
import { compose } from 'ramda'
|
||||
import React, { Component } from 'react'
|
||||
import { Trans, withI18n } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import { capitalise0 } from '../../utils'
|
||||
import './Examples.css'
|
||||
|
||||
@connect(
|
||||
state => ({
|
||||
parsedRules: state.parsedRules,
|
||||
themeColours: state.themeColours
|
||||
}),
|
||||
dispatch => ({
|
||||
setExample: compose(
|
||||
dispatch,
|
||||
setExample
|
||||
)
|
||||
})
|
||||
)
|
||||
@translate()
|
||||
export default class Examples extends Component {
|
||||
render() {
|
||||
let {
|
||||
situationExists,
|
||||
rule,
|
||||
themeColours,
|
||||
setExample,
|
||||
currentExample
|
||||
} = this.props,
|
||||
{ examples } = rule
|
||||
export default compose(
|
||||
connect(
|
||||
state => ({
|
||||
parsedRules: state.parsedRules,
|
||||
themeColours: state.themeColours
|
||||
}),
|
||||
dispatch => ({
|
||||
setExample: compose(
|
||||
dispatch,
|
||||
setExample
|
||||
)
|
||||
})
|
||||
),
|
||||
withI18n()
|
||||
)(
|
||||
class Examples extends Component {
|
||||
render() {
|
||||
let {
|
||||
situationExists,
|
||||
rule,
|
||||
themeColours,
|
||||
setExample,
|
||||
currentExample
|
||||
} = this.props,
|
||||
{ examples } = rule
|
||||
|
||||
if (!examples) return null
|
||||
return (
|
||||
<div id="examples">
|
||||
<h2>
|
||||
<Trans i18nKey="examples">Exemples</Trans>{' '}
|
||||
<small>
|
||||
<Trans i18nKey="clickexample">
|
||||
Cliquez sur un exemple pour le tester
|
||||
</Trans>
|
||||
</small>
|
||||
</h2>
|
||||
<ul>
|
||||
{examples.map(ex => (
|
||||
<Example
|
||||
key={ex.nom}
|
||||
{...{ ex, rule, currentExample, setExample, themeColours }}
|
||||
/>
|
||||
))}
|
||||
</ul>
|
||||
if (!examples) return null
|
||||
return (
|
||||
<div id="examples">
|
||||
<h2>
|
||||
<Trans i18nKey="examples">Exemples</Trans>{' '}
|
||||
<small>
|
||||
<Trans i18nKey="clickexample">
|
||||
Cliquez sur un exemple pour le tester
|
||||
</Trans>
|
||||
</small>
|
||||
</h2>
|
||||
<ul>
|
||||
{examples.map(ex => (
|
||||
<Example
|
||||
key={ex.nom}
|
||||
{...{ ex, rule, currentExample, setExample, themeColours }}
|
||||
/>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
{situationExists &&
|
||||
currentExample && (
|
||||
{situationExists && currentExample && (
|
||||
<div>
|
||||
<button
|
||||
id="injectSituation"
|
||||
|
@ -62,10 +63,11 @@ export default class Examples extends Component {
|
|||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
let Example = ({
|
||||
ex: { nom, situation },
|
||||
|
|
|
@ -1,77 +1,80 @@
|
|||
import { groupBy, toPairs } from 'ramda'
|
||||
import React from 'react'
|
||||
import { Trans, translate } from 'react-i18next'
|
||||
import { Trans, withI18n } from 'react-i18next'
|
||||
import references from 'Règles/ressources/références/références.yaml'
|
||||
import { capitalise0 } from '../../utils'
|
||||
import './References.css'
|
||||
|
||||
@translate()
|
||||
export default class References extends React.Component {
|
||||
state = {
|
||||
showComplementary: false
|
||||
}
|
||||
render() {
|
||||
let { refs } = this.props,
|
||||
{ complementary, official = [] } = groupBy(
|
||||
([, link]) => (this.findRefKey(link) ? 'official' : 'complementary')
|
||||
)(toPairs(refs)),
|
||||
showComplementary = this.state.showComplementary,
|
||||
showComplementaryButton = !this.state.showComplementary && complementary
|
||||
export default withI18n()(
|
||||
class References extends React.Component {
|
||||
state = {
|
||||
showComplementary: false
|
||||
}
|
||||
render() {
|
||||
let { refs } = this.props,
|
||||
{ complementary, official = [] } = groupBy(([, link]) =>
|
||||
this.findRefKey(link) ? 'official' : 'complementary'
|
||||
)(toPairs(refs)),
|
||||
showComplementary = this.state.showComplementary,
|
||||
showComplementaryButton = !this.state.showComplementary && complementary
|
||||
|
||||
return (
|
||||
<ul className="references">
|
||||
{[
|
||||
...official.map(this.renderRef),
|
||||
official.length == 0 ? (
|
||||
<li id="noOfficialReferences">
|
||||
<Trans>Pas de sources officielles</Trans>
|
||||
</li>
|
||||
) : null,
|
||||
...(showComplementaryButton
|
||||
? [
|
||||
<li id="complementary" key="compl">
|
||||
<a
|
||||
href="#/"
|
||||
onClick={() => this.setState({ showComplementary: true })}>
|
||||
<i className="fa fa-eye" aria-hidden="true" />
|
||||
<Trans>afficher les sources complémentaires</Trans>
|
||||
</a>
|
||||
</li>
|
||||
]
|
||||
: []),
|
||||
...(showComplementary ? complementary.map(this.renderRef) : [])
|
||||
]}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
renderRef = ([name, link]) => {
|
||||
let refKey = this.findRefKey(link),
|
||||
refData = (refKey && references[refKey]) || {},
|
||||
domain = this.cleanDomain(link)
|
||||
return (
|
||||
<ul className="references">
|
||||
{[
|
||||
...official.map(this.renderRef),
|
||||
official.length == 0 ? (
|
||||
<li id="noOfficialReferences">
|
||||
<Trans>Pas de sources officielles</Trans>
|
||||
</li>
|
||||
) : null,
|
||||
...(showComplementaryButton
|
||||
? [
|
||||
<li id="complementary" key="compl">
|
||||
<a
|
||||
href="#/"
|
||||
onClick={() =>
|
||||
this.setState({ showComplementary: true })
|
||||
}>
|
||||
<i className="fa fa-eye" aria-hidden="true" />
|
||||
<Trans>afficher les sources complémentaires</Trans>
|
||||
</a>
|
||||
</li>
|
||||
]
|
||||
: []),
|
||||
...(showComplementary ? complementary.map(this.renderRef) : [])
|
||||
]}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
renderRef = ([name, link]) => {
|
||||
let refKey = this.findRefKey(link),
|
||||
refData = (refKey && references[refKey]) || {},
|
||||
domain = this.cleanDomain(link)
|
||||
|
||||
return (
|
||||
<li key={name}>
|
||||
<span className="imageWrapper">
|
||||
{refData.image && (
|
||||
<img
|
||||
src={require('Règles/ressources/références/' + refData.image)}
|
||||
/>
|
||||
)}
|
||||
</span>
|
||||
<a href={link} target="_blank">
|
||||
{capitalise0(name)}
|
||||
</a>
|
||||
<span className="url">{domain}</span>
|
||||
</li>
|
||||
)
|
||||
return (
|
||||
<li key={name}>
|
||||
<span className="imageWrapper">
|
||||
{refData.image && (
|
||||
<img
|
||||
src={require('Règles/ressources/références/' + refData.image)}
|
||||
/>
|
||||
)}
|
||||
</span>
|
||||
<a href={link} target="_blank">
|
||||
{capitalise0(name)}
|
||||
</a>
|
||||
<span className="url">{domain}</span>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
findRefKey(link) {
|
||||
return Object.keys(references).find(r => link.indexOf(r) > -1)
|
||||
}
|
||||
cleanDomain(link) {
|
||||
return (link.indexOf('://') > -1
|
||||
? link.split('/')[2]
|
||||
: link.split('/')[0]
|
||||
).replace('www.', '')
|
||||
}
|
||||
}
|
||||
findRefKey(link) {
|
||||
return Object.keys(references).find(r => link.indexOf(r) > -1)
|
||||
}
|
||||
cleanDomain(link) {
|
||||
return (link.indexOf('://') > -1
|
||||
? link.split('/')[2]
|
||||
: link.split('/')[0]
|
||||
).replace('www.', '')
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -7,10 +7,10 @@ import {
|
|||
findRuleByDottedName,
|
||||
findRuleByNamespace
|
||||
} from 'Engine/rules'
|
||||
import { isEmpty } from 'ramda'
|
||||
import { compose, isEmpty } from 'ramda'
|
||||
import React, { Component } from 'react'
|
||||
import Helmet from 'react-helmet'
|
||||
import { Trans, translate } from 'react-i18next'
|
||||
import { Trans, withI18n } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { reduxForm } from 'redux-form'
|
||||
|
@ -26,112 +26,115 @@ import RuleHeader from './Header'
|
|||
import References from './References'
|
||||
import './Rule.css'
|
||||
|
||||
@connect((state, props) => ({
|
||||
currentExample: state.currentExample,
|
||||
flatRules: flatRulesSelector(state),
|
||||
valuesToShow: !noUserInputSelector(state),
|
||||
analysedRule: ruleAnalysisSelector(state, props),
|
||||
analysedExample: exampleAnalysisSelector(state, props)
|
||||
}))
|
||||
@translate()
|
||||
@withLanguage
|
||||
class Rule extends Component {
|
||||
render() {
|
||||
let {
|
||||
dottedName,
|
||||
currentExample,
|
||||
flatRules,
|
||||
valuesToShow,
|
||||
analysedExample,
|
||||
analysedRule,
|
||||
language
|
||||
} = this.props,
|
||||
flatRule = findRuleByDottedName(flatRules, dottedName)
|
||||
export default compose(
|
||||
connect((state, props) => ({
|
||||
currentExample: state.currentExample,
|
||||
flatRules: flatRulesSelector(state),
|
||||
valuesToShow: !noUserInputSelector(state),
|
||||
analysedRule: ruleAnalysisSelector(state, props),
|
||||
analysedExample: exampleAnalysisSelector(state, props)
|
||||
})),
|
||||
withI18n(),
|
||||
withLanguage
|
||||
)(
|
||||
class Rule extends Component {
|
||||
render() {
|
||||
let {
|
||||
dottedName,
|
||||
currentExample,
|
||||
flatRules,
|
||||
valuesToShow,
|
||||
analysedExample,
|
||||
analysedRule,
|
||||
language
|
||||
} = this.props,
|
||||
flatRule = findRuleByDottedName(flatRules, dottedName)
|
||||
|
||||
let { type, name, title, description, question, ns, icon } = flatRule,
|
||||
namespaceRules = findRuleByNamespace(flatRules, dottedName)
|
||||
let { type, name, title, description, question, ns, icon } = flatRule,
|
||||
namespaceRules = findRuleByNamespace(flatRules, dottedName)
|
||||
|
||||
let displayedRule = analysedExample || analysedRule
|
||||
let showValues = valuesToShow || currentExample
|
||||
let displayedRule = analysedExample || analysedRule
|
||||
let showValues = valuesToShow || currentExample
|
||||
|
||||
return (
|
||||
<div id="rule" className="ui__ container">
|
||||
<Helmet>
|
||||
<title>{title}</title>
|
||||
<meta name="description" content={description} />
|
||||
</Helmet>
|
||||
<RuleHeader
|
||||
{...{
|
||||
ns,
|
||||
type,
|
||||
description,
|
||||
question,
|
||||
flatRule,
|
||||
flatRules,
|
||||
name,
|
||||
title,
|
||||
icon
|
||||
}}
|
||||
/>
|
||||
return (
|
||||
<div id="rule" className="ui__ container">
|
||||
<Helmet>
|
||||
<title>{title}</title>
|
||||
<meta name="description" content={description} />
|
||||
</Helmet>
|
||||
<RuleHeader
|
||||
{...{
|
||||
ns,
|
||||
type,
|
||||
description,
|
||||
question,
|
||||
flatRule,
|
||||
flatRules,
|
||||
name,
|
||||
title,
|
||||
icon
|
||||
}}
|
||||
/>
|
||||
|
||||
<section id="rule-content">
|
||||
{displayedRule.nodeValue ? (
|
||||
<div id="ruleValue">
|
||||
<i className="fa fa-calculator" aria-hidden="true" />{' '}
|
||||
{displayedRule.format === 'euros' || displayedRule.formule
|
||||
? Intl.NumberFormat(language, {
|
||||
style: 'currency',
|
||||
currency: 'EUR'
|
||||
}).format(displayedRule.nodeValue)
|
||||
: typeof displayedRule.nodeValue !== 'object'
|
||||
<section id="rule-content">
|
||||
{displayedRule.nodeValue ? (
|
||||
<div id="ruleValue">
|
||||
<i className="fa fa-calculator" aria-hidden="true" />{' '}
|
||||
{displayedRule.format === 'euros' || displayedRule.formule
|
||||
? Intl.NumberFormat(language, {
|
||||
style: 'currency',
|
||||
currency: 'EUR'
|
||||
}).format(displayedRule.nodeValue)
|
||||
: typeof displayedRule.nodeValue !== 'object'
|
||||
? displayedRule.nodeValue
|
||||
: null}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{displayedRule.defaultValue != null &&
|
||||
typeof displayedRule.defaultValue !== 'object' ? (
|
||||
<div id="ruleDefault">
|
||||
Valeur par défaut : {displayedRule.defaultValue}
|
||||
</div>
|
||||
) : null}
|
||||
{displayedRule.defaultValue != null &&
|
||||
typeof displayedRule.defaultValue !== 'object' ? (
|
||||
<div id="ruleDefault">
|
||||
Valeur par défaut : {displayedRule.defaultValue}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{//flatRule.question &&
|
||||
// Fonctionnalité intéressante, à implémenter correctement
|
||||
false && <UserInput {...{ flatRules, dottedName }} />}
|
||||
{flatRule.ns && (
|
||||
<Algorithm rule={displayedRule} showValues={showValues} />
|
||||
)}
|
||||
{flatRule.note && (
|
||||
<section id="notes">
|
||||
<h3>Note: </h3>
|
||||
{createMarkdownDiv(flatRule.note)}
|
||||
</section>
|
||||
)}
|
||||
<Examples
|
||||
currentExample={currentExample}
|
||||
situationExists={valuesToShow}
|
||||
rule={displayedRule}
|
||||
/>
|
||||
{!isEmpty(namespaceRules) && (
|
||||
<NamespaceRulesList {...{ namespaceRules }} />
|
||||
)}
|
||||
{this.renderReferences(flatRule)}
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
{//flatRule.question &&
|
||||
// Fonctionnalité intéressante, à implémenter correctement
|
||||
false && <UserInput {...{ flatRules, dottedName }} />}
|
||||
{flatRule.ns && (
|
||||
<Algorithm rule={displayedRule} showValues={showValues} />
|
||||
)}
|
||||
{flatRule.note && (
|
||||
<section id="notes">
|
||||
<h3>Note: </h3>
|
||||
{createMarkdownDiv(flatRule.note)}
|
||||
</section>
|
||||
)}
|
||||
<Examples
|
||||
currentExample={currentExample}
|
||||
situationExists={valuesToShow}
|
||||
rule={displayedRule}
|
||||
/>
|
||||
{!isEmpty(namespaceRules) && (
|
||||
<NamespaceRulesList {...{ namespaceRules }} />
|
||||
)}
|
||||
{this.renderReferences(flatRule)}
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
renderReferences = ({ références: refs }) =>
|
||||
refs ? (
|
||||
<div>
|
||||
<h2>
|
||||
<Trans>Références</Trans>
|
||||
</h2>
|
||||
<References refs={refs} />
|
||||
</div>
|
||||
) : null
|
||||
}
|
||||
|
||||
renderReferences = ({ références: refs }) =>
|
||||
refs ? (
|
||||
<div>
|
||||
<h2>
|
||||
<Trans>Références</Trans>
|
||||
</h2>
|
||||
<References refs={refs} />
|
||||
</div>
|
||||
) : null
|
||||
}
|
||||
)
|
||||
|
||||
let NamespaceRulesList = withColours(({ namespaceRules, colours }) => (
|
||||
<section>
|
||||
|
@ -155,15 +158,14 @@ let NamespaceRulesList = withColours(({ namespaceRules, colours }) => (
|
|||
</section>
|
||||
))
|
||||
|
||||
@reduxForm({
|
||||
const UserInput = reduxForm({
|
||||
form: 'conversation',
|
||||
destroyOnUnmount: false
|
||||
})
|
||||
class UserInput extends Component {
|
||||
render() {
|
||||
let { flatRules, dottedName } = this.props
|
||||
return getInputComponent(flatRules)(dottedName)
|
||||
})(
|
||||
class UserInput extends Component {
|
||||
render() {
|
||||
let { flatRules, dottedName } = this.props
|
||||
return getInputComponent(flatRules)(dottedName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Rule
|
||||
)
|
||||
|
|
|
@ -16,15 +16,15 @@ let RuleValueVignette = ({ name, title, nodeValue: ruleValue }) => (
|
|||
</span>
|
||||
)
|
||||
|
||||
@withLanguage
|
||||
export class RuleValue extends Component {
|
||||
render() {
|
||||
let { value, language } = this.props
|
||||
let unsatisfied = value == null,
|
||||
irrelevant = value == 0
|
||||
let [className, text] = irrelevant
|
||||
? ['irrelevant', '0']
|
||||
: unsatisfied
|
||||
export const RuleValue = withLanguage(
|
||||
class RuleValue extends Component {
|
||||
render() {
|
||||
let { value, language } = this.props
|
||||
let unsatisfied = value == null,
|
||||
irrelevant = value == 0
|
||||
let [className, text] = irrelevant
|
||||
? ['irrelevant', '0']
|
||||
: unsatisfied
|
||||
? ['unsatisfied', '']
|
||||
: [
|
||||
'figure',
|
||||
|
@ -35,18 +35,19 @@ export class RuleValue extends Component {
|
|||
minimumFractionDigits: 0
|
||||
}).format(value)
|
||||
]
|
||||
return (
|
||||
<ReactCSSTransitionGroup
|
||||
transitionName="flash"
|
||||
transitionEnterTimeout={100}
|
||||
transitionLeaveTimeout={100}>
|
||||
<span key={text} className="Rule-value">
|
||||
{' '}
|
||||
<span className={className}>{text}</span>
|
||||
</span>
|
||||
</ReactCSSTransitionGroup>
|
||||
)
|
||||
return (
|
||||
<ReactCSSTransitionGroup
|
||||
transitionName="flash"
|
||||
transitionEnterTimeout={100}
|
||||
transitionLeaveTimeout={100}>
|
||||
<span key={text} className="Rule-value">
|
||||
{' '}
|
||||
<span className={className}>{text}</span>
|
||||
</span>
|
||||
</ReactCSSTransitionGroup>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
export default RuleValueVignette
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import withTracker from 'Components/utils/withTracker'
|
||||
import { Component } from 'react'
|
||||
|
||||
@withTracker
|
||||
export default class TrackPageView extends Component {
|
||||
componentDidMount() {
|
||||
this.props.tracker.push(['trackPageView'])
|
||||
export default withTracker(
|
||||
class TrackPageView extends Component {
|
||||
componentDidMount() {
|
||||
this.props.tracker.push(['trackPageView'])
|
||||
}
|
||||
render() {
|
||||
return null
|
||||
}
|
||||
}
|
||||
render() {
|
||||
return null
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
import PropTypes from 'prop-types'
|
||||
import React, { Component } from 'react'
|
||||
import { withI18n } from 'react-i18next'
|
||||
|
||||
export default function withLanguage(WrappedComponent) {
|
||||
return class WithLanguage extends Component {
|
||||
static contextTypes = {
|
||||
i18n: PropTypes.object.isRequired
|
||||
return withI18n()(
|
||||
class WithLanguage extends Component {
|
||||
static displayName = `withLanguage(${Component.displayName ||
|
||||
Component.name})`
|
||||
render() {
|
||||
return (
|
||||
<WrappedComponent
|
||||
{...this.props}
|
||||
language={this.props.i18n.language + ''}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
static displayName = `withLanguage(${Component.displayName ||
|
||||
Component.name})`
|
||||
render() {
|
||||
return (
|
||||
<WrappedComponent
|
||||
{...this.props}
|
||||
language={this.context.i18n.language + ''}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -15,8 +15,8 @@ let treatValue = (data, language) =>
|
|||
data == null
|
||||
? '?'
|
||||
: typeof data == 'boolean'
|
||||
? { true: '✅', false: '✘' }[data]
|
||||
: formatNumber(data, language)
|
||||
? { true: '✅', false: '✘' }[data]
|
||||
: formatNumber(data, language)
|
||||
|
||||
export let formatNumber = (data, language) =>
|
||||
!isNaN(data)
|
||||
|
@ -80,28 +80,29 @@ export function InlineMecanism({ name }) {
|
|||
}
|
||||
|
||||
// Un élément du graphe de calcul qui a une valeur interprétée (à afficher)
|
||||
@connect(state => ({ flatRules: flatRulesSelector(state) }))
|
||||
export class Leaf extends Component {
|
||||
render() {
|
||||
let { classes, dottedName, name, value, flatRules, filter } = this.props,
|
||||
rule = findRuleByDottedName(flatRules, dottedName)
|
||||
export const Leaf = connect(state => ({ flatRules: flatRulesSelector(state) }))(
|
||||
class Leaf extends Component {
|
||||
render() {
|
||||
let { classes, dottedName, name, value, flatRules, filter } = this.props,
|
||||
rule = findRuleByDottedName(flatRules, dottedName)
|
||||
|
||||
return (
|
||||
<span className={classNames(classes, 'leaf')}>
|
||||
{dottedName && (
|
||||
<span className="nodeHead">
|
||||
<Link to={'../règle/' + encodeRuleName(dottedName)}>
|
||||
<span className="name">
|
||||
{rule.title || capitalise0(name)} {filter}
|
||||
<NodeValuePointer data={value} />
|
||||
</span>
|
||||
</Link>
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
return (
|
||||
<span className={classNames(classes, 'leaf')}>
|
||||
{dottedName && (
|
||||
<span className="nodeHead">
|
||||
<Link to={'../règle/' + encodeRuleName(dottedName)}>
|
||||
<span className="name">
|
||||
{rule.title || capitalise0(name)} {filter}
|
||||
<NodeValuePointer data={value} />
|
||||
</span>
|
||||
</Link>
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
export function SimpleRuleLink({ rule: { dottedName, title, name } }) {
|
||||
return (
|
||||
|
|
|
@ -21,7 +21,6 @@ let lang =
|
|||
setToSessionStorage('lang', lang)
|
||||
i18next.init(
|
||||
{
|
||||
debug: true,
|
||||
lng: lang,
|
||||
resources: {
|
||||
en: {
|
||||
|
|
|
@ -522,3 +522,11 @@ privacyContent: >
|
|||
</2>
|
||||
<3>You can opt out below.</3>
|
||||
Vie privée: Privacy
|
||||
|
||||
Nom: Name
|
||||
Activité principale: Main activity
|
||||
Adresse: Address
|
||||
Ville: City
|
||||
Région: Region
|
||||
Nombre d'employés: Number of employees
|
||||
Date de création: Creation date
|
||||
|
|
|
@ -3,32 +3,33 @@ import { SliderPicker } from 'react-color'
|
|||
import { connect } from 'react-redux'
|
||||
import Home from './Home'
|
||||
|
||||
@connect(
|
||||
export default connect(
|
||||
state => ({ couleur: state.themeColours.colour }),
|
||||
dispatch => ({
|
||||
changeColour: colour => dispatch({ type: 'CHANGE_THEME_COLOUR', colour })
|
||||
})
|
||||
)
|
||||
export default class Couleur extends React.Component {
|
||||
changeColour = ({ hex }) => this.props.changeColour(hex)
|
||||
render() {
|
||||
return (
|
||||
<div className="ui__ container">
|
||||
<p className="indication">
|
||||
Visualisez sur cette page l’apparence du module pour différentes
|
||||
couleurs principales.
|
||||
</p>
|
||||
<SliderPicker
|
||||
color={this.props.couleur}
|
||||
onChangeComplete={this.changeColour}
|
||||
/>
|
||||
<p className="indication">
|
||||
La couleur sélectionnée, à déclarer comme attribut
|
||||
"data-couleur" du script sur votre page est :{' '}
|
||||
<b>{this.props.couleur}</b>
|
||||
</p>
|
||||
<Home />
|
||||
</div>
|
||||
)
|
||||
)(
|
||||
class Couleur extends React.Component {
|
||||
changeColour = ({ hex }) => this.props.changeColour(hex)
|
||||
render() {
|
||||
return (
|
||||
<div className="ui__ container">
|
||||
<p className="indication">
|
||||
Visualisez sur cette page l’apparence du module pour différentes
|
||||
couleurs principales.
|
||||
</p>
|
||||
<SliderPicker
|
||||
color={this.props.couleur}
|
||||
onChangeComplete={this.changeColour}
|
||||
/>
|
||||
<p className="indication">
|
||||
La couleur sélectionnée, à déclarer comme attribut
|
||||
"data-couleur" du script sur votre page est :{' '}
|
||||
<b>{this.props.couleur}</b>
|
||||
</p>
|
||||
<Home />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
// Page listing the engine's currently implemented mecanisms and their tests
|
||||
import React, { Component } from 'react'
|
||||
import './ExampleSituations.css'
|
||||
import examples from 'Règles/cas-types.yaml'
|
||||
import { analyseMany } from 'Engine/traverse'
|
||||
import { connect } from 'react-redux'
|
||||
import {
|
||||
ruleDefaultsSelector,
|
||||
parsedRulesSelector
|
||||
} from 'Selectors/analyseSelectors'
|
||||
import withColours from 'Components/utils/withColours'
|
||||
import { analyseMany } from 'Engine/traverse'
|
||||
import { compose } from 'ramda'
|
||||
import React, { Component } from 'react'
|
||||
import emoji from 'react-easy-emoji'
|
||||
import { connect } from 'react-redux'
|
||||
import examples from 'Règles/cas-types.yaml'
|
||||
import {
|
||||
parsedRulesSelector,
|
||||
ruleDefaultsSelector
|
||||
} from 'Selectors/analyseSelectors'
|
||||
import './ExampleSituations.css'
|
||||
|
||||
class ExampleSituations extends Component {
|
||||
export default class ExampleSituations extends Component {
|
||||
render() {
|
||||
return (
|
||||
<div className="ui__ container" id="exampleSituations">
|
||||
|
@ -28,69 +29,71 @@ class ExampleSituations extends Component {
|
|||
)
|
||||
}
|
||||
}
|
||||
@connect(state => ({
|
||||
defaults: ruleDefaultsSelector(state),
|
||||
parsedRules: parsedRulesSelector(state)
|
||||
}))
|
||||
@withColours
|
||||
class Example extends Component {
|
||||
render() {
|
||||
let {
|
||||
ex: { nom, situation },
|
||||
parsedRules,
|
||||
defaults,
|
||||
colours
|
||||
} = this.props,
|
||||
[total, net, netAprèsImpôts] = analyseMany(parsedRules, [
|
||||
'total',
|
||||
'net',
|
||||
'net après impôt'
|
||||
])(dottedName => ({ ...defaults, ...situation }[dottedName])).targets,
|
||||
figures = [
|
||||
total,
|
||||
do {
|
||||
let dottedName = 'contrat salarié . salaire . brut de base'
|
||||
;({
|
||||
dottedName,
|
||||
nodeValue: situation[dottedName],
|
||||
title: 'Salaire brut'
|
||||
})
|
||||
},
|
||||
net,
|
||||
{ ...netAprèsImpôts, title: 'Après impôt' }
|
||||
]
|
||||
|
||||
return (
|
||||
<li className="example">
|
||||
<h2>{nom}</h2>
|
||||
<ul>
|
||||
{figures.map(t => (
|
||||
<li key={t.dottedName}>
|
||||
<h3>{t.title}</h3>
|
||||
const Example = compose(
|
||||
connect(state => ({
|
||||
defaults: ruleDefaultsSelector(state),
|
||||
parsedRules: parsedRulesSelector(state)
|
||||
})),
|
||||
withColours
|
||||
)(
|
||||
class Example extends Component {
|
||||
render() {
|
||||
let {
|
||||
ex: { nom, situation },
|
||||
parsedRules,
|
||||
defaults,
|
||||
colours
|
||||
} = this.props,
|
||||
[total, net, netAprèsImpôts] = analyseMany(parsedRules, [
|
||||
'total',
|
||||
'net',
|
||||
'net après impôt'
|
||||
])(dottedName => ({ ...defaults, ...situation }[dottedName])).targets,
|
||||
figures = [
|
||||
total,
|
||||
do {
|
||||
let dottedName = 'contrat salarié . salaire . brut de base'
|
||||
;({
|
||||
dottedName,
|
||||
nodeValue: situation[dottedName],
|
||||
title: 'Salaire brut'
|
||||
})
|
||||
},
|
||||
net,
|
||||
{ ...netAprèsImpôts, title: 'Après impôt' }
|
||||
]
|
||||
|
||||
return (
|
||||
<li className="example">
|
||||
<h2>{nom}</h2>
|
||||
<ul>
|
||||
{figures.map(t => (
|
||||
<li key={t.dottedName}>
|
||||
<h3>{t.title}</h3>
|
||||
<span
|
||||
style={{ color: colours.textColourOnWhite }}
|
||||
className="figure">
|
||||
{Math.round(t.nodeValue)} €
|
||||
</span>
|
||||
</li>
|
||||
))}{' '}
|
||||
<li key="%">
|
||||
<h3>Prélèvements</h3>
|
||||
<span
|
||||
style={{ color: colours.textColourOnWhite }}
|
||||
className="figure">
|
||||
{Math.round(t.nodeValue)} €
|
||||
{do {
|
||||
let de = figures[0].nodeValue,
|
||||
à = figures[3].nodeValue
|
||||
Math.round(((de - à) / de) * 100)
|
||||
}}{' '}
|
||||
%
|
||||
</span>
|
||||
</li>
|
||||
))}{' '}
|
||||
<li key="%">
|
||||
<h3>Prélèvements</h3>
|
||||
<span
|
||||
style={{ color: colours.textColourOnWhite }}
|
||||
className="figure">
|
||||
{do {
|
||||
let de = figures[0].nodeValue,
|
||||
à = figures[3].nodeValue
|
||||
Math.round(((de - à) / de) * 100)
|
||||
}}{' '}
|
||||
%
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
)
|
||||
</ul>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default ExampleSituations
|
||||
)
|
||||
|
|
|
@ -1,58 +1,60 @@
|
|||
import LangSwitcher from 'Components/LangSwitcher'
|
||||
import React, { Component } from 'react'
|
||||
import { translate } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import { withRouter } from 'react-router'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { withI18n } from 'react-i18next'
|
||||
import Logo from '../images/logo/logo-simulateur.svg'
|
||||
import './Header.css'
|
||||
import { compose } from 'ramda';
|
||||
|
||||
@withRouter
|
||||
@translate()
|
||||
export class Header extends Component {
|
||||
state = {
|
||||
mobileNavVisible: false
|
||||
}
|
||||
togglemobileNavVisible = () =>
|
||||
this.setState({ mobileNavVisible: !this.state.mobileNavVisible })
|
||||
export const Header = compose(
|
||||
withRouter,
|
||||
withI18n()
|
||||
)(
|
||||
class Header extends Component {
|
||||
state = {
|
||||
mobileNavVisible: false
|
||||
}
|
||||
togglemobileNavVisible = () =>
|
||||
this.setState({ mobileNavVisible: !this.state.mobileNavVisible })
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div id="header">
|
||||
<Link id="brand" to="/">
|
||||
<img id="logo" src={Logo} alt="Un service de l'État français" />
|
||||
<h1>
|
||||
Simulateur
|
||||
<br />
|
||||
d'embauche
|
||||
</h1>
|
||||
</Link>
|
||||
<div id="headerRight">
|
||||
<nav className={this.state.mobileNavVisible ? 'visible' : ''}>
|
||||
<Links toggle={this.togglemobileNavVisible} />
|
||||
</nav>
|
||||
<LangSwitcher className="menu-item ui__ link-button" />
|
||||
<span id="menuButton">
|
||||
{this.state.mobileNavVisible ? (
|
||||
<i
|
||||
className="fa fa-times"
|
||||
aria-hidden="true"
|
||||
onClick={this.togglemobileNavVisible}
|
||||
/>
|
||||
) : (
|
||||
<i
|
||||
className="fa fa-bars"
|
||||
aria-hidden="true"
|
||||
onClick={this.togglemobileNavVisible}
|
||||
/>
|
||||
)}
|
||||
</span>
|
||||
render() {
|
||||
return (
|
||||
<div id="header">
|
||||
<Link id="brand" to="/">
|
||||
<img id="logo" src={Logo} alt="Un service de l'État français" />
|
||||
<h1>
|
||||
Simulateur
|
||||
<br />
|
||||
d'embauche
|
||||
</h1>
|
||||
</Link>
|
||||
<div id="headerRight">
|
||||
<nav className={this.state.mobileNavVisible ? 'visible' : ''}>
|
||||
<Links toggle={this.togglemobileNavVisible} />
|
||||
</nav>
|
||||
<LangSwitcher className="menu-item ui__ link-button" />
|
||||
<span id="menuButton">
|
||||
{this.state.mobileNavVisible ? (
|
||||
<i
|
||||
className="fa fa-times"
|
||||
aria-hidden="true"
|
||||
onClick={this.togglemobileNavVisible}
|
||||
/>
|
||||
) : (
|
||||
<i
|
||||
className="fa fa-bars"
|
||||
aria-hidden="true"
|
||||
onClick={this.togglemobileNavVisible}
|
||||
/>
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
)
|
||||
let Links = ({ toggle }) => (
|
||||
<div id="links" onClick={toggle}>
|
||||
<Link className="menu-item" to="/exemples">
|
||||
|
|
|
@ -7,10 +7,9 @@ import URSSAF from 'Images/urssaf.svg'
|
|||
import './Home.css'
|
||||
import { inIframe } from '../../../utils'
|
||||
import emoji from 'react-easy-emoji'
|
||||
import translate from 'react-i18next/dist/commonjs/translate'
|
||||
import withLanguage from 'Components/utils/withLanguage'
|
||||
|
||||
const Home = translate()(
|
||||
const Home =
|
||||
withLanguage(({ language }) => (
|
||||
<div id="home" className="ui__ container">
|
||||
<PreviousSimulationBanner />
|
||||
|
@ -66,6 +65,5 @@ const Home = translate()(
|
|||
</p>
|
||||
</div>
|
||||
))
|
||||
)
|
||||
|
||||
export default Home
|
||||
|
|
|
@ -1,29 +1,28 @@
|
|||
import LangSwitcher from 'Components/LangSwitcher'
|
||||
import React, { Component } from 'react'
|
||||
import { Trans, translate } from 'react-i18next'
|
||||
import emoji from 'react-easy-emoji'
|
||||
import { Trans, withI18n } from 'react-i18next'
|
||||
import screenfull from 'screenfull'
|
||||
import emoji from 'react-easy-emoji';
|
||||
import { isIE } from '../../../utils';
|
||||
import { isIE } from '../../../utils'
|
||||
|
||||
@translate()
|
||||
export default class IframeFooter extends Component {
|
||||
componentDidMount() {
|
||||
screenfull.enabled && screenfull.onchange(() => this.forceUpdate())
|
||||
}
|
||||
export default withI18n()(
|
||||
class IframeFooter extends Component {
|
||||
componentDidMount() {
|
||||
screenfull.enabled && screenfull.onchange(() => this.forceUpdate())
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div
|
||||
className="ui__ container"
|
||||
style={{
|
||||
textAlign: 'right',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between'
|
||||
}}>
|
||||
<LangSwitcher className="ui__ button simple" />
|
||||
{screenfull.enabled &&
|
||||
!screenfull.isFullscreen && !isIE() && (
|
||||
render() {
|
||||
return (
|
||||
<div
|
||||
className="ui__ container"
|
||||
style={{
|
||||
textAlign: 'right',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between'
|
||||
}}>
|
||||
<LangSwitcher className="ui__ button simple" />
|
||||
{screenfull.enabled && !screenfull.isFullscreen && !isIE() && (
|
||||
<button
|
||||
className="ui__ button small"
|
||||
onClick={() => {
|
||||
|
@ -33,11 +32,12 @@ export default class IframeFooter extends Component {
|
|||
<Trans>Plein écran</Trans>
|
||||
</button>
|
||||
)}
|
||||
<button className="ui__ button small" onClick={() =>window.print()} >
|
||||
{emoji('🖨')}
|
||||
<Trans>Imprimer</Trans>
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
<button className="ui__ button small" onClick={() => window.print()}>
|
||||
{emoji('🖨')}
|
||||
<Trans>Imprimer</Trans>
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
import React, { Component } from 'react'
|
||||
import { withRouter } from 'react-router'
|
||||
|
||||
@withRouter
|
||||
export default class IntegrationTest extends Component {
|
||||
componentDidMount() {
|
||||
const script = document.createElement('script')
|
||||
script.id = 'script-simulateur-embauche'
|
||||
script['data-couleur'] = script.src =
|
||||
window.location.origin + '/dist/simulateur.js'
|
||||
script.dataset.couleur = '#2975D1'
|
||||
script.dataset.iframeUrl =
|
||||
window.location.origin + this.props.history.createHref({})
|
||||
this.DOMNode.appendChild(script)
|
||||
export default withRouter(
|
||||
class IntegrationTest extends Component {
|
||||
componentDidMount() {
|
||||
const script = document.createElement('script')
|
||||
script.id = 'script-simulateur-embauche'
|
||||
script['data-couleur'] = script.src =
|
||||
window.location.origin + '/dist/simulateur.js'
|
||||
script.dataset.couleur = '#2975D1'
|
||||
script.dataset.iframeUrl =
|
||||
window.location.origin + this.props.history.createHref({})
|
||||
this.DOMNode.appendChild(script)
|
||||
}
|
||||
render() {
|
||||
return <div ref={ref => (this.DOMNode = ref)} />
|
||||
}
|
||||
}
|
||||
render() {
|
||||
return <div ref={ref => (this.DOMNode = ref)} />
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -5,21 +5,22 @@ import 'react-select/dist/react-select.css'
|
|||
import { flatRulesSelector } from 'Selectors/analyseSelectors'
|
||||
import './RulesList.css'
|
||||
|
||||
@connect(state => ({
|
||||
export default connect(state => ({
|
||||
flatRules: flatRulesSelector(state)
|
||||
}))
|
||||
export default class RulesList extends Component {
|
||||
render() {
|
||||
let { flatRules } = this.props
|
||||
return (
|
||||
<div id="RulesList" className="ui__ container">
|
||||
<h1>Explorez notre base de règles</h1>
|
||||
<SearchBar
|
||||
showDefaultList={true}
|
||||
rules={flatRules}
|
||||
rulePagesBasePath="règle"
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}))(
|
||||
class RulesList extends Component {
|
||||
render() {
|
||||
let { flatRules } = this.props
|
||||
return (
|
||||
<div id="RulesList" className="ui__ container">
|
||||
<h1>Explorez notre base de règles</h1>
|
||||
<SearchBar
|
||||
showDefaultList={true}
|
||||
rules={flatRules}
|
||||
rulePagesBasePath="règle"
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -3,7 +3,7 @@ import { defaultTracker } from 'Components/utils/withTracker'
|
|||
import createRavenMiddleware from 'raven-for-redux'
|
||||
import Raven from 'raven-js'
|
||||
import React, { Component } from 'react'
|
||||
import { translate } from 'react-i18next'
|
||||
import { withI18n } from 'react-i18next'
|
||||
import { Route, Switch } from 'react-router-dom'
|
||||
import 'Ui/index.css'
|
||||
import Provider from '../../Provider'
|
||||
|
@ -68,7 +68,7 @@ class InFranceRoute extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
let RouterSwitch = translate()(() => {
|
||||
let RouterSwitch = withI18n()(() => {
|
||||
const paths = sitePaths()
|
||||
return (
|
||||
<Switch>
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
/* @flow */
|
||||
|
||||
import PageFeedback from 'Components/Feedback/PageFeedback'
|
||||
import LegalNotice from 'Components/LegalNotice'
|
||||
import withColours from 'Components/utils/withColours'
|
||||
|
@ -6,7 +8,7 @@ import { compose } from 'ramda'
|
|||
import React from 'react'
|
||||
import emoji from 'react-easy-emoji'
|
||||
import Helmet from 'react-helmet'
|
||||
import { Trans, translate } from 'react-i18next'
|
||||
import { Trans, withI18n } from 'react-i18next'
|
||||
import { withRouter } from 'react-router'
|
||||
import i18n from '../../../../i18n'
|
||||
import { feedbackBlacklist } from '../../config'
|
||||
|
@ -80,5 +82,5 @@ const Footer = ({ colours: { colour } }) => {
|
|||
export default compose(
|
||||
withRouter,
|
||||
withColours,
|
||||
translate()
|
||||
withI18n()
|
||||
)(Footer)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import { React, T } from 'Components'
|
||||
import { compose } from 'ramda'
|
||||
import emoji from 'react-easy-emoji'
|
||||
import { translate } from 'react-i18next'
|
||||
import { withI18n } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import { NavLink, withRouter } from 'react-router-dom'
|
||||
import selectors from 'Selectors/progressSelectors'
|
||||
|
@ -235,7 +235,7 @@ const StepsHeader = ({
|
|||
|
||||
export default compose(
|
||||
withRouter,
|
||||
translate(),
|
||||
withI18n(),
|
||||
connect(
|
||||
state => ({
|
||||
...selectors(state),
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
import { React, T } from 'Components'
|
||||
import withTracker from 'Components/utils/withTracker'
|
||||
import { compose } from 'ramda'
|
||||
import { translate } from 'react-i18next'
|
||||
import { withI18n } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import { NavLink, withRouter } from 'react-router-dom'
|
||||
import selectors from 'Selectors/progressSelectors'
|
||||
|
@ -87,5 +87,5 @@ export default compose(
|
|||
selectors,
|
||||
{}
|
||||
),
|
||||
translate()
|
||||
withI18n()
|
||||
)(StepsHeader)
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
/* @flow */
|
||||
import { React, T } from 'Components'
|
||||
import { ScrollToTop } from 'Components/utils/Scroll'
|
||||
import { translate } from 'react-i18next'
|
||||
import { compose } from 'ramda'
|
||||
import { withI18n } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import { Link } from 'react-router-dom'
|
||||
import Animate from 'Ui/animate'
|
||||
|
@ -25,7 +26,7 @@ const AfterRegistration = ({ t, companyStatusChoice }: Props) => (
|
|||
Une fois que votre{' '}
|
||||
{{
|
||||
companyStatusChoice:
|
||||
companyStatusChoice || t('après.entreprise', 'entreprise')
|
||||
companyStatusChoice || t(['après.entreprise', 'entreprise'])
|
||||
}}{' '}
|
||||
aura été créée, vous recevrez les informations suivantes :
|
||||
</T>
|
||||
|
@ -93,6 +94,9 @@ const AfterRegistration = ({ t, companyStatusChoice }: Props) => (
|
|||
</Animate.fromBottom>
|
||||
)
|
||||
|
||||
export default connect(state => ({
|
||||
companyStatusChoice: state.inFranceApp.companyStatusChoice
|
||||
}))(translate()(AfterRegistration))
|
||||
export default compose(
|
||||
connect(state => ({
|
||||
companyStatusChoice: state.inFranceApp.companyStatusChoice
|
||||
})),
|
||||
withI18n()
|
||||
)(AfterRegistration)
|
||||
|
|
|
@ -8,7 +8,7 @@ import { React, T } from 'Components'
|
|||
import Scroll from 'Components/utils/Scroll'
|
||||
import { compose } from 'ramda'
|
||||
import Helmet from 'react-helmet'
|
||||
import { translate } from 'react-i18next'
|
||||
import { withI18n } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import { Link } from 'react-router-dom'
|
||||
import * as Animate from 'Ui/animate'
|
||||
|
@ -388,7 +388,7 @@ const CreateCompany = ({
|
|||
)
|
||||
}
|
||||
export default compose(
|
||||
translate(),
|
||||
withI18n(),
|
||||
connect(
|
||||
state => ({
|
||||
companyCreationChecklist: state.inFranceApp.companyCreationChecklist,
|
||||
|
|
|
@ -3,7 +3,7 @@ import { defineDirectorStatus } from 'Actions/companyStatusActions'
|
|||
import { React, T } from 'Components'
|
||||
import { compose } from 'ramda'
|
||||
import Helmet from 'react-helmet'
|
||||
import { translate } from 'react-i18next'
|
||||
import { withI18n } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import { SkipButton } from 'Ui/Button'
|
||||
import type { DirectorStatus } from 'Types/companyTypes'
|
||||
|
@ -76,7 +76,7 @@ const DefineDirectorStatus = ({ defineDirectorStatus, t }: Props) => (
|
|||
)
|
||||
|
||||
export default compose(
|
||||
translate(),
|
||||
withI18n(),
|
||||
connect(
|
||||
null,
|
||||
{ defineDirectorStatus }
|
||||
|
|
|
@ -3,7 +3,7 @@ import { saveExistingCompanyDetails } from 'Actions/existingCompanyActions'
|
|||
import { React, T } from 'Components'
|
||||
import { compose } from 'ramda'
|
||||
import Helmet from 'react-helmet'
|
||||
import { translate } from 'react-i18next'
|
||||
import { withI18n } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import { withRouter } from 'react-router'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
@ -121,5 +121,5 @@ export default compose(
|
|||
onCompanyDetailsConfirmation: saveExistingCompanyDetails
|
||||
}
|
||||
),
|
||||
translate()
|
||||
withI18n()
|
||||
)(Search)
|
||||
|
|
|
@ -3,7 +3,7 @@ import { chooseCompanyLiability } from 'Actions/companyStatusActions'
|
|||
import { React, T } from 'Components'
|
||||
import { compose } from 'ramda'
|
||||
import Helmet from 'react-helmet'
|
||||
import { translate } from 'react-i18next'
|
||||
import { withI18n } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import { SkipButton } from 'Ui/Button'
|
||||
import type { CompanyLiability } from 'Types/companyTypes'
|
||||
|
@ -116,7 +116,7 @@ const Liability = ({
|
|||
)
|
||||
|
||||
export default compose(
|
||||
translate(),
|
||||
withI18n(),
|
||||
connect(
|
||||
state => ({
|
||||
multipleAssociates:
|
||||
|
|
|
@ -3,7 +3,7 @@ import { companyIsMicroenterprise } from 'Actions/companyStatusActions'
|
|||
import { React, T } from 'Components'
|
||||
import { compose } from 'ramda'
|
||||
import Helmet from 'react-helmet'
|
||||
import { translate } from 'react-i18next'
|
||||
import { withI18n } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import { SkipButton } from 'Ui/Button'
|
||||
import type { TFunction } from 'react-i18next'
|
||||
|
@ -101,7 +101,7 @@ const Microenterprise = ({ companyIsMicroenterprise, t }: Props) => (
|
|||
)
|
||||
|
||||
export default compose(
|
||||
translate(),
|
||||
withI18n(),
|
||||
connect(
|
||||
null,
|
||||
{ companyIsMicroenterprise }
|
||||
|
|
|
@ -3,7 +3,7 @@ import { directorIsInAMinority } from 'Actions/companyStatusActions'
|
|||
import { React, T } from 'Components'
|
||||
import { compose } from 'ramda'
|
||||
import Helmet from 'react-helmet'
|
||||
import { translate } from 'react-i18next'
|
||||
import { withI18n } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import { SkipButton } from 'Ui/Button'
|
||||
import type { TFunction } from 'react-i18next'
|
||||
|
@ -72,7 +72,7 @@ const MinorityDirector = ({ directorIsInAMinority, t }: Props) => (
|
|||
)
|
||||
|
||||
export default compose(
|
||||
translate(),
|
||||
withI18n(),
|
||||
connect(
|
||||
null,
|
||||
{ directorIsInAMinority }
|
||||
|
|
|
@ -4,7 +4,7 @@ import Helmet from 'react-helmet'
|
|||
import { connect } from 'react-redux'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { possibleStatusSelector } from 'Selectors/companyStatusSelectors'
|
||||
import {translate} from 'react-i18next';
|
||||
import { withI18n } from 'react-i18next';
|
||||
import StatusDescription from './StatusDescription'
|
||||
import type { RouterHistory } from 'react-router'
|
||||
import {compose} from 'ramda'
|
||||
|
@ -23,7 +23,7 @@ type Props = {
|
|||
t: TFunction
|
||||
}
|
||||
|
||||
const StatusButton = translate()(({ status, t }: { status: LegalStatus, t: TFunction }) => (
|
||||
const StatusButton = withI18n()(({ status, t }: { status: LegalStatus, t: TFunction }) => (
|
||||
<Link to={sitePaths().entreprise.créer(status)} className="ui__ button">
|
||||
<T>Créer une</T> {t(status)}
|
||||
</Link>
|
||||
|
@ -143,7 +143,7 @@ const SetMainStatus = ({ history, possibleStatus, t, language }: Props) => {
|
|||
</>
|
||||
)
|
||||
}
|
||||
export default compose(translate(), withLanguage, connect(
|
||||
export default compose(withI18n(), withLanguage, connect(
|
||||
state => ({ possibleStatus: possibleStatusSelector(state) }),
|
||||
{ setMainStatus }
|
||||
))(SetMainStatus)
|
||||
|
|
|
@ -3,20 +3,22 @@
|
|||
import { React, T } from 'Components'
|
||||
import withLanguage from 'Components/utils/withLanguage'
|
||||
import { toPairs } from 'ramda'
|
||||
import { withI18n } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import { Link, Redirect } from 'react-router-dom'
|
||||
import sitePaths from '../../sitePaths'
|
||||
import type { ResetExistingCompanyDetailsAction } from 'Types/companyTypes'
|
||||
import type { TFunction } from 'react-i18next'
|
||||
|
||||
let companyDataSelection = {
|
||||
l1_normalisee: 'Name',
|
||||
libelle_activite_principale: 'Main activity',
|
||||
l4_normalisee: 'Street',
|
||||
l6_normalisee: 'City',
|
||||
libelle_region: 'Region',
|
||||
libelle_tranche_effectif_salarie_entreprise: 'Number of employees',
|
||||
date_creation: 'Creation date'
|
||||
}
|
||||
let companyDataSelection = t => ({
|
||||
l1_normalisee: t('Nom'),
|
||||
libelle_activite_principale: t('Activité principale'),
|
||||
l4_normalisee: t('Adresse'),
|
||||
l6_normalisee: t('Ville'),
|
||||
libelle_region: t('Région'),
|
||||
libelle_tranche_effectif_salarie_entreprise: t("Nombre d'employés"),
|
||||
date_creation: t('Date de création')
|
||||
})
|
||||
|
||||
const YYYYMMDDToDate = (date: string): Date =>
|
||||
new Date(date.replace(/^([\d]{4})([\d]{2})([\d]{2})$/, '$1/$2/$3'))
|
||||
|
@ -36,14 +38,15 @@ const LocaleDate = withLanguage(
|
|||
}).format(date)
|
||||
)
|
||||
|
||||
export const CompanyDetails = (data: { [string]: string }) => {
|
||||
return (
|
||||
<ul>
|
||||
{toPairs(data).map(
|
||||
([key, value]) =>
|
||||
companyDataSelection[key] != null ? (
|
||||
export const CompanyDetails = withI18n()(
|
||||
({ t, ...data }: { t: TFunction, [string]: string }) => {
|
||||
const localizedCompanyDataSelection = companyDataSelection(t)
|
||||
return (
|
||||
<ul>
|
||||
{toPairs(data).map(([key, value]) =>
|
||||
localizedCompanyDataSelection[key] != null ? (
|
||||
<li key={key}>
|
||||
<strong>{companyDataSelection[key]}</strong>
|
||||
<strong>{localizedCompanyDataSelection[key]}</strong>
|
||||
<br />
|
||||
{key === 'date_creation' ? (
|
||||
<LocaleDate date={YYYYMMDDToDate(value)} />
|
||||
|
@ -52,10 +55,11 @@ export const CompanyDetails = (data: { [string]: string }) => {
|
|||
)}
|
||||
</li>
|
||||
) : null
|
||||
)}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
)}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
const YourCompany = ({ companyDetails, resetCompanyDetails }) => (
|
||||
<>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react'
|
||||
import { translate } from 'react-i18next'
|
||||
import { withI18n } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import { Redirect, Route, Switch } from 'react-router'
|
||||
import * as Animate from 'Ui/animate'
|
||||
|
@ -107,4 +107,4 @@ const CreateMyCompany = ({
|
|||
export default connect(state => ({
|
||||
companyStatusChoice: state.inFranceApp.companyStatusChoice,
|
||||
existingCompany: state.inFranceApp.existingCompanyDetails
|
||||
}))(translate()(CreateMyCompany))
|
||||
}))(withI18n()(CreateMyCompany))
|
||||
|
|
|
@ -6,7 +6,7 @@ import {
|
|||
import { React, T } from 'Components'
|
||||
import { compose } from 'ramda'
|
||||
import Helmet from 'react-helmet'
|
||||
import { translate } from 'react-i18next'
|
||||
import { withI18n } from 'react-i18next'
|
||||
import { connect } from 'react-redux'
|
||||
import { Link } from 'react-router-dom'
|
||||
import Animate from 'Ui/animate'
|
||||
|
@ -198,7 +198,9 @@ const HiringProcess = ({
|
|||
</li>
|
||||
<li>Remettre la fiche de paie à votre employé</li>
|
||||
</ul>
|
||||
<Link className="ui__ button" to={sitePaths().sécuritéSociale + '/simulation'}>
|
||||
<Link
|
||||
className="ui__ button"
|
||||
to={sitePaths().sécuritéSociale + '/simulation'}>
|
||||
Obtenir un exemple de fiche de paie
|
||||
</Link>
|
||||
</T>
|
||||
|
@ -206,7 +208,7 @@ const HiringProcess = ({
|
|||
)
|
||||
|
||||
export default compose(
|
||||
translate(),
|
||||
withI18n(),
|
||||
connect(
|
||||
state => ({ hiringChecklist: state.inFranceApp.hiringChecklist }),
|
||||
{
|
||||
|
|
|
@ -5,7 +5,7 @@ import marianneSvg from 'Images/marianne.svg'
|
|||
import urssafSvg from 'Images/urssaf.svg'
|
||||
import React from 'react'
|
||||
import emoji from 'react-easy-emoji'
|
||||
import { Trans, translate } from 'react-i18next'
|
||||
import { Trans, withI18n } from 'react-i18next'
|
||||
import { Link } from 'react-router-dom'
|
||||
import companySvg from '../images/company.svg'
|
||||
import estimateSvg from '../images/estimate.svg'
|
||||
|
@ -14,7 +14,7 @@ import Footer from '../layout/Footer/Footer'
|
|||
import sitePaths from '../sitePaths'
|
||||
import './Landing.css'
|
||||
|
||||
export default translate()(
|
||||
export default withI18n()(
|
||||
withColours(({ colours: { colour } }) => (
|
||||
<>
|
||||
<header className="landing__header">
|
||||
|
|
|
@ -4,7 +4,7 @@ import { Component, React, T } from 'Components'
|
|||
import Simulateur from 'Components/Simu'
|
||||
import { ScrollToTop } from 'Components/utils/Scroll'
|
||||
import Helmet from 'react-helmet'
|
||||
import { translate } from 'react-i18next'
|
||||
import { withI18n } from 'react-i18next'
|
||||
import * as Animate from 'Ui/animate'
|
||||
import type { Match, Location } from 'react-router'
|
||||
import type { TFunction } from 'react-i18next'
|
||||
|
@ -82,4 +82,4 @@ class SocialSecurity extends Component<Props, {}> {
|
|||
}
|
||||
}
|
||||
|
||||
export default translate()(SocialSecurity)
|
||||
export default withI18n()(SocialSecurity)
|
||||
|
|
Loading…
Reference in New Issue