rm old lib/modules/webserver/backend
replaced by embark-ui
This commit is contained in:
parent
67d8c675c7
commit
6999a37487
|
@ -1 +0,0 @@
|
||||||
lib/modules/webserver/backend/assets/*
|
|
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Before Width: | Height: | Size: 163 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 714 B |
Binary file not shown.
Before Width: | Height: | Size: 49 KiB |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,82 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import ContractContext from './contract-context';
|
|
||||||
import CardAlert from './card-alert';
|
|
||||||
|
|
||||||
class AccountList extends React.Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
error: false,
|
|
||||||
errorMessage: "",
|
|
||||||
accounts: []
|
|
||||||
};
|
|
||||||
|
|
||||||
this.handleClick = this.handleClick.bind(this);
|
|
||||||
this.handleCopyClick = this.handleCopyClick.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
handleClick(e, updateAccountsCallback) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
try {
|
|
||||||
updateAccountsCallback();
|
|
||||||
} catch (err) {
|
|
||||||
this.setState({
|
|
||||||
error: true,
|
|
||||||
errorMessage: e.name + ': ' + e.message
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
handleCopyClick(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
var dummy = document.createElement("input");
|
|
||||||
document.body.appendChild(dummy);
|
|
||||||
dummy.setAttribute('value', "await web3.eth.getAccounts();");
|
|
||||||
dummy.select();
|
|
||||||
document.execCommand("copy");
|
|
||||||
document.body.removeChild(dummy);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return <ContractContext.Consumer>
|
|
||||||
{(context) => (
|
|
||||||
|
|
||||||
<div className="card function">
|
|
||||||
<div className="card-header">
|
|
||||||
<h3 className="card-title">Get Accounts</h3>
|
|
||||||
<div className="card-options">
|
|
||||||
<a href="#" onClick={this.handleCopyClick} title="Copy to clipboard"><i className="fe fe-copy"></i></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<CardAlert show={this.state.error} message={this.state.errorMessage}/>
|
|
||||||
<div className="card-body row">
|
|
||||||
<div className="col-md-11">
|
|
||||||
<code>
|
|
||||||
await web3.eth.getAccounts();
|
|
||||||
<input type="text" id="accountsTxt"/>
|
|
||||||
</code>
|
|
||||||
</div>
|
|
||||||
<div className="col-md-1">
|
|
||||||
<button className="btn btn-primary ml-auto"
|
|
||||||
onClick={event => this.handleClick(event, context.updateAccounts)}>⏎</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="card-footer">
|
|
||||||
<p><tt>accounts</tt> variable is available in the console</p>
|
|
||||||
<ul>
|
|
||||||
{
|
|
||||||
context.accounts.map((account, i) => <li key={i}>{account}</li>)
|
|
||||||
}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</ContractContext.Consumer>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AccountList;
|
|
|
@ -1,15 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
class CardAlert extends React.Component {
|
|
||||||
render() {
|
|
||||||
return this.props.show ? <div className="card-alert alert alert-danger mb-0">{this.props.message}</div> : '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CardAlert.propTypes = {
|
|
||||||
show: PropTypes.bool,
|
|
||||||
message: PropTypes.string
|
|
||||||
};
|
|
||||||
|
|
||||||
export default CardAlert;
|
|
|
@ -1,12 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
const ContractContext = React.createContext({
|
|
||||||
accounts: [],
|
|
||||||
instances: [],
|
|
||||||
updateAccounts: () => {
|
|
||||||
},
|
|
||||||
updateInstances: (_instance) => {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export default ContractContext;
|
|
|
@ -1,141 +0,0 @@
|
||||||
/*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 {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.updateInstances = this.updateInstances.bind(this);
|
|
||||||
this.updateAccounts = this.updateAccounts.bind(this);
|
|
||||||
this.handleInstanceSelection = this.handleInstanceSelection.bind(this);
|
|
||||||
this.handleMenuClick = this.handleMenuClick.bind(this);
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
accounts: [],
|
|
||||||
instances: [],
|
|
||||||
selectedInstance: null,
|
|
||||||
updateAccounts: this.updateAccounts,
|
|
||||||
updateInstances: this.updateInstances,
|
|
||||||
selectedTab: 'deploy'
|
|
||||||
};
|
|
||||||
|
|
||||||
if (props.contract.options.address !== null) {
|
|
||||||
this.state.instances = [props.contract.options.address];
|
|
||||||
this.state.selectedInstance = props.contract.options.address;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.updateAccounts();
|
|
||||||
}
|
|
||||||
|
|
||||||
handleMenuClick(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
this.setState({
|
|
||||||
selectedTab: e.target.getAttribute('data-target')
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async updateAccounts() {
|
|
||||||
let accounts = await web3.eth.getAccounts();
|
|
||||||
window.accounts = accounts;
|
|
||||||
|
|
||||||
console.log("%cawait web3.eth.getAccounts()", 'font-weight: bold');
|
|
||||||
console.log(accounts);
|
|
||||||
|
|
||||||
this.setState({accounts: accounts});
|
|
||||||
}
|
|
||||||
|
|
||||||
updateInstances(_instance) {
|
|
||||||
this.state.instances.push(_instance);
|
|
||||||
this.setState({
|
|
||||||
instances: this.state.instances
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleInstanceSelection(_instance) {
|
|
||||||
this.props.contract.options.address = _instance;
|
|
||||||
this.setState({
|
|
||||||
selectedInstance: _instance
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<ContractContext.Provider value={this.state}>
|
|
||||||
<div className="row">
|
|
||||||
<div className="col-md-3">
|
|
||||||
<h3 className="page-title mb-5">{this.props.name}</h3>
|
|
||||||
<div>
|
|
||||||
<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-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 className="col-md-9">
|
|
||||||
<Tab id="deploy" selectedTab={this.state.selectedTab}>
|
|
||||||
<h4 className="mb-5">Deployment Utils</h4>
|
|
||||||
<div className="card">
|
|
||||||
<div className="card-body">
|
|
||||||
<ul>
|
|
||||||
<li>Open your browser's console: <code>Tools > Developer Tools</code></li>
|
|
||||||
<li>Remix: <a href="https://remix.ethereum.org" target="_blank" rel="noopener noreferrer">http://remix.ethereum.org</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<AccountList accountUpdate={this.updateAccounts}/>
|
|
||||||
<h5>Deploy</h5>
|
|
||||||
{
|
|
||||||
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"/>
|
|
||||||
</Tab>
|
|
||||||
|
|
||||||
<Tab id="functions" selectedTab={this.state.selectedTab}>
|
|
||||||
<h4 className="mb-5">Functions</h4>
|
|
||||||
{(this.props.definition.code !== "") && <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}
|
|
||||||
contract={this.props.contract} type="fallback"/>
|
|
||||||
</Tab>
|
|
||||||
|
|
||||||
<Tab id="contract" selectedTab={this.state.selectedTab}>
|
|
||||||
<h4 className="mb-5">Source Code</h4>
|
|
||||||
<SourceArea definition={this.props.definition} source={this.props.source}/>
|
|
||||||
</Tab>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
,
|
|
||||||
|
|
||||||
|
|
||||||
</ContractContext.Provider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ContractUI.propTypes = {
|
|
||||||
definition: PropTypes.object,
|
|
||||||
source: PropTypes.string,
|
|
||||||
contract: PropTypes.object,
|
|
||||||
name: PropTypes.string
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export default ContractUI;
|
|
|
@ -1,36 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import FunctionForm from './function-form';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
return <React.Fragment>
|
|
||||||
{
|
|
||||||
this.props.contract.options.jsonInterface
|
|
||||||
.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}/>)
|
|
||||||
}
|
|
||||||
</React.Fragment>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FunctionArea.propTypes = {
|
|
||||||
type: PropTypes.string,
|
|
||||||
contract: PropTypes.object,
|
|
||||||
contractName: PropTypes.string,
|
|
||||||
definition: PropTypes.object,
|
|
||||||
instanceUpdate: PropTypes.func
|
|
||||||
};
|
|
||||||
|
|
||||||
export default FunctionArea;
|
|
|
@ -1,159 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import CardAlert from './card-alert';
|
|
||||||
import Function from './function';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
class FunctionForm extends React.Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
fields: {},
|
|
||||||
error: false,
|
|
||||||
message: null,
|
|
||||||
receipt: null
|
|
||||||
};
|
|
||||||
|
|
||||||
this.child = React.createRef();
|
|
||||||
|
|
||||||
this.showResults = this.showResults.bind(this);
|
|
||||||
this.handleCopyClick = this.handleCopyClick.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleCopyClick(e) {
|
|
||||||
this.child.current.copyCommand(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
_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}
|
|
||||||
key={'input' + i}/>)
|
|
||||||
.join(', ') + ')';
|
|
||||||
}
|
|
||||||
|
|
||||||
_getMethodType(_elem) {
|
|
||||||
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() {
|
|
||||||
const functionName = this.props.abi.name;
|
|
||||||
const isDuplicated = this.props.contract.options.jsonInterface.filter(x => x.name === functionName).length > 1;
|
|
||||||
const contract = this.props.contract;
|
|
||||||
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">
|
|
||||||
|
|
||||||
<div className="card-header">
|
|
||||||
<h3
|
|
||||||
className="card-title">{title}</h3>
|
|
||||||
<div className="card-options">
|
|
||||||
<a href="#" onClick={this.handleCopyClick} title="Copy to clipboard"><i className="fe fe-copy"></i></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<CardAlert show={this.state.error} message={this.state.message}/>
|
|
||||||
|
|
||||||
<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}/>
|
|
||||||
</div>
|
|
||||||
{this.renderContent(receipt, contract)}
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
showResults(_error, _message, _receipt) {
|
|
||||||
this.setState({
|
|
||||||
error: _error,
|
|
||||||
message: _message,
|
|
||||||
receipt: _receipt
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FunctionForm.propTypes = {
|
|
||||||
abi: PropTypes.object,
|
|
||||||
contract: PropTypes.object,
|
|
||||||
definition: PropTypes.object,
|
|
||||||
contractName: PropTypes.string
|
|
||||||
};
|
|
||||||
|
|
||||||
export default FunctionForm;
|
|
|
@ -1,271 +0,0 @@
|
||||||
/*global web3*/
|
|
||||||
import React from 'react';
|
|
||||||
import ContractContext from './contract-context';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
class Function extends React.Component {
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
onRequest: false,
|
|
||||||
fields: {},
|
|
||||||
methodFields: {
|
|
||||||
from: '',
|
|
||||||
to: '',
|
|
||||||
value: 0,
|
|
||||||
data: '',
|
|
||||||
gasLimit: '7000000'
|
|
||||||
},
|
|
||||||
receipt: null
|
|
||||||
};
|
|
||||||
|
|
||||||
this.handleParameterChange = this.handleParameterChange.bind(this);
|
|
||||||
this.handleMethodFieldChange = this.handleMethodFieldChange.bind(this);
|
|
||||||
this.handleClick = this.handleClick.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
copyCommand(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
let functionLabel = this._getFunctionLabel();
|
|
||||||
let functionParams = this._getFunctionParamString();
|
|
||||||
let methodParams = this._getMethodString();
|
|
||||||
if (this.props.abi.type === "constructor") functionParams = `{arguments: [${functionParams}]}`;
|
|
||||||
|
|
||||||
const command = `await ${functionLabel}(${functionParams})${this.props.abi.type !== 'fallback' ? '.' + this._getMethodType() : ''}${methodParams}`;
|
|
||||||
|
|
||||||
var dummy = document.createElement("input");
|
|
||||||
document.body.appendChild(dummy);
|
|
||||||
dummy.setAttribute('value', command);
|
|
||||||
dummy.select();
|
|
||||||
document.execCommand("copy");
|
|
||||||
document.body.removeChild(dummy);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async handleClick(e, instanceUpdateCallback) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
this.setState({onRequest: true, receipt: null});
|
|
||||||
|
|
||||||
this.props.resultHandler(false, null, null);
|
|
||||||
|
|
||||||
let executionParams = {
|
|
||||||
from: this.state.methodFields.from,
|
|
||||||
gasLimit: this.state.methodFields.gasLimit
|
|
||||||
};
|
|
||||||
|
|
||||||
if (this.props.abi.payable) executionParams.value = this.state.methodFields.value;
|
|
||||||
|
|
||||||
if (this.props.abi.type === 'fallback') {
|
|
||||||
executionParams.data = this.state.methodFields.data;
|
|
||||||
executionParams.to = this.props.contract.options.address;
|
|
||||||
}
|
|
||||||
|
|
||||||
let fields = this.state.fields;
|
|
||||||
|
|
||||||
let functionLabel = this._getFunctionLabel();
|
|
||||||
let functionParams = this._getFunctionParamString();
|
|
||||||
let methodParams = this._getMethodString();
|
|
||||||
if (this.props.abi.type === "constructor") functionParams = `{arguments: [${functionParams}]}`;
|
|
||||||
|
|
||||||
console.log(`%cawait ${functionLabel}(${functionParams})${this.props.abi.type !== 'fallback' ? '.' + this._getMethodType() : ''}${methodParams}`, 'font-weight: bold');
|
|
||||||
|
|
||||||
let _receipt;
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (this.props.abi.type === 'constructor') {
|
|
||||||
let contractInstance = await this.props.contract.deploy({arguments: Object.keys(fields).map(val => fields[val])}).send(executionParams);
|
|
||||||
instanceUpdateCallback(contractInstance.options.address);
|
|
||||||
this.setState({onRequest: false});
|
|
||||||
console.log(contractInstance.options.address);
|
|
||||||
this.props.resultHandler(false, 'New instance: ' + contractInstance.options.address);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (this.props.abi.type === 'fallback') _receipt = await web3.eth.sendTransaction(executionParams);
|
|
||||||
else _receipt = await this.props.contract
|
|
||||||
.methods[this.props.abi.name + '(' + this.props.abi.inputs.map(input => input.type).join(',') + ')']
|
|
||||||
.apply(null, Object.keys(fields).map(val => {
|
|
||||||
let input = this.props.abi.inputs.filter(x => x.name === val)[0];
|
|
||||||
return input.type.indexOf('bool') === -1 ? fields[val] : (fields[val].toLowerCase() === 'true');
|
|
||||||
}))[this._getMethodType()](executionParams);
|
|
||||||
|
|
||||||
if (this._getMethodType() === 'call') {
|
|
||||||
this.props.resultHandler(false, _receipt, null);
|
|
||||||
} else {
|
|
||||||
this.props.resultHandler(false, null, _receipt);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({onRequest: false, receipt: _receipt});
|
|
||||||
console.log(_receipt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error('%s: %s', err.name, err.message);
|
|
||||||
this.setState({onRequest: false});
|
|
||||||
this.props.resultHandler(true, err.name + ": " + err.message, _receipt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (e.target.getAttribute('data-param') === 'from') {
|
|
||||||
newState.selectedAccount = e.target.options[e.target.selectedIndex].text;
|
|
||||||
}
|
|
||||||
this.setState(newState);
|
|
||||||
}
|
|
||||||
|
|
||||||
_getFunctionLabel() {
|
|
||||||
if (this.props.abi.type === 'function') if (!this.props.duplicated) return `${this.props.contractName}.methods.${this.props.abi.name}`;
|
|
||||||
else {
|
|
||||||
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') {
|
|
||||||
return `web3.eth.sendTransaction`;
|
|
||||||
}
|
|
||||||
else return `${this.props.contractName}.deploy`;
|
|
||||||
}
|
|
||||||
|
|
||||||
_getMethodType() {
|
|
||||||
return (this.props.abi.constant === true || this.props.abi.stateMutability === 'view' || this.props.abi.stateMutability === 'pure') ? 'call' : 'send';
|
|
||||||
}
|
|
||||||
|
|
||||||
_getMethodFields(accounts) {
|
|
||||||
return <React.Fragment>
|
|
||||||
from: <select data-param="from" disabled={accounts.length === 0} value={this.state.from}
|
|
||||||
onChange={this.handleMethodFieldChange}>
|
|
||||||
<option>-</option>
|
|
||||||
{
|
|
||||||
accounts.map(function(item, i) {
|
|
||||||
return <option key={i} value={item}>{`accounts[${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>}
|
|
||||||
</React.Fragment>;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
_getFunctionParamFields() {
|
|
||||||
return <React.Fragment>
|
|
||||||
{
|
|
||||||
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}/>)
|
|
||||||
.reduce((accu, elem) => {
|
|
||||||
return accu === null ? [elem] : [...accu, ', ', elem];
|
|
||||||
}, null)
|
|
||||||
}
|
|
||||||
</React.Fragment>;
|
|
||||||
}
|
|
||||||
|
|
||||||
_getFunctionParamString() {
|
|
||||||
if (this.props.abi.type === 'fallback') return '';
|
|
||||||
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 ? '"' : ''))
|
|
||||||
.join(', ');
|
|
||||||
}
|
|
||||||
|
|
||||||
_getMethodString(_elem) {
|
|
||||||
let methodParams = "({";
|
|
||||||
|
|
||||||
methodParams += `from: ` + (this.state.selectedAccount || '"0x00"');
|
|
||||||
if (this._getMethodType() === 'send') {
|
|
||||||
methodParams += ', gasLimit: ' + (this.state.methodFields.gasLimit || 0);
|
|
||||||
if (this.props.abi.payable) {
|
|
||||||
methodParams += ', value: ' + (this.state.methodFields.value || 0);
|
|
||||||
}
|
|
||||||
if (this.props.abi.type === 'fallback') {
|
|
||||||
methodParams += ', data: "' + (this.state.methodFields.data || '"0x00"') + '", to: "' + (this.state.methodFields.to || '"0x00"') + '"';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return methodParams + "})";
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
|
|
||||||
let btnClass = "btn ml-auto ";
|
|
||||||
let disabled = false;
|
|
||||||
|
|
||||||
if (this.state.onRequest) {
|
|
||||||
disabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.props.definition.code === "") {
|
|
||||||
btnClass += "btn-secondary";
|
|
||||||
disabled = true;
|
|
||||||
} else {
|
|
||||||
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>⏎</React.Fragment>;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <ContractContext.Consumer>
|
|
||||||
{(context) => (
|
|
||||||
<React.Fragment>
|
|
||||||
<div className="col-md-11">
|
|
||||||
<code>
|
|
||||||
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(context.accounts)})
|
|
||||||
</code>
|
|
||||||
</div>
|
|
||||||
<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}>
|
|
||||||
{requestResult}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</React.Fragment>
|
|
||||||
)}
|
|
||||||
</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;
|
|
|
@ -1,131 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import ContractContext from './contract-context';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
class InstanceSelector extends React.Component {
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
showInstances: false,
|
|
||||||
showCustomAddressField: false,
|
|
||||||
selectedInstance: props.selectedInstance,
|
|
||||||
customInstance: "",
|
|
||||||
error: false,
|
|
||||||
errorMessage: ""
|
|
||||||
};
|
|
||||||
|
|
||||||
this.handleShowInstances = this.handleShowInstances.bind(this);
|
|
||||||
this.handleChange = this.handleChange.bind(this);
|
|
||||||
this.handleClick = this.handleClick.bind(this);
|
|
||||||
this.handleTextChange = this.handleTextChange.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleTextChange(e) {
|
|
||||||
this.setState({customInstance: e.target.value});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleShowInstances(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
this.setState({
|
|
||||||
showInstances: !this.state.showInstances
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleClick(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
let instance;
|
|
||||||
if (this.state.selectedInstance === "custom") {
|
|
||||||
instance = this.state.customInstance;
|
|
||||||
} else {
|
|
||||||
instance = this.state.selectedInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(/^0x[0-9a-f]{40}$/i).test(instance)) {
|
|
||||||
this.setState({error: true, errorMessage: 'Not a valid Ethereum address.'});
|
|
||||||
console.log(this.state.errorMessage);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
this.setState({error: false});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.props.instanceUpdate(instance);
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
showInstances: false,
|
|
||||||
showCustomAddressField: false,
|
|
||||||
selectedInstance: instance,
|
|
||||||
customInstance: this.state.selectedInstance === "custom" ? this.state.customInstance : ""
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleChange(e) {
|
|
||||||
this.setState({
|
|
||||||
showCustomAddressField: e.target.value === "custom",
|
|
||||||
selectedInstance: e.target.value
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
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>
|
|
||||||
{(context) => (<div className="contractSelection">
|
|
||||||
<div className="card">
|
|
||||||
<div className="card-header">
|
|
||||||
<h3 className="card-title">
|
|
||||||
Instance Selected: <b>{this.props.selectedInstance !== null ? this.props.selectedInstance : 'none'}</b>
|
|
||||||
</h3>
|
|
||||||
<div className="card-options">
|
|
||||||
{showInstance}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{
|
|
||||||
this.state.showInstances && <React.Fragment>
|
|
||||||
{
|
|
||||||
this.state.error && <div className="card-alert alert alert-danger mb-0">
|
|
||||||
{this.state.errorMessage}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
<div className="card-body">
|
|
||||||
<div className="form-group control-group error">
|
|
||||||
<select className="form-control" id="contracts" value={this.state.selectedInstance}
|
|
||||||
onChange={this.handleChange}>
|
|
||||||
<option value="custom">Specific contract address</option>
|
|
||||||
{
|
|
||||||
context.instances.map(function(item, i) {
|
|
||||||
return <option key={i} value={item}>{item}</option>;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
{
|
|
||||||
this.state.showCustomAddressField &&
|
|
||||||
<input type="text" className="form-control" id="specificAddress"
|
|
||||||
onChange={this.handleTextChange} placeholder="0x"/>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="card-footer text-right">
|
|
||||||
<button className="btn btn-primary" onClick={this.handleClick}>Change</button>
|
|
||||||
</div>
|
|
||||||
</React.Fragment>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</ContractContext.Consumer>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InstanceSelector.propTypes = {
|
|
||||||
instanceUpdate: PropTypes.func,
|
|
||||||
selectedInstance: PropTypes.string
|
|
||||||
};
|
|
||||||
|
|
||||||
export default InstanceSelector;
|
|
|
@ -1,27 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
class MenuItem extends React.Component {
|
|
||||||
render() {
|
|
||||||
|
|
||||||
let classNames = "list-group-item list-group-item-action d-flex align-items-center ";
|
|
||||||
let icon = "fe " + this.props.icon;
|
|
||||||
if (this.props.target === this.props.selectedTab) {
|
|
||||||
classNames += "active";
|
|
||||||
}
|
|
||||||
|
|
||||||
return <a href="#" onClick={this.props.click} data-target={this.props.target} className={classNames}>
|
|
||||||
<span className="icon mr-3"><i className={icon}></i></span>{this.props.text}
|
|
||||||
</a>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuItem.propTypes = {
|
|
||||||
icon: PropTypes.string,
|
|
||||||
target: PropTypes.string,
|
|
||||||
selectedTab: PropTypes.string,
|
|
||||||
text: PropTypes.string,
|
|
||||||
click: PropTypes.func
|
|
||||||
};
|
|
||||||
|
|
||||||
export default MenuItem;
|
|
|
@ -1,38 +0,0 @@
|
||||||
/*global hljs*/
|
|
||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
class SourceArea extends React.Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
sourceCode: ""
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
let colorCodedText = hljs.highlight('javascript', this.props.source, true).value;
|
|
||||||
this.setState({sourceCode: colorCodedText});
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return <div className="card">
|
|
||||||
<div className="card-header">
|
|
||||||
<h3 className="card-title">{this.props.definition.className}</h3>
|
|
||||||
<div className="card-options">
|
|
||||||
<small>{this.props.definition.filename}</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="card-body">
|
|
||||||
<pre dangerouslySetInnerHTML={{__html: this.state.sourceCode}}></pre>
|
|
||||||
</div>
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SourceArea.propTypes = {
|
|
||||||
definition: PropTypes.object,
|
|
||||||
source: PropTypes.string
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SourceArea;
|
|
|
@ -1,20 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
class Tab extends React.Component {
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
this.props.selectedTab === this.props.id && <div id={this.props.id}>
|
|
||||||
{this.props.children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Tab.propTypes = {
|
|
||||||
selectedTab: PropTypes.string,
|
|
||||||
id: PropTypes.string,
|
|
||||||
children: PropTypes.element
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Tab;
|
|
|
@ -1,37 +0,0 @@
|
||||||
code {
|
|
||||||
width: 100%;
|
|
||||||
overflow: auto;
|
|
||||||
display: block;
|
|
||||||
white-space: nowrap;
|
|
||||||
padding-top: 5px;
|
|
||||||
padding-bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
code input, code select {
|
|
||||||
padding: 0.375rem 0.75rem;
|
|
||||||
font-size: 0.9375rem;
|
|
||||||
line-height: 1.6;
|
|
||||||
color: #495057;
|
|
||||||
background-color: #fff;
|
|
||||||
background-clip: padding-box;
|
|
||||||
border: 1px solid rgba(0, 40, 100, 0.12);
|
|
||||||
border-radius: 3px;
|
|
||||||
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.function button {
|
|
||||||
margin-top: .6em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#accountsTxt {
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-options a.btn-primary {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.card-options a.btn-primary:hover {
|
|
||||||
background-color: #ccc;
|
|
||||||
}
|
|
|
@ -1,209 +0,0 @@
|
||||||
<!doctype html>
|
|
||||||
<html lang="en" dir="ltr">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
||||||
<meta http-equiv="Content-Language" content="en" />
|
|
||||||
<meta name="msapplication-TileColor" content="#2d89ef">
|
|
||||||
<meta name="theme-color" content="#4188c9">
|
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
|
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
||||||
<meta name="mobile-web-app-capable" content="yes">
|
|
||||||
<meta name="HandheldFriendly" content="True">
|
|
||||||
<meta name="MobileOptimized" content="320">
|
|
||||||
<link rel="icon" href="./favicon.ico" type="image/x-icon"/>
|
|
||||||
<link rel="shortcut icon" type="image/x-icon" href="./favicon.ico" />
|
|
||||||
<!-- Generated: 2018-04-04 13:48:30 +0200 -->
|
|
||||||
<title>Embark</title>
|
|
||||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
|
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,300i,400,400i,500,500i,600,600i,700,700i&subset=latin-ext">
|
|
||||||
<!--
|
|
||||||
<script src="./assets/js/require.min.js"></script>
|
|
||||||
<script>
|
|
||||||
requirejs.config({
|
|
||||||
baseUrl: '.'
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
-->
|
|
||||||
<!-- Dashboard Core -->
|
|
||||||
<link href="../assets/css/dashboard.css" rel="stylesheet" />
|
|
||||||
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
|
|
||||||
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
|
|
||||||
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
|
|
||||||
<script src="../assets/js/jquery-3.3.1.min.js"></script>
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css">
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.4.0/languages/javascript.min.js"></script>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Import this with a bundler -->
|
|
||||||
<link rel="stylesheet" href="./contracts.css">
|
|
||||||
<script src="../assets/js/web3-1.0.min.js" type="text/javascript"></script>
|
|
||||||
<script src="./components/account-list.js" type="text/babel"></script>
|
|
||||||
<script src="./components/contract-context.js" type="text/babel"></script>
|
|
||||||
<script src="./components/contract-ui.js" type="text/babel"></script>
|
|
||||||
<script src="./components/function-area.js" type="text/babel"></script>
|
|
||||||
<script src="./components/function-form.js" type="text/babel"></script>
|
|
||||||
<script src="./components/function.js" type="text/babel"></script>
|
|
||||||
<script src="./components/instance-selector.js" type="text/babel"></script>
|
|
||||||
<script src="./components/source-area.js" type="text/babel"></script>
|
|
||||||
<script src="./components/tab.js" type="text/babel"></script>
|
|
||||||
<script src="./components/menu-item.js" type="text/babel"></script>
|
|
||||||
<script src="./components/card-alert.js" type="text/babel"></script>
|
|
||||||
<script src="./view.js" type="text/babel"></script>
|
|
||||||
|
|
||||||
|
|
||||||
<!--
|
|
||||||
<script src="./assets/js/dashboard.js"></script>
|
|
||||||
<link href="./assets/plugins/charts-c3/plugin.css" rel="stylesheet" />
|
|
||||||
<script src="./assets/plugins/charts-c3/plugin.js"></script>
|
|
||||||
<link href="./assets/plugins/maps-google/plugin.css" rel="stylesheet" />
|
|
||||||
<script src="./assets/plugins/maps-google/plugin.js"></script>
|
|
||||||
<script src="./assets/plugins/input-mask/plugin.js"></script>
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
</head>
|
|
||||||
<body class="">
|
|
||||||
<div class="page">
|
|
||||||
<div class="page-main">
|
|
||||||
<div class="header">
|
|
||||||
<div class="container">
|
|
||||||
<div class="d-flex">
|
|
||||||
<a class="navbar-brand" href="/embark/index.html">
|
|
||||||
<img src="../assets/images/logo.png" class="navbar-brand-img" alt="Embark">
|
|
||||||
</a>
|
|
||||||
<div class="ml-auto d-flex order-lg-2">
|
|
||||||
<div class="dropdown d-none d-md-flex">
|
|
||||||
<a class="nav-link icon" data-toggle="dropdown">
|
|
||||||
<i class="fe fe-bell"></i>
|
|
||||||
<span class="nav-unread"></span>
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-menu dropdown-menu-right dropdown-menu-arrow">
|
|
||||||
<a href="#" class="dropdown-item d-flex">
|
|
||||||
<span class="avatar mr-3 align-self-center" style="background-image: url(demo/faces/male/41.jpg)"></span>
|
|
||||||
<div>
|
|
||||||
<strong>Nathan</strong> pushed new commit: Fix page load performance issue.
|
|
||||||
<div class="small text-muted">10 minutes ago</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="dropdown-item d-flex">
|
|
||||||
<span class="avatar mr-3 align-self-center" style="background-image: url(demo/faces/female/1.jpg)"></span>
|
|
||||||
<div>
|
|
||||||
<strong>Alice</strong> started new task: Tabler UI design.
|
|
||||||
<div class="small text-muted">1 hour ago</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="dropdown-item d-flex">
|
|
||||||
<span class="avatar mr-3 align-self-center" style="background-image: url(demo/faces/female/18.jpg)"></span>
|
|
||||||
<div>
|
|
||||||
<strong>Rose</strong> deployed new version of NodeJS REST Api V3
|
|
||||||
<div class="small text-muted">2 hours ago</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-divider"></div>
|
|
||||||
<a href="#" class="dropdown-item text-center text-muted-dark">Mark all as read</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="dropdown">
|
|
||||||
<a href="#" class="nav-link pr-0" data-toggle="dropdown">
|
|
||||||
<span class="avatar" style="background-image: url(./demo/faces/female/25.jpg)"></span>
|
|
||||||
<span class="ml-2 d-none d-lg-block">
|
|
||||||
<span class="text-default">Dade Murphy</span>
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-menu dropdown-menu-right dropdown-menu-arrow">
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="dropdown-icon fe fe-user"></i> Profile
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="dropdown-icon fe fe-settings"></i> Settings
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<span class="float-right"><span class="badge badge-primary">6</span></span>
|
|
||||||
<i class="dropdown-icon fe fe-mail"></i> Inbox
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="dropdown-icon fe fe-send"></i> Message
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-divider"></div>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="dropdown-icon fe fe-help-circle"></i> Need help?
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="dropdown-icon fe fe-log-out"></i> Sign out
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="header-nav d-none d-lg-flex">
|
|
||||||
<div class="container">
|
|
||||||
<div class="row align-items-center">
|
|
||||||
<div class="col">
|
|
||||||
<ul class="nav nav-tabs">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a href="/embark/index.html" class="nav-link"><i class="fe fe-home"></i> Home</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a href="javascript:void(0)" class="nav-link active"><i class="fe fe-box"></i> Contracts</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a href="./docs/index.html" class="nav-link"><i class="fe fe-file-text"></i> Documentation</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="col-3 ml-auto">
|
|
||||||
<form class="input-icon">
|
|
||||||
<input type="search" class="form-control header-search" placeholder="Search…" tabindex="1">
|
|
||||||
<div class="input-icon-addon">
|
|
||||||
<i class="fe fe-search"></i>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="page-content">
|
|
||||||
<div class="container">
|
|
||||||
|
|
||||||
|
|
||||||
<div id="contracts-area"></div>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<footer class="footer">
|
|
||||||
<div class="container">
|
|
||||||
<div class="row align-items-center flex-row-reverse">
|
|
||||||
<div class="col-auto ml-auto">
|
|
||||||
<div class="row align-items-center">
|
|
||||||
<div class="col-auto">
|
|
||||||
<ul class="list-inline list-inline-dots mb-0">
|
|
||||||
<li class="list-inline-item"><a href="./docs/index.html">Documentation</a></li>
|
|
||||||
<li class="list-inline-item"><a href="./faq.html">FAQ</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto">
|
|
||||||
<a href="https://github.com/tabler/tabler" class="btn btn-outline-primary btn-sm">Source code</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-lg-auto mt-3 mt-lg-0 text-center">
|
|
||||||
Copyright © 2018 <a href=".">Status Embark</a>.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,57 +0,0 @@
|
||||||
/*global Web3*/
|
|
||||||
import React from 'react';
|
|
||||||
import ReactDOM from 'react-dom';
|
|
||||||
import ContractUI from './components/contract-ui';
|
|
||||||
|
|
||||||
const contractName = location.search.replace(/\?/, '');
|
|
||||||
|
|
||||||
let contractDefinition;
|
|
||||||
let host;
|
|
||||||
|
|
||||||
fetch("/embark/console", {
|
|
||||||
method: "POST",
|
|
||||||
headers: {'content-type': 'application/x-www-form-urlencoded; charset=UTF-8'},
|
|
||||||
body: "cmd=web3.currentProvider.host"
|
|
||||||
})
|
|
||||||
.then(response => response.text())
|
|
||||||
.then(text => {
|
|
||||||
host = text;
|
|
||||||
return fetch("/embark/contract/" + contractName);
|
|
||||||
})
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(_contractDefinition => {
|
|
||||||
contractDefinition = _contractDefinition;
|
|
||||||
return fetch("/embark/files/contracts?filename=" + contractDefinition.originalFilename);
|
|
||||||
})
|
|
||||||
.then(response => response.text())
|
|
||||||
.then(contractSource => {
|
|
||||||
const web3 = new Web3(host);
|
|
||||||
window.web3 = web3;
|
|
||||||
|
|
||||||
let contractObj = new web3.eth.Contract(contractDefinition.abiDefinition);
|
|
||||||
contractObj.options.data = "0x" + contractDefinition.code;
|
|
||||||
contractObj.options.address = contractDefinition.deployedAddress;
|
|
||||||
|
|
||||||
window[contractDefinition.className] = contractObj;
|
|
||||||
|
|
||||||
ReactDOM.render(
|
|
||||||
<ContractUI name={contractDefinition.className} definition={contractDefinition} contract={contractObj}
|
|
||||||
source={contractSource}/>,
|
|
||||||
document.getElementById('contracts-area')
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.catch(function(err) {
|
|
||||||
console.log('%cError while rendering UI', 'font-weight: bold');
|
|
||||||
console.error(err);
|
|
||||||
|
|
||||||
ReactDOM.render(
|
|
||||||
<div>
|
|
||||||
<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>
|
|
||||||
</div>,
|
|
||||||
document.getElementById('contracts-area')
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
|
@ -1,348 +0,0 @@
|
||||||
<!doctype html>
|
|
||||||
<html lang="en" dir="ltr">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
||||||
<meta http-equiv="Content-Language" content="en" />
|
|
||||||
<meta name="msapplication-TileColor" content="#2d89ef">
|
|
||||||
<meta name="theme-color" content="#4188c9">
|
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
|
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
||||||
<meta name="mobile-web-app-capable" content="yes">
|
|
||||||
<meta name="HandheldFriendly" content="True">
|
|
||||||
<meta name="MobileOptimized" content="320">
|
|
||||||
<link rel="icon" href="./favicon.ico" type="image/x-icon"/>
|
|
||||||
<link rel="shortcut icon" type="image/x-icon" href="./favicon.ico" />
|
|
||||||
<!-- Generated: 2018-04-04 13:48:30 +0200 -->
|
|
||||||
<title>Embark</title>
|
|
||||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
|
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,300i,400,400i,500,500i,600,600i,700,700i&subset=latin-ext">
|
|
||||||
<!--
|
|
||||||
<script src="./assets/js/require.min.js"></script>
|
|
||||||
<script>
|
|
||||||
requirejs.config({
|
|
||||||
baseUrl: '.'
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
-->
|
|
||||||
<!-- Dashboard Core -->
|
|
||||||
<link href="./assets/css/dashboard.css" rel="stylesheet" />
|
|
||||||
|
|
||||||
<script src="./assets/js/jquery-3.3.1.min.js"></script>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
<script src="./assets/js/dashboard.js"></script>
|
|
||||||
<link href="./assets/plugins/charts-c3/plugin.css" rel="stylesheet" />
|
|
||||||
<script src="./assets/plugins/charts-c3/plugin.js"></script>
|
|
||||||
<link href="./assets/plugins/maps-google/plugin.css" rel="stylesheet" />
|
|
||||||
<script src="./assets/plugins/maps-google/plugin.js"></script>
|
|
||||||
<script src="./assets/plugins/input-mask/plugin.js"></script>
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
</head>
|
|
||||||
<body class="">
|
|
||||||
<div class="page">
|
|
||||||
<div class="page-main">
|
|
||||||
<div class="header">
|
|
||||||
<div class="container">
|
|
||||||
<div class="d-flex">
|
|
||||||
<a class="navbar-brand" href="./index.html">
|
|
||||||
<img src="./assets/images/logo.png" class="navbar-brand-img" alt="Embark">
|
|
||||||
</a>
|
|
||||||
<div class="ml-auto d-flex order-lg-2">
|
|
||||||
<div class="dropdown d-none d-md-flex">
|
|
||||||
<a class="nav-link icon" data-toggle="dropdown">
|
|
||||||
<i class="fe fe-bell"></i>
|
|
||||||
<span class="nav-unread"></span>
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-menu dropdown-menu-right dropdown-menu-arrow">
|
|
||||||
<a href="#" class="dropdown-item d-flex">
|
|
||||||
<span class="avatar mr-3 align-self-center" style="background-image: url(demo/faces/male/41.jpg)"></span>
|
|
||||||
<div>
|
|
||||||
<strong>Nathan</strong> pushed new commit: Fix page load performance issue.
|
|
||||||
<div class="small text-muted">10 minutes ago</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="dropdown-item d-flex">
|
|
||||||
<span class="avatar mr-3 align-self-center" style="background-image: url(demo/faces/female/1.jpg)"></span>
|
|
||||||
<div>
|
|
||||||
<strong>Alice</strong> started new task: Tabler UI design.
|
|
||||||
<div class="small text-muted">1 hour ago</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="dropdown-item d-flex">
|
|
||||||
<span class="avatar mr-3 align-self-center" style="background-image: url(demo/faces/female/18.jpg)"></span>
|
|
||||||
<div>
|
|
||||||
<strong>Rose</strong> deployed new version of NodeJS REST Api V3
|
|
||||||
<div class="small text-muted">2 hours ago</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-divider"></div>
|
|
||||||
<a href="#" class="dropdown-item text-center text-muted-dark">Mark all as read</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="dropdown">
|
|
||||||
<a href="#" class="nav-link pr-0" data-toggle="dropdown">
|
|
||||||
<span class="avatar" style="background-image: url(./demo/faces/female/25.jpg)"></span>
|
|
||||||
<span class="ml-2 d-none d-lg-block">
|
|
||||||
<span class="text-default">Dade Murphy</span>
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-menu dropdown-menu-right dropdown-menu-arrow">
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="dropdown-icon fe fe-user"></i> Profile
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="dropdown-icon fe fe-settings"></i> Settings
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<span class="float-right"><span class="badge badge-primary">6</span></span>
|
|
||||||
<i class="dropdown-icon fe fe-mail"></i> Inbox
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="dropdown-icon fe fe-send"></i> Message
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-divider"></div>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="dropdown-icon fe fe-help-circle"></i> Need help?
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="dropdown-icon fe fe-log-out"></i> Sign out
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="header-nav d-none d-lg-flex">
|
|
||||||
<div class="container">
|
|
||||||
<div class="row align-items-center">
|
|
||||||
<div class="col">
|
|
||||||
<ul class="nav nav-tabs">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a href="./index.html" class="nav-link active"><i class="fe fe-home"></i> Home</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a href="javascript:void(0)" class="nav-link"><i class="fe fe-box"></i> Contracts</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a href="./docs/index.html" class="nav-link"><i class="fe fe-file-text"></i> Documentation</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="col-3 ml-auto">
|
|
||||||
<form class="input-icon">
|
|
||||||
<input type="search" class="form-control header-search" placeholder="Search…" tabindex="1">
|
|
||||||
<div class="input-icon-addon">
|
|
||||||
<i class="fe fe-search"></i>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="page-content">
|
|
||||||
<div class="container">
|
|
||||||
<div class="page-header">
|
|
||||||
<h1 class="page-title">
|
|
||||||
Dashboard
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
<div class="row row-cards">
|
|
||||||
<div class="col-sm-6 col-lg-3">
|
|
||||||
<div class="card p-3">
|
|
||||||
<div class="d-flex align-items-center">
|
|
||||||
<span class="stamp stamp-md bg-blue mr-3">
|
|
||||||
<i class="fe fa-cube"></i>
|
|
||||||
</span>
|
|
||||||
<div>
|
|
||||||
<h4 class="m-0"><a href="javascript:void(0)">IPFS</a></h4>
|
|
||||||
<small class="text-muted">version 2.5</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-6 col-lg-3">
|
|
||||||
<div class="card p-3">
|
|
||||||
<div class="d-flex align-items-center">
|
|
||||||
<span class="stamp stamp-md bg-green mr-3">
|
|
||||||
<i class="fe fe-check"></i>
|
|
||||||
</span>
|
|
||||||
<div>
|
|
||||||
<h4 class="m-0"><a href="javascript:void(0)">Ethereum</a></h4>
|
|
||||||
<small class="text-muted">Geth 1.6.7-stable</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-6 col-lg-3">
|
|
||||||
<div class="card p-3">
|
|
||||||
<div class="d-flex align-items-center">
|
|
||||||
<span class="stamp stamp-md bg-red mr-3">
|
|
||||||
<i class="fe fe-message-square"></i>
|
|
||||||
</span>
|
|
||||||
<div>
|
|
||||||
<h4 class="m-0"><a href="javascript:void(0)">Whisper</a></h4>
|
|
||||||
<small class="text-muted">V5</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-6 col-lg-3">
|
|
||||||
<div class="card p-3">
|
|
||||||
<div class="d-flex align-items-center">
|
|
||||||
<span class="stamp stamp-md bg-yellow mr-3">
|
|
||||||
<i class="fe fe-server"></i>
|
|
||||||
</span>
|
|
||||||
<div>
|
|
||||||
<h4 class="m-0"><a href="javascript:void(0)">Webserver</a></h4>
|
|
||||||
<small class="text-muted">http://localhost:8000</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row row-cards row-deck">
|
|
||||||
<div class="col-12">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-header">
|
|
||||||
<h3 class="card-title">Contracts</h3>
|
|
||||||
</div>
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table card-table table-vcenter text-nowrap">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Contract Name</th>
|
|
||||||
<th>Address</th>
|
|
||||||
<th>Status</th>
|
|
||||||
<th></th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody id="contractsTable">
|
|
||||||
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row row-cards row-deck">
|
|
||||||
<div class="col-12">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-header">
|
|
||||||
<h3 class="card-title">Console</h3>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="log">
|
|
||||||
<p>Welcome!</p>
|
|
||||||
</div>
|
|
||||||
<div class="command-line">
|
|
||||||
<div class="form-group">
|
|
||||||
<input type="text" class="form-control" name="example-text-input" placeholder="type a command (e.g help)" data-com.agilebits.onepassword.user-edited="yes">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
$.get( "/embark/contracts").done(function( data ) {
|
|
||||||
$.each(data, function(i, contract) {
|
|
||||||
|
|
||||||
let $tr = $('<tr>');
|
|
||||||
|
|
||||||
if (contract.deploy === false) {
|
|
||||||
$tr.append(
|
|
||||||
$(`<td><a href="contracts/view.html?${contract.name}">${contract.name}</a>`),
|
|
||||||
$('<td>').text('Interface or set to not deploy'),
|
|
||||||
$('<td>').text('n/a'),
|
|
||||||
);
|
|
||||||
} else if (contract.error) {
|
|
||||||
$tr.append(
|
|
||||||
$(`<td><a href="contracts/view.html?${contract.name}">${contract.name}</a>`),
|
|
||||||
$('<td>').text((contract.error).split("\n")[0].replace(/Error: /g, '').substring(0, 32)),
|
|
||||||
$('<td>').text('Error'),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$tr.append(
|
|
||||||
$(`<td><a href="contracts/view.html?${contract.name}">${contract.name}</a>`),
|
|
||||||
$('<td>').text(contract.address || '...'),
|
|
||||||
$('<td>').text(contract.address !== undefined ? 'Deployed' : 'Pending')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$tr.append(
|
|
||||||
$('<td class="text-right"><a href="javascript:void(0)" class="btn btn-secondary btn-sm">Manage</a><div class="dropdown"><button class="btn btn-secondary btn-sm dropdown-toggle" data-toggle="dropdown">Actions</button></div></td>'),
|
|
||||||
$('<td><a class="icon" href="javascript:void(0)"><i class="fe fe-edit"></i></a></td>')
|
|
||||||
);
|
|
||||||
$tr.appendTo('#contractsTable');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
var ws = new WebSocket("ws://localhost:8000/embark/logs");
|
|
||||||
ws.onopen = function() {
|
|
||||||
};
|
|
||||||
ws.onmessage = function (evt) {
|
|
||||||
var received_msg = evt.data;
|
|
||||||
var log = JSON.parse(received_msg);
|
|
||||||
console.log(log);
|
|
||||||
$(".log").append('<br>[' + log.logLevel + '] ' + log.msg_clear);
|
|
||||||
};
|
|
||||||
ws.onclose = function() {
|
|
||||||
console.log("Connection is closed...");
|
|
||||||
};
|
|
||||||
window.onbeforeunload = function(event) {
|
|
||||||
ws.close();
|
|
||||||
};
|
|
||||||
|
|
||||||
$(".command-line input").keypress(function(e) {
|
|
||||||
if (e.which == 13) {
|
|
||||||
let value = $(".command-line input").val();
|
|
||||||
|
|
||||||
$.post( "/embark/console", { cmd: value }).done(function( data ) {
|
|
||||||
$(".log").append('<br>' + data.replace(/\n/g, '<br>'));
|
|
||||||
});
|
|
||||||
|
|
||||||
$(".command-line input").val('');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<footer class="footer">
|
|
||||||
<div class="container">
|
|
||||||
<div class="row align-items-center flex-row-reverse">
|
|
||||||
<div class="col-auto ml-auto">
|
|
||||||
<div class="row align-items-center">
|
|
||||||
<div class="col-auto">
|
|
||||||
<ul class="list-inline list-inline-dots mb-0">
|
|
||||||
<li class="list-inline-item"><a href="./docs/index.html">Documentation</a></li>
|
|
||||||
<li class="list-inline-item"><a href="./faq.html">FAQ</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto">
|
|
||||||
<a href="https://github.com/tabler/tabler" class="btn btn-outline-primary btn-sm">Source code</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-lg-auto mt-3 mt-lg-0 text-center">
|
|
||||||
Copyright © 2018 <a href=".">Status Embark</a>.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
Loading…
Reference in New Issue