diff --git a/embark-ui/package-lock.json b/embark-ui/package-lock.json
index b57f63d0d..8c3da60b9 100644
--- a/embark-ui/package-lock.json
+++ b/embark-ui/package-lock.json
@@ -2039,11 +2039,47 @@
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.3.0.tgz",
"integrity": "sha512-MAAAIOdi2s4Gl6rZ76PNcUa9IOYB+5ICdT41o5uMRf09aEu/F9RK+qhe8RjXNPwcTjGV7KU7h2P/fljThFVqyQ=="
},
+ "component-clone": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/component-clone/-/component-clone-0.2.2.tgz",
+ "integrity": "sha1-x/WXmCKID62M+wliuikYbQYe4E8=",
+ "requires": {
+ "component-type": "*"
+ }
+ },
"component-emitter": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
"integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="
},
+ "component-raf": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/component-raf/-/component-raf-1.2.0.tgz",
+ "integrity": "sha1-srxy1D8bAU/eeks8RHx2S8c8y6o="
+ },
+ "component-tween": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/component-tween/-/component-tween-1.2.0.tgz",
+ "integrity": "sha1-zDnOXbqwW1KCX0HRlHY4oLAbK4o=",
+ "requires": {
+ "component-clone": "0.2.2",
+ "component-emitter": "1.2.0",
+ "component-type": "1.1.0",
+ "ease-component": "1.0.0"
+ },
+ "dependencies": {
+ "component-emitter": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.0.tgz",
+ "integrity": "sha1-zNETqGOI0GSC0D3j/H35hSa6jv4="
+ }
+ }
+ },
+ "component-type": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/component-type/-/component-type-1.1.0.tgz",
+ "integrity": "sha1-lbZmqtU+XI0fK+E1xFtdSZGXwMU="
+ },
"compressible": {
"version": "2.0.14",
"resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.14.tgz",
@@ -2835,6 +2871,11 @@
"resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
"integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI="
},
+ "ease-component": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/ease-component/-/ease-component-1.0.0.tgz",
+ "integrity": "sha1-s3VybbC1sEWVt3RAOW/sfapdd8k="
+ },
"ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
@@ -9033,6 +9074,14 @@
}
}
},
+ "react-scroll-to-component": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/react-scroll-to-component/-/react-scroll-to-component-1.0.2.tgz",
+ "integrity": "sha1-8mDck2xipT53J4bXgy/giE4ZU1Q=",
+ "requires": {
+ "scroll-to": "0.0.2"
+ }
+ },
"react-text-mask": {
"version": "5.4.3",
"resolved": "https://registry.npmjs.org/react-text-mask/-/react-text-mask-5.4.3.tgz",
@@ -9554,6 +9603,15 @@
"ajv": "^5.0.0"
}
},
+ "scroll-to": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/scroll-to/-/scroll-to-0.0.2.tgz",
+ "integrity": "sha1-k205ipEzZgokkhRcLACB38sHKPM=",
+ "requires": {
+ "component-raf": "1.2.0",
+ "component-tween": "1.2.0"
+ }
+ },
"select-hose": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
diff --git a/embark-ui/package.json b/embark-ui/package.json
index 6fc98abab..99671d5fa 100644
--- a/embark-ui/package.json
+++ b/embark-ui/package.json
@@ -15,6 +15,7 @@
"react-redux": "^5.0.7",
"react-router-dom": "^4.3.1",
"react-scripts": "1.1.4",
+ "react-scroll-to-component": "^1.0.2",
"redux": "^4.0.0",
"redux-saga": "^0.16.0",
"tabler-react": "^1.18.0"
diff --git a/embark-ui/public/monaco-editor-worker-loader-proxy.js b/embark-ui/public/monaco-editor-worker-loader-proxy.js
deleted file mode 100644
index 0585b5c06..000000000
--- a/embark-ui/public/monaco-editor-worker-loader-proxy.js
+++ /dev/null
@@ -1,5 +0,0 @@
-self.MonacoEnvironment = {
- baseUrl: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.13.1/min/'
-};
-
-importScripts('https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.13.1/min/vs/base/worker/workerMain.js'); // eslint-disable-line
diff --git a/embark-ui/src/actions/index.js b/embark-ui/src/actions/index.js
index 50b6670b8..834b5d97b 100644
--- a/embark-ui/src/actions/index.js
+++ b/embark-ui/src/actions/index.js
@@ -144,13 +144,13 @@ export function listenToContractLogs() {
}
// Fiddle
-export const FETCH_COMPILE_CODE = 'FETCH_COMPILE_CODE';
-export const RECEIVE_COMPILE_CODE = 'RECEIVE_COMPILE_CODE';
-export const RECEIVE_COMPILE_CODE_ERROR = 'RECEIVE_COMPILE_CODE_ERROR';
+export const COMPILE_CODE_REQUEST = 'COMPILE_CODE_REQUEST';
+export const COMPILE_CODE_SUCCESS = 'COMPILE_CODE_SUCCESS';
+export const COMPILE_CODE_FAILURE = 'COMPILE_CODE_FAILURE';
export function fetchCodeCompilation(codeToCompile){
return {
- type: FETCH_COMPILE_CODE,
+ type: COMPILE_CODE_REQUEST,
codeToCompile
};
}
@@ -158,14 +158,14 @@ export function fetchCodeCompilation(codeToCompile){
export function receiveCodeCompilation(compilationResult){
return {
- type: RECEIVE_COMPILE_CODE,
+ type: COMPILE_CODE_SUCCESS,
compilationResult
};
}
export function receiveCodeCompilationError(){
return {
- type: RECEIVE_COMPILE_CODE_ERROR
+ type: COMPILE_CODE_FAILURE
};
}
diff --git a/embark-ui/src/components/Fiddle.js b/embark-ui/src/components/Fiddle.js
index 6d6183049..a380fe935 100644
--- a/embark-ui/src/components/Fiddle.js
+++ b/embark-ui/src/components/Fiddle.js
@@ -5,28 +5,49 @@ import 'brace/theme/tomorrow_night_blue';
import 'ace-mode-solidity/build/remix-ide/mode-solidity';
import PropTypes from 'prop-types';
-const Fiddle = ({onCodeChange, value}) => {
+class Fiddle extends React.Component {
+ constructor(props) {
+ super(props);
- return (
-
- Fiddle
- Play around with contract code and deploy against your running node.
-
-
- );
-};
+ this.ace = null;
+ }
+
+ render() {
+ const {onCodeChange, value, errors, warnings} = this.props;
+ const annotations = errors.map((error) => { return error.annotation; }).concat(warnings.map(warning => { return warning.annotation; }));
+ return (
+
+
+ { this.ace = ace; }}
+ setOptions={{
+ useWorker: false
+ }}
+ editorProps={{
+ $blockScrolling: Infinity,
+ enableLiveAutocompletion:true,
+ highlightSelectedWord: true
+ }}
+ />
+
+ );
+ }
+}
Fiddle.propTypes = {
onCodeChange: PropTypes.func,
- value: PropTypes.string
+ value: PropTypes.string,
+ errors: PropTypes.array,
+ warnings: PropTypes.array
};
export default Fiddle;
diff --git a/embark-ui/src/components/FiddleResults.js b/embark-ui/src/components/FiddleResults.js
index 1f69fc009..b79a55d1e 100644
--- a/embark-ui/src/components/FiddleResults.js
+++ b/embark-ui/src/components/FiddleResults.js
@@ -1,41 +1,35 @@
+/* eslint {jsx-a11y/anchor-has-content:"off"} */
import React, {Component} from 'react';
import {Card, List, Badge} from 'tabler-react';
import PropTypes from 'prop-types';
-class FiddleResults extends Component{
+class FiddleResults extends Component {
- constructor(props){
- super(props);
- this.state = {
- errors: props.compilationResult.errors
- };
+ static _removeClass(elems, className) {
+ for (let elem of elems) {
+ elem.className = elem.className.replace(className, '').replace(' ', ' ');
+ }
}
- static _removeClass(elems, className){
- for(let elem of elems) {
- elem.className = elem.className.replace(className, '').replace(' ', ' ');
+ static _toggleClass(elems, className) {
+ for (let elem of elems) {
+ if (elem.className.indexOf(className) > -1) {
+ FiddleResults._removeClass([elem], className);
}
- }
-
- static _toggleClass(elems, className){
- for(let elem of elems) {
- if(elem.className.indexOf(className) > -1){
- FiddleResults._removeClass([elem], className);
- }
- else{
- elem.className = (elem.className.length > 0 ? elem.className + ' ' : '') + className;
- }
+ else {
+ elem.className = (elem.className.length > 0 ? elem.className + ' ' : '') + className;
}
+ }
}
- toggleCollapse(e) {
+ _toggleCollapse(e) {
const collapsedClassName = 'card-collapsed';
const className = e.currentTarget.parentElement.className.replace('card-options', '').replace(' ', '');
const elems = document.getElementsByClassName(className + '-card');
FiddleResults._toggleClass(elems, collapsedClassName);
}
-
- toggleFullscreen(e) {
+
+ _toggleFullscreen(e) {
const collapsedClassName = 'card-collapsed';
const fullscreenClassName = 'card-fullscreen';
const className = e.currentTarget.parentElement.className.replace('card-options', '').replace(' ', '');
@@ -44,91 +38,58 @@ class FiddleResults extends Component{
FiddleResults._removeClass(elems, collapsedClassName);
}
- render(){
- const warningObjs = this.props.compilationResult.errors.filter(error => {
- return error.severity === 'warning';
- });
- const errorObjs = this.props.compilationResult.errors.filter(error => {
- return error.severity === 'error';
- });
- const warnings = warningObjs.map((warning, index) => {
- return (
-
-
- Lines {warning.sourceLocation.start}-{warning.sourceLocation.end}
-
- {warning.formattedMessage}
-
- );
- });
- const errors = errorObjs.map((error, index) => {
- return (
-
-
- Lines {error.sourceLocation.start}-{error.sourceLocation.end}
-
- {error.formattedMessage}
-
- );
- });
- const errorsCard =
+ className={errorType + "s-card"}
+ key={errorType + "s-card"}>
- Errors {errors.length}
-
-
-
+ {errorType + "s"} {errors.length}
+
+
+
- {errors}
-
-
- ;
- const warningsCard =
-
- Warnings {warnings.length}
-
-
-
-
-
-
-
- {warnings}
+ {errors.map(error => { return error.node; })}
;
+ }
+
+ render() {
+ const {warnings, errors} = this.props;
let renderings = [];
- if(!this.state.errors){
- return 'Compilation successful (add green tick mark)';
- }
- if(errors.length) renderings.push(errorsCard);
- if(warnings.length) renderings.push(warningsCard);
-
+ if (errors.length) renderings.push(
+
+
+ {this._getFormatted(errors, "error")}
+
+ );
+ if (warnings.length) renderings.push(
+
+
+ {this._getFormatted(warnings, "warning")}
+
+ );
+
return (
- {renderings}
+ {renderings}
);
}
}
FiddleResults.propTypes = {
- compilationResult: PropTypes.object
+ errors: PropTypes.array,
+ warnings: PropTypes.array
};
export default FiddleResults;
diff --git a/embark-ui/src/components/FiddleResultsSummary.js b/embark-ui/src/components/FiddleResultsSummary.js
new file mode 100644
index 000000000..40c56bd37
--- /dev/null
+++ b/embark-ui/src/components/FiddleResultsSummary.js
@@ -0,0 +1,45 @@
+import React, {Component} from 'react';
+import {Badge} from 'tabler-react';
+import PropTypes from 'prop-types';
+
+class FiddleResultsSummary extends Component{
+
+ render(){
+ const {warnings, errors, isFetching, hasResult} = this.props;
+ let renderings = [];
+ if(isFetching){
+ renderings.push(
+ Compiling...
+ );
+ }
+ if(hasResult && !errors.length){
+ renderings.push(Compiled);
+ }
+ if(errors.length) renderings.push(
+
+ {errors.length} error{errors.length > 1 ? "s" : ""}
+
+ );
+ if(warnings.length) renderings.push(
+
+ {warnings.length} warning{warnings.length > 1 ? "s" : ""}
+
+ );
+
+ return (
+
+ {renderings}
+ {!(hasResult || isFetching) ? " " : ""}
+
+ );
+ }
+}
+
+FiddleResultsSummary.propTypes = {
+ errors: PropTypes.array,
+ warnings: PropTypes.array,
+ isFetching: PropTypes.bool,
+ hasResult: PropTypes.bool
+};
+
+export default FiddleResultsSummary;
diff --git a/embark-ui/src/containers/FiddleContainer.js b/embark-ui/src/containers/FiddleContainer.js
index cb385c9c8..fd9e61675 100644
--- a/embark-ui/src/containers/FiddleContainer.js
+++ b/embark-ui/src/containers/FiddleContainer.js
@@ -6,43 +6,129 @@ import PropTypes from 'prop-types';
import {fetchCodeCompilation} from '../actions';
import Fiddle from '../components/Fiddle';
import FiddleResults from '../components/FiddleResults';
+import FiddleReultsSummary from '../components/FiddleResultsSummary';
+import {Badge} from 'tabler-react';
+import scrollToComponent from 'react-scroll-to-component';
class FiddleContainer extends Component {
- constructor(props){
+ constructor(props) {
super(props);
- this.state = {
+ this.state = {
value: ''
};
this.compileTimeout = null;
+ this.ace = null;
+ this.editor = null;
}
- componentDidMount(){
- if(this.state.value){
+ componentDidMount() {
+ if (this.state.value) {
this.props.fetchCodeCompilation(this.state.value);
}
}
- onCodeChange(newValue) {
+ _onCodeChange(newValue) {
this.setState({value: newValue});
- if(this.compileTimeout) clearTimeout(this.compileTimeout);
+ if (this.compileTimeout) clearTimeout(this.compileTimeout);
this.compileTimeout = setTimeout(() => {
this.props.fetchCodeCompilation(newValue);
}, 1000);
-
+
+ }
+
+ _getFormattedErrors(errors, errorType){
+ return errors.reduce(
+ (errors, error, index) => {
+ if (error.severity === errorType) {
+ const errorRowCol = this._getRowCol(error.formattedMessage);
+ const annotation = Object.assign({}, {
+ row: errorRowCol.row - 1, // must be 0 based
+ column: errorRowCol.col - 1, // must be 0 based
+ text: error.formattedMessage, // text to show in tooltip
+ type: error.severity // "error"|"warning"|"info"
+ });
+ errors.push({
+ solcError: error,
+ node:
+ { this._onErrorClick(e, annotation); }}
+ key={index}
+ //ref={(item) => { this.refCallback(item, annotation); }}
+ >
+
+ Line {errorRowCol.row}
+
+ {error.formattedMessage}
+ ,
+ annotation: annotation
+ });
+ }
+ return errors;
+ }, []);
+ }
+
+ _getRowCol(errorMessage){
+ const errorSplit = errorMessage.split(':');
+ if(errorSplit.length >= 3){
+ return {row: errorSplit[1], col: errorSplit[2]};
+ }
+ return {row: 0, col: 0};
+ }
+
+ _onErrorClick(e, annotation){
+ e.preventDefault();
+ this.editor.gotoLine(annotation.row + 1);
+ scrollToComponent(this.ace);
}
render() {
const {fiddles} = this.props;
-
- let renderings = [ this.onCodeChange(n)} />];
- if(fiddles.compilationResult) {
- renderings.push();
+ let renderings = [];
+ let warnings = [];
+ let errors = [];
+ if (fiddles.compilationResult) {
+ warnings = this._getFormattedErrors(fiddles.compilationResult.errors, "warning");
+ errors = this._getFormattedErrors(fiddles.compilationResult.errors, "error");
+
}
- else renderings.push('Nothing to compile');
-
+ renderings.push(
+
+
+ this._onCodeChange(n)}
+ errors={errors}
+ warnings={warnings}
+ ref={(fiddle) => {
+ if(fiddle) {
+ this.editor = fiddle.ace.editor;
+ this.ace = fiddle.ace;
+ }
+ }}
+ />
+
+ );
+ if (fiddles.compilationResult) {
+ renderings.push(
+ );
+ }
+
return (
-
+
+ Fiddle
+ Play around with contract code and deploy against your running node.
{renderings}
);
diff --git a/embark-ui/src/general.css b/embark-ui/src/general.css
index 97a265f08..819083634 100644
--- a/embark-ui/src/general.css
+++ b/embark-ui/src/general.css
@@ -25,5 +25,43 @@
white-space: pre-line;
}
.card.card-fullscreen{
- z-index:4;
+ z-index:6;
}
+.card.warnings-card, .card.errors-card{
+ text-transform: capitalize;
+}
+.card.warnings-card .list-group-item, .card.errors-card .list-group-item{
+ white-space: pre-line;
+}
+.card.warnings-card .card-options a, .card.errors-card .card-options a{
+ cursor:pointer;
+}
+.compilation-summary {
+ float:right;
+ margin-bottom:3px;
+ line-height:30px;
+ visibility: hidden;
+}
+.compilation-summary.visible{
+ visibility: visible;
+}
+.compilation-summary .badge-link:not(:last-child){
+ margin-right:5px;
+}
+.ace_editor {
+ margin-bottom:24px;
+}
+.loader, .loader:before, .loader:after{
+ width:1.2rem;
+ height:1.2rem;
+}
+.loader:before, .loader:after{
+ margin:-0.6rem 0 0 -0.6rem;
+}
+.loader, .loader-text{
+ display:inline-block;
+ vertical-align: middle;
+}
+.loader {
+ margin-right:5px;
+}
\ No newline at end of file
diff --git a/embark-ui/src/reducers/fiddleReducer.js b/embark-ui/src/reducers/fiddleReducer.js
index 4ce66f5e5..5d53d1308 100644
--- a/embark-ui/src/reducers/fiddleReducer.js
+++ b/embark-ui/src/reducers/fiddleReducer.js
@@ -1,11 +1,13 @@
-import {RECEIVE_COMPILE_CODE, RECEIVE_COMPILE_CODE_ERROR} from "../actions";
+import {COMPILE_CODE_REQUEST, COMPILE_CODE_FAILURE, COMPILE_CODE_SUCCESS} from "../actions";
export default function processes(state = {}, action) {
switch (action.type) {
- case RECEIVE_COMPILE_CODE:
- return Object.assign({}, state, {compilationResult: action.compilationResult});
- case RECEIVE_COMPILE_CODE_ERROR:
- return Object.assign({}, state, {error: true});
+ case COMPILE_CODE_REQUEST:
+ return {...state, isFetching: true, compilationResult: action.compilationResult};
+ case COMPILE_CODE_SUCCESS:
+ return {...state, isFetching: false, compilationResult: action.compilationResult};
+ case COMPILE_CODE_FAILURE:
+ return {...state, isFetching: false, error: true};
default:
return state;
}
diff --git a/embark-ui/src/sagas/index.js b/embark-ui/src/sagas/index.js
index 85e09cc9c..5243cf852 100644
--- a/embark-ui/src/sagas/index.js
+++ b/embark-ui/src/sagas/index.js
@@ -170,7 +170,7 @@ export function *fetchCodeCompilation(action) {
}
export function *watchFetchCodeCompilation() {
- yield takeEvery(actions.FETCH_COMPILE_CODE, fetchCodeCompilation);
+ yield takeEvery(actions.COMPILE_CODE_REQUEST, fetchCodeCompilation);
}
export default function *root() {
diff --git a/lib/modules/solidity/index.js b/lib/modules/solidity/index.js
index 386229cde..5784507d9 100644
--- a/lib/modules/solidity/index.js
+++ b/lib/modules/solidity/index.js
@@ -25,10 +25,7 @@ class Solidity {
'post',
'/embark-api/contract/compile',
(req, res) => {
- console.log('=====> POST contract/compile, req = ' + JSON.stringify(req.body));
this.events.request("contract:compile", req.body.code, (errors, compilationResult) => {
- console.log('=====> POST contract/compile, errors = ' + JSON.stringify(errors));
- console.log('=====> POST contract/compile, compilationResult = ' + JSON.stringify(compilationResult));
res.send({errors:errors, compilationResult: compilationResult});
});
}