2016-07-18 01:06:43 +02:00
|
|
|
import React, { PropTypes } from 'react';
|
2016-07-21 06:33:41 +02:00
|
|
|
import InlineSVG from 'react-inlinesvg';
|
|
|
|
const upArrowUrl = require('../../../images/up-arrow.svg');
|
|
|
|
const downArrowUrl = require('../../../images/down-arrow.svg');
|
|
|
|
import classNames from 'classnames';
|
2016-07-18 01:06:43 +02:00
|
|
|
|
2016-07-18 02:05:20 +02:00
|
|
|
/**
|
|
|
|
* How many console messages to store
|
|
|
|
* @type {Number}
|
|
|
|
*/
|
2016-10-06 22:58:14 +02:00
|
|
|
const consoleMax = 200;
|
2016-07-18 01:06:43 +02:00
|
|
|
|
|
|
|
class Console extends React.Component {
|
|
|
|
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
2016-07-18 02:05:20 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* An array of React Elements that include previous console messages
|
|
|
|
* @type {Array}
|
|
|
|
*/
|
2016-07-18 01:06:43 +02:00
|
|
|
this.children = [];
|
2016-10-06 21:45:26 +02:00
|
|
|
this.appendConsoleEvent = this.appendConsoleEvent.bind(this);
|
2016-07-18 01:06:43 +02:00
|
|
|
}
|
|
|
|
|
2016-07-18 02:49:57 +02:00
|
|
|
componentWillReceiveProps(nextProps) {
|
|
|
|
if (nextProps.isPlaying && !this.props.isPlaying) {
|
2016-07-18 01:06:43 +02:00
|
|
|
this.children = [];
|
2016-10-06 21:45:26 +02:00
|
|
|
} else if (nextProps.consoleEvent !== this.props.consoleEvent && this.props.isPlaying) {
|
2016-10-06 22:58:14 +02:00
|
|
|
nextProps.consoleEvent.forEach(consoleEvent => {
|
2016-12-13 21:37:11 +01:00
|
|
|
const args = consoleEvent.arguments;
|
|
|
|
Object.keys(args).forEach((key) => {
|
|
|
|
if (args[key].includes('Exiting potential infinite loop')) {
|
|
|
|
this.props.stopSketch();
|
|
|
|
this.props.expandConsole();
|
|
|
|
this.appendConsoleEvent(consoleEvent);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
this.appendConsoleEvent(consoleEvent);
|
2016-10-06 19:01:48 +02:00
|
|
|
});
|
2016-07-18 01:06:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-18 02:49:57 +02:00
|
|
|
shouldComponentUpdate(nextProps) {
|
2016-07-21 06:33:41 +02:00
|
|
|
return (nextProps.consoleEvent !== this.props.consoleEvent)
|
|
|
|
|| (nextProps.isPlaying && !this.props.isPlaying)
|
|
|
|
|| (this.props.isExpanded !== nextProps.isExpanded);
|
2016-07-18 02:49:57 +02:00
|
|
|
}
|
2016-07-18 01:06:43 +02:00
|
|
|
|
2016-07-21 06:05:47 +02:00
|
|
|
componentDidUpdate() {
|
|
|
|
this.refs.console_messages.scrollTop = this.refs.console_messages.scrollHeight;
|
|
|
|
}
|
|
|
|
|
2016-10-06 21:45:26 +02:00
|
|
|
appendConsoleEvent(consoleEvent) {
|
|
|
|
const args = consoleEvent.arguments;
|
|
|
|
const method = consoleEvent.method;
|
2016-11-03 00:23:35 +01:00
|
|
|
let nextChild;
|
|
|
|
if (Object.keys(args).length === 0) {
|
|
|
|
nextChild = (
|
|
|
|
<div key={this.children.length} className="preview-console__undefined">
|
|
|
|
<span key={`${this.children.length}-0`}>{'undefined'}</span>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
nextChild = (
|
|
|
|
<div key={this.children.length} className={`preview-console__${method}`}>
|
|
|
|
{Object.keys(args).map((key) => <span key={`${this.children.length}-${key}`}>{args[key]}</span>)}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
2016-10-06 21:45:26 +02:00
|
|
|
this.children.push(nextChild);
|
|
|
|
}
|
|
|
|
|
2016-07-18 02:49:57 +02:00
|
|
|
render() {
|
|
|
|
const childrenToDisplay = this.children.slice(-consoleMax);
|
2016-07-21 06:33:41 +02:00
|
|
|
const consoleClass = classNames({
|
|
|
|
'preview-console': true,
|
|
|
|
'preview-console--collapsed': !this.props.isExpanded
|
|
|
|
});
|
2016-07-18 01:06:43 +02:00
|
|
|
|
|
|
|
return (
|
2016-08-10 23:24:52 +02:00
|
|
|
<div ref="console" className={consoleClass} role="main" tabIndex="0" title="console">
|
2016-07-21 06:33:41 +02:00
|
|
|
<div className="preview-console__header">
|
2016-12-19 23:07:04 +01:00
|
|
|
<h2 className="preview-console__header-title"><span className="preview-console__icon">>_</span>console</h2>
|
2016-07-31 04:46:48 +02:00
|
|
|
<button className="preview-console__collapse" onClick={this.props.collapseConsole} aria-label="collapse console">
|
2016-07-21 06:33:41 +02:00
|
|
|
<InlineSVG src={downArrowUrl} />
|
2016-07-31 04:46:48 +02:00
|
|
|
</button>
|
|
|
|
<button className="preview-console__expand" onClick={this.props.expandConsole} aria-label="expand console">
|
2016-07-21 06:33:41 +02:00
|
|
|
<InlineSVG src={upArrowUrl} />
|
2016-07-31 04:46:48 +02:00
|
|
|
</button>
|
2016-07-21 06:33:41 +02:00
|
|
|
</div>
|
2016-07-21 06:05:47 +02:00
|
|
|
<div ref="console_messages" className="preview-console__messages">
|
|
|
|
{childrenToDisplay}
|
|
|
|
</div>
|
2016-07-18 01:06:43 +02:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Console.propTypes = {
|
2016-10-06 22:58:14 +02:00
|
|
|
consoleEvent: PropTypes.array,
|
2016-07-21 06:33:41 +02:00
|
|
|
isPlaying: PropTypes.bool.isRequired,
|
|
|
|
isExpanded: PropTypes.bool.isRequired,
|
|
|
|
collapseConsole: PropTypes.func.isRequired,
|
2016-10-06 19:01:48 +02:00
|
|
|
expandConsole: PropTypes.func.isRequired,
|
|
|
|
stopSketch: PropTypes.func.isRequired,
|
2016-07-18 01:06:43 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
export default Console;
|