Add block & timestamp conditions to Signer (#4411)

* WIP

* WIP (with lint)

* Update ui/RadioButtons

* transaction.condition

* Date & Time selection in-place

* Swap to condition-only

* Fix tests, align naming

* Pick error properly from validation

* Update tests

* condition: time sent withough ms

* Format numbers as base-10

* override popup styles (zIndex)

* Pass condition to signer

* Update expectation (failing test typo)

* Adjust min/max height for expanded bar

* Fix address display

* Fix name display

* Number inputs for gas/gasPrice/blockNumber

* Default blockNumber to 1 (align with min setting)

* Update tests with min value

* Add Block Number

* Fix failing tests (after blockNumber intro)
This commit is contained in:
Jaco Greeff
2017-02-03 20:01:09 +01:00
committed by GitHub
parent 312aa72747
commit cd4d489b57
31 changed files with 894 additions and 255 deletions

View File

@@ -78,6 +78,9 @@ class InputAddress extends Component {
props.focused = focused;
}
// FIXME: The is not advisable, fixes the display issue, however the name should come from
// a common component.
// account.name || (value ? 'UNNAMED' : value)
return (
<div className={ containerClasses.join(' ') }>
<Input
@@ -96,7 +99,7 @@ class InputAddress extends Component {
tabIndex={ tabIndex }
value={
text && account
? account.name
? (account.name || (value ? 'UNNAMED' : value))
: (nullName || value)
}
{ ...props }

View File

@@ -0,0 +1,17 @@
// Copyright 2015-2017 Parity Technologies (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 <http://www.gnu.org/licenses/>.
export default from './inputDate';

View File

@@ -0,0 +1,22 @@
/* Copyright 2015-2017 Parity Technologies (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 <http://www.gnu.org/licenses/>.
*/
.container {
.input {
width: 100%;
}
}

View File

@@ -0,0 +1,53 @@
// Copyright 2015-2017 Parity Technologies (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 <http://www.gnu.org/licenses/>.
import { DatePicker } from 'material-ui';
import React, { Component, PropTypes } from 'react';
import Label from '../Label';
import styles from './inputDate.css';
// NOTE: Has to be larger than Signer overlay Z, aligns with ../InputTime
const DIALOG_STYLE = { zIndex: 10010 };
export default class InputDate extends Component {
static propTypes = {
className: PropTypes.string,
hint: PropTypes.node,
label: PropTypes.node,
onChange: PropTypes.func,
value: PropTypes.object.isRequired
};
render () {
const { className, hint, label, onChange, value } = this.props;
return (
<div className={ [styles.container, className].join(' ') }>
<Label label={ label } />
<DatePicker
autoOk
className={ styles.input }
dialogContainerStyle={ DIALOG_STYLE }
hintText={ hint }
onChange={ onChange }
value={ value }
/>
</div>
);
}
}

View File

@@ -0,0 +1,17 @@
// Copyright 2015-2017 Parity Technologies (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 <http://www.gnu.org/licenses/>.
export default from './inputTime';

View File

@@ -0,0 +1,22 @@
/* Copyright 2015-2017 Parity Technologies (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 <http://www.gnu.org/licenses/>.
*/
.container {
.input {
width: 100%;
}
}

View File

@@ -0,0 +1,54 @@
// Copyright 2015-2017 Parity Technologies (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 <http://www.gnu.org/licenses/>.
import { TimePicker } from 'material-ui';
import React, { Component, PropTypes } from 'react';
import Label from '../Label';
import styles from './inputTime.css';
// NOTE: Has to be larger than Signer overlay Z, aligns with ../InputDate
const DIALOG_STYLE = { zIndex: 10010 };
export default class InputTime extends Component {
static propTypes = {
className: PropTypes.string,
hint: PropTypes.node,
label: PropTypes.node,
onChange: PropTypes.func,
value: PropTypes.object.isRequired
}
render () {
const { className, hint, label, onChange, value } = this.props;
return (
<div className={ [styles.container, className].join(' ') }>
<Label label={ label } />
<TimePicker
autoOk
className={ styles.input }
dialogStyle={ DIALOG_STYLE }
format='24hr'
hintText={ hint }
onChange={ onChange }
value={ value }
/>
</div>
);
}
}

View File

@@ -0,0 +1,17 @@
// Copyright 2015-2017 Parity Technologies (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 <http://www.gnu.org/licenses/>.
export default from './label';

View File

@@ -0,0 +1,24 @@
/* Copyright 2015-2017 Parity Technologies (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 <http://www.gnu.org/licenses/>.
*/
$labelColor: rgba(255, 255, 255, 0.5);
$labelFontSize: 0.75rem;
.label {
color: $labelColor;
font-size: $labelFontSize;
}

View File

@@ -0,0 +1,40 @@
// Copyright 2015-2017 Parity Technologies (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 <http://www.gnu.org/licenses/>.
import React, { Component, PropTypes } from 'react';
import styles from './label.css';
export default class Label extends Component {
static propTypes = {
className: PropTypes.string,
label: PropTypes.node
}
render () {
const { className, label } = this.props;
if (!label) {
return null;
}
return (
<label className={ [styles.label, className].join(' ') }>
{ label }
</label>
);
}
}

View File

@@ -15,18 +15,23 @@
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
*/
.spaced {
margin: 0.25em 0;
}
.container {
.label {
}
.typeContainer {
display: flex;
flex-direction: column;
.radioButton {
margin: 0.25em 0;
}
.desc {
font-size: 0.8em;
margin-bottom: 0.5em;
color: #ccc;
z-index: 2;
.radioLabel {
display: flex;
flex-direction: column;
.description {
font-size: 0.8em;
margin-bottom: 0.5em;
color: #ccc;
z-index: 2;
}
}
}

View File

@@ -18,10 +18,14 @@ import { RadioButton, RadioButtonGroup } from 'material-ui/RadioButton';
import React, { Component, PropTypes } from 'react';
import { arrayOrObjectProptype } from '~/util/proptypes';
import Label from '../Label';
import styles from './radioButtons.css';
export default class RadioButtons extends Component {
static propTypes = {
className: PropTypes.string,
label: PropTypes.node,
name: PropTypes.string,
onChange: PropTypes.func.isRequired,
value: PropTypes.any,
@@ -34,10 +38,10 @@ export default class RadioButtons extends Component {
};
render () {
const { value, values } = this.props;
const { className, label, value, values } = this.props;
const index = Number.isNaN(parseInt(value))
? values.findIndex((val) => val.key === value)
? values.findIndex((_value) => _value.key === value)
: parseInt(value);
const selectedValue = typeof value !== 'object'
? values[index]
@@ -45,13 +49,19 @@ export default class RadioButtons extends Component {
const key = this.getKey(selectedValue, index);
return (
<RadioButtonGroup
name={ name }
onChange={ this.onChange }
valueSelected={ key }
>
{ this.renderContent() }
</RadioButtonGroup>
<div className={ [styles.container, className].join(' ') }>
<Label
className={ styles.label }
label={ label }
/>
<RadioButtonGroup
name={ name }
onChange={ this.onChange }
valueSelected={ key }
>
{ this.renderContent() }
</RadioButtonGroup>
</div>
);
}
@@ -67,14 +77,14 @@ export default class RadioButtons extends Component {
return (
<RadioButton
className={ styles.spaced }
className={ styles.radioButton }
key={ index }
label={
<div className={ styles.typeContainer }>
<div className={ styles.radioLabel }>
<span>{ label }</span>
{
description
? <span className={ styles.desc }>{ description }</span>
? <span className={ styles.description }>{ description }</span>
: null
}
</div>
@@ -97,7 +107,7 @@ export default class RadioButtons extends Component {
onChange = (event, index) => {
const { onChange, values } = this.props;
const value = values[index] || values.find((v) => v.key === index);
const value = values[index] || values.find((value) => value.key === index);
onChange(value, index);
}

View File

@@ -16,25 +16,31 @@
import AddressSelect from './AddressSelect';
import FormWrap from './FormWrap';
import TypedInput from './TypedInput';
import Input from './Input';
import InputAddress from './InputAddress';
import InputAddressSelect from './InputAddressSelect';
import InputChip from './InputChip';
import InputDate from './InputDate';
import InputInline from './InputInline';
import Select from './Select';
import InputTime from './InputTime';
import Label from './Label';
import RadioButtons from './RadioButtons';
import Select from './Select';
import TypedInput from './TypedInput';
export default from './form';
export {
AddressSelect,
FormWrap,
TypedInput,
Input,
InputAddress,
InputAddressSelect,
InputChip,
InputDate,
InputInline,
InputTime,
Label,
RadioButtons,
Select,
RadioButtons
TypedInput
};