Gas price dropdown (#61)

* implement gas price dropdown
This commit is contained in:
skubakdj 2017-07-20 13:06:10 -04:00 committed by Daniel Ternyak
parent d2ae162e80
commit 7fd7ba66c9
7 changed files with 170 additions and 8 deletions

View File

@ -11,6 +11,11 @@ export type ChangeLanguageAction = {
value: string
};
export type ChangeGasPriceAction = {
type: 'CONFIG_GAS_PRICE',
value: number
}
export type ConfigAction = ChangeNodeAction | ChangeLanguageAction;
export function changeLanguage(sign: string) {
@ -26,3 +31,11 @@ export function changeNode(value: string): ChangeNodeAction {
value
};
}
export function changeGasPrice(value: number): ChangeGasPriceAction {
return {
type: 'CONFIG_GAS_PRICE',
value
}
}

View File

@ -0,0 +1,80 @@
// @flow
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import './GasPriceDropdown.scss';
import { gasPriceDefaults } from 'config/data';
export default class GasPriceDropdown extends Component {
state = { expanded: false };
static propTypes = {
value: PropTypes.number,
onChange: PropTypes.func.isRequired
};
render() {
return (
<span className="dropdown">
<a
aria-haspopup="true"
aria-label="adjust gas price"
className="dropdown-toggle"
onClick={this.toggleExpanded}
>
<span>Gas Price</span>: {this.props.value} Gwei
<i className="caret" />
</a>
{this.state.expanded &&
<ul className="dropdown-menu GasPrice-dropdown-menu">
<div className="GasPrice-header">
<span>Gas Price</span>: {this.props.value} Gwei
<input
type="range"
value={this.props.value}
min={gasPriceDefaults.gasPriceMinGwei}
max={gasPriceDefaults.gasPriceMaxGwei}
onChange={this.updateGasPrice}
/>
<p className="small col-xs-4 text-left GasPrice-padding-reset">
Not So Fast
</p>
<p className="small col-xs-4 text-center GasPrice-padding-reset">
Fast
</p>
<p className="small col-xs-4 text-right GasPrice-padding-reset">
Fast AF
</p>
<p className="small GasPrice-description">
Gas Price is the amount you pay per unit of gas.{' '}
<code>TX fee = gas price * gas limit</code> & is paid to miners
for including your TX in a block. Higher the gas price = faster
transaction, but more expensive. Default is <code>21 GWEI</code>.
</p>
<p>
{/* TODO: maybe not hardcode a link? :) */}
<a
href="https://myetherwallet.groovehq.com/knowledge_base/topics/what-is-gas"
target="_blank"
>
Read more
</a>
</p>
</div>
</ul>}
</span>
);
}
toggleExpanded = () => {
this.setState(state => {
return {
expanded: !state.expanded
};
});
};
updateGasPrice = (e: SyntheticInputEvent) => {
this.props.onChange(e.currentTarget.valueAsNumber);
};
}

View File

@ -0,0 +1,33 @@
@import "common/sass/variables";
.GasPrice {
&-dropdown-menu {
padding: 0.5rem !important;
min-width: 300px !important;
}
&-header {
max-width: 26rem;
color: $text-color;
p {
font-weight: 400;
margin: $space-sm 0 0;
}
a, a:hover, a:focus, a:visited {
color: $brand-primary !important;
}
}
&-padding-reset {
padding-left: 0 !important;
padding-right: 0 !important;
}
&-description {
white-space: normal;
font-weight: 300 !important;
margin: 2rem 0 0;
}
}

View File

@ -1,6 +1,7 @@
// @flow
import React, { Component } from 'react';
import Navigation from './components/Navigation';
import GasPriceDropdown from './components/GasPriceDropdown';
import { Link } from 'react-router';
import { Dropdown } from 'components/ui';
import { languages, NODES } from '../../config/data';
@ -13,9 +14,11 @@ export default class Header extends Component {
location: {},
languageSelection: string,
nodeSelection: string,
gasPriceGwei: number,
changeLanguage: (sign: string) => any,
changeNode: (key: string) => any
changeNode: (key: string) => any,
changeGasPrice: (price: number) => any
};
render() {
@ -47,6 +50,11 @@ export default class Header extends Component {
Open-Source & Client-Side Ether Wallet · v3.6.0
</span>
<GasPriceDropdown
value={this.props.gasPriceGwei}
onChange={this.props.changeGasPrice}
/>
<Dropdown
ariaLabel={`change language. current language ${selectedLanguage.name}`}
options={languages}

View File

@ -9,6 +9,11 @@ export const DONATION_ADDRESSES_MAP = {
export const donationAddressMap = DONATION_ADDRESSES_MAP;
export const gasPriceDefaults = {
gasPriceMinGwei: 1,
gasPriceMaxGwei: 60
};
export const languages = [
{
sign: 'en',

View File

@ -16,8 +16,11 @@ class App extends Component {
languageSelection: string,
nodeSelection: string,
gasPriceGwei: number,
changeLanguage: typeof actions.changeLanguage,
changeNode: typeof actions.changeNode,
changeGasPrice: typeof actions.changeGasPrice,
handleWindowResize: () => void
};
@ -25,18 +28,24 @@ class App extends Component {
let {
children,
// APP
nodeSelection,
languageSelection,
gasPriceGwei,
changeLanguage,
changeNode,
nodeSelection
changeGasPrice
} = this.props;
let headerProps = {
location,
changeLanguage,
languageSelection,
nodeSelection,
gasPriceGwei,
changeLanguage,
changeNode,
nodeSelection
changeGasPrice
};
return (
@ -59,7 +68,9 @@ function mapStateToProps(state) {
nodeSelection: state.config.nodeSelection,
nodeToggle: state.config.nodeToggle,
languageSelection: state.config.languageSelection,
languageToggle: state.config.languageToggle
languageToggle: state.config.languageToggle,
gasPriceGwei: state.config.gasPriceGwei
};
}

View File

@ -2,19 +2,22 @@
import type {
ConfigAction,
ChangeNodeAction,
ChangeLanguageAction
ChangeLanguageAction,
ChangeGasPriceAction
} from 'actions/config';
import { languages, NODES } from '../config/data';
export type State = {
// FIXME
languageSelection: string,
nodeSelection: string
nodeSelection: string,
gasPriceGwei: number
};
export const initialState: State = {
languageSelection: languages[0].sign,
nodeSelection: Object.keys(NODES)[0]
nodeSelection: Object.keys(NODES)[0],
gasPriceGwei: 21
};
function changeLanguage(state: State, action: ChangeLanguageAction): State {
@ -31,6 +34,13 @@ function changeNode(state: State, action: ChangeNodeAction): State {
};
}
function changeGasPrice(state: State, action: ChangeGasPriceAction): State {
return {
...state,
gasPriceGwei: action.value
};
}
export function config(
state: State = initialState,
action: ConfigAction
@ -40,6 +50,8 @@ export function config(
return changeLanguage(state, action);
case 'CONFIG_NODE_CHANGE':
return changeNode(state, action);
case 'CONFIG_GAS_PRICE':
return changeGasPrice(state, action);
default:
return state;
}