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 {
|
return {
|
||||||
type: ActionTypes.CONSOLE_EVENT,
|
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');
|
const downArrowUrl = require('../../../images/down-arrow.svg');
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
/**
|
|
||||||
* How many console messages to store
|
|
||||||
* @type {Number}
|
|
||||||
*/
|
|
||||||
const consoleMax = 200;
|
|
||||||
|
|
||||||
class Console extends React.Component {
|
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() {
|
componentDidUpdate() {
|
||||||
this.refs.console_messages.scrollTop = this.refs.console_messages.scrollHeight;
|
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() {
|
render() {
|
||||||
const childrenToDisplay = this.children.slice(-consoleMax);
|
|
||||||
const consoleClass = classNames({
|
const consoleClass = classNames({
|
||||||
'preview-console': true,
|
'preview-console': true,
|
||||||
'preview-console--collapsed': !this.props.isExpanded
|
'preview-console--collapsed': !this.props.isExpanded
|
||||||
|
@ -81,11 +18,11 @@ class Console extends React.Component {
|
||||||
return (
|
return (
|
||||||
<div ref="console" className={consoleClass} role="main" tabIndex="0" title="console">
|
<div ref="console" className={consoleClass} role="main" tabIndex="0" title="console">
|
||||||
<div className="preview-console__header">
|
<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">
|
<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
|
Clear
|
||||||
</button>
|
</a>
|
||||||
<button className="preview-console__collapse" onClick={this.props.collapseConsole} aria-label="collapse console">
|
<button className="preview-console__collapse" onClick={this.props.collapseConsole} aria-label="collapse console">
|
||||||
<InlineSVG src={downArrowUrl} />
|
<InlineSVG src={downArrowUrl} />
|
||||||
</button>
|
</button>
|
||||||
|
@ -95,7 +32,22 @@ class Console extends React.Component {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div ref="console_messages" className="preview-console__messages">
|
<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>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -104,12 +56,12 @@ class Console extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.propTypes = {
|
Console.propTypes = {
|
||||||
consoleLines: PropTypes.array,
|
consoleEvents: PropTypes.array,
|
||||||
isPlaying: PropTypes.bool.isRequired,
|
isPlaying: PropTypes.bool.isRequired,
|
||||||
isExpanded: PropTypes.bool.isRequired,
|
isExpanded: PropTypes.bool.isRequired,
|
||||||
collapseConsole: PropTypes.func.isRequired,
|
collapseConsole: PropTypes.func.isRequired,
|
||||||
expandConsole: PropTypes.func.isRequired,
|
expandConsole: PropTypes.func.isRequired,
|
||||||
stopSketch: PropTypes.func.isRequired,
|
clearConsole: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Console;
|
export default Console;
|
||||||
|
|
|
@ -87,8 +87,17 @@ class PreviewFrame extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.props.dispatchConsoleEvent) {
|
if (this.props.dispatchConsoleEvent) {
|
||||||
window.addEventListener('message', (msg) => {
|
window.addEventListener('message', (messageEvent) => {
|
||||||
this.props.dispatchConsoleEvent(msg);
|
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,
|
endSketchRefresh: PropTypes.func.isRequired,
|
||||||
previewIsRefreshing: PropTypes.bool.isRequired,
|
previewIsRefreshing: PropTypes.bool.isRequired,
|
||||||
fullView: PropTypes.bool,
|
fullView: PropTypes.bool,
|
||||||
setBlobUrl: PropTypes.func.isRequired
|
setBlobUrl: PropTypes.func.isRequired,
|
||||||
|
stopSketch: PropTypes.func.isRequired,
|
||||||
|
expandConsole: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
export default PreviewFrame;
|
export default PreviewFrame;
|
||||||
|
|
|
@ -324,12 +324,12 @@ class IDEView extends React.Component {
|
||||||
collapseSidebar={this.props.collapseSidebar}
|
collapseSidebar={this.props.collapseSidebar}
|
||||||
/>
|
/>
|
||||||
<Console
|
<Console
|
||||||
consoleLines={this.props.console}
|
consoleEvents={this.props.console}
|
||||||
isPlaying={this.props.ide.isPlaying}
|
isPlaying={this.props.ide.isPlaying}
|
||||||
isExpanded={this.props.ide.consoleIsExpanded}
|
isExpanded={this.props.ide.consoleIsExpanded}
|
||||||
expandConsole={this.props.expandConsole}
|
expandConsole={this.props.expandConsole}
|
||||||
collapseConsole={this.props.collapseConsole}
|
collapseConsole={this.props.collapseConsole}
|
||||||
stopSketch={this.props.stopSketch}
|
clearConsole={this.props.clearConsole}
|
||||||
/>
|
/>
|
||||||
</SplitPane>
|
</SplitPane>
|
||||||
<div className="preview-frame-holder">
|
<div className="preview-frame-holder">
|
||||||
|
@ -359,6 +359,8 @@ class IDEView extends React.Component {
|
||||||
endSketchRefresh={this.props.endSketchRefresh}
|
endSketchRefresh={this.props.endSketchRefresh}
|
||||||
stopSketch={this.props.stopSketch}
|
stopSketch={this.props.stopSketch}
|
||||||
setBlobUrl={this.props.setBlobUrl}
|
setBlobUrl={this.props.setBlobUrl}
|
||||||
|
stopSketch={this.props.stopSketch}
|
||||||
|
expandConsole={this.props.expandConsole}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</SplitPane>
|
</SplitPane>
|
||||||
|
@ -587,7 +589,8 @@ IDEView.propTypes = {
|
||||||
resetProject: PropTypes.func.isRequired,
|
resetProject: PropTypes.func.isRequired,
|
||||||
closeForceAuthentication: PropTypes.func.isRequired,
|
closeForceAuthentication: PropTypes.func.isRequired,
|
||||||
openForceAuthentication: PropTypes.func.isRequired,
|
openForceAuthentication: PropTypes.func.isRequired,
|
||||||
console: PropTypes.array.isRequired
|
console: PropTypes.array.isRequired,
|
||||||
|
clearConsole: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
function mapStateToProps(state) {
|
function mapStateToProps(state) {
|
||||||
|
|
|
@ -6,7 +6,7 @@ const initialState = [];
|
||||||
const console = (state = initialState, action) => {
|
const console = (state = initialState, action) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case ActionTypes.CONSOLE_EVENT:
|
case ActionTypes.CONSOLE_EVENT:
|
||||||
return [...state, action.event].slice(-consoleMax);
|
return state.concat(action.event).slice(-consoleMax);
|
||||||
case ActionTypes.CLEAR_CONSOLE:
|
case ActionTypes.CLEAR_CONSOLE:
|
||||||
return [];
|
return [];
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
padding: #{5 / $base-font-size}rem;
|
padding: #{5 / $base-font-size}rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-console__header-title {
|
.preview-console__header-title {
|
||||||
|
@ -70,6 +71,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-console__collapse {
|
.preview-console__collapse {
|
||||||
|
padding-top: #{3 / $base-font-size}rem;
|
||||||
@include themify() {
|
@include themify() {
|
||||||
@extend %icon;
|
@extend %icon;
|
||||||
}
|
}
|
||||||
|
@ -79,6 +81,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-console__expand {
|
.preview-console__expand {
|
||||||
|
padding-top: #{3 / $base-font-size}rem;
|
||||||
@include themify() {
|
@include themify() {
|
||||||
@extend %icon;
|
@extend %icon;
|
||||||
}
|
}
|
||||||
|
@ -87,3 +90,15 @@
|
||||||
display: inline-block;
|
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