From 29442673f8bae829df4cf93fc84878811af227a4 Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Mon, 14 Nov 2016 17:39:45 +0100 Subject: [PATCH] Clean-Up #3314 --- .../DeployContract/DetailsStep/detailsStep.js | 337 +----------------- .../modals/DeployContract/deployContract.css | 14 - .../modals/DeployContract/deployContract.js | 2 - js/src/ui/Form/TypedInput/index.js | 17 + js/src/ui/Form/TypedInput/typedInput.css | 31 ++ js/src/ui/Form/TypedInput/typedInput.js | 239 +++++++++++++ js/src/ui/Form/index.js | 2 + js/src/ui/index.js | 3 +- js/src/util/abi.js | 146 ++++++++ 9 files changed, 440 insertions(+), 351 deletions(-) create mode 100644 js/src/ui/Form/TypedInput/index.js create mode 100644 js/src/ui/Form/TypedInput/typedInput.css create mode 100644 js/src/ui/Form/TypedInput/typedInput.js create mode 100644 js/src/util/abi.js diff --git a/js/src/modals/DeployContract/DetailsStep/detailsStep.js b/js/src/modals/DeployContract/DetailsStep/detailsStep.js index 1773fd0da..6e23f79c9 100644 --- a/js/src/modals/DeployContract/DetailsStep/detailsStep.js +++ b/js/src/modals/DeployContract/DetailsStep/detailsStep.js @@ -15,223 +15,13 @@ // along with Parity. If not, see . import React, { Component, PropTypes } from 'react'; -import { MenuItem } from 'material-ui'; -import { range } from 'lodash'; -import IconButton from 'material-ui/IconButton'; -import AddIcon from 'material-ui/svg-icons/content/add'; -import RemoveIcon from 'material-ui/svg-icons/content/remove'; - -import { AddressSelect, Form, Input, InputAddressSelect, Select } from '../../../ui'; +import { AddressSelect, Form, Input, TypedInput } from '../../../ui'; import { validateAbi } from '../../../util/validation'; +import { parseAbiType } from '../../../util/abi'; import styles from '../deployContract.css'; -class TypedInput extends Component { - - static propTypes = { - onChange: PropTypes.func.isRequired, - accounts: PropTypes.object.isRequired, - param: PropTypes.object.isRequired, - - error: PropTypes.any, - value: PropTypes.any, - label: PropTypes.string - }; - - render () { - const { param } = this.props; - const { type } = param; - - if (type === ARRAY_TYPE) { - const { accounts, label, value = param.default } = this.props; - const { subtype, length } = param; - - const fixedLength = !!length; - - const inputs = range(length || value.length).map((_, index) => { - const onChange = (inputValue) => { - const newValues = [].concat(this.props.value); - newValues[index] = inputValue; - this.props.onChange(newValues); - }; - - return ( - - ); - }); - - return ( -
- - { fixedLength ? null : this.renderLength() } - { inputs } -
- ); - } - - return this.renderType(type); - } - - renderLength () { - const style = { - width: 16, - height: 16 - }; - - return ( -
- - - - - - - -
- ); - } - - renderType (type) { - if (type === ADDRESS_TYPE) { - return this.renderAddress(); - } - - if (type === BOOL_TYPE) { - return this.renderBoolean(); - } - - if (type === STRING_TYPE) { - return this.renderDefault(); - } - - if (type === BYTES_TYPE) { - return this.renderDefault(); - } - - if (type === INT_TYPE) { - return this.renderNumber(); - } - - if (type === FIXED_TYPE) { - return this.renderNumber(); - } - - return this.renderDefault(); - } - - renderNumber () { - const { label, value, error, param } = this.props; - - return ( - - ); - } - - renderDefault () { - const { label, value, error } = this.props; - - return ( - - ); - } - - renderAddress () { - const { accounts, label, value, error } = this.props; - - return ( - - ); - } - - renderBoolean () { - const { label, value, error } = this.props; - - const boolitems = ['false', 'true'].map((bool) => { - return ( - - { bool } - - ); - }); - - return ( - - ); - } - - onChangeBool = (event, _index, value) => { - this.props.onChange(value === 'true'); - } - - onChange = (event, value) => { - this.props.onChange(value); - } - - onSubmit = (value) => { - this.props.onChange(value); - } - - onAddField = () => { - const { value, onChange, param } = this.props; - const newValues = [].concat(value, param.subtype.default); - - onChange(newValues); - } - - onRemoveField = () => { - const { value, onChange } = this.props; - const newValues = value.slice(0, -1); - - onChange(newValues); - } - -} - export default class DetailsStep extends Component { static contextTypes = { api: PropTypes.object.isRequired @@ -313,6 +103,7 @@ export default class DetailsStep extends Component { value={ code } onSubmit={ this.onCodeChange } readOnly={ readOnly } /> + { this.renderConstructorInputs() } ); @@ -400,125 +191,3 @@ export default class DetailsStep extends Component { onCodeChange(code); } } - -const ARRAY_TYPE = 'ARRAY_TYPE'; -const ADDRESS_TYPE = 'ADDRESS_TYPE'; -const STRING_TYPE = 'STRING_TYPE'; -const BOOL_TYPE = 'BOOL_TYPE'; -const BYTES_TYPE = 'BYTES_TYPE'; -const INT_TYPE = 'INT_TYPE'; -const FIXED_TYPE = 'FIXED_TYPE'; - -function parseAbiType (type) { - const arrayRegex = /^(.+)\[(\d*)\]$/; - - if (arrayRegex.test(type)) { - const matches = arrayRegex.exec(type); - - const subtype = parseAbiType(matches[1]); - const M = parseInt(matches[2]) || null; - const defaultValue = !M - ? [] - : range(M).map(() => subtype.default); - - return { - type: ARRAY_TYPE, - subtype: subtype, - length: M, - default: defaultValue - }; - } - - const lengthRegex = /^(u?int|bytes)(\d{1,3})$/; - - if (lengthRegex.test(type)) { - const matches = lengthRegex.exec(type); - - const subtype = parseAbiType(matches[1]); - const length = parseInt(matches[2]); - - return { - ...subtype, - length - }; - } - - const fixedLengthRegex = /^(u?fixed)(\d{1,3})x(\d{1,3})$/; - - if (fixedLengthRegex.test(type)) { - const matches = fixedLengthRegex.exec(type); - - const subtype = parseAbiType(matches[1]); - const M = parseInt(matches[2]); - const N = parseInt(matches[3]); - - return { - ...subtype, - M, N - }; - } - - if (type === 'string') { - return { - type: STRING_TYPE, - default: '' - }; - } - - if (type === 'bool') { - return { - type: BOOL_TYPE, - default: false - }; - } - - if (type === 'address') { - return { - type: ADDRESS_TYPE, - default: '0x' - }; - } - - if (type === 'bytes') { - return { - type: BYTES_TYPE, - default: '0x' - }; - } - - if (type === 'uint') { - return { - type: INT_TYPE, - default: 0, - length: 256, - signed: false - }; - } - - if (type === 'int') { - return { - type: INT_TYPE, - default: 0, - length: 256, - signed: true - }; - } - - if (type === 'ufixed') { - return { - type: FIXED_TYPE, - default: 0, - length: 256, - signed: false - }; - } - - if (type === 'fixed') { - return { - type: FIXED_TYPE, - default: 0, - length: 256, - signed: true - }; - } -} diff --git a/js/src/modals/DeployContract/deployContract.css b/js/src/modals/DeployContract/deployContract.css index ef92b24af..45fd7a852 100644 --- a/js/src/modals/DeployContract/deployContract.css +++ b/js/src/modals/DeployContract/deployContract.css @@ -31,17 +31,3 @@ .funcparams { padding-left: 3em; } - -.inputs { - padding-top: 2px; - - label { - line-height: 22px; - pointer-events: none; - color: rgba(255, 255, 255, 0.498039); - -webkit-user-select: none; - font-size: 12px; - top: 11px; - position: relative; - } -} diff --git a/js/src/modals/DeployContract/deployContract.js b/js/src/modals/DeployContract/deployContract.js index d38851ccb..257ede1f1 100644 --- a/js/src/modals/DeployContract/deployContract.js +++ b/js/src/modals/DeployContract/deployContract.js @@ -278,8 +278,6 @@ export default class DeployContract extends Component { return; } - console.log('onDeploymentState', data); - switch (data.state) { case 'estimateGas': case 'postTransaction': diff --git a/js/src/ui/Form/TypedInput/index.js b/js/src/ui/Form/TypedInput/index.js new file mode 100644 index 000000000..9c12bf7eb --- /dev/null +++ b/js/src/ui/Form/TypedInput/index.js @@ -0,0 +1,17 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +export default from './typedInput'; diff --git a/js/src/ui/Form/TypedInput/typedInput.css b/js/src/ui/Form/TypedInput/typedInput.css new file mode 100644 index 000000000..c13206c96 --- /dev/null +++ b/js/src/ui/Form/TypedInput/typedInput.css @@ -0,0 +1,31 @@ +/* Copyright 2015, 2016 Ethcore (UK) Ltd. +/* This file is part of Parity. +/* +/* Parity is free software: you can redistribute it and/or modify +/* it under the terms of the GNU General Public License as published by +/* the Free Software Foundation, either version 3 of the License, or +/* (at your option) any later version. +/* +/* Parity is distributed in the hope that it will be useful, +/* but WITHOUT ANY WARRANTY; without even the implied warranty of +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +/* GNU General Public License for more details. +/* +/* You should have received a copy of the GNU General Public License +/* along with Parity. If not, see . +*/ + +.inputs { + padding-top: 2px; + overflow-x: hidden; + + label { + line-height: 22px; + pointer-events: none; + color: rgba(255, 255, 255, 0.498039); + -webkit-user-select: none; + font-size: 12px; + top: 11px; + position: relative; + } +} diff --git a/js/src/ui/Form/TypedInput/typedInput.js b/js/src/ui/Form/TypedInput/typedInput.js new file mode 100644 index 000000000..6bcb5bbf1 --- /dev/null +++ b/js/src/ui/Form/TypedInput/typedInput.js @@ -0,0 +1,239 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +import React, { Component, PropTypes } from 'react'; +import { MenuItem } from 'material-ui'; +import { range } from 'lodash'; + +import IconButton from 'material-ui/IconButton'; +import AddIcon from 'material-ui/svg-icons/content/add'; +import RemoveIcon from 'material-ui/svg-icons/content/remove'; + +import { Input, InputAddressSelect, Select } from '../../../ui'; +import { ABI_TYPES } from '../../../util/abi'; + +import styles from './typedInput.css'; + +export default class TypedInput extends Component { + + static propTypes = { + onChange: PropTypes.func.isRequired, + accounts: PropTypes.object.isRequired, + param: PropTypes.object.isRequired, + + error: PropTypes.any, + value: PropTypes.any, + label: PropTypes.string + }; + + render () { + const { param } = this.props; + const { type } = param; + + if (type === ABI_TYPES.ARRAY) { + const { accounts, label, value = param.default } = this.props; + const { subtype, length } = param; + + const fixedLength = !!length; + + const inputs = range(length || value.length).map((_, index) => { + const onChange = (inputValue) => { + const newValues = [].concat(this.props.value); + newValues[index] = inputValue; + this.props.onChange(newValues); + }; + + return ( + + ); + }); + + return ( +
+ + { fixedLength ? null : this.renderLength() } + { inputs } +
+ ); + } + + return this.renderType(type); + } + + renderLength () { + const iconStyle = { + width: 16, + height: 16 + }; + + const style = { + width: 32, + height: 32, + padding: 0 + }; + + return ( +
+ + + + + + + +
+ ); + } + + renderType (type) { + if (type === ABI_TYPES.ADDRESS) { + return this.renderAddress(); + } + + if (type === ABI_TYPES.BOOL) { + return this.renderBoolean(); + } + + if (type === ABI_TYPES.STRING) { + return this.renderDefault(); + } + + if (type === ABI_TYPES.BYTES) { + return this.renderDefault(); + } + + if (type === ABI_TYPES.INT) { + return this.renderNumber(); + } + + if (type === ABI_TYPES.FIXED) { + return this.renderNumber(); + } + + return this.renderDefault(); + } + + renderNumber () { + const { label, value, error, param } = this.props; + + return ( + + ); + } + + renderDefault () { + const { label, value, error } = this.props; + + return ( + + ); + } + + renderAddress () { + const { accounts, label, value, error } = this.props; + + return ( + + ); + } + + renderBoolean () { + const { label, value, error } = this.props; + + const boolitems = ['false', 'true'].map((bool) => { + return ( + + { bool } + + ); + }); + + return ( + + ); + } + + onChangeBool = (event, _index, value) => { + this.props.onChange(value === 'true'); + } + + onChange = (event, value) => { + this.props.onChange(value); + } + + onSubmit = (value) => { + this.props.onChange(value); + } + + onAddField = () => { + const { value, onChange, param } = this.props; + const newValues = [].concat(value, param.subtype.default); + + onChange(newValues); + } + + onRemoveField = () => { + const { value, onChange } = this.props; + const newValues = value.slice(0, -1); + + onChange(newValues); + } + +} diff --git a/js/src/ui/Form/index.js b/js/src/ui/Form/index.js index 061cdddd0..46bb106f4 100644 --- a/js/src/ui/Form/index.js +++ b/js/src/ui/Form/index.js @@ -16,6 +16,7 @@ import AddressSelect from './AddressSelect'; import FormWrap from './FormWrap'; +import TypedInput from './TypedInput'; import Input from './Input'; import InputAddress from './InputAddress'; import InputAddressSelect from './InputAddressSelect'; @@ -27,6 +28,7 @@ export default from './form'; export { AddressSelect, FormWrap, + TypedInput, Input, InputAddress, InputAddressSelect, diff --git a/js/src/ui/index.js b/js/src/ui/index.js index ebfce3ad1..69a7d26c3 100644 --- a/js/src/ui/index.js +++ b/js/src/ui/index.js @@ -29,7 +29,7 @@ import ContextProvider from './ContextProvider'; import CopyToClipboard from './CopyToClipboard'; import Editor from './Editor'; import Errors from './Errors'; -import Form, { AddressSelect, FormWrap, Input, InputAddress, InputAddressSelect, InputChip, InputInline, Select } from './Form'; +import Form, { AddressSelect, FormWrap, TypedInput, Input, InputAddress, InputAddressSelect, InputChip, InputInline, Select } from './Form'; import IdentityIcon from './IdentityIcon'; import IdentityName from './IdentityName'; import MethodDecoding from './MethodDecoding'; @@ -62,6 +62,7 @@ export { Errors, Form, FormWrap, + TypedInput, Input, InputAddress, InputAddressSelect, diff --git a/js/src/util/abi.js b/js/src/util/abi.js new file mode 100644 index 000000000..9c6c597f5 --- /dev/null +++ b/js/src/util/abi.js @@ -0,0 +1,146 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +import { range } from 'lodash'; + +const ARRAY_TYPE = 'ARRAY_TYPE'; +const ADDRESS_TYPE = 'ADDRESS_TYPE'; +const STRING_TYPE = 'STRING_TYPE'; +const BOOL_TYPE = 'BOOL_TYPE'; +const BYTES_TYPE = 'BYTES_TYPE'; +const INT_TYPE = 'INT_TYPE'; +const FIXED_TYPE = 'FIXED_TYPE'; + +export const ABI_TYPES = { + ARRAY: ARRAY_TYPE, ADDRESS: ADDRESS_TYPE, + STRING: STRING_TYPE, BOOL: BOOL_TYPE, + BYTES: BYTES_TYPE, INT: INT_TYPE, + FIXED: FIXED_TYPE +}; + +export function parseAbiType (type) { + const arrayRegex = /^(.+)\[(\d*)\]$/; + + if (arrayRegex.test(type)) { + const matches = arrayRegex.exec(type); + + const subtype = parseAbiType(matches[1]); + const M = parseInt(matches[2]) || null; + const defaultValue = !M + ? [] + : range(M).map(() => subtype.default); + + return { + type: ARRAY_TYPE, + subtype: subtype, + length: M, + default: defaultValue + }; + } + + const lengthRegex = /^(u?int|bytes)(\d{1,3})$/; + + if (lengthRegex.test(type)) { + const matches = lengthRegex.exec(type); + + const subtype = parseAbiType(matches[1]); + const length = parseInt(matches[2]); + + return { + ...subtype, + length + }; + } + + const fixedLengthRegex = /^(u?fixed)(\d{1,3})x(\d{1,3})$/; + + if (fixedLengthRegex.test(type)) { + const matches = fixedLengthRegex.exec(type); + + const subtype = parseAbiType(matches[1]); + const M = parseInt(matches[2]); + const N = parseInt(matches[3]); + + return { + ...subtype, + M, N + }; + } + + if (type === 'string') { + return { + type: STRING_TYPE, + default: '' + }; + } + + if (type === 'bool') { + return { + type: BOOL_TYPE, + default: false + }; + } + + if (type === 'address') { + return { + type: ADDRESS_TYPE, + default: '0x' + }; + } + + if (type === 'bytes') { + return { + type: BYTES_TYPE, + default: '0x' + }; + } + + if (type === 'uint') { + return { + type: INT_TYPE, + default: 0, + length: 256, + signed: false + }; + } + + if (type === 'int') { + return { + type: INT_TYPE, + default: 0, + length: 256, + signed: true + }; + } + + if (type === 'ufixed') { + return { + type: FIXED_TYPE, + default: 0, + length: 256, + signed: false + }; + } + + if (type === 'fixed') { + return { + type: FIXED_TYPE, + default: 0, + length: 256, + signed: true + }; + } +}