diff --git a/.gitignore b/.gitignore index 7b9e66caf1..ca23db9e8a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ build dist node_modules +coverage npm-debug.log # Signing Identity diff --git a/.jshintrc b/.jshintrc index 9240a3ae9f..daeaf45072 100644 --- a/.jshintrc +++ b/.jshintrc @@ -27,5 +27,5 @@ "jest": true, "pit": true }, - "predef": [ "-Promise" ] + "predef": [ "Promise" ] } diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..8d530885bf --- /dev/null +++ b/.travis.yml @@ -0,0 +1,12 @@ +language: node_js +node_js: + - "0.10" + +sudo: false + +cache: + - resources + - node_modules + +after_success: + which ./node_modules/coveralls/bin/coveralls.js && cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2f2537d80d..3fe22bdc17 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,12 +6,30 @@ Before you fil an issue or a pull request, quickly read of the following tips on ## Table of Contents + - [Development](#development) - [GitHub Issues](#github-issues) - - [Pull Requests](#submitting-pull-requests) + - [Pull Requests](#pull-requests) - [Code Guidelines](#code-guidelines) - [Testing](#testing) - [License](#license) +### Development + +- `npm install` + +To run the app in development: + +- `npm start` + +### Building & Release + +- `npm run release` + +### Unit Tests + +- `npm test` + + ## GitHub Issues Please try and label any issue as: @@ -35,6 +53,10 @@ We're thrilled to receive pull requests of any kind. Anything from bug fix, test That said, please let us know what you're planning to do! For large changes always create a proposal. Maintainers will love to give you advice on building it and it keeps the app's design coherent. +### Pull Request Requirements: +- Tests +- [Signed Off](https://github.com/docker/docker/blob/master/CONTRIBUTING.md#sign-your-work) + ## Code Guidelines ### Javascript diff --git a/README.md b/README.md index a04fc308fc..84d453e802 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ [![CircleCI](https://img.shields.io/circleci/project/kitematic/kitematic.svg)](https://circleci.com/gh/kitematic/kitematic/tree/master) +[![Coverage Status](https://coveralls.io/repos/kitematic/kitematic/badge.svg?branch=master)](https://coveralls.io/r/kitematic/kitematic?branch=master) [![bitHound Score](https://app.bithound.io/kitematic/kitematic/badges/score.svg)](http://app.bithound.io/kitematic/kitematic) +[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/kitematic/kitematic?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) ![Kitematic Logo](https://cloud.githubusercontent.com/assets/251292/5269258/1b229c3c-7a2f-11e4-96f1-e7baf3c86d73.png) -Kitematic is a simple application for managing Docker containers on Mac OS X. +Kitematic is a simple application for managing Docker containers on Mac OS X and Windows (coming soon!). ## Installing Kitematic @@ -13,21 +15,23 @@ Kitematic is a simple application for managing Docker containers on Mac OS X. Kitematic's documentation and other information can be found at [http://kitematic.com/docs](http://kitematic.com/docs). -### Development +## Bugs and Feature Requests -- `npm install` +Have a bug or a feature request? Please first read the [Issue Guidelines](https://github.com/kitematic/kitematic/blob/master/CONTRIBUTING.md#using-the-issue-tracker) and search for existing and closed issues. If your problem or idea is not addressed yet, [please open a new issue](https://github.com/kitematic/kitematic/issues/new). -To run the app in development: +## Roadmap & Contributing -- `npm start` +We welcome all pull requests and contributions that anyone would like to make. The Kitematic team is super happy to support anyone who wants to get involved. Please checkout our [roadmap](ROADMAP.md) that we keep up to date for ideas to help you with contributing. We would love to talk to you about contributing. Please ask us questions and discuss contributions on our [dedicated contributors forum](https://dev.dockerproject.com/c/kitematic). -### Building the Mac OS X Package +Please read through our [Contributing Guidelines](https://github.com/kitematic/kitematic/blob/master/CONTRIBUTING.md). Included are directions for opening issues, coding standards, and notes on development. -- `npm run release` +## Community -### Unit Tests - -- `npm test` +- For questions on how to use Kitematic, see our [user forum](https://forums.docker.com/c/kitematic). +- **#kitematic** on IRC. [Join the channel](http://webchat.freenode.net/?channels=%23kitematic&uio=d4). +- Join the Kitematic [Gitter Channel](https://gitter.im/kitematic/kitematic) +- Follow [@kitematic on Twitter](https://twitter.com/kitematic). +- Read and subscribe to [the Kitematic Blog](http://blog.kitematic.com). ## Uninstalling @@ -38,23 +42,6 @@ To run the app in development: rm -rf ~/Library/Application\ Support/Kitematic ``` -## Bugs and Feature Requests - -Have a bug or a feature request? Please first read the [Issue Guidelines](https://github.com/kitematic/kitematic/blob/master/CONTRIBUTING.md#using-the-issue-tracker) and search for existing and closed issues. If your problem or idea is not addressed yet, [please open a new issue](https://github.com/kitematic/kitematic/issues/new). - -## Roadmap & Contributing - -We will be accepting pull requests that help with our [roadmap](ROADMAP.md). - -Please read through our [Contributing Guidelines](https://github.com/kitematic/kitematic/blob/master/CONTRIBUTING.md). Included are directions for opening issues, coding standards, and notes on development. - -## Community - -Keep track of development and community news. - -- Follow [@kitematic on Twitter](https://twitter.com/kitematic). -- Read and subscribe to [The Kitematic Blog](http://blog.kitematic.com). - ## Copyright and License Code released under the [Apache license](LICENSE). diff --git a/ROADMAP.md b/ROADMAP.md index 5e85569825..35adb0cbc6 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,7 +1,5 @@ ## Kitematic Roadmap -We will be accepting pull requests that help with our roadmap. - **January 2015** * Automatic updates diff --git a/circle.yml b/circle.yml index 0ddf9ac841..9933147169 100644 --- a/circle.yml +++ b/circle.yml @@ -5,3 +5,6 @@ dependencies: cache_directories: - "resources" - "node_modules" +notify: + webhooks: + - url: https://coveralls.io/webhook diff --git a/images/button-restart.png b/images/button-restart.png index 69f030d3ec..0cf9ae43ce 100644 Binary files a/images/button-restart.png and b/images/button-restart.png differ diff --git a/images/button-restart@2x.png b/images/button-restart@2x.png index c710010d35..bb62729cb3 100644 Binary files a/images/button-restart@2x.png and b/images/button-restart@2x.png differ diff --git a/images/button-terminal.png b/images/button-terminal.png index e64a22aa5e..cfcedd974f 100644 Binary files a/images/button-terminal.png and b/images/button-terminal.png differ diff --git a/images/button-terminal@2x.png b/images/button-terminal@2x.png index be2c92fa24..658786d3f6 100644 Binary files a/images/button-terminal@2x.png and b/images/button-terminal@2x.png differ diff --git a/images/button-view.png b/images/button-view.png index 4d67f928f4..0eb0c2e5bd 100644 Binary files a/images/button-view.png and b/images/button-view.png differ diff --git a/images/button-view@2x.png b/images/button-view@2x.png index a445545558..9a9e206961 100644 Binary files a/images/button-view@2x.png and b/images/button-view@2x.png differ diff --git a/index.html b/index.html index 86d233b8db..2301b021e4 100644 --- a/index.html +++ b/index.html @@ -6,6 +6,6 @@ Kitematic - + diff --git a/package.json b/package.json index c7f5153e58..057aac3a84 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "Kitematic", - "version": "0.5.11", + "version": "0.5.13", "author": "Kitematic", "description": "Simple Docker Container management for Mac OS X.", "homepage": "https://kitematic.com/", @@ -12,7 +12,7 @@ "bugs": "https://github.com/kitematic/kitematic/issues", "scripts": { "start": "gulp", - "test": "jest", + "test": "jest --coverage", "release": "gulp release", "release:beta": "gulp release --beta", "preinstall": "./util/deps", @@ -28,30 +28,36 @@ "jest": { "scriptPreprocessor": "/util/preprocessor.js", "setupEnvScriptFile": "/util/testenv.js", + "collectCoverage": true, + "testDirectoryName": "src", + "testPathIgnorePatterns": [ + "/node_modules/", + "^((?!-test).)*$" + ], "unmockedModulePathPatterns": [ + "stream", "tty", "net", "crypto", - "stream", + "/node_modules/.*JSONStream", "/node_modules/object-assign", "/node_modules/underscore", - "/node_modules/react", - "/node_modules/bluebird", - "/node_modules/babel" + "/node_modules/bluebird" ] }, "docker-version": "1.5.0", "docker-machine-version": "0.1.0-kitematic-0.5.10", "atom-shell-version": "0.21.3", - "virtualbox-version": "4.3.24", - "virtualbox-filename": "VirtualBox-4.3.24.pkg", - "virtualbox-checksum": "100eee21df3808fc1b1e461e86f10b6d2a748935c5f31bc665f4ff0777e44a0b", + "virtualbox-version": "4.3.26", + "virtualbox-filename": "VirtualBox-4.3.26.pkg", + "virtualbox-checksum": "668f61c95efe37f8fc65cafe95b866fba64e37f2492dfc1e2b44a7ac3dcafa3b", "dependencies": { "ansi-to-html": "0.3.0", "async": "^0.9.0", "bluebird": "^2.9.12", "bugsnag-js": "^2.4.7", - "dockerode": "^2.0.7", + "coveralls": "^2.11.2", + "dockerode": "^2.1.1", "exec": "0.2.0", "jquery": "^2.1.3", "minimist": "^1.1.0", @@ -76,6 +82,7 @@ "gulp-cssmin": "^0.1.6", "gulp-download-atom-shell": "0.0.4", "gulp-if": "^1.2.5", + "gulp-insert": "^0.4.0", "gulp-less": "^3.0.1", "gulp-livereload": "^3.8.0", "gulp-plumber": "^0.6.6", @@ -83,7 +90,7 @@ "gulp-shell": "^0.3.0", "gulp-sourcemaps": "^1.5.0", "gulp-util": "^3.0.4", - "jest-cli": "^0.4.0", + "jest-cli": "kitematic/jest", "jsxhint": "^0.12.1", "react-tools": "^0.12.2", "run-sequence": "^1.0.2" diff --git a/src/ContainerDetailsSubheader.react.js b/src/ContainerDetailsSubheader.react.js index 2978175e54..8b44ea8c62 100644 --- a/src/ContainerDetailsSubheader.react.js +++ b/src/ContainerDetailsSubheader.react.js @@ -107,7 +107,7 @@ var ContainerDetailsSubheader = React.createClass({ var container = this.props.container; var terminal = path.join(process.cwd(), 'resources', 'terminal'); machine.ip().then(ip => { - var cmd = [terminal, 'ssh', '-o', 'UserKnownHostsFile=/dev/null', '-o', 'LogLevel=quiet', '-o', 'StrictHostKeyChecking=no', '-i', '~/.docker/machine/machines/' + machine.name() + '/id_rsa', 'docker@' + ip, '-t', 'docker', 'exec', '-i', '-t', container.Name, 'sh']; + var cmd = [terminal, 'ssh', '-p', '22', '-o', 'UserKnownHostsFile=/dev/null', '-o', 'LogLevel=quiet', '-o', 'StrictHostKeyChecking=no', '-i', '~/.docker/machine/machines/' + machine.name() + '/id_rsa', 'docker@' + ip, '-t', 'docker', 'exec', '-i', '-t', container.Name, 'sh']; exec(cmd, function (stderr, stdout, code) { if (code) { console.log(stderr); diff --git a/src/ContainerHome.react.js b/src/ContainerHome.react.js index bb3c4655f1..530e1b2668 100644 --- a/src/ContainerHome.react.js +++ b/src/ContainerHome.react.js @@ -74,7 +74,9 @@ var ContainerHome = React.createClass({ if (this.props.error) { body = (
-

There was a problem connecting to the Docker Engine in the VirtualBox VM.
This could be caused because this Mac is currently connected to a VPN, blocking access to the VM. If the issue persists, please file a ticket on our GitHub repo.

+

An error occurred:

+

{this.props.error.statusCode} {this.props.error.reason} - {this.props.error.json}

+

If you feel that this error is invalid, please file a ticket on our GitHub repo.

); diff --git a/src/ContainerHomeFolders.react.js b/src/ContainerHomeFolders.react.js index 513cc974b5..1ace6d4e90 100644 --- a/src/ContainerHomeFolders.react.js +++ b/src/ContainerHomeFolders.react.js @@ -2,19 +2,38 @@ var _ = require('underscore'); var React = require('react/addons'); var RetinaImage = require('react-retina-image'); var path = require('path'); -var exec = require('exec'); +var shell = require('shell'); +var util = require('./Util'); var metrics = require('./Metrics'); var Router = require('react-router'); +var ContainerStore = require('./ContainerStore'); var ContainerHomeFolder = React.createClass({ mixins: [Router.State, Router.Navigation], - handleClickFolder: function (path) { + handleClickFolder: function (hostVolume, containerVolume) { metrics.track('Opened Volume Directory', { from: 'home' }); - exec(['open', path], function (err) { - if (err) { throw err; } - }); + + if (hostVolume.indexOf(process.env.HOME) === -1) { + var volumes = _.clone(this.props.container.Volumes); + var newHostVolume = path.join(util.home(), 'Kitematic', this.props.container.Name, containerVolume); + volumes[containerVolume] = newHostVolume; + var binds = _.pairs(volumes).map(function (pair) { + return pair[1] + ':' + pair[0]; + }); + ContainerStore.updateContainer(this.props.container.Name, { + Binds: binds + }, function (err) { + if (err) { + console.log(err); + return; + } + shell.showItemInFolder(newHostVolume); + }); + } else { + shell.showItemInFolder(hostVolume); + } }, handleClickChangeFolders: function () { metrics.track('Viewed Volume Settings', { @@ -23,24 +42,21 @@ var ContainerHomeFolder = React.createClass({ this.transitionTo('containerSettingsVolumes', {name: this.getParams().name}); }, render: function () { - var folders; - if (this.props.container) { - var self = this; - folders = _.map(self.props.container.Volumes, function (val, key) { - var firstFolder = key.split(path.sep)[1]; - if (!val || val.indexOf(process.env.HOME) === -1) { - return; - } else { - return ( -
- -
{firstFolder}
-
- ); - } - }); + if (!this.props.container) { + return false; } - if (this.props.container && this.props.container.Volumes && _.keys(this.props.container.Volumes).length > 0 && this.props.container.State.Running) { + + var folders = _.map(this.props.container.Volumes, (val, key) => { + var firstFolder = key.split(path.sep)[1]; + return ( +
+ +
{firstFolder}
+
+ ); + }); + + if (this.props.container.Volumes && _.keys(this.props.container.Volumes).length > 0 && this.props.container.State.Running) { return (

Edit Files

@@ -51,9 +67,7 @@ var ContainerHomeFolder = React.createClass({
); } else { - return ( -
- ); + return false; } } }); diff --git a/src/ContainerHomeLogs.react.js b/src/ContainerHomeLogs.react.js index a13f310c3c..d400a48d72 100644 --- a/src/ContainerHomeLogs.react.js +++ b/src/ContainerHomeLogs.react.js @@ -52,6 +52,9 @@ var ContainerHomeLogs = React.createClass({ var logs = this.state.logs.map(function (l, i) { return

; }); + if (logs.length === 0) { + logs = "No logs for this container."; + } return (

Logs

diff --git a/src/ContainerHomePreview.react.js b/src/ContainerHomePreview.react.js index 9e0d21a108..e03c448411 100644 --- a/src/ContainerHomePreview.react.js +++ b/src/ContainerHomePreview.react.js @@ -37,9 +37,6 @@ var ContainerHomePreview = React.createClass({ }); } }, - componentDidUpdate: function () { - this.reload(); - }, componentWillUnmount: function() { clearInterval(this.timer); }, diff --git a/src/ContainerLogs.react.js b/src/ContainerLogs.react.js index cdde86f4d2..e20910cc49 100644 --- a/src/ContainerLogs.react.js +++ b/src/ContainerLogs.react.js @@ -45,6 +45,9 @@ var ContainerLogs = React.createClass({ var logs = this.state.logs.map(function (l, i) { return

; }); + if (logs.length === 0) { + logs = "No logs for this container."; + } return (
{logs} diff --git a/src/ContainerSettingsVolumes.react.js b/src/ContainerSettingsVolumes.react.js index 32e699449e..cb470e75aa 100644 --- a/src/ContainerSettingsVolumes.react.js +++ b/src/ContainerSettingsVolumes.react.js @@ -31,6 +31,21 @@ var ContainerSettingsVolumes = React.createClass({ } }); }, + handleRemoveVolumeClick: function (dockerVol) { + metrics.track('Removed Volume Directory', { + from: 'settings' + }); + var volumes = _.clone(this.props.container.Volumes); + delete volumes[dockerVol]; + var binds = _.pairs(volumes).map(function (pair) { + return pair[1] + ':' + pair[0]; + }); + ContainerStore.updateContainer(this.props.container.Name, { + Binds: binds + }, function (err) { + if (err) { console.log(err); } + }); + }, handleOpenVolumeClick: function (path) { metrics.track('Opened Volume Directory', { from: 'settings' @@ -50,6 +65,7 @@ var ContainerSettingsVolumes = React.createClass({ No Folder Change + Remove ); } else { @@ -57,6 +73,7 @@ var ContainerSettingsVolumes = React.createClass({ {val.replace(process.env.HOME, '~')} Change + Remove ); } diff --git a/src/ContainerStore.js b/src/ContainerStore.js index 64db81119b..f3c0f5613c 100644 --- a/src/ContainerStore.js +++ b/src/ContainerStore.js @@ -1,14 +1,12 @@ var _ = require('underscore'); var EventEmitter = require('events').EventEmitter; var async = require('async'); -var path = require('path'); var assign = require('object-assign'); var docker = require('./Docker'); var metrics = require('./Metrics'); var registry = require('./Registry'); var logstore = require('./LogStore'); var bugsnag = require('bugsnag-js'); -var util = require('./Util'); var _placeholders = {}; var _containers = {}; @@ -59,6 +57,12 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), { var data = JSON.parse(str); console.log(data); + if (data.error) { + _error = data.error; + callback(data.error); + return; + } + if (data.status && (data.status === 'Pulling dependent layers' || data.status.indexOf('already being pulled by another client') !== -1)) { blockedCallback(); return; @@ -85,7 +89,8 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), { progressCallback(totalProgress); }); stream.on('end', function () { - callback(); + callback(_error); + _error = null; }); }); }); @@ -93,38 +98,22 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), { }, _startContainer: function (name, containerData, callback) { var self = this; - docker.client().getImage(containerData.Image).inspect(function (err, data) { + var binds = containerData.Binds || []; + var startopts = { + Binds: binds + }; + if (containerData.NetworkSettings && containerData.NetworkSettings.Ports) { + startopts.PortBindings = containerData.NetworkSettings.Ports; + } else{ + startopts.PublishAllPorts = true; + } + var container = docker.client().getContainer(name); + container.start(startopts, function (err) { if (err) { callback(err); return; } - var binds = containerData.Binds || []; - if (data.Config.Volumes) { - _.each(data.Config.Volumes, function (value, key) { - var existingBind = _.find(binds, b => { - return b.indexOf(':' + key) !== -1; - }); - if (!existingBind) { - binds.push(path.join(util.home(), 'Kitematic', name, key)+ ':' + key); - } - }); - } - var startopts = { - Binds: binds - }; - if (containerData.NetworkSettings && containerData.NetworkSettings.Ports) { - startopts.PortBindings = containerData.NetworkSettings.Ports; - } else{ - startopts.PublishAllPorts = true; - } - var container = docker.client().getContainer(name); - container.start(startopts, function (err) { - if (err) { - callback(err); - return; - } - self.fetchContainer(name, callback); - }); + self.fetchContainer(name, callback); }); }, _createContainer: function (name, containerData, callback) { @@ -138,6 +127,9 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), { if (containerData.Config && containerData.Config.Image) { containerData.Image = containerData.Config.Image; } + if (!containerData.Env && containerData.Config && containerData.Config.Env) { + containerData.Env = containerData.Config.Env; + } existing.kill(function () { existing.remove(function () { docker.client().createContainer(containerData, function (err) { @@ -145,11 +137,7 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), { callback(err, null); return; } - if (containerData.State && !containerData.State.Running) { - self.fetchContainer(containerData.name, callback); - } else { - self._startContainer(name, containerData, callback); - } + self._startContainer(name, containerData, callback); }); }); }); diff --git a/src/ImageCard.react.js b/src/ImageCard.react.js index b132aec25f..659d1407e6 100644 --- a/src/ImageCard.react.js +++ b/src/ImageCard.react.js @@ -5,6 +5,7 @@ var ContainerStore = require('./ContainerStore'); var metrics = require('./Metrics'); var OverlayTrigger = require('react-bootstrap').OverlayTrigger; var Tooltip = require('react-bootstrap').Tooltip; +var util = require('./Util'); var ImageCard = React.createClass({ getInitialState: function () { @@ -30,16 +31,33 @@ var ImageCard = React.createClass({ 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) { + $.get('https://registry.hub.docker.com/v1/repositories/' + name + '/tags', result => { this.setState({ tags: result }); - }.bind(this)); + }); }, handleCloseTagOverlay: function () { var $tagOverlay = $(this.getDOMNode()).find('.tag-overlay'); $tagOverlay.fadeOut(300); }, + handleRepoClick: function () { + var $repoUri = 'https://registry.hub.docker.com/'; + if (this.props.image.is_official) { + $repoUri = $repoUri + "_/"; + } else { + $repoUri = $repoUri + "u/"; + } + util.exec(['open', $repoUri + this.props.image.name]); + }, + componentDidMount: function() { + $.get('https://registry.hub.docker.com/v1/repositories/' + this.props.image.name + '/tags', result => { + this.setState({ + tags: result, + chosenTag: result[0].name + }); + }); + }, render: function () { var self = this; var name; @@ -57,8 +75,8 @@ var ImageCard = React.createClass({ name = (
{namespace}
- {this.props.image.name}}> - {repo} + View on DockerHub}> + {repo}
); @@ -66,8 +84,8 @@ var ImageCard = React.createClass({ name = (
{namespace}
- {this.props.image.name}}> - {repo} + View on DockerHub}> + {repo}
); diff --git a/__tests__/SetupStore-test.js b/src/SetupStore-test.js similarity index 92% rename from __tests__/SetupStore-test.js rename to src/SetupStore-test.js index 1410a883b0..42add6fd37 100644 --- a/__tests__/SetupStore-test.js +++ b/src/SetupStore-test.js @@ -1,10 +1,9 @@ -jest.dontMock('../src/SetupStore'); -var setupStore = require('../src/SetupStore'); -var virtualBox = require('../src/VirtualBox'); -var util = require('../src/Util'); -var machine = require('../src/DockerMachine'); -var setupUtil = require('../src/SetupUtil'); -var Promise = require('bluebird'); +jest.dontMock('./SetupStore'); +var setupStore = require('./SetupStore'); +var virtualBox = require('./VirtualBox'); +var util = require('./Util'); +var machine = require('./DockerMachine'); +var setupUtil = require('./SetupUtil'); describe('SetupStore', function () { describe('download step', function () { diff --git a/src/Startup.js b/src/Startup.js new file mode 100644 index 0000000000..03f16bf78f --- /dev/null +++ b/src/Startup.js @@ -0,0 +1 @@ +require('./Main'); \ No newline at end of file diff --git a/__tests__/Virtualbox-test.js b/src/Virtualbox-test.js similarity index 76% rename from __tests__/Virtualbox-test.js rename to src/Virtualbox-test.js index 1a8efa7aab..567210a08a 100644 --- a/__tests__/Virtualbox-test.js +++ b/src/Virtualbox-test.js @@ -1,7 +1,6 @@ -jest.dontMock('../src/VirtualBox'); -var virtualBox = require('../src/VirtualBox'); -var util = require('../src/Util'); -var Promise = require('bluebird'); +jest.dontMock('./VirtualBox'); +var virtualBox = require('./VirtualBox'); +var util = require('./Util'); describe('VirtualBox', function () { it('returns the right command', function () { diff --git a/styles/left-panel.less b/styles/left-panel.less index ecba94e97c..2aa98270fc 100644 --- a/styles/left-panel.less +++ b/styles/left-panel.less @@ -201,7 +201,7 @@ left: -20px; .at2x('runningwave.png', 20px, 20px); -webkit-animation-name: translatewave; - -webkit-animation-duration: 8.0s; + -webkit-animation-duration: 7.0s; -webkit-animation-iteration-count: infinite; -webkit-animation-timing-function: linear; } diff --git a/styles/new-container.less b/styles/new-container.less index 0a201ae8f3..a00f9c3eb3 100644 --- a/styles/new-container.less +++ b/styles/new-container.less @@ -186,6 +186,7 @@ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + text-decoration: underline; } } .description { diff --git a/styles/right-panel.less b/styles/right-panel.less index 2d5af45524..384b3e8934 100644 --- a/styles/right-panel.less +++ b/styles/right-panel.less @@ -25,7 +25,6 @@ .action { display: inline-block; position: relative; - top: 10px; &.disabled { opacity: 0.3; } @@ -36,11 +35,11 @@ .btn-label { position: absolute; color: @brand-action; - font-size: 10px; + font-size: 9px; width: 200px; - top: 30px; + top: 45px; &.view { - left: 6px; + left: 7px; //left: 0px; } &.restart {