diff --git a/images/button-stop.png b/images/button-stop.png new file mode 100644 index 0000000000..14f88011b8 Binary files /dev/null and b/images/button-stop.png differ diff --git a/images/button-stop@2x.png b/images/button-stop@2x.png new file mode 100644 index 0000000000..3d20f5315a Binary files /dev/null and b/images/button-stop@2x.png differ diff --git a/src/components/ContainerDetailsHeader.react.js b/src/components/ContainerDetailsHeader.react.js index ded2816d5e..016bb01287 100644 --- a/src/components/ContainerDetailsHeader.react.js +++ b/src/components/ContainerDetailsHeader.react.js @@ -6,7 +6,7 @@ var ContainerDetailsHeader = React.createClass({ if (!this.props.container) { 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 = RUNNING; } else if (this.props.container.State.Restarting) { state = RESTARTING; diff --git a/src/components/ContainerDetailsSubheader.react.js b/src/components/ContainerDetailsSubheader.react.js index 36e5fa25d3..9023208e13 100644 --- a/src/components/ContainerDetailsSubheader.react.js +++ b/src/components/ContainerDetailsSubheader.react.js @@ -54,6 +54,12 @@ var ContainerDetailsSubheader = React.createClass({ } return (this.props.container.State.Downloading || this.props.container.State.Restarting); }, + disableStop: function () { + if (!this.props.container) { + return false; + } + return (this.props.container.State.Downloading || this.props.container.State.ExitCode); + }, disableTerminal: function () { if (!this.props.container) { return false; @@ -103,6 +109,13 @@ var ContainerDetailsSubheader = React.createClass({ }); } }, + handleStop: function () { + if (!this.disableStop()) { + metrics.track('Stopped Container'); + ContainerStore.stop(this.props.container.Name, function () { + }); + } + }, handleTerminal: function () { if (!this.disableTerminal()) { metrics.track('Terminaled Into Container'); @@ -134,6 +147,14 @@ var ContainerDetailsSubheader = React.createClass({ var $action = $(this.getDOMNode()).find('.action .restart'); $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 () { var $action = $(this.getDOMNode()).find('.action .terminal'); $action.css("visibility", "visible"); @@ -151,6 +172,10 @@ var ContainerDetailsSubheader = React.createClass({ action: true, disabled: this.disableRestart() }); + var stopActionClass = classNames({ + action: true, + disabled: this.disableStop() + }); var terminalActionClass = classNames({ action: true, disabled: this.disableTerminal() @@ -181,6 +206,10 @@ var ContainerDetailsSubheader = React.createClass({
Restart +
+
+ Stop +
Terminal diff --git a/src/stores/ContainerStore.js b/src/stores/ContainerStore.js index 81715a5a16..080684cec4 100644 --- a/src/stores/ContainerStore.js +++ b/src/stores/ContainerStore.js @@ -398,6 +398,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) { if (_placeholders[name]) { delete _placeholders[name];