mirror of https://github.com/docker/docs.git
Removing active event from ContainerStore
This commit is contained in:
parent
5d291b6cd8
commit
b28c27455f
|
@ -1,15 +1,19 @@
|
|||
var _ = require('underscore');
|
||||
var React = require('react');
|
||||
var Router = require('react-router');
|
||||
var Convert = require('ansi-to-html');
|
||||
var convert = new Convert();
|
||||
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 Convert = require('ansi-to-html');
|
||||
var convert = new Convert();
|
||||
var ContainerStore = require('./ContainerStore');
|
||||
var docker = require('./docker');
|
||||
|
||||
var ContainerDetails = React.createClass({
|
||||
mixins: [Router.State],
|
||||
|
@ -19,14 +23,17 @@ var ContainerDetails = React.createClass({
|
|||
};
|
||||
},
|
||||
componentWillReceiveProps: function () {
|
||||
console.log('props');
|
||||
this.update();
|
||||
this.setState({
|
||||
logs: []
|
||||
});
|
||||
var self = this;
|
||||
var logs = [];
|
||||
var index = 0;
|
||||
docker.client().getContainer(this.getParams().name).logs({
|
||||
follow: false,
|
||||
stdout: true,
|
||||
stderr: true,
|
||||
timestamps: true
|
||||
}, function (err, stream) {
|
||||
stream.setEncoding('utf8');
|
||||
|
@ -44,6 +51,7 @@ var ContainerDetails = React.createClass({
|
|||
docker.client().getContainer(self.getParams().name).logs({
|
||||
follow: true,
|
||||
stdout: true,
|
||||
stderr: true,
|
||||
timestamps: true,
|
||||
tail: 0
|
||||
}, function (err, stream) {
|
||||
|
@ -75,11 +83,9 @@ var ContainerDetails = React.createClass({
|
|||
},
|
||||
update: function () {
|
||||
var name = this.getParams().name;
|
||||
var container = ContainerStore.container(name);
|
||||
var progress = ContainerStore.progress(name);
|
||||
this.setState({
|
||||
progress: progress,
|
||||
container: container
|
||||
container: ContainerStore.container(name),
|
||||
progress: ContainerStore.progress(name)
|
||||
});
|
||||
},
|
||||
_escapeHTML: function (html) {
|
||||
|
@ -88,8 +94,32 @@ var ContainerDetails = React.createClass({
|
|||
div.appendChild(text);
|
||||
return div.innerHTML;
|
||||
},
|
||||
handleClick: function (name) {
|
||||
var container = this.state.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;
|
||||
});
|
||||
console.log(ports);
|
||||
exec(['open', ports[0].url], function (err) {
|
||||
if (err) { throw err; }
|
||||
});
|
||||
});
|
||||
},
|
||||
render: function () {
|
||||
console.log('render details');
|
||||
var self = this;
|
||||
|
||||
if (!this.state) {
|
||||
|
@ -111,12 +141,32 @@ var ContainerDetails = React.createClass({
|
|||
state = <h2 className="status">restarting</h2>;
|
||||
}
|
||||
|
||||
var progress;
|
||||
if (this.state.progress > 0 && this.state.progress != 1) {
|
||||
progress = (
|
||||
<div className="details-progress">
|
||||
<ProgressBar now={this.state.progress * 100} label="%(percent)s%" />
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
progress = <div></div>;
|
||||
}
|
||||
|
||||
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 name = this.state.container.Name.replace('/', '');
|
||||
|
||||
return (
|
||||
<div className="details">
|
||||
<div className="details-header">
|
||||
<h1>{this.state.container.Name.replace('/', '')}</h1>
|
||||
<h2>{this.state.progress}</h2>
|
||||
<h1>{name}</h1> <a className="btn btn-primary" onClick={this.handleClick}>View</a>
|
||||
</div>
|
||||
{progress}
|
||||
<div className="details-logs">
|
||||
<div className="logs">
|
||||
{logs}
|
||||
|
|
|
@ -16,16 +16,13 @@ var RouteHandler = Router.RouteHandler;
|
|||
var Navigation= Router.Navigation;
|
||||
|
||||
var ContainerList = React.createClass({
|
||||
mixins: [Navigation],
|
||||
getInitialState: function () {
|
||||
return {
|
||||
active: null,
|
||||
containers: []
|
||||
};
|
||||
},
|
||||
componentDidMount: function () {
|
||||
this.updateContainers();
|
||||
ContainerStore.addChangeListener(ContainerStore.ACTIVE, this.updateActive);
|
||||
ContainerStore.addChangeListener(ContainerStore.CONTAINERS, this.updateContainers);
|
||||
},
|
||||
componentWillMount: function () {
|
||||
|
@ -33,29 +30,13 @@ var ContainerList = React.createClass({
|
|||
},
|
||||
componentWillUnmount: function () {
|
||||
ContainerStore.removeChangeListener(ContainerStore.CONTAINERS, this.updateContainers);
|
||||
ContainerStore.removeChangeListener(ContainerStore.ACTIVE, updateActive.update);
|
||||
},
|
||||
updateActive: function () {
|
||||
if (ContainerStore.active()) {
|
||||
this.transitionTo('container', {name: ContainerStore.active()});
|
||||
}
|
||||
},
|
||||
updateContainers: function () {
|
||||
// Sort by name
|
||||
var containers = _.values(ContainerStore.containers()).sort(function (a, b) {
|
||||
return a.Name.localeCompare(b.Name);
|
||||
});
|
||||
|
||||
this.setState({containers: containers});
|
||||
|
||||
// Transition to the active container or set one
|
||||
var active = ContainerStore.active();
|
||||
if (!ContainerStore.container(active) && containers.length > 0) {
|
||||
ContainerStore.setActive(containers[0].Name.replace('/', ''));
|
||||
}
|
||||
},
|
||||
handleClick: function (containerId) {
|
||||
ContainerStore.setActive(name);
|
||||
},
|
||||
render: function () {
|
||||
var self = this;
|
||||
|
@ -95,13 +76,15 @@ var ContainerList = React.createClass({
|
|||
state = <div className="state state-stopped"></div>;
|
||||
}
|
||||
|
||||
var name = container.Name.replace('/', '');
|
||||
|
||||
return (
|
||||
<Link key={container.Name.replace('/', '')} to="container" params={{name: container.Name.replace('/', '')}} onClick={self.handleClick.bind(self, container.Id)}>
|
||||
<Link key={name} data-container={name} to="container" params={{name: name}}>
|
||||
<li>
|
||||
{state}
|
||||
<div className="info">
|
||||
<div className="name">
|
||||
{container.Name.replace('/', '')}
|
||||
{name}
|
||||
</div>
|
||||
<div className="image">
|
||||
{imageName}
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
var async = require('async');
|
||||
var $ = require('jquery');
|
||||
var React = require('react');
|
||||
var Router = require('react-router');
|
||||
var Modal = require('react-bootstrap/Modal');
|
||||
var RetinaImage = require('react-retina-image');
|
||||
var $ = require('jquery');
|
||||
var ContainerStore = require('./ContainerStore');
|
||||
|
||||
var Navigation = Router.Navigation;
|
||||
|
||||
var ContainerModal = React.createClass({
|
||||
mixins: [Navigation],
|
||||
_searchRequest: null,
|
||||
getInitialState: function () {
|
||||
return {
|
||||
query: '',
|
||||
results: []
|
||||
results: [],
|
||||
recommended: ContainerStore.recommended()
|
||||
};
|
||||
},
|
||||
componentDidMount: function () {
|
||||
|
@ -21,6 +24,8 @@ var ContainerModal = React.createClass({
|
|||
search: function (query) {
|
||||
var self = this;
|
||||
this._searchRequest = $.get('https://registry.hub.docker.com/v1/search?q=' + query, function (result) {
|
||||
self._searchRequest.abort();
|
||||
self._searchRequest = null;
|
||||
if (self.isMounted()) {
|
||||
self.setState(result);
|
||||
console.log(result);
|
||||
|
@ -35,6 +40,7 @@ var ContainerModal = React.createClass({
|
|||
}
|
||||
|
||||
if (this._searchRequest) {
|
||||
console.log('Cancel');
|
||||
this._searchRequest.abort();
|
||||
this._searchRequest = null;
|
||||
}
|
||||
|
@ -48,14 +54,20 @@ var ContainerModal = React.createClass({
|
|||
var name = event.target.getAttribute('name');
|
||||
var self = this;
|
||||
ContainerStore.create(name, 'latest', function (err, containerName) {
|
||||
ContainerStore.setActive(containerName);
|
||||
// this.transitionTo('containers', {container: containerName});
|
||||
self.props.onRequestHide();
|
||||
});
|
||||
}.bind(this));
|
||||
},
|
||||
render: function () {
|
||||
var top = this.state.results.splice(0, 7);
|
||||
var self = this;
|
||||
var results = top.map(function (r) {
|
||||
|
||||
var data;
|
||||
if (this.state.query) {
|
||||
data = this.state.results.splice(0, 7);
|
||||
} else {
|
||||
data = this.state.recommended;
|
||||
}
|
||||
var results = data.map(function (r) {
|
||||
var name;
|
||||
if (r.is_official) {
|
||||
name = <span><RetinaImage src="official.png"/>{r.name}</span>;
|
||||
|
@ -79,6 +91,14 @@ var ContainerModal = React.createClass({
|
|||
</li>
|
||||
);
|
||||
});
|
||||
|
||||
var title;
|
||||
if (this.state.query) {
|
||||
title = <div className="title">Results</div>;
|
||||
} else {
|
||||
title = <div className="title">Recommended</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal {...this.props} animation={false} className="create-modal">
|
||||
<div className="modal-body">
|
||||
|
@ -88,7 +108,7 @@ var ContainerModal = React.createClass({
|
|||
<a href="#"><span>What's an image?</span></a>
|
||||
</div>
|
||||
<div className="results">
|
||||
<div className="title">Results</div>
|
||||
{title}
|
||||
<ul>
|
||||
{results}
|
||||
</ul>
|
||||
|
|
|
@ -11,11 +11,11 @@ var ContainerStore = assign(EventEmitter.prototype, {
|
|||
CONTAINERS: 'containers',
|
||||
PROGRESS: 'progress',
|
||||
LOGS: 'logs',
|
||||
ACTIVE: 'active',
|
||||
RECOMMENDED: 'recommended',
|
||||
_recommended: [],
|
||||
_containers: {},
|
||||
_progress: {},
|
||||
_logs: {},
|
||||
_active: null,
|
||||
_pullScratchImage: function (callback) {
|
||||
var image = docker.client().getImage('scratch:latest');
|
||||
image.inspect(function (err, data) {
|
||||
|
@ -101,7 +101,9 @@ var ContainerStore = assign(EventEmitter.prototype, {
|
|||
// Refresh with docker & hook into events
|
||||
var self = this;
|
||||
this.update(function (err) {
|
||||
self.updateRecommended(function (err) {
|
||||
callback();
|
||||
});
|
||||
var downloading = _.filter(_.values(self._containers), function (container) {
|
||||
var env = container.Config.Env;
|
||||
return _.indexOf(env, 'KITEMATIC_DOWNLOADING=true') !== -1;
|
||||
|
@ -168,6 +170,30 @@ var ContainerStore = assign(EventEmitter.prototype, {
|
|||
});
|
||||
});
|
||||
},
|
||||
updateRecommended: function (callback) {
|
||||
var self = this;
|
||||
$.ajax({
|
||||
url: 'https://kitematic.com/recommended.json',
|
||||
dataType: 'json',
|
||||
success: function (res, status) {
|
||||
var recommended = res.recommended;
|
||||
async.map(recommended, function (repository, callback) {
|
||||
$.get('https://registry.hub.docker.com/v1/search?q=' + repository, function (data) {
|
||||
var results = data.results;
|
||||
callback(null, _.find(results, function (r) {
|
||||
return r.name === repository;
|
||||
}));
|
||||
});
|
||||
}, function (err, results) {
|
||||
self._recommended = results;
|
||||
callback();
|
||||
});
|
||||
},
|
||||
error: function (err) {
|
||||
console.log(err);
|
||||
}
|
||||
});
|
||||
},
|
||||
create: function (repository, tag, callback) {
|
||||
tag = tag || 'latest';
|
||||
var self = this;
|
||||
|
@ -213,7 +239,6 @@ var ContainerStore = assign(EventEmitter.prototype, {
|
|||
}, {});
|
||||
|
||||
self._progress[containerName] = 0;
|
||||
self.emit(containerName);
|
||||
|
||||
stream.on('data', function (str) {
|
||||
console.log(str);
|
||||
|
@ -253,26 +278,19 @@ var ContainerStore = assign(EventEmitter.prototype, {
|
|||
// If not then directly create the container
|
||||
self._createContainer(imageName, containerName, function () {
|
||||
callback(null, containerName);
|
||||
console.log('done');
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
setActive: function (name) {
|
||||
console.log('set active');
|
||||
this._active = name;
|
||||
this.emit(this.ACTIVE);
|
||||
},
|
||||
active: function () {
|
||||
return this._active;
|
||||
},
|
||||
// Returns all containers
|
||||
containers: function() {
|
||||
return this._containers;
|
||||
},
|
||||
container: function (name) {
|
||||
return this._containers[name];
|
||||
},
|
||||
recommended: function () {
|
||||
return this._recommended;
|
||||
},
|
||||
progress: function (name) {
|
||||
return this._progress[name];
|
||||
},
|
||||
|
|
|
@ -233,7 +233,12 @@
|
|||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 0px 45px 14px;
|
||||
background: white;
|
||||
position: relative;
|
||||
a {
|
||||
position: absolute;
|
||||
right: 30px;
|
||||
top: -4px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
margin: 0;
|
||||
|
@ -253,6 +258,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
.details-progress {
|
||||
margin: 26% auto 0;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.details-logs {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
|
|
Loading…
Reference in New Issue