fix eslint on EVERYTHING

This commit is contained in:
Jonathan Rainville 2018-08-02 15:17:40 -04:00
parent 1ba7cb80e6
commit 4220d1fbf5
32 changed files with 916 additions and 818 deletions

1
.eslintignore Normal file
View File

@ -0,0 +1 @@
lib/modules/webserver/backend/assets/*

View File

@ -10,7 +10,7 @@
], ],
"parserOptions": { "parserOptions": {
"sourceType": "module", "sourceType": "module",
"ecmaVersion": 2017, "ecmaVersion": 2018,
"ecmaFeatures": { "ecmaFeatures": {
"jsx": true "jsx": true
} }
@ -67,7 +67,7 @@
], ],
"dot-notation": "off", "dot-notation": "off",
"eol-last": "error", "eol-last": "error",
"eqeqeq": "off", "eqeqeq": "error",
"for-direction": "error", "for-direction": "error",
"func-call-spacing": "error", "func-call-spacing": "error",
"func-name-matching": "error", "func-name-matching": "error",

View File

@ -3,7 +3,7 @@ import {NavLink, Route, Switch, withRouter} from 'react-router-dom';
import { import {
Page, Page,
Grid, Grid,
List, List
} from "tabler-react"; } from "tabler-react";
import AccountsContainer from '../containers/AccountsContainer'; import AccountsContainer from '../containers/AccountsContainer';

View File

@ -20,7 +20,8 @@ const Transactions = ({transactions}) => (
{content: "From"}, {content: "From"},
{content: "To"}, {content: "To"},
{content: "Type"}, {content: "Type"},
{content: "Hash"}]} {content: "Hash"}
]}
bodyItems={ bodyItems={
transactions.map((transaction) => { transactions.map((transaction) => {
return ([ return ([

View File

@ -11,7 +11,7 @@ class Scaffolding {
} }
generate(contractName, contractConfiguration){ generate(contractName, contractConfiguration){
if(this.framework == 'react'){ if(this.framework === 'react'){
this.embark.plugins.loadInternalPlugin('scaffolding-react', this.options); this.embark.plugins.loadInternalPlugin('scaffolding-react', this.options);
} }
@ -19,7 +19,7 @@ class Scaffolding {
let build = null; let build = null;
dappGenerators.forEach((plugin) => { dappGenerators.forEach((plugin) => {
plugin.dappGenerators.forEach((d) => { plugin.dappGenerators.forEach((d) => {
if(d.framework == this.framework){ if(d.framework === this.framework){
build = d.cb; build = d.cb;
} }
}); });

View File

@ -399,7 +399,7 @@ class ContractsManager {
let orderedDependencies; let orderedDependencies;
try { try {
orderedDependencies = toposort(converted_dependencies.filter((x) => x[0] != x[1])).reverse(); orderedDependencies = toposort(converted_dependencies.filter((x) => x[0] !== x[1])).reverse();
} catch(e) { } catch(e) {
this.logger.error((__("Error: ") + e.message).red); this.logger.error((__("Error: ") + e.message).red);
this.logger.error(__("there are two or more contracts that depend on each other in a cyclic manner").bold.red); this.logger.error(__("there are two or more contracts that depend on each other in a cyclic manner").bold.red);
@ -408,13 +408,11 @@ class ContractsManager {
//process.exit(0); //process.exit(0);
} }
let newList = contractList.sort(function (a, b) { return contractList.sort(function (a, b) {
let order_a = orderedDependencies.indexOf(a.className); let order_a = orderedDependencies.indexOf(a.className);
let order_b = orderedDependencies.indexOf(b.className); let order_b = orderedDependencies.indexOf(b.className);
return order_a - order_b; return order_a - order_b;
}); });
return newList;
} }
// TODO: should be built contracts // TODO: should be built contracts

View File

@ -31,7 +31,7 @@ class Dashboard {
plugin.registerAPICall( plugin.registerAPICall(
'ws', 'ws',
'/embark-api/dashboard', '/embark-api/dashboard',
(ws, req) => { (ws, _req) => {
let dashboardState = {contractsState: [], environment: "", status: "", availableServices: []}; let dashboardState = {contractsState: [], environment: "", status: "", availableServices: []};
// TODO: doesn't feel quite right, should be refactored into a shared // TODO: doesn't feel quite right, should be refactored into a shared

View File

@ -363,6 +363,7 @@ class Embark {
scaffold(options) { scaffold(options) {
const Scaffolding = require('./cmds/scaffolding.js'); const Scaffolding = require('./cmds/scaffolding.js');
const Engine = require('./core/engine.js');
// initialise embark engine // initialise embark engine
let engine = new Engine({ let engine = new Engine({

View File

@ -58,7 +58,7 @@ class GraphGenerator {
for (let i = 0; i < contract.abiDefinition.length; i++) { for (let i = 0; i < contract.abiDefinition.length; i++) {
let abiDef = contract.abiDefinition[i]; let abiDef = contract.abiDefinition[i];
if (abiDef.type == 'event' && options.skipEvents) continue; if (abiDef.type === 'event' && options.skipEvents) continue;
if (['constructor', 'fallback'].indexOf(abiDef.type) > -1 && options.skipFunctions) continue; if (['constructor', 'fallback'].indexOf(abiDef.type) > -1 && options.skipFunctions) continue;
switch(abiDef.type){ switch(abiDef.type){
@ -68,14 +68,14 @@ class GraphGenerator {
case 'constructor': case 'constructor':
contractLabel += "«constructor»("; contractLabel += "«constructor»(";
abiDef.inputs.forEach(function(elem, index){ abiDef.inputs.forEach(function(elem, index){
contractLabel += (index == 0 ? "" : ", ") + elem.type; contractLabel += (index === 0 ? "" : ", ") + elem.type;
}); });
contractLabel += ")\\l"; contractLabel += ")\\l";
break; break;
case 'event': case 'event':
contractLabel += "«event»" + abiDef.name + "("; contractLabel += "«event»" + abiDef.name + "(";
abiDef.inputs.forEach(function(elem, index){ abiDef.inputs.forEach(function(elem, index){
contractLabel += (index == 0 ? "" : ", ") + elem.type; contractLabel += (index === 0 ? "" : ", ") + elem.type;
}); });
contractLabel += ")\\l"; contractLabel += ")\\l";
break; break;
@ -84,7 +84,7 @@ class GraphGenerator {
} }
let fHashes = contract.functionHashes; let fHashes = contract.functionHashes;
if (fHashes != {} && fHashes != undefined && !options.skipFunctions){ if (fHashes !== {} && fHashes !== undefined && !options.skipFunctions){
for (let method in contract.functionHashes){ for (let method in contract.functionHashes){
contractLabel += method + '\\l'; contractLabel += method + '\\l';
} }

View File

@ -17,7 +17,7 @@ class Npm {
} }
_isInstalling(packageName, version){ _isInstalling(packageName, version){
return typeof this._installing[packageName + version] != 'undefined'; return typeof this._installing[packageName + version] !== 'undefined';
} }
getPackageVersion(packageName, version, callback) { getPackageVersion(packageName, version, callback) {

View File

@ -6,7 +6,7 @@ i18n.setOrDetectLocale('en');
class NpmTimer{ class NpmTimer{
constructor(options){ constructor(options){
this._logger = (options.logger && typeof options.logger.info == 'function') ? options.logger : console; this._logger = (options.logger && typeof options.logger.info === 'function') ? options.logger : console;
this._packageName = options.packageName; this._packageName = options.packageName;
this._version = options.version; this._version = options.version;
this._showSpinner = options.showSpinner || false; this._showSpinner = options.showSpinner || false;
@ -24,7 +24,7 @@ class NpmTimer{
} }
get observer(){ get observer(){
if(typeof this._observer == 'undefined'){ if(typeof this._observer === 'undefined'){
this._observer = new PerformanceObserver((items) => { this._observer = new PerformanceObserver((items) => {
let entry; let entry;
let strDuration; let strDuration;

View File

@ -15,7 +15,7 @@ class ContractFuzzer {
generateFuzz(iterations, contract) { generateFuzz(iterations, contract) {
const self = this; const self = this;
let fuzzMap = {}; let fuzzMap = {};
contract.abiDefinition.filter((x) => x.inputs && x.inputs.length != 0 && x.type != "event").forEach((abiMethod) => { contract.abiDefinition.filter((x) => x.inputs && x.inputs.length !== 0 && x.type !== "event").forEach((abiMethod) => {
let name = abiMethod.type === "constructor" ? "constructor" : abiMethod.name; let name = abiMethod.type === "constructor" ? "constructor" : abiMethod.name;
let inputTypes = abiMethod.inputs.map(input => input.type); let inputTypes = abiMethod.inputs.map(input => input.type);
fuzzMap[name] = {}; fuzzMap[name] = {};
@ -49,9 +49,9 @@ class ContractFuzzer {
let length = arraySize === undefined || arraySize === null || arraySize === '' ? Math.floor((Math.random() * 256) + 1) : arraySize; let length = arraySize === undefined || arraySize === null || arraySize === '' ? Math.floor((Math.random() * 256) + 1) : arraySize;
return self.generateArrayOfType(length, type); return self.generateArrayOfType(length, type);
} }
case kind == "bool": case kind === "bool":
return self.generateRandomBool(); return self.generateRandomBool();
case kind == "uint" || kind == "int": case kind === "uint" || kind === "int":
return self.generateRandomInt(size); return self.generateRandomInt(size);
case kind === "bytes" && size !== undefined: case kind === "bytes" && size !== undefined:
return self.generateRandomStaticBytes(size); return self.generateRandomStaticBytes(size);

View File

@ -23,7 +23,7 @@ class GasEstimator {
// already provided for us // already provided for us
gasMap['constructor'] = contract.gasEstimates.creation.totalCost.toString(); gasMap['constructor'] = contract.gasEstimates.creation.totalCost.toString();
return gasCb(null, name, abiMethod.type); return gasCb(null, name, abiMethod.type);
} else if (abiMethod.type == "fallback") { } else if (abiMethod.type === "fallback") {
gasMap['fallback'] = contract.gasEstimates.external[""].toString(); gasMap['fallback'] = contract.gasEstimates.external[""].toString();
return gasCb(null, name, abiMethod.type); return gasCb(null, name, abiMethod.type);
} else if ( } else if (

View File

@ -7,7 +7,7 @@ Handlebars.registerHelper('capitalize', function(word) {
}); });
Handlebars.registerHelper('ifview', function(stateMutability, options) { Handlebars.registerHelper('ifview', function(stateMutability, options) {
let result = stateMutability == 'view' || stateMutability == 'pure' || stateMutability == 'constant'; let result = stateMutability === 'view' || stateMutability === 'pure' || stateMutability === 'constant';
if (result) { if (result) {
return options.fn(this); return options.fn(this);
} }
@ -15,7 +15,7 @@ Handlebars.registerHelper('ifview', function(stateMutability, options) {
}); });
Handlebars.registerHelper('ifeq', function(elem, value, options){ Handlebars.registerHelper('ifeq', function(elem, value, options){
if (elem == value) { if (elem === value) {
return options.fn(this); return options.fn(this);
} }
return options.inverse(this); return options.inverse(this);
@ -34,8 +34,8 @@ Handlebars.registerHelper('emptyname', function(name, index) {
Handlebars.registerHelper('methodname', function(abiDefinition, functionName, inputs){ Handlebars.registerHelper('methodname', function(abiDefinition, functionName, inputs){
let funCount = abiDefinition.filter(x => x.name == functionName).length; let funCount = abiDefinition.filter(x => x.name === functionName).length;
if(funCount == 1){ if(funCount === 1){
return '.' + functionName; return '.' + functionName;
} }
return new Handlebars.SafeString(`['${functionName}(${inputs !== null ? inputs.map(input => input.type).join(',') : ''})']`); return new Handlebars.SafeString(`['${functionName}(${inputs !== null ? inputs.map(input => input.type).join(',') : ''})']`);
@ -74,7 +74,7 @@ class ScaffoldingReact {
}); });
} }
async build(contract){ build(contract){
this._buildHTML(contract); this._buildHTML(contract);
const filename = contract.className.toLowerCase(); const filename = contract.className.toLowerCase();
@ -83,7 +83,7 @@ class ScaffoldingReact {
{ {
'title': contract.className, 'title': contract.className,
'contractName': contract.className, 'contractName': contract.className,
'functions': contract.abiDefinition.filter(x => x.type == 'function') 'functions': contract.abiDefinition.filter(x => x.type === 'function')
}); });
// Update config // Update config

View File

@ -21,7 +21,6 @@ class Solidity {
} }
let self = this; let self = this;
let input = {}; let input = {};
let solcW;
let originalFilepath = {}; let originalFilepath = {};
async.waterfall([ async.waterfall([

View File

@ -76,7 +76,7 @@ process.on('message', (msg) => {
return process.send({result: "loadedCompiler"}); return process.send({result: "loadedCompiler"});
} }
else if (msg.action == 'installAndLoadCompiler') { else if (msg.action === 'installAndLoadCompiler') {
solcProcess.installAndLoadCompiler(msg.solcVersion, msg.packagePath).then(() => { solcProcess.installAndLoadCompiler(msg.solcVersion, msg.packagePath).then(() => {
return process.send({result: "loadedCompiler"}); return process.send({result: "loadedCompiler"});
}); });

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,7 @@
import React from 'react';
import ContractContext from './contract-context';
import CardAlert from './card-alert';
class AccountList extends React.Component { class AccountList extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
@ -12,7 +16,7 @@ class AccountList extends React.Component {
} }
async handleClick(e, updateAccountsCallback){ handleClick(e, updateAccountsCallback) {
e.preventDefault(); e.preventDefault();
try { try {
@ -21,7 +25,7 @@ class AccountList extends React.Component {
this.setState({ this.setState({
error: true, error: true,
errorMessage: e.name + ': ' + e.message errorMessage: e.name + ': ' + e.message
}) });
} }
} }
@ -57,7 +61,8 @@ class AccountList extends React.Component {
</code> </code>
</div> </div>
<div className="col-md-1"> <div className="col-md-1">
<button className="btn btn-primary ml-auto" onClick={event => this.handleClick(event, context.updateAccounts)}>&#9166;</button> <button className="btn btn-primary ml-auto"
onClick={event => this.handleClick(event, context.updateAccounts)}>&#9166;</button>
</div> </div>
</div> </div>
<div className="card-footer"> <div className="card-footer">
@ -73,3 +78,5 @@ class AccountList extends React.Component {
</ContractContext.Consumer>; </ContractContext.Consumer>;
} }
} }
export default AccountList;

View File

@ -1,13 +1,15 @@
import React from 'react';
import PropTypes from 'prop-types';
class CardAlert extends React.Component { class CardAlert extends React.Component {
render() { render() {
return this.props.show ? return this.props.show ? <div className="card-alert alert alert-danger mb-0">{this.props.message}</div> : '';
<div className="card-alert alert alert-danger mb-0">
{this.props.message}
</div>
:
'';
} }
} }
CardAlert.propTypes = {
show: PropTypes.bool,
message: PropTypes.string
};
export default CardAlert;

View File

@ -1,7 +1,12 @@
import React from 'react';
const ContractContext = React.createContext({ const ContractContext = React.createContext({
accounts: [], accounts: [],
instances: [], instances: [],
updateAccounts: () => {}, updateAccounts: () => {
updateInstances: (_instance) => {} },
updateInstances: (_instance) => {
}
}); });
export default ContractContext;

View File

@ -1,3 +1,14 @@
/*global web3*/
import React from 'react';
import ContractContext from './contract-context';
import MenuItem from './menu-item';
import AccountList from './account-list';
import FunctionArea from './function-area';
import Tab from './tab';
import InstanceSelector from './instance-selector';
import SourceArea from './source-area';
import PropTypes from 'prop-types';
class ContractUI extends React.Component { class ContractUI extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
@ -16,7 +27,7 @@ class ContractUI extends React.Component {
selectedTab: 'deploy' selectedTab: 'deploy'
}; };
if(props.contract.options.address != null){ if (props.contract.options.address !== null) {
this.state.instances = [props.contract.options.address]; this.state.instances = [props.contract.options.address];
this.state.selectedInstance = props.contract.options.address; this.state.selectedInstance = props.contract.options.address;
} }
@ -54,7 +65,7 @@ class ContractUI extends React.Component {
this.props.contract.options.address = _instance; this.props.contract.options.address = _instance;
this.setState({ this.setState({
selectedInstance: _instance selectedInstance: _instance
}) });
} }
render() { render() {
@ -65,9 +76,12 @@ class ContractUI extends React.Component {
<h3 className="page-title mb-5">{this.props.name}</h3> <h3 className="page-title mb-5">{this.props.name}</h3>
<div> <div>
<div className="list-group list-group-transparent mb-0"> <div className="list-group list-group-transparent mb-0">
<MenuItem icon="fe-file-plus" click={this.handleMenuClick} selectedTab={this.state.selectedTab} target="deploy" text="Deployment / Utils" /> <MenuItem icon="fe-file-plus" click={this.handleMenuClick} selectedTab={this.state.selectedTab}
<MenuItem icon="fe-list" click={this.handleMenuClick} selectedTab={this.state.selectedTab} target="functions" text="Functions" /> target="deploy" text="Deployment / Utils"/>
<MenuItem icon="fe-file-text" click={this.handleMenuClick} selectedTab={this.state.selectedTab} target="contract" text="Source Code" /> <MenuItem icon="fe-list" click={this.handleMenuClick} selectedTab={this.state.selectedTab}
target="functions" text="Functions"/>
<MenuItem icon="fe-file-text" click={this.handleMenuClick} selectedTab={this.state.selectedTab}
target="contract" text="Source Code"/>
</div> </div>
</div> </div>
</div> </div>
@ -77,28 +91,29 @@ class ContractUI extends React.Component {
<div className="card"> <div className="card">
<div className="card-body"> <div className="card-body">
<ul> <ul>
<li>Open your browser's console: <code>Tools &gt; Developer Tools</code></li> <li>Open your browser&apos;s console: <code>Tools &gt; Developer Tools</code></li>
<li>Remix: <a href="https://remix.ethereum.org" target="_blank">http://remix.ethereum.org</a></li> <li>Remix: <a href="https://remix.ethereum.org" target="_blank" rel="noopener noreferrer">http://remix.ethereum.org</a></li>
</ul> </ul>
</div> </div>
</div> </div>
<AccountList accountUpdate={this.updateAccounts}/> <AccountList accountUpdate={this.updateAccounts}/>
<h5>Deploy</h5> <h5>Deploy</h5>
{ {
this.props.definition.code == "" ? <p>Interface or set to not deploy</p>: "" this.props.definition.code === "" ? <p>Interface or set to not deploy</p> : ""
} }
<FunctionArea definition={this.props.definition} contractName={this.props.name} contract={this.props.contract} type="constructor" /> <FunctionArea definition={this.props.definition} contractName={this.props.name}
contract={this.props.contract} type="constructor"/>
</Tab> </Tab>
<Tab id="functions" selectedTab={this.state.selectedTab}> <Tab id="functions" selectedTab={this.state.selectedTab}>
<h4 className="mb-5">Functions</h4> <h4 className="mb-5">Functions</h4>
{ {(this.props.definition.code !== "") && <InstanceSelector selectedInstance={this.state.selectedInstance}
this.props.definition.code != "" ? instanceUpdate={this.handleInstanceSelection}/>
<InstanceSelector selectedInstance={this.state.selectedInstance} instanceUpdate={this.handleInstanceSelection} />
: ""
} }
<FunctionArea definition={this.props.definition} contractName={this.props.name} contract={this.props.contract} type="function" /> <FunctionArea definition={this.props.definition} contractName={this.props.name}
<FunctionArea definition={this.props.definition} contractName={this.props.name} contract={this.props.contract} type="fallback" /> contract={this.props.contract} type="function"/>
<FunctionArea definition={this.props.definition} contractName={this.props.name}
contract={this.props.contract} type="fallback"/>
</Tab> </Tab>
<Tab id="contract" selectedTab={this.state.selectedTab}> <Tab id="contract" selectedTab={this.state.selectedTab}>
@ -106,28 +121,21 @@ class ContractUI extends React.Component {
<SourceArea definition={this.props.definition} source={this.props.source}/> <SourceArea definition={this.props.definition} source={this.props.source}/>
</Tab> </Tab>
</div> </div>
</div>, </div>
,
</ContractContext.Provider> </ContractContext.Provider>
) );
} }
} }
ContractUI.propTypes = {
definition: PropTypes.object,
source: PropTypes.string,
contract: PropTypes.object,
name: PropTypes.string
};
export default ContractUI;

View File

@ -1,3 +1,7 @@
import React from 'react';
import FunctionForm from './function-form';
import PropTypes from 'prop-types';
class FunctionArea extends React.Component { class FunctionArea extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
@ -12,9 +16,21 @@ class FunctionArea extends React.Component {
return <React.Fragment> return <React.Fragment>
{ {
this.props.contract.options.jsonInterface this.props.contract.options.jsonInterface
.filter(item => item.type == type) .filter(item => item.type === type)
.map((item, i) => <FunctionForm definition={this.props.definition} key={i} contract={contract} contractName={contractName} abi={item} instanceUpdate={this.props.instanceUpdate} />) .map((item, i) => <FunctionForm definition={this.props.definition} key={i} contract={contract}
contractName={contractName} abi={item}
instanceUpdate={this.props.instanceUpdate}/>)
} }
</React.Fragment>; </React.Fragment>;
} }
} }
FunctionArea.propTypes = {
type: PropTypes.string,
contract: PropTypes.object,
contractName: PropTypes.string,
definition: PropTypes.object,
instanceUpdate: PropTypes.func
};
export default FunctionArea;

View File

@ -1,3 +1,8 @@
import React from 'react';
import CardAlert from './card-alert';
import Function from './function';
import PropTypes from 'prop-types';
class FunctionForm extends React.Component { class FunctionForm extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
@ -18,28 +23,107 @@ class FunctionForm extends React.Component {
this.child.current.copyCommand(e); this.child.current.copyCommand(e);
} }
_getFunctionParamFields(elem){ _getFunctionParamFields(_elem) {
if(this.props.abi.type == 'fallback') return ''; if (this.props.abi.type === 'fallback') return '';
return '(' + this.props.abi.inputs return '(' + this.props.abi.inputs
.map((input, i) => <input type="text" data-var-type={input.type} data-type="inputParam" data-name={input.name} placeholder={input.name} title={input.type + ' ' + input.name} size={input.name.length} />) .map((input, i) => <input type="text" data-var-type={input.type} data-type="inputParam" data-name={input.name}
placeholder={input.name} title={input.type + ' ' + input.name}
size={input.name.length}
key={'input' + i}/>)
.join(', ') + ')'; .join(', ') + ')';
} }
_getMethodType(elem){ _getMethodType(_elem) {
return (this.props.abi.constant == true || this.props.abi.stateMutability == 'view' || this.props.abi.stateMutability == 'pure') ? 'call' : 'send'; return (this.props.abi.constant === true || this.props.abi.stateMutability === 'view' || this.props.abi.stateMutability === 'pure') ? 'call' : 'send';
}
renderContent(receipt, contract) {
if (receipt === null && (this.state.error || this.state.message === null)) {
return '';
}
let messagesList;
if (this.props.abi.outputs.filter(x => x.name !== "").length > 0) {
messagesList = Object.keys(this.state.message).map((key, index) => {
if (isNaN(key)) {
return <li key={index}>{key}: {this.state.message[key]}</li>;
} else {
return '';
}
});
} else {
messagesList = Object.keys(this.state.message).map((key, index) => {
return <li key={index}>{key}: {this.state.message[key]}</li>;
});
}
let message;
if (this.state.message !== null && typeof this.state.message === 'object') {
message = <ul>
{messagesList}
</ul>;
} else if (typeof this.state.message === "boolean") {
message = (this.state.message ? 'true' : 'false');
} else {
message = this.state.message;
}
return (<div className="card-footer">
{receipt && <ul>
<li>Status: {receipt.status}</li>
<li>Transaction Hash: {receipt.transactionHash}</li>
{
receipt.events && <li>Events:
<ul>
{
Object.keys(receipt.events).map(function(ev, index) {
if (!isNaN(ev)) return null;
const eventAbi = contract.options.jsonInterface.filter(x => x.name === ev)[0];
let props = [];
for (let prop in receipt.events[ev].returnValues) {
if (isNaN(prop)) {
let input = eventAbi.inputs.filter(x => x.name === prop)[0];
props.push(prop + ': ' +
(input.type.indexOf('int') === -1 ? '"' : '') +
receipt.events[ev].returnValues[prop] +
(input.type.indexOf('int') === -1 ? '"' : ''));
}
}
return <li key={index}>{ev}({props.join(', ')})</li>;
})
}
</ul>
</li>
}
</ul>
}
{
!this.state.error && this.state.message && <React.Fragment>
{message}
</React.Fragment>}
</div>);
} }
render() { render() {
const functionName = this.props.abi.name; const functionName = this.props.abi.name;
const isDuplicated = this.props.contract.options.jsonInterface.filter(x => x.name == functionName).length > 1; const isDuplicated = this.props.contract.options.jsonInterface.filter(x => x.name === functionName).length > 1;
const contract = this.props.contract; const contract = this.props.contract;
const receipt = this.state.receipt; const receipt = this.state.receipt;
let title;
if (this.props.abi.type === 'function') {
title = this.props.abi.name;
} else if (this.props.abi.type === 'fallback') {
title = '(fallback)';
} else {
title = this.props.abi.name;
}
return <div className="card function"> return <div className="card function">
<div className="card-header"> <div className="card-header">
<h3 className="card-title">{this.props.abi.type == 'function' ? this.props.abi.name : (this.props.abi.type == 'fallback' ? '(fallback)' : this.props.abi.name)}</h3> <h3
className="card-title">{title}</h3>
<div className="card-options"> <div className="card-options">
<a href="#" onClick={this.handleCopyClick} title="Copy to clipboard"><i className="fe fe-copy"></i></a> <a href="#" onClick={this.handleCopyClick} title="Copy to clipboard"><i className="fe fe-copy"></i></a>
</div> </div>
@ -48,81 +132,11 @@ class FunctionForm extends React.Component {
<CardAlert show={this.state.error} message={this.state.message}/> <CardAlert show={this.state.error} message={this.state.message}/>
<div className="card-body row"> <div className="card-body row">
<Function ref={this.child} definition={this.props.definition} contract={this.props.contract} contractName={this.props.contractName} duplicated={isDuplicated} abi={this.props.abi} resultHandler={this.showResults} /> <Function ref={this.child} definition={this.props.definition} contract={this.props.contract}
contractName={this.props.contractName} duplicated={isDuplicated} abi={this.props.abi}
resultHandler={this.showResults}/>
</div> </div>
{ {this.renderContent(receipt, contract)}
receipt != null || !this.state.error && this.state.message != null
?
<div className="card-footer">
{ receipt != null ?
<ul>
<li>Status: {receipt.status}</li>
<li>Transaction Hash: {receipt.transactionHash}</li>
{
receipt.events != null ?
<li>Events:
<ul>
{
Object.keys(receipt.events).map(function(ev, index) {
if(!isNaN(ev)) return null;
const eventAbi = contract.options.jsonInterface.filter(x => x.name == ev)[0];
let props = [];
for(let prop in receipt.events[ev].returnValues){
if(isNaN(prop)){
let input = eventAbi.inputs.filter(x => x.name == prop)[0];
props.push(prop + ': '
+ (input.type.indexOf('int') == -1 ? '"' : '')
+ receipt.events[ev].returnValues[prop]
+ (input.type.indexOf('int') == -1 ? '"' : ''));
}
}
return <li key={index}>{ev}({props.join(', ')})</li>;
})
}
</ul>
</li>
: ''
}
</ul>
: ""
}
{
!this.state.error && this.state.message != null
?
<React.Fragment>{
(this.state.message !== null && typeof this.state.message === 'object')
?
(
<ul>
{
this.props.abi.outputs.filter(x => x.name !== "").length > 0
?
Object.keys(this.state.message).map((key, index) => {
if(isNaN(key)){
return <li key={index}>{key}: {this.state.message[key]}</li>
} else {
return '';
}
})
:
Object.keys(this.state.message).map((key, index) => {
return <li key={index}>{key}: {this.state.message[key]}</li>
})
}
</ul>
)
:
(typeof this.state.message === "boolean" ?
(this.state.message ? 'true' : 'false')
:
this.state.message)
}</React.Fragment>
: '' }
</div>
: ''
}
</div>; </div>;
} }
@ -131,6 +145,15 @@ class FunctionForm extends React.Component {
error: _error, error: _error,
message: _message, message: _message,
receipt: _receipt receipt: _receipt
}) });
} }
} }
FunctionForm.propTypes = {
abi: PropTypes.object,
contract: PropTypes.object,
definition: PropTypes.object,
contractName: PropTypes.string
};
export default FunctionForm;

View File

@ -1,3 +1,8 @@
/*global web3*/
import React from 'react';
import ContractContext from './contract-context';
import PropTypes from 'prop-types';
class Function extends React.Component { class Function extends React.Component {
constructor(props) { constructor(props) {
@ -24,15 +29,12 @@ class Function extends React.Component {
copyCommand(e) { copyCommand(e) {
e.preventDefault(); e.preventDefault();
let fields = this.state.fields;
let functionLabel = this._getFunctionLabel(); let functionLabel = this._getFunctionLabel();
let functionParams = this._getFunctionParamString(); let functionParams = this._getFunctionParamString();
let methodParams = this._getMethodString(); let methodParams = this._getMethodString();
if(this.props.abi.type == "constructor") if (this.props.abi.type === "constructor") functionParams = `{arguments: [${functionParams}]}`;
functionParams = `{arguments: [${functionParams}]}`;
const command = `await ${functionLabel}(${functionParams})${this.props.abi.type != 'fallback' ? '.' + this._getMethodType() : ''}${methodParams}`; const command = `await ${functionLabel}(${functionParams})${this.props.abi.type !== 'fallback' ? '.' + this._getMethodType() : ''}${methodParams}`;
var dummy = document.createElement("input"); var dummy = document.createElement("input");
document.body.appendChild(dummy); document.body.appendChild(dummy);
@ -43,7 +45,6 @@ class Function extends React.Component {
} }
async handleClick(e, instanceUpdateCallback) { async handleClick(e, instanceUpdateCallback) {
e.preventDefault(); e.preventDefault();
@ -54,12 +55,11 @@ class Function extends React.Component {
let executionParams = { let executionParams = {
from: this.state.methodFields.from, from: this.state.methodFields.from,
gasLimit: this.state.methodFields.gasLimit gasLimit: this.state.methodFields.gasLimit
} };
if(this.props.abi.payable) if (this.props.abi.payable) executionParams.value = this.state.methodFields.value;
executionParams.value = this.state.methodFields.value;
if(this.props.abi.type == 'fallback'){ if (this.props.abi.type === 'fallback') {
executionParams.data = this.state.methodFields.data; executionParams.data = this.state.methodFields.data;
executionParams.to = this.props.contract.options.address; executionParams.to = this.props.contract.options.address;
} }
@ -69,15 +69,14 @@ class Function extends React.Component {
let functionLabel = this._getFunctionLabel(); let functionLabel = this._getFunctionLabel();
let functionParams = this._getFunctionParamString(); let functionParams = this._getFunctionParamString();
let methodParams = this._getMethodString(); let methodParams = this._getMethodString();
if(this.props.abi.type == "constructor") if (this.props.abi.type === "constructor") functionParams = `{arguments: [${functionParams}]}`;
functionParams = `{arguments: [${functionParams}]}`;
console.log(`%cawait ${functionLabel}(${functionParams})${this.props.abi.type != 'fallback' ? '.' + this._getMethodType() : ''}${methodParams}`, 'font-weight: bold'); console.log(`%cawait ${functionLabel}(${functionParams})${this.props.abi.type !== 'fallback' ? '.' + this._getMethodType() : ''}${methodParams}`, 'font-weight: bold');
let _receipt; let _receipt;
try { try {
if(this.props.abi.type == 'constructor'){ if (this.props.abi.type === 'constructor') {
let contractInstance = await this.props.contract.deploy({arguments: Object.keys(fields).map(val => fields[val])}).send(executionParams); let contractInstance = await this.props.contract.deploy({arguments: Object.keys(fields).map(val => fields[val])}).send(executionParams);
instanceUpdateCallback(contractInstance.options.address); instanceUpdateCallback(contractInstance.options.address);
this.setState({onRequest: false}); this.setState({onRequest: false});
@ -85,18 +84,15 @@ class Function extends React.Component {
this.props.resultHandler(false, 'New instance: ' + contractInstance.options.address); this.props.resultHandler(false, 'New instance: ' + contractInstance.options.address);
} else { } else {
if(this.props.abi.type == 'fallback') if (this.props.abi.type === 'fallback') _receipt = await web3.eth.sendTransaction(executionParams);
_receipt = await web3.eth.sendTransaction(executionParams); else _receipt = await this.props.contract
else
_receipt = await this.props.contract
.methods[this.props.abi.name + '(' + this.props.abi.inputs.map(input => input.type).join(',') + ')'] .methods[this.props.abi.name + '(' + this.props.abi.inputs.map(input => input.type).join(',') + ')']
.apply(null, Object.keys(fields).map(val => { .apply(null, Object.keys(fields).map(val => {
let input = this.props.abi.inputs.filter(x => x.name == val)[0]; let input = this.props.abi.inputs.filter(x => x.name === val)[0];
return input.type.indexOf('bool') == -1 ? fields[val] : (fields[val].toLowerCase() === 'true') return input.type.indexOf('bool') === -1 ? fields[val] : (fields[val].toLowerCase() === 'true');
})) }))[this._getMethodType()](executionParams);
[this._getMethodType()](executionParams)
if(this._getMethodType() == 'call'){ if (this._getMethodType() === 'call') {
this.props.resultHandler(false, _receipt, null); this.props.resultHandler(false, _receipt, null);
} else { } else {
this.props.resultHandler(false, null, _receipt); this.props.resultHandler(false, null, _receipt);
@ -107,10 +103,10 @@ class Function extends React.Component {
} }
} catch (e) { } catch (err) {
console.error('%s: %s', e.name, e.message); console.error('%s: %s', err.name, err.message);
this.setState({onRequest: false}); this.setState({onRequest: false});
this.props.resultHandler(true, e.name + ": " + e.message, _receipt); this.props.resultHandler(true, err.name + ": " + err.message, _receipt);
} }
} }
@ -124,34 +120,31 @@ class Function extends React.Component {
let newState = this.state; let newState = this.state;
newState.methodFields[e.target.getAttribute('data-param')] = e.target.value; newState.methodFields[e.target.getAttribute('data-param')] = e.target.value;
if(e.target.getAttribute('data-param') == 'from'){ if (e.target.getAttribute('data-param') === 'from') {
newState.selectedAccount = e.target.options[e.target.selectedIndex].text; newState.selectedAccount = e.target.options[e.target.selectedIndex].text;
} }
this.setState(newState); this.setState(newState);
} }
_getFunctionLabel() { _getFunctionLabel() {
if(this.props.abi.type == 'function') if (this.props.abi.type === 'function') if (!this.props.duplicated) return `${this.props.contractName}.methods.${this.props.abi.name}`;
if(!this.props.duplicated)
return `${this.props.contractName}.methods.${this.props.abi.name}`;
else { else {
return `${this.props.contractName}.methods['${this.props.abi.name + '(' + (this.props.abi.inputs != null ? this.props.abi.inputs.map(input => input.type).join(',') : '') + ')'}']`; return `${this.props.contractName}.methods['${this.props.abi.name + '(' + (this.props.abi.inputs !== null ? this.props.abi.inputs.map(input => input.type).join(',') : '') + ')'}']`;
} }
else if(this.props.abi.type == 'fallback'){ else if (this.props.abi.type === 'fallback') {
return `web3.eth.sendTransaction`; return `web3.eth.sendTransaction`;
} }
else else return `${this.props.contractName}.deploy`;
return `${this.props.contractName}.deploy`;
} }
_getMethodType() { _getMethodType() {
return (this.props.abi.constant == true || this.props.abi.stateMutability == 'view' || this.props.abi.stateMutability == 'pure') ? 'call' : 'send'; return (this.props.abi.constant === true || this.props.abi.stateMutability === 'view' || this.props.abi.stateMutability === 'pure') ? 'call' : 'send';
} }
_getMethodFields(accounts) { _getMethodFields(accounts) {
let methodParams;
return <React.Fragment> return <React.Fragment>
from: <select data-param="from" disabled={accounts.length == 0} value={this.state.from} onChange={this.handleMethodFieldChange}> from: <select data-param="from" disabled={accounts.length === 0} value={this.state.from}
onChange={this.handleMethodFieldChange}>
<option>-</option> <option>-</option>
{ {
accounts.map(function(item, i) { accounts.map(function(item, i) {
@ -159,27 +152,22 @@ class Function extends React.Component {
}) })
} }
</select> </select>
{ {this.props.abi.payable &&
this.props.abi.payable ?
<span>, value: <span>, value:
<input type="text" data-param="value" value={this.state.methodFields.value} size="6" onChange={this.handleMethodFieldChange} /> <input type="text" data-param="value" value={this.state.methodFields.value} size="6"
onChange={this.handleMethodFieldChange}/>
</span> </span>
: ''
} }
{ {this._getMethodType() === 'send' &&
this._getMethodType() == 'send' ?
<span>, gasLimit: <span>, gasLimit:
<input type="text" data-param="gasLimit" value={this.state.methodFields.gasLimit} size="6" onChange={this.handleMethodFieldChange} /> <input type="text" data-param="gasLimit" value={this.state.methodFields.gasLimit} size="6"
</span> onChange={this.handleMethodFieldChange}/>
: '' </span>}
} {this._getMethodType() === 'send' && this.props.abi.type === 'fallback' &&
{
this._getMethodType() == 'send' && this.props.abi.type == 'fallback' ?
<span>, data: <span>, data:
<input type="text" data-param="data" value={this.state.methodFields.data} size="6" onChange={this.handleMethodFieldChange} /> <input type="text" data-param="data" value={this.state.methodFields.data} size="6"
</span> onChange={this.handleMethodFieldChange}/>
: '' </span>}
}
</React.Fragment>; </React.Fragment>;
} }
@ -188,32 +176,35 @@ class Function extends React.Component {
return <React.Fragment> return <React.Fragment>
{ {
this.props.abi.inputs this.props.abi.inputs
.map((input, i) => <input key={i} type="text" data-var-type={input.type} data-type="inputParam" data-name={input.name} placeholder={input.name} title={input.type + ' ' + input.name} size={input.name.length} value={this.state.fields[input.name] || ''} onChange={this.handleParameterChange} />) .map((input, i) => <input key={i} type="text" data-var-type={input.type} data-type="inputParam"
data-name={input.name} placeholder={input.name}
title={input.type + ' ' + input.name} size={input.name.length}
value={this.state.fields[input.name] || ''} onChange={this.handleParameterChange}/>)
.reduce((accu, elem) => { .reduce((accu, elem) => {
return accu === null ? [elem] : [...accu, ', ', elem] return accu === null ? [elem] : [...accu, ', ', elem];
}, null) }, null)
} }
</React.Fragment>; </React.Fragment>;
} }
_getFunctionParamString() { _getFunctionParamString() {
if(this.props.abi.type == 'fallback') return ''; if (this.props.abi.type === 'fallback') return '';
return this.props.abi.inputs return this.props.abi.inputs
.map((input, i) => (input.type.indexOf('int') == -1 && input.type.indexOf('bool') == -1 ? '"' : '') + (this.state.fields[input.name] || (input.type.indexOf('int') == -1 ? '' : '0')) + (input.type.indexOf('int') == -1 ? '"' : '')) .map((input, _i) => (input.type.indexOf('int') === -1 && input.type.indexOf('bool') === -1 ? '"' : '') + (this.state.fields[input.name] || (input.type.indexOf('int') === -1 ? '' : '0')) + (input.type.indexOf('int') === -1 ? '"' : ''))
.join(', '); .join(', ');
} }
_getMethodString(elem){ _getMethodString(_elem) {
let methodParams = "({"; let methodParams = "({";
methodParams += `from: ` + (this.state.selectedAccount || '"0x00"'); methodParams += `from: ` + (this.state.selectedAccount || '"0x00"');
if(this._getMethodType() == 'send'){ if (this._getMethodType() === 'send') {
methodParams += ', gasLimit: ' + (this.state.methodFields.gasLimit || 0) methodParams += ', gasLimit: ' + (this.state.methodFields.gasLimit || 0);
if (this.props.abi.payable) { if (this.props.abi.payable) {
methodParams += ', value: ' + (this.state.methodFields.value || 0) methodParams += ', value: ' + (this.state.methodFields.value || 0);
} }
if(this.props.abi.type == 'fallback'){ if (this.props.abi.type === 'fallback') {
methodParams += ', data: "' + (this.state.methodFields.data || '"0x00"' ) + '", to: "' + (this.state.methodFields.to || '"0x00"') + '"' methodParams += ', data: "' + (this.state.methodFields.data || '"0x00"') + '", to: "' + (this.state.methodFields.to || '"0x00"') + '"';
} }
} }
return methodParams + "})"; return methodParams + "})";
@ -228,45 +219,53 @@ class Function extends React.Component {
disabled = true; disabled = true;
} }
if(this.props.definition.code == ""){ if (this.props.definition.code === "") {
btnClass += "btn-secondary"; btnClass += "btn-secondary";
disabled = true; disabled = true;
} else { } else {
btnClass += "btn-primary"; btnClass += "btn-primary";
} }
let requestResult;
if (this.state.onRequest) {
requestResult = <img src="../assets/images/loading.gif" className="loading" alt=""/>;
} else {
requestResult = this.props.definition.code === "" ? <React.Fragment>_</React.Fragment>: <React.Fragment>&#9166;</React.Fragment>;
}
return <ContractContext.Consumer> return <ContractContext.Consumer>
{(context) => ( {(context) => (
<React.Fragment> <React.Fragment>
<div className="col-md-11"> <div className="col-md-11">
<code> <code>
await {this._getFunctionLabel()} await {this._getFunctionLabel()}
{ this.props.abi.type != 'fallback' ? '(' : '' } {this.props.abi.type !== 'fallback' ? '(' : ''}
{ this.props.abi.type != 'fallback' ? this._getFunctionParamFields() : '' } {this.props.abi.type !== 'fallback' ? this._getFunctionParamFields() : ''}
{ this.props.abi.type != 'fallback' ? ')' : '' } {this.props.abi.type !== 'fallback' ? ')' : ''}
{ this.props.abi.type != 'fallback' ? '.' + this._getMethodType() : '' } {this.props.abi.type !== 'fallback' ? '.' + this._getMethodType() : ''}
({this._getMethodFields(context.accounts)}) ({this._getMethodFields(context.accounts)})
</code> </code>
</div> </div>
<div className="col-md-1"> <div className="col-md-1">
<button className={btnClass} title={this.props.definition.code == "" ? "Can't execute function" : "Execute function"} onClick={event => this.handleClick(event, context.updateInstances)} disabled={disabled}> <button className={btnClass}
{ this.state.onRequest ? title={this.props.definition.code === "" ? "Can't execute function" : "Execute function"}
<img src="../assets/images/loading.gif" className="loading" alt="" /> onClick={event => this.handleClick(event, context.updateInstances)} disabled={disabled}>
: {requestResult}
(
this.props.definition.code == ""
?
<React.Fragment>_</React.Fragment>
:
<React.Fragment>&#9166;</React.Fragment>
)
}
</button> </button>
</div> </div>
</React.Fragment> </React.Fragment>
)} )}
</ContractContext.Consumer>; </ContractContext.Consumer>;
} }
} }
Function.propTypes = {
definition: PropTypes.object,
abi: PropTypes.object,
contract: PropTypes.object,
resultHandler: PropTypes.func,
duplicated: PropTypes.bool,
contractName: PropTypes.string
};
export default Function;

View File

@ -1,3 +1,7 @@
import React from 'react';
import ContractContext from './contract-context';
import PropTypes from 'prop-types';
class InstanceSelector extends React.Component { class InstanceSelector extends React.Component {
constructor(props) { constructor(props) {
@ -32,13 +36,13 @@ class InstanceSelector extends React.Component {
e.preventDefault(); e.preventDefault();
let instance; let instance;
if(this.state.selectedInstance == "custom"){ if (this.state.selectedInstance === "custom") {
instance = this.state.customInstance; instance = this.state.customInstance;
} else { } else {
instance = this.state.selectedInstance; instance = this.state.selectedInstance;
} }
if(!/^0x[0-9a-f]{40}$/i.test(instance)){ if (!(/^0x[0-9a-f]{40}$/i).test(instance)) {
this.setState({error: true, errorMessage: 'Not a valid Ethereum address.'}); this.setState({error: true, errorMessage: 'Not a valid Ethereum address.'});
console.log(this.state.errorMessage); console.log(this.state.errorMessage);
return; return;
@ -52,54 +56,47 @@ class InstanceSelector extends React.Component {
showInstances: false, showInstances: false,
showCustomAddressField: false, showCustomAddressField: false,
selectedInstance: instance, selectedInstance: instance,
customInstance: this.state.selectedInstance == "custom" ? this.state.customInstance : "" customInstance: this.state.selectedInstance === "custom" ? this.state.customInstance : ""
}) });
} }
handleChange(e) { handleChange(e) {
this.setState({ this.setState({
showCustomAddressField: e.target.value == "custom", showCustomAddressField: e.target.value === "custom",
selectedInstance: e.target.value selectedInstance: e.target.value
}); });
} }
render() { render() {
let showInstance;
if (!this.state.showInstances) {
showInstance = <a href="#" className="btn btn-primary btn-sm" onClick={this.handleShowInstances}>Change</a>;
} else {
showInstance = <a href="#" className="btn btn-secondary btn-sm" onClick={this.handleShowInstances}>Cancel</a>;
}
return <ContractContext.Consumer> return <ContractContext.Consumer>
{(context) => (<div className="contractSelection"> {(context) => (<div className="contractSelection">
<div className="card"> <div className="card">
<div className="card-header"> <div className="card-header">
<h3 className="card-title"> <h3 className="card-title">
Instance Selected: <b>{this.props.selectedInstance != null ? this.props.selectedInstance : 'none'}</b> Instance Selected: <b>{this.props.selectedInstance !== null ? this.props.selectedInstance : 'none'}</b>
</h3> </h3>
<div className="card-options"> <div className="card-options">
{ {showInstance}
!this.state.showInstances
?
<a href="#" className="btn btn-primary btn-sm" onClick={this.handleShowInstances}>Change</a>
:
<a href="#" className="btn btn-secondary btn-sm" onClick={this.handleShowInstances}>Cancel</a>
}
</div> </div>
</div> </div>
{ {
this.state.showInstances ? this.state.showInstances && <React.Fragment>
<React.Fragment>
{ {
this.state.error this.state.error && <div className="card-alert alert alert-danger mb-0">
?
<div className="card-alert alert alert-danger mb-0">
{this.state.errorMessage} {this.state.errorMessage}
</div> </div>
:
''
} }
<div className="card-body"> <div className="card-body">
<div className="form-group control-group error"> <div className="form-group control-group error">
<select className="form-control" id="contracts" value={this.state.selectedInstance} onChange={this.handleChange}> <select className="form-control" id="contracts" value={this.state.selectedInstance}
onChange={this.handleChange}>
<option value="custom">Specific contract address</option> <option value="custom">Specific contract address</option>
{ {
context.instances.map(function(item, i) { context.instances.map(function(item, i) {
@ -108,9 +105,9 @@ class InstanceSelector extends React.Component {
} }
</select> </select>
{ {
this.state.showCustomAddressField ? this.state.showCustomAddressField &&
<input type="text" className="form-control" id="specificAddress" onChange={this.handleTextChange} placeholder="0x" /> <input type="text" className="form-control" id="specificAddress"
: '' onChange={this.handleTextChange} placeholder="0x"/>
} }
</div> </div>
</div> </div>
@ -118,13 +115,17 @@ class InstanceSelector extends React.Component {
<button className="btn btn-primary" onClick={this.handleClick}>Change</button> <button className="btn btn-primary" onClick={this.handleClick}>Change</button>
</div> </div>
</React.Fragment> </React.Fragment>
:
''
} }
</div> </div>
</div> </div>
)} )}
</ContractContext.Consumer>; </ContractContext.Consumer>;
} }
} }
InstanceSelector.propTypes = {
instanceUpdate: PropTypes.func,
selectedInstance: PropTypes.string
};
export default InstanceSelector;

View File

@ -1,9 +1,12 @@
import React from 'react';
import PropTypes from 'prop-types';
class MenuItem extends React.Component { class MenuItem extends React.Component {
render() { render() {
let classNames = "list-group-item list-group-item-action d-flex align-items-center "; let classNames = "list-group-item list-group-item-action d-flex align-items-center ";
let icon = "fe " + this.props.icon; let icon = "fe " + this.props.icon;
if(this.props.target == this.props.selectedTab){ if (this.props.target === this.props.selectedTab) {
classNames += "active"; classNames += "active";
} }
@ -12,3 +15,13 @@ class MenuItem extends React.Component {
</a>; </a>;
} }
} }
MenuItem.propTypes = {
icon: PropTypes.string,
target: PropTypes.string,
selectedTab: PropTypes.string,
text: PropTypes.string,
click: PropTypes.func
};
export default MenuItem;

View File

@ -1,3 +1,7 @@
/*global hljs*/
import React from 'react';
import PropTypes from 'prop-types';
class SourceArea extends React.Component { class SourceArea extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
@ -25,3 +29,10 @@ class SourceArea extends React.Component {
</div>; </div>;
} }
} }
SourceArea.propTypes = {
definition: PropTypes.object,
source: PropTypes.string
};
export default SourceArea;

View File

@ -1,13 +1,20 @@
import React from 'react';
import PropTypes from 'prop-types';
class Tab extends React.Component { class Tab extends React.Component {
render() { render() {
return ( return (
this.props.selectedTab == this.props.id this.props.selectedTab === this.props.id && <div id={this.props.id}>
?
<div id={this.props.id}>
{this.props.children} {this.props.children}
</div> </div>
:
''
); );
} }
} }
Tab.propTypes = {
selectedTab: PropTypes.string,
id: PropTypes.string,
children: PropTypes.element
};
export default Tab;

View File

@ -1,3 +1,7 @@
/*global Web3*/
import React from 'react';
import ReactDOM from 'react-dom';
import ContractUI from './components/contract-ui';
const contractName = location.search.replace(/\?/, ''); const contractName = location.search.replace(/\?/, '');
@ -31,7 +35,8 @@ fetch("/embark/console", {
window[contractDefinition.className] = contractObj; window[contractDefinition.className] = contractObj;
ReactDOM.render( ReactDOM.render(
<ContractUI name={contractDefinition.className} definition={contractDefinition} contract={contractObj} source={contractSource} />, <ContractUI name={contractDefinition.className} definition={contractDefinition} contract={contractObj}
source={contractSource}/>,
document.getElementById('contracts-area') document.getElementById('contracts-area')
); );
}) })
@ -42,7 +47,8 @@ fetch("/embark/console", {
ReactDOM.render( ReactDOM.render(
<div> <div>
<h1 className="h2 mb-3">Error rendering the UI</h1> <h1 className="h2 mb-3">Error rendering the UI</h1>
<p className="h4 text-muted font-weight-normal mb-7">UI for "{contractName}" cannot be generated</p> <p className="h4 text-muted font-weight-normal mb-7">UI for &quot;&lbrace;contractName&rbrace;&quot; cannot be
generated</p>
</div>, </div>,
document.getElementById('contracts-area') document.getElementById('contracts-area')
); );

View File

@ -36,7 +36,7 @@ class Whisper {
return self.connectToProvider(); return self.connectToProvider();
} }
self.web3.shh.getVersion(function (err, version) { self.web3.shh.getVersion(function (err, version) {
if (err || version == "2") { if (err || version === "2") {
return cb({name: 'Whisper', status: 'off'}); return cb({name: 'Whisper', status: 'off'});
} else { } else {
return cb({name: 'Whisper (version ' + version + ')', status: 'on'}); return cb({name: 'Whisper (version ' + version + ')', status: 'on'});

View File

@ -3,7 +3,7 @@
"version": "3.1.0", "version": "3.1.0",
"description": "Embark is a framework that allows you to easily develop and deploy DApps", "description": "Embark is a framework that allows you to easily develop and deploy DApps",
"scripts": { "scripts": {
"lint": "./node_modules/.bin/eslint lib/", "lint": "./node_modules/.bin/eslint lib/ embark-ui/src",
"test": "mocha test/ --no-timeouts --exit", "test": "mocha test/ --no-timeouts --exit",
"testdapp_1": "cd test_apps/test_app/ && npm install && node ../../bin/embark test", "testdapp_1": "cd test_apps/test_app/ && npm install && node ../../bin/embark test",
"testdapp_2": "cd test_apps/contracts_app/ && npm install && node ../../bin/embark test", "testdapp_2": "cd test_apps/contracts_app/ && npm install && node ../../bin/embark test",