diff --git a/js/packages/api/api.js b/js/packages/api/api.js index a911e21ee..af03ca0e2 100644 --- a/js/packages/api/api.js +++ b/js/packages/api/api.js @@ -17,8 +17,8 @@ import EventEmitter from 'eventemitter3'; import Contract from './contract'; -import { PromiseProvider, Http as HttpProvider, PostMessage as PostMessageProvider, Ws as WsProvider } from './provider'; -import { Http as HttpTransport, Ws as WsTransport } from './transport'; +import { PromiseProvider, Http as HttpProvider, PostMessage as PostMessageProvider, Ws as WsProvider, WsSecure as WsSecureProvider } from './provider'; +import { Http as HttpTransport, Ws as WsTransport, WsSecure as WsSecureTransport } from './transport'; import { Db, Eth, Parity, Net, Personal, Shell, Shh, Signer, Trace, Web3 } from './rpc'; import Subscriptions from './subscriptions'; @@ -74,10 +74,17 @@ export default class Api extends EventEmitter { } } + get isConnected () { + const isConnected = this.provider.isConnected; + + return isConnected || typeof isConnected === 'undefined'; + } + get pubsub () { if (!this._pubsub) { throw Error('Pubsub is only available with a subscribing-supported transport injected!'); } + return this._pubsub; } @@ -186,12 +193,14 @@ export default class Api extends EventEmitter { static Provider = { Http: HttpProvider, PostMessage: PostMessageProvider, - Ws: WsProvider + Ws: WsProvider, + WsSecure: WsSecureProvider } // NOTE: kept for backwards compatibility static Transport = { Http: HttpTransport, - Ws: WsTransport + Ws: WsTransport, + WsSecure: WsSecureTransport } } diff --git a/js/packages/api/provider/index.js b/js/packages/api/provider/index.js index 06de8cd70..67a2af856 100644 --- a/js/packages/api/provider/index.js +++ b/js/packages/api/provider/index.js @@ -14,8 +14,15 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -export PromiseProvider from './promise'; +import Ws from './ws'; export Http from './http'; export PostMessage from './postMessage'; -export Ws from './ws'; +export PromiseProvider from './promise'; + +const WsSecure = Ws; + +export { + Ws, + WsSecure +}; diff --git a/js/packages/api/provider/postMessage.js b/js/packages/api/provider/postMessage.js index 86d2d031f..56f37e991 100644 --- a/js/packages/api/provider/postMessage.js +++ b/js/packages/api/provider/postMessage.js @@ -46,7 +46,7 @@ export default class PostMessage { } subscribe = (api, callback, params) => { - console.log('paritySubscribe', JSON.stringify(params), api, callback); + // console.log('paritySubscribe', JSON.stringify(params), api, callback); return new Promise((resolve, reject) => { const id = ++this.id; @@ -89,8 +89,10 @@ export default class PostMessage { } if (this._messages[id].subscription) { - console.log('subscription', result, 'initial?', this._messages[id].initial); - this._messages[id].initial ? this._messages[id].resolve(result) : this._messages[id].callback(error && new Error(error), result); + // console.log('subscription', result, 'initial?', this._messages[id].initial); + this._messages[id].initial + ? this._messages[id].resolve(result) + : this._messages[id].callback(error && new Error(error), result); this._messages[id].initial = false; } else { this._messages[id].callback(error && new Error(error), result); diff --git a/js/packages/api/transport/index.js b/js/packages/api/transport/index.js index fdd3861a8..896cf5c5f 100644 --- a/js/packages/api/transport/index.js +++ b/js/packages/api/transport/index.js @@ -14,7 +14,15 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +import Ws from './ws'; + export Http from './http'; -export Ws from './ws'; export TransportError from './error'; export Middleware from './middleware'; + +const WsSecure = Ws; + +export { + Ws, + WsSecure +}; diff --git a/js/packages/dapp-status/Node/node.js b/js/packages/dapp-status/Node/node.js index a297e636c..67d3550af 100644 --- a/js/packages/dapp-status/Node/node.js +++ b/js/packages/dapp-status/Node/node.js @@ -15,51 +15,29 @@ // along with Parity. If not, see . import bytes from 'bytes'; -import moment from 'moment'; import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { FormattedMessage } from 'react-intl'; -import { connect } from 'react-redux'; +import { observer } from 'mobx-react'; -import { Container, ContainerTitle, Input } from '@parity/ui'; +import { BlockNumber, BlockTimestamp, Container, ContainerTitle, Input, NetPeers } from '@parity/ui'; import MiningSettings from '../MiningSettings'; import StatusStore from './store'; import styles from './node.css'; -class Node extends Component { +@observer +export default class Node extends Component { static contextTypes = { api: PropTypes.object.isRequired }; - static propTypes = { - blockNumber: PropTypes.object, - blockTimestamp: PropTypes.object, - netChain: PropTypes.string, - netPeers: PropTypes.object - }; - statusStore = new StatusStore(this.context.api); - componentWillMount () { - this.statusStore.startPolling(); - } - - componentWillUnmount () { - this.statusStore.stopPolling(); - } - render () { - const { blockNumber, blockTimestamp, netPeers } = this.props; const { hashrate } = this.statusStore; - - if (!netPeers || !blockNumber) { - return null; - } - const hashrateValue = bytes(hashrate.toNumber()) || 0; - const peers = `${netPeers.active}/${netPeers.connected}/${netPeers.max}`; return ( @@ -76,10 +54,10 @@ class Node extends Component { } />
- #{ blockNumber.toFormat() } + #
- { moment(blockTimestamp).calendar() } +
@@ -92,7 +70,7 @@ class Node extends Component { } />
- { peers } +
@@ -158,7 +136,6 @@ class Node extends Component { } renderSettings () { - const { netChain } = this.props; const { enode, rpcSettings, netPort = '' } = this.statusStore; if (!rpcSettings) { @@ -186,7 +163,7 @@ class Node extends Component { defaultMessage='chain' /> } - value={ netChain } + value={ this.statusStore.netChain } />
@@ -279,24 +256,3 @@ class Node extends Component { ); } } - -function mapStateToProps (state) { - const { - blockNumber, - blockTimestamp, - netChain, - netPeers - } = state.nodeStatus; - - return { - blockNumber, - blockTimestamp, - netChain, - netPeers - }; -} - -export default connect( - mapStateToProps, - null -)(Node); diff --git a/js/packages/dapp-status/Node/store.js b/js/packages/dapp-status/Node/store.js index 22fe20070..44d6a5fd9 100644 --- a/js/packages/dapp-status/Node/store.js +++ b/js/packages/dapp-status/Node/store.js @@ -15,7 +15,11 @@ // along with Parity. If not, see . import BigNumber from 'bignumber.js'; -import { action, observable, transaction } from 'mobx'; +import { action, computed, observable, transaction } from 'mobx'; + +import { NetChain } from '@parity/ui'; + +console.log('NetChain', NetChain, NetChain.Store); export default class StatusStore { @observable defaultExtraData = ''; @@ -35,6 +39,13 @@ export default class StatusStore { constructor (api) { this.api = api; + this.chainStore = NetChain.Store.get(api); + + this.startPolling(); + } + + @computed get netChain () { + return this.chainStore.netChain; } @action setLongStatus ({ defaultExtraData, enode, netPort, rpcSettings }) { diff --git a/js/packages/dapp-status/status.js b/js/packages/dapp-status/status.js index cf37ef043..8c3b001f7 100644 --- a/js/packages/dapp-status/status.js +++ b/js/packages/dapp-status/status.js @@ -26,6 +26,8 @@ import Peers from './Peers'; import styles from './status.css'; +console.log('Node', Node); + export default function Status () { return ( { - const status = { netPeers, syncing, health }; - - health.overall = this._overallStatus(health); - health.peers = health.peers || {}; - health.sync = health.sync || {}; - health.time = health.time || {}; + .then(([ syncing, netPeers ]) => { + const status = { netPeers, syncing }; if (!isEqual(status, this._status)) { this._store.dispatch(statusCollection(status)); @@ -234,43 +224,6 @@ export default class Status { }); } - _overallStatus = (health) => { - const all = [health.peers, health.sync, health.time].filter(x => x); - const statuses = all.map(x => x.status); - const bad = statuses.find(x => x === STATUS_BAD); - const needsAttention = statuses.find(x => x === STATUS_WARN); - const message = all.map(x => x.message).filter(x => x); - - if (all.length) { - return { - status: bad || needsAttention || STATUS_OK, - message - }; - } - - return { - status: STATUS_BAD, - message: ['Unable to fetch node health.'] - }; - } - - _fetchHealth = () => { - // Support Parity-Extension. - const uiUrl = this._api.transport.uiUrlWithProtocol || ''; - - return fetch(`${uiUrl}/api/health`) - .then((response) => { - if (!response.ok) { - return {}; - } - - return response.json(); - }) - .catch(() => { - return {}; - }); - } - /** * The data fetched here should not change * unless Parity is restarted. They are thus diff --git a/js/packages/ui/BlockNumber/blockNumber.css b/js/packages/ui/BlockNumber/blockNumber.css new file mode 100644 index 000000000..4cf6aaf4a --- /dev/null +++ b/js/packages/ui/BlockNumber/blockNumber.css @@ -0,0 +1,21 @@ +/* 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 . +*/ + +.blockNumber, +.syncStatus { + display: inline-block; +} diff --git a/js/packages/ui/BlockStatus/blockStatus.js b/js/packages/ui/BlockNumber/blockNumber.js similarity index 59% rename from js/packages/ui/BlockStatus/blockStatus.js rename to js/packages/ui/BlockNumber/blockNumber.js index 9df0c6961..f2b17dc6b 100644 --- a/js/packages/ui/BlockStatus/blockStatus.js +++ b/js/packages/ui/BlockNumber/blockNumber.js @@ -15,39 +15,37 @@ // along with Parity. If not, see . import React from 'react'; -import PropTypes from 'prop-types'; import { FormattedMessage } from 'react-intl'; -import { connect } from 'react-redux'; +import PropTypes from 'prop-types'; +import { observer } from 'mobx-react'; -import styles from './blockStatus.css'; +import Store from './store'; -function BlockStatus ({ blockNumber, syncing }) { - if (!blockNumber) { +import styles from './blockNumber.css'; + +function BlockNumber ({ className, message }, { api }) { + const store = Store.get(api); + + if (!store.blockNumber) { return null; } - if (!syncing) { + if (!store.syncing) { return ( -
- +
+ { store.blockNumber.toFormat() }{ message }
); } - if (syncing.warpChunksAmount && syncing.warpChunksProcessed && !syncing.warpChunksAmount.eq(syncing.warpChunksProcessed)) { + if (store.syncing.warpChunksAmount && store.syncing.warpChunksProcessed && !store.syncing.warpChunksAmount.eq(store.syncing.warpChunksProcessed)) { return (
@@ -57,23 +55,23 @@ function BlockStatus ({ blockNumber, syncing }) { let syncStatus = null; let warpStatus = null; - if (syncing.currentBlock && syncing.highestBlock) { + if (store.syncing.currentBlock && store.syncing.highestBlock) { syncStatus = ( ); } - if (syncing.blockGap) { - const [first, last] = syncing.blockGap; + if (store.syncing.blockGap) { + const [first, last] = store.syncing.blockGap; warpStatus = ( @@ -96,24 +94,17 @@ function BlockStatus ({ blockNumber, syncing }) { ); } -BlockStatus.propTypes = { - blockNumber: PropTypes.object, - syncing: PropTypes.oneOfType([ - PropTypes.bool, - PropTypes.object - ]) +BlockNumber.propTypes = { + className: PropTypes.string, + message: PropTypes.node }; -function mapStateToProps (state) { - const { blockNumber, syncing } = state.nodeStatus; +BlockNumber.contextTypes = { + api: PropTypes.object.isRequired +}; - return { - blockNumber, - syncing - }; -} +const ObserverComponent = observer(BlockNumber); -export default connect( - mapStateToProps, - null -)(BlockStatus); +ObserverComponent.Store = Store; + +export default ObserverComponent; diff --git a/js/packages/ui/BlockStatus/index.js b/js/packages/ui/BlockNumber/index.js similarity index 95% rename from js/packages/ui/BlockStatus/index.js rename to js/packages/ui/BlockNumber/index.js index 904ad512d..f44b433b5 100644 --- a/js/packages/ui/BlockStatus/index.js +++ b/js/packages/ui/BlockNumber/index.js @@ -14,4 +14,4 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -export default from './blockStatus'; +export default from './blockNumber'; diff --git a/js/packages/ui/BlockNumber/store.js b/js/packages/ui/BlockNumber/store.js new file mode 100644 index 000000000..a3dd6bfbd --- /dev/null +++ b/js/packages/ui/BlockNumber/store.js @@ -0,0 +1,79 @@ +// 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 . + +import { action, observable } from 'mobx'; + +export default class Store { + @observable blockNumber = null; + @observable blockTimestamp = null; + @observable syncing = null; + + constructor (api) { + this._api = api; + this._api.on('connected', this.setupSubscriptions, this); + + // Connected and/or events NOT available + if (this._api.isConnected) { + this.setupSubscriptions(); + } + } + + setupSubscriptions = () => { + this._api.pubsub.eth.syncing((error, syncing) => { + if (!error) { + this.setSyncing(syncing); + } + }); + + this._api.pubsub.eth.blockNumber((error, blockNumber) => { + if (!error) { + this.setBlockNumber(blockNumber); + } + + this._api.parity + .getBlockHeaderByNumber(blockNumber) + .then((block) => { + if (!block) { + return; + } + + this.setBlockTimestamp(block.timestamp); + }); + }); + } + + @action setBlockNumber = (blockNumber) => { + this.blockNumber = blockNumber; + } + + @action setBlockTimestamp = (blockTimestamp) => { + this.blockTimestamp = blockTimestamp; + } + + @action setSyncing = (syncing) => { + this.syncing = syncing; + } + + static instance = null; + + static get (api) { + if (!Store.instance) { + Store.instance = new Store(api); + } + + return Store.instance; + } +} diff --git a/js/packages/ui/BlockStatus/blockStatus.spec.js b/js/packages/ui/BlockStatus/blockStatus.spec.js deleted file mode 100644 index 277c286c5..000000000 --- a/js/packages/ui/BlockStatus/blockStatus.spec.js +++ /dev/null @@ -1,94 +0,0 @@ -// 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 . - -import BigNumber from 'bignumber.js'; -import { shallow } from 'enzyme'; -import React from 'react'; -import sinon from 'sinon'; - -import BlockStatus from './'; - -let component; - -function createRedux (syncing = false, blockNumber = new BigNumber(123)) { - return { - dispatch: sinon.stub(), - subscribe: sinon.stub(), - getState: () => { - return { - nodeStatus: { - blockNumber, - syncing - } - }; - } - }; -} - -function render (reduxStore = createRedux(), props) { - component = shallow( - , - { context: { store: reduxStore } } - ).find('BlockStatus').shallow(); - - return component; -} - -describe('ui/BlockStatus', () => { - it('renders defaults', () => { - expect(render()).to.be.ok; - }); - - it('renders null with no blockNumber', () => { - expect(render(createRedux(false, null)).find('div')).to.have.length(0); - }); - - it('renders only the best block when syncing === false', () => { - const messages = render().find('FormattedMessage'); - - expect(messages).to.have.length(1); - expect(messages).to.have.id('ui.blockStatus.bestBlock'); - }); - - it('renders only the warp restore status when restoring', () => { - const messages = render(createRedux({ - warpChunksAmount: new BigNumber(100), - warpChunksProcessed: new BigNumber(5) - })).find('FormattedMessage'); - - expect(messages).to.have.length(1); - expect(messages).to.have.id('ui.blockStatus.warpRestore'); - }); - - it('renders the current/highest when syncing', () => { - const messages = render(createRedux({ - currentBlock: new BigNumber(123), - highestBlock: new BigNumber(456) - })).find('FormattedMessage'); - - expect(messages).to.have.length(1); - expect(messages).to.have.id('ui.blockStatus.syncStatus'); - }); - - it('renders warp blockGap when catching up', () => { - const messages = render(createRedux({ - blockGap: [new BigNumber(123), new BigNumber(456)] - })).find('FormattedMessage'); - - expect(messages).to.have.length(1); - expect(messages).to.have.id('ui.blockStatus.warpStatus'); - }); -}); diff --git a/js/packages/ui/BlockTimestamp/blockTimestamp.css b/js/packages/ui/BlockTimestamp/blockTimestamp.css new file mode 100644 index 000000000..84a3f7354 --- /dev/null +++ b/js/packages/ui/BlockTimestamp/blockTimestamp.css @@ -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 . +*/ + +.blockTimestamp { + display: inline-block; +} diff --git a/js/packages/ui/BlockTimestamp/blockTimestamp.js b/js/packages/ui/BlockTimestamp/blockTimestamp.js new file mode 100644 index 000000000..d63467f72 --- /dev/null +++ b/js/packages/ui/BlockTimestamp/blockTimestamp.js @@ -0,0 +1,52 @@ +// 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 . + +import React from 'react'; +import PropTypes from 'prop-types'; +import { observer } from 'mobx-react'; +import moment from 'moment'; + +import Store from '../BlockNumber/store'; + +import styles from './blockTimestamp.css'; + +function BlockTimestamp ({ className }, { api }) { + const store = Store.get(api); + + if (!store.blockTimestamp) { + return null; + } + + return ( +
+ { moment(store.blockTimestamp).calendar() } +
+ ); +} + +BlockTimestamp.propTypes = { + className: PropTypes.string +}; + +BlockTimestamp.contextTypes = { + api: PropTypes.object.isRequired +}; + +const ObserverComponent = observer(BlockTimestamp); + +ObserverComponent.Store = Store; + +export default ObserverComponent; diff --git a/js/packages/ui/BlockTimestamp/index.js b/js/packages/ui/BlockTimestamp/index.js new file mode 100644 index 000000000..0a14293ad --- /dev/null +++ b/js/packages/ui/BlockTimestamp/index.js @@ -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 . + +export default from './blockTimestamp'; diff --git a/js/packages/ui/ClientVersion/clientVersion.css b/js/packages/ui/ClientVersion/clientVersion.css new file mode 100644 index 000000000..3a9d1c224 --- /dev/null +++ b/js/packages/ui/ClientVersion/clientVersion.css @@ -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 . +*/ + +.clientVersion { + display: inline-block; +} diff --git a/js/packages/ui/ClientVersion/clientVersion.js b/js/packages/ui/ClientVersion/clientVersion.js new file mode 100644 index 000000000..c40d3135f --- /dev/null +++ b/js/packages/ui/ClientVersion/clientVersion.js @@ -0,0 +1,52 @@ +// 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 . + +import React from 'react'; +import PropTypes from 'prop-types'; +import { observer } from 'mobx-react'; + +import Store from './store'; + +import styles from './clientVersion.css'; + +function ClientVersion ({ className }, { api }) { + const store = Store.get(api); + + if (!store.clientVersion) { + return null; + } + + const [ clientName, , versionString, , ] = store.clientVersion.split('/'); + const [ versionNumber, versionType, , versionDate ] = (versionString || '').split('-'); + + return ( +
+ { clientName } { versionNumber }-{ versionDate } { versionType } +
+ ); +} + +ClientVersion.propTypes = { + className: PropTypes.string +}; + +ClientVersion.contextTypes = { + api: PropTypes.object.isRequired +}; + +ClientVersion.Store = Store; + +export default observer(ClientVersion); diff --git a/js/packages/ui/ClientVersion/index.js b/js/packages/ui/ClientVersion/index.js new file mode 100644 index 000000000..8003639fa --- /dev/null +++ b/js/packages/ui/ClientVersion/index.js @@ -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 . + +export default from './clientVersion'; diff --git a/js/packages/ui/ClientVersion/store.js b/js/packages/ui/ClientVersion/store.js new file mode 100644 index 000000000..3d2044c59 --- /dev/null +++ b/js/packages/ui/ClientVersion/store.js @@ -0,0 +1,50 @@ +// 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 . + +import { action, observable } from 'mobx'; + +export default class Store { + @observable clientVersion = ''; + + constructor (api) { + this._api = api; + this._api.on('connected', this.setupSubscriptions, this); + + if (this._api.isConnected) { + this.setupSubscriptions(); + } + } + + setupSubscriptions = () => { + this._api.web3 + .clientVersion() + .then(this.setClientVersion); + } + + @action setClientVersion = (clientVersion) => { + this.clientVersion = clientVersion; + } + + static instance = null; + + static get (api) { + if (!Store.instance) { + Store.instance = new Store(api); + } + + return Store.instance; + } +} diff --git a/js/packages/ui/CurrencySymbol/currencySymbol.js b/js/packages/ui/CurrencySymbol/currencySymbol.js index 8698d070c..7fc4d7739 100644 --- a/js/packages/ui/CurrencySymbol/currencySymbol.js +++ b/js/packages/ui/CurrencySymbol/currencySymbol.js @@ -14,53 +14,45 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import React, { Component } from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; +import { observer } from 'mobx-react'; + +import Store from '../NetChain/store'; const SYMBOL_ETC = 'ETC'; const SYMBOL_ETH = 'ETH'; const SYMBOL_EXP = 'EXP'; -export class CurrencySymbol extends Component { - static propTypes = { - className: PropTypes.string, - netChain: PropTypes.string.isRequired - } +function renderSymbol (netChain) { + switch (netChain) { + case 'classic': + return SYMBOL_ETC; - render () { - const { className } = this.props; + case 'expanse': + return SYMBOL_EXP; - return ( - { this.renderSymbol() } - ); - } - - renderSymbol () { - const { netChain } = this.props; - - switch (netChain) { - case 'classic': - return SYMBOL_ETC; - - case 'expanse': - return SYMBOL_EXP; - - default: - return SYMBOL_ETH; - } + default: + return SYMBOL_ETH; } } -function mapStateToProps (state) { - const { netChain } = state.nodeStatus; +function CurrencySymbol ({ className }, { api }) { + const store = Store.get(api); - return { - netChain - }; + return ( + + { renderSymbol(store.netChain) } + + ); } -export default connect( - mapStateToProps, - null -)(CurrencySymbol); +CurrencySymbol.propTypes = { + className: PropTypes.string +}; + +CurrencySymbol.contextTypes = { + api: PropTypes.object.isRequired +}; + +export default observer(CurrencySymbol); diff --git a/js/packages/ui/CurrencySymbol/currencySymbol.spec.js b/js/packages/ui/CurrencySymbol/currencySymbol.spec.js deleted file mode 100644 index e705b5edc..000000000 --- a/js/packages/ui/CurrencySymbol/currencySymbol.spec.js +++ /dev/null @@ -1,99 +0,0 @@ -// 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 . - -import { shallow } from 'enzyme'; -import React from 'react'; -import sinon from 'sinon'; - -import CurrencySymbol from './'; - -let component; -let store; - -function createRedux (netChain = 'ropsten') { - store = { - dispatch: sinon.stub(), - subscribe: sinon.stub(), - getState: () => { - return { - nodeStatus: { - netChain - } - }; - } - }; - - return store; -} - -function render (netChain, props = {}) { - component = shallow( - , - { - context: { - store: createRedux(netChain) - } - } - ).find('CurrencySymbol').shallow(); - - return component; -} - -describe('ui/CurrencySymbol', () => { - it('renders defaults', () => { - expect(render()).to.be.ok; - }); - - it('passes the className as provided', () => { - expect(render('ropsten', { className: 'test' }).find('span').hasClass('test')).to.be.true; - }); - - describe('currencies', () => { - it('renders ETH as default', () => { - expect(render().text()).equal('ETH'); - }); - - it('renders ETC for classic', () => { - expect(render('classic').text()).equal('ETC'); - }); - - it('renders EXP for expanse', () => { - expect(render('expanse').text()).equal('EXP'); - }); - - it('renders ETH as default', () => { - expect(render('somethingElse').text()).equal('ETH'); - }); - }); - - describe('renderSymbol', () => { - it('render defaults', () => { - expect(render().instance().renderSymbol()).to.be.ok; - }); - - it('render ETH as default', () => { - expect(render().instance().renderSymbol()).equal('ETH'); - }); - - it('render ETC', () => { - expect(render('classic').instance().renderSymbol()).equal('ETC'); - }); - - it('render EXP', () => { - expect(render('expanse').instance().renderSymbol()).equal('EXP'); - }); - }); -}); diff --git a/js/packages/ui/NetChain/index.js b/js/packages/ui/NetChain/index.js new file mode 100644 index 000000000..31b62d1db --- /dev/null +++ b/js/packages/ui/NetChain/index.js @@ -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 . + +export default from './netChain'; diff --git a/js/packages/ui/NetChain/netChain.css b/js/packages/ui/NetChain/netChain.css new file mode 100644 index 000000000..8bca8f20c --- /dev/null +++ b/js/packages/ui/NetChain/netChain.css @@ -0,0 +1,34 @@ +/* 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 . +*/ + +$networkLiveColor: rgb(0, 136, 0); +$networkTestColor: rgb(136, 0, 0); + +.chain { + border-radius: 0.4em; + line-height: 1.2; + padding: 0.25em 0.5em; + text-transform: uppercase; + + &.live { + background: $networkLiveColor; + } + + &.test { + background: $networkTestColor; + } +} diff --git a/js/packages/ui/NetChain/netChain.js b/js/packages/ui/NetChain/netChain.js new file mode 100644 index 000000000..7e1bc715a --- /dev/null +++ b/js/packages/ui/NetChain/netChain.js @@ -0,0 +1,47 @@ +// 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 . + +import React from 'react'; +import PropTypes from 'prop-types'; +import { observer } from 'mobx-react'; + +import Store from './store'; + +import styles from './netChain.css'; + +function NetChain ({ className }, { api }) { + const store = Store.get(api); + + return ( +
+ { store.netChain } +
+ ); +} + +NetChain.propTypes = { + className: PropTypes.string +}; + +NetChain.contextTypes = { + api: PropTypes.object.isRequired +}; + +const ObserverComponent = observer(NetChain); + +ObserverComponent.Store = Store; + +export default ObserverComponent; diff --git a/js/src/Status/store.js b/js/packages/ui/NetChain/store.js similarity index 76% rename from js/src/Status/store.js rename to js/packages/ui/NetChain/store.js index b81862442..9f3318e35 100644 --- a/js/src/Status/store.js +++ b/js/packages/ui/NetChain/store.js @@ -19,9 +19,7 @@ import { action, computed, observable } from 'mobx'; import { isTestnet } from '@parity/shared/util/testnet'; export default class Store { - @observable clientVersion = ''; @observable netChain = ''; - @observable netPeers = {}; @observable netVersion = 1; constructor (api) { @@ -38,39 +36,21 @@ export default class Store { if (!error) { this.setNetChain(netChain); } + + this._api.net + .version() + .then(this.setNetVersion); }); - - this._api.pubsub.parity.netPeers((error, netPeers) => { - if (!error) { - this.setNetPeers(netPeers); - } - }); - - this._api.net - .version() - .then(this.setNetVersion); - - this._api.web3 - .clientVersion() - .then(this.setClientVersion); } @computed get isTest () { return isTestnet(this.netVersion); } - @action setClientVersion = (clientVersion) => { - this.clientVersion = clientVersion; - } - @action setNetChain = (netChain) => { this.netChain = netChain; } - @action setNetPeers = (netPeers) => { - this.netPeers = netPeers; - } - @action setNetVersion = (netVersion) => { this.netVersion = netVersion; } diff --git a/js/packages/ui/NetPeers/index.js b/js/packages/ui/NetPeers/index.js new file mode 100644 index 000000000..6111a2f93 --- /dev/null +++ b/js/packages/ui/NetPeers/index.js @@ -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 . + +export default from './netPeers'; diff --git a/js/packages/ui/BlockStatus/blockStatus.css b/js/packages/ui/NetPeers/netPeers.css similarity index 95% rename from js/packages/ui/BlockStatus/blockStatus.css rename to js/packages/ui/NetPeers/netPeers.css index d5e8a655d..aa5b47699 100644 --- a/js/packages/ui/BlockStatus/blockStatus.css +++ b/js/packages/ui/NetPeers/netPeers.css @@ -15,8 +15,6 @@ /* along with Parity. If not, see . */ -.blockNumber { -} - -.syncStatus { +.peers { + display: inline-block; } diff --git a/js/packages/ui/NetPeers/netPeers.js b/js/packages/ui/NetPeers/netPeers.js new file mode 100644 index 000000000..ca81a575c --- /dev/null +++ b/js/packages/ui/NetPeers/netPeers.js @@ -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 . + +import React from 'react'; +import PropTypes from 'prop-types'; +import { observer } from 'mobx-react'; + +import Store from './store'; + +import styles from './netPeers.css'; + +function NetPeers ({ className, message }, { api }) { + const store = Store.get(api); + + if (!store.netPeers) { + return null; + } + + const { max, connected } = store.netPeers; + + return ( +
+ { connected ? connected.toFormat() : '0' }/{ max ? max.toFormat() : '0' }{ message } +
+ ); +} + +NetPeers.propTypes = { + className: PropTypes.string, + message: PropTypes.node +}; + +NetPeers.contextTypes = { + api: PropTypes.object.isRequired +}; + +const ObserverComponent = observer(NetPeers); + +ObserverComponent.Store = Store; + +export default ObserverComponent; diff --git a/js/packages/ui/NetPeers/store.js b/js/packages/ui/NetPeers/store.js new file mode 100644 index 000000000..0f270f9ba --- /dev/null +++ b/js/packages/ui/NetPeers/store.js @@ -0,0 +1,52 @@ +// 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 . + +import { action, observable } from 'mobx'; + +export default class Store { + @observable netPeers = {}; + + constructor (api) { + this._api = api; + this._api.on('connected', this.setupSubscriptions, this); + + if (this._api.isConnected) { + this.setupSubscriptions(); + } + } + + setupSubscriptions = () => { + this._api.pubsub.parity.netPeers((error, netPeers) => { + if (!error) { + this.setNetPeers(netPeers); + } + }); + } + + @action setNetPeers = (netPeers) => { + this.netPeers = netPeers; + } + + static instance = null; + + static get (api) { + if (!Store.instance) { + Store.instance = new Store(api); + } + + return Store.instance; + } +} diff --git a/js/packages/ui/StatusIndicator/statusIndicator.css b/js/packages/ui/StatusIndicator/statusIndicator.css index 2d96f0391..3d075c37a 100644 --- a/js/packages/ui/StatusIndicator/statusIndicator.css +++ b/js/packages/ui/StatusIndicator/statusIndicator.css @@ -68,10 +68,12 @@ height: .4em; border-right: 0; } + &.needsAttention { height: .6em; border-right: 0; } + &.ok { height: 1em; } @@ -80,9 +82,11 @@ &.bad > .bar.active { background-color: #c00; } + &.ok > .bar.active { background-color: #080; } + &.needsAttention > .bar.active { background-color: #dc0; } diff --git a/js/packages/ui/StatusIndicator/statusIndicator.js b/js/packages/ui/StatusIndicator/statusIndicator.js index 860f2deb5..c34640b75 100644 --- a/js/packages/ui/StatusIndicator/statusIndicator.js +++ b/js/packages/ui/StatusIndicator/statusIndicator.js @@ -14,58 +14,86 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import React, { Component } from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; import ReactTooltip from 'react-tooltip'; +import { observer } from 'mobx-react'; + +import Store from './store'; import styles from './statusIndicator.css'; const statuses = ['bad', 'needsAttention', 'ok']; -export default class StatusIndicator extends Component { - static propTypes = { - type: PropTypes.oneOf(['radial', 'signal']), - id: PropTypes.string.isRequired, - status: PropTypes.oneOf(statuses).isRequired, - title: PropTypes.arrayOf(PropTypes.node), - tooltipPlacement: PropTypes.oneOf(['left', 'top', 'bottom', 'right']) - }; +function StatusIndicator ({ id, status, title = [], tooltipPlacement, type = 'signal' }, { api }) { + const store = Store.get(api); + const checkStatus = status || store.overall.status; + const message = title.length + ? title + : store.overall.message; - static defaultProps = { - type: 'signal', - title: [] - }; + return ( + + + { + type === 'signal' + ? statuses.map((signal) => { + const index = statuses.indexOf(checkStatus); + const isActive = statuses.indexOf(signal) <= index; - render () { - const { id, status, title, type, tooltipPlacement } = this.props; - const tooltip = title.find(x => !x.isEmpty) ? ( - - { title.map(x => (
{ x }
)) } -
- ) : null; - - return ( - - - { type === 'signal' && statuses.map(this.renderBar) } - - {tooltip} + return ( + + ); + }) + : null + } - ); - } - - renderBar = (signal) => { - const idx = statuses.indexOf(this.props.status); - const isActive = statuses.indexOf(signal) <= idx; - const activeClass = isActive ? styles.active : ''; - - return ( - - ); - } + { + message.find((x) => !x.isEmpty) + ? ( + + { + message.map((x) => ( +
+ { x } +
) + ) + } +
+ ) + : null + } +
+ ); } + +StatusIndicator.propTypes = { + type: PropTypes.oneOf([ + 'radial', 'signal' + ]), + id: PropTypes.string.isRequired, + status: PropTypes.oneOf(statuses), + title: PropTypes.arrayOf(PropTypes.node), + tooltipPlacement: PropTypes.oneOf([ + 'left', 'top', 'bottom', 'right' + ]) +}; + +StatusIndicator.contextTypes = { + api: PropTypes.object.isRequired +}; + +const ObserverComponent = observer(StatusIndicator); + +ObserverComponent.Store = Store; + +export default ObserverComponent; diff --git a/js/packages/ui/StatusIndicator/store.js b/js/packages/ui/StatusIndicator/store.js new file mode 100644 index 000000000..c32e68c3d --- /dev/null +++ b/js/packages/ui/StatusIndicator/store.js @@ -0,0 +1,106 @@ +// 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 . + +import { action, computed, observable } from 'mobx'; + +const STATUS_OK = 'ok'; +const STATUS_WARN = 'needsAttention'; +const STATUS_BAD = 'bad'; +const EMPTY_OVERALL = { message: [], status: STATUS_BAD }; + +export default class Store { + @observable _health = null; + + constructor (api) { + this._api = api; + + setInterval(this.fetchHealth, 2500); + } + + @computed get health () { + return this._health + ? this._health + : {}; + } + + @computed get overall () { + return this._health + ? this._health.overall + : EMPTY_OVERALL; + } + + fetchHealth = () => { + // Support Parity-Extension. + const uiUrl = this._api.transport.uiUrlWithProtocol || ''; + + return fetch(`${uiUrl}/api/health`) + .then((response) => { + if (!response.ok) { + return null; + } + + return response.json(); + }) + .catch(() => { + return null; + }) + .then(this.setHealth); + } + + _overallStatus = (health) => { + const all = [health.peers, health.sync, health.time].filter(x => x); + const statuses = all.map(x => x.status); + const bad = statuses.find(x => x === STATUS_BAD); + const needsAttention = statuses.find(x => x === STATUS_WARN); + const message = all.map(x => x.message).filter(x => x); + + if (all.length) { + return { + status: bad || needsAttention || STATUS_OK, + message + }; + } + + return { + status: STATUS_BAD, + message: ['Unable to fetch node health.'] + }; + } + + @action setHealth = (health) => { + if (!health) { + this._health = null; + return; + } + + health.peers = health.peers || {}; + health.sync = health.sync || {}; + health.time = health.time || {}; + health.overall = this._overallStatus(health); + + this._health = health; + } + + static instance = null; + + static get (api) { + if (!Store.instance) { + Store.instance = new Store(api); + } + + return Store.instance; + } +} diff --git a/js/packages/ui/index.js b/js/packages/ui/index.js index de8b2d03e..54ec9f521 100644 --- a/js/packages/ui/index.js +++ b/js/packages/ui/index.js @@ -20,9 +20,11 @@ export AccountCard from './AccountCard'; export Actionbar, { Export as ActionbarExport, Import as ActionbarImport, Search as ActionbarSearch, Sort as ActionbarSort } from './Actionbar'; export Badge from './Badge'; export Balance from './Balance'; -export BlockStatus from './BlockStatus'; +export BlockNumber from './BlockNumber'; +export BlockTimestamp from './BlockTimestamp'; export Button from './Button'; export Certifications from './Certifications'; +export ClientVersion from './ClientVersion'; export ConfirmDialog from './ConfirmDialog'; export Container, { Title as ContainerTitle } from './Container'; export ContextProvider from './ContextProvider'; @@ -46,6 +48,8 @@ export Loading from './Loading'; export MethodDecoding from './MethodDecoding'; export { Busy as BusyStep, Completed as CompletedStep } from './Modal'; export ModalBox from './ModalBox'; +export NetChain from './NetChain'; +export NetPeers from './NetPeers'; export Page from './Page'; export Popup from './Popup'; export Portal from './Portal'; diff --git a/js/src/Application.orig/Status/status.js b/js/src/Application.orig/Status/status.js deleted file mode 100644 index ae112170e..000000000 --- a/js/src/Application.orig/Status/status.js +++ /dev/null @@ -1,155 +0,0 @@ -// 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 . - -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { FormattedMessage } from 'react-intl'; -import { connect } from 'react-redux'; - -import { BlockStatus, StatusIndicator } from '@parity/ui'; - -import styles from './status.css'; - -class Status extends Component { - static propTypes = { - clientVersion: PropTypes.string, - isTest: PropTypes.bool, - netChain: PropTypes.string, - netPeers: PropTypes.object, - health: PropTypes.object, - upgradeStore: PropTypes.object.isRequired - } - - render () { - const { clientVersion, isTest, netChain, netPeers, health } = this.props; - - return ( -
-
- { clientVersion } -
-
- { this.renderConsensus() } - { this.renderUpgradeButton() } -
-
-
- -
- - - -
- { netChain } -
-
-
- ); - } - - renderConsensus () { - const { upgradeStore } = this.props; - - if (!upgradeStore || !upgradeStore.consensusCapability) { - return null; - } - - if (upgradeStore.consensusCapability === 'capable') { - return ( -
- -
- ); - } - - if (upgradeStore.consensusCapability.capableUntil) { - return ( -
- -
- ); - } - - if (upgradeStore.consensusCapability.incapableSince) { - return ( -
- -
- ); - } - - return; - } - - renderUpgradeButton () { - const { upgradeStore } = this.props; - - if (!upgradeStore.available) { - return null; - } - - return ( -
- - - -
- ); - } -} - -function mapStateToProps (state) { - const { clientVersion, health, netPeers, netChain, isTest } = state.nodeStatus; - - return { - clientVersion, - health, - netPeers, - netChain, - isTest - }; -} - -export default connect( - mapStateToProps, - null -)(Status); diff --git a/js/src/Application.orig/TabBar/tabBar.css b/js/src/Application.orig/TabBar/tabBar.css deleted file mode 100644 index fa8478f8b..000000000 --- a/js/src/Application.orig/TabBar/tabBar.css +++ /dev/null @@ -1,100 +0,0 @@ -/* 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 . -*/ - -.toolbar { - background: none !important; - height: 72px !important; - position: relative; -} - -.tabs { - width: 100%; - position: relative; - display: flex; - - & > * { - flex: 1; - } -} - -.tabLink { - display: flex; - - > * { - flex: 1; - } - - &:hover { - background: rgba(0, 0, 0, 0.4) !important; - } - - &.tabactive, &.tabactive:hover { - background: rgba(0, 0, 0, 0.25) !important; - border-radius: 4px 4px 0 0; - - * { - color: white !important; - } - } -} - -.tabLink, -.settings, -.first, -.last { - background: rgba(0, 0, 0, 0.5) !important; /* rgba(0, 0, 0, 0.25) !important; */ -} - -.tabbarTooltip { - left: 3em; - top: 4em; -} - -.label { - position: relative; -} - -.labelBubble { - position: absolute; - top: -12px; - right: -12px; -} - -.first, -.last { - margin: 0; - padding: 36px 12px; - white-space: nowrap; -} - -.indicatorTab { - font-size: 1.5rem; - flex: 0; -} - -.indicator { - padding: 20px 12px 0; - opacity: 0.8; -} - -.first { - margin-left: -24px; -} - -.last { - margin-right: -24px; -} diff --git a/js/src/Application.orig/TabBar/tabBar.js b/js/src/Application.orig/TabBar/tabBar.js deleted file mode 100644 index 6caeb0c8a..000000000 --- a/js/src/Application.orig/TabBar/tabBar.js +++ /dev/null @@ -1,153 +0,0 @@ -// 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 . - -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { FormattedMessage } from 'react-intl'; -import { connect } from 'react-redux'; -import { Link } from 'react-router'; -import { Toolbar, ToolbarGroup } from 'material-ui/Toolbar'; -import { isEqual } from 'lodash'; - -import { Tooltip, StatusIndicator } from '@parity/ui'; - -import Tab from './Tab'; -import styles from './tabBar.css'; - -class TabBar extends Component { - static contextTypes = { - router: PropTypes.object.isRequired - }; - - static propTypes = { - pending: PropTypes.array, - health: PropTypes.object.isRequired, - views: PropTypes.array.isRequired - }; - - static defaultProps = { - pending: [] - }; - - render () { - const { health } = this.props; - - return ( - - -
- -
- -
- -
- - { this.renderTabItems() } - - } - /> -
- -
- - - ); - } - - renderTabItems () { - const { views, pending } = this.props; - - return views.map((view, index) => { - return ( - - - - ); - }); - } -} - -function mapStateToProps (initState) { - const { views } = initState.settings; - - let filteredViewIds = Object - .keys(views) - .filter((id) => views[id].fixed || views[id].active); - - let filteredViews = filteredViewIds.map((id) => ({ - ...views[id], - id - })); - - return (state) => { - const { availability = 'unknown' } = state.nodeStatus.nodeKind || {}; - const { views } = state.settings; - const { health } = state.nodeStatus; - - const viewIds = Object - .keys(views) - .filter((id) => { - const view = views[id]; - - const isEnabled = view.fixed || view.active; - const isAllowed = !view.onlyPersonal || availability === 'personal'; - - return isEnabled && isAllowed; - }); - - if (isEqual(viewIds, filteredViewIds)) { - return { views: filteredViews, health }; - } - - filteredViewIds = viewIds; - filteredViews = viewIds.map((id) => ({ - ...views[id], - id - })); - - return { views: filteredViews, health }; - }; -} - -export default connect( - mapStateToProps, - null -)(TabBar); diff --git a/js/src/ParityBar/parityBar.js b/js/src/ParityBar/parityBar.js index 15eff549a..2aaee166f 100644 --- a/js/src/ParityBar/parityBar.js +++ b/js/src/ParityBar/parityBar.js @@ -53,8 +53,7 @@ class ParityBar extends Component { static propTypes = { dapp: PropTypes.bool, externalLink: PropTypes.string, - pending: PropTypes.array, - health: PropTypes.object + pending: PropTypes.array }; state = { @@ -214,7 +213,7 @@ class ParityBar extends Component { } renderBar () { - const { dapp, health } = this.props; + const { dapp } = this.props; if (!dapp) { return null; @@ -223,10 +222,7 @@ class ParityBar extends Component { return (