diff --git a/images/loading-white.png b/images/loading-white.png new file mode 100644 index 00000000..17096a36 Binary files /dev/null and b/images/loading-white.png differ diff --git a/images/loading-white@2x.png b/images/loading-white@2x.png new file mode 100644 index 00000000..75051f37 Binary files /dev/null and b/images/loading-white@2x.png differ diff --git a/src/ImageCard.react.js b/src/ImageCard.react.js new file mode 100644 index 00000000..2c01f670 --- /dev/null +++ b/src/ImageCard.react.js @@ -0,0 +1,113 @@ +var $ = require('jquery'); +var React = require('react/addons'); +var RetinaImage = require('react-retina-image'); +var ContainerStore = require('./ContainerStore'); + +var ImageCard = React.createClass({ + getInitialState: function () { + return { + tags: [], + chosenTag: 'latest' + }; + }, + handleTagClick: function (tag) { + this.setState({ + chosenTag: tag + }); + var $tagOverlay = $(this.getDOMNode()).find('.tag-overlay'); + $tagOverlay.fadeOut(300); + }, + handleClick: function (name) { + ContainerStore.create(name, this.state.chosenTag, function (err) { + if (err) { + throw err; + } + $(document.body).find('.new-container-item').parent().fadeOut(); + }.bind(this)); + }, + handleTagOverlayClick: function (name) { + var $tagOverlay = $(this.getDOMNode()).find('.tag-overlay'); + $tagOverlay.fadeIn(300); + $.get('https://registry.hub.docker.com/v1/repositories/' + name + '/tags', function (result) { + console.log(result); + this.setState({ + tags: result + }); + }.bind(this)); + + }, + handleCloseTagOverlay: function () { + var $tagOverlay = $(this.getDOMNode()).find('.tag-overlay'); + $tagOverlay.fadeOut(300); + }, + render: function () { + var self = this; + var name; + if (this.props.image.is_official) { + name = {this.props.image.name}; + } else { + name = {this.props.image.name}; + } + var description; + if (this.props.image.description) { + description = this.props.image.description; + } else { + description = "No description."; + } + var logoStyle = { + backgroundImage: `linear-gradient(-180deg, ${this.props.image.gradient_start} 4%, ${this.props.image.gradient_end} 100%)` + }; + var imgsrc; + if (this.props.image.img) { + imgsrc = `http://kitematic.com/recommended/${this.props.image.img}`; + } else { + imgsrc = 'http://kitematic.com/recommended/kitematic_html.png'; + } + var tags; + if (this.state.tags.length > 0) { + var tagDisplay = this.state.tags.map(function (t) { + return
{t.name}
; + }); + tags = ( +
+ {tagDisplay} +
+ ); + } else { + tags = ; + } + return ( +
+
+ {tags} +
+
+ +
+
+
+ {name} +
+
+ {description} +
+
+
+ + {this.props.image.star_count} +
+
+ + {this.state.chosenTag} +
+
+ Create +
+
+
+
+ ); + } +}); + +module.exports = ImageCard; diff --git a/src/Main.js b/src/Main.js index 69beea64..63f46262 100644 --- a/src/Main.js +++ b/src/Main.js @@ -10,7 +10,6 @@ var boot2docker = require('./boot2docker'); var ContainerStore = require('./ContainerStore'); var SetupStore = require('./SetupStore'); var settingsjson; -var Menu = require('./Menu'); try { settingsjson = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'settings.json'), 'utf8')); diff --git a/src/NewContainer.react.js b/src/NewContainer.react.js index 02b3a17a..ccda2514 100644 --- a/src/NewContainer.react.js +++ b/src/NewContainer.react.js @@ -1,10 +1,9 @@ -var _ = require('underscore'); var $ = require('jquery'); var React = require('react/addons'); var RetinaImage = require('react-retina-image'); var ContainerStore = require('./ContainerStore'); var Radial = require('./Radial.react'); -var assign = require('object-assign'); +var ImageCard = require('./ImageCard.react'); var NewContainer = React.createClass({ _searchRequest: null, @@ -12,10 +11,7 @@ var NewContainer = React.createClass({ return { query: '', results: [], - loading: false, - tags: {}, - active: null, - creating: [] + loading: false }; }, componentDidMount: function () { @@ -79,32 +75,7 @@ var NewContainer = React.createClass({ }, 200); } }, - handleClick: function (name) { - ContainerStore.create(name, 'latest', function (err) { - if (err) { - throw err; - } - $(document.body).find('.new-container-item').parent().fadeOut(); - }.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 = []; if (this.state.results) { @@ -112,61 +83,9 @@ var NewContainer = React.createClass({ } 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."; - } - var logoStyle = { - backgroundImage: `linear-gradient(-180deg, ${r.gradient_start} 4%, ${r.gradient_end} 100%)` - }; - var imgsrc; - if (r.img) { - imgsrc = `http://kitematic.com/recommended/${r.img}`; - } else { - imgsrc = 'http://kitematic.com/recommended/kitematic_html.png'; - } - var action; - if (_.find(self.state.creating, r.name)) { - action = ; - } else { - action = Create; - } + var items = data.map(function (image) { return ( -
-
- -
-
-
- {name} -
-
- {description} -
-
-
- - {r.star_count} -
-
- - latest -
-
- {action} -
-
-
-
+ ); }); diff --git a/src/NoContainers.react.js b/src/NoContainers.react.js deleted file mode 100644 index 2be1c9d0..00000000 --- a/src/NoContainers.react.js +++ /dev/null @@ -1,13 +0,0 @@ -var React = require('react/addons'); - -var NoContainers = React.createClass({ - render: function () { - return ( -
-

No Containers

-
- ); - } -}); - -module.exports = NoContainers; diff --git a/styles/containers.less b/styles/containers.less index 750a29ae..32a24493 100644 --- a/styles/containers.less +++ b/styles/containers.less @@ -34,6 +34,48 @@ background-color: white; margin-right: 20px; margin-bottom: 20px; + .tag-overlay { + z-index: 999; + background-color: rgba(0,0,0,0.8); + border-radius: 4px; + width: 320px; + height: 166px; + position: absolute; + color: white; + font-size: 13px; + display: none; + padding: 10px; + .tag-list { + display: flex; + flex-direction: row; + align-items: flex-start; + align-content: flex-start; + flex-flow: row wrap; + height: 140px; + overflow: scroll; + .tag { + display: inline-block; + flex: 0 auto; + margin-right: 2px; + padding: 3px 5px; + &:hover { + background-color: rgba(255,255,255,0.2); + border-radius: 20px; + } + } + } + .tags-loading { + position: relative; + left: 42%; + top: 20%; + text-align: center; + margin: 14px auto; + -webkit-animation-name: spin; + -webkit-animation-duration: 1.8s; + -webkit-animation-iteration-count: infinite; + -webkit-animation-timing-function: linear; + } + } .logo { flex: 1 auto; min-width: 90px; @@ -100,13 +142,19 @@ .icon { position: relative; font-size: 11px; - margin-right: 5px; + margin-right: 2px; top: 2px; color: @gray-darkest; } .text { position: relative; top: 0px; + padding: 3px 5px; + &:hover { + background-color: @brand-action; + color: white; + border-radius: 20px; + } } } .action {