diff --git a/.jshintrc b/.jshintrc
index 9240a3ae9f..daeaf45072 100644
--- a/.jshintrc
+++ b/.jshintrc
@@ -27,5 +27,5 @@
"jest": true,
"pit": true
},
- "predef": [ "-Promise" ]
+ "predef": [ "Promise" ]
}
diff --git a/src/ContainerHomeFolders.react.js b/src/ContainerHomeFolders.react.js
index 2e3e796cc3..1ace6d4e90 100644
--- a/src/ContainerHomeFolders.react.js
+++ b/src/ContainerHomeFolders.react.js
@@ -7,7 +7,6 @@ var util = require('./Util');
var metrics = require('./Metrics');
var Router = require('react-router');
var ContainerStore = require('./ContainerStore');
-var dialog = require('remote').require('dialog');
var ContainerHomeFolder = React.createClass({
mixins: [Router.State, Router.Navigation],
@@ -17,27 +16,20 @@ var ContainerHomeFolder = React.createClass({
});
if (hostVolume.indexOf(process.env.HOME) === -1) {
- dialog.showMessageBox({
- message: 'Enable all volumes to edit files via Finder? This may not work with all database containers.',
- buttons: ['Enable Volumes', 'Cancel']
- }, (index) => {
- if (index === 0) {
- var volumes = _.clone(this.props.container.Volumes);
- var newHostVolume = path.join(util.home(), 'Kitematic', this.props.container.Name, containerVolume);
- volumes[containerVolume] = newHostVolume;
- var binds = _.pairs(volumes).map(function (pair) {
- return pair[1] + ':' + pair[0];
- });
- ContainerStore.updateContainer(this.props.container.Name, {
- Binds: binds
- }, (err) => {
- if (err) {
- console.log(err);
- return;
- }
- shell.showItemInFolder(newHostVolume);
- });
+ var volumes = _.clone(this.props.container.Volumes);
+ var newHostVolume = path.join(util.home(), 'Kitematic', this.props.container.Name, containerVolume);
+ volumes[containerVolume] = newHostVolume;
+ var binds = _.pairs(volumes).map(function (pair) {
+ return pair[1] + ':' + pair[0];
+ });
+ ContainerStore.updateContainer(this.props.container.Name, {
+ Binds: binds
+ }, function (err) {
+ if (err) {
+ console.log(err);
+ return;
}
+ shell.showItemInFolder(newHostVolume);
});
} else {
shell.showItemInFolder(hostVolume);
diff --git a/src/ContainerList.react.js b/src/ContainerList.react.js
index 1e6f358d6d..d2954dc603 100644
--- a/src/ContainerList.react.js
+++ b/src/ContainerList.react.js
@@ -19,9 +19,15 @@ var ContainerList = React.createClass({
);
});
+ var newItem;
+ if (!this.props.downloading) {
+ newItem = ;
+ } else {
+ newItem = '';
+ }
return (
-
+ {newItem}
{containers}
);
diff --git a/src/ContainerStore.js b/src/ContainerStore.js
index 262ddc6a57..109a022d19 100644
--- a/src/ContainerStore.js
+++ b/src/ContainerStore.js
@@ -14,7 +14,6 @@ var _progress = {};
var _muted = {};
var _blocked = {};
var _error = null;
-var _pending = null;
var ContainerStore = assign(Object.create(EventEmitter.prototype), {
CLIENT_CONTAINER_EVENT: 'client_container_event',
@@ -202,10 +201,6 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), {
var data = JSON.parse(json);
console.log(data);
- if (data.status === 'pull' || data.status === 'untag' || data.status === 'delete') {
- return;
- }
-
// If the event is delete, remove the container
if (data.status === 'destroy') {
var container = _.findWhere(_.values(_containers), {Id: data.id});
@@ -231,6 +226,7 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), {
}
},
init: function (callback) {
+ // TODO: Load cached data from db on loading
this.fetchAllContainers(err => {
if (err) {
_error = err;
@@ -475,20 +471,6 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), {
},
downloading: function () {
return !!_.keys(_placeholders).length;
- },
- pending: function () {
- return _pending;
- },
- setPending: function (repository, tag) {
- _pending = {
- repository: repository,
- tag: tag
- };
- this.emit(this.CLIENT_CONTAINER_EVENT, null, 'pending');
- },
- clearPending: function () {
- _pending = null;
- this.emit(this.CLIENT_CONTAINER_EVENT, null, 'pending');
}
});
diff --git a/src/Containers.react.js b/src/Containers.react.js
index ab613bb61a..af151dabca 100644
--- a/src/Containers.react.js
+++ b/src/Containers.react.js
@@ -10,6 +10,8 @@ var metrics = require('./Metrics');
var autoUpdater = remote.require('auto-updater');
var RetinaImage = require('react-retina-image');
var machine = require('./DockerMachine');
+var OverlayTrigger = require('react-bootstrap').OverlayTrigger;
+var Tooltip = require('react-bootstrap').Tooltip;
var util = require('./Util');
var Containers = React.createClass({
@@ -31,6 +33,10 @@ var Containers = React.createClass({
ContainerStore.on(ContainerStore.SERVER_CONTAINER_EVENT, this.update);
ContainerStore.on(ContainerStore.CLIENT_CONTAINER_EVENT, this.updateFromClient);
+ if (this.state.sorted.length) {
+ this.transitionTo('containerHome', {name: this.state.sorted[0].Name});
+ }
+
ipc.on('application:update-available', () => {
this.setState({
updateAvailable: true
@@ -42,33 +48,38 @@ var Containers = React.createClass({
ContainerStore.removeListener(ContainerStore.SERVER_CONTAINER_EVENT, this.update);
ContainerStore.removeListener(ContainerStore.CLIENT_CONTAINER_EVENT, this.updateFromClient);
},
+ onDestroy: function () {
+ if (this.state.sorted.length) {
+ this.transitionTo('containerHome', {name: this.state.sorted[0].Name});
+ } else {
+ this.transitionTo('containers');
+ }
+ },
updateError: function (err) {
this.setState({
error: err
});
},
update: function (name, status) {
- var sorted = ContainerStore.sorted();
this.setState({
containers: ContainerStore.containers(),
- sorted: sorted,
- pending: ContainerStore.pending(),
+ sorted: ContainerStore.sorted(),
downloading: ContainerStore.downloading()
});
if (status === 'destroy') {
- if (sorted.length) {
- this.transitionTo('containerHome', {name: sorted[0].Name});
- } else {
- this.transitionTo('containers');
- }
+ this.onDestroy();
}
},
updateFromClient: function (name, status) {
- this.update(name, status);
+ this.setState({
+ containers: ContainerStore.containers(),
+ sorted: ContainerStore.sorted(),
+ downloading: ContainerStore.downloading()
+ });
if (status === 'create') {
this.transitionTo('containerHome', {name: name});
- } else if (status === 'pending' && ContainerStore.pending()) {
- this.transitionTo('pull');
+ } else if (status === 'destroy') {
+ this.onDestroy();
}
},
handleScroll: function (e) {
@@ -151,6 +162,17 @@ var Containers = React.createClass({
);
}
+ var button;
+ if (this.state.downloading) {
+ button = (
+ Only one Docker image can be downloaded at a time.}>
+
+
+ );
+ } else {
+ button = ;
+ }
+
var container = this.getParams().name ? this.state.containers[this.getParams().name] : {};
return (
@@ -160,7 +182,7 @@ var Containers = React.createClass({
@@ -175,7 +197,7 @@ var Containers = React.createClass({
-
+
);
diff --git a/src/Main.js b/src/Main.js
index 44235be0bc..9f582f3588 100644
--- a/src/Main.js
+++ b/src/Main.js
@@ -27,48 +27,14 @@ setInterval(function () {
router.run(Handler => React.render(, document.body));
-ipc.on('application:quitting', opts => {
- if (!opts.updating && localStorage.getItem('settings.closeVMOnQuit') === 'true') {
- machine.stop();
- }
-});
-
-ipc.on('application:open-url', opts => {
- var repoRegexp = /[a-z0-9]+(?:[._-][a-z0-9]+)*/;
- var parser = document.createElement('a');
- parser.href = opts.url;
-
- if (parser.protocol !== 'docker:') {
- return;
- }
-
- var pathname = parser.pathname.replace('//', '');
- var tokens = pathname.split('/');
- var type = tokens[0];
- var method = tokens[1];
- var repo = tokens.slice(2).join('/');
-
- // Only accept official repos for now
- if (repo.indexOf('/') !== -1 || !repoRegexp.test(repo)) {
- return;
- }
-
- if (type === 'repository' && method === 'run') {
- ContainerStore.setPending(repo, 'latest');
- }
-});
-
SetupStore.setup().then(() => {
- if (ContainerStore.pending()) {
- router.transitionTo('pull');
- } else {
- router.transitionTo('new');
- }
Menu.setApplicationMenu(Menu.buildFromTemplate(template()));
ContainerStore.on(ContainerStore.SERVER_ERROR_EVENT, (err) => {
bugsnag.notify(err);
});
- ContainerStore.init(function () {});
+ ContainerStore.init(function () {
+ router.transitionTo('containers');
+ });
}).catch(err => {
metrics.track('Setup Failed', {
step: 'catch',
@@ -77,3 +43,9 @@ SetupStore.setup().then(() => {
console.log(err);
bugsnag.notify(err);
});
+
+ipc.on('application:quitting', opts => {
+ if (!opts.updating && localStorage.getItem('settings.closeVMOnQuit') === 'true') {
+ machine.stop();
+ }
+});
diff --git a/src/NewContainerSearch.react.js b/src/NewContainer.react.js
similarity index 95%
rename from src/NewContainerSearch.react.js
rename to src/NewContainer.react.js
index 3ac67f2882..05e772cedd 100644
--- a/src/NewContainerSearch.react.js
+++ b/src/NewContainer.react.js
@@ -10,7 +10,7 @@ var metrics = require('./Metrics');
var _recommended = [];
var _searchPromise = null;
-module.exports = React.createClass({
+var NewContainer = React.createClass({
getInitialState: function () {
return {
query: '',
@@ -47,7 +47,7 @@ module.exports = React.createClass({
loading: true
});
- _searchPromise = Promise.delay(200).cancellable().then(() => Promise.resolve($.get('https://registry.hub.docker.com/v1/search?q=' + query))).then(data => {
+ _searchPromise = Promise.delay(200).then(() => Promise.resolve($.get('https://registry.hub.docker.com/v1/search?q=' + query))).cancellable().then(data => {
metrics.track('Searched for Images');
this.setState({
results: data.results,
@@ -166,3 +166,5 @@ module.exports = React.createClass({
);
}
});
+
+module.exports = NewContainer;
diff --git a/src/NewContainerPull.react.js b/src/NewContainerPull.react.js
deleted file mode 100644
index bc915b4dda..0000000000
--- a/src/NewContainerPull.react.js
+++ /dev/null
@@ -1,42 +0,0 @@
-var React = require('react/addons');
-var Router = require('react-router');
-var shell = require('shell');
-var ContainerStore = require('./ContainerStore');
-
-module.exports = React.createClass({
- mixins: [Router.Navigation],
- handleOpenClick: function () {
- var repo = this.props.pending.repository;
- if (repo.indexOf('/') === -1) {
- shell.openExternal(`https://registry.hub.docker.com/_/${this.props.pending.repository}`);
- } else {
- shell.openExternal(`https://registry.hub.docker.com/u/${this.props.pending.repository}`);
- }
- },
- handleCancelClick: function () {
- ContainerStore.clearPending();
- this.transitionTo('new');
- },
- handleConfirmClick: function () {
- ContainerStore.clearPending();
- ContainerStore.create(this.props.pending.repository, this.props.pending.tag, function () {});
- },
- render: function () {
- if (!this.props.pending) {
- return false;
- }
- return (
-
-
-
-
-
Please confirm to create the container.
-
-
-
-
- );
- }
-});
diff --git a/src/Routes.js b/src/Routes.js
index cfdade8b51..eab468fa1c 100644
--- a/src/Routes.js
+++ b/src/Routes.js
@@ -9,14 +9,12 @@ var ContainerSettingsGeneral = require('./ContainerSettingsGeneral.react');
var ContainerSettingsPorts = require('./ContainerSettingsPorts.react');
var ContainerSettingsVolumes = require('./ContainerSettingsVolumes.react');
var Preferences = require('./Preferences.react');
-var NewContainerSearch = require('./NewContainerSearch.react');
-var NewContainerPull = require('./NewContainerPull.react');
+var NewContainer = require('./NewContainer.react');
var Router = require('react-router');
var Route = Router.Route;
var DefaultRoute = Router.DefaultRoute;
var RouteHandler = Router.RouteHandler;
-var Redirect = Router.Redirect;
var App = React.createClass({
render: function () {
@@ -29,21 +27,17 @@ var App = React.createClass({
var routes = (
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
+
diff --git a/src/browser.js b/src/browser.js
index ee7810450a..8722673dcb 100644
--- a/src/browser.js
+++ b/src/browser.js
@@ -18,13 +18,6 @@ try {
settingsjson = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'settings.json'), 'utf8'));
} catch (err) {}
-
-var openURL = null;
-app.on('open-url', function (event, url) {
- event.preventDefault();
- openURL = url;
-});
-
app.on('ready', function () {
var mainWindow = new BrowserWindow({
width: size.width || 1000,
@@ -72,18 +65,6 @@ app.on('ready', function () {
mainWindow.show();
mainWindow.focus();
- if (openURL) {
- mainWindow.webContents.send('application:open-url', {
- url: openURL
- });
- }
- app.on('open-url', function (event, url) {
- event.preventDefault();
- mainWindow.webContents.send('application:open-url', {
- url: url
- });
- });
-
if (process.env.NODE_ENV !== 'development') {
autoUpdater.setFeedUrl('https://updates.kitematic.com/releases/latest?version=' + app.getVersion() + '&beta=' + !!settingsjson.beta);
}
diff --git a/styles/new-container.less b/styles/new-container.less
index 86b60d8903..a00f9c3eb3 100644
--- a/styles/new-container.less
+++ b/styles/new-container.less
@@ -1,32 +1,3 @@
-.new-container-pull {
- display: flex;
- flex: 1 auto;
- align-items: center;
- justify-content: center;
- .content {
- text-align: center;
-
- .buttons {
- margin-top: 30px;
- .btn {
- margin-left: 10px;
- margin-right: 10px;
- padding: 8px 18px;
- font-size: 14px;
- background: white;
- font-weight: 300;
- }
- }
- }
- h1 {
- font-size: 20px;
- color: @gray-normal;
- font-weight: 400;
- text-align: center;
- margin-top: 10px;
- }
-}
-
.new-container {
display: flex;
flex: 1 auto;
diff --git a/styles/theme.less b/styles/theme.less
index d20daccc76..07e8cedd22 100644
--- a/styles/theme.less
+++ b/styles/theme.less
@@ -134,6 +134,7 @@ input[type="text"] {
font-weight: 400;
text-shadow: none;
padding: 5px 14px 5px 14px;
+ height: 30px;
cursor: default;
&.small {
diff --git a/util/Info.plist b/util/Info.plist
index 5efd29e633..396be69183 100644
--- a/util/Info.plist
+++ b/util/Info.plist
@@ -26,16 +26,5 @@
AtomApplication
NSSupportsAutomaticGraphicsSwitching
- CFBundleURLTypes
-
-
- CFBundleURLSchemes
-
- docker
-
- CFBundleURLName
- Docker App Protocol
-
-