diff --git a/images/container-white.png b/images/container-white.png
new file mode 100644
index 0000000000..94fc0e6bad
Binary files /dev/null and b/images/container-white.png differ
diff --git a/images/container-white@2x.png b/images/container-white@2x.png
new file mode 100644
index 0000000000..dc5fde9ef5
Binary files /dev/null and b/images/container-white@2x.png differ
diff --git a/images/container.png b/images/container.png
new file mode 100644
index 0000000000..b2ed8b5f95
Binary files /dev/null and b/images/container.png differ
diff --git a/images/container@2x.png b/images/container@2x.png
new file mode 100644
index 0000000000..82b02cb2c0
Binary files /dev/null and b/images/container@2x.png differ
diff --git a/package.json b/package.json
index 09fb1e3eaf..201644c157 100644
--- a/package.json
+++ b/package.json
@@ -34,7 +34,7 @@
]
},
"boot2docker-version": "1.4.1",
- "atom-shell-version": "0.20.0",
+ "atom-shell-version": "0.21.1",
"virtualbox-version": "4.3.20",
"virtualbox-filename": "VirtualBox-4.3.20-96996-OSX.dmg",
"virtualbox-required-version": "4.3.18",
diff --git a/src/ContainerList.react.js b/src/ContainerList.react.js
index 3d59457b1f..3526d5a789 100644
--- a/src/ContainerList.react.js
+++ b/src/ContainerList.react.js
@@ -1,5 +1,6 @@
var React = require('react/addons');
var ContainerListItem = require('./ContainerListItem.react');
+var ContainerListNewItem = require('./ContainerListNewItem.react');
var ContainerList = React.createClass({
render: function () {
@@ -11,6 +12,7 @@ var ContainerList = React.createClass({
});
return (
);
diff --git a/src/ContainerListNewItem.react.js b/src/ContainerListNewItem.react.js
new file mode 100644
index 0000000000..3260aceb2f
--- /dev/null
+++ b/src/ContainerListNewItem.react.js
@@ -0,0 +1,43 @@
+var $ = require('jquery');
+var React = require('react/addons');
+var Router = require('react-router');
+
+var ContainerListNewItem = React.createClass({
+ handleItemMouseEnter: function () {
+ var $action = $(this.getDOMNode()).find('.action');
+ $action.show();
+ },
+ handleItemMouseLeave: function () {
+ var $action = $(this.getDOMNode()).find('.action');
+ $action.hide();
+ },
+ handleDelete: function () {
+ $(this.getDOMNode()).fadeOut();
+ },
+ render: function () {
+ var self = this;
+ var action;
+ if (this.props.containers.length > 0) {
+ action = (
+
+
+
+ );
+ }
+ return (
+
+
+
+
+ {action}
+
+
+ );
+ }
+});
+
+module.exports = ContainerListNewItem;
diff --git a/src/ContainerModal.react.js b/src/ContainerModal.react.js
index 0f6a13bda4..a78ef0edd0 100644
--- a/src/ContainerModal.react.js
+++ b/src/ContainerModal.react.js
@@ -77,17 +77,17 @@ var ContainerModal = React.createClass({
}, 200);
}
},
- handleClick: function (name, event) {
+ handleClick: function (name) {
this.props.onRequestHide();
- ContainerStore.create(name, 'latest', function (err, containerName) {
+ ContainerStore.create(name, 'latest', function (err) {
if (err) {
throw err;
}
}.bind(this));
},
- handleTagClick: function (tag, name, event) {
+ handleTagClick: function (tag, name) {
this.props.onRequestHide();
- ContainerStore.create(name, tag, function (err, containerName) {});
+ ContainerStore.create(name, tag, function () {});
},
handleDropdownClick: function (name) {
this.setState({
diff --git a/src/ContainerStore.js b/src/ContainerStore.js
index 32773181f4..7e3ad1020a 100644
--- a/src/ContainerStore.js
+++ b/src/ContainerStore.js
@@ -118,11 +118,11 @@ var ContainerStore = assign(EventEmitter.prototype, {
if (containerData.Config && containerData.Config.Image) {
containerData.Image = containerData.Config.Image;
}
- existing.kill(function (err, data) {
+ existing.kill(function (err) {
if (err) {
console.log(err);
}
- existing.remove(function (err, data) {
+ existing.remove(function (err) {
if (err) {
console.log(err);
}
@@ -386,7 +386,6 @@ var ContainerStore = assign(EventEmitter.prototype, {
var self = this;
var imageName = repository + ':' + tag;
var containerName = this._generateName(repository);
- var image = docker.client().getImage(imageName);
// Pull image
self._createPlaceholderContainer(imageName, containerName, function (err, container) {
if (err) {
@@ -398,7 +397,7 @@ var ContainerStore = assign(EventEmitter.prototype, {
_muted[containerName] = true;
_progress[containerName] = 0;
self._pullImage(repository, tag, function () {
- self._createContainer(containerName, {Image: imageName}, function (err, container) {
+ self._createContainer(containerName, {Image: imageName}, function () {
delete _progress[containerName];
_muted[containerName] = false;
self.emit(self.CLIENT_CONTAINER_EVENT, containerName);
diff --git a/src/Containers.react.js b/src/Containers.react.js
index aeafab212e..81070e7ba2 100644
--- a/src/Containers.react.js
+++ b/src/Containers.react.js
@@ -1,11 +1,9 @@
+var $ = require('jquery');
var React = require('react/addons');
var Router = require('react-router');
-var ModalTrigger = require('react-bootstrap/ModalTrigger');
-var ContainerModal = require('./ContainerModal.react');
var ContainerStore = require('./ContainerStore');
var ContainerList = require('./ContainerList.react');
var Header = require('./Header.react');
-var router = require('./Router');
var Containers = React.createClass({
mixins: [Router.Navigation, Router.State],
@@ -13,7 +11,7 @@ var Containers = React.createClass({
return {
sidebarOffset: 0,
containers: ContainerStore.containers(),
- sorted: ContainerStore.sorted(),
+ sorted: ContainerStore.sorted()
};
},
componentDidMount: function () {
@@ -63,6 +61,8 @@ var Containers = React.createClass({
}
},
handleNewContainer: function () {
+ console.log($(this.getDOMNode()).find('.new-container-item'));
+ $(this.getDOMNode()).find('.new-container-item').parent().fadeIn();
this.transitionTo('new');
},
render: function () {
@@ -84,7 +84,7 @@ var Containers = React.createClass({
diff --git a/src/NewContainer.react.js b/src/NewContainer.react.js
index 5f1162bae5..33e97d34a2 100644
--- a/src/NewContainer.react.js
+++ b/src/NewContainer.react.js
@@ -2,6 +2,7 @@ var $ = require('jquery');
var React = require('react/addons');
var RetinaImage = require('react-retina-image');
var ContainerStore = require('./ContainerStore');
+var assign = require('object-assign');
var NewContainer = React.createClass({
_searchRequest: null,
@@ -71,7 +72,92 @@ var NewContainer = React.createClass({
}, 200);
}
},
+ handleClick: function (name) {
+ ContainerStore.create(name, 'latest', function (err) {
+ if (err) {
+ throw err;
+ }
+ }.bind(this));
+ },
+ handleDropdownClick: function (name) {
+ this.setState({
+ active: name
+ });
+ if (this.state.tags[name]) {
+ return;
+ }
+ $.get('https://registry.hub.docker.com/v1/repositories/' + name + '/tags', function (result) {
+ var res = {};
+ res[name] = result;
+ console.log(assign(this.state.tags, res));
+ this.setState({
+ tags: assign(this.state.tags, res)
+ });
+ }.bind(this));
+ },
render: function () {
+ var self = this;
+ var title = this.state.query ? 'Results' : 'Recommended';
+ var data = this.state.results.slice(0, 7);
+
+ var results;
+ if (data.length) {
+ var items = data.map(function (r) {
+ var name;
+ if (r.is_official) {
+ name = {r.name};
+ } else {
+ name = {r.name};
+ }
+ var description;
+ if (r.description) {
+ description = r.description;
+ } else {
+ description = "No description.";
+ }
+ return (
+
+
+
+
+
+ {name}
+
+
+ {description}
+
+
+
+
+ {r.star_count}
+
+
+
+ latest
+
+
+
+
+
+ );
+ });
+
+ results = (
+
+ {items}
+
+ );
+ } else {
+ results = (
+
+
+ No Results
+
+
+ );
+ }
var loadingClasses = React.addons.classSet({
hidden: !this.state.loading,
loading: true
@@ -98,6 +184,10 @@ var NewContainer = React.createClass({
+
+
{title}
+ {results}
+
diff --git a/src/Setup.react.js b/src/Setup.react.js
index 8df59eb28e..ef3bd7160f 100644
--- a/src/Setup.react.js
+++ b/src/Setup.react.js
@@ -1,11 +1,6 @@
var React = require('react/addons');
var Router = require('react-router');
var Radial = require('./Radial.react.js');
-var async = require('async');
-var assign = require('object-assign');
-var fs = require('fs');
-var path = require('path');
-var virtualbox = require('./Virtualbox');
var SetupStore = require('./SetupStore');
var RetinaImage = require('react-retina-image');
diff --git a/styles/containers.less b/styles/containers.less
index 1eb03f3787..57fcd49f6b 100644
--- a/styles/containers.less
+++ b/styles/containers.less
@@ -19,9 +19,109 @@
}
}
+.result-grid {
+ display: flex;
+ flex-flow: row wrap;
+ justify-content: flex-start;
+ margin-top: 20px;
+ overflow: auto;
+ .image-item {
+ display: flex;
+ .logo {
+ min-width: 90px;
+ height: 100%;
+ background-color: @brand-action;
+ }
+ .card {
+ padding: 10px 20px 10px 20px;
+ .name {
+ font-size: 18px;
+ color: @gray-darkest;
+ margin-bottom: 5px;
+ img {
+ margin-right: 7px;
+ position: relative;
+ top: -1px;
+ }
+ }
+ .description {
+ font-size: 12px;
+ color: @gray-normal;
+ height: 70px;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 4;
+ display: -webkit-box;
+ word-wrap: break-word;
+ }
+ .actions {
+ width: 190px;
+ padding-top: 25px;
+ .stars {
+ height: 15px;
+ font-size: 10px;
+ color: @gray-darker;
+ border-right: 1px solid @gray-lightest;
+ padding-right: 10px;
+ .icon {
+ position: relative;
+ font-size: 16px;
+ margin-right: 3px;
+ top: -1px;
+ color: @gray-darkest;
+ }
+ .text {
+ position: relative;
+ top: -6px;
+ }
+ }
+ .tags {
+ height: 15px;
+ font-size: 10px;
+ color: @gray-darker;
+ padding-left: 10px;
+ .icon {
+ position: relative;
+ font-size: 11px;
+ margin-right: 5px;
+ top: 2px;
+ color: @gray-darkest;
+ }
+ .text {
+ position: relative;
+ top: 0px;
+ }
+ }
+ .action {
+ flex: 1 auto;
+ .btn {
+ text-align: right;
+ position: relative;
+ float: right;
+ top: -7px;
+ }
+ }
+ display: flex;
+ flex-direaction: row;
+ position: relative;
+ bottom: 0px;
+ }
+ }
+ width: 320px;
+ height: 170px;
+ border-radius: 4px;
+ border: 1px solid @gray-lightest;
+ background-color: white;
+ margin-right: 20px;
+ margin-bottom: 20px;
+ }
+}
+
.new-container {
padding: 35px 20px 32px 25px;
.new-container-header {
+ margin-bottom: 20px;
display: flex;
flex: 1;
.text {
@@ -160,6 +260,13 @@
display: flex;
flex-direction: column;
+ .new-container-item {
+ .info {
+ position: relative;
+ top: 9px;
+ }
+ }
+
a {
color: inherit;
flex-shrink: 0;
@@ -168,6 +275,7 @@
&.active {
background: @brand-primary;
li {
+ height: 57px;
border-bottom: none;
background-image: linear-gradient(-180deg, #24B8EB 4%, #24A3EB 100%);
.name {
@@ -187,6 +295,9 @@
color: white;
}
}
+ .state-new {
+ .at2x('container-white.png', 20px, 20px);
+ }
.state-running {
.at2x('running-white.png', 20px, 20px);
@@ -197,7 +308,6 @@
.state-stopped {
.at2x('stopped-white.png', 20px, 20px);
}
-
.state-downloading {
.at2x('downloading-white.png', 20px, 20px);
@@ -223,6 +333,7 @@
display: flex;
flex-direction: row;
+ height: 57px;
.info {
@@ -283,6 +394,10 @@
.at2x('paused.png', 20px, 20px);
}
+ .state-new {
+ .at2x('container.png', 20px, 20px);
+ }
+
.state-downloading {
.at2x('downloading.png', 20px, 20px);
overflow: hidden;