UI for controls.

- Make backend address configurable via env variable
- `BACKEND_HOST=1.2.3.4:4040 npm start` points the frontend to the app on that server. Just for development
- Render control icons
  - removed close x for details panel
  - added control icons in its space
  - closing of panel still works by clicking on same node, or background
- Dont allow control while pending
- Render and auto-dismiss control error
- Make tests pass
This commit is contained in:
David Kaltschmidt
2015-11-03 10:30:00 +00:00
committed by Tom Wilkie
parent 8f957c4f13
commit abcb94b1f1
20 changed files with 267 additions and 69 deletions

View File

@@ -2,6 +2,8 @@ jest.dontMock('../node-details.js');
jest.dontMock('../../mixins/node-color-mixin');
jest.dontMock('../../utils/title-utils');
__WS_URL__ = false
describe('NodeDetails', () => {
let NodeDetails;
let nodes;

View File

@@ -20,6 +20,8 @@ const ESC_KEY_CODE = 27;
function getStateFromStores() {
return {
activeTopologyOptions: AppStore.getActiveTopologyOptions(),
controlError: AppStore.getControlError(),
controlPending: AppStore.isControlPending(),
currentTopology: AppStore.getCurrentTopology(),
currentTopologyId: AppStore.getCurrentTopologyId(),
currentTopologyOptions: AppStore.getCurrentTopologyOptions(),
@@ -81,6 +83,8 @@ const App = React.createClass({
return (
<div>
{showingDetails && <Details nodes={this.state.nodes}
controlError={this.state.controlError}
controlPending={this.state.controlPending}
nodeId={this.state.selectedNodeId}
details={this.state.nodeDetails} /> }

View File

@@ -2,7 +2,6 @@ const React = require('react');
const mui = require('material-ui');
const Paper = mui.Paper;
const AppActions = require('../actions/app-actions');
const NodeDetails = require('./node-details');
const Details = React.createClass({
@@ -11,21 +10,10 @@ const Details = React.createClass({
return (
<div id="details">
<Paper zDepth={3} style={{height: '100%', paddingBottom: 8}}>
<div className="details-tools-wrapper">
<div className="details-tools">
<span className="fa fa-close" onClick={this.handleClickClose} />
</div>
</div>
<NodeDetails nodeId={this.props.nodeId} details={this.props.details}
nodes={this.props.nodes} />
<NodeDetails {...this.props} />
</Paper>
</div>
);
},
handleClickClose: function(ev) {
ev.preventDefault();
AppActions.clickCloseDetails();
}
});

View File

@@ -0,0 +1,23 @@
const React = require('react');
const AppActions = require('../actions/app-actions');
const NodeControlButton = React.createClass({
render: function() {
let className = `node-control-button fa ${this.props.control.icon}`;
if (this.props.pending) {
className += ' node-control-button-pending';
}
return (
<span className={className} title={this.props.control.human} onClick={this.handleClick} />
);
},
handleClick: function(ev) {
ev.preventDefault();
AppActions.doControl(this.props.control.probeId, this.props.control.nodeId, this.props.control.id);
}
});
module.exports = NodeControlButton;

View File

@@ -0,0 +1,25 @@
const React = require('react');
const NodeControlButton = require('./node-control-button');
const NodeDetailsControls = React.createClass({
render: function() {
return (
<div className="node-details-controls">
{this.props.error && <div className="node-details-controls-error" title={this.props.error}>
<span className="node-details-controls-error-icon fa fa-warning" />
<span className="node-details-controls-error-messages">{this.props.error}</span>
</div>}
{this.props.controls && this.props.controls.map(control => {
return (
<NodeControlButton control={control} pending={this.props.pending} />
);
})}
</div>
);
}
});
module.exports = NodeDetailsControls;

View File

@@ -1,6 +1,7 @@
const _ = require('lodash');
const React = require('react');
const NodeDetailsControls = require('./node-details-controls');
const NodeDetailsTable = require('./node-details-table');
const NodeColorMixin = require('../mixins/node-color-mixin');
const TitleUtils = require('../utils/title-utils');
@@ -65,6 +66,8 @@ const NodeDetails = React.createClass({
return (
<div className="node-details">
<div className="node-details-header" style={style}>
<NodeDetailsControls controls={details.controls}
pending={this.props.controlPending} error={this.props.controlError} />
<h2 className="node-details-header-label truncate" title={details.label_major}>
{details.label_major}
</h2>

View File

@@ -1,7 +1,6 @@
const React = require('react');
const NodesChart = require('../charts/nodes-chart');
const AppActions = require('../actions/app-actions');
const navbarHeight = 160;
const marginTop = 0;
@@ -23,10 +22,6 @@ const Nodes = React.createClass({
window.removeEventListener('resize', this.handleResize);
},
onNodeClick: function(ev) {
AppActions.clickNode(ev.currentTarget.id);
},
render: function() {
return (
<NodesChart
@@ -34,7 +29,6 @@ const Nodes = React.createClass({
highlightedNodeIds={this.props.highlightedNodeIds}
selectedNodeId={this.props.selectedNodeId}
nodes={this.props.nodes}
onNodeClick={this.onNodeClick}
width={this.state.width}
height={this.state.height}
topologyId={this.props.topologyId}