Feature/status pill (#38)
* feat(styles): create status pill component * feat(styles): add status pill icons * feat(status-pill): refactor component logic * feat(status-pill): add component in docz * feat(status-pill): show component on header * feat(status-pill): call RPC to check verification progress * feat(status-pill): add setInterval on getBlockchainStatus function * chore: clean code * feat(status-pill): add ticker to check blockchain info * feat(status-pill): improve component experience * chore(status-pill): refactor component lifecycle * chore(status-pill): increase update time
This commit is contained in:
parent
45fcb6245d
commit
df02b32421
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.6 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
|
@ -6,6 +6,8 @@ import styled from 'styled-components';
|
||||||
import { ZcashLogo } from './zcash-logo';
|
import { ZcashLogo } from './zcash-logo';
|
||||||
import { TextComponent } from './text';
|
import { TextComponent } from './text';
|
||||||
import { Divider } from './divider';
|
import { Divider } from './divider';
|
||||||
|
import { RowComponent } from './row';
|
||||||
|
import { StatusPill } from './status-pill';
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
const Wrapper = styled.div`
|
||||||
height: ${props => props.theme.headerHeight};
|
height: ${props => props.theme.headerHeight};
|
||||||
|
@ -38,6 +40,12 @@ const TitleWrapper = styled.div`
|
||||||
padding-right: ${props => props.theme.layoutPaddingRight};
|
padding-right: ${props => props.theme.layoutPaddingRight};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const TitleRow = styled(RowComponent)`
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
`;
|
||||||
|
|
||||||
const Title = styled(TextComponent)`
|
const Title = styled(TextComponent)`
|
||||||
font-size: ${props => `${props.theme.fontSize.large}em`};
|
font-size: ${props => `${props.theme.fontSize.large}em`};
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
|
@ -57,7 +65,10 @@ export const HeaderComponent = ({ title }: Props) => (
|
||||||
<ZcashLogo />
|
<ZcashLogo />
|
||||||
</LogoWrapper>
|
</LogoWrapper>
|
||||||
<TitleWrapper>
|
<TitleWrapper>
|
||||||
<Title value={title} />
|
<TitleRow alignItems='center' justifyContent='space-around'>
|
||||||
|
<Title value={title} />
|
||||||
|
<StatusPill />
|
||||||
|
</TitleRow>
|
||||||
<Divider opacity={0.1} />
|
<Divider opacity={0.1} />
|
||||||
</TitleWrapper>
|
</TitleWrapper>
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
// @flow
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import styled, { keyframes } from 'styled-components';
|
||||||
|
import eres from 'eres';
|
||||||
|
|
||||||
|
import { TextComponent } from './text';
|
||||||
|
|
||||||
|
import rpc from '../../services/api';
|
||||||
|
|
||||||
|
import readyIcon from '../assets/images/green_check.png';
|
||||||
|
import syncIcon from '../assets/images/sync_icon.png';
|
||||||
|
import errorIcon from '../assets/images/error_icon.png';
|
||||||
|
|
||||||
|
const rotate = keyframes`
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Wrapper = styled.div`
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
background-color: #000;
|
||||||
|
border-radius: 27px;
|
||||||
|
padding: 7px 13px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Icon = styled.img`
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
margin-right: 8px;
|
||||||
|
animation: 2s linear infinite;
|
||||||
|
animation-name: ${props => (props.animated ? rotate : 'none')};
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StatusPillLabel = styled(TextComponent)`
|
||||||
|
color: ${props => props.theme.colors.statusPillLabel};
|
||||||
|
font-weight: ${props => props.theme.fontWeight.bold};
|
||||||
|
text-transform: uppercase;
|
||||||
|
`;
|
||||||
|
|
||||||
|
type Props = {};
|
||||||
|
|
||||||
|
type State = {
|
||||||
|
type: string,
|
||||||
|
icon: string,
|
||||||
|
progress: number,
|
||||||
|
isSynching: boolean,
|
||||||
|
};
|
||||||
|
|
||||||
|
export class StatusPill extends Component<Props, State> {
|
||||||
|
timer: ?IntervalID = null;
|
||||||
|
|
||||||
|
state = {
|
||||||
|
type: 'synching',
|
||||||
|
icon: syncIcon,
|
||||||
|
progress: 0,
|
||||||
|
isSynching: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.timer = setInterval(() => {
|
||||||
|
this.getBlockchainStatus();
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
if (this.timer) {
|
||||||
|
clearInterval(this.timer);
|
||||||
|
this.timer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getBlockchainStatus = async () => {
|
||||||
|
const [blockchainErr, blockchaininfo] = await eres(
|
||||||
|
rpc.getblockchaininfo(),
|
||||||
|
);
|
||||||
|
|
||||||
|
const newProgress = blockchaininfo.verificationprogress * 100;
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
progress: newProgress,
|
||||||
|
...(newProgress > 99.99 ? {
|
||||||
|
type: 'ready',
|
||||||
|
icon: readyIcon,
|
||||||
|
isSynching: false,
|
||||||
|
} : {}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (blockchainErr) {
|
||||||
|
this.setState(() => ({ type: 'error', icon: errorIcon }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
type, icon, progress, isSynching,
|
||||||
|
} = this.state;
|
||||||
|
const showPercent = isSynching ? `(${progress.toFixed(2)}%)` : '';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Wrapper>
|
||||||
|
<Icon src={icon} animated={isSynching} />
|
||||||
|
<StatusPillLabel value={`${type} ${showPercent}`} />
|
||||||
|
</Wrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
---
|
||||||
|
name: StatusPill
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Playground, PropsTable } from 'docz'
|
||||||
|
|
||||||
|
import { StatusPill } from './status-pill.js'
|
||||||
|
import { DoczWrapper } from '../theme.js'
|
||||||
|
|
||||||
|
# StatusPill
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
<PropsTable of={StatusPill} />
|
||||||
|
|
||||||
|
## Basic Usage
|
||||||
|
|
||||||
|
<Playground>
|
||||||
|
<DoczWrapper>
|
||||||
|
{() => <StatusPill percent={83.} />}
|
||||||
|
</DoczWrapper>
|
||||||
|
</Playground>
|
|
@ -24,6 +24,7 @@ const transactionReceived = '#6AEAC0';
|
||||||
const transactionsDate = '#777777';
|
const transactionsDate = '#777777';
|
||||||
const transactionsItemHovered = '#222222';
|
const transactionsItemHovered = '#222222';
|
||||||
const selectButtonShadow = 'rgba(238,201,76,0.65)';
|
const selectButtonShadow = 'rgba(238,201,76,0.65)';
|
||||||
|
const statusPillLabel = '#727272';
|
||||||
const transactionsDetailsLabel = transactionsDate;
|
const transactionsDetailsLabel = transactionsDate;
|
||||||
|
|
||||||
const appTheme = {
|
const appTheme = {
|
||||||
|
@ -68,6 +69,7 @@ const appTheme = {
|
||||||
inputBackground: brandOne,
|
inputBackground: brandOne,
|
||||||
selectButtonShadow,
|
selectButtonShadow,
|
||||||
transactionsDetailsLabel,
|
transactionsDetailsLabel,
|
||||||
|
statusPillLabel,
|
||||||
},
|
},
|
||||||
sidebarWidth: '180px',
|
sidebarWidth: '180px',
|
||||||
headerHeight: '60px',
|
headerHeight: '60px',
|
||||||
|
|
Loading…
Reference in New Issue