Skip to content

Commit

Permalink
Merge pull request #151 from betagouv/recalcul-immédiat
Browse files Browse the repository at this point in the history
Recalcul immédiat
  • Loading branch information
laem authored Jan 30, 2018
2 parents ad8fbd6 + 48d9dca commit 92389f8
Show file tree
Hide file tree
Showing 13 changed files with 183 additions and 87 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"nearley": "^2.9.2",
"npm": "^5.3.0",
"ramda": "^0.25.0",
"rc-progress": "^2.2.5",
"react": "^16.2.0",
"react-addons-css-transition-group": "^15.6.2",
"react-color": "^2.13.8",
Expand Down
4 changes: 2 additions & 2 deletions source/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// The state keeps track of which of them have been submitted
// The user can also come back to one of his answers and edit it
export const STEP_ACTION = 'STEP_ACTION'
export function stepAction(name, step) {
return { type: STEP_ACTION, name, step }
export function stepAction(name, step, source) {
return { type: STEP_ACTION, name, step, source }
}

export const START_CONVERSATION = 'START_CONVERSATION'
Expand Down
9 changes: 1 addition & 8 deletions source/components/ProgressTip.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#sim .tip {
font-style: italic;
margin-bottom: 1em;
margin-bottom: -0.3em;
text-align: center;
}
#sim .tip p {
Expand All @@ -12,10 +12,3 @@
border-width: 1px;
border-style: solid;
}

progress::-webkit-progress-bar {
background: white;
}

progress::-webkit-progress-value {
}
27 changes: 11 additions & 16 deletions source/components/ProgressTip.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ import React, { Component } from 'react'
import { connect } from 'react-redux'
import { withRouter } from 'react-router'
import './ProgressTip.css'
import { Line } from 'rc-progress'

@withRouter
@connect(state => ({
done: state.done,
foldedSteps: state.foldedSteps,
nextSteps: state.nextSteps,
textColourOnWhite: state.themeColours.textColourOnWhite
colour: state.themeColours.colour
}))
export default class ProgressTip extends Component {
state = {
Expand All @@ -21,7 +22,7 @@ export default class ProgressTip extends Component {
})
}
render() {
let { done, nextSteps, foldedSteps, textColourOnWhite } = this.props,
let { done, nextSteps, foldedSteps, colour } = this.props,
nbQuestions = nextSteps.length
if (!done) return null
return (
Expand All @@ -35,24 +36,18 @@ export default class ProgressTip extends Component {
{nbQuestions === 1
? 'Une dernière question !'
: `Il reste moins de ${nbQuestions} questions`}
<ProgressBar
foldedSteps={foldedSteps}
nbQuestions={nbQuestions}
colour={textColourOnWhite}
<Line
percent={
100 * foldedSteps.length / (foldedSteps.length + nbQuestions)
}
strokeWidth="1"
strokeColor={colour}
trailColor="white"
strokeLinecap="butt"
/>
</p>
)}
</div>
)
}
}

let ProgressBar = ({ foldedSteps, nbQuestions, colour }) => (
<progress
value={foldedSteps.length}
max={foldedSteps.length + nbQuestions}
style={{
borderColor: colour
}}
/>
)
10 changes: 5 additions & 5 deletions source/components/conversation/FormDecorator.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export var FormDecorator = formType => RenderField =>
formValueSelector('conversation')(state, 'inversions.' + dottedName)
}),
dispatch => ({
stepAction: (name, step) => dispatch(stepAction(name, step)),
stepAction: (name, step, source) => dispatch(stepAction(name, step, source)),
setFormValue: (field, value) =>
dispatch(change('conversation', field, value))
})
Expand Down Expand Up @@ -75,11 +75,11 @@ export var FormDecorator = formType => RenderField =>
props passées à ce dernier, car React 15.2 n'aime pas les attributes inconnus
des balises html, <input> dans notre cas.
*/
let submit = () => setTimeout(() => stepAction('fold', fieldName), 1),
//TODO hack, enables redux-form/CHANGE to update the form state before the traverse functions are run
let submit = (cause) => setTimeout(() => stepAction('fold', fieldName, cause), 1),
stepProps = {
...this.props.step,
inverted,
//TODO hack, enables redux-form/CHANGE to update the form state before the traverse functions are run
submit,
setFormValue: (value, name = fieldName) => setFormValue(name, value)
}
Expand Down Expand Up @@ -121,7 +121,7 @@ export var FormDecorator = formType => RenderField =>
<IgnoreStepButton
action={() => {
setFormValue(fieldName, '' + defaultValue)
submit()
submit('ignore')
}}
/>
)}
Expand Down Expand Up @@ -159,7 +159,7 @@ export var FormDecorator = formType => RenderField =>
</span>
<button
className="edit"
onClick={() => stepAction('unfold', dottedName)}
onClick={() => stepAction('unfold', dottedName, 'unfold')}
style={{ color: themeColours.textColourOnWhite }}
>
<i className="fa fa-pencil" aria-hidden="true" />
Expand Down
31 changes: 17 additions & 14 deletions source/components/conversation/Input.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import SendButton from './SendButton'
@FormDecorator('input')
export default class Input extends Component {
state = {
hoverSuggestion: null
lastValue: ''
}
render() {
let {
Expand All @@ -20,7 +20,6 @@ export default class Input extends Component {
answerSuffix = valueType.suffix,
suffixed = answerSuffix != null,
inputError = dirty && error,
{ hoverSuggestion } = this.state,
submitDisabled = !dirty || inputError

return (
Expand All @@ -33,7 +32,6 @@ export default class Input extends Component {
}}
type="text"
{...input}
value={hoverSuggestion != null ? hoverSuggestion : input.value}
className={classnames({ suffixed })}
id={'step-' + dottedName}
{...attributes}
Expand All @@ -42,9 +40,6 @@ export default class Input extends Component {
? { border: '2px dashed #ddd' }
: { border: `1px solid ${themeColours.textColourOnWhite}` }
}
onKeyDown={({ key }) =>
key == 'Enter' && (submitDisabled ? input.onBlur() : submit())
}
/>
{suffixed && (
<label
Expand Down Expand Up @@ -104,7 +99,7 @@ export default class Input extends Component {
)
}
renderSuggestions(themeColours) {
let { setFormValue, submit, suggestions, inverted } = this.props.stepProps
let { setFormValue, suggestions, inverted } = this.props.stepProps

if (!suggestions || inverted) return null
return (
Expand All @@ -114,16 +109,24 @@ export default class Input extends Component {
{toPairs(suggestions).map(([text, value]) => (
<li
key={value}
onClick={e =>
setFormValue('' + value) && submit() && e.preventDefault()
onClick={() => {
this.setState({ lastValue: null })
setFormValue('' + value)
if (this.state.suggestion !== value)
this.setState({ suggestion: value })
else this.props.stepProps.submit('suggestion')
}}
onMouseOver={() => {
this.setState({ lastValue: this.props.input.value })
setFormValue('' + value)
}}
onMouseOut={() =>
this.state.lastValue != null &&
setFormValue('' + this.state.lastValue)
}
onMouseOver={() => this.setState({ hoverSuggestion: value })}
onMouseOut={() => this.setState({ hoverSuggestion: null })}
style={{ color: themeColours.textColourOnWhite }}
>
<a href="#" title="cliquer pour valider">
{text}
</a>
<span title="cliquez pour insérer cette suggestion">{text}</span>
</li>
))}
</ul>
Expand Down
52 changes: 34 additions & 18 deletions source/components/conversation/Question.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { answer, answered } from './userAnswerButtonStyle'
import HoverDecorator from '../HoverDecorator'
import Explicable from './Explicable'
import { pipe, split, reverse, reduce, is } from 'ramda'

import SendButton from './SendButton'
/* 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
Expand All @@ -21,26 +21,37 @@ import { pipe, split, reverse, reduce, is } from 'ramda'
*/

let dottedNameToObject = pipe(
split(' . '),
reverse,
reduce((memo, next) => ({ [next]: memo }), 'oui')
)

// FormDecorator permet de factoriser du code partagé par les différents types de saisie,
// dont Question est un example
@FormDecorator('question')
export default class Question extends Component {
render() {
let { stepProps: { choices } } = this.props

if (is(Array)(choices)) return this.renderBinaryQuestion()
else return this.renderChildren(choices)
let {
stepProps: { choices, submit },
themeColours,
meta: { pristine }
} = this.props
let choiceElements = is(Array)(choices)
? this.renderBinaryQuestion()
: this.renderChildren(choices)
return (
<>
{choiceElements}
<SendButton
{...{
disabled: pristine,
themeColours,
error: false,
submit
}}
/>
</>
)
}
renderBinaryQuestion() {
let {
input, // vient de redux-form
stepProps: { submit, choices },
stepProps: { submit, choices, setFormValue },
themeColours
} = this.props

Expand All @@ -49,7 +60,7 @@ export default class Question extends Component {
{choices.map(({ value, label }) => (
<RadioLabel
key={value}
{...{ value, label, input, submit, themeColours }}
{...{ value, label, input, submit, themeColours, setFormValue }}
/>
))}
</ul>
Expand All @@ -62,7 +73,7 @@ export default class Question extends Component {
themeColours
} = this.props,
{ name } = input,
{ submit } = stepProps,
{ submit, setFormValue } = stepProps,
// seront stockées ainsi dans le state :
// [parent object path]: dotted name relative to parent
relativeDottedName = radioDottedName =>
Expand All @@ -79,7 +90,8 @@ export default class Question extends Component {
input,
submit,
themeColours,
dottedName: null
dottedName: null,
setFormValue
}}
/>
</li>
Expand All @@ -101,7 +113,8 @@ export default class Question extends Component {
dottedName,
input,
submit,
themeColours
themeColours,
setFormValue
}}
/>
</li>
Expand All @@ -120,8 +133,11 @@ let RadioLabel = props => (

@HoverDecorator
class RadioLabelContent extends Component {
click = value => () => {
if (this.props.input.value == value) this.props.submit('dblClick')
}
render() {
let { value, label, input, submit, hover, themeColours } = this.props,
let { value, label, input, hover, themeColours } = this.props,
// value = when(is(Object), prop('value'))(choice),
labelStyle = Object.assign(
value === input.value || hover
Expand All @@ -136,7 +152,7 @@ class RadioLabelContent extends Component {
<input
type="radio"
{...input}
onClick={submit}
onClick={this.click(value)}
value={value}
checked={value === input.value ? 'checked' : ''}
/>
Expand Down
19 changes: 16 additions & 3 deletions source/components/conversation/SendButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,20 @@ import HoverDecorator from 'Components/HoverDecorator'
export default class SendButton extends Component {
getAction() {
let { disabled, submit } = this.props
return () => (!disabled ? submit() : null)
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, themeColours, hover } = this.props
Expand All @@ -18,10 +31,10 @@ export default class SendButton extends Component {
color: themeColours.textColour,
background: themeColours.colour
}}
onClick={this.getAction()}
onClick={(event) => this.getAction()('accept')}
>
<span className="text">valider</span>
<span className="icon">&#10003;</span>
<i className="fa fa-check" aria-hidden="true" />
</button>
<span
className="keyIcon"
Expand Down
Loading

0 comments on commit 92389f8

Please sign in to comment.