Merge branch 'master' into ui-2
# Conflicts: # js/src/shared/redux/middleware.js # js/src/shared/redux/providers/registry/middleware.js # js/src/shell/Application/application.js # js/src/ui/Actionbar/actionbar.js # js/src/ui/Button/button.js # js/src/ui/Form/AddressSelect/addressSelect.js # js/src/ui/Form/Input/input.js # js/src/ui/MethodDecoding/methodDecoding.js
This commit is contained in:
commit
566b6a1967
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1781,7 +1781,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "parity-ui-precompiled"
|
||||
version = "1.4.0"
|
||||
source = "git+https://github.com/paritytech/js-precompiled.git#cff0aec1877a4b75f51de3facee9fe439a41a90d"
|
||||
source = "git+https://github.com/paritytech/js-precompiled.git#eef7f1ac0dfc44527ef1925968235c5e69add959"
|
||||
dependencies = [
|
||||
"parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "parity.js",
|
||||
"version": "1.7.70",
|
||||
"version": "1.7.73",
|
||||
"main": "release/index.js",
|
||||
"jsnext:main": "src/index.js",
|
||||
"author": "Parity Team <admin@parity.io>",
|
||||
|
@ -37,8 +37,8 @@ export default function (api, browserHistory, forEmbed = false) {
|
||||
];
|
||||
|
||||
if (!forEmbed) {
|
||||
const certifications = new CertificationsMiddleware().toMiddleware(api);
|
||||
const registry = new RegistryMiddleware(api);
|
||||
const certifications = new CertificationsMiddleware(api).toMiddleware();
|
||||
const registry = new RegistryMiddleware(api).toMiddleware();
|
||||
|
||||
middleware.push(certifications, registry);
|
||||
}
|
||||
|
@ -241,7 +241,7 @@ export default class Balances {
|
||||
|
||||
// If syncing, only retrieve balances once every
|
||||
// few seconds
|
||||
if (syncing) {
|
||||
if (syncing || syncing === null) {
|
||||
this.shortThrottledFetch.cancel();
|
||||
this.longThrottledFetch(skipNotifications);
|
||||
|
||||
|
@ -58,10 +58,14 @@ const updatableFilter = (api, onFilter) => {
|
||||
};
|
||||
|
||||
export default class CertificationsMiddleware {
|
||||
toMiddleware (api) {
|
||||
const badgeReg = Contracts.get(api).badgeReg;
|
||||
constructor (api) {
|
||||
this._api = api;
|
||||
}
|
||||
|
||||
const contract = new Contract(api, CertifierABI);
|
||||
toMiddleware () {
|
||||
const badgeReg = Contracts.get(this._api).badgeReg;
|
||||
|
||||
const contract = new Contract(this._api, CertifierABI);
|
||||
const Confirmed = contract.events.find((e) => e.name === 'Confirmed');
|
||||
const Revoked = contract.events.find((e) => e.name === 'Revoked');
|
||||
|
||||
@ -73,12 +77,12 @@ export default class CertificationsMiddleware {
|
||||
let badgeRegFilter = null;
|
||||
let fetchCertifiersPromise = null;
|
||||
|
||||
const updateFilter = updatableFilter(api, (filterId) => {
|
||||
const updateFilter = updatableFilter(this._api, (filterId) => {
|
||||
filterChanged = true;
|
||||
filter = filterId;
|
||||
});
|
||||
|
||||
const badgeRegUpdateFilter = updatableFilter(api, (filterId) => {
|
||||
const badgeRegUpdateFilter = updatableFilter(this._api, (filterId) => {
|
||||
filterChanged = true;
|
||||
badgeRegFilter = filterId;
|
||||
});
|
||||
@ -96,7 +100,7 @@ export default class CertificationsMiddleware {
|
||||
.then(() => {
|
||||
shortFetchChanges();
|
||||
|
||||
api.subscribe('eth_blockNumber', (err) => {
|
||||
this._api.subscribe('eth_blockNumber', (err) => {
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
@ -141,12 +145,12 @@ export default class CertificationsMiddleware {
|
||||
|
||||
filterChanged = false;
|
||||
|
||||
api.eth[method](badgeRegFilter)
|
||||
this._api.eth[method](badgeRegFilter)
|
||||
.then(onBadgeRegLogs)
|
||||
.catch((err) => {
|
||||
console.error('Failed to fetch badge reg events:', err);
|
||||
})
|
||||
.then(() => api.eth[method](filter))
|
||||
.then(() => this._api.eth[method](filter))
|
||||
.then(onLogs)
|
||||
.catch((err) => {
|
||||
console.error('Failed to fetch new certifier events:', err);
|
||||
|
@ -15,131 +15,150 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { debounce } from 'lodash';
|
||||
import store from 'store';
|
||||
import lsstore from 'store';
|
||||
|
||||
import Contracts from '@parity/shared/contracts';
|
||||
import registryABI from '@parity/shared/contracts/abi/registry.json';
|
||||
import subscribeToEvents from '@parity/shared/util/subscribe-to-events';
|
||||
import Contracts from '~/shared/contracts';
|
||||
import registryABI from '~/shared/contracts/abi/registry.json';
|
||||
import subscribeToEvents from '~/shared/util/subscribe-to-events';
|
||||
|
||||
import { setReverse } from './actions';
|
||||
import { setReverse, startCachingReverses } from './actions';
|
||||
|
||||
const STORE_KEY = '_parity::reverses';
|
||||
|
||||
const read = (chain) => {
|
||||
const reverses = store.get(`${STORE_KEY}::${chain}::data`);
|
||||
const lastBlock = store.get(`${STORE_KEY}::${chain}::lastBlock`);
|
||||
export default class RegistryMiddleware {
|
||||
contract;
|
||||
interval;
|
||||
store;
|
||||
subscription;
|
||||
timeout;
|
||||
|
||||
if (!reverses || !lastBlock) {
|
||||
return null;
|
||||
addressesToCheck = {};
|
||||
|
||||
constructor (api) {
|
||||
this._api = api;
|
||||
}
|
||||
return { reverses, lastBlock };
|
||||
};
|
||||
|
||||
const write = debounce((getChain, getReverses, getLastBlock) => {
|
||||
const chain = getChain();
|
||||
const reverses = getReverses();
|
||||
const lastBlock = getLastBlock();
|
||||
toMiddleware () {
|
||||
return (store) => {
|
||||
this.store = store;
|
||||
|
||||
store.set(`${STORE_KEY}::${chain}::data`, reverses);
|
||||
store.set(`${STORE_KEY}::${chain}::lastBlock`, lastBlock);
|
||||
}, 20000);
|
||||
return (next) => (action) => {
|
||||
switch (action.type) {
|
||||
case 'initAll':
|
||||
next(action);
|
||||
store.dispatch(startCachingReverses());
|
||||
break;
|
||||
|
||||
export default (api) => (store) => {
|
||||
let contract;
|
||||
let subscription;
|
||||
let timeout;
|
||||
let interval;
|
||||
case 'startCachingReverses':
|
||||
this.cacheReverses();
|
||||
break;
|
||||
|
||||
let addressesToCheck = {};
|
||||
case 'stopCachingReverses':
|
||||
if (this.subscription) {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
if (this.interval) {
|
||||
clearInterval(this.interval);
|
||||
}
|
||||
if (this.timeout) {
|
||||
clearTimeout(this.timeout);
|
||||
}
|
||||
|
||||
const onLog = (log) => {
|
||||
switch (log.event) {
|
||||
case 'ReverseConfirmed':
|
||||
addressesToCheck[log.params.reverse.value] = true;
|
||||
this.write.flush();
|
||||
break;
|
||||
|
||||
break;
|
||||
case 'ReverseRemoved':
|
||||
delete addressesToCheck[log.params.reverse.value];
|
||||
case 'setReverse':
|
||||
this.write(
|
||||
() => store.getState().nodeStatus.netChain,
|
||||
() => store.getState().registry.reverse,
|
||||
() => +store.getState().nodeStatus.blockNumber
|
||||
);
|
||||
next(action);
|
||||
break;
|
||||
|
||||
break;
|
||||
default:
|
||||
next(action);
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
cacheReverses () {
|
||||
const { registry } = Contracts.get();
|
||||
const cached = this.read(this.store.getState().nodeStatus.netChain);
|
||||
|
||||
if (cached) {
|
||||
Object
|
||||
.entries(cached.reverses)
|
||||
.forEach(([ address, reverse ]) => this.store.dispatch(setReverse(address, reverse)));
|
||||
}
|
||||
};
|
||||
|
||||
const checkReverses = () => {
|
||||
registry.getInstance()
|
||||
.then((instance) => this._api.newContract(registryABI, instance.address))
|
||||
.then((_contract) => {
|
||||
this.contract = _contract;
|
||||
|
||||
this.subscription = subscribeToEvents(this.contract, [
|
||||
'ReverseConfirmed', 'ReverseRemoved'
|
||||
], {
|
||||
from: cached ? cached.lastBlock : 0
|
||||
});
|
||||
this.subscription.on('log', this.onLog);
|
||||
|
||||
this.timeout = setTimeout(this.checkReverses, 10000);
|
||||
this.interval = setInterval(this.checkReverses, 20000);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Failed to start caching reverses:', err);
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
checkReverses = () => {
|
||||
Object
|
||||
.keys(addressesToCheck)
|
||||
.keys(this.addressesToCheck)
|
||||
.forEach((address) => {
|
||||
contract
|
||||
this.contract
|
||||
.instance
|
||||
.reverse
|
||||
.call({}, [ address ])
|
||||
.then((reverse) => {
|
||||
store.dispatch(setReverse(address, reverse));
|
||||
this.store.dispatch(setReverse(address, reverse));
|
||||
});
|
||||
});
|
||||
|
||||
addressesToCheck = {};
|
||||
this.addressesToCheck = {};
|
||||
};
|
||||
|
||||
return (next) => (action) => {
|
||||
switch (action.type) {
|
||||
case 'startCachingReverses':
|
||||
const { registry } = Contracts.get(api);
|
||||
const cached = read(store.getState().nodeStatus.netChain);
|
||||
|
||||
if (cached) {
|
||||
Object
|
||||
.entries(cached.reverses)
|
||||
.forEach(([ address, reverse ]) => store.dispatch(setReverse(address, reverse)));
|
||||
}
|
||||
|
||||
registry.getInstance()
|
||||
.then((instance) => api.newContract(registryABI, instance.address))
|
||||
.then((_contract) => {
|
||||
contract = _contract;
|
||||
|
||||
subscription = subscribeToEvents(_contract, [
|
||||
'ReverseConfirmed', 'ReverseRemoved'
|
||||
], {
|
||||
from: cached ? cached.lastBlock : 0
|
||||
});
|
||||
subscription.on('log', onLog);
|
||||
|
||||
timeout = setTimeout(checkReverses, 10000);
|
||||
interval = setInterval(checkReverses, 20000);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Failed to start caching reverses:', err);
|
||||
throw err;
|
||||
});
|
||||
onLog = (log) => {
|
||||
switch (log.event) {
|
||||
case 'ReverseConfirmed':
|
||||
this.addressesToCheck[log.params.reverse.value] = true;
|
||||
|
||||
break;
|
||||
case 'ReverseRemoved':
|
||||
delete this.addressesToCheck[log.params.reverse.value];
|
||||
|
||||
case 'stopCachingReverses':
|
||||
if (subscription) {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
if (interval) {
|
||||
clearInterval(interval);
|
||||
}
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
|
||||
write.flush();
|
||||
break;
|
||||
|
||||
case 'setReverse':
|
||||
write(
|
||||
() => store.getState().nodeStatus.netChain,
|
||||
() => store.getState().registry.reverse,
|
||||
() => +store.getState().nodeStatus.blockNumber
|
||||
);
|
||||
next(action);
|
||||
break;
|
||||
|
||||
default:
|
||||
next(action);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
read = (chain) => {
|
||||
const reverses = lsstore.get(`${STORE_KEY}::${chain}::data`);
|
||||
const lastBlock = lsstore.get(`${STORE_KEY}::${chain}::lastBlock`);
|
||||
|
||||
if (!reverses || !lastBlock) {
|
||||
return null;
|
||||
}
|
||||
return { reverses, lastBlock };
|
||||
};
|
||||
|
||||
write = debounce((getChain, getReverses, getLastBlock) => {
|
||||
const chain = getChain();
|
||||
const reverses = getReverses();
|
||||
const lastBlock = getLastBlock();
|
||||
|
||||
lsstore.set(`${STORE_KEY}::${chain}::data`, reverses);
|
||||
lsstore.set(`${STORE_KEY}::${chain}::lastBlock`, lastBlock);
|
||||
}, 20000);
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ const initialState = {
|
||||
netVersion: '0',
|
||||
nodeKind: null,
|
||||
nodeKindFull: null,
|
||||
syncing: true,
|
||||
syncing: null,
|
||||
isConnected: false,
|
||||
isConnecting: false,
|
||||
isTest: undefined,
|
||||
|
44
js/src/shared/util/messages.js
Normal file
44
js/src/shared/util/messages.js
Normal file
@ -0,0 +1,44 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Convert a String or a FormattedMessage
|
||||
* element into a string
|
||||
*
|
||||
* @param {Object} context - The React `context`
|
||||
* @param {String|Object} value - A String or a FormattedMessage
|
||||
* element
|
||||
* @return {String}
|
||||
*/
|
||||
export function toString (context, value) {
|
||||
if (!context.intl) {
|
||||
console.warn(`remember to add:
|
||||
static contextTypes = {
|
||||
intl: React.PropTypes.object.isRequired
|
||||
};
|
||||
to your component`);
|
||||
return value;
|
||||
}
|
||||
|
||||
const textValue = typeof value !== 'string' && (value && value.props)
|
||||
? context.intl.formatMessage(
|
||||
value.props,
|
||||
value.props.values || {}
|
||||
)
|
||||
: value || '';
|
||||
|
||||
return textValue;
|
||||
}
|
@ -30,11 +30,13 @@ import Snackbar from '../Snackbar';
|
||||
import Status from '../Status';
|
||||
import UpgradeParity from '../UpgradeParity';
|
||||
import UpgradeStore from '../UpgradeParity/store';
|
||||
import SyncWarning, { showSyncWarning } from '../SyncWarning';
|
||||
|
||||
import Store from './store';
|
||||
import styles from './application.css';
|
||||
|
||||
const inFrame = window.parent !== window && window.parent.frames.length !== 0;
|
||||
const doShowSyncWarning = showSyncWarning();
|
||||
|
||||
@observer
|
||||
class Application extends Component {
|
||||
@ -74,6 +76,11 @@ class Application extends Component {
|
||||
? this.renderMinimized()
|
||||
: this.renderApp()
|
||||
}
|
||||
{
|
||||
doShowSyncWarning
|
||||
? <SyncWarning />
|
||||
: null
|
||||
}
|
||||
<Connection />
|
||||
<Requests />
|
||||
<ParityBar dapp={ isMinimized } />
|
||||
|
17
js/src/shell/SyncWarning/index.js
Normal file
17
js/src/shell/SyncWarning/index.js
Normal 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, { showSyncWarning } from './syncWarning';
|
60
js/src/shell/SyncWarning/syncWarning.css
Normal file
60
js/src/shell/SyncWarning/syncWarning.css
Normal file
@ -0,0 +1,60 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
.overlay {
|
||||
background: rgba(255, 255, 255, 0.75);
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 0;
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
.modal {
|
||||
align-items: flex-start;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 0;
|
||||
z-index: 10001;
|
||||
}
|
||||
|
||||
.body {
|
||||
background: rgba(25, 25, 25, 0.75);
|
||||
box-shadow: rgba(0, 0, 0, 0.25) 0 14px 45px, rgba(0, 0, 0, 0.22) 0 10px 18px;
|
||||
color: rgb(208, 208, 208);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0 auto;
|
||||
max-width: 20em;
|
||||
padding: 2em 4em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.button {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.body,
|
||||
.button {
|
||||
> * {
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
}
|
130
js/src/shell/SyncWarning/syncWarning.js
Normal file
130
js/src/shell/SyncWarning/syncWarning.js
Normal file
@ -0,0 +1,130 @@
|
||||
// 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 { Checkbox } from 'material-ui';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { connect } from 'react-redux';
|
||||
import store from 'store';
|
||||
|
||||
import { Button } from '~/ui';
|
||||
|
||||
import styles from './syncWarning.css';
|
||||
|
||||
const LS_DONT_SHOW_AGAIN = '_parity::syncWarning::dontShowAgain';
|
||||
|
||||
export const showSyncWarning = () => {
|
||||
const dontShowAgain = store.get(LS_DONT_SHOW_AGAIN);
|
||||
|
||||
if (dontShowAgain === undefined || dontShowAgain === null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !dontShowAgain;
|
||||
};
|
||||
|
||||
class SyncWarning extends Component {
|
||||
static propTypes = {
|
||||
isSyncing: PropTypes.bool
|
||||
};
|
||||
|
||||
state = {
|
||||
dontShowAgain: false,
|
||||
show: true
|
||||
};
|
||||
|
||||
render () {
|
||||
const { isSyncing } = this.props;
|
||||
const { dontShowAgain, show } = this.state;
|
||||
|
||||
if (!isSyncing || isSyncing === null || !show) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={ styles.overlay } />
|
||||
<div className={ styles.modal }>
|
||||
<div className={ styles.body }>
|
||||
<FormattedMessage
|
||||
id='syncWarning.message.line1'
|
||||
defaultMessage={ `
|
||||
Your Parity node is still syncing to the chain.
|
||||
` }
|
||||
/>
|
||||
<FormattedMessage
|
||||
id='syncWarning.message.line2'
|
||||
defaultMessage={ `
|
||||
Some of the shown information might be out-of-date.
|
||||
` }
|
||||
/>
|
||||
|
||||
<div className={ styles.button }>
|
||||
<Checkbox
|
||||
label={
|
||||
<FormattedMessage
|
||||
id='syncWarning.dontShowAgain.label'
|
||||
defaultMessage='Do not show this warning again'
|
||||
/>
|
||||
}
|
||||
checked={ dontShowAgain }
|
||||
onCheck={ this.handleCheck }
|
||||
/>
|
||||
<Button
|
||||
label={
|
||||
<FormattedMessage
|
||||
id='syncWarning.understandBtn.label'
|
||||
defaultMessage='I understand'
|
||||
/>
|
||||
}
|
||||
onClick={ this.handleAgreeClick }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
handleCheck = () => {
|
||||
this.setState({ dontShowAgain: !this.state.dontShowAgain });
|
||||
}
|
||||
|
||||
handleAgreeClick = () => {
|
||||
if (this.state.dontShowAgain) {
|
||||
store.set(LS_DONT_SHOW_AGAIN, true);
|
||||
}
|
||||
|
||||
this.setState({ show: false });
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps (state) {
|
||||
const { syncing } = state.nodeStatus;
|
||||
// syncing could be an Object, false, or null
|
||||
const isSyncing = syncing
|
||||
? true
|
||||
: syncing;
|
||||
|
||||
return {
|
||||
isSyncing
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
null
|
||||
)(SyncWarning);
|
57
js/src/shell/SyncWarning/syncWarning.spec.js
Normal file
57
js/src/shell/SyncWarning/syncWarning.spec.js
Normal file
@ -0,0 +1,57 @@
|
||||
// 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 { shallow } from 'enzyme';
|
||||
import React from 'react';
|
||||
|
||||
import SyncWarning from './';
|
||||
|
||||
let component;
|
||||
|
||||
function createRedux (syncing = null) {
|
||||
return {
|
||||
getState: () => {
|
||||
return {
|
||||
nodeStatus: {
|
||||
syncing
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function render (store) {
|
||||
component = shallow(
|
||||
<SyncWarning />,
|
||||
{ context: { store: store || createRedux() } }
|
||||
).find('SyncWarning').shallow();
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
describe('shell/SyncWarning', () => {
|
||||
it('renders defaults', () => {
|
||||
expect(render()).to.be.ok;
|
||||
});
|
||||
|
||||
it('does render when syncing', () => {
|
||||
expect(render(createRedux({})).find('div')).to.have.length.gte(1);
|
||||
});
|
||||
|
||||
it('does not render when not syncing', () => {
|
||||
expect(render(createRedux(false)).find('div')).to.have.length(0);
|
||||
});
|
||||
});
|
20
js/src/ui/Button/button.css
Normal file
20
js/src/ui/Button/button.css
Normal file
@ -0,0 +1,20 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
.tooltip {
|
||||
text-transform: uppercase;
|
||||
}
|
@ -24,6 +24,7 @@ import TextFieldUnderline from 'material-ui/TextField/TextFieldUnderline';
|
||||
|
||||
import apiutil from '@parity/api/util';
|
||||
import { nodeOrStringProptype } from '@parity/shared/util/proptypes';
|
||||
import { toString } from '@parity/shared/util/messages';
|
||||
import { validateAddress } from '@parity/shared/util/validation';
|
||||
|
||||
import AccountCard from '~/ui/AccountCard';
|
||||
@ -186,12 +187,7 @@ class AddressSelect extends Component {
|
||||
}
|
||||
|
||||
const id = `addressSelect_${++currentId}`;
|
||||
const ilHint = typeof hint === 'string' || !(hint && hint.props)
|
||||
? (hint || '')
|
||||
: this.context.intl.formatMessage(
|
||||
hint.props,
|
||||
hint.props.values || {}
|
||||
);
|
||||
const ilHint = toString(this.context, hint);
|
||||
|
||||
return (
|
||||
<Portal
|
||||
|
@ -20,6 +20,7 @@ import { noop } from 'lodash';
|
||||
import keycode from 'keycode';
|
||||
|
||||
import { nodeOrStringProptype } from '@parity/shared/util/proptypes';
|
||||
import { toString } from '@parity/shared/util/messages';
|
||||
|
||||
import CopyToClipboard from '~/ui/CopyToClipboard';
|
||||
|
||||
@ -149,12 +150,7 @@ export default class Input extends Component {
|
||||
? UNDERLINE_FOCUSED
|
||||
: readOnly && typeof focused !== 'boolean' ? { display: 'none' } : null;
|
||||
|
||||
const textValue = typeof value !== 'string' && (value && value.props)
|
||||
? this.context.intl.formatMessage(
|
||||
value.props,
|
||||
value.props.values || {}
|
||||
)
|
||||
: value;
|
||||
const textValue = toString(this.context, value);
|
||||
|
||||
return (
|
||||
<div className={ styles.container } style={ style }>
|
||||
|
@ -14,6 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import BigNumber from 'bignumber.js';
|
||||
import moment from 'moment';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
@ -177,10 +178,12 @@ class MethodDecoding extends Component {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (condition.block && condition.block.gt(0)) {
|
||||
const blockCondition = new BigNumber(condition.block || 0);
|
||||
|
||||
if (blockCondition.gt(0)) {
|
||||
const blockNumber = (
|
||||
<span className={ styles.highlight }>
|
||||
#{ condition.block.toFormat(0) }
|
||||
#{ blockCondition.toFormat(0) }
|
||||
</span>
|
||||
);
|
||||
|
||||
|
@ -347,12 +347,13 @@ class ContractDevelop extends Component {
|
||||
}
|
||||
onClick={ this.store.handleCompile }
|
||||
primary={ false }
|
||||
disabled={ compiling }
|
||||
disabled={ compiling || this.store.isPristine }
|
||||
/>
|
||||
{
|
||||
contract
|
||||
? (
|
||||
<Button
|
||||
disabled={ compiling || !this.store.isPristine }
|
||||
icon={ <SendIcon /> }
|
||||
label={
|
||||
<FormattedMessage
|
||||
|
@ -15,7 +15,7 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { debounce } from 'lodash';
|
||||
import { action, observable, transaction } from 'mobx';
|
||||
import { action, computed, observable, transaction } from 'mobx';
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import store from 'store';
|
||||
@ -140,7 +140,7 @@ export default class ContractDevelopStore {
|
||||
this.worker = worker;
|
||||
|
||||
return Promise.all([
|
||||
this.fetchSolidityVersions(),
|
||||
this.fetchSolidityVersions().then(() => this.handleCompile()),
|
||||
this.reloadContracts(undefined, undefined, false)
|
||||
]);
|
||||
}
|
||||
@ -316,6 +316,18 @@ export default class ContractDevelopStore {
|
||||
});
|
||||
}
|
||||
|
||||
@computed get isPristine () {
|
||||
return this.getHash() === this.lastCompilation.hash;
|
||||
}
|
||||
|
||||
getHash () {
|
||||
const build = this.builds[this.selectedBuild];
|
||||
const version = build.longVersion;
|
||||
const sourcecode = this.sourcecode.replace(/\s+/g, ' ');
|
||||
|
||||
return sha3(JSON.stringify({ version, sourcecode, optimize: this.optimize }));
|
||||
}
|
||||
|
||||
@action handleCompile = () => {
|
||||
transaction(() => {
|
||||
this.compiled = false;
|
||||
@ -324,9 +336,7 @@ export default class ContractDevelopStore {
|
||||
});
|
||||
|
||||
const build = this.builds[this.selectedBuild];
|
||||
const version = build.longVersion;
|
||||
const sourcecode = this.sourcecode.replace(/\s+/g, ' ');
|
||||
const hash = sha3(JSON.stringify({ version, sourcecode, optimize: this.optimize }));
|
||||
const hash = this.getHash();
|
||||
|
||||
let promise = Promise.resolve(null);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user