diff --git a/package.json b/package.json index 99d0c89df..14e7fc6d6 100644 --- a/package.json +++ b/package.json @@ -12,57 +12,57 @@ }, "dependencies": { "babel-runtime": "^6.23.0", - "classnames": "^2.2.1", + "classnames": "^2.2.5", "deep-assign": "^2.0.0", - "install": "^0.8.2", - "js-yaml": "^3.7.0", + "install": "^0.10.1", + "js-yaml": "^3.8.4", "marked": "^0.3.6", - "nearley": "^2.7.14", - "npm": "^4.4.1", + "nearley": "^2.9.2", + "npm": "^4.6.1", "ramda": "^0.23.0", "react": "^15.5.4", "react-dom": "^15.5.4", - "react-redux": "^5.0.3", + "react-redux": "^5.0.5", "react-router-dom": "^4.1.1", "reduce-reducers": "^0.1.2", "redux": "^3.6.0", - "redux-form": "^6.6.3", - "redux-saga": "^0.14.3", - "reselect": "^2.5.2", - "whatwg-fetch": "^2.0.2" + "redux-form": "^6.7.0", + "redux-saga": "^0.15.3", + "reselect": "^3.0.1", + "whatwg-fetch": "^2.0.3" }, "devDependencies": { - "autoprefixer": "^6.3.3", - "babel": "^6.23.0", - "babel-core": "^6.24.0", - "babel-eslint": "^7.1.1", - "babel-loader": "^6.4.0", - "babel-plugin-transform-class-properties": "^6.23.0", + "autoprefixer": "^7.1.1", + "babel-cli": "^6.23.0", + "babel-core": "^6.24.1", + "babel-eslint": "^7.2.3", + "babel-loader": "^7.0.0", + "babel-plugin-transform-class-properties": "^6.24.1", "babel-plugin-transform-decorators-legacy": "^1.3.4", "babel-plugin-transform-do-expressions": "^6.22.0", "babel-plugin-transform-object-rest-spread": "^6.23.0", "babel-polyfill": "^6.23.0", - "babel-preset-env": "^1.2.1", - "babel-preset-react": "^6.23.0", - "core-js": "^2.2.0", - "css-loader": "^0.27.3", - "eslint": "^3.13.1", - "eslint-plugin-react": "^6.9.0", - "express": "^4.13.3", - "file-loader": "^0.10.1", - "html-loader": "^0.4.2", - "img-loader": "^1.2.2", + "babel-preset-env": "^1.4.0", + "babel-preset-react": "^6.24.1", + "core-js": "^2.4.1", + "css-loader": "^0.28.1", + "eslint": "^3.19.0", + "eslint-plugin-react": "^7.0.1", + "express": "^4.15.3", + "file-loader": "^0.11.1", + "html-loader": "^0.4.5", + "img-loader": "^2.0.0", "json-loader": "^0.5.4", "nearley-loader": "0.0.2", - "postcss-loader": "^1.2.2", + "postcss-loader": "^2.0.5", "react-hot-loader": "^3.0.0-beta.6", - "redux-devtools": "^3.2.0", - "redux-devtools-dock-monitor": "^1.1.1", - "redux-devtools-log-monitor": "^1.0.9", - "style-loader": "^0.13.0", - "url-loader": "^0.5.7", - "webpack": "^2.2.1", - "webpack-dev-server": "^2.4.2", + "redux-devtools": "^3.4.0", + "redux-devtools-dock-monitor": "^1.1.2", + "redux-devtools-log-monitor": "^1.3.0", + "style-loader": "^0.17.0", + "url-loader": "^0.5.8", + "webpack": "^2.5.1", + "webpack-dev-server": "^2.4.5", "yaml-loader": "^0.4.0" }, "scripts": { diff --git a/source/.eslintrc b/source/.eslintrc.yaml similarity index 93% rename from source/.eslintrc rename to source/.eslintrc.yaml index d69429c45..bf550be7c 100644 --- a/source/.eslintrc +++ b/source/.eslintrc.yaml @@ -13,6 +13,7 @@ rules: no-global-assign: 0 no-unsafe-negation: 0 no-undef: 1 + no-mixed-spaces-and-tabs: 1 react/jsx-uses-vars: 2 react/jsx-uses-react: 2 diff --git a/source/components/CDD.css b/source/components/CDD.css deleted file mode 100644 index fb982f8fb..000000000 --- a/source/components/CDD.css +++ /dev/null @@ -1,44 +0,0 @@ -p { - color: #333; -} - -#sim section { - padding: 2em; -} - -#sim > h1 { - color: #333350; - margin-top: 3%; - text-align: center; - font-size: 350%; - font-weight: 800; -} - - -#conversation { - margin: 3em auto; - font-size: 110%; - line-height: normal; - display: flex; - align-items: flex-start; - min-height: 10em; - max-width: 90%; - max-height: 85%; -} - - -#fin { - margin: 6em auto; - width: 20em; - display: block; - text-align: center; - font-style: italic; -} -#fin p:first-of-type { - font-weight: bold -} - -#questions-answers { - min-width: 50%; - transition: width 1s; -} diff --git a/source/components/Results.css b/source/components/Results.css index 45a878bc6..f87205f85 100644 --- a/source/components/Results.css +++ b/source/components/Results.css @@ -13,7 +13,7 @@ left: 0; box-shadow: 1px -7px 20px 2px #ccc; - /*opacity: 0;*/ + opacity: 0; transform: translateY(12em); transition: transform .5s; transition-delay: .3s; @@ -21,6 +21,7 @@ } #results.show { transform: translateY(0); + opacity: 1; } diff --git a/source/components/Satisfaction.js b/source/components/Satisfaction.js new file mode 100644 index 000000000..74d0bd046 --- /dev/null +++ b/source/components/Satisfaction.js @@ -0,0 +1,81 @@ +import React, {Component} from 'react' +import HoverDecorator from 'Components/HoverDecorator' +import 'whatwg-fetch' +import {connect} from 'react-redux' + +@connect( + state => ({ + sessionId: state.sessionId + }) +) +export default class Satisfaction extends Component { + state = { + answer: false + } + sendSatisfaction(satisfait) { + fetch('https://embauche.beta.gouv.fr/retour-syso', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + fields: { + satisfait, + message: '', //pas de message pour l'instant + date: new Date().toISOString(), + id: this.props.sessionId, + url: document.location.href.toString() + } + }) + }).then(response => { + if (!response.ok) + return console.log('Erreur dans la récolte de la satisfaction') //eslint-disable-line no-console + this.setState({answer: satisfait}) + + }) + } + render() { + let {answer} = this.state + if (answer) + return ( +

+ {answer === ':)' ? 'Une suggestion' : 'Un problème'} ? Envie de discuter ?
+ + Écrivez-nous + +

+ ) + + return ( +

+ Vous êtes satisfait du simulateur ? + {" "} + this.sendSatisfaction(s)}/> + this.sendSatisfaction(s)}/> +

+ ) + } +} + +@HoverDecorator +export class Smiley extends Component { + render() { + return ( + + ) + } +} diff --git a/source/components/Simulateur.css b/source/components/Simulateur.css index 5c92ae1b0..0f798ba63 100644 --- a/source/components/Simulateur.css +++ b/source/components/Simulateur.css @@ -40,7 +40,7 @@ #sim .intro { font-style: italic; font-size: 100%; - margin-bottom: 4%; + margin-bottom: 3%; } #sim .intro > div { margin: 1em 0; @@ -90,6 +90,24 @@ } +#conversation { + margin: 3em auto; + font-size: 110%; + line-height: normal; + display: flex; + align-items: flex-start; + min-height: 10em; + max-width: 90%; + max-height: 85%; +} + + +#questions-answers { + min-width: 50%; + transition: width 1s; +} + + #foldedSteps .header { margin-bottom: 1em; text-align: center; @@ -106,3 +124,41 @@ margin-right: .3em; vertical-align: top } + + + +#fin { + margin: 0 auto; + width: 80%; + display: flex; + align-items: flex-end; + font-style: italic; +} +#fin-text { + width: 50%; + margin-left: 2em; + display: inline-block; +} +#fin p:first-of-type { + font-weight: bold +} +#fin img { + width: 25%; + display: inline-block; +} + + + +.satisfaction-smiley { + color: #4A89DC; + font-size: 90%; + font-weight: bold; + border-radius: 6em; + width: 2em; + text-align: center; + display: inline-block; + border: 2px solid #4A89DC; + margin: 0 .6em; + padding: .3em 0; + transform: rotate(90deg) +} diff --git a/source/components/Simulateur.js b/source/components/Simulateur.js index f6d0e8388..d8f3757bf 100644 --- a/source/components/Simulateur.js +++ b/source/components/Simulateur.js @@ -1,17 +1,17 @@ import React, {Component} from 'react' -import './CDD.css' import {reduxForm, formValueSelector, reset} from 'redux-form' import {connect} from 'react-redux' -import './conversation/conversation.css' import {START_CONVERSATION} from '../actions' -import Aide from './Aide' import R from 'ramda' import {Redirect, Link, withRouter} from 'react-router-dom' -import {createMarkdownDiv} from '../engine/marked' -import './Simulateur.css' +import Aide from './Aide' +import {createMarkdownDiv} from 'Engine/marked' +import {findRuleByName, decodeRuleName} from 'Engine/rules' +import 'Components/conversation/conversation.css' +import 'Components/Simulateur.css' import classNames from 'classnames' -import {findRuleByName, decodeRuleName} from '../engine/rules' import {capitalise0} from '../utils' +import Satisfaction from 'Components/Satisfaction' let situationSelector = formValueSelector('conversation') @@ -27,7 +27,7 @@ let situationSelector = formValueSelector('conversation') }), dispatch => ({ startConversation: rootVariable => dispatch({type: START_CONVERSATION, rootVariable}), - resetForm: rootVariable => dispatch(reset('conversation')) + resetForm: () => dispatch(reset('conversation')) }) ) export default class extends React.Component { @@ -39,7 +39,7 @@ export default class extends React.Component { } } } = this.props, - name = decodeRuleName(encodedName) + name = decodeRuleName(encodedName) this.encodedName = encodedName this.name = name @@ -58,8 +58,8 @@ export default class extends React.Component { sim = path => R.path(R.unless(R.is(Array), R.of)(path))(this.rule.simulateur || {}), reinitalise = () => { - this.props.resetForm(this.name); - this.props.startConversation(this.name); + this.props.resetForm(this.name) + this.props.startConversation(this.name) } @@ -96,7 +96,9 @@ export default class extends React.Component { Pour simplifier, les résultats sont calculés par mois de contrat, et pour un temps complet.

- N'hésitez pas à nous écrire ! La loi française est très ciblée, et donc complexe. Nous pouvons la rendre plus transparente. + N'hésitez pas à nous écrire + + ! La loi française est très ciblée, et donc complexe. Nous pouvons la rendre plus transparente.

@@ -136,7 +138,7 @@ export default class extends React.Component { }} {unfoldedSteps.length == 0 && - } + } @@ -153,15 +155,15 @@ class Conclusion extends Component { return (
-

- Nous n'avons plus de questions : votre simulation est terminée. -

-

- Cliquez sur les obligations en bas pour comprendre vos résultats. -

-

- Une remarque ? Écrivez-nous ! -

+
+

+ Votre simulation est terminée ! +

+

+ N'hésitez pas à modifier vos réponses, ou cliquez sur vos résultats pour comprendre le calcul. +

+ +
) } diff --git a/source/containers/Layout.js b/source/containers/Layout.js index abbe8bb71..95e45e096 100644 --- a/source/containers/Layout.js +++ b/source/containers/Layout.js @@ -2,14 +2,14 @@ import React, { Component } from 'react' import './Layout.css' import './reset.css' import {Link, Route, BrowserRouter as Router, Switch} from 'react-router-dom' -import HomeEmbauche from '../components/HomeEmbauche' -import HomeSyso from '../components/HomeSyso' -import Rule from '../components/rule/Rule' -import Route404 from '../components/Route404' -import Contact from '../components/Contact' -import Simulateur from '../components/Simulateur' -import Results from '../components/Results' -import R from 'ramda' +import HomeEmbauche from 'Components/HomeEmbauche' +import HomeSyso from 'Components/HomeSyso' +import Rule from 'Components/rule/Rule' +import Route404 from 'Components/Route404' +import Contact from 'Components/Contact' +import Simulateur from 'Components/Simulateur' +import Results from 'Components/Results' + export default class Layout extends Component { render() { diff --git a/source/engine/generateQuestions.js b/source/engine/generateQuestions.js index e4665d325..8aeb64301 100644 --- a/source/engine/generateQuestions.js +++ b/source/engine/generateQuestions.js @@ -1,9 +1,9 @@ import React from 'react' -import Explicable from '../components/conversation/Explicable' +import Explicable from 'Components/conversation/Explicable' import R from 'ramda' -import Question from '../components/conversation/Question' -import Input from '../components/conversation/Input' -import formValueTypes from '../components/conversation/formValueTypes' +import Question from 'Components/conversation/Question' +import Input from 'Components/conversation/Input' +import formValueTypes from 'Components/conversation/formValueTypes' import {analyseSituation} from './traverse' import {formValueSelector} from 'redux-form' import { STEP_ACTION, START_CONVERSATION} from '../actions' diff --git a/source/engine/rules.js b/source/engine/rules.js index 3920c0d09..b359392dc 100644 --- a/source/engine/rules.js +++ b/source/engine/rules.js @@ -51,7 +51,7 @@ export let disambiguateRuleReference = ({ns, name}, partialName) => { fragments = ns.split(' . '), // ex. [CDD . événements . rupture] pathPossibilities = // -> [ [CDD . événements . rupture], [CDD . événements], [CDD] ] R.range(0, fragments.length + 1) - .map(nbEl => R.take(nbEl)(fragments)) + .map(nbEl => R.take(nbEl)(fragments)) .reverse(), found = R.reduce((res, path) => R.when( diff --git a/source/entry.js b/source/entry.js index e3776fdcc..e596c39b9 100644 --- a/source/entry.js +++ b/source/entry.js @@ -1,26 +1,17 @@ import React from 'react' import { render } from 'react-dom' -import { compose, createStore, applyMiddleware } from 'redux' +import { compose, createStore } from 'redux' import App from './containers/App' import reducers from './reducers' import DevTools from './DevTools' import { AppContainer } from 'react-hot-loader' -import createSagaMiddleware from 'redux-saga' -import rootSaga from './sagas' - -const sagaMiddleware = createSagaMiddleware() - -const createFinalStore = compose( - // Enables your middleware: - applyMiddleware(sagaMiddleware), // any Redux middleware, e.g. redux-thunk - // Provides support for DevTools: - DevTools.instrument() -)(createStore) - - -const store = createFinalStore(reducers) -sagaMiddleware.run(rootSaga) +let store = createStore( + reducers, + compose( + DevTools.instrument() + ) +) let anchor = document.querySelector('#js') @@ -29,7 +20,7 @@ render( anchor ) -// Hot react component reloading. Unstable but helpful. +// Hot react component reloading. Unstable but helpful. if (module.hot) { module.hot.accept('./containers/App', () => { // If you use Webpack 2 in ES modules mode, you can diff --git a/source/reducers.js b/source/reducers.js index 6e1b6af1f..7a62410dc 100644 --- a/source/reducers.js +++ b/source/reducers.js @@ -40,6 +40,7 @@ function pointedOutObjectives(state=[], {type, objectives}) { export default reduceReducers( combineReducers({ + sessionId: (id = Math.floor(Math.random() * 1000000000000) + '') => id, // this is handled by redux-form, pas touche ! form: formReducer, diff --git a/source/sagas.js b/source/sagas.js deleted file mode 100644 index f22dab87b..000000000 --- a/source/sagas.js +++ /dev/null @@ -1,16 +0,0 @@ -import { takeEvery} from 'redux-saga/effects' -// import { call, put} from 'redux-saga/effects' -// import Promise from 'core-js/fn/promise' - -// Nothing happening here ! - -function* handleSubmitStep() { -} - -function* watchSteps() { - yield* takeEvery('SUBMIT_STEP', handleSubmitStep) -} - -export default function* rootSaga() { - yield [ watchSteps() ] -} diff --git a/source/webpack.config.js b/source/webpack.config.js index fa4bd0a2d..cf4c6ccff 100644 --- a/source/webpack.config.js +++ b/source/webpack.config.js @@ -7,6 +7,7 @@ module.exports = { devtool: 'cheap-module-source-map', entry: prodEnv ? [ 'babel-polyfill', + 'whatwg-fetch', './source/entry.js' ] : [ 'webpack-dev-server/client?http://localhost:3000/', @@ -23,7 +24,8 @@ module.exports = { resolve: { alias: { Engine: path.resolve('source/engine/'), - Règles: path.resolve('règles/') + Règles: path.resolve('règles/'), + Components: path.resolve('source/components/') } }, module: { @@ -70,10 +72,7 @@ module.exports = { }, plugins: [ new webpack.EnvironmentPlugin({ NODE_ENV: 'development' }), - new webpack.NoEmitOnErrorsPlugin(), - new webpack.ProvidePlugin({ - 'fetch': 'imports?this=>global!exports?global.fetch!whatwg-fetch', - }), + new webpack.NoEmitOnErrorsPlugin() ] .concat(!prodEnv ? [new webpack.HotModuleReplacementPlugin()] : []) .concat(prodEnv ? [new webpack.optimize.UglifyJsPlugin()] : []),