mirror of https://github.com/docker/docs.git
Adding pull container feature
This commit is contained in:
parent
d7dea0bcfa
commit
a5b003b381
|
@ -27,5 +27,5 @@
|
|||
"jest": true,
|
||||
"pit": true
|
||||
},
|
||||
"predef": [ "Promise" ]
|
||||
"predef": [ "-Promise" ]
|
||||
}
|
||||
|
|
|
@ -13,15 +13,9 @@ var ContainerList = React.createClass({
|
|||
<ContainerListItem key={container.Id} container={container} start={self._start}/>
|
||||
);
|
||||
});
|
||||
var newItem;
|
||||
if (!this.props.downloading) {
|
||||
newItem = <ContainerListNewItem key={'newcontainer'} containers={this.props.containers} />;
|
||||
} else {
|
||||
newItem = '';
|
||||
}
|
||||
return (
|
||||
<ul>
|
||||
{newItem}
|
||||
<ContainerListNewItem key={'newcontainer'} containers={this.props.containers}/>
|
||||
{containers}
|
||||
</ul>
|
||||
);
|
||||
|
|
|
@ -297,10 +297,6 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), {
|
|||
var imageName = repository + ':' + tag;
|
||||
var containerName = this._generateName(repository);
|
||||
|
||||
if (_pending && _pending.repository === repository && _pending.tag === tag) {
|
||||
_pending = null;
|
||||
}
|
||||
|
||||
_placeholders[containerName] = {
|
||||
Name: containerName,
|
||||
Image: imageName,
|
||||
|
|
|
@ -10,8 +10,6 @@ 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({
|
||||
|
@ -33,14 +31,6 @@ var Containers = React.createClass({
|
|||
ContainerStore.on(ContainerStore.SERVER_CONTAINER_EVENT, this.update);
|
||||
ContainerStore.on(ContainerStore.CLIENT_CONTAINER_EVENT, this.updateFromClient);
|
||||
|
||||
console.log(this.state);
|
||||
if (this.state.pending) {
|
||||
console.log('pending');
|
||||
this.transitionTo('pull');
|
||||
} else if (this.state.sorted.length) {
|
||||
this.transitionTo('containerHome', {name: this.state.sorted[0].Name});
|
||||
}
|
||||
|
||||
ipc.on('application:update-available', () => {
|
||||
this.setState({
|
||||
updateAvailable: true
|
||||
|
@ -52,44 +42,33 @@ 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: ContainerStore.sorted(),
|
||||
downloading: ContainerStore.downloading(),
|
||||
pending: ContainerStore.pending()
|
||||
sorted: sorted,
|
||||
pending: ContainerStore.pending(),
|
||||
downloading: ContainerStore.downloading()
|
||||
});
|
||||
if (status === 'destroy') {
|
||||
this.onDestroy();
|
||||
if (sorted.length) {
|
||||
this.transitionTo('containerHome', {name: sorted[0].Name});
|
||||
} else {
|
||||
this.transitionTo('containers');
|
||||
}
|
||||
}
|
||||
},
|
||||
updateFromClient: function (name, status) {
|
||||
this.setState({
|
||||
containers: ContainerStore.containers(),
|
||||
sorted: ContainerStore.sorted(),
|
||||
downloading: ContainerStore.downloading(),
|
||||
pending: ContainerStore.pending()
|
||||
});
|
||||
console.log('update from client');
|
||||
|
||||
if (this.state.pending) {
|
||||
this.transitionTo('pull');
|
||||
} else if (status === 'create') {
|
||||
this.update(name, status);
|
||||
if (status === 'create') {
|
||||
this.transitionTo('containerHome', {name: name});
|
||||
} else if (status === 'destroy') {
|
||||
this.onDestroy();
|
||||
} else if (status === 'pending' && ContainerStore.pending()) {
|
||||
this.transitionTo('pull');
|
||||
}
|
||||
},
|
||||
handleScroll: function (e) {
|
||||
|
@ -172,17 +151,6 @@ var Containers = React.createClass({
|
|||
);
|
||||
}
|
||||
|
||||
var button;
|
||||
if (this.state.downloading) {
|
||||
button = (
|
||||
<OverlayTrigger placement="bottom" overlay={<Tooltip>Only one Docker image can be downloaded at a time.</Tooltip>}>
|
||||
<a disabled={true} className="btn-new icon icon-add-3"></a>
|
||||
</OverlayTrigger>
|
||||
);
|
||||
} else {
|
||||
button = <a className="btn-new icon icon-add-3" onClick={this.handleNewContainer}></a>;
|
||||
}
|
||||
|
||||
var container = this.getParams().name ? this.state.containers[this.getParams().name] : {};
|
||||
return (
|
||||
<div className="containers">
|
||||
|
@ -192,7 +160,7 @@ var Containers = React.createClass({
|
|||
<section className={sidebarHeaderClass}>
|
||||
<h4>Containers</h4>
|
||||
<div className="create">
|
||||
{button}
|
||||
<a className="btn-new icon icon-add-3" onClick={this.handleNewContainer}></a>
|
||||
</div>
|
||||
</section>
|
||||
<section className="sidebar-containers" onScroll={this.handleScroll}>
|
||||
|
|
10
src/Main.js
10
src/Main.js
|
@ -51,16 +51,18 @@ ipc.on('application:open-url', opts => {
|
|||
ContainerStore.setPending(repo, 'latest');
|
||||
}
|
||||
});
|
||||
ContainerStore.setPending('kitematic/ghost', '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 () {
|
||||
router.transitionTo('containers');
|
||||
});
|
||||
ContainerStore.init(function () {});
|
||||
}).catch(err => {
|
||||
metrics.track('Setup Failed', {
|
||||
step: 'catch',
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
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 (
|
||||
<div className="details">
|
||||
<div className="new-container-pull">
|
||||
<div className="content">
|
||||
<h1>You're about to download <a onClick={this.handleOpenClick}>{this.props.pending.repository}</a>.</h1>
|
||||
<h1>Please confirm to create the container.</h1>
|
||||
<div className="buttons">
|
||||
<a className="btn btn-action" onClick={this.handleCancelClick}>Cancel</a> <a onClick={this.handleConfirmClick} className="btn btn-action">Confirm</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
|
@ -4,13 +4,13 @@ var React = require('react/addons');
|
|||
var RetinaImage = require('react-retina-image');
|
||||
var Radial = require('./Radial.react');
|
||||
var ImageCard = require('./ImageCard.react');
|
||||
var metrics = require('./Metrics');
|
||||
var Promise = require('bluebird');
|
||||
var metrics = require('./Metrics');
|
||||
|
||||
var _recommended = [];
|
||||
var _searchPromise = null;
|
||||
|
||||
var NewContainer = React.createClass({
|
||||
module.exports = React.createClass({
|
||||
getInitialState: function () {
|
||||
return {
|
||||
query: '',
|
||||
|
@ -47,7 +47,7 @@ var NewContainer = React.createClass({
|
|||
loading: true
|
||||
});
|
||||
|
||||
_searchPromise = Promise.delay(200).then(() => Promise.resolve($.get('https://registry.hub.docker.com/v1/search?q=' + query))).cancellable().then(data => {
|
||||
_searchPromise = Promise.delay(200).cancellable().then(() => Promise.resolve($.get('https://registry.hub.docker.com/v1/search?q=' + query))).then(data => {
|
||||
metrics.track('Searched for Images');
|
||||
this.setState({
|
||||
results: data.results,
|
||||
|
@ -142,7 +142,6 @@ var NewContainer = React.createClass({
|
|||
'icon-magnifier': true,
|
||||
'search-icon': true
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="details">
|
||||
<div className="new-container">
|
||||
|
@ -167,5 +166,3 @@ var NewContainer = React.createClass({
|
|||
);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = NewContainer;
|
|
@ -9,13 +9,14 @@ var ContainerSettingsGeneral = require('./ContainerSettingsGeneral.react');
|
|||
var ContainerSettingsPorts = require('./ContainerSettingsPorts.react');
|
||||
var ContainerSettingsVolumes = require('./ContainerSettingsVolumes.react');
|
||||
var Preferences = require('./Preferences.react');
|
||||
var NewContainer = require('./NewContainer.react');
|
||||
var PullContainer = require('./PullContainer.react');
|
||||
var NewContainerSearch = require('./NewContainerSearch.react');
|
||||
var NewContainerPull = require('./NewContainerPull.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 () {
|
||||
|
@ -28,18 +29,21 @@ var App = React.createClass({
|
|||
var routes = (
|
||||
<Route name="app" path="/" handler={App}>
|
||||
<Route name="containers" handler={Containers}>
|
||||
<Route name="containerDetails" path="containers/:name" handler={ContainerDetails}>
|
||||
<Route name="containerHome" path="containers/:name/home" handler={ContainerHome} />
|
||||
<Route name="containerLogs" path="containers/:name/logs" handler={ContainerLogs}/>
|
||||
<Route name="containerSettings" path="containers/:name/settings" handler={ContainerSettings}>
|
||||
<Route name="containerSettingsGeneral" path="containers/:name/settings/general" handler={ContainerSettingsGeneral}/>
|
||||
<Route name="containerSettingsPorts" path="containers/:name/settings/ports" handler={ContainerSettingsPorts}/>
|
||||
<Route name="containerSettingsVolumes" path="containers/:name/settings/volumes" handler={ContainerSettingsVolumes}/>
|
||||
<Route name="containerDetails" path="containers/details/:name" handler={ContainerDetails}>
|
||||
<Route name="containerHome" path="containers/details/:name/home" handler={ContainerHome} />
|
||||
<Route name="containerLogs" path="containers/details/:name/logs" handler={ContainerLogs}/>
|
||||
<Route name="containerSettings" path="containers/details/:name/settings" handler={ContainerSettings}>
|
||||
<Route name="containerSettingsGeneral" path="containers/details/:name/settings/general" handler={ContainerSettingsGeneral}/>
|
||||
<Route name="containerSettingsPorts" path="containers/details/:name/settings/ports" handler={ContainerSettingsPorts}/>
|
||||
<Route name="containerSettingsVolumes" path="containers/details/:name/settings/volumes" handler={ContainerSettingsVolumes}/>
|
||||
</Route>
|
||||
</Route>
|
||||
<Route name="new" path="containers/new">
|
||||
<DefaultRoute name="search" handler={NewContainerSearch}/>
|
||||
<Route name="pull" path="containers/new/pull" handler={NewContainerPull}></Route>
|
||||
</Route>
|
||||
<Route name="preferences" path="/preferences" handler={Preferences}/>
|
||||
<DefaultRoute name="new" handler={NewContainer}/>
|
||||
<Route name="pull" handler={PullContainer}></Route>
|
||||
<Redirect to="new"/>
|
||||
</Route>
|
||||
<DefaultRoute name="setup" handler={Setup}/>
|
||||
</Route>
|
||||
|
|
|
@ -1,3 +1,32 @@
|
|||
.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;
|
||||
|
|
|
@ -134,7 +134,6 @@ input[type="text"] {
|
|||
font-weight: 400;
|
||||
text-shadow: none;
|
||||
padding: 5px 14px 5px 14px;
|
||||
height: 30px;
|
||||
cursor: default;
|
||||
|
||||
&.small {
|
||||
|
|
Loading…
Reference in New Issue