From d80d16f4ca7538e43771a1bc102368f19019ca5a Mon Sep 17 00:00:00 2001 From: Richard Ramos Date: Thu, 10 May 2018 17:02:47 -0400 Subject: [PATCH] Form generation for view/constant/pure functions --- lib/core/plugin.js | 2 +- lib/modules/scaffolding-react/index.js | 42 ++++++- .../scaffolding-react/templates/dapp.js.tpl | 103 +++++++++++++++++- .../templates/index.html.tpl | 5 + 4 files changed, 144 insertions(+), 8 deletions(-) diff --git a/lib/core/plugin.js b/lib/core/plugin.js index 61525780..f7d6c8a7 100644 --- a/lib/core/plugin.js +++ b/lib/core/plugin.js @@ -125,7 +125,7 @@ Plugin.prototype.registerPipeline = function(matcthingFiles, cb) { Plugin.prototype.registerCustomType = function(type){ this.pluginTypes.push(type); -} +}; Plugin.prototype.addFileToPipeline = function(file, intendedPath, options) { this.pipelineFiles.push({file: file, intendedPath: intendedPath, options: options}); diff --git a/lib/modules/scaffolding-react/index.js b/lib/modules/scaffolding-react/index.js index e594e6bb..8f9ed674 100644 --- a/lib/modules/scaffolding-react/index.js +++ b/lib/modules/scaffolding-react/index.js @@ -1,8 +1,41 @@ const Handlebars = require('handlebars'); const fs = require('../../core/fs'); -const utils = require('../../utils/utils'); +Handlebars.registerHelper('capitalize', function(word) { + return word.charAt(0).toUpperCase() + word.slice(1); +}); + +Handlebars.registerHelper('ifview', function(stateMutability, options) { + let result = stateMutability == 'view' || stateMutability == 'pure' || stateMutability == 'constant'; + if (result) { + return options.fn(this); + } else { + return options.inverse(this); + } +}); + +Handlebars.registerHelper('ifarrlengthgt', function(arr, val, options) { + if (arr.length > val) { + return options.fn(this); + } else { + return options.inverse(this); + } +}); + +Handlebars.registerHelper('emptyname', function(name, index) { + return name ? name : 'outputParam' + index; +}); + + +Handlebars.registerHelper('methodname', function(abiDefinition, functionName, inputs){ + let funCount = abiDefinition.filter(x => x.name == functionName).length; + if(funCount == 1){ + return '.' + functionName; + } else { + return new Handlebars.SafeString(`['${functionName}(${inputs !== null ? inputs.map(input => input.type).join(',') : '' })']`); + } +}); class ScaffoldingReact { constructor(embark, options){ @@ -43,7 +76,8 @@ class ScaffoldingReact { this._generateFile(contract, 'dapp.js.tpl', 'js', { 'title': contract.className + ' autogenerated UI', - 'contractName': contract.className + 'contractName': contract.className, + 'functions': contract.abiDefinition.filter(x => x.type == 'function') }); // Update config @@ -51,10 +85,8 @@ class ScaffoldingReact { let embarkJson = JSON.parse(contents); embarkJson.app["js/" + filename + ".js"] = "app/" + filename + '.js'; embarkJson.app[filename + ".html"] = "app/" + filename + '.html'; + fs.writeFileSync("./embark.json", JSON.stringify(embarkJson, null, 4)); - - - } } diff --git a/lib/modules/scaffolding-react/templates/dapp.js.tpl b/lib/modules/scaffolding-react/templates/dapp.js.tpl index 3140fff4..1ad6d429 100644 --- a/lib/modules/scaffolding-react/templates/dapp.js.tpl +++ b/lib/modules/scaffolding-react/templates/dapp.js.tpl @@ -3,7 +3,102 @@ import {{contractName}} from 'Embark/contracts/{{contractName}}'; import React from 'react'; import ReactDOM from 'react-dom'; -import { Tabs, Tab } from 'react-bootstrap'; +import { FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap'; + + +{{#each functions}} +class {{capitalize name}}_{{@index}}_Form extends React.Component { + constructor(props){ + super(props); + this.state = { + {{#if inputs.length}} + input: { + {{#each inputs}} + {{name}}: ''{{#unless @last}},{{/unless}} + {{/each}} + }, + {{/if}} + {{#ifview stateMutability}} + output: null, + {{/ifview}} + message: '' + }; + } + + handleChange(e, name){ + this.state[name] = e.target.value; + this.setState(this.state); + } + + async handleClick(e){ + e.preventDefault(); + + {{#ifview stateMutability}} + this.setState({output: null}); + + let result = await {{../contractName}}.methods{{methodname ../functions name inputs}}({{#each inputs}}this.state.{{name}}{{#unless @last}}, {{/unless}}{{/each}}).call(); + {{#ifarrlengthgt outputs 1}} + this.setState({output: { + {{#each outputs}} + {{emptyname name @index}}: result[{{@index}}]{{#unless @last}},{{/unless}} + {{/each}} + }}); + {{else}} + this.setState({output: result}); + {{/ifarrlengthgt}} + + + + // TODO show on screen + {{/ifview}} + + // TODO validate + } + + render(){ + return
+

{{name}}

+
+ {{#if inputs.length}} + {{#each inputs}} + + {{name}} + this.handleChange(e, '{{name}}')} + /> + + {{/each}} + {{/if}} + {{#ifview stateMutability}} + + { + this.state.output != null ? + +

Results

+ {{#ifarrlengthgt outputs 1}} +
    + {{#each outputs}} +
  • {{emptyname name @index}}: { this.state.output.{{emptyname name @index}} }
  • + {{/each}} +
+ {{else}} + {this.state.output} + {{/ifarrlengthgt}} +
+ : '' + } + + {{/ifview}} +
+
; + } +} + +{{/each}} + class {{contractName}}UI extends React.Component { constructor (props) { @@ -13,7 +108,11 @@ class {{contractName}}UI extends React.Component { } render(){ - return (

Test

); + return (
+ {{#each functions}} + <{{capitalize name}}_{{@index}}_Form /> + {{/each}} +
); } } diff --git a/lib/modules/scaffolding-react/templates/index.html.tpl b/lib/modules/scaffolding-react/templates/index.html.tpl index 97ee3728..22b95b93 100644 --- a/lib/modules/scaffolding-react/templates/index.html.tpl +++ b/lib/modules/scaffolding-react/templates/index.html.tpl @@ -3,6 +3,11 @@ {{title}} +