mirror of https://github.com/docker/docs.git
Grid implementation.
This commit is contained in:
parent
ca19d62000
commit
9709e5fec4
Binary file not shown.
After Width: | Height: | Size: 128 B |
Binary file not shown.
After Width: | Height: | Size: 193 B |
Binary file not shown.
After Width: | Height: | Size: 126 B |
Binary file not shown.
After Width: | Height: | Size: 201 B |
|
@ -34,7 +34,7 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"boot2docker-version": "1.4.1",
|
"boot2docker-version": "1.4.1",
|
||||||
"atom-shell-version": "0.20.0",
|
"atom-shell-version": "0.21.1",
|
||||||
"virtualbox-version": "4.3.20",
|
"virtualbox-version": "4.3.20",
|
||||||
"virtualbox-filename": "VirtualBox-4.3.20-96996-OSX.dmg",
|
"virtualbox-filename": "VirtualBox-4.3.20-96996-OSX.dmg",
|
||||||
"virtualbox-required-version": "4.3.18",
|
"virtualbox-required-version": "4.3.18",
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
var React = require('react/addons');
|
var React = require('react/addons');
|
||||||
var ContainerListItem = require('./ContainerListItem.react');
|
var ContainerListItem = require('./ContainerListItem.react');
|
||||||
|
var ContainerListNewItem = require('./ContainerListNewItem.react');
|
||||||
|
|
||||||
var ContainerList = React.createClass({
|
var ContainerList = React.createClass({
|
||||||
render: function () {
|
render: function () {
|
||||||
|
@ -11,6 +12,7 @@ var ContainerList = React.createClass({
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<ul>
|
<ul>
|
||||||
|
<ContainerListNewItem containers={this.props.containers} />
|
||||||
{containers}
|
{containers}
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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 = (
|
||||||
|
<div className="action">
|
||||||
|
<span className="icon icon-delete-3 btn-delete" onClick={this.handleDelete}></span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Router.Link to="new">
|
||||||
|
<li className="new-container-item" onMouseEnter={self.handleItemMouseEnter} onMouseLeave={self.handleItemMouseLeave}>
|
||||||
|
<div className="state state-new"></div>
|
||||||
|
<div className="info">
|
||||||
|
<div className="name">
|
||||||
|
New Container
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{action}
|
||||||
|
</li>
|
||||||
|
</Router.Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = ContainerListNewItem;
|
|
@ -77,17 +77,17 @@ var ContainerModal = React.createClass({
|
||||||
}, 200);
|
}, 200);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleClick: function (name, event) {
|
handleClick: function (name) {
|
||||||
this.props.onRequestHide();
|
this.props.onRequestHide();
|
||||||
ContainerStore.create(name, 'latest', function (err, containerName) {
|
ContainerStore.create(name, 'latest', function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
handleTagClick: function (tag, name, event) {
|
handleTagClick: function (tag, name) {
|
||||||
this.props.onRequestHide();
|
this.props.onRequestHide();
|
||||||
ContainerStore.create(name, tag, function (err, containerName) {});
|
ContainerStore.create(name, tag, function () {});
|
||||||
},
|
},
|
||||||
handleDropdownClick: function (name) {
|
handleDropdownClick: function (name) {
|
||||||
this.setState({
|
this.setState({
|
||||||
|
|
|
@ -118,11 +118,11 @@ var ContainerStore = assign(EventEmitter.prototype, {
|
||||||
if (containerData.Config && containerData.Config.Image) {
|
if (containerData.Config && containerData.Config.Image) {
|
||||||
containerData.Image = containerData.Config.Image;
|
containerData.Image = containerData.Config.Image;
|
||||||
}
|
}
|
||||||
existing.kill(function (err, data) {
|
existing.kill(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
existing.remove(function (err, data) {
|
existing.remove(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
|
@ -386,7 +386,6 @@ var ContainerStore = assign(EventEmitter.prototype, {
|
||||||
var self = this;
|
var self = this;
|
||||||
var imageName = repository + ':' + tag;
|
var imageName = repository + ':' + tag;
|
||||||
var containerName = this._generateName(repository);
|
var containerName = this._generateName(repository);
|
||||||
var image = docker.client().getImage(imageName);
|
|
||||||
// Pull image
|
// Pull image
|
||||||
self._createPlaceholderContainer(imageName, containerName, function (err, container) {
|
self._createPlaceholderContainer(imageName, containerName, function (err, container) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -398,7 +397,7 @@ var ContainerStore = assign(EventEmitter.prototype, {
|
||||||
_muted[containerName] = true;
|
_muted[containerName] = true;
|
||||||
_progress[containerName] = 0;
|
_progress[containerName] = 0;
|
||||||
self._pullImage(repository, tag, function () {
|
self._pullImage(repository, tag, function () {
|
||||||
self._createContainer(containerName, {Image: imageName}, function (err, container) {
|
self._createContainer(containerName, {Image: imageName}, function () {
|
||||||
delete _progress[containerName];
|
delete _progress[containerName];
|
||||||
_muted[containerName] = false;
|
_muted[containerName] = false;
|
||||||
self.emit(self.CLIENT_CONTAINER_EVENT, containerName);
|
self.emit(self.CLIENT_CONTAINER_EVENT, containerName);
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
|
var $ = require('jquery');
|
||||||
var React = require('react/addons');
|
var React = require('react/addons');
|
||||||
var Router = require('react-router');
|
var Router = require('react-router');
|
||||||
var ModalTrigger = require('react-bootstrap/ModalTrigger');
|
|
||||||
var ContainerModal = require('./ContainerModal.react');
|
|
||||||
var ContainerStore = require('./ContainerStore');
|
var ContainerStore = require('./ContainerStore');
|
||||||
var ContainerList = require('./ContainerList.react');
|
var ContainerList = require('./ContainerList.react');
|
||||||
var Header = require('./Header.react');
|
var Header = require('./Header.react');
|
||||||
var router = require('./Router');
|
|
||||||
|
|
||||||
var Containers = React.createClass({
|
var Containers = React.createClass({
|
||||||
mixins: [Router.Navigation, Router.State],
|
mixins: [Router.Navigation, Router.State],
|
||||||
|
@ -13,7 +11,7 @@ var Containers = React.createClass({
|
||||||
return {
|
return {
|
||||||
sidebarOffset: 0,
|
sidebarOffset: 0,
|
||||||
containers: ContainerStore.containers(),
|
containers: ContainerStore.containers(),
|
||||||
sorted: ContainerStore.sorted(),
|
sorted: ContainerStore.sorted()
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
componentDidMount: function () {
|
componentDidMount: function () {
|
||||||
|
@ -63,6 +61,8 @@ var Containers = React.createClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleNewContainer: function () {
|
handleNewContainer: function () {
|
||||||
|
console.log($(this.getDOMNode()).find('.new-container-item'));
|
||||||
|
$(this.getDOMNode()).find('.new-container-item').parent().fadeIn();
|
||||||
this.transitionTo('new');
|
this.transitionTo('new');
|
||||||
},
|
},
|
||||||
render: function () {
|
render: function () {
|
||||||
|
@ -84,7 +84,7 @@ var Containers = React.createClass({
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section className="sidebar-containers" onScroll={this.handleScroll}>
|
<section className="sidebar-containers" onScroll={this.handleScroll}>
|
||||||
<ContainerList containers={this.state.sorted}/>
|
<ContainerList containers={this.state.sorted} newContainer={this.state.newContainer} />
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
<Router.RouteHandler container={container}/>
|
<Router.RouteHandler container={container}/>
|
||||||
|
|
|
@ -2,6 +2,7 @@ var $ = require('jquery');
|
||||||
var React = require('react/addons');
|
var React = require('react/addons');
|
||||||
var RetinaImage = require('react-retina-image');
|
var RetinaImage = require('react-retina-image');
|
||||||
var ContainerStore = require('./ContainerStore');
|
var ContainerStore = require('./ContainerStore');
|
||||||
|
var assign = require('object-assign');
|
||||||
|
|
||||||
var NewContainer = React.createClass({
|
var NewContainer = React.createClass({
|
||||||
_searchRequest: null,
|
_searchRequest: null,
|
||||||
|
@ -71,7 +72,92 @@ var NewContainer = React.createClass({
|
||||||
}, 200);
|
}, 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 () {
|
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 = <span><RetinaImage src="official.png"/>{r.name}</span>;
|
||||||
|
} else {
|
||||||
|
name = <span>{r.name}</span>;
|
||||||
|
}
|
||||||
|
var description;
|
||||||
|
if (r.description) {
|
||||||
|
description = r.description;
|
||||||
|
} else {
|
||||||
|
description = "No description.";
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div key={r.name} className="image-item">
|
||||||
|
<div className="logo">
|
||||||
|
</div>
|
||||||
|
<div className="card">
|
||||||
|
<div className="name">
|
||||||
|
{name}
|
||||||
|
</div>
|
||||||
|
<div className="description">
|
||||||
|
{description}
|
||||||
|
</div>
|
||||||
|
<div className="actions">
|
||||||
|
<div className="stars">
|
||||||
|
<span className="icon icon-star-9"></span>
|
||||||
|
<span className="text">{r.star_count}</span>
|
||||||
|
</div>
|
||||||
|
<div className="tags">
|
||||||
|
<span className="icon icon-tag-1"></span>
|
||||||
|
<span className="text">latest</span>
|
||||||
|
</div>
|
||||||
|
<div className="action">
|
||||||
|
<a className="btn btn-action" onClick={self.handleClick.bind(self, r.name)}>Create</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
results = (
|
||||||
|
<div className="result-grid">
|
||||||
|
{items}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
results = (
|
||||||
|
<div className="no-results">
|
||||||
|
<h3>
|
||||||
|
No Results
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
var loadingClasses = React.addons.classSet({
|
var loadingClasses = React.addons.classSet({
|
||||||
hidden: !this.state.loading,
|
hidden: !this.state.loading,
|
||||||
loading: true
|
loading: true
|
||||||
|
@ -98,6 +184,10 @@ var NewContainer = React.createClass({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="results">
|
||||||
|
<h4>{title}</h4>
|
||||||
|
{results}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
var React = require('react/addons');
|
var React = require('react/addons');
|
||||||
var Router = require('react-router');
|
var Router = require('react-router');
|
||||||
var Radial = require('./Radial.react.js');
|
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 SetupStore = require('./SetupStore');
|
||||||
var RetinaImage = require('react-retina-image');
|
var RetinaImage = require('react-retina-image');
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
.new-container {
|
||||||
padding: 35px 20px 32px 25px;
|
padding: 35px 20px 32px 25px;
|
||||||
.new-container-header {
|
.new-container-header {
|
||||||
|
margin-bottom: 20px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
.text {
|
.text {
|
||||||
|
@ -160,6 +260,13 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
|
.new-container-item {
|
||||||
|
.info {
|
||||||
|
position: relative;
|
||||||
|
top: 9px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
@ -168,6 +275,7 @@
|
||||||
&.active {
|
&.active {
|
||||||
background: @brand-primary;
|
background: @brand-primary;
|
||||||
li {
|
li {
|
||||||
|
height: 57px;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
background-image: linear-gradient(-180deg, #24B8EB 4%, #24A3EB 100%);
|
background-image: linear-gradient(-180deg, #24B8EB 4%, #24A3EB 100%);
|
||||||
.name {
|
.name {
|
||||||
|
@ -187,6 +295,9 @@
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.state-new {
|
||||||
|
.at2x('container-white.png', 20px, 20px);
|
||||||
|
}
|
||||||
.state-running {
|
.state-running {
|
||||||
.at2x('running-white.png', 20px, 20px);
|
.at2x('running-white.png', 20px, 20px);
|
||||||
|
|
||||||
|
@ -197,7 +308,6 @@
|
||||||
.state-stopped {
|
.state-stopped {
|
||||||
.at2x('stopped-white.png', 20px, 20px);
|
.at2x('stopped-white.png', 20px, 20px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.state-downloading {
|
.state-downloading {
|
||||||
.at2x('downloading-white.png', 20px, 20px);
|
.at2x('downloading-white.png', 20px, 20px);
|
||||||
|
|
||||||
|
@ -223,6 +333,7 @@
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
height: 57px;
|
||||||
|
|
||||||
|
|
||||||
.info {
|
.info {
|
||||||
|
@ -283,6 +394,10 @@
|
||||||
.at2x('paused.png', 20px, 20px);
|
.at2x('paused.png', 20px, 20px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.state-new {
|
||||||
|
.at2x('container.png', 20px, 20px);
|
||||||
|
}
|
||||||
|
|
||||||
.state-downloading {
|
.state-downloading {
|
||||||
.at2x('downloading.png', 20px, 20px);
|
.at2x('downloading.png', 20px, 20px);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
Loading…
Reference in New Issue