refactor console to its own reducer and actions, add clear button, clean up console component
This commit is contained in:
parent
d1c1279061
commit
8120fdd7db
6 changed files with 59 additions and 78 deletions
|
@ -6,9 +6,9 @@ export function clearConsole() {
|
|||
};
|
||||
}
|
||||
|
||||
export function dispatchConsoleEvent(...args) {
|
||||
export function dispatchConsoleEvent(messages) {
|
||||
return {
|
||||
type: ActionTypes.CONSOLE_EVENT,
|
||||
event: args[0].data
|
||||
event: messages
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,75 +4,12 @@ const upArrowUrl = require('../../../images/up-arrow.svg');
|
|||
const downArrowUrl = require('../../../images/down-arrow.svg');
|
||||
import classNames from 'classnames';
|
||||
|
||||
/**
|
||||
* How many console messages to store
|
||||
* @type {Number}
|
||||
*/
|
||||
const consoleMax = 200;
|
||||
|
||||
class Console extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.appendConsoleEvent = this.appendConsoleEvent.bind(this);
|
||||
this.clearConsole = this.clearConsole.bind(this);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.isPlaying && !this.props.isPlaying) {
|
||||
this.children = [];
|
||||
} else if (nextProps.consoleEvent !== this.props.consoleEvent && this.props.isPlaying) {
|
||||
nextProps.consoleEvent.forEach(consoleEvent => {
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// shouldComponentUpdate(nextProps) {
|
||||
// return (nextProps.consoleEvent !== this.props.consoleEvent)
|
||||
// || (nextProps.isPlaying && !this.props.isPlaying)
|
||||
// || (this.props.isExpanded !== nextProps.isExpanded)
|
||||
// || ;
|
||||
// }
|
||||
|
||||
componentDidUpdate() {
|
||||
this.refs.console_messages.scrollTop = this.refs.console_messages.scrollHeight;
|
||||
}
|
||||
|
||||
appendConsoleEvent(consoleEvent) {
|
||||
const args = consoleEvent.arguments;
|
||||
const method = consoleEvent.method;
|
||||
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>
|
||||
);
|
||||
}
|
||||
this.children.push(nextChild);
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
this.children = [];
|
||||
}
|
||||
|
||||
render() {
|
||||
const childrenToDisplay = this.children.slice(-consoleMax);
|
||||
const consoleClass = classNames({
|
||||
'preview-console': true,
|
||||
'preview-console--collapsed': !this.props.isExpanded
|
||||
|
@ -81,11 +18,11 @@ class Console extends React.Component {
|
|||
return (
|
||||
<div ref="console" className={consoleClass} role="main" tabIndex="0" title="console">
|
||||
<div className="preview-console__header">
|
||||
<h2 className="preview-console__header-title">console</h2>
|
||||
<h2 className="preview-console__header-title">Console</h2>
|
||||
<div className="preview-console__header-buttons">
|
||||
<button className="preview-console__clear" onClick={this.clearConsole} aria-label="clear console">
|
||||
<a className="preview-console__clear" onClick={this.props.clearConsole} aria-label="clear console">
|
||||
Clear
|
||||
</button>
|
||||
</a>
|
||||
<button className="preview-console__collapse" onClick={this.props.collapseConsole} aria-label="collapse console">
|
||||
<InlineSVG src={downArrowUrl} />
|
||||
</button>
|
||||
|
@ -95,7 +32,22 @@ class Console extends React.Component {
|
|||
</div>
|
||||
</div>
|
||||
<div ref="console_messages" className="preview-console__messages">
|
||||
{childrenToDisplay}
|
||||
{this.props.consoleEvents.map((consoleEvent, index) => {
|
||||
const args = consoleEvent.arguments;
|
||||
const method = consoleEvent.method;
|
||||
if (Object.keys(args).length === 0) {
|
||||
return (
|
||||
<div key={index} className="preview-console__undefined">
|
||||
<span key={`${index}-0`}>{'undefined'}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div key={index} className={`preview-console__${method}`}>
|
||||
{Object.keys(args).map((key) => <span key={`${index}-${key}`}>{args[key]}</span>)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -104,12 +56,12 @@ class Console extends React.Component {
|
|||
}
|
||||
|
||||
Console.propTypes = {
|
||||
consoleLines: PropTypes.array,
|
||||
consoleEvents: PropTypes.array,
|
||||
isPlaying: PropTypes.bool.isRequired,
|
||||
isExpanded: PropTypes.bool.isRequired,
|
||||
collapseConsole: PropTypes.func.isRequired,
|
||||
expandConsole: PropTypes.func.isRequired,
|
||||
stopSketch: PropTypes.func.isRequired,
|
||||
clearConsole: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default Console;
|
||||
|
|
|
@ -87,8 +87,17 @@ class PreviewFrame extends React.Component {
|
|||
}
|
||||
|
||||
if (this.props.dispatchConsoleEvent) {
|
||||
window.addEventListener('message', (msg) => {
|
||||
this.props.dispatchConsoleEvent(msg);
|
||||
window.addEventListener('message', (messageEvent) => {
|
||||
messageEvent.data.forEach(message => {
|
||||
const args = message.arguments;
|
||||
Object.keys(args).forEach((key) => {
|
||||
if (args[key].includes('Exiting potential infinite loop')) {
|
||||
this.props.stopSketch();
|
||||
this.props.expandConsole();
|
||||
}
|
||||
});
|
||||
});
|
||||
this.props.dispatchConsoleEvent(messageEvent.data);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -375,7 +384,9 @@ PreviewFrame.propTypes = {
|
|||
endSketchRefresh: PropTypes.func.isRequired,
|
||||
previewIsRefreshing: PropTypes.bool.isRequired,
|
||||
fullView: PropTypes.bool,
|
||||
setBlobUrl: PropTypes.func.isRequired
|
||||
setBlobUrl: PropTypes.func.isRequired,
|
||||
stopSketch: PropTypes.func.isRequired,
|
||||
expandConsole: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default PreviewFrame;
|
||||
|
|
|
@ -324,12 +324,12 @@ class IDEView extends React.Component {
|
|||
collapseSidebar={this.props.collapseSidebar}
|
||||
/>
|
||||
<Console
|
||||
consoleLines={this.props.console}
|
||||
consoleEvents={this.props.console}
|
||||
isPlaying={this.props.ide.isPlaying}
|
||||
isExpanded={this.props.ide.consoleIsExpanded}
|
||||
expandConsole={this.props.expandConsole}
|
||||
collapseConsole={this.props.collapseConsole}
|
||||
stopSketch={this.props.stopSketch}
|
||||
clearConsole={this.props.clearConsole}
|
||||
/>
|
||||
</SplitPane>
|
||||
<div className="preview-frame-holder">
|
||||
|
@ -359,6 +359,8 @@ class IDEView extends React.Component {
|
|||
endSketchRefresh={this.props.endSketchRefresh}
|
||||
stopSketch={this.props.stopSketch}
|
||||
setBlobUrl={this.props.setBlobUrl}
|
||||
stopSketch={this.props.stopSketch}
|
||||
expandConsole={this.props.expandConsole}
|
||||
/>
|
||||
</div>
|
||||
</SplitPane>
|
||||
|
@ -587,7 +589,8 @@ IDEView.propTypes = {
|
|||
resetProject: PropTypes.func.isRequired,
|
||||
closeForceAuthentication: PropTypes.func.isRequired,
|
||||
openForceAuthentication: PropTypes.func.isRequired,
|
||||
console: PropTypes.array.isRequired
|
||||
console: PropTypes.array.isRequired,
|
||||
clearConsole: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
|
|
|
@ -6,7 +6,7 @@ const initialState = [];
|
|||
const console = (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case ActionTypes.CONSOLE_EVENT:
|
||||
return [...state, action.event].slice(-consoleMax);
|
||||
return state.concat(action.event).slice(-consoleMax);
|
||||
case ActionTypes.CLEAR_CONSOLE:
|
||||
return [];
|
||||
default:
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
padding: #{5 / $base-font-size}rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.preview-console__header-title {
|
||||
|
@ -70,6 +71,7 @@
|
|||
}
|
||||
|
||||
.preview-console__collapse {
|
||||
padding-top: #{3 / $base-font-size}rem;
|
||||
@include themify() {
|
||||
@extend %icon;
|
||||
}
|
||||
|
@ -79,6 +81,7 @@
|
|||
}
|
||||
|
||||
.preview-console__expand {
|
||||
padding-top: #{3 / $base-font-size}rem;
|
||||
@include themify() {
|
||||
@extend %icon;
|
||||
}
|
||||
|
@ -87,3 +90,15 @@
|
|||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.preview-console__header-buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.preview-console__clear {
|
||||
padding-right: #{10 / $base-font-size}rem;
|
||||
.preview-console--collapsed & {
|
||||
display: none;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue