Ajout d'un formulaire de retour à la fin de la conversation
parent
c46e609ed5
commit
51783e64ab
68
package.json
68
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": {
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 (
|
||||
<p>
|
||||
{answer === ':)' ? 'Une suggestion' : 'Un problème'} ? Envie de discuter ? <br/>
|
||||
<a href={"mailto:contact@embauche.beta.gouv.fr?subject=Suggestion pour le simulateur " + this.props.simu}>
|
||||
Écrivez-nous <i className="fa fa-envelope-open-o" aria-hidden="true" style={{margin: '0 .3em'}}></i>
|
||||
</a>
|
||||
</p>
|
||||
)
|
||||
|
||||
return (
|
||||
<p id="satisfaction">
|
||||
Vous êtes satisfait du simulateur ?
|
||||
{" "}
|
||||
<Smiley text=":)" hoverColor="#16a085" clicked={s => this.sendSatisfaction(s)}/>
|
||||
<Smiley text=":|" hoverColor="#f39c12" clicked={s => this.sendSatisfaction(s)}/>
|
||||
</p>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@HoverDecorator
|
||||
export class Smiley extends Component {
|
||||
render() {
|
||||
return (
|
||||
<button
|
||||
onClick={() => this.props.clicked(this.props.text)}
|
||||
className="satisfaction-smiley"
|
||||
style={
|
||||
this.props.hover
|
||||
? {
|
||||
background: this.props.hoverColor,
|
||||
color: "white",
|
||||
borderColor: "transparent"
|
||||
}
|
||||
: {}
|
||||
}
|
||||
>
|
||||
{this.props.text}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
</p>
|
||||
<p>
|
||||
N'hésitez pas à nous écrire <Link to="/contact"><i className="fa fa-envelope-open-o" aria-hidden="true" style={{margin: '0 .3em'}}></i></Link> ! La loi française est très ciblée, et donc complexe. Nous pouvons la rendre plus transparente.
|
||||
N'hésitez pas à nous écrire <Link to="/contact">
|
||||
<i className="fa fa-envelope-open-o" aria-hidden="true" style={{margin: '0 .3em'}}></i>
|
||||
</Link> ! La loi française est très ciblée, et donc complexe. Nous pouvons la rendre plus transparente.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -136,7 +138,7 @@ export default class extends React.Component {
|
|||
}}
|
||||
</div>
|
||||
{unfoldedSteps.length == 0 &&
|
||||
<Conclusion />}
|
||||
<Conclusion simu={this.name}/>}
|
||||
</div>
|
||||
<Aide />
|
||||
</div>
|
||||
|
@ -153,15 +155,15 @@ class Conclusion extends Component {
|
|||
return (
|
||||
<div id="fin">
|
||||
<img src={require('../images/fin.png')} />
|
||||
<p>
|
||||
Nous n'avons plus de questions : votre simulation est terminée.
|
||||
</p>
|
||||
<p>
|
||||
Cliquez sur les obligations en bas pour comprendre vos résultats.
|
||||
</p>
|
||||
<p>
|
||||
Une remarque ? <Link to="/contact">Écrivez-nous !</Link>
|
||||
</p>
|
||||
<div id="fin-text">
|
||||
<p>
|
||||
Votre simulation est terminée !
|
||||
</p>
|
||||
<p>
|
||||
N'hésitez pas à modifier vos réponses, ou cliquez sur vos résultats pour comprendre le calcul.
|
||||
</p>
|
||||
<Satisfaction simu={this.props.simu}/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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() ]
|
||||
}
|
|
@ -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()] : []),
|
||||
|
|
Loading…
Reference in New Issue