Merge branch 'master' into revert-382-revert-374-hub-button

This commit is contained in:
Jeffrey Morgan 2015-04-27 09:45:31 -04:00
commit b9cb2e5fe5
9 changed files with 75 additions and 10 deletions

BIN
images/button-stop.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
images/button-stop@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -27,6 +27,7 @@
"jest": { "jest": {
"scriptPreprocessor": "<rootDir>/util/preprocessor.js", "scriptPreprocessor": "<rootDir>/util/preprocessor.js",
"setupEnvScriptFile": "<rootDir>/util/testenv.js", "setupEnvScriptFile": "<rootDir>/util/testenv.js",
"setupTestFrameworkScriptFile": "<rootDir>/util/prepare.js",
"collectCoverage": true, "collectCoverage": true,
"testDirectoryName": "src", "testDirectoryName": "src",
"testPathIgnorePatterns": [ "testPathIgnorePatterns": [
@ -42,7 +43,8 @@
"<rootDir>/node_modules/.*JSONStream", "<rootDir>/node_modules/.*JSONStream",
"<rootDir>/node_modules/object-assign", "<rootDir>/node_modules/object-assign",
"<rootDir>/node_modules/underscore", "<rootDir>/node_modules/underscore",
"<rootDir>/node_modules/bluebird" "<rootDir>/node_modules/bluebird",
"<rootDir>/node_modules/source-map-support"
] ]
}, },
"docker-version": "1.6.0", "docker-version": "1.6.0",
@ -93,6 +95,7 @@
"jsxhint": "^0.14.0", "jsxhint": "^0.14.0",
"minimist": "^1.1.1", "minimist": "^1.1.1",
"react-tools": "^0.13.1", "react-tools": "^0.13.1",
"run-sequence": "^1.0.2" "run-sequence": "^1.0.2",
"source-map-support": "^0.2.10"
} }
} }

View File

@ -6,7 +6,7 @@ var ContainerDetailsHeader = React.createClass({
if (!this.props.container) { if (!this.props.container) {
return false; return false;
} }
if (this.props.container.State.Running && !this.props.container.State.Paused && !this.props.container.State.Restarting) { if (this.props.container.State.Running && !this.props.container.State.Paused && !this.props.container.State.ExitCode && !this.props.container.State.Restarting) {
state = <span className="status running">RUNNING</span>; state = <span className="status running">RUNNING</span>;
} else if (this.props.container.State.Restarting) { } else if (this.props.container.State.Restarting) {
state = <span className="status restarting">RESTARTING</span>; state = <span className="status restarting">RESTARTING</span>;

View File

@ -54,6 +54,12 @@ var ContainerDetailsSubheader = React.createClass({
} }
return (this.props.container.State.Downloading || this.props.container.State.Restarting); return (this.props.container.State.Downloading || this.props.container.State.Restarting);
}, },
stopDisabled: function () {
if (!this.props.container) {
return false;
}
return (this.props.container.State.Downloading || this.props.container.State.ExitCode);
},
disableTerminal: function () { disableTerminal: function () {
if (!this.props.container) { if (!this.props.container) {
return false; return false;
@ -103,6 +109,13 @@ var ContainerDetailsSubheader = React.createClass({
}); });
} }
}, },
handleStop: function () {
if (!this.stopDisabled()) {
metrics.track('Stopped Container');
ContainerStore.stop(this.props.container.Name, function () {
});
}
},
handleTerminal: function () { handleTerminal: function () {
if (!this.disableTerminal()) { if (!this.disableTerminal()) {
metrics.track('Terminaled Into Container'); metrics.track('Terminaled Into Container');
@ -134,6 +147,14 @@ var ContainerDetailsSubheader = React.createClass({
var $action = $(this.getDOMNode()).find('.action .restart'); var $action = $(this.getDOMNode()).find('.action .restart');
$action.css("visibility", "hidden"); $action.css("visibility", "hidden");
}, },
handleItemMouseEnterStop: function () {
var $action = $(this.getDOMNode()).find('.action .stop');
$action.css("visibility", "visible");
},
handleItemMouseLeaveStop: function () {
var $action = $(this.getDOMNode()).find('.action .stop');
$action.css("visibility", "hidden");
},
handleItemMouseEnterTerminal: function () { handleItemMouseEnterTerminal: function () {
var $action = $(this.getDOMNode()).find('.action .terminal'); var $action = $(this.getDOMNode()).find('.action .terminal');
$action.css("visibility", "visible"); $action.css("visibility", "visible");
@ -151,6 +172,10 @@ var ContainerDetailsSubheader = React.createClass({
action: true, action: true,
disabled: this.disableRestart() disabled: this.disableRestart()
}); });
var stopActionClass = classNames({
action: true,
disabled: this.stopDisabled()
});
var terminalActionClass = classNames({ var terminalActionClass = classNames({
action: true, action: true,
disabled: this.disableTerminal() disabled: this.disableTerminal()
@ -181,6 +206,10 @@ var ContainerDetailsSubheader = React.createClass({
<div className="action-icon" onClick={this.handleRestart}><RetinaImage src="button-restart.png"/></div> <div className="action-icon" onClick={this.handleRestart}><RetinaImage src="button-restart.png"/></div>
<span className="btn-label restart">Restart</span> <span className="btn-label restart">Restart</span>
</div> </div>
<div className={stopActionClass} onMouseEnter={this.handleItemMouseEnterStop} onMouseLeave={this.handleItemMouseLeaveStop}>
<div className="action-icon" onClick={this.handleStop}><RetinaImage src="button-stop.png"/></div>
<span className="btn-label stop">Stop</span>
</div>
<div className={terminalActionClass} onMouseEnter={this.handleItemMouseEnterTerminal} onMouseLeave={this.handleItemMouseLeaveTerminal}> <div className={terminalActionClass} onMouseEnter={this.handleItemMouseEnterTerminal} onMouseLeave={this.handleItemMouseLeaveTerminal}>
<div className="action-icon" onClick={this.handleTerminal}><RetinaImage src="button-terminal.png"/></div> <div className="action-icon" onClick={this.handleTerminal}><RetinaImage src="button-terminal.png"/></div>
<span className="btn-label terminal">Terminal</span> <span className="btn-label terminal">Terminal</span>

View File

@ -402,6 +402,19 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), {
} }
}); });
}, },
stop: function (name, callback) {
var container = docker.client().getContainer(name);
_muted[name] = true;
container.stop(err => {
if (err && err.statusCode !== 304) {
_muted[name] = false;
callback(err);
} else {
_muted[name] = false;
this.fetchContainer(name, callback);
}
});
},
remove: function (name, callback) { remove: function (name, callback) {
if (_placeholders[name]) { if (_placeholders[name]) {
delete _placeholders[name]; delete _placeholders[name];

View File

@ -46,6 +46,10 @@
left: 2px; left: 2px;
//left: -18px; //left: -18px;
} }
&.stop {
left: 7px;
//left: -18px;
}
&.terminal { &.terminal {
left: -1px; left: -1px;
//left: -30px; //left: -30px;

14
util/prepare.js Normal file
View File

@ -0,0 +1,14 @@
require.requireActual('babel/polyfill');
require.requireActual('source-map-support').install({
retrieveSourceMap: function(filename) {
if (filename.indexOf('node_modules') === -1) {
try {
return {
map: require.requireActual('fs').readFileSync('/tmp/' + require('crypto').createHash('md5').update(filename).digest('hex') + '.map', 'utf8')
};
} catch (err) {
return undefined;
}
}
}
});

View File

@ -1,12 +1,14 @@
var babel = require('babel');
var fs = require('fs');
var crypto = require('crypto');
module.exports = { module.exports = {
process: function(src, filename) { process: function(src, filename) {
if (filename.indexOf('node_modules') === -1) { if (filename.indexOf('node_modules') !== -1) {
var res = require('babel').transform(src).code; return src;
if (filename.indexOf('-test') !== -1) {
res = 'require(\'babel/polyfill\');' + res;
}
return res;
} }
return src; var compiled = babel.transform(src, {filename: filename, sourceMap: true});
fs.writeFileSync('/tmp/' + crypto.createHash('md5').update(filename).digest('hex') + '.map', JSON.stringify(compiled.map));
return compiled.code;
} }
}; };