Merge pull request #871 from paulkaplan/ask-answer-events
Wire up ask/answer components to the stage
This commit is contained in:
6 files changed
+181
-6
No files matched your search
@@ -0,0 +1,57 @@
|
||||
@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;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
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';
|
||||
import Box from '../box/box.jsx';
|
||||
import Loupe from '../loupe/loupe.jsx';
|
||||
import MonitorList from '../../containers/monitor-list.jsx';
|
||||
import Question from '../../containers/question.jsx';
|
||||
import styles from './stage.css';
|
||||
|
||||
const StageComponent = props => {
|
||||
@@ -15,6 +16,8 @@ const StageComponent = props => {
|
||||
colorInfo,
|
||||
onDeactivateColorPicker,
|
||||
isColorPicking,
|
||||
question,
|
||||
onQuestionAnswered,
|
||||
...boxProps
|
||||
} = props;
|
||||
return (
|
||||
@@ -40,6 +43,12 @@ const StageComponent = props => {
|
||||
<Loupe colorInfo={colorInfo} />
|
||||
</Box>
|
||||
) : null}
|
||||
{question === null ? null : (
|
||||
<Question
|
||||
question={question}
|
||||
onQuestionAnswered={onQuestionAnswered}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
{isColorPicking ? (
|
||||
<Box
|
||||
@@ -56,6 +65,8 @@ StageComponent.propTypes = {
|
||||
height: PropTypes.number,
|
||||
isColorPicking: PropTypes.bool,
|
||||
onDeactivateColorPicker: PropTypes.func,
|
||||
onQuestionAnswered: PropTypes.func,
|
||||
question: PropTypes.string,
|
||||
width: PropTypes.number
|
||||
};
|
||||
StageComponent.defaultProps = {
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
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 {
|
||||
'cancelMouseDownTimeout',
|
||||
'detachMouseEvents',
|
||||
'handleDoubleClick',
|
||||
'handleQuestionAnswered',
|
||||
'onMouseUp',
|
||||
'onMouseMove',
|
||||
'onMouseDown',
|
||||
'onStartDrag',
|
||||
'onStopDrag',
|
||||
'updateRect',
|
||||
'questionListener',
|
||||
'setCanvas'
|
||||
]);
|
||||
this.state = {
|
||||
@@ -38,7 +40,8 @@ class Stage extends React.Component {
|
||||
isDragging: false,
|
||||
dragOffset: null,
|
||||
dragId: null,
|
||||
colorInfo: null
|
||||
colorInfo: null,
|
||||
question: null
|
||||
};
|
||||
}
|
||||
componentDidMount () {
|
||||
@@ -47,12 +50,14 @@ class Stage extends React.Component {
|
||||
this.updateRect();
|
||||
this.renderer = new Renderer(this.canvas);
|
||||
this.props.vm.attachRenderer(this.renderer);
|
||||
this.props.vm.runtime.addListener('QUESTION', this.questionListener);
|
||||
}
|
||||
shouldComponentUpdate (nextProps, nextState) {
|
||||
return this.props.width !== nextProps.width ||
|
||||
this.props.height !== nextProps.height ||
|
||||
this.props.isColorPicking !== nextProps.isColorPicking ||
|
||||
this.state.colorInfo !== nextState.colorInfo;
|
||||
this.state.colorInfo !== nextState.colorInfo ||
|
||||
this.state.question !== nextState.question;
|
||||
}
|
||||
componentDidUpdate (prevProps) {
|
||||
if (this.props.isColorPicking && !prevProps.isColorPicking) {
|
||||
@@ -66,6 +71,14 @@ class Stage extends React.Component {
|
||||
this.detachRectEvents();
|
||||
this.stopColorPickingLoop();
|
||||
}
|
||||
questionListener (question) {
|
||||
this.setState({question: question});
|
||||
}
|
||||
handleQuestionAnswered (answer) {
|
||||
this.setState({question: null}, () => {
|
||||
this.props.vm.runtime.emit('ANSWER', answer);
|
||||
});
|
||||
}
|
||||
startColorPickingLoop () {
|
||||
this.intervalId = setInterval(() => {
|
||||
this.setState({colorInfo: this.getColorInfo(this.pickX, this.pickY)});
|
||||
@@ -251,7 +264,9 @@ class Stage extends React.Component {
|
||||
<StageComponent
|
||||
canvasRef={this.setCanvas}
|
||||
colorInfo={this.state.colorInfo}
|
||||
question={this.state.question}
|
||||
onDoubleClick={this.handleDoubleClick}
|
||||
onQuestionAnswered={this.handleQuestionAnswered}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -336,12 +336,12 @@ const control = `
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="control_forever"/>
|
||||
<block id="forever" type="control_forever"/>
|
||||
${blockSeparator}
|
||||
<block type="control_if"/>
|
||||
<block type="control_if_else"/>
|
||||
<block type="control_wait_until"/>
|
||||
<block type="control_repeat_until"/>
|
||||
<block id="wait_until" type="control_wait_until"/>
|
||||
<block id="repeat_until" type="control_repeat_until"/>
|
||||
${blockSeparator}
|
||||
<block type="control_stop"/>
|
||||
${blockSeparator}
|
||||
@@ -382,7 +382,7 @@ const sensing = `
|
||||
</value>
|
||||
</block>
|
||||
${blockSeparator}
|
||||
<block type="sensing_askandwait">
|
||||
<block id="askandwait" type="sensing_askandwait">
|
||||
<value name="QUESTION">
|
||||
<shadow type="text">
|
||||
<field name="TEXT">What's your name?</field>
|
||||
|
||||
Reference in new issue
Block a user