This repository has been archived by the owner on Apr 15, 2019. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #495 from LiskHQ/351-forging-tab
Migrate forging component to React - Closes #351
- Loading branch information
Showing
29 changed files
with
730 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import actionTypes from '../constants/actions'; | ||
|
||
export const updateForgedBlocks = data => ({ | ||
data, | ||
type: actionTypes.forgedBlocksUpdated, | ||
}); | ||
|
||
export const updateForgingStats = data => ({ | ||
data, | ||
type: actionTypes.forgingStatsUpdated, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { expect } from 'chai'; | ||
import actionTypes from '../constants/actions'; | ||
import { updateForgedBlocks, updateForgingStats } from './forging'; | ||
|
||
describe('actions', () => { | ||
it('should create an action to update forged blocks', () => { | ||
const data = { | ||
online: true, | ||
}; | ||
|
||
const expectedAction = { | ||
data, | ||
type: actionTypes.forgedBlocksUpdated, | ||
}; | ||
expect(updateForgedBlocks(data)).to.be.deep.equal(expectedAction); | ||
}); | ||
|
||
it('should create an action to update forging stats', () => { | ||
const data = { last7d: 1000 }; | ||
|
||
const expectedAction = { | ||
data, | ||
type: actionTypes.forgingStatsUpdated, | ||
}; | ||
expect(updateForgingStats(data)).to.be.deep.equal(expectedAction); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
:global .CircularProgressbar { | ||
/* | ||
* This fixes an issue where the CircularProgressbar svg has | ||
* 0 width inside a "display: flex" container, and thus not visible. | ||
* | ||
* If you're not using "display: flex", you can remove this style. | ||
*/ | ||
width: 100%; | ||
} | ||
|
||
:global .CircularProgressbar .CircularProgressbar-path { | ||
stroke: rgb(2, 136, 209); | ||
transition: stroke-dashoffset 0.5s ease 0s; | ||
} | ||
|
||
:global .CircularProgressbar .CircularProgressbar-trail { | ||
stroke: #d6d6d6; | ||
} | ||
|
||
:global .CircularProgressbar .CircularProgressbar-text { | ||
font-size: 20px; | ||
dominant-baseline: middle; | ||
text-anchor: middle; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import React from 'react'; | ||
import { Card, CardText } from 'react-toolbox/lib/card'; | ||
import CircularProgressbar from 'react-circular-progressbar'; | ||
import grid from '../../../node_modules/flexboxgrid/dist/flexboxgrid.css'; | ||
import style from './forging.css'; | ||
|
||
const identity = x => (x); | ||
const addPercentSign = x => (`${x}%`); | ||
|
||
const progressCircleCardList = [ | ||
{ | ||
key: 'rate', | ||
label: 'Rank', | ||
percentageTransform: percentage => (Math.max(0, 101 - percentage)), | ||
textForPercentage: identity, | ||
}, { | ||
key: 'productivity', | ||
label: 'Productivity', | ||
percentageTransform: identity, | ||
textForPercentage: addPercentSign, | ||
}, { | ||
key: 'approval', | ||
label: 'Approval', | ||
percentageTransform: identity, | ||
textForPercentage: addPercentSign, | ||
}, | ||
]; | ||
|
||
const DelegateStats = props => ( | ||
<div className={`${grid.row} ${grid['between-xs']}`}> | ||
{progressCircleCardList.map(cardItem => ( | ||
<div className={grid['col-xs-4']} key={cardItem.key}> | ||
<Card className={style.grayCard}> | ||
<CardText> | ||
<div className={grid['col-xs-12']}> | ||
<div className={`${grid.row} ${grid['between-xs']}`}> | ||
<div className={style.circularProgressTitle}> {cardItem.label} </div> | ||
<CircularProgressbar | ||
percentage={cardItem.percentageTransform(props.delegate[cardItem.key])} | ||
textForPercentage={cardItem.textForPercentage.bind(props.delegate[cardItem.key])}/> | ||
</div> | ||
</div> | ||
</CardText> | ||
</Card> | ||
</div> | ||
))} | ||
</div> | ||
); | ||
|
||
export default DelegateStats; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import React from 'react'; | ||
import chai, { expect } from 'chai'; | ||
import sinonChai from 'sinon-chai'; | ||
import { mount } from 'enzyme'; | ||
import DelegateStats from './delegateStats'; | ||
|
||
chai.use(sinonChai); | ||
|
||
describe('DelegateStats', () => { | ||
const delegate = { | ||
username: 'genesis_17', | ||
rate: 19, | ||
approval: 30, | ||
productivity: 99.2, | ||
}; | ||
let wrapper; | ||
|
||
beforeEach(() => { | ||
wrapper = mount(<DelegateStats delegate={delegate} />); | ||
}); | ||
|
||
it('should render 3 Card components', () => { | ||
expect(wrapper.find('Card')).to.have.lengthOf(3); | ||
}); | ||
|
||
it('should render 3 CircularProgressbar components', () => { | ||
expect(wrapper.find('svg.CircularProgressbar')).to.have.lengthOf(3); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import React from 'react'; | ||
import { Card, CardTitle } from 'react-toolbox/lib/card'; | ||
import { Table, TableHead, TableRow, TableCell } from 'react-toolbox/lib/table'; | ||
import { TooltipTime } from '../timestamp'; | ||
import LiskAmount from '../liskAmount'; | ||
import FormattedNumber from '../formattedNumber'; | ||
import grid from '../../../node_modules/flexboxgrid/dist/flexboxgrid.css'; | ||
import style from './forging.css'; | ||
|
||
|
||
const ForgedBlocks = props => ( | ||
<Card className={`${style.grayCard} ${grid['col-xs-12']}`}> | ||
<CardTitle> | ||
Forged Blocks | ||
</CardTitle> | ||
<div className={style.forgedBlocksTableWrapper}> | ||
<Table selectable={false}> | ||
<TableHead> | ||
<TableCell>Block height</TableCell> | ||
<TableCell>Block Id</TableCell> | ||
<TableCell>Timestamp</TableCell> | ||
<TableCell>Total fee</TableCell> | ||
<TableCell>Reward</TableCell> | ||
</TableHead> | ||
{props.forgedBlocks.map((block, idx) => ( | ||
<TableRow key={idx}> | ||
<TableCell><FormattedNumber val={block.height} /></TableCell> | ||
<TableCell>{block.id}</TableCell> | ||
<TableCell><TooltipTime label={block.timestamp} /></TableCell> | ||
<TableCell><LiskAmount val={block.totalFee} /></TableCell> | ||
<TableCell><LiskAmount val={block.reward} /></TableCell> | ||
</TableRow> | ||
))} | ||
</Table> | ||
</div> | ||
</Card> | ||
); | ||
|
||
export default ForgedBlocks; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import React from 'react'; | ||
import chai, { expect } from 'chai'; | ||
import sinonChai from 'sinon-chai'; | ||
import { mount } from 'enzyme'; | ||
import ForgedBlocks from './forgedBlocks'; | ||
|
||
chai.use(sinonChai); | ||
|
||
describe('ForgedBlocks', () => { | ||
const forgedBlocks = [{ | ||
id: '16113150790072764126', | ||
timestamp: 36280810, | ||
height: 29394, | ||
totalFee: 0, | ||
reward: 0, | ||
}, | ||
{ | ||
id: '13838471839278892195', | ||
version: 0, | ||
timestamp: 36280700, | ||
height: 29383, | ||
totalFee: 0, | ||
reward: 0, | ||
}, | ||
{ | ||
id: '5654150596698663763', | ||
version: 0, | ||
timestamp: 36279700, | ||
height: 29283, | ||
totalFee: 0, | ||
reward: 0, | ||
}, | ||
]; | ||
let wrapper; | ||
|
||
beforeEach(() => { | ||
wrapper = mount(<ForgedBlocks forgedBlocks={forgedBlocks} />); | ||
}); | ||
|
||
it('should render 1 Table component', () => { | ||
expect(wrapper.find('Table')).to.have.lengthOf(1); | ||
}); | ||
|
||
it('should render TableHead component with 5 TableCell componenets', () => { | ||
expect(wrapper.find('TableHead')).to.have.lengthOf(1); | ||
expect(wrapper.find('TableHead').find('TableCell')).to.have.lengthOf(5); | ||
}); | ||
|
||
it('should render 3 TableRow components', () => { | ||
expect(wrapper.find('TableRow')).to.have.lengthOf(3); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
@import './circularProgressbar.css'; | ||
|
||
.delegateName { | ||
margin: 0; | ||
font-weight: normal; | ||
} | ||
|
||
.grayCard { | ||
background: #f7f8f9; | ||
} | ||
|
||
.forgedBlocksTableWrapper { | ||
margin: 0 -8px; | ||
} | ||
|
||
.circularProgressTitle { | ||
text-align: center; | ||
padding-bottom: 16px; | ||
width: 100%; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import React from 'react'; | ||
import { Card } from 'react-toolbox/lib/card'; | ||
import Waypoint from 'react-waypoint'; | ||
import { getForgedBlocks, getForgedStats } from '../../utils/api/forging'; | ||
import ForgingTitle from './forgingTitle'; | ||
import DelegateStats from './delegateStats'; | ||
import ForgingStats from './forgingStats'; | ||
import ForgedBlocks from './forgedBlocks'; | ||
|
||
class ForgingComponent extends React.Component { | ||
loadStats(key, startMoment) { | ||
getForgedStats(this.props.peers.data, startMoment, this.props.account.publicKey, | ||
).then((data) => { | ||
this.props.onForgingStatsUpdate({ [key]: data.forged }); | ||
}); | ||
} | ||
|
||
loadForgedBlocks(activePeer, limit, offset, generatorPublicKey) { | ||
getForgedBlocks(activePeer, limit, offset, generatorPublicKey).then((data) => { | ||
this.props.onForgedBlocksLoaded(data.blocks); | ||
}); | ||
} | ||
|
||
render() { | ||
return ( | ||
<Card style={{ padding: 8 }}> | ||
{this.props.account && this.props.account.isDelegate ? | ||
<div> | ||
<ForgingTitle account={this.props.account} statistics={this.props.statistics} | ||
loadStats={this.loadStats.bind(this)} /> | ||
<br /> | ||
<ForgingStats account={this.props.account} statistics={this.props.statistics} | ||
loadStats={this.loadStats.bind(this)} /> | ||
<br /> | ||
<DelegateStats delegate={this.props.account.delegate} /> | ||
<br /> | ||
<ForgedBlocks forgedBlocks={this.props.forgedBlocks} /> | ||
<Waypoint onEnter={() => this.loadForgedBlocks( | ||
this.props.peers.data, | ||
20, | ||
this.props.forgedBlocks.length, | ||
this.props.account.publicKey, | ||
) } /> | ||
</div> : | ||
null | ||
} | ||
{this.props.account && this.props.account.delegate && !this.props.account.isDelegate ? | ||
<p> | ||
You need to become a delegate to start forging. | ||
If you already registered to become a delegate, | ||
your registration hasn't been processed, yet. | ||
</p> : | ||
null | ||
} | ||
</Card> | ||
); | ||
} | ||
} | ||
|
||
export default ForgingComponent; |
Oops, something went wrong.