Commit 370d9e10 authored by Kenny Tran's avatar Kenny Tran Committed by Chi Kei Chan

Pending transactions modal (#67)

* Create pending transactions modal

* Add pending icon
parent 9db88515
<svg width="13" height="12" viewBox="0 0 13 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12.1603 6C10.7795 8.39146 7.72159 9.21084 5.33013 7.83013C2.93866 6.44942 2.11929 3.39146 3.5 1" stroke="#2F80ED" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
import React from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { drizzleConnect } from 'drizzle-react' import { drizzleConnect } from 'drizzle-react'
import classnames from 'classnames'; import classnames from 'classnames';
import Web3 from 'web3'; import Web3 from 'web3';
import Jazzicon from 'jazzicon'; import Jazzicon from 'jazzicon';
import { CSSTransitionGroup } from "react-transition-group";
import './web3-status.scss'; import './web3-status.scss';
import Pending from '../../assets/images/pending.svg';
import Modal from '../Modal';
function Web3Status(props) { function getEtherscanLink(tx) {
const { address } = props; return `https://etherscan.io/tx/${tx}`;
}
return ( class Web3Status extends Component {
<div state = {
className={classnames("web3-status", { isShowingModal: false,
'web3-status__connected': props.isConnected, };
})}
> handleClick = () => {
if (this.props.hasPendingTransactions && !this.state.isShowingModal) {
this.setState({isShowingModal: true});
}
}
renderPendingTransactions() {
return this.props.pendingTransactions.map((transaction) => {
return (
<div
key={transaction}
className={classnames('pending-modal__transaction-row')}
onClick={() => window.open(getEtherscanLink(transaction), '_blank')}
>
<div className="pending-modal__transaction-label">
{transaction}
</div>
<div className="pending-modal__pending-indicator">
<img src={Pending} />
Pending
</div>
</div>
);
});
}
renderModal() {
if (!this.state.isShowingModal) {
return null;
}
return (
<Modal onClose={() => this.setState({ isShowingModal: false })}>
<CSSTransitionGroup
transitionName="token-modal"
transitionAppear={true}
transitionLeave={true}
transitionAppearTimeout={200}
transitionLeaveTimeout={200}
transitionEnterTimeout={200}
>
<div className="pending-modal">
<div className="pending-modal__transaction-list">
<div className="pending-modal__header">Transactions</div>
{this.renderPendingTransactions()}
</div>
</div>
</CSSTransitionGroup>
</Modal>
);
}
render() {
const { address, transactions, pendingTransactions, hasPendingTransactions } = this.props;
console.count('hi');
let text = getText(address);
if (hasPendingTransactions) {
text = getPendingText(pendingTransactions);
}
return (
<div <div
className="web3-status__identicon" className={classnames("web3-status", {
ref={el => { 'web3-status__connected': this.props.isConnected,
if (!el) { })}
return; onClick={this.handleClick}
} >
<div
className="web3-status__identicon"
ref={el => {
if (!el) {
return;
}
if (!address|| address.length < 42 || !Web3.utils.isHexStrict(address)) { if (!address|| address.length < 42 || !Web3.utils.isHexStrict(address)) {
return; return;
} }
el.innerHTML = ''; el.innerHTML = '';
el.appendChild(Jazzicon(18, parseInt(address.slice(2), 16))); el.appendChild(Jazzicon(18, parseInt(address.slice(2), 16)));
}} }}
/> />
<div className="web3-status__text"> <div className="web3-status__text">
{ getText(props.address) } {
hasPendingTransactions ?
getPendingText(pendingTransactions) :
getText(address)
}
</div>
{this.renderModal()}
</div> </div>
);
}
}
function getPendingText(pendingTransactions) {
return (
<div className="web3-status__pending-container">
<img key="icon" src={Pending} />
<span key="text">{pendingTransactions.length} Pending</span>
</div> </div>
) );
} }
function getText(text) { function getText(text) {
...@@ -43,7 +130,6 @@ function getText(text) { ...@@ -43,7 +130,6 @@ function getText(text) {
} }
const address = Web3.utils.toChecksumAddress(text); const address = Web3.utils.toChecksumAddress(text);
return `${address.substring(0, 6)}...${address.substring(38)}`; return `${address.substring(0, 6)}...${address.substring(38)}`;
} }
...@@ -59,8 +145,19 @@ Web3Status.defaultProps = { ...@@ -59,8 +145,19 @@ Web3Status.defaultProps = {
export default drizzleConnect( export default drizzleConnect(
Web3Status, Web3Status,
state => ({ state => {
address: state.accounts[0], const pendingTransactions = [];
isConnected: !!(state.drizzleStatus.initialized && state.accounts[0]), Object.keys(state.transactions).forEach((transaction) => {
}) if (state.transactions[transaction] && state.transactions[transaction].status === 'pending') {
pendingTransactions.push(transaction);
}
});
return {
address: state.accounts[0],
isConnected: !!(state.drizzleStatus.initialized && state.accounts[0]),
pendingTransactions,
hasPendingTransactions: pendingTransactions.length > 0,
};
}
); );
...@@ -28,4 +28,74 @@ ...@@ -28,4 +28,74 @@
margin-left: 1rem; margin-left: 1rem;
font-size: .85rem; font-size: .85rem;
} }
}
\ No newline at end of file &__pending-container {
display: flex;
justify-content: space-around;
}
}
.pending-modal {
background-color: $white;
position: relative;
bottom: 12rem;
height: 12rem;
width: 100%;
z-index: 2000;
border-top-left-radius: 1rem;
border-top-right-radius: 1rem;
transition: 250ms ease-in-out;
&__transaction-list {
height: 12rem;
overflow-y: auto;
}
&__transaction-row {
@extend %row-nowrap;
box-sizing: border-box;
align-items: center;
padding: 0.25rem 1.5rem;
justify-content: space-between;
cursor: pointer;
width: 100%;
user-select: none;
}
&__transaction-label {
color: $royal-blue;
width: 60%;
overflow: hidden;
text-overflow: ellipsis;
font-weight: 200;
}
&__pending-indicator {
color: $royal-blue;
border: 1px solid $zumthor-blue;
padding: 10px;
border-radius: 100px;
& > img {
margin-right: 10px;
}
}
&__header {
font-size: 1rem;
color: $dove-gray;
padding: 1rem 1.5rem 0.25rem 1.5rem;
}
}
.pending-modal-appear {
bottom: 0;
}
.pending-modal-appear.modal-container-appear-active {
bottom: 0;
}
...@@ -28,5 +28,6 @@ html, body { ...@@ -28,5 +28,6 @@ html, body {
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
right: 0;
z-index: 200; z-index: 200;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment