mirror of https://github.com/docker/docs.git
213 lines
6.8 KiB
JavaScript
213 lines
6.8 KiB
JavaScript
var _ = require('underscore');
|
|
var $ = require('jquery');
|
|
var React = require('react/addons');
|
|
var Router = require('react-router');
|
|
var ContainerStore = require('./ContainerStore');
|
|
var docker = require('./docker');
|
|
var exec = require('exec');
|
|
var boot2docker = require('./boot2docker');
|
|
var ProgressBar = require('react-bootstrap/ProgressBar');
|
|
|
|
var Route = Router.Route;
|
|
var NotFoundRoute = Router.NotFoundRoute;
|
|
var DefaultRoute = Router.DefaultRoute;
|
|
var Link = Router.Link;
|
|
var RouteHandler = Router.RouteHandler;
|
|
|
|
var ContainerDetails = React.createClass({
|
|
mixins: [Router.State],
|
|
_oldHeight: 0,
|
|
PAGE_LOGS: 'logs',
|
|
PAGE_SETTINGS: 'settings',
|
|
getInitialState: function () {
|
|
return {
|
|
logs: [],
|
|
page: this.PAGE_LOGS
|
|
};
|
|
},
|
|
componentWillReceiveProps: function () {
|
|
this.setState({
|
|
page: this.PAGE_LOGS
|
|
});
|
|
ContainerStore.fetchLogs(this.getParams().name, function () {
|
|
this.updateLogs();
|
|
}.bind(this));
|
|
},
|
|
componentDidMount: function () {
|
|
ContainerStore.on(ContainerStore.SERVER_PROGRESS_EVENT, this.updateProgress);
|
|
ContainerStore.on(ContainerStore.SERVER_LOGS_EVENT, this.updateLogs);
|
|
},
|
|
componentWillUnmount: function () {
|
|
ContainerStore.removeListener(ContainerStore.SERVER_PROGRESS_EVENT, this.updateProgress);
|
|
ContainerStore.removeListener(ContainerStore.SERVER_LOGS_EVENT, this.updateLogs);
|
|
},
|
|
componentDidUpdate: function () {
|
|
var parent = $('.details-logs');
|
|
if (!parent.length) {
|
|
return;
|
|
}
|
|
if (parent.scrollTop() >= this._oldHeight) {
|
|
parent.stop();
|
|
parent.scrollTop(parent[0].scrollHeight - parent.height());
|
|
}
|
|
this._oldHeight = parent[0].scrollHeight - parent.height();
|
|
},
|
|
updateLogs: function (name) {
|
|
if (name && name !== this.getParams().name) {
|
|
return;
|
|
}
|
|
this.setState({
|
|
logs: ContainerStore.logs(this.getParams().name)
|
|
});
|
|
},
|
|
updateProgress: function (name) {
|
|
console.log('progress', name, ContainerStore.progress(name));
|
|
if (name === this.getParams().name) {
|
|
this.setState({
|
|
progress: ContainerStore.progress(name)
|
|
});
|
|
}
|
|
},
|
|
showLogs: function () {
|
|
this.setState({
|
|
page: this.PAGE_LOGS
|
|
});
|
|
},
|
|
showSettings: function () {
|
|
this.setState({
|
|
page: this.PAGE_SETTINGS
|
|
});
|
|
},
|
|
handleClick: function (name) {
|
|
var container = this.props.container;
|
|
boot2docker.ip(function (err, ip) {
|
|
var ports = _.map(container.NetworkSettings.Ports, function (value, key) {
|
|
var portProtocolPair = key.split('/');
|
|
var res = {
|
|
'port': portProtocolPair[0],
|
|
'protocol': portProtocolPair[1]
|
|
};
|
|
if (value && value.length) {
|
|
var port = value[0].HostPort;
|
|
res.host = ip;
|
|
res.port = port;
|
|
res.url = 'http://' + ip + ':' + port;
|
|
} else {
|
|
return null;
|
|
}
|
|
return res;
|
|
});
|
|
exec(['open', ports[0].url], function (err) {
|
|
if (err) { throw err; }
|
|
});
|
|
});
|
|
},
|
|
render: function () {
|
|
var self = this;
|
|
|
|
if (!this.state) {
|
|
return <div></div>;
|
|
}
|
|
|
|
var logs = this.state.logs.map(function (l, i) {
|
|
return <p key={i} dangerouslySetInnerHTML={{__html: l}}></p>;
|
|
});
|
|
|
|
if (!this.props.container) {
|
|
return false;
|
|
}
|
|
|
|
var state;
|
|
if (this.props.container.State.Running) {
|
|
state = <h2 className="status running">running</h2>;
|
|
} else if (this.props.container.State.Restarting) {
|
|
state = <h2 className="status restarting">restarting</h2>;
|
|
} else if (this.props.container.State.Paused) {
|
|
state = <h2 className="status paused">paused</h2>;
|
|
} else if (this.props.container.State.Downloading) {
|
|
state = <h2 className="status">downloading</h2>;
|
|
}
|
|
|
|
var button;
|
|
if (this.state.progress === 1) {
|
|
button = <a className="btn btn-primary" onClick={this.handleClick}>View</a>;
|
|
} else {
|
|
button = <a className="btn btn-primary disabled" onClick={this.handleClick}>View</a>;
|
|
}
|
|
|
|
var body;
|
|
if (this.props.container.State.Downloading) {
|
|
body = (
|
|
<div className="details-progress">
|
|
<ProgressBar now={this.state.progress * 100} label="%(percent)s%" />
|
|
</div>
|
|
);
|
|
} else {
|
|
if (this.state.page === this.PAGE_LOGS) {
|
|
body = (
|
|
<div className="details-logs">
|
|
<div className="logs">
|
|
{logs}
|
|
</div>
|
|
</div>
|
|
);
|
|
} else {
|
|
body = (
|
|
<div className="details-logs">
|
|
<div className="settings">
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
}
|
|
|
|
var textButtonClasses = React.addons.classSet({
|
|
'btn': true,
|
|
'btn-action': true,
|
|
'only-icon': true,
|
|
'active': this.state.page === this.PAGE_LOGS
|
|
});
|
|
|
|
var gearButtonClass = React.addons.classSet({
|
|
'btn': true,
|
|
'btn-action': true,
|
|
'only-icon': true,
|
|
'active': this.state.page === this.PAGE_SETTINGS
|
|
});
|
|
|
|
var name = this.props.container.Name;
|
|
var image = this.props.container.Config.Image;
|
|
|
|
return (
|
|
<div className="details">
|
|
<div className="details-header">
|
|
<div className="details-header-info">
|
|
<h1>{name}</h1>{state}<h2 className="image-label">Image</h2><h2 className="image">{image}</h2>
|
|
</div>
|
|
<div className="details-header-actions">
|
|
<div className="action btn-group">
|
|
<a className="btn btn-action with-icon" onClick={this.handleClick}><span className="icon icon-preview-2"></span><span className="content">View</span></a><a className="btn btn-action with-icon dropdown-toggle"><span className="icon-dropdown icon icon-arrow-37"></span></a>
|
|
</div>
|
|
<div className="action">
|
|
<a className="btn btn-action with-icon dropdown-toggle" onClick={this.handleClick}><span className="icon icon-folder-1"></span> <span className="content">Volumes</span> <span className="icon-dropdown icon icon-arrow-37"></span></a>
|
|
</div>
|
|
<div className="action">
|
|
<a className="btn btn-action with-icon" onClick={this.handleClick}><span className="icon icon-refresh"></span> <span className="content">Restart</span></a>
|
|
</div>
|
|
<div className="action">
|
|
<a className="btn btn-action with-icon" onClick={this.handleClick}><span className="icon icon-window-code-3"></span> <span className="content">Terminal</span></a>
|
|
</div>
|
|
<div className="details-header-actions-rhs tabs btn-group">
|
|
<a className={textButtonClasses} onClick={this.showLogs}><span className="icon icon-text-wrapping-2"></span></a>
|
|
<a className={gearButtonClass} onClick={this.showSettings}><span className="icon icon-setting-gear"></span></a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{body}
|
|
</div>
|
|
);
|
|
}
|
|
});
|
|
|
|
module.exports = ContainerDetails;
|