From a24ad6e57f2d949bb6fc3e0cdd3c2e10dd7d1b7b Mon Sep 17 00:00:00 2001 From: emizzle Date: Mon, 13 Aug 2018 21:44:42 +1000 Subject: [PATCH] Addressed PR comments Changed `fiddle` to an entity and removed unneeded fiddle reducer. Added a selector for getting the entity. Changed fiddle saga to `doRequest`. Changed fiddle api call to the `post` method (did not see beofre the rebase). Added `CompilerError` presentation component to handle displaying compiler errors and warnings. Added spaces to css (as requested). Removed extra space after function in solidity compiler (as requested). Removed the compile contract event from the solidity compiler (as requested). Handling of fatal api error in the UI. Changed fiddle action to the one created with `createRequestTypes`. Moved `Fiddle` nav tab before `Documentation`. Changed `FiddleResults` DOM manipulation to be controlled via React state instead. --- embark-ui/src/actions/index.js | 29 ++--- embark-ui/src/api/index.js | 4 +- embark-ui/src/components/CompilerError.js | 27 +++++ embark-ui/src/components/FiddleResults.js | 105 ++++++++++-------- .../src/components/FiddleResultsSummary.js | 43 ++++--- embark-ui/src/components/Layout.js | 4 +- embark-ui/src/containers/FiddleContainer.js | 66 ++++++----- embark-ui/src/general.css | 27 ++--- embark-ui/src/reducers/fiddleReducer.js | 14 --- embark-ui/src/reducers/index.js | 7 +- embark-ui/src/reducers/selectors.js | 4 + embark-ui/src/sagas/index.js | 22 +--- lib/modules/solidity/index.js | 24 ++-- 13 files changed, 193 insertions(+), 183 deletions(-) create mode 100644 embark-ui/src/components/CompilerError.js delete mode 100644 embark-ui/src/reducers/fiddleReducer.js diff --git a/embark-ui/src/actions/index.js b/embark-ui/src/actions/index.js index 834b5d97..61606f13 100644 --- a/embark-ui/src/actions/index.js +++ b/embark-ui/src/actions/index.js @@ -143,30 +143,17 @@ export function listenToContractLogs() { }; } -// Fiddle -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){ +export function initBlockHeader(){ return { - type: COMPILE_CODE_REQUEST, - codeToCompile + type: INIT_BLOCK_HEADER }; } - -export function receiveCodeCompilation(compilationResult){ - return { - type: COMPILE_CODE_SUCCESS, - compilationResult - }; -} - -export function receiveCodeCompilationError(){ - return { - type: COMPILE_CODE_FAILURE - }; -} +export const FIDDLE = createRequestTypes('FIDDLE'); +export const fiddle = { + request: (codeToCompile) => action(FIDDLE[REQUEST], {codeToCompile}), + success: (fiddle) => action(FIDDLE[SUCCESS], {fiddle}), + failure: (error) => action(FIDDLE[FAILURE], {error}) +}; diff --git a/embark-ui/src/api/index.js b/embark-ui/src/api/index.js index 1b159d60..d2a17e75 100644 --- a/embark-ui/src/api/index.js +++ b/embark-ui/src/api/index.js @@ -96,6 +96,6 @@ export function webSocketBlockHeader() { return new WebSocket(`${constants.wsEndpoint}/blockchain/blockHeader`); } -export function fetchCodeCompilation(codeToCompile) { - return axios.post(constants.httpEndpoint + '/contract/compile', {code: codeToCompile}); +export function fetchFiddle(payload) { + return post('/contract/compile', {code: payload.codeToCompile}); } diff --git a/embark-ui/src/components/CompilerError.js b/embark-ui/src/components/CompilerError.js new file mode 100644 index 00000000..954cc892 --- /dev/null +++ b/embark-ui/src/components/CompilerError.js @@ -0,0 +1,27 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import {Badge} from 'tabler-react'; + +const CompilerError = ({key, onClick, errorType, row, errorMessage}) => ( + + + Line {row} + + {errorMessage} + +); + +CompilerError.propTypes = { + key: PropTypes.string, + onClick: PropTypes.func, + errorType: PropTypes.string, + row: PropTypes.number, + errorMessage: PropTypes.string +}; + +export default CompilerError; diff --git a/embark-ui/src/components/FiddleResults.js b/embark-ui/src/components/FiddleResults.js index b79a55d1..6de31f81 100644 --- a/embark-ui/src/components/FiddleResults.js +++ b/embark-ui/src/components/FiddleResults.js @@ -1,57 +1,48 @@ /* eslint {jsx-a11y/anchor-has-content:"off"} */ import React, {Component} from 'react'; -import {Card, List, Badge} from 'tabler-react'; +import {Card, List, Badge, Icon} from 'tabler-react'; import PropTypes from 'prop-types'; +import classNames from 'classnames'; class FiddleResults extends Component { - static _removeClass(elems, className) { - for (let elem of elems) { - elem.className = elem.className.replace(className, '').replace(' ', ' '); - } + constructor(props){ + super(props); + + this.state = { + errorsCollapsed: false, + warningsCollapsed: false, + errorsFullscreen: false, + warningsFullscreen: false + }; } - 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; - } - } - } - - _toggleCollapse(e) { - const collapsedClassName = 'card-collapsed'; + _toggle(e, type){ const className = e.currentTarget.parentElement.className.replace('card-options', '').replace(' ', ''); - const elems = document.getElementsByClassName(className + '-card'); - FiddleResults._toggleClass(elems, collapsedClassName); - } - - _toggleFullscreen(e) { - const collapsedClassName = 'card-collapsed'; - const fullscreenClassName = 'card-fullscreen'; - const className = e.currentTarget.parentElement.className.replace('card-options', '').replace(' ', ''); - const elems = document.getElementsByClassName(className + '-card'); - FiddleResults._toggleClass(elems, fullscreenClassName); - FiddleResults._removeClass(elems, collapsedClassName); + const updatedState = {}; + updatedState[className + type] = !(this.state[className + type]); + this.setState(updatedState); } _getFormatted(errors, errorType){ const color = (errorType === "error" ? "danger" : errorType); + const isFullscreen = Boolean(this.state[errorType + 'sFullscreen']); + const classes = classNames({ + 'card-fullscreen': Boolean(this.state[errorType + 'sFullscreen']), + 'card-collapsed': Boolean(this.state[errorType + 'sCollapsed']) && !isFullscreen + }); return {errorType + "s"} {errors.length} - - + this._toggle(e, 'Collapsed')}/> + this._toggle(e, 'Fullscreen')} /> @@ -63,21 +54,42 @@ class FiddleResults extends Component { } render() { - const {warnings, errors} = this.props; + const {warnings, errors, fatal} = this.props; let renderings = []; - if (errors.length) renderings.push( - - + + ); + } + else if(isFetching){ renderings.push(
Compiling...
); } - if(hasResult && !errors.length){ - renderings.push(Compiled); + else { + 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" : ""} + + ); } - 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} @@ -39,7 +47,8 @@ FiddleResultsSummary.propTypes = { errors: PropTypes.array, warnings: PropTypes.array, isFetching: PropTypes.bool, - hasResult: PropTypes.bool + hasResult: PropTypes.bool, + fatal: PropTypes.string }; export default FiddleResultsSummary; diff --git a/embark-ui/src/components/Layout.js b/embark-ui/src/components/Layout.js index eb6fe588..01f21641 100644 --- a/embark-ui/src/components/Layout.js +++ b/embark-ui/src/components/Layout.js @@ -10,8 +10,8 @@ const navBarItems = [ {value: "Contracts", to: "/embark/contracts", icon: "box", LinkComponent: withRouter(NavLink)}, {value: "Explorer", to: "/embark/explorer/accounts", icon: "activity", LinkComponent: withRouter(NavLink)}, {value: "Processes", to: "/embark/processes", icon: "cpu", LinkComponent: withRouter(NavLink)}, - {value: "Documentation", to: "/embark/documentation", icon: "file-text", LinkComponent: withRouter(NavLink)}, - {value: "Fiddle", to: "/embark/fiddle", icon: "codepen", LinkComponent: withRouter(NavLink)} + {value: "Fiddle", to: "/embark/fiddle", icon: "codepen", LinkComponent: withRouter(NavLink)}, + {value: "Documentation", to: "/embark/documentation", icon: "file-text", LinkComponent: withRouter(NavLink)} ]; const Layout = (props) => ( diff --git a/embark-ui/src/containers/FiddleContainer.js b/embark-ui/src/containers/FiddleContainer.js index 6d1d4794..a0c37024 100644 --- a/embark-ui/src/containers/FiddleContainer.js +++ b/embark-ui/src/containers/FiddleContainer.js @@ -3,12 +3,13 @@ import React, {Component} from 'react'; import {connect} from 'react-redux'; import PropTypes from 'prop-types'; -import {fetchCodeCompilation} from '../actions'; +import {fiddle as fiddleAction} from '../actions'; import Fiddle from '../components/Fiddle'; import FiddleResults from '../components/FiddleResults'; -import FiddleReultsSummary from '../components/FiddleResultsSummary'; -import {Badge} from 'tabler-react'; +import FiddleResultsSummary from '../components/FiddleResultsSummary'; import scrollToComponent from 'react-scroll-to-component'; +import {getFiddle} from "../reducers/selectors"; +import CompilerError from "../components/CompilerError"; class FiddleContainer extends Component { @@ -22,17 +23,11 @@ class FiddleContainer extends Component { this.editor = null; } - componentDidMount() { - if (this.state.value) { - this.props.fetchCodeCompilation(this.state.value); - } - } - _onCodeChange(newValue) { this.setState({value: newValue}); if (this.compileTimeout) clearTimeout(this.compileTimeout); this.compileTimeout = setTimeout(() => { - this.props.fetchCodeCompilation(newValue); + this.props.fetchFiddle(newValue); }, 1000); } @@ -51,17 +46,12 @@ class FiddleContainer extends Component { errors.push({ solcError: error, node: - { this._onErrorClick(e, annotation); }} - key={index} - > - - Line {errorRowCol.row} - - {error.formattedMessage} - , + { this._onErrorClick(e, annotation); }} + key={index} + errorType={errorType} + row={errorRowCol.row} + errorMessage={error.formattedMessage}/>, annotation: annotation }); } @@ -84,22 +74,22 @@ class FiddleContainer extends Component { } render() { - const {fiddles} = this.props; + const {fiddle, loading, error} = this.props; let renderings = []; let warnings = []; let errors = []; - if (fiddles.compilationResult) { - warnings = this._getFormattedErrors(fiddles.compilationResult.errors, "warning"); - errors = this._getFormattedErrors(fiddles.compilationResult.errors, "error"); - + if (fiddle && fiddle.errors) { + warnings = this._getFormattedErrors(fiddle.errors, "warning"); + errors = this._getFormattedErrors(fiddle.errors, "error"); } renderings.push( - ); - if (fiddles.compilationResult) { + if (fiddle || (this.state.value && error)) { renderings.push( ); } @@ -134,19 +125,24 @@ class FiddleContainer extends Component { } } function mapStateToProps(state) { - return { - fiddles: state.fiddles + return { + fiddle: getFiddle(state), + error: state.errorMessage, + loading: state.loading }; } FiddleContainer.propTypes = { - fiddles: PropTypes.object, - fetchCodeCompilation: PropTypes.func + fiddle: PropTypes.object, + error: PropTypes.string, + fetchFiddle: PropTypes.func, + loading: PropTypes.bool }; export default connect( mapStateToProps, { - fetchCodeCompilation + fetchFiddle: fiddleAction.request + //fetchBlock: blockAction.request }, )(FiddleContainer); diff --git a/embark-ui/src/general.css b/embark-ui/src/general.css index 81908363..934ac06f 100644 --- a/embark-ui/src/general.css +++ b/embark-ui/src/general.css @@ -21,47 +21,44 @@ color: #8f98a2; } -.text__new-line { +.text__new-line, .card.warnings-card .list-group-item, .card.errors-card .list-group-item { white-space: pre-line; } .card.card-fullscreen{ - z-index:6; + 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; + 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; + margin-right: 5px; } .ace_editor { - margin-bottom:24px; + margin-bottom: 24px; } .loader, .loader:before, .loader:after{ - width:1.2rem; - height:1.2rem; + width: 1.2rem; + height: 1.2rem; } .loader:before, .loader:after{ - margin:-0.6rem 0 0 -0.6rem; + margin: -0.6rem 0 0 -0.6rem; } .loader, .loader-text{ - display:inline-block; + display: inline-block; vertical-align: middle; } .loader { - margin-right:5px; + 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 deleted file mode 100644 index 5d53d130..00000000 --- a/embark-ui/src/reducers/fiddleReducer.js +++ /dev/null @@ -1,14 +0,0 @@ -import {COMPILE_CODE_REQUEST, COMPILE_CODE_FAILURE, COMPILE_CODE_SUCCESS} from "../actions"; - -export default function processes(state = {}, action) { - switch (action.type) { - 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/reducers/index.js b/embark-ui/src/reducers/index.js index 47795b15..2e7ca707 100644 --- a/embark-ui/src/reducers/index.js +++ b/embark-ui/src/reducers/index.js @@ -1,6 +1,5 @@ import {combineReducers} from 'redux'; import {REQUEST} from "../actions"; -import fiddleRecuder from './fiddleReducer'; const BN_FACTOR = 10000; @@ -16,7 +15,8 @@ const entitiesDefaultState = { commands: [], messages: [], messageChannels: [], - messageVersion: null + messageVersion: null, + fiddle: null }; const sorter = { @@ -97,8 +97,7 @@ function loading(_state = false, action) { const rootReducer = combineReducers({ entities, loading, - errorMessage, - fiddles: fiddleRecuder + errorMessage }); export default rootReducer; diff --git a/embark-ui/src/reducers/selectors.js b/embark-ui/src/reducers/selectors.js index b957c909..164b477c 100644 --- a/embark-ui/src/reducers/selectors.js +++ b/embark-ui/src/reducers/selectors.js @@ -80,3 +80,7 @@ export function getMessages(state) { }); return messages; } + +export function getFiddle(state){ + return state.entities.fiddle; +} diff --git a/embark-ui/src/sagas/index.js b/embark-ui/src/sagas/index.js index 5243cf85..78a0e0e0 100644 --- a/embark-ui/src/sagas/index.js +++ b/embark-ui/src/sagas/index.js @@ -4,7 +4,8 @@ import {eventChannel} from 'redux-saga'; import {all, call, fork, put, takeEvery, take} from 'redux-saga/effects'; const {account, accounts, block, blocks, transaction, transactions, processes, commands, processLogs, - contracts, contract, contractProfile, messageSend, messageVersion, messageListen, contractLogs} = actions; + contracts, contract, contractProfile, messageSend, messageVersion, messageListen, contractLogs, + fiddle} = actions; function *doRequest(entity, apiFn, payload) { const {response, error} = yield call(apiFn, payload); @@ -28,6 +29,7 @@ export const fetchContractLogs = doRequest.bind(null, contractLogs, api.fetchCon export const fetchContracts = doRequest.bind(null, contracts, api.fetchContracts); export const fetchContract = doRequest.bind(null, contract, api.fetchContract); export const fetchContractProfile = doRequest.bind(null, contractProfile, api.fetchContractProfile); +export const fetchFiddle = doRequest.bind(null, fiddle, api.fetchFiddle); export function *watchFetchTransaction() { yield takeEvery(actions.TRANSACTION[actions.REQUEST], fetchTransaction); @@ -157,20 +159,8 @@ export function *watchCommunicationVersion() { yield takeEvery(actions.MESSAGE_VERSION[actions.REQUEST], fetchCommunicationVersion); } -export function *fetchCodeCompilation(action) { - try { - const compilationResponse = yield call(api.fetchCodeCompilation, action.codeToCompile); - if(compilationResponse.status !== 200){ - yield put(actions.receiveCodeCompilationError(compilationResponse.data)); - } - else yield put(actions.receiveCodeCompilation(compilationResponse.data)); - } catch (e) { - yield put(actions.receiveCodeCompilationError(e)); - } -} - -export function *watchFetchCodeCompilation() { - yield takeEvery(actions.COMPILE_CODE_REQUEST, fetchCodeCompilation); +export function *watchFetchFiddle() { + yield takeEvery(actions.FIDDLE[actions.REQUEST], fetchFiddle); } export default function *root() { @@ -194,7 +184,7 @@ export default function *root() { fork(watchFetchContract), fork(watchFetchTransaction), fork(watchFetchContractProfile), - fork(watchFetchCodeCompilation) + fork(watchFetchFiddle) ]); } diff --git a/lib/modules/solidity/index.js b/lib/modules/solidity/index.js index edcf120e..a16aa3da 100644 --- a/lib/modules/solidity/index.js +++ b/lib/modules/solidity/index.js @@ -24,23 +24,26 @@ class Solidity { 'post', '/embark-api/contract/compile', (req, res) => { - this.events.request("contract:compile", req.body.code, (errors, compilationResult) => { - res.send({errors:errors, compilationResult: compilationResult}); + const input = {'fiddler': {content: req.body.code.replace(/\r\n/g, '\n')}}; + this.compile_solidity_code(input, {}, true, (errors, compilationResult) => { + const responseData = {errors: errors, compilationResult: compilationResult}; + this.logger.trace(`POST response /embark-api/contract/compile:\n ${JSON.stringify(responseData)}`); + res.send(responseData); }); } ); } - _compile(jsonObj, returnAllErrors, callback){ + _compile(jsonObj, returnAllErrors, callback) { this.solcW.compile(jsonObj, (err, output) => { - if(err){ + if (err) { return callback(err); } - if(output.errors && returnAllErrors){ + if (output.errors && returnAllErrors) { return callback(output.errors); } if (output.errors) { - for (let i=0; i