diff --git a/package.json b/package.json
index fcc00df32d..2fc733d444 100644
--- a/package.json
+++ b/package.json
@@ -65,12 +65,15 @@
"bugsnag-js": "^2.4.7",
"classnames": "^1.2.0",
"coveralls": "^2.11.2",
+ "deep-extend": "^0.4.0",
"dockerode": "^2.1.1",
"exec": "0.2.0",
+ "install": "^0.1.8",
"jquery": "^2.1.3",
"mixpanel": "0.2.0",
"mkdirp": "^0.5.0",
"node-uuid": "^1.4.3",
+ "npm": "^2.9.1",
"object-assign": "^2.0.0",
"parseUri": "^1.2.3-2",
"react": "^0.13.1",
diff --git a/src/actions/ContainerActions.js b/src/actions/ContainerActions.js
index 07f75167e9..e5fd4e1dae 100644
--- a/src/actions/ContainerActions.js
+++ b/src/actions/ContainerActions.js
@@ -1,7 +1,7 @@
import alt from '../alt';
import dockerUtil from '../utils/DockerUtil';
-class ContainerServerActions {
+class ContainerActions {
start (name) {
this.dispatch({name});
dockerUtil.start(name);
@@ -12,7 +12,6 @@ class ContainerServerActions {
dockerUtil.destroy(name);
}
- // TODO: don't require all container data for this method
rename (name, newName) {
this.dispatch({name, newName});
dockerUtil.rename(name, newName);
@@ -24,7 +23,7 @@ class ContainerServerActions {
}
update (name, container) {
- this.dispatch({container});
+ this.dispatch({name, container});
dockerUtil.updateContainer(name, container);
}
@@ -37,4 +36,4 @@ class ContainerServerActions {
}
}
-export default alt.createActions(ContainerServerActions);
+export default alt.createActions(ContainerActions);
diff --git a/src/actions/ContainerServerActions.js b/src/actions/ContainerServerActions.js
index 3bc0d29ce6..bbbf9c82ff 100644
--- a/src/actions/ContainerServerActions.js
+++ b/src/actions/ContainerServerActions.js
@@ -8,9 +8,10 @@ class ContainerServerActions {
'destroyed',
'error',
'muted',
- 'unmuted',
- 'progress',
'pending',
+ 'progress',
+ 'started',
+ 'unmuted',
'updated',
'waiting'
);
diff --git a/src/components/ContainerDetails.react.js b/src/components/ContainerDetails.react.js
index 58cf2fb628..793de1cbd2 100644
--- a/src/components/ContainerDetails.react.js
+++ b/src/components/ContainerDetails.react.js
@@ -12,14 +12,19 @@ var ContainerDetails = React.createClass({
},
render: function () {
+ if (!this.props.container) {
+ return false;
+ }
+
let ports = containerUtil.ports(this.props.container);
let defaultPort = _.find(_.keys(ports), port => {
return util.webPorts.indexOf(port) !== -1;
});
+
return (
-
+
);
diff --git a/src/components/ContainerDetailsHeader.react.js b/src/components/ContainerDetailsHeader.react.js
index abb2009645..adbf2d2326 100644
--- a/src/components/ContainerDetailsHeader.react.js
+++ b/src/components/ContainerDetailsHeader.react.js
@@ -7,7 +7,9 @@ var ContainerDetailsHeader = React.createClass({
return false;
}
- if (this.props.container.State.Running && !this.props.container.State.Paused && !this.props.container.State.ExitCode && !this.props.container.State.Restarting) {
+ if (this.props.container.State.Updating) {
+ state = UPDATING;
+ } else 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 efce15965c..9b4cda575f 100644
--- a/src/components/ContainerDetailsSubheader.react.js
+++ b/src/components/ContainerDetailsSubheader.react.js
@@ -20,31 +20,31 @@ var ContainerDetailsSubheader = React.createClass({
if (!this.props.container) {
return false;
}
- return (!this.props.container.State.Running || !this.props.defaultPort);
+ return (!this.props.container.State.Running || !this.props.defaultPort || this.props.container.State.Updating);
},
disableRestart: function () {
if (!this.props.container) {
return false;
}
- return (this.props.container.State.Downloading || this.props.container.State.Restarting);
+ return (this.props.container.State.Downloading || this.props.container.State.Restarting || this.props.container.State.Updating);
},
disableStop: function () {
if (!this.props.container) {
return false;
}
- return (this.props.container.State.Downloading || this.props.container.State.ExitCode || !this.props.container.State.Running);
+ return (this.props.container.State.Downloading || this.props.container.State.ExitCode || !this.props.container.State.Running || this.props.container.State.Updating);
},
disableStart: function () {
if (!this.props.container) {
return false;
}
- return (this.props.container.State.Downloading || this.props.container.State.Running);
+ return (this.props.container.State.Downloading || this.props.container.State.Running || this.props.container.State.Updating);
},
disableTerminal: function () {
if (!this.props.container) {
return false;
}
- return (!this.props.container.State.Running);
+ return (!this.props.container.State.Running || this.props.container.State.Updating);
},
disableTab: function () {
if (!this.props.container) {
diff --git a/src/components/ContainerHome.react.js b/src/components/ContainerHome.react.js
index 45ffec576b..08016322d1 100644
--- a/src/components/ContainerHome.react.js
+++ b/src/components/ContainerHome.react.js
@@ -35,12 +35,16 @@ var ContainerHome = React.createClass({
},
render: function () {
+ if (!this.props.container) {
+ return;
+ }
+
let body;
- if (this.props.error) {
+ if (this.props.container.Error) {
body = (
An error occurred:
-
{this.props.error.statusCode} {this.props.error.reason} - {this.props.error.json}
+
{this.props.container.Error.message}
diff --git a/src/components/ContainerHomeLogs.react.js b/src/components/ContainerHomeLogs.react.js
index 40d3fede58..f8d7ac4570 100644
--- a/src/components/ContainerHomeLogs.react.js
+++ b/src/components/ContainerHomeLogs.react.js
@@ -22,6 +22,14 @@ module.exports = React.createClass({
LogStore.on(LogStore.SERVER_LOGS_EVENT, this.update);
LogStore.fetch(this.props.container.Name);
},
+
+ componentWillReceiveProps: function (nextProps) {
+ if (this.props.container && nextProps.container && this.props.container.Name !== nextProps.container.Name) {
+ LogStore.detach(this.props.container.Name);
+ LogStore.fetch(nextProps.container.Name);
+ }
+ },
+
componentWillUnmount: function() {
if (!this.props.container) {
return;
diff --git a/src/components/ContainerSettingsGeneral.react.js b/src/components/ContainerSettingsGeneral.react.js
index f2a910e0ea..f07439bfbb 100644
--- a/src/components/ContainerSettingsGeneral.react.js
+++ b/src/components/ContainerSettingsGeneral.react.js
@@ -16,7 +16,6 @@ var ContainerSettingsGeneral = React.createClass({
getInitialState: function () {
let env = ContainerUtil.env(this.props.container) || [];
env.push(['', '']);
- console.log(env);
return {
slugName: null,
nameError: null,
@@ -28,9 +27,7 @@ var ContainerSettingsGeneral = React.createClass({
if (nextState.slugName !== this.state.slugName || nextState.nameError !== this.state.nameError) {
return true;
}
- if (nextState.env.length === this.state.env.length) {
- return false;
- }
+
return true;
},
@@ -195,7 +192,7 @@ var ContainerSettingsGeneral = React.createClass({
}
return (
-
+
Delete Container
diff --git a/src/components/ContainerSettingsVolumes.react.js b/src/components/ContainerSettingsVolumes.react.js
index 4aa87f4350..5ccd5e4f32 100644
--- a/src/components/ContainerSettingsVolumes.react.js
+++ b/src/components/ContainerSettingsVolumes.react.js
@@ -22,7 +22,7 @@ var ContainerSettingsVolumes = React.createClass({
return pair[1] + ':' + pair[0];
});
- containerActions.update(this.props.container.Name, {Binds: binds});
+ containerActions.update(this.props.container.Name, {Binds: binds, Volumes: volumes});
}
});
},
@@ -35,7 +35,7 @@ var ContainerSettingsVolumes = React.createClass({
var binds = _.pairs(volumes).map(function (pair) {
return pair[1] + ':' + pair[0];
});
- containerActions.update(this.props.container.Name, {Binds: binds});
+ containerActions.update(this.props.container.Name, {Binds: binds, Volumes: volumes});
},
handleOpenVolumeClick: function (path) {
metrics.track('Opened Volume Directory', {
@@ -45,24 +45,24 @@ var ContainerSettingsVolumes = React.createClass({
},
render: function () {
if (!this.props.container) {
- return (
);
+ return false;
}
- var self = this;
- var volumes = _.map(self.props.container.Volumes, function (val, key) {
+
+ var volumes = _.map(this.props.container.Volumes, (val, key) => {
if (!val || val.indexOf(process.env.HOME) === -1) {
val = (
No Folder
- Change
- Remove
+ Change
+ Remove
);
} else {
val = (
- {val.replace(process.env.HOME, '~')}
- Change
- Remove
+ {val.replace(process.env.HOME, '~')}
+ Change
+ Remove
);
}
diff --git a/src/components/Containers.react.js b/src/components/Containers.react.js
index a5829d82ce..03319d7d20 100644
--- a/src/components/Containers.react.js
+++ b/src/components/Containers.react.js
@@ -195,7 +195,7 @@ var Containers = React.createClass({
-
+
);
diff --git a/src/stores/ContainerStore.js b/src/stores/ContainerStore.js
index ddb8a9d676..d3b63099a0 100644
--- a/src/stores/ContainerStore.js
+++ b/src/stores/ContainerStore.js
@@ -1,4 +1,5 @@
import _ from 'underscore';
+import deepExtend from 'deep-extend';
import alt from '../alt';
import containerServerActions from '../actions/ContainerServerActions';
import containerActions from '../actions/ContainerActions';
@@ -9,13 +10,18 @@ class ContainerStore {
this.bindActions(containerServerActions);
this.containers = {};
- // Blacklist of containers to avoid updating
- this.muted = {};
-
// Pending container to create
this.pending = null;
}
+ error ({name, error}) {
+ let containers = this.containers;
+ if (containers[name]) {
+ containers[name].Error = error;
+ }
+ this.setState({containers});
+ }
+
start ({name}) {
let containers = this.containers;
if (containers[name]) {
@@ -24,6 +30,15 @@ class ContainerStore {
}
}
+ started ({name}) {
+ let containers = this.containers;
+ if (containers[name]) {
+ containers[name].State.Starting = false;
+ containers[name].State.Updating = false;
+ this.setState({containers});
+ }
+ }
+
stop ({name}) {
let containers = this.containers;
if (containers[name]) {
@@ -36,6 +51,11 @@ class ContainerStore {
let containers = this.containers;
let data = containers[name];
data.Name = newName;
+
+ if (data.State) {
+ data.State.Updating = true;
+ }
+
containers[newName] = data;
delete containers[name];
this.setState({containers});
@@ -44,23 +64,32 @@ class ContainerStore {
added ({container}) {
let containers = this.containers;
containers[container.Name] = container;
- delete this.muted[container.Name];
+ this.setState({containers});
+ }
+
+ update ({name, container}) {
+ let containers = this.containers;
+ if (containers[name] && containers[name].State && containers[name].State.Updating) {
+ return;
+ }
+
+ deepExtend(containers[name], container);
+
+ if (containers[name].State) {
+ containers[name].State.Updating = true;
+ }
+
this.setState({containers});
}
updated ({container}) {
- if (this.muted[container.Name]) {
+ let containers = this.containers;
+ if (!containers[container.Name] || containers[container.Name].State.Updating) {
return;
}
- let containers = this.containers;
- if (!containers[container.Name]) {
- return;
- }
containers[container.Name] = container;
- if (container.State.Running) {
- delete container.State.Starting;
- }
+
this.setState({containers});
}
@@ -87,20 +116,17 @@ class ContainerStore {
let container = _.find(_.values(this.containers), container => {
return container.Id === name || container.Name === name;
});
- if (container && !this.muted[container.Name]) {
+
+ if (container && container.State && container.State.Updating) {
+ return;
+ }
+
+ if (container) {
delete containers[container.Name];
this.setState({containers});
}
}
- muted ({name}) {
- this.muted[name] = true;
- }
-
- unmuted ({name}) {
- this.muted[name] = false;
- }
-
waiting({name, waiting}) {
let containers = this.containers;
if (containers[name]) {
@@ -109,14 +135,6 @@ class ContainerStore {
this.setState({containers});
}
- error ({name, error}) {
- let containers = this.containers;
- if (containers[name]) {
- containers[name].Error = error;
- }
- this.setState({containers});
- }
-
pending ({repo, tag}) {
let pending = {repo, tag};
this.setState({pending});
@@ -127,10 +145,10 @@ class ContainerStore {
}
static generateName (repo) {
- let base = _.last(repo.split('/'));
- let count = 1;
- let name = base;
- let names = _.keys(this.getState().containers);
+ const base = _.last(repo.split('/'));
+ const names = _.keys(this.getState().containers);
+ var count = 1;
+ var name = base;
while (true) {
if (names.indexOf(name) === -1) {
return name;
diff --git a/src/utils/DockerUtil.js b/src/utils/DockerUtil.js
index 99e925687d..a2f107d619 100644
--- a/src/utils/DockerUtil.js
+++ b/src/utils/DockerUtil.js
@@ -79,7 +79,7 @@ export default {
containerServerActions.error({name, error});
return;
}
- containerServerActions.unmuted({name});
+ containerServerActions.started({name, error});
this.fetchContainer(name);
});
},
@@ -184,9 +184,6 @@ export default {
updateContainer (name, data) {
let existing = this.client.getContainer(name);
existing.inspect((error, existingData) => {
- if (error) {
- return;
- }
if (error) {
containerServerActions.error({name, error});
return;
@@ -202,7 +199,6 @@ export default {
}
var fullData = _.extend(existingData, data);
- containerServerActions.muted({name});
this.createContainer(name, fullData);
});
},
@@ -213,7 +209,6 @@ export default {
containerServerActions.error({name, error});
return;
}
- this.fetchAllContainers();
var oldPath = path.join(util.home(), 'Kitematic', name);
var newPath = path.join(util.home(), 'Kitematic', newName);
@@ -223,7 +218,6 @@ export default {
containerServerActions.error({newName, error});
}
rimraf(newPath, () => {
- console.log('removed');
if (fs.existsSync(oldPath)) {
fs.renameSync(oldPath, newPath);
}
@@ -295,9 +289,7 @@ export default {
containerServerActions.destroyed({id: name});
var volumePath = path.join(util.home(), 'Kitematic', name);
if (fs.existsSync(volumePath)) {
- rimraf(volumePath, function (err) {
- console.log(err);
- });
+ rimraf(volumePath, () => {});
}
});
});