From 7d0780d723ca27b89eca49f6dfd602517d78143a Mon Sep 17 00:00:00 2001 From: Amaury Martiny Date: Wed, 6 Dec 2017 10:44:50 +0100 Subject: [PATCH] Make Signing Requests more visible (#7204) * Add a signerPending component with popup * Add text when no requests * Remove lock icon * Fix lint * Create separate component from RequestItem * Render different types of transaction * Remove blue View button * Remove useless code --- .../SignerPending/EtherValue/etherValue.js | 39 ++++ .../Status/SignerPending/EtherValue/index.js | 17 ++ .../Status/SignerPending/RequestItem/index.js | 17 ++ .../SignerPending/RequestItem/requestItem.css | 24 +++ .../SignerPending/RequestItem/requestItem.js | 188 ++++++++++++++++++ js/src/Status/SignerPending/index.js | 17 ++ js/src/Status/SignerPending/signerPending.css | 30 +++ js/src/Status/SignerPending/signerPending.js | 128 ++++++++++++ js/src/Status/SignerPending/store.js | 50 +++++ js/src/Status/status.css | 4 - js/src/Status/status.js | 10 +- 11 files changed, 513 insertions(+), 11 deletions(-) create mode 100644 js/src/Status/SignerPending/EtherValue/etherValue.js create mode 100644 js/src/Status/SignerPending/EtherValue/index.js create mode 100644 js/src/Status/SignerPending/RequestItem/index.js create mode 100644 js/src/Status/SignerPending/RequestItem/requestItem.css create mode 100644 js/src/Status/SignerPending/RequestItem/requestItem.js create mode 100644 js/src/Status/SignerPending/index.js create mode 100644 js/src/Status/SignerPending/signerPending.css create mode 100644 js/src/Status/SignerPending/signerPending.js create mode 100644 js/src/Status/SignerPending/store.js diff --git a/js/src/Status/SignerPending/EtherValue/etherValue.js b/js/src/Status/SignerPending/EtherValue/etherValue.js new file mode 100644 index 000000000..bc5b79c90 --- /dev/null +++ b/js/src/Status/SignerPending/EtherValue/etherValue.js @@ -0,0 +1,39 @@ +// 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'; + +const EtherValue = ({ value }, { api }) => { + const ether = api.util.fromWei(value); + + return ( + + {ether.toFormat(5)} + ETH + + ); +}; + +EtherValue.propTypes = { + value: PropTypes.object.isRequired +}; + +EtherValue.contextTypes = { + api: PropTypes.object.isRequired +}; + +export default EtherValue; diff --git a/js/src/Status/SignerPending/EtherValue/index.js b/js/src/Status/SignerPending/EtherValue/index.js new file mode 100644 index 000000000..eb8fcffa8 --- /dev/null +++ b/js/src/Status/SignerPending/EtherValue/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 './etherValue'; diff --git a/js/src/Status/SignerPending/RequestItem/index.js b/js/src/Status/SignerPending/RequestItem/index.js new file mode 100644 index 000000000..c6a73a370 --- /dev/null +++ b/js/src/Status/SignerPending/RequestItem/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 './requestItem'; diff --git a/js/src/Status/SignerPending/RequestItem/requestItem.css b/js/src/Status/SignerPending/RequestItem/requestItem.css new file mode 100644 index 000000000..5d1a2e9b6 --- /dev/null +++ b/js/src/Status/SignerPending/RequestItem/requestItem.css @@ -0,0 +1,24 @@ +/* Copyright 2015-2017 Parity Technologies (UK) Ltd. +/* This file is part of Parity. +/* +/* Parity is free software: you can redistribute it and/or modify +/* it under the terms of the GNU General Public License as published by +/* the Free Software Foundation, either version 3 of the License, or +/* (at your option) any later version. +/* +/* Parity is distributed in the hope that it will be useful, +/* but WITHOUT ANY WARRANTY; without even the implied warranty of +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +/* GNU General Public License for more details. +/* +/* You should have received a copy of the GNU General Public License +/* along with Parity. If not, see . +*/ + +.listDescription { + display: flex !important; +} + +.toAvatar { + margin-left: 3px; +} diff --git a/js/src/Status/SignerPending/RequestItem/requestItem.js b/js/src/Status/SignerPending/RequestItem/requestItem.js new file mode 100644 index 000000000..13cddea0f --- /dev/null +++ b/js/src/Status/SignerPending/RequestItem/requestItem.js @@ -0,0 +1,188 @@ +// 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 { connect } from 'react-redux'; +import { observer } from 'mobx-react'; +import PropTypes from 'prop-types'; +import { FormattedMessage } from 'react-intl'; + +import MethodDecodingStore from '@parity/ui/lib/MethodDecoding/methodDecodingStore'; +import { TOKEN_METHODS } from '@parity/ui/lib/MethodDecoding/constants'; +import TokenValue from '@parity/ui/lib/MethodDecoding/tokenValue'; +import IdentityIcon from '@parity/ui/lib/IdentityIcon'; +import Image from 'semantic-ui-react/dist/commonjs/elements/Image'; +import List from 'semantic-ui-react/dist/commonjs/elements/List'; + +import EtherValue from '../EtherValue'; +import styles from './requestItem.css'; + +@observer +@connect(({ tokens }, { transaction }) => ({ + token: Object.values(tokens).find(({ address }) => address === transaction.to) +})) +class RequestItem extends Component { + static propTypes = { + onClick: PropTypes.func.isRequired, + transaction: PropTypes.object.isRequired, + token: PropTypes.object + }; + + static contextTypes = { + api: PropTypes.object.isRequired + }; + + state = { + decoded: null // Decoded transaction + }; + + methodDecodingStore = MethodDecodingStore.get(this.context.api); + + componentWillMount () { + const { transaction } = this.props; + + // Decode the transaction and put it into the state + this.methodDecodingStore + .lookup(transaction.from, transaction) + .then(lookup => this.setState({ + decoded: lookup + })); + } + + renderDescription = () => { + // Decide what to display in the description, depending + // on what type of transaction we're dealing with + const { token } = this.props; + const { + inputs, + signature, + contract, + deploy + } = this.state.decoded; + + if (deploy) { + return this.renderDeploy(); + } + + if (contract && signature) { + if (token && TOKEN_METHODS[signature] && inputs) { + return this.renderTokenTransfer(); + } + return this.renderContractMethod(); + } + + return this.renderValueTransfer(); + } + + renderDeploy = () => { + return ( + + ); + }; + + renderContractMethod = () => { + const { transaction } = this.props; + + return ( + + + {this.renderRecipient(transaction.to)} + + ); + }; + + renderTokenTransfer = () => { + const { token } = this.props; + const { inputs } = this.state.decoded; + const valueInput = inputs.find(({ name }) => name === '_value'); + const toInput = inputs.find(({ name }) => name === '_to'); + + return ( + + + ) + } + } + /> + {this.renderRecipient(toInput.value)} + + ); + }; + + renderValueTransfer = () => { + const { transaction } = this.props; + + return ( + + + } + } + /> + {this.renderRecipient(transaction.to)} + + ); + }; + + renderRecipient = address => ( + + ); + + render () { + const { transaction, onClick } = this.props; + + if (!this.state.decoded) { return null; } + + return ( + + + + + + + + + {this.renderDescription()} + + + ); + } +} + +export default RequestItem; diff --git a/js/src/Status/SignerPending/index.js b/js/src/Status/SignerPending/index.js new file mode 100644 index 000000000..b172c419a --- /dev/null +++ b/js/src/Status/SignerPending/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 './signerPending'; diff --git a/js/src/Status/SignerPending/signerPending.css b/js/src/Status/SignerPending/signerPending.css new file mode 100644 index 000000000..3fcc9ae7d --- /dev/null +++ b/js/src/Status/SignerPending/signerPending.css @@ -0,0 +1,30 @@ +/* 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 . +*/ + +.signerPending { + margin-top: 4px !important; + position: relative; + cursor: pointer; +} + +.label { + font-size: 0.65rem !important; +} + +.noRequest { + min-width: 280px; +} diff --git a/js/src/Status/SignerPending/signerPending.js b/js/src/Status/SignerPending/signerPending.js new file mode 100644 index 000000000..7c8283f40 --- /dev/null +++ b/js/src/Status/SignerPending/signerPending.js @@ -0,0 +1,128 @@ +// 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 { observer } from 'mobx-react'; +import PropTypes from 'prop-types'; +import { FormattedMessage } from 'react-intl'; + +import Container from 'semantic-ui-react/dist/commonjs/elements/Container'; +import Header from 'semantic-ui-react/dist/commonjs/elements/Header'; +import Icon from 'semantic-ui-react/dist/commonjs/elements/Icon'; +import Label from 'semantic-ui-react/dist/commonjs/elements/Label'; +import List from 'semantic-ui-react/dist/commonjs/elements/List'; +import Popup from 'semantic-ui-react/dist/commonjs/modules/Popup'; + +import Store from './store'; +import ParityBarStore from '../../ParityBar/store'; +import RequestItem from './RequestItem'; +import styles from './signerPending.css'; + +@observer +class SignerPending extends Component { + static propTypes = {}; + + static contextTypes = { + api: PropTypes.object.isRequired + }; + + state = { + isOpen: false + }; + + store = Store.get(this.context.api); + parityBarStore = ParityBarStore.get(); + + handleRequestClick = () => { + this.parityBarStore.toggleOpenSigner(); + this.handleClose(); + }; + + handleOpen = () => { + this.setState({ isOpen: true }); + }; + + handleClose = () => { + this.setState({ isOpen: false }); + }; + + renderPopupContent = () => ( +
+
+ +
+ {this.store.pending.length > 0 + ? ( + + {this.store.pending.map(request => ( + + ))} + + ) : ( + + + + ) + } +
+ ); + + render () { + return ( + + 0 ? 'bell' : 'bell outline' } + /> + {this.store.pending.length > 0 && ( + + )} + + } + content={ this.renderPopupContent() } + offset={ 8 } // Empirically looks better + on='click' + hideOnScroll + open={ this.state.isOpen } + onClose={ this.handleClose } + onOpen={ this.handleOpen } + position='bottom right' + /> + ); + } +} + +export default SignerPending; diff --git a/js/src/Status/SignerPending/store.js b/js/src/Status/SignerPending/store.js new file mode 100644 index 000000000..c2dad5351 --- /dev/null +++ b/js/src/Status/SignerPending/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'; + +let instance; + +export default class Store { + @observable pending = []; + + constructor (api) { + this._api = api; + this.startSubscription(); + } + + @action setPending = (pending = []) => { + this.pending = pending; + } + + startSubscription () { + this._api.subscribe('signer_requestsToConfirm', (error, pending) => { + if (error) { + return; + } + + this.setPending(pending); + }); + } + + static get (api) { + if (!instance) { + instance = new Store(api); + } + + return instance; + } +} diff --git a/js/src/Status/status.css b/js/src/Status/status.css index e38792f9e..110d2f3c8 100644 --- a/js/src/Status/status.css +++ b/js/src/Status/status.css @@ -75,10 +75,6 @@ $textColor: #ccc; opacity: 0.75; } - .signerPending { - cursor: pointer; - } - .health { > span { margin: -0.5rem 0 0.2rem 0 !important; diff --git a/js/src/Status/status.js b/js/src/Status/status.js index 24513304b..947a09739 100644 --- a/js/src/Status/status.js +++ b/js/src/Status/status.js @@ -25,21 +25,19 @@ import GradientBg from '@parity/ui/lib/GradientBg'; import { HomeIcon } from '@parity/ui/lib/Icons'; import NetChain from '@parity/ui/lib/NetChain'; import NetPeers from '@parity/ui/lib/NetPeers'; -import SignerPending from '@parity/ui/lib/SignerPending'; import StatusIndicator from '@parity/ui/lib/StatusIndicator'; import Consensus from './Consensus'; import DefaultAccount from './DefaultAccount'; import AccountStore from '../ParityBar/accountStore'; -import ParityBarStore from '../ParityBar/store'; import SyncWarning from '../SyncWarning'; import PluginStore from './pluginStore'; +import SignerPending from './SignerPending'; import Upgrade from './Upgrade'; import styles from './status.css'; const pluginStore = PluginStore.get(); -const parityBarStore = ParityBarStore.get(); function Status ({ className = '', upgradeStore }, { api }) { const accountStore = AccountStore.get(api); @@ -63,10 +61,6 @@ function Status ({ className = '', upgradeStore }, { api }) { )) }
- + +