Fixes to the Registry dapp (#4984)
* Don't show fee warning when there is none * Hide Warning in Registry onclick * Use the default account in the Registry * Fix Etherscan links in Regsitry
This commit is contained in:
parent
b725829bfd
commit
a028e445fe
@ -42,7 +42,7 @@ export default class Personal {
|
||||
|
||||
// FIXME: Because of the different API instances, the "wait for valid changes" approach
|
||||
// doesn't work. Since the defaultAccount is critical to operation, we poll in exactly
|
||||
// same way we do in ../eth (ala same as eth_blockNumber) and update. This should be moved
|
||||
// same way we do in ../eth (ala eth_blockNumber) and update. This should be moved
|
||||
// to pub-sub as it becomes available
|
||||
_defaultAccount = (timerDisabled = false) => {
|
||||
const nextTimeout = (timeout = 1000) => {
|
||||
|
@ -15,24 +15,10 @@
|
||||
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
.button {
|
||||
/* TODO remove !important once material design lite is used */
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.icon {
|
||||
/* TODO remove !important once material design lite is used */
|
||||
margin: 0 !important;
|
||||
width: 30px !important;
|
||||
height: 30px !important;
|
||||
}
|
||||
|
||||
.menuIcon {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.menuText {
|
||||
display: inline-block;
|
||||
line-height: 24px;
|
||||
vertical-align: top;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
width: 30px !important;
|
||||
}
|
||||
|
@ -17,83 +17,50 @@
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import IconMenu from 'material-ui/IconMenu';
|
||||
import IconButton from 'material-ui/IconButton/IconButton';
|
||||
import AccountIcon from 'material-ui/svg-icons/action/account-circle';
|
||||
import MenuItem from 'material-ui/MenuItem';
|
||||
|
||||
import { init } from './actions';
|
||||
import IdentityIcon from '../IdentityIcon';
|
||||
import Address from '../ui/address';
|
||||
|
||||
import { select } from './actions';
|
||||
import styles from './accounts.css';
|
||||
|
||||
class Accounts extends Component {
|
||||
static propTypes = {
|
||||
all: PropTypes.object.isRequired,
|
||||
selected: PropTypes.object,
|
||||
selected: PropTypes.oneOfType([
|
||||
PropTypes.oneOf([ null ]),
|
||||
PropTypes.string
|
||||
]),
|
||||
onInit: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
select: PropTypes.func.isRequired
|
||||
componentWillMount () {
|
||||
this.props.onInit();
|
||||
}
|
||||
|
||||
render () {
|
||||
const { all, selected } = this.props;
|
||||
const { selected } = this.props;
|
||||
|
||||
const origin = { horizontal: 'right', vertical: 'top' };
|
||||
|
||||
const accountsButton = (
|
||||
<IconButton className={ styles.button }>
|
||||
{ selected
|
||||
? (
|
||||
<IdentityIcon
|
||||
className={ styles.icon }
|
||||
address={ selected.address }
|
||||
/>
|
||||
) : (
|
||||
if (!selected) {
|
||||
return (
|
||||
<AccountIcon
|
||||
className={ styles.icon }
|
||||
color='white'
|
||||
/>
|
||||
)
|
||||
}
|
||||
</IconButton>);
|
||||
|
||||
return (
|
||||
<IconMenu
|
||||
value={ selected ? this.renderAccount(selected) : null }
|
||||
onChange={ this.onAccountSelect }
|
||||
iconButtonElement={ accountsButton }
|
||||
|
||||
anchorOrigin={ origin }
|
||||
targetOrigin={ origin }
|
||||
>
|
||||
{ Object.values(all).map(this.renderAccount) }
|
||||
</IconMenu>
|
||||
);
|
||||
}
|
||||
|
||||
renderAccount = (account) => {
|
||||
const { selected } = this.props;
|
||||
const isSelected = selected && selected.address === account.address;
|
||||
|
||||
return (
|
||||
<MenuItem
|
||||
key={ account.address }
|
||||
value={ account.address }
|
||||
checked={ isSelected }
|
||||
insetChildren={ !isSelected }
|
||||
>
|
||||
<Address address={ account.address } />
|
||||
</MenuItem>
|
||||
<IdentityIcon
|
||||
className={ styles.icon }
|
||||
address={ selected }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
onAccountSelect = (e, address) => {
|
||||
this.props.select(address);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => state.accounts;
|
||||
const mapDispatchToProps = (dispatch) => bindActionCreators({ select }, dispatch);
|
||||
const mapDispatchToProps = (dispatch) => bindActionCreators({
|
||||
onInit: init
|
||||
}, dispatch);
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Accounts);
|
||||
|
@ -14,4 +14,27 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { api } from '../parity';
|
||||
|
||||
export const select = (address) => ({ type: 'accounts select', address });
|
||||
|
||||
export const init = () => (dispatch) => {
|
||||
api.subscribe('parity_defaultAccount', (error, accountAddress) => {
|
||||
if (error) {
|
||||
return console.error(error);
|
||||
}
|
||||
|
||||
if (accountAddress) {
|
||||
dispatch(select(accountAddress));
|
||||
}
|
||||
});
|
||||
|
||||
return api.parity
|
||||
.defaultAccount()
|
||||
.then((accountAddress) => {
|
||||
dispatch(select(accountAddress));
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
});
|
||||
};
|
||||
|
@ -16,9 +16,11 @@
|
||||
*/
|
||||
|
||||
.header {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: 0; padding: .3em 1em;
|
||||
margin: 0;
|
||||
padding: 0.3em 1em;
|
||||
color: #fff;
|
||||
background-color: #333;
|
||||
}
|
||||
@ -54,6 +56,7 @@
|
||||
background: #f80;
|
||||
bottom: 0;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
left: 0;
|
||||
opacity: 1;
|
||||
padding: 1.5em;
|
||||
|
@ -49,6 +49,10 @@ export default class Application extends Component {
|
||||
fee: nullableProptype(PropTypes.object.isRequired)
|
||||
};
|
||||
|
||||
state = {
|
||||
showWarning: true
|
||||
};
|
||||
|
||||
render () {
|
||||
const { contract, fee } = this.props;
|
||||
let warning = null;
|
||||
@ -65,9 +69,7 @@ export default class Application extends Component {
|
||||
<Lookup />
|
||||
{ this.renderActions() }
|
||||
<Events />
|
||||
<div className={ styles.warning }>
|
||||
WARNING: The name registry is experimental. Please ensure that you understand the risks, benefits & consequences of registering a name before doing so. A non-refundable fee of { api.util.fromWei(fee).toFormat(3) }<small>ETH</small> is required for all registrations.
|
||||
</div>
|
||||
{ this.renderWarning() }
|
||||
</div>
|
||||
) : (
|
||||
<CircularProgress size={ 60 } />
|
||||
@ -98,4 +100,39 @@ export default class Application extends Component {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderWarning () {
|
||||
const { showWarning } = this.state;
|
||||
const { fee } = this.props;
|
||||
|
||||
if (!showWarning) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={ styles.warning }
|
||||
onClick={ this.handleHideWarning }
|
||||
>
|
||||
<span>
|
||||
WARNING: The name registry is experimental. Please ensure that you understand the risks,
|
||||
benefits & consequences of registering a name before doing so.
|
||||
</span>
|
||||
{
|
||||
fee && api.util.fromWei(fee).gt(0)
|
||||
? (
|
||||
<span>
|
||||
A non-refundable fee of { api.util.fromWei(fee).toFormat(3) } <small>ETH</small>
|
||||
is required for all registrations.
|
||||
</span>
|
||||
)
|
||||
: null
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
handleHideWarning = () => {
|
||||
this.setState({ showWarning: false });
|
||||
}
|
||||
}
|
||||
|
@ -33,11 +33,11 @@ export const reserveFail = (name, error) => ({ type: 'names reserve fail', name,
|
||||
|
||||
export const reserve = (name) => (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const account = state.accounts.selected;
|
||||
const accountAddress = state.accounts.selected;
|
||||
const contract = state.contract;
|
||||
const fee = state.fee;
|
||||
|
||||
if (!contract || !account) {
|
||||
if (!contract || !accountAddress) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ export const reserve = (name) => (dispatch, getState) => {
|
||||
const { reserve } = contract.instance;
|
||||
|
||||
const options = {
|
||||
from: account.address,
|
||||
from: accountAddress,
|
||||
value: fee
|
||||
};
|
||||
const values = [
|
||||
@ -88,10 +88,10 @@ export const dropFail = (name, error) => ({ type: 'names drop fail', name, error
|
||||
|
||||
export const drop = (name) => (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const account = state.accounts.selected;
|
||||
const accountAddress = state.accounts.selected;
|
||||
const contract = state.contract;
|
||||
|
||||
if (!contract || !account) {
|
||||
if (!contract || !accountAddress) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -105,14 +105,14 @@ export const drop = (name) => (dispatch, getState) => {
|
||||
|
||||
return getOwner(contract, name)
|
||||
.then((owner) => {
|
||||
if (owner.toLowerCase() !== account.address.toLowerCase()) {
|
||||
if (owner.toLowerCase() !== accountAddress.toLowerCase()) {
|
||||
throw new Error(`you are not the owner of "${name}"`);
|
||||
}
|
||||
|
||||
const { drop } = contract.instance;
|
||||
|
||||
const options = {
|
||||
from: account.address
|
||||
from: accountAddress
|
||||
};
|
||||
|
||||
const values = [
|
||||
|
@ -30,10 +30,10 @@ export const fail = (error) => ({ type: 'records update fail', error });
|
||||
|
||||
export const update = (name, key, value) => (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const account = state.accounts.selected;
|
||||
const accountAddress = state.accounts.selected;
|
||||
const contract = state.contract;
|
||||
|
||||
if (!contract || !account) {
|
||||
if (!contract || !accountAddress) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ export const update = (name, key, value) => (dispatch, getState) => {
|
||||
|
||||
return getOwner(contract, name)
|
||||
.then((owner) => {
|
||||
if (owner.toLowerCase() !== account.address.toLowerCase()) {
|
||||
if (owner.toLowerCase() !== accountAddress.toLowerCase()) {
|
||||
throw new Error(`you are not the owner of "${name}"`);
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ export const update = (name, key, value) => (dispatch, getState) => {
|
||||
: contract.instance.setData || contract.instance.set;
|
||||
|
||||
const options = {
|
||||
from: account.address
|
||||
from: accountAddress
|
||||
};
|
||||
|
||||
const values = [
|
||||
|
@ -30,10 +30,10 @@ export const fail = (action, error) => ({ type: `reverse ${action} fail`, error
|
||||
|
||||
export const propose = (name, address) => (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const account = state.accounts.selected;
|
||||
const accountAddress = state.accounts.selected;
|
||||
const contract = state.contract;
|
||||
|
||||
if (!contract || !account) {
|
||||
if (!contract || !accountAddress) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -42,14 +42,14 @@ export const propose = (name, address) => (dispatch, getState) => {
|
||||
|
||||
return getOwner(contract, name)
|
||||
.then((owner) => {
|
||||
if (owner.toLowerCase() !== account.address.toLowerCase()) {
|
||||
if (owner.toLowerCase() !== accountAddress.toLowerCase()) {
|
||||
throw new Error(`you are not the owner of "${name}"`);
|
||||
}
|
||||
|
||||
const { proposeReverse } = contract.instance;
|
||||
|
||||
const options = {
|
||||
from: account.address
|
||||
from: accountAddress
|
||||
};
|
||||
|
||||
const values = [
|
||||
@ -74,10 +74,10 @@ export const propose = (name, address) => (dispatch, getState) => {
|
||||
|
||||
export const confirm = (name) => (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const account = state.accounts.selected;
|
||||
const accountAddress = state.accounts.selected;
|
||||
const contract = state.contract;
|
||||
|
||||
if (!contract || !account) {
|
||||
if (!contract || !accountAddress) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -86,14 +86,14 @@ export const confirm = (name) => (dispatch, getState) => {
|
||||
|
||||
return getOwner(contract, name)
|
||||
.then((owner) => {
|
||||
if (owner.toLowerCase() !== account.address.toLowerCase()) {
|
||||
if (owner.toLowerCase() !== accountAddress.toLowerCase()) {
|
||||
throw new Error(`you are not the owner of "${name}"`);
|
||||
}
|
||||
|
||||
const { confirmReverse } = contract.instance;
|
||||
|
||||
const options = {
|
||||
from: account.address
|
||||
from: accountAddress
|
||||
};
|
||||
|
||||
const values = [
|
||||
|
@ -31,8 +31,8 @@ export default (state = initialState, action) => {
|
||||
return { ...state, all: accounts };
|
||||
}
|
||||
|
||||
if (action.type === 'accounts select' && state.all[action.address]) {
|
||||
return { ...state, selected: state.all[action.address] };
|
||||
if (action.type === 'accounts select') {
|
||||
return { ...state, selected: action.address };
|
||||
}
|
||||
|
||||
return state;
|
||||
|
@ -22,7 +22,7 @@ const etherscanUrl = (hash, isTestnet, netVersion) => {
|
||||
hash = hash.toLowerCase().replace(leading0x, '');
|
||||
const type = hash.length === 40 ? 'address' : 'tx';
|
||||
|
||||
return `https://${externalUrl(isTestnet, netVersion)}/${type}/0x${hash}`;
|
||||
return `${externalUrl(isTestnet, netVersion)}/${type}/0x${hash}`;
|
||||
};
|
||||
|
||||
export default etherscanUrl;
|
||||
|
Loading…
Reference in New Issue
Block a user