New componets for generating function forms

This commit is contained in:
Richard Ramos 2018-04-13 14:58:09 -04:00
parent 4b582347c7
commit 1136e4273a
5 changed files with 183 additions and 11 deletions

View File

@ -3,7 +3,8 @@ class AccountList extends React.Component {
super(props);
this.state = {
error: false,
errorMessage: ""
errorMessage: "",
accounts: []
};
this.handleClick = this.handleClick.bind(this);
@ -19,6 +20,8 @@ class AccountList extends React.Component {
console.log("%cawait web3.eth.getAccounts()", 'font-weight: bold');
console.log(accounts);
this.setState({accounts: accounts});
this.props.accountUpdate(accounts);
} catch(err) {
this.setState({
@ -36,7 +39,11 @@ class AccountList extends React.Component {
<div id="getAccounts" className="code">
await web3.eth.getAccounts(); <button onClick={this.handleClick}>&#9166;</button>
</div>
{
this.state.accounts.length > 0 ?
<p className="note"><tt>accounts</tt> variable is available in the console</p>
: ""
}
{this.state.error ? '<p className="error">' + this.state.errorMessage + '</p>' : ''}
</div>
</div>;

View File

@ -2,6 +2,7 @@ import Tab from './tab';
import AccountList from './account-list';
import SourceArea from './source-area';
import InstanceSelector from './instance-selector';
import FunctionArea from './function-area';
class ContractUI extends React.Component {
constructor(props) {
@ -48,11 +49,12 @@ class ContractUI extends React.Component {
<Tab id="deploy" name="Deployment / Utils" active={true}>
<AccountList accountUpdate={this.handleAccountUpdate} />
<h3>Deploy</h3>
<div id="constructor">
</div>
<FunctionArea accounts={this.state.accounts} contractName={this.props.name} contract={this.props.contract} type="constructor" />
</Tab>
<Tab id="functions" name="Functions">
<InstanceSelector selectedInstance={this.state.selectedInstance} instances={this.state.instances} instanceUpdate={this.handleInstanceSelection} />
<FunctionArea accounts={this.state.accounts} contractName={this.props.name} contract={this.props.contract} type="function" />
<FunctionArea accounts={this.state.accounts} contractName={this.props.name} contract={this.props.contract} type="fallback" />
</Tab>
<Tab id="contract" name="Contract">
<SourceArea sourceURL={this.props.sourceURL} />

View File

@ -0,0 +1,25 @@
import FunctionForm from './function-form';
class FunctionArea extends React.Component {
constructor(props) {
super(props);
this.state = { };
}
render(){
const type = this.props.type;
const contract = this.props.contract;
const contractName = this.props.contractName;
const accounts = this.props.accounts;
return <div>
{
this.props.contract.options.jsonInterface
.filter(item => item.type == type)
.map((item, i) => <FunctionForm key={i} accounts={accounts} contract={contract} contractName={contractName} abi={item} />)
}
</div>;
}
}
export default FunctionArea;

View File

@ -1,16 +1,36 @@
import Function from './function';
class FunctionForm extends React.Component {
constructor(props) {
super(props);
this.state = { };
this.state = {
fields: {}
};
}
_getFunctionParamFields(elem){
if(this.props.abi.type == 'fallback') return '';
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} />)
.join(', ') + ')';
}
_getMethodType(elem){
return (this.props.abi.constant == true || this.props.abi.stateMutability == 'view' || this.props.abi.stateMutability == 'pure') ? 'call' : 'send';
}
render(){
return <div className="function" id="${this.name}-${i}">
<h4></h4>
const functionName = this.props.abi.name;
const isDuplicated = this.props.contract.options.jsonInterface.filter(x => x.name == functionName).length > 1;
return <div className="function">
<h4>{this.props.abi.type == 'function' ? this.props.abi.name : (this.props.abi.type == 'fallback' ? '(fallback)' : this.props.abi.name)}</h4>
<div className="scenario">
<div className="code">
await <button>&#9166;</button>
<img src="images/loading.gif" className="loading" alt="" />
<Function accounts={this.props.accounts} contract={this.props.contractName} duplicated={isDuplicated} abi={this.props.abi} />
</div>
<p className="error"></p>
<p className="note"></p>
@ -18,3 +38,5 @@ class FunctionForm extends React.Component {
</div>;
}
}
export default FunctionForm;

116
app/components/function.js Normal file
View File

@ -0,0 +1,116 @@
class Function extends React.Component {
constructor(props) {
super(props);
this.state = {
fields: {},
methodFields: {
from: '',
to: '',
value: 0,
data: '',
gasLimit: '700000'
}
};
this.handleParameterChange = this.handleParameterChange.bind(this);
this.handleMethodFieldChange = this.handleMethodFieldChange.bind(this);
}
handleParameterChange(e){
let newState = this.state;
newState.fields[e.target.getAttribute('data-name')] = e.target.value;
this.setState(newState);
}
handleMethodFieldChange(e){
let newState = this.state;
newState.methodFields[e.target.getAttribute('data-param')] = e.target.value;
this.setState(newState);
}
_getFunctionLabel(){
if(this.props.abi.type == 'function')
if(!this.props.duplicated)
return `${this.props.contract}.methods.${this.props.abi.name}`;
else {
return `${this.props.contract}.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'){
return `web3.eth.sendTransaction`;
}
else
return `${this.props.contract}.deploy`;
}
_getMethodType(){
return (this.props.abi.constant == true || this.props.abi.stateMutability == 'view' || this.props.abi.stateMutability == 'pure') ? 'call' : 'send';
}
_getMethodFields(){
let methodParams;
return <span>
from: <select data-param="from" disabled={this.props.accounts.length == 0} onChange={this.handleMethodFieldChange}>
{
this.props.accounts.length == 0 ?
<option>No accounts</option>
:
this.props.accounts.map(function (item, i) {
return <option key={i} value={item}>{`account[${i}]`}</option>;
})
}
</select>
{
this.props.abi.payable ?
<span>, value:
<input type="text" data-param="value" value={this.state.methodFields.value} size="6" onChange={this.handleMethodFieldChange} />
</span>
: ''
}
{
this._getMethodType() == 'send' ?
<span>, gasLimit:
<input type="text" data-param="gasLimit" value={this.state.methodFields.gasLimit} size="6" onChange={this.handleMethodFieldChange} />
</span>
: ''
}
{
this._getMethodType() == 'send' && this.props.abi.type == 'fallback' ?
<span>, data:
<input type="text" data-param="data" value={this.state.methodFields.data} size="6" onChange={this.handleMethodFieldChange} />
</span>
: ''
}
</span>;
}
_getFunctionParamFields(){
return <span>
{
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]} size="6" onChange={this.handleParameterChange} />)
.reduce((accu, elem) => {
return accu === null ? [elem] : [...accu, ', ', elem]
}, null)
}
</span>;
}
render(){
return <span>
await {this._getFunctionLabel()}
{ this.props.abi.type != 'fallback' ? '(' : '' }
{ this.props.abi.type != 'fallback' ? this._getFunctionParamFields() : '' }
{ this.props.abi.type != 'fallback' ? ')' : '' }
{ this.props.abi.type != 'fallback' ? '.' + this._getMethodType() : '' }
({ this._getMethodFields() })
<button>&#9166;</button>
<img src="images/loading.gif" className="loading" alt="" />
</span>;
}
}
export default Function;