Skip to content
Snippets Groups Projects
Commit 1a5d8082 authored by Paul Kaplan's avatar Paul Kaplan
Browse files

Add question and answer components.

parent 76bde5a4
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 and focus outline */
.question-input > input {
width: 100%;
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}
/> />
); );
......
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