@@ -116,12 +81,12 @@ var ContainerHome = React.createClass({
);
}
} else {
- if (this.state.defaultPort) {
+ if (this.props.defaultPort) {
body = (
-
+
@@ -132,7 +97,7 @@ var ContainerHome = React.createClass({
);
} else {
var right;
- if (_.keys(this.state.ports) > 0) {
+ if (_.keys(this.props.ports) > 0) {
right = (
diff --git a/src/components/ContainerHomeFolders.react.js b/src/components/ContainerHomeFolders.react.js
index db5095f23e..4f769ce766 100644
--- a/src/components/ContainerHomeFolders.react.js
+++ b/src/components/ContainerHomeFolders.react.js
@@ -5,8 +5,9 @@ var path = require('path');
var shell = require('shell');
var util = require('../utils/Util');
var metrics = require('../utils/MetricsUtil');
-var ContainerStore = require('../stores/ContainerStore');
+var containerActions = require('../actions/ContainerActions');
var dialog = require('remote').require('dialog');
+var mkdirp = require('mkdirp');
var ContainerHomeFolder = React.createClass({
contextTypes: {
@@ -37,15 +38,14 @@ var ContainerHomeFolder = React.createClass({
}
return pair[1] + ':' + pair[0];
});
- ContainerStore.updateContainer(this.props.container.Name, {
- Binds: binds
- }, (err) => {
- if (err) {
- console.log(err);
- return;
+ mkdirp(newHostVolume, function (err) {
+ console.log(err);
+ if (!err) {
+ shell.showItemInFolder(newHostVolume);
}
- shell.showItemInFolder(newHostVolume);
});
+
+ containerActions.update(this.props.container.Name, {Binds: binds});
}
});
} else {
diff --git a/src/components/ContainerHomePreview.react.js b/src/components/ContainerHomePreview.react.js
index 1d1ac925a8..116b6d5b89 100644
--- a/src/components/ContainerHomePreview.react.js
+++ b/src/components/ContainerHomePreview.react.js
@@ -1,28 +1,14 @@
var _ = require('underscore');
var React = require('react/addons');
-var ContainerStore = require('../stores/ContainerStore');
-var ContainerUtil = require('../utils/ContainerUtil');
var request = require('request');
var shell = require('shell');
var metrics = require('../utils/MetricsUtil');
-var webPorts = require('../utils/Util').webPorts;
var ContainerHomePreview = React.createClass({
contextTypes: {
router: React.PropTypes.func
},
- getInitialState: function () {
- return {
- ports: {},
- defaultPort: null
- };
- },
- componentWillReceiveProps: function () {
- this.init();
- },
- componentDidMount: function() {
- this.init();
- },
+
reload: function () {
var webview = document.getElementById('webview');
if (webview) {
@@ -38,40 +24,31 @@ var ContainerHomePreview = React.createClass({
});
}
},
+
componentWillUnmount: function() {
clearInterval(this.timer);
},
- init: function () {
- var container = ContainerStore.container(this.context.router.getCurrentParams().name);
- if (!container) {
- return;
- }
- var ports = ContainerUtil.ports(container);
- this.setState({
- ports: ports,
- defaultPort: _.find(_.keys(ports), function (port) {
- return webPorts.indexOf(port) !== -1;
- })
- });
- },
+
handleClickPreview: function () {
- if (this.state.defaultPort) {
+ if (this.props.defaultPort) {
metrics.track('Opened In Browser', {
from: 'preview'
});
- shell.openExternal(this.state.ports[this.state.defaultPort].url);
+ shell.openExternal(this.props.ports[this.props.defaultPort].url);
}
},
+
handleClickNotShowingCorrectly: function () {
metrics.track('Viewed Port Settings', {
from: 'preview'
});
this.context.router.transitionTo('containerSettingsPorts', {name: this.context.router.getCurrentParams().name});
},
+
render: function () {
var preview;
- if (this.state.defaultPort) {
- var frame = React.createElement('webview', {className: 'frame', id: 'webview', src: this.state.ports[this.state.defaultPort].url, autosize: 'on'});
+ if (this.props.defaultPort) {
+ var frame = React.createElement('webview', {className: 'frame', id: 'webview', src: this.props.ports[this.props.defaultPort].url, autosize: 'on'});
preview = (
Web Preview
@@ -83,7 +60,7 @@ var ContainerHomePreview = React.createClass({
);
} else {
- var ports = _.map(_.pairs(this.state.ports), function (pair) {
+ var ports = _.map(_.pairs(this.props.ports), function (pair) {
var key = pair[0];
var val = pair[1];
return (
diff --git a/src/components/ContainerList.react.js b/src/components/ContainerList.react.js
index 1e6f358d6d..7ff8504b3f 100644
--- a/src/components/ContainerList.react.js
+++ b/src/components/ContainerList.react.js
@@ -4,19 +4,12 @@ var ContainerListNewItem = require('./ContainerListNewItem.react');
var ContainerList = React.createClass({
componentWillMount: function () {
- this._start = Date.now();
+ this.start = Date.now();
},
render: function () {
- var self = this;
- var containers = this.props.containers.map(function (container) {
- var containerId = container.Id;
- if (!containerId && container.State.Downloading) {
- // Fall back to the container image name when there is no id. (when the
- // image is downloading).
- containerId = container.Image;
- }
+ var containers = this.props.containers.map(container => {
return (
-
+
);
});
return (
diff --git a/src/components/ContainerListItem.react.js b/src/components/ContainerListItem.react.js
index 827a1abb9c..b8c07387af 100644
--- a/src/components/ContainerListItem.react.js
+++ b/src/components/ContainerListItem.react.js
@@ -4,9 +4,9 @@ var Router = require('react-router');
var remote = require('remote');
var dialog = remote.require('dialog');
var metrics = require('../utils/MetricsUtil');
-var ContainerStore = require('../stores/ContainerStore');
var OverlayTrigger = require('react-bootstrap').OverlayTrigger;
var Tooltip = require('react-bootstrap').Tooltip;
+var containerActions = require('../actions/ContainerActions');
var ContainerListItem = React.createClass({
handleItemMouseEnter: function () {
@@ -29,12 +29,7 @@ var ContainerListItem = React.createClass({
from: 'list',
type: 'existing'
});
- ContainerStore.remove(this.props.container.Name, () => {
- var containers = ContainerStore.sorted();
- if (containers.length === 0) {
- $(document.body).find('.new-container-item').parent().fadeIn();
- }
- });
+ containerActions.destroy(this.props.container.Name);
}
}.bind(this));
},
@@ -56,7 +51,7 @@ var ContainerListItem = React.createClass({
// Synchronize all animations
var style = {
- WebkitAnimationDelay: (self.props.start - Date.now()) + 'ms'
+ WebkitAnimationDelay: 0 + 'ms'
};
var state;
@@ -101,7 +96,7 @@ var ContainerListItem = React.createClass({
}
return (
-
+
{state}
diff --git a/src/components/ContainerSettings.react.js b/src/components/ContainerSettings.react.js
index 7a25dd73ae..856b1fccc9 100644
--- a/src/components/ContainerSettings.react.js
+++ b/src/components/ContainerSettings.react.js
@@ -45,7 +45,7 @@ var ContainerSettings = React.createClass({
-
+
);
diff --git a/src/components/ContainerSettingsGeneral.react.js b/src/components/ContainerSettingsGeneral.react.js
index 4fad44b149..11798c4b3c 100644
--- a/src/components/ContainerSettingsGeneral.react.js
+++ b/src/components/ContainerSettingsGeneral.react.js
@@ -1,80 +1,61 @@
var _ = require('underscore');
var $ = require('jquery');
var React = require('react/addons');
-var path = require('path');
var remote = require('remote');
-var rimraf = require('rimraf');
-var fs = require('fs');
var metrics = require('../utils/MetricsUtil');
var dialog = remote.require('dialog');
-var ContainerStore = require('../stores/ContainerStore');
var ContainerUtil = require('../utils/ContainerUtil');
-
-var containerNameSlugify = function (text) {
- text = text.replace(/^\s+|\s+$/g, ''); // Trim
- text = text.toLowerCase();
- // Remove Accents
- var from = "àáäâèéëêìíïîòóöôùúüûñç·/,:;";
- var to = "aaaaeeeeiiiioooouuuunc-----";
- for (var i=0, l=from.length ; i
{
- if (err) {
- this.setState({
- nameError: err.message
- });
- return;
- }
- metrics.track('Changed Container Name');
- this.context.router.transitionTo('containerSettingsGeneral', {name: newName});
- var oldPath = path.join(process.env.HOME, 'Kitematic', oldName);
- var newPath = path.join(process.env.HOME, 'Kitematic', newName);
- rimraf(newPath, () => {
- if (fs.existsSync(oldPath)) {
- fs.renameSync(oldPath, newPath);
- }
- var binds = _.pairs(this.props.container.Volumes).map(function (pair) {
- return pair[1] + ':' + pair[0];
- });
- var newBinds = binds.map(b => {
- return b.replace(path.join(process.env.HOME, 'Kitematic', oldName), path.join(process.env.HOME, 'Kitematic', newName));
- });
- ContainerStore.updateContainer(newName, {Binds: newBinds}, err => {
- rimraf(oldPath, () => {});
- if (err) {
- console.log(err);
- }
- });
- });
- });
+
+ containerActions.rename(this.props.container.Name, newName);
+ this.context.router.transitionTo('containerSettingsGeneral', {name: newName});
+ metrics.track('Changed Container Name');
},
+
handleSaveEnvVar: function () {
var $rows = $('.env-vars .keyval-row');
var envVarList = [];
@@ -132,22 +89,10 @@ var ContainerSettingsGeneral = React.createClass({
}
envVarList.push(key + '=' + val);
});
- var self = this;
metrics.track('Saved Environment Variables');
- ContainerStore.updateContainer(self.props.container.Name, {
- Env: envVarList
- }, function (err) {
- if (err) {
- console.error(err);
- } else {
- self.setState({
- pendingEnv: {}
- });
- $('#new-env-key').val('');
- $('#new-env-val').val('');
- }
- });
+ containerActions.update(this.props.container.Name, {Env: envVarList});
},
+
handleAddPendingEnvVar: function () {
var newKey = $('#new-env-key').val();
var newVal = $('#new-env-val').val();
@@ -160,42 +105,30 @@ var ContainerSettingsGeneral = React.createClass({
$('#new-env-val').val('');
metrics.track('Added Pending Environment Variable');
},
- handleRemoveEnvVar: function (key) {
+
+ handleRemovePendingEnvVar: function (key) {
var newEnv = _.omit(this.state.env, key);
this.setState({
env: newEnv
});
metrics.track('Removed Environment Variable');
},
- handleRemovePendingEnvVar: function (key) {
- var newEnv = _.omit(this.state.pendingEnv, key);
- this.setState({
- pendingEnv: newEnv
- });
- metrics.track('Removed Pending Environment Variable');
- },
+
handleDeleteContainer: function () {
dialog.showMessageBox({
message: 'Are you sure you want to delete this container?',
buttons: ['Delete', 'Cancel']
- }, function (index) {
- var volumePath = path.join(process.env.HOME, 'Kitematic', this.props.container.Name);
- if (fs.existsSync(volumePath)) {
- rimraf(volumePath, function (err) {
- console.log(err);
- });
- }
+ }, index => {
if (index === 0) {
metrics.track('Deleted Container', {
from: 'settings',
type: 'existing'
});
- ContainerStore.remove(this.props.container.Name, function (err) {
- console.error(err);
- });
+ containerActions.destroy(this.props.container.Name);
}
- }.bind(this));
+ });
},
+
render: function () {
if (!this.props.container) {
return ();
@@ -226,22 +159,12 @@ var ContainerSettingsGeneral = React.createClass({
{btnSaveName}
);
- var self = this;
- var envVars = _.map(this.state.env, function (val, key) {
+ var pendingEnvVars = _.map(this.state.pendingEnv, (val, key) => {
return (
- );
- });
- var pendingEnvVars = _.map(this.state.pendingEnv, function (val, key) {
- return (
-
);
});
@@ -255,7 +178,6 @@ var ContainerSettingsGeneral = React.createClass({
VALUE
- {envVars}
{pendingEnvVars}
diff --git a/src/components/ContainerSettingsPorts.react.js b/src/components/ContainerSettingsPorts.react.js
index 1992763a4f..c266384d94 100644
--- a/src/components/ContainerSettingsPorts.react.js
+++ b/src/components/ContainerSettingsPorts.react.js
@@ -1,7 +1,6 @@
var _ = require('underscore');
var React = require('react/addons');
var shell = require('shell');
-var ContainerStore = require('../stores/ContainerStore');
var ContainerUtil = require('../utils/ContainerUtil');
var metrics = require('../utils/MetricsUtil');
var webPorts = require('../utils/Util').webPorts;
@@ -16,18 +15,11 @@ var ContainerSettingsPorts = React.createClass({
defaultPort: null
};
},
- componentWillReceiveProps: function () {
- this.init();
- },
componentDidMount: function() {
- this.init();
- },
- init: function () {
- var container = ContainerStore.container(this.context.router.getCurrentParams().name);
- if (!container) {
+ if (!this.props.container) {
return;
}
- var ports = ContainerUtil.ports(container);
+ var ports = ContainerUtil.ports(this.props.container);
this.setState({
ports: ports,
defaultPort: _.find(_.keys(ports), function (port) {
diff --git a/src/components/Containers.react.js b/src/components/Containers.react.js
index 25e603c5f1..9b6c525b80 100644
--- a/src/components/Containers.react.js
+++ b/src/components/Containers.react.js
@@ -1,7 +1,8 @@
var $ = require('jquery');
+var _ = require('underscore');
var React = require('react/addons');
var Router = require('react-router');
-var ContainerStore = require('../stores/ContainerStore');
+var containerStore = require('../stores/ContainerStore');
var ContainerList = require('./ContainerList.react');
var Header = require('./Header.react');
var ipc = require('ipc');
@@ -16,22 +17,19 @@ var Containers = React.createClass({
contextTypes: {
router: React.PropTypes.func
},
+
getInitialState: function () {
return {
sidebarOffset: 0,
- containers: ContainerStore.containers(),
- sorted: ContainerStore.sorted(),
+ containers: {},
+ sorted: [],
updateAvailable: false,
- currentButtonLabel: '',
- error: ContainerStore.error(),
- downloading: ContainerStore.downloading()
+ currentButtonLabel: ''
};
},
+
componentDidMount: function () {
- this.update();
- ContainerStore.on(ContainerStore.SERVER_ERROR_EVENT, this.updateError);
- ContainerStore.on(ContainerStore.SERVER_CONTAINER_EVENT, this.update);
- ContainerStore.on(ContainerStore.CLIENT_CONTAINER_EVENT, this.updateFromClient);
+ containerStore.listen(this.update);
ipc.on('application:update-available', () => {
this.setState({
@@ -40,41 +38,44 @@ var Containers = React.createClass({
});
autoUpdater.checkForUpdates();
},
+
componentDidUnmount: function () {
- ContainerStore.removeListener(ContainerStore.SERVER_CONTAINER_EVENT, this.update);
- ContainerStore.removeListener(ContainerStore.CLIENT_CONTAINER_EVENT, this.updateFromClient);
+ containerStore.unlisten(this.update);
},
- updateError: function (err) {
- this.setState({
- error: err
+
+ update: function () {
+ let containers = containerStore.getState().containers;
+ let sorted = _.values(containers).sort(function (a, b) {
+ if (a.State.Downloading && !b.State.Downloading) {
+ return -1;
+ } else if (!a.State.Downloading && b.State.Downloading) {
+ return 1;
+ } else {
+ if (a.State.Running && !b.State.Running) {
+ return -1;
+ } else if (!a.State.Running && b.State.Running) {
+ return 1;
+ } else {
+ return a.Name.localeCompare(b.Name);
+ }
+ }
});
- },
- update: function (name, status) {
- var sorted = ContainerStore.sorted();
- this.setState({
- containers: ContainerStore.containers(),
- sorted: sorted,
- pending: ContainerStore.pending(),
- downloading: ContainerStore.downloading()
- });
- if (status === 'destroy') {
+
+ let name = this.context.router.getCurrentParams().name;
+ if (name && !containers[name]) {
if (sorted.length) {
this.context.router.transitionTo('containerHome', {name: sorted[0].Name});
} else {
- this.context.router.transitionTo('containers');
+ this.context.router.transitionTo('search');
}
}
+
+ this.setState({
+ containers: containers,
+ sorted: sorted
+ });
},
- updateFromClient: function (name, status) {
- this.update(name, status);
- if (status === 'create') {
- this.context.router.transitionTo('containerHome', {name: name});
- } else if (status === 'pending' && ContainerStore.pending()) {
- this.context.router.transitionTo('pull');
- } else if (status === 'destroy') {
- this.onDestroy();
- }
- },
+
handleScroll: function (e) {
if (e.target.scrollTop > 0 && !this.state.sidebarOffset) {
this.setState({
@@ -86,63 +87,75 @@ var Containers = React.createClass({
});
}
},
+
handleNewContainer: function () {
$(this.getDOMNode()).find('.new-container-item').parent().fadeIn();
this.context.router.transitionTo('new');
metrics.track('Pressed New Container');
},
+
handleAutoUpdateClick: function () {
metrics.track('Restarted to Update');
ipc.send('application:quit-install');
},
+
handleClickPreferences: function () {
metrics.track('Opened Preferences', {
from: 'app'
});
this.context.router.transitionTo('preferences');
},
+
handleClickDockerTerminal: function () {
metrics.track('Opened Docker Terminal', {
from: 'app'
});
machine.dockerTerminal();
},
+
handleClickReportIssue: function () {
metrics.track('Opened Issue Reporter', {
from: 'app'
});
shell.openExternal('https://github.com/kitematic/kitematic/issues/new');
},
+
handleMouseEnterDockerTerminal: function () {
this.setState({
currentButtonLabel: 'Open terminal to use Docker command line.'
});
},
+
handleMouseLeaveDockerTerminal: function () {
this.setState({
currentButtonLabel: ''
});
},
+
handleMouseEnterReportIssue: function () {
this.setState({
currentButtonLabel: 'Report an issue or suggest feedback.'
});
},
+
handleMouseLeaveReportIssue: function () {
this.setState({
currentButtonLabel: ''
});
},
+
handleMouseEnterPreferences: function () {
this.setState({
currentButtonLabel: 'Change app preferences.'
});
},
+
handleMouseLeavePreferences: function () {
this.setState({
currentButtonLabel: ''
});
},
+
render: function () {
var sidebarHeaderClass = 'sidebar-header';
if (this.state.sidebarOffset) {
@@ -168,7 +181,7 @@ var Containers = React.createClass({
-
+
{this.state.currentButtonLabel}
@@ -179,7 +192,7 @@ var Containers = React.createClass({
-
+