From 51831852bef2a48cd1781bda45b9ff0e5e48acfd Mon Sep 17 00:00:00 2001 From: Zach Rispoli Date: Mon, 17 Jul 2017 16:13:59 -0400 Subject: [PATCH 1/4] Line error highlight styling --- client/modules/IDE/components/Editor.jsx | 2 ++ client/styles/components/_editor.scss | 25 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/client/modules/IDE/components/Editor.jsx b/client/modules/IDE/components/Editor.jsx index 585f3772..97637bfc 100644 --- a/client/modules/IDE/components/Editor.jsx +++ b/client/modules/IDE/components/Editor.jsx @@ -105,6 +105,8 @@ class Editor extends React.Component { this._cm.getWrapperElement().style['font-size'] = `${this.props.fontSize}px`; this._cm.setOption('indentWithTabs', this.props.isTabIndent); this._cm.setOption('tabSize', this.props.indentationAmount); + + this._cm.addLineClass(1, null, 'line-runtime-error'); } componentWillUpdate(nextProps) { diff --git a/client/styles/components/_editor.scss b/client/styles/components/_editor.scss index ad455a00..0d244103 100644 --- a/client/styles/components/_editor.scss +++ b/client/styles/components/_editor.scss @@ -27,6 +27,31 @@ padding-left: #{5 / $base-font-size}rem; } +.CodeMirror-activeline-background { + background-color: rgba(0,0,0,0.025) !important; +} + +.CodeMirror-linebackground { + +} + +.line-runtime-error { + background-color: #ffaaaa !important; + border-radius: 5px; +} + +.CodeMirror-guttermarker-subtle { + +} + +.CodeMirror-foldgutter-folded { + +} + +.CodeMirror-foldgutter-open { + +} + .CodeMirror-gutter-wrapper { right: 100%; top: 0; From 0faccbbc0473d4021d155e536e23f73522db9cb3 Mon Sep 17 00:00:00 2001 From: Zach Rispoli Date: Mon, 17 Jul 2017 17:27:21 -0400 Subject: [PATCH 2/4] Hacky runtime error highlight working --- client/modules/IDE/components/Editor.jsx | 23 ++++++++++++++++++++--- client/modules/IDE/pages/IDEView.jsx | 1 + 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/client/modules/IDE/components/Editor.jsx b/client/modules/IDE/components/Editor.jsx index 97637bfc..2507dd3e 100644 --- a/client/modules/IDE/components/Editor.jsx +++ b/client/modules/IDE/components/Editor.jsx @@ -105,8 +105,6 @@ class Editor extends React.Component { this._cm.getWrapperElement().style['font-size'] = `${this.props.fontSize}px`; this._cm.setOption('indentWithTabs', this.props.isTabIndent); this._cm.setOption('tabSize', this.props.indentationAmount); - - this._cm.addLineClass(1, null, 'line-runtime-error'); } componentWillUpdate(nextProps) { @@ -142,6 +140,20 @@ class Editor extends React.Component { if (this.props.theme !== prevProps.theme) { this._cm.setOption('theme', `p5-${this.props.theme}`); } + for (let i = 0; i < 1000; i += 1) { + this._cm.removeLineClass(i, 'background', 'line-runtime-error'); + } + this.props.consoleEvents.forEach((consoleEvent) => { + if (consoleEvent.method === 'error') { + console.log(consoleEvent.arguments); + console.log(consoleEvent.source); + + const n = consoleEvent.arguments.replace(')', '').split(' '); + const lineNumber = parseInt(n[n.length - 1], 10) - 1; + console.log(lineNumber); + this._cm.addLineClass(lineNumber, 'background', 'line-runtime-error'); + } + }); } componentWillUnmount() { @@ -278,6 +290,10 @@ Editor.propTypes = { message: PropTypes.string.isRequired, id: PropTypes.number.isRequired })).isRequired, + consoleEvents: PropTypes.arrayOf(PropTypes.shape({ + method: PropTypes.string.isRequired, + args: PropTypes.arrayOf(PropTypes.string) + })), updateLintMessage: PropTypes.func.isRequired, clearLintMessage: PropTypes.func.isRequired, indentationAmount: PropTypes.number.isRequired, @@ -313,7 +329,8 @@ Editor.propTypes = { }; Editor.defaultProps = { - isUserOwner: false + isUserOwner: false, + consoleEvents: [] }; export default Editor; diff --git a/client/modules/IDE/pages/IDEView.jsx b/client/modules/IDE/pages/IDEView.jsx index fb957d27..4a119955 100644 --- a/client/modules/IDE/pages/IDEView.jsx +++ b/client/modules/IDE/pages/IDEView.jsx @@ -329,6 +329,7 @@ class IDEView extends React.Component { collapseSidebar={this.props.collapseSidebar} isUserOwner={this.isUserOwner()} clearConsole={this.props.clearConsole} + consoleEvents={this.props.console} /> Date: Wed, 26 Jul 2017 14:46:59 -0400 Subject: [PATCH 3/4] Runtime error line highlight dissappears on lint message update --- client/constants.js | 3 ++ client/modules/IDE/actions/ide.js | 12 +++++ client/modules/IDE/components/Editor.jsx | 60 ++++++++++++++---------- client/modules/IDE/pages/IDEView.jsx | 10 +++- client/modules/IDE/reducers/ide.js | 7 ++- 5 files changed, 65 insertions(+), 27 deletions(-) diff --git a/client/constants.js b/client/constants.js index 149dc79c..52e6f709 100644 --- a/client/constants.js +++ b/client/constants.js @@ -117,3 +117,6 @@ export const CLEAR_PERSISTED_STATE = 'CLEAR_PERSISTED_STATE'; export const SHOW_HELP_MODAL = 'SHOW_HELP_MODAL'; export const HIDE_HELP_MODAL = 'HIDE_HELP_MODAL'; + +export const HIDE_RUNTIME_ERROR_WARNING = 'HIDE_RUNTIME_ERROR_WARNING'; +export const SHOW_RUNTIME_ERROR_WARNING = 'SHOW_RUNTIME_ERROR_WARNING'; diff --git a/client/modules/IDE/actions/ide.js b/client/modules/IDE/actions/ide.js index 4f5c0662..691d08dc 100644 --- a/client/modules/IDE/actions/ide.js +++ b/client/modules/IDE/actions/ide.js @@ -233,3 +233,15 @@ export function hideHelpModal() { type: ActionTypes.HIDE_HELP_MODAL }; } + +export function hideRuntimeErrorWarning() { + return { + type: ActionTypes.HIDE_RUNTIME_ERROR_WARNING + }; +} + +export function showRuntimeErrorWarning() { + return { + type: ActionTypes.SHOW_RUNTIME_ERROR_WARNING + }; +} diff --git a/client/modules/IDE/components/Editor.jsx b/client/modules/IDE/components/Editor.jsx index 2507dd3e..512dea96 100644 --- a/client/modules/IDE/components/Editor.jsx +++ b/client/modules/IDE/components/Editor.jsx @@ -38,6 +38,7 @@ class Editor extends React.Component { constructor(props) { super(props); this.tidyCode = this.tidyCode.bind(this); + this.onUpdateLinting = this.onUpdateLinting.bind(this); } componentDidMount() { this.beep = new Audio(beepUrl); @@ -52,17 +53,7 @@ class Editor extends React.Component { gutters: ['CodeMirror-lint-markers'], keyMap: 'sublime', lint: { - onUpdateLinting: debounce((annotations) => { - this.props.clearLintMessage(); - annotations.forEach((x) => { - if (x.from.line > -1) { - this.props.updateLintMessage(x.severity, (x.from.line + 1), x.message); - } - }); - if (this.props.lintMessages.length > 0 && this.props.lintWarning) { - this.beep.play(); - } - }, 2000), + onUpdateLinting: this.onUpdateLinting, options: { 'asi': true, 'eqeqeq': false, @@ -140,26 +131,44 @@ class Editor extends React.Component { if (this.props.theme !== prevProps.theme) { this._cm.setOption('theme', `p5-${this.props.theme}`); } + + if (prevProps.consoleEvents !== this.props.consoleEvents) { + this.props.showRuntimeErrorWarning(); + } for (let i = 0; i < 1000; i += 1) { this._cm.removeLineClass(i, 'background', 'line-runtime-error'); } - this.props.consoleEvents.forEach((consoleEvent) => { - if (consoleEvent.method === 'error') { - console.log(consoleEvent.arguments); - console.log(consoleEvent.source); - - const n = consoleEvent.arguments.replace(')', '').split(' '); - const lineNumber = parseInt(n[n.length - 1], 10) - 1; - console.log(lineNumber); - this._cm.addLineClass(lineNumber, 'background', 'line-runtime-error'); - } - }); + if (this.props.runtimeErrorWarningVisible) { + this.props.consoleEvents.forEach((consoleEvent) => { + if (consoleEvent.method === 'error') { + const n = consoleEvent.arguments.replace(')', '').split(' '); + const lineNumber = parseInt(n[n.length - 1], 10) - 1; + this._cm.addLineClass(lineNumber, 'background', 'line-runtime-error'); + } + }); + } } componentWillUnmount() { this._cm = null; } + onUpdateLinting() { + this.props.hideRuntimeErrorWarning(); + + debounce((annotations) => { + this.props.clearLintMessage(); + annotations.forEach((x) => { + if (x.from.line > -1) { + this.props.updateLintMessage(x.severity, (x.from.line + 1), x.message); + } + }); + if (this.props.lintMessages.length > 0 && this.props.lintWarning) { + this.beep.play(); + } + }, 2000); + } + getFileMode(fileName) { let mode; if (fileName.match(/.+\.js$/i)) { @@ -325,12 +334,15 @@ Editor.propTypes = { collapseSidebar: PropTypes.func.isRequired, expandSidebar: PropTypes.func.isRequired, isUserOwner: PropTypes.bool, - clearConsole: PropTypes.func.isRequired + clearConsole: PropTypes.func.isRequired, + showRuntimeErrorWarning: PropTypes.func.isRequired, + hideRuntimeErrorWarning: PropTypes.func.isRequired, + runtimeErrorWarningVisible: PropTypes.bool.isRequired, }; Editor.defaultProps = { isUserOwner: false, - consoleEvents: [] + consoleEvents: [], }; export default Editor; diff --git a/client/modules/IDE/pages/IDEView.jsx b/client/modules/IDE/pages/IDEView.jsx index 4a119955..01dcf984 100644 --- a/client/modules/IDE/pages/IDEView.jsx +++ b/client/modules/IDE/pages/IDEView.jsx @@ -330,6 +330,9 @@ class IDEView extends React.Component { isUserOwner={this.isUserOwner()} clearConsole={this.props.clearConsole} consoleEvents={this.props.console} + showRuntimeErrorWarning={this.props.showRuntimeErrorWarning} + hideRuntimeErrorWarning={this.props.hideRuntimeErrorWarning} + runtimeErrorWarningVisible={this.props.ide.runtimeErrorWarningVisible} /> { @@ -95,6 +96,10 @@ const ide = (state = initialState, action) => { return Object.assign({}, state, { helpType: action.helpType }); case ActionTypes.HIDE_HELP_MODAL: return Object.assign({}, state, { helpType: undefined }); + case ActionTypes.HIDE_RUNTIME_ERROR_WARNING: + return Object.assign({}, state, { runtimeErrorWarningVisible: false }); + case ActionTypes.SHOW_RUNTIME_ERROR_WARNING: + return Object.assign({}, state, { runtimeErrorWarningVisible: true }); default: return state; } From 4d3e998f333ac38024f91e505945396486c573ae Mon Sep 17 00:00:00 2001 From: Zach Rispoli Date: Wed, 26 Jul 2017 15:17:05 -0400 Subject: [PATCH 4/4] Fix broken accessibility feature --- client/modules/IDE/components/Editor.jsx | 34 +++++++++++------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/client/modules/IDE/components/Editor.jsx b/client/modules/IDE/components/Editor.jsx index 512dea96..9379bd94 100644 --- a/client/modules/IDE/components/Editor.jsx +++ b/client/modules/IDE/components/Editor.jsx @@ -38,7 +38,18 @@ class Editor extends React.Component { constructor(props) { super(props); this.tidyCode = this.tidyCode.bind(this); - this.onUpdateLinting = this.onUpdateLinting.bind(this); + + this.updateLintingMessageAccessibility = debounce((annotations) => { + this.props.clearLintMessage(); + annotations.forEach((x) => { + if (x.from.line > -1) { + this.props.updateLintMessage(x.severity, (x.from.line + 1), x.message); + } + }); + if (this.props.lintMessages.length > 0 && this.props.lintWarning) { + this.beep.play(); + } + }, 2000); } componentDidMount() { this.beep = new Audio(beepUrl); @@ -53,7 +64,10 @@ class Editor extends React.Component { gutters: ['CodeMirror-lint-markers'], keyMap: 'sublime', lint: { - onUpdateLinting: this.onUpdateLinting, + onUpdateLinting: ((annotations) => { + this.props.hideRuntimeErrorWarning(); + this.updateLintingMessageAccessibility(annotations); + }), options: { 'asi': true, 'eqeqeq': false, @@ -153,22 +167,6 @@ class Editor extends React.Component { this._cm = null; } - onUpdateLinting() { - this.props.hideRuntimeErrorWarning(); - - debounce((annotations) => { - this.props.clearLintMessage(); - annotations.forEach((x) => { - if (x.from.line > -1) { - this.props.updateLintMessage(x.severity, (x.from.line + 1), x.message); - } - }); - if (this.props.lintMessages.length > 0 && this.props.lintWarning) { - this.beep.play(); - } - }, 2000); - } - getFileMode(fileName) { let mode; if (fileName.match(/.+\.js$/i)) {