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

View File

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

View File

@ -60,7 +60,7 @@ export const PrintIcon = () => <Icon name='print' />;
export const QrIcon = () => <Icon name='qrcode' />; export const QrIcon = () => <Icon name='qrcode' />;
export const RefreshIcon = () => <Icon name='refresh' />; export const RefreshIcon = () => <Icon name='refresh' />;
export const RemoveIcon = () => <Icon name='remove' />; 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 ReplayIcon = () => <Icon name='retweet' />;
export const SaveIcon = () => <Icon name='save' />; export const SaveIcon = () => <Icon name='save' />;
export const SearchIcon = () => <Icon name='search' />; 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,35 +14,17 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { Step, Stepper, StepLabel } from 'material-ui/Stepper'; import React, { PropTypes } from 'react';
import React, { Component, 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 { Title as ContainerTitle } from '~/ui/Container';
import Progress from '~/ui/Progress';
import { nodeOrStringProptype } from '~/util/proptypes'; import { nodeOrStringProptype } from '~/util/proptypes';
import Steps from './Steps';
import Waiting from './Waiting';
import styles from './title.css'; import styles from './title.css';
export default class Title extends Component { export default function Title ({ activeStep, busy, busySteps, byline, className, description, isSubTitle, steps, title }) {
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()
}
render () {
const { activeStep, byline, className, description, isSubTitle, steps, title } = this.props;
if (!title && !steps) { if (!title && !steps) {
return null; return null;
} }
@ -67,54 +49,27 @@ export default class Title extends Component {
: title : title
} }
/> />
{ this.renderSteps() } <Steps
{ this.renderWaiting() } activeStep={ activeStep }
steps={ steps }
/>
<Waiting
activeStep={ activeStep }
busy={ busy }
busySteps={ busySteps }
/>
</div> </div>
); );
} }
renderSteps () { Title.propTypes = {
const { activeStep, steps } = this.props; activeStep: PropTypes.number,
description: nodeOrStringProptype(),
if (!steps || steps.length < 2) { busy: PropTypes.bool,
return; busySteps: PropTypes.array,
} byline: nodeOrStringProptype(),
className: PropTypes.string,
return ( isSubTitle: PropTypes.bool,
<div className={ styles.steps }> steps: PropTypes.array,
<Stepper activeStep={ activeStep }> title: nodeOrStringProptype()
{ 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>
);
}
}

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 { Container } from '~/ui';
import { PauseIcon, PlayIcon, ReorderIcon, ReplayIcon } from '~/ui/Icons'; import { PauseIcon, PlayIcon, ReorderIcon, ReplayIcon } from '~/ui/Icons';
import Logs from './Logs';
import Toggle from './Toggle';
import DebugStore from './store'; import DebugStore from './store';
import styles from './debug.css'; import styles from './debug.css';
@ -37,7 +39,7 @@ export default class Debug extends Component {
} }
render () { render () {
const { logsLevels } = this.debugStore; const { logs, logsEnabled, logsLevels } = this.debugStore;
return ( return (
<Container <Container
@ -48,67 +50,17 @@ export default class Debug extends Component {
/> />
} }
> >
{ this.renderActions() }
<h2 className={ styles.subheader }>
{ logsLevels || '-' }
</h2>
{ this.renderToggle() }
{ this.renderLogs() }
</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 }> <div className={ styles.actions }>
<a onClick={ this.toggle }>{ toggleButton }</a> <a onClick={ this.toggle }>
<a onClick={ this.clear }><ReplayIcon /></a> {
logsEnabled
? <PauseIcon />
: <PlayIcon />
}
</a>
<a onClick={ this.clear }>
<ReplayIcon />
</a>
<a <a
onClick={ this.reverse } onClick={ this.reverse }
title={ title={
@ -121,6 +73,12 @@ export default class Debug extends Component {
<ReorderIcon /> <ReorderIcon />
</a> </a>
</div> </div>
<h2 className={ styles.subheader }>
{ logsLevels || '-' }
</h2>
<Toggle logsEnabled={ logsEnabled } />
<Logs logs={ logs } />
</Container>
); );
} }

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

View File

@ -25,9 +25,9 @@ import { Container, ContainerTitle, Input } from '~/ui';
import MiningSettings from '../MiningSettings'; import MiningSettings from '../MiningSettings';
import StatusStore from './store'; import StatusStore from './store';
import styles from './nodeStatus.css'; import styles from './node.css';
class NodeStatus extends Component { class Node extends Component {
static contextTypes = { static contextTypes = {
api: PropTypes.object.isRequired api: PropTypes.object.isRequired
}; };
@ -298,4 +298,4 @@ function mapStateToProps (state) {
export default connect( export default connect(
mapStateToProps, mapStateToProps,
null 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,32 +14,26 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // 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 { FormattedMessage } from 'react-intl';
import { connect } from 'react-redux'; 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'; import styles from './peers.css';
class Peers extends Component { function Peers ({ peers }) {
static propTypes = {
peers: PropTypes.array.isRequired
};
render () {
const { peers } = this.props;
return ( return (
<Container> <Container
<ContainerTitle
title={ title={
<FormattedMessage <FormattedMessage
id='status.peers.title' id='status.peers.title'
defaultMessage='network peers' defaultMessage='network peers'
/> />
} }
/> >
<div className={ styles.peers }> <div className={ styles.peers }>
<table> <table>
<thead> <thead>
@ -84,7 +78,17 @@ class Peers extends Component {
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{ this.renderPeers(peers) } {
peers.map((peer, index) => {
return (
<Peer
index={ index }
key={ index }
peer={ peer }
/>
);
})
}
</tbody> </tbody>
</table> </table>
</div> </div>
@ -92,55 +96,9 @@ class Peers extends Component {
); );
} }
renderPeers (peers) { Peers.propTypes = {
return peers.map((peer, index) => this.renderPeer(peer, index)); peers: PropTypes.array.isRequired
} };
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>
);
}
}
function mapStateToProps (state) { function mapStateToProps (state) {
const handshakeRegex = /handshake/i; const handshakeRegex = /handshake/i;
@ -160,4 +118,7 @@ function mapStateToProps (state) {
return { peers: realPeers }; 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 { Page } from '~/ui';
import Debug from './Debug'; import Debug from './Debug';
import Node from './Node';
import Peers from './Peers'; import Peers from './Peers';
import NodeStatus from './NodeStatus';
import styles from './status.css'; import styles from './status.css';
@ -36,7 +36,7 @@ export default function Status () {
} }
> >
<div className={ styles.body }> <div className={ styles.body }>
<NodeStatus /> <Node />
<Peers /> <Peers />
<Debug /> <Debug />
</div> </div>