UI 2 Status dapp fixes (#5531)

* Stateless components

* Adjust borders

* Stateless for status
This commit is contained in:
Jaco Greeff 2017-05-02 11:14:18 +02:00 committed by GitHub
parent 4781d2e15a
commit fa243cdf89
25 changed files with 646 additions and 360 deletions

View File

@ -0,0 +1,45 @@
// 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 <http://www.gnu.org/licenses/>.
import React from 'react';
import { nodeOrStringProptype } from '~/util/proptypes';
import styles from '../title.css';
export default function Byline ({ byline }) {
if (!byline) {
return null;
}
return (
<div className={ styles.byline }>
{
typeof byline === 'string'
? (
<span title={ byline }>
{ byline }
</span>
)
: byline
}
</div>
);
}
Byline.propTypes = {
byline: nodeOrStringProptype()
};

View File

@ -14,4 +14,4 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
export default from './nodeStatus';
export default from './byline';

View File

@ -0,0 +1,45 @@
// 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 <http://www.gnu.org/licenses/>.
import React from 'react';
import { nodeOrStringProptype } from '~/util/proptypes';
import styles from '../title.css';
export default function Description ({ description }) {
if (!description) {
return null;
}
return (
<div className={ styles.description }>
{
typeof description === 'string'
? (
<span title={ description }>
{ description }
</span>
)
: description
}
</div>
);
}
Description.propTypes = {
description: nodeOrStringProptype()
};

View File

@ -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 <http://www.gnu.org/licenses/>.
export default from './description';

View File

@ -14,75 +14,30 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import React, { Component, PropTypes } from 'react';
import React, { PropTypes } from 'react';
import { nodeOrStringProptype } from '~/util/proptypes';
import Byline from './Byline';
import Description from './Description';
import styles from './title.css';
export default class Title extends Component {
static propTypes = {
byline: nodeOrStringProptype(),
className: PropTypes.string,
description: nodeOrStringProptype(),
title: nodeOrStringProptype()
}
render () {
const { className, title } = this.props;
return (
<div className={ className }>
<h3 className={ styles.title }>
{ title }
</h3>
{ this.renderByline() }
{ this.renderDescription() }
</div>
);
}
renderByline () {
const { byline } = this.props;
if (!byline) {
return null;
}
return (
<div className={ styles.byline }>
{
typeof byline === 'string'
? (
<span title={ byline }>
{ byline }
</span>
)
: byline
}
</div>
);
}
renderDescription () {
const { description } = this.props;
if (!description) {
return null;
}
return (
<div className={ styles.description }>
{
typeof description === 'string'
? (
<span title={ description }>
{ description }
</span>
)
: description
}
</div>
);
}
export default function Title ({ byline, className, description, title }) {
return (
<div className={ className }>
<h3 className={ styles.title }>
{ title }
</h3>
<Byline byline={ byline } />
<Description description={ description } />
</div>
);
}
Title.propTypes = {
byline: nodeOrStringProptype(),
className: PropTypes.string,
description: nodeOrStringProptype(),
title: nodeOrStringProptype()
};

View File

@ -15,9 +15,10 @@
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
*/
$background: rgba(255, 255, 255, 0.85);
$backgroundHover: rgba(249, 249, 249, 1);
$background: rgba(254, 254, 254, 1);
$backgroundHover: rgba(250, 250, 250, 1);
$backgroundLight: rgba(18, 18, 18, 0.5);
$borderColor: rgba(242, 242, 242, 1);
.container {
background: $background;
@ -48,7 +49,7 @@ $backgroundLight: rgba(18, 18, 18, 0.5);
.hoverOverlay {
background: $backgroundHover !important;
border: 1px solid whitesmoke;
border: 1px solid $borderColor;
border-top: 1px solid transparent;
box-shadow: none !important;
display: block;
@ -61,7 +62,7 @@ $backgroundLight: rgba(18, 18, 18, 0.5);
.padded {
background-color: transparent !important;
border-radius: 0 !important;
border: 1px solid whitesmoke;
border: 1px solid $borderColor;
box-shadow: none !important;
height: 100%;
position: relative;

View File

@ -60,7 +60,7 @@ export const PrintIcon = () => <Icon name='print' />;
export const QrIcon = () => <Icon name='qrcode' />;
export const RefreshIcon = () => <Icon name='refresh' />;
export const RemoveIcon = () => <Icon name='remove' />;
export const ReorderIcon = <Icon name='align justify' />;
export const ReorderIcon = () => <Icon name='align justify' />;
export const ReplayIcon = () => <Icon name='retweet' />;
export const SaveIcon = () => <Icon name='save' />;
export const SearchIcon = () => <Icon name='search' />;

View File

@ -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 <http://www.gnu.org/licenses/>.
export default from './steps';

View File

@ -0,0 +1,49 @@
// 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 <http://www.gnu.org/licenses/>.
import React, { PropTypes } from 'react';
import { Step, Stepper, StepLabel } from 'material-ui/Stepper';
import styles from '../title.css';
export default function Steps ({ activeStep, steps }) {
if (!steps || steps.length < 2) {
return null;
}
return (
<div className={ styles.steps }>
<Stepper activeStep={ activeStep }>
{
steps.map((label, index) => {
return (
<Step key={ label.key || index }>
<StepLabel>
{ label }
</StepLabel>
</Step>
);
})
}
</Stepper>
</div>
);
}
Steps.propTypes = {
activeStep: PropTypes.number,
steps: PropTypes.array
};

View File

@ -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 <http://www.gnu.org/licenses/>.
export default from './waiting';

View File

@ -0,0 +1,41 @@
// 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 <http://www.gnu.org/licenses/>.
import React, { PropTypes } from 'react';
import Progress from '~/ui/Progress';
import styles from '../title.css';
export default function Waiting ({ activeStep, busy, busySteps }) {
const isWaiting = busy || (busySteps || []).includes(activeStep);
if (!isWaiting) {
return null;
}
return (
<div className={ styles.waiting }>
<Progress />
</div>
);
}
Waiting.propTypes = {
activeStep: PropTypes.number,
busy: PropTypes.bool,
busySteps: PropTypes.array
};

View File

@ -14,107 +14,62 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { Step, Stepper, StepLabel } from 'material-ui/Stepper';
import React, { Component, PropTypes } from 'react';
import React, { PropTypes } from 'react';
// TODO: It would make sense (going forward) to replace all uses of
// ContainerTitle with this component. In that case the styles for the
// h3 (title) can be pulled from there. (As it stands the duplication
// between the 2 has been removed, but as a short-term DRY only)
import { Title as ContainerTitle } from '~/ui/Container';
import Progress from '~/ui/Progress';
import { nodeOrStringProptype } from '~/util/proptypes';
import Steps from './Steps';
import Waiting from './Waiting';
import styles from './title.css';
export default class Title extends Component {
static propTypes = {
activeStep: PropTypes.number,
description: nodeOrStringProptype(),
busy: PropTypes.bool,
busySteps: PropTypes.array,
byline: nodeOrStringProptype(),
className: PropTypes.string,
isSubTitle: PropTypes.bool,
steps: PropTypes.array,
title: nodeOrStringProptype()
export default function Title ({ activeStep, busy, busySteps, byline, className, description, isSubTitle, steps, title }) {
if (!title && !steps) {
return null;
}
render () {
const { activeStep, byline, className, description, isSubTitle, steps, title } = this.props;
if (!title && !steps) {
return null;
}
return (
<div
className={
[
isSubTitle
? styles.subtitle
: styles.title,
className
].join(' ')
return (
<div
className={
[
isSubTitle
? styles.subtitle
: styles.title,
className
].join(' ')
}
>
<ContainerTitle
byline={ byline }
description={ description }
title={
steps
? steps[activeStep || 0]
: title
}
>
<ContainerTitle
byline={ byline }
description={ description }
title={
steps
? steps[activeStep || 0]
: title
}
/>
{ this.renderSteps() }
{ this.renderWaiting() }
</div>
);
}
renderSteps () {
const { activeStep, steps } = this.props;
if (!steps || steps.length < 2) {
return;
}
return (
<div className={ styles.steps }>
<Stepper activeStep={ activeStep }>
{ this.renderTimeline() }
</Stepper>
</div>
);
}
renderTimeline () {
const { steps } = this.props;
return steps.map((label, index) => {
return (
<Step key={ label.key || index }>
<StepLabel>
{ label }
</StepLabel>
</Step>
);
});
}
renderWaiting () {
const { activeStep, busy, busySteps } = this.props;
const isWaiting = busy || (busySteps || []).includes(activeStep);
if (!isWaiting) {
return null;
}
return (
<div className={ styles.waiting }>
<Progress />
</div>
);
}
/>
<Steps
activeStep={ activeStep }
steps={ steps }
/>
<Waiting
activeStep={ activeStep }
busy={ busy }
busySteps={ busySteps }
/>
</div>
);
}
Title.propTypes = {
activeStep: PropTypes.number,
description: nodeOrStringProptype(),
busy: PropTypes.bool,
busySteps: PropTypes.array,
byline: nodeOrStringProptype(),
className: PropTypes.string,
isSubTitle: PropTypes.bool,
steps: PropTypes.array,
title: nodeOrStringProptype()
};

View File

@ -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 <http://www.gnu.org/licenses/>.
export default from './logs';

View File

@ -0,0 +1,46 @@
// 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 <http://www.gnu.org/licenses/>.
import React from 'react';
import { arrayOrObjectProptype } from '~/util/proptypes';
import styles from '../debug.css';
export default function Logs ({ logs }) {
if (!logs || logs.length === 0) {
return null;
}
return (
<div className={ styles.logs }>
{
logs.map((log, index) => {
return (
<p key={ index } className={ styles.log }>
<span className={ styles.logDate }>[{ log.date.toLocaleString() }]</span>
<span className={ styles.logText }>{ log.log }</span>
</p>
);
})
}
</div>
);
}
Logs.propTypes = {
logs: arrayOrObjectProptype()
};

View File

@ -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 <http://www.gnu.org/licenses/>.
export default from './toggle';

View File

@ -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 <http://www.gnu.org/licenses/>.
import React, { PropTypes } from 'react';
import { FormattedMessage } from 'react-intl';
import styles from '../debug.css';
export default function Toggle ({ logsEnabled }) {
if (logsEnabled) {
return null;
}
return (
<div className={ styles.stopped }>
<FormattedMessage
id='status.debug.stopped'
defaultMessage='Refresh and display of logs from Parity is currently stopped via the UI, start it to see the latest updates.'
/>
</div>
);
}
Toggle.propTypes = {
logsEnabled: PropTypes.bool
};

View File

@ -21,6 +21,8 @@ import { FormattedMessage } from 'react-intl';
import { Container } from '~/ui';
import { PauseIcon, PlayIcon, ReorderIcon, ReplayIcon } from '~/ui/Icons';
import Logs from './Logs';
import Toggle from './Toggle';
import DebugStore from './store';
import styles from './debug.css';
@ -37,7 +39,7 @@ export default class Debug extends Component {
}
render () {
const { logsLevels } = this.debugStore;
const { logs, logsEnabled, logsLevels } = this.debugStore;
return (
<Container
@ -48,82 +50,38 @@ export default class Debug extends Component {
/>
}
>
{ this.renderActions() }
<div className={ styles.actions }>
<a onClick={ this.toggle }>
{
logsEnabled
? <PauseIcon />
: <PlayIcon />
}
</a>
<a onClick={ this.clear }>
<ReplayIcon />
</a>
<a
onClick={ this.reverse }
title={
<FormattedMessage
id='status.debug.reverse'
defaultMessage='Reverse Order'
/>
}
>
<ReorderIcon />
</a>
</div>
<h2 className={ styles.subheader }>
{ logsLevels || '-' }
</h2>
{ this.renderToggle() }
{ this.renderLogs() }
<Toggle logsEnabled={ logsEnabled } />
<Logs logs={ logs } />
</Container>
);
}
renderToggle () {
const { logsEnabled } = this.debugStore;
if (logsEnabled) {
return null;
}
return (
<div className={ styles.stopped }>
<FormattedMessage
id='status.debug.stopped'
defaultMessage='Refresh and display of logs from Parity is currently stopped via the UI, start it to see the latest updates.'
/>
</div>
);
}
renderLogs () {
const { logs } = this.debugStore;
if (logs.length === 0) {
return null;
}
const text = logs
.map((log, index) => {
return (
<p key={ index } className={ styles.log }>
<span className={ styles.logDate }>[{ log.date.toLocaleString() }]</span>
<span className={ styles.logText }>{ log.log }</span>
</p>
);
});
return (
<div className={ styles.logs }>
{ text }
</div>
);
}
renderActions () {
const { logsEnabled } = this.debugStore;
const toggleButton = logsEnabled
? <PauseIcon />
: <PlayIcon />;
return (
<div className={ styles.actions }>
<a onClick={ this.toggle }>{ toggleButton }</a>
<a onClick={ this.clear }><ReplayIcon /></a>
<a
onClick={ this.reverse }
title={
<FormattedMessage
id='status.debug.reverse'
defaultMessage='Reverse Order'
/>
}
>
<ReorderIcon />
</a>
</div>
);
}
clear = () => {
this.debugStore.clearLogs();
};

View File

@ -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 <http://www.gnu.org/licenses/>.
export default from './node';

View File

@ -14,6 +14,7 @@
/* You should have received a copy of the GNU General Public License
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
*/
.container {
padding-bottom: 1em;
}

View File

@ -25,9 +25,9 @@ import { Container, ContainerTitle, Input } from '~/ui';
import MiningSettings from '../MiningSettings';
import StatusStore from './store';
import styles from './nodeStatus.css';
import styles from './node.css';
class NodeStatus extends Component {
class Node extends Component {
static contextTypes = {
api: PropTypes.object.isRequired
};
@ -298,4 +298,4 @@ function mapStateToProps (state) {
export default connect(
mapStateToProps,
null
)(NodeStatus);
)(Node);

View File

@ -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 <http://www.gnu.org/licenses/>.
export default from './peer';

View File

@ -0,0 +1,71 @@
// 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 <http://www.gnu.org/licenses/>.
import React, { PropTypes } from 'react';
import { ScrollableText, ShortenedHash } from '~/ui';
import styles from '../peers.css';
export default function Peer ({ index, peer }) {
const { caps, id, name, network, protocols } = peer;
return (
<tr
className={ styles.peer }
key={ id }
>
<td>
{ index + 1 }
</td>
<td>
<ScrollableText small text={ id } />
</td>
<td>
{ network.remoteAddress }
</td>
<td>
{ name }
</td>
<td>
{
protocols.eth
? <ShortenedHash data={ protocols.eth.head } />
: null
}
</td>
<td>
{
protocols.eth && protocols.eth.difficulty.gt(0)
? protocols.eth.difficulty.toExponential(16)
: null
}
</td>
<td>
{
caps && caps.length > 0
? caps.join(' - ')
: null
}
</td>
</tr>
);
}
Peer.propTypes = {
peer: PropTypes.object,
index: PropTypes.number
};

View File

@ -14,134 +14,92 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import React, { Component, PropTypes } from 'react';
import React, { PropTypes } from 'react';
import { FormattedMessage } from 'react-intl';
import { connect } from 'react-redux';
import { Container, ContainerTitle, ScrollableText, ShortenedHash } from '~/ui';
import { Container } from '~/ui';
import Peer from './peer';
import styles from './peers.css';
class Peers extends Component {
static propTypes = {
peers: PropTypes.array.isRequired
};
render () {
const { peers } = this.props;
return (
<Container>
<ContainerTitle
title={
<FormattedMessage
id='status.peers.title'
defaultMessage='network peers'
/>
}
function Peers ({ peers }) {
return (
<Container
title={
<FormattedMessage
id='status.peers.title'
defaultMessage='network peers'
/>
<div className={ styles.peers }>
<table>
<thead>
<tr>
<th />
<th>
<FormattedMessage
id='status.peers.table.header.id'
defaultMessage='ID'
}
>
<div className={ styles.peers }>
<table>
<thead>
<tr>
<th />
<th>
<FormattedMessage
id='status.peers.table.header.id'
defaultMessage='ID'
/>
</th>
<th>
<FormattedMessage
id='status.peers.table.header.remoteAddress'
defaultMessage='Remote Address'
/>
</th>
<th>
<FormattedMessage
id='status.peers.table.header.name'
defaultMessage='Name'
/>
</th>
<th>
<FormattedMessage
id='status.peers.table.header.ethHeader'
defaultMessage='Header (ETH)'
/>
</th>
<th>
<FormattedMessage
id='status.peers.table.header.ethDiff'
defaultMessage='Difficulty (ETH)'
/>
</th>
<th>
<FormattedMessage
id='status.peers.table.header.caps'
defaultMessage='Capabilities'
/>
</th>
</tr>
</thead>
<tbody>
{
peers.map((peer, index) => {
return (
<Peer
index={ index }
key={ index }
peer={ peer }
/>
</th>
<th>
<FormattedMessage
id='status.peers.table.header.remoteAddress'
defaultMessage='Remote Address'
/>
</th>
<th>
<FormattedMessage
id='status.peers.table.header.name'
defaultMessage='Name'
/>
</th>
<th>
<FormattedMessage
id='status.peers.table.header.ethHeader'
defaultMessage='Header (ETH)'
/>
</th>
<th>
<FormattedMessage
id='status.peers.table.header.ethDiff'
defaultMessage='Difficulty (ETH)'
/>
</th>
<th>
<FormattedMessage
id='status.peers.table.header.caps'
defaultMessage='Capabilities'
/>
</th>
</tr>
</thead>
<tbody>
{ this.renderPeers(peers) }
</tbody>
</table>
</div>
</Container>
);
}
renderPeers (peers) {
return peers.map((peer, index) => this.renderPeer(peer, index));
}
renderPeer (peer, index) {
const { caps, id, name, network, protocols } = peer;
return (
<tr
className={ styles.peer }
key={ id }
>
<td>
{ index + 1 }
</td>
<td>
<ScrollableText small text={ id } />
</td>
<td>
{ network.remoteAddress }
</td>
<td>
{ name }
</td>
<td>
{
protocols.eth
? <ShortenedHash data={ protocols.eth.head } />
: null
}
</td>
<td>
{
protocols.eth && protocols.eth.difficulty.gt(0)
? protocols.eth.difficulty.toExponential(16)
: null
}
</td>
<td>
{
caps && caps.length > 0
? caps.join(' - ')
: null
}
</td>
</tr>
);
}
);
})
}
</tbody>
</table>
</div>
</Container>
);
}
Peers.propTypes = {
peers: PropTypes.array.isRequired
};
function mapStateToProps (state) {
const handshakeRegex = /handshake/i;
@ -160,4 +118,7 @@ function mapStateToProps (state) {
return { peers: realPeers };
}
export default connect(mapStateToProps)(Peers);
export default connect(
mapStateToProps,
null
)(Peers);

View File

@ -20,8 +20,8 @@ import { FormattedMessage } from 'react-intl';
import { Page } from '~/ui';
import Debug from './Debug';
import Node from './Node';
import Peers from './Peers';
import NodeStatus from './NodeStatus';
import styles from './status.css';
@ -36,7 +36,7 @@ export default function Status () {
}
>
<div className={ styles.body }>
<NodeStatus />
<Node />
<Peers />
<Debug />
</div>