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