Skip to content
Snippets Groups Projects
Unverified Commit cd6de7f0 authored by Paul Kaplan's avatar Paul Kaplan Committed by GitHub
Browse files

Merge pull request #871 from paulkaplan/ask-answer-events

Wire up ask/answer components to the stage
parents db58669f 0e4b0995
No related branches found
No related tags found
No related merge requests found
@import "../../css/units.css";
@import "../../css/colors.css";
.question-wrapper {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
}
.question-container {
margin: $space;
border: 1px solid $form-border;
border-radius: $space;
border-width: 2px;
padding: 1rem;
background: white;
}
.question-label {
font-size: 0.75rem;
font-weight: bold;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
color: $text-primary;
padding-bottom: $space;
}
.question-input {
display: flex; /* Keeps the input from going outside this container */
position: relative;
}
.question-submit-button {
position: absolute;
top: calc($space / 2);
right: calc($space / 2);
width: calc(2rem - $space);
height: calc(2rem - $space);
border: none;
border-radius: 100%;
color: white;
background: $motion-primary;
}
/* Input overrides: width, font-weight, focus outline and padding */
.question-input > input {
width: 100%;
padding: 0 2rem 0 0.75rem; /* To make room for the submit button */
font-weight: normal;
}
.question-input > input:focus {
box-shadow: 0px 0px 0px 3px $motion-transparent;
}
import PropTypes from 'prop-types';
import React from 'react';
import styles from './question.css';
import Input from '../forms/input.jsx';
const QuestionComponent = props => {
const {
answer,
question,
onChange,
onClick,
onKeyPress
} = props;
return (
<div className={styles.questionWrapper}>
<div className={styles.questionContainer}>
{question ? (
<div className={styles.questionLabel}>{question}</div>
) : null}
<div className={styles.questionInput}>
<Input
autoFocus
value={answer}
onChange={onChange}
onKeyPress={onKeyPress}
/>
<button
className={styles.questionSubmitButton}
onClick={onClick}
>
✔︎
</button>
</div>
</div>
</div>
);
};
QuestionComponent.propTypes = {
answer: PropTypes.string,
onChange: PropTypes.func.isRequired,
onClick: PropTypes.func.isRequired,
onKeyPress: PropTypes.func.isRequired,
question: PropTypes.string
};
export default QuestionComponent;
...@@ -5,6 +5,7 @@ import classNames from 'classnames'; ...@@ -5,6 +5,7 @@ import classNames from 'classnames';
import Box from '../box/box.jsx'; import Box from '../box/box.jsx';
import Loupe from '../loupe/loupe.jsx'; import Loupe from '../loupe/loupe.jsx';
import MonitorList from '../../containers/monitor-list.jsx'; import MonitorList from '../../containers/monitor-list.jsx';
import Question from '../../containers/question.jsx';
import styles from './stage.css'; import styles from './stage.css';
const StageComponent = props => { const StageComponent = props => {
...@@ -15,6 +16,8 @@ const StageComponent = props => { ...@@ -15,6 +16,8 @@ const StageComponent = props => {
colorInfo, colorInfo,
onDeactivateColorPicker, onDeactivateColorPicker,
isColorPicking, isColorPicking,
question,
onQuestionAnswered,
...boxProps ...boxProps
} = props; } = props;
return ( return (
...@@ -40,6 +43,12 @@ const StageComponent = props => { ...@@ -40,6 +43,12 @@ const StageComponent = props => {
<Loupe colorInfo={colorInfo} /> <Loupe colorInfo={colorInfo} />
</Box> </Box>
) : null} ) : null}
{question === null ? null : (
<Question
question={question}
onQuestionAnswered={onQuestionAnswered}
/>
)}
</Box> </Box>
{isColorPicking ? ( {isColorPicking ? (
<Box <Box
...@@ -56,6 +65,8 @@ StageComponent.propTypes = { ...@@ -56,6 +65,8 @@ StageComponent.propTypes = {
height: PropTypes.number, height: PropTypes.number,
isColorPicking: PropTypes.bool, isColorPicking: PropTypes.bool,
onDeactivateColorPicker: PropTypes.func, onDeactivateColorPicker: PropTypes.func,
onQuestionAnswered: PropTypes.func,
question: PropTypes.string,
width: PropTypes.number width: PropTypes.number
}; };
StageComponent.defaultProps = { StageComponent.defaultProps = {
......
import PropTypes from 'prop-types';
import React from 'react';
import bindAll from 'lodash.bindall';
import QuestionComponent from '../components/question/question.jsx';
class Question extends React.Component {
constructor (props) {
super(props);
bindAll(this, [
'handleChange',
'handleKeyPress',
'handleSubmit'
]);
this.state = {
answer: ''
};
}
handleChange (e) {
this.setState({answer: e.target.value});
}
handleKeyPress (event) {
if (event.key === 'Enter') this.handleSubmit();
}
handleSubmit () {
this.props.onQuestionAnswered(this.state.answer);
}
render () {
return (
<QuestionComponent
answer={this.state.answer}
question={this.props.question}
onChange={this.handleChange}
onClick={this.handleSubmit}
onKeyPress={this.handleKeyPress}
/>
);
}
}
Question.propTypes = {
onQuestionAnswered: PropTypes.func.isRequired,
question: PropTypes.string
};
export default Question;
...@@ -24,12 +24,14 @@ class Stage extends React.Component { ...@@ -24,12 +24,14 @@ class Stage extends React.Component {
'cancelMouseDownTimeout', 'cancelMouseDownTimeout',
'detachMouseEvents', 'detachMouseEvents',
'handleDoubleClick', 'handleDoubleClick',
'handleQuestionAnswered',
'onMouseUp', 'onMouseUp',
'onMouseMove', 'onMouseMove',
'onMouseDown', 'onMouseDown',
'onStartDrag', 'onStartDrag',
'onStopDrag', 'onStopDrag',
'updateRect', 'updateRect',
'questionListener',
'setCanvas' 'setCanvas'
]); ]);
this.state = { this.state = {
...@@ -38,7 +40,8 @@ class Stage extends React.Component { ...@@ -38,7 +40,8 @@ class Stage extends React.Component {
isDragging: false, isDragging: false,
dragOffset: null, dragOffset: null,
dragId: null, dragId: null,
colorInfo: null colorInfo: null,
question: null
}; };
} }
componentDidMount () { componentDidMount () {
...@@ -47,12 +50,14 @@ class Stage extends React.Component { ...@@ -47,12 +50,14 @@ class Stage extends React.Component {
this.updateRect(); this.updateRect();
this.renderer = new Renderer(this.canvas); this.renderer = new Renderer(this.canvas);
this.props.vm.attachRenderer(this.renderer); this.props.vm.attachRenderer(this.renderer);
this.props.vm.runtime.addListener('QUESTION', this.questionListener);
} }
shouldComponentUpdate (nextProps, nextState) { shouldComponentUpdate (nextProps, nextState) {
return this.props.width !== nextProps.width || return this.props.width !== nextProps.width ||
this.props.height !== nextProps.height || this.props.height !== nextProps.height ||
this.props.isColorPicking !== nextProps.isColorPicking || this.props.isColorPicking !== nextProps.isColorPicking ||
this.state.colorInfo !== nextState.colorInfo; this.state.colorInfo !== nextState.colorInfo ||
this.state.question !== nextState.question;
} }
componentDidUpdate (prevProps) { componentDidUpdate (prevProps) {
if (this.props.isColorPicking && !prevProps.isColorPicking) { if (this.props.isColorPicking && !prevProps.isColorPicking) {
...@@ -66,6 +71,14 @@ class Stage extends React.Component { ...@@ -66,6 +71,14 @@ class Stage extends React.Component {
this.detachRectEvents(); this.detachRectEvents();
this.stopColorPickingLoop(); this.stopColorPickingLoop();
} }
questionListener (question) {
this.setState({question: question});
}
handleQuestionAnswered (answer) {
this.setState({question: null}, () => {
this.props.vm.runtime.emit('ANSWER', answer);
});
}
startColorPickingLoop () { startColorPickingLoop () {
this.intervalId = setInterval(() => { this.intervalId = setInterval(() => {
this.setState({colorInfo: this.getColorInfo(this.pickX, this.pickY)}); this.setState({colorInfo: this.getColorInfo(this.pickX, this.pickY)});
...@@ -251,7 +264,9 @@ class Stage extends React.Component { ...@@ -251,7 +264,9 @@ class Stage extends React.Component {
<StageComponent <StageComponent
canvasRef={this.setCanvas} canvasRef={this.setCanvas}
colorInfo={this.state.colorInfo} colorInfo={this.state.colorInfo}
question={this.state.question}
onDoubleClick={this.handleDoubleClick} onDoubleClick={this.handleDoubleClick}
onQuestionAnswered={this.handleQuestionAnswered}
{...props} {...props}
/> />
); );
......
...@@ -336,12 +336,12 @@ const control = ` ...@@ -336,12 +336,12 @@ const control = `
</shadow> </shadow>
</value> </value>
</block> </block>
<block type="control_forever"/> <block id="forever" type="control_forever"/>
${blockSeparator} ${blockSeparator}
<block type="control_if"/> <block type="control_if"/>
<block type="control_if_else"/> <block type="control_if_else"/>
<block type="control_wait_until"/> <block id="wait_until" type="control_wait_until"/>
<block type="control_repeat_until"/> <block id="repeat_until" type="control_repeat_until"/>
${blockSeparator} ${blockSeparator}
<block type="control_stop"/> <block type="control_stop"/>
${blockSeparator} ${blockSeparator}
...@@ -382,7 +382,7 @@ const sensing = ` ...@@ -382,7 +382,7 @@ const sensing = `
</value> </value>
</block> </block>
${blockSeparator} ${blockSeparator}
<block type="sensing_askandwait"> <block id="askandwait" type="sensing_askandwait">
<value name="QUESTION"> <value name="QUESTION">
<shadow type="text"> <shadow type="text">
<field name="TEXT">What's your name?</field> <field name="TEXT">What's your name?</field>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment