From 72ccbc6c35da0ca6ae8cbb065a2f5302766ce365 Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Wed, 21 Jan 2015 20:48:03 -0500 Subject: [PATCH] Removing active event from ContainerStore --- app/ContainerDetails.react.js | 74 +++++++++++++++++++++++++++++------ app/ContainerList.react.js | 25 ++---------- app/ContainerModal.react.js | 34 ++++++++++++---- app/ContainerStore.js | 46 +++++++++++++++------- app/styles/containers.less | 12 +++++- 5 files changed, 136 insertions(+), 55 deletions(-) diff --git a/app/ContainerDetails.react.js b/app/ContainerDetails.react.js index d867cc9746..cd8c140d6f 100644 --- a/app/ContainerDetails.react.js +++ b/app/ContainerDetails.react.js @@ -1,15 +1,19 @@ var _ = require('underscore'); var React = require('react'); var Router = require('react-router'); +var Convert = require('ansi-to-html'); +var convert = new Convert(); +var ContainerStore = require('./ContainerStore'); +var docker = require('./docker'); +var exec = require('exec'); +var boot2docker = require('./boot2docker'); +var ProgressBar = require('react-bootstrap/ProgressBar'); + var Route = Router.Route; var NotFoundRoute = Router.NotFoundRoute; var DefaultRoute = Router.DefaultRoute; var Link = Router.Link; var RouteHandler = Router.RouteHandler; -var Convert = require('ansi-to-html'); -var convert = new Convert(); -var ContainerStore = require('./ContainerStore'); -var docker = require('./docker'); var ContainerDetails = React.createClass({ mixins: [Router.State], @@ -19,14 +23,17 @@ var ContainerDetails = React.createClass({ }; }, componentWillReceiveProps: function () { - console.log('props'); this.update(); + this.setState({ + logs: [] + }); var self = this; var logs = []; var index = 0; docker.client().getContainer(this.getParams().name).logs({ follow: false, stdout: true, + stderr: true, timestamps: true }, function (err, stream) { stream.setEncoding('utf8'); @@ -44,6 +51,7 @@ var ContainerDetails = React.createClass({ docker.client().getContainer(self.getParams().name).logs({ follow: true, stdout: true, + stderr: true, timestamps: true, tail: 0 }, function (err, stream) { @@ -75,11 +83,9 @@ var ContainerDetails = React.createClass({ }, update: function () { var name = this.getParams().name; - var container = ContainerStore.container(name); - var progress = ContainerStore.progress(name); this.setState({ - progress: progress, - container: container + container: ContainerStore.container(name), + progress: ContainerStore.progress(name) }); }, _escapeHTML: function (html) { @@ -88,8 +94,32 @@ var ContainerDetails = React.createClass({ div.appendChild(text); return div.innerHTML; }, + handleClick: function (name) { + var container = this.state.container; + boot2docker.ip(function (err, ip) { + var ports = _.map(container.NetworkSettings.Ports, function (value, key) { + var portProtocolPair = key.split('/'); + var res = { + 'port': portProtocolPair[0], + 'protocol': portProtocolPair[1] + }; + if (value && value.length) { + var port = value[0].HostPort; + res.host = ip; + res.port = port; + res.url = 'http://' + ip + ':' + port; + } else { + return null; + } + return res; + }); + console.log(ports); + exec(['open', ports[0].url], function (err) { + if (err) { throw err; } + }); + }); + }, render: function () { - console.log('render details'); var self = this; if (!this.state) { @@ -111,12 +141,32 @@ var ContainerDetails = React.createClass({ state =

restarting

; } + var progress; + if (this.state.progress > 0 && this.state.progress != 1) { + progress = ( +
+ +
+ ); + } else { + progress =
; + } + + var button; + if (this.state.progress === 1) { + button = View; + } else { + button = View; + } + + var name = this.state.container.Name.replace('/', ''); + return (
-

{this.state.container.Name.replace('/', '')}

-

{this.state.progress}

+

{name}

View
+ {progress}
{logs} diff --git a/app/ContainerList.react.js b/app/ContainerList.react.js index f63d07b534..81ade25892 100644 --- a/app/ContainerList.react.js +++ b/app/ContainerList.react.js @@ -16,16 +16,13 @@ var RouteHandler = Router.RouteHandler; var Navigation= Router.Navigation; var ContainerList = React.createClass({ - mixins: [Navigation], getInitialState: function () { return { - active: null, containers: [] }; }, componentDidMount: function () { this.updateContainers(); - ContainerStore.addChangeListener(ContainerStore.ACTIVE, this.updateActive); ContainerStore.addChangeListener(ContainerStore.CONTAINERS, this.updateContainers); }, componentWillMount: function () { @@ -33,29 +30,13 @@ var ContainerList = React.createClass({ }, componentWillUnmount: function () { ContainerStore.removeChangeListener(ContainerStore.CONTAINERS, this.updateContainers); - ContainerStore.removeChangeListener(ContainerStore.ACTIVE, updateActive.update); - }, - updateActive: function () { - if (ContainerStore.active()) { - this.transitionTo('container', {name: ContainerStore.active()}); - } }, updateContainers: function () { // Sort by name var containers = _.values(ContainerStore.containers()).sort(function (a, b) { return a.Name.localeCompare(b.Name); }); - this.setState({containers: containers}); - - // Transition to the active container or set one - var active = ContainerStore.active(); - if (!ContainerStore.container(active) && containers.length > 0) { - ContainerStore.setActive(containers[0].Name.replace('/', '')); - } - }, - handleClick: function (containerId) { - ContainerStore.setActive(name); }, render: function () { var self = this; @@ -95,13 +76,15 @@ var ContainerList = React.createClass({ state =
; } + var name = container.Name.replace('/', ''); + return ( - +
  • {state}
    - {container.Name.replace('/', '')} + {name}
    {imageName} diff --git a/app/ContainerModal.react.js b/app/ContainerModal.react.js index a01de96227..2568d4f103 100644 --- a/app/ContainerModal.react.js +++ b/app/ContainerModal.react.js @@ -1,18 +1,21 @@ +var async = require('async'); +var $ = require('jquery'); var React = require('react'); var Router = require('react-router'); var Modal = require('react-bootstrap/Modal'); var RetinaImage = require('react-retina-image'); -var $ = require('jquery'); var ContainerStore = require('./ContainerStore'); var Navigation = Router.Navigation; var ContainerModal = React.createClass({ + mixins: [Navigation], _searchRequest: null, getInitialState: function () { return { query: '', - results: [] + results: [], + recommended: ContainerStore.recommended() }; }, componentDidMount: function () { @@ -21,6 +24,8 @@ var ContainerModal = React.createClass({ search: function (query) { var self = this; this._searchRequest = $.get('https://registry.hub.docker.com/v1/search?q=' + query, function (result) { + self._searchRequest.abort(); + self._searchRequest = null; if (self.isMounted()) { self.setState(result); console.log(result); @@ -35,6 +40,7 @@ var ContainerModal = React.createClass({ } if (this._searchRequest) { + console.log('Cancel'); this._searchRequest.abort(); this._searchRequest = null; } @@ -48,14 +54,20 @@ var ContainerModal = React.createClass({ var name = event.target.getAttribute('name'); var self = this; ContainerStore.create(name, 'latest', function (err, containerName) { - ContainerStore.setActive(containerName); + // this.transitionTo('containers', {container: containerName}); self.props.onRequestHide(); - }); + }.bind(this)); }, render: function () { - var top = this.state.results.splice(0, 7); var self = this; - var results = top.map(function (r) { + + var data; + if (this.state.query) { + data = this.state.results.splice(0, 7); + } else { + data = this.state.recommended; + } + var results = data.map(function (r) { var name; if (r.is_official) { name = {r.name}; @@ -79,6 +91,14 @@ var ContainerModal = React.createClass({
  • ); }); + + var title; + if (this.state.query) { + title =
    Results
    ; + } else { + title =
    Recommended
    ; + } + return (
    @@ -88,7 +108,7 @@ var ContainerModal = React.createClass({ What's an image?
    -
    Results
    + {title}
      {results}
    diff --git a/app/ContainerStore.js b/app/ContainerStore.js index 2f75319cf2..ff54d4351a 100644 --- a/app/ContainerStore.js +++ b/app/ContainerStore.js @@ -11,11 +11,11 @@ var ContainerStore = assign(EventEmitter.prototype, { CONTAINERS: 'containers', PROGRESS: 'progress', LOGS: 'logs', - ACTIVE: 'active', + RECOMMENDED: 'recommended', + _recommended: [], _containers: {}, _progress: {}, _logs: {}, - _active: null, _pullScratchImage: function (callback) { var image = docker.client().getImage('scratch:latest'); image.inspect(function (err, data) { @@ -101,7 +101,9 @@ var ContainerStore = assign(EventEmitter.prototype, { // Refresh with docker & hook into events var self = this; this.update(function (err) { - callback(); + self.updateRecommended(function (err) { + callback(); + }); var downloading = _.filter(_.values(self._containers), function (container) { var env = container.Config.Env; return _.indexOf(env, 'KITEMATIC_DOWNLOADING=true') !== -1; @@ -168,6 +170,30 @@ var ContainerStore = assign(EventEmitter.prototype, { }); }); }, + updateRecommended: function (callback) { + var self = this; + $.ajax({ + url: 'https://kitematic.com/recommended.json', + dataType: 'json', + success: function (res, status) { + var recommended = res.recommended; + async.map(recommended, function (repository, callback) { + $.get('https://registry.hub.docker.com/v1/search?q=' + repository, function (data) { + var results = data.results; + callback(null, _.find(results, function (r) { + return r.name === repository; + })); + }); + }, function (err, results) { + self._recommended = results; + callback(); + }); + }, + error: function (err) { + console.log(err); + } + }); + }, create: function (repository, tag, callback) { tag = tag || 'latest'; var self = this; @@ -213,7 +239,6 @@ var ContainerStore = assign(EventEmitter.prototype, { }, {}); self._progress[containerName] = 0; - self.emit(containerName); stream.on('data', function (str) { console.log(str); @@ -253,26 +278,19 @@ var ContainerStore = assign(EventEmitter.prototype, { // If not then directly create the container self._createContainer(imageName, containerName, function () { callback(null, containerName); - console.log('done'); }); } }); }, - setActive: function (name) { - console.log('set active'); - this._active = name; - this.emit(this.ACTIVE); - }, - active: function () { - return this._active; - }, - // Returns all containers containers: function() { return this._containers; }, container: function (name) { return this._containers[name]; }, + recommended: function () { + return this._recommended; + }, progress: function (name) { return this._progress[name]; }, diff --git a/app/styles/containers.less b/app/styles/containers.less index 14aa1cdc43..a8944625bd 100644 --- a/app/styles/containers.less +++ b/app/styles/containers.less @@ -233,7 +233,12 @@ display: flex; flex-direction: row; padding: 0px 45px 14px; - background: white; + position: relative; + a { + position: absolute; + right: 30px; + top: -4px; + } h1 { font-size: 24px; margin: 0; @@ -253,6 +258,11 @@ } } + .details-progress { + margin: 26% auto 0; + width: 300px; + } + .details-logs { flex: 1; overflow: auto;