diff --git a/.jshintrc b/.jshintrc index daeaf45072..9240a3ae9f 100644 --- a/.jshintrc +++ b/.jshintrc @@ -27,5 +27,5 @@ "jest": true, "pit": true }, - "predef": [ "Promise" ] + "predef": [ "-Promise" ] } diff --git a/package.json b/package.json index 2ac0a9d617..99fbf376b2 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "async": "^0.9.0", "bluebird": "^2.9.24", "bugsnag-js": "^2.4.7", + "classnames": "^1.2.0", "coveralls": "^2.11.2", "dockerode": "^2.1.1", "exec": "0.2.0", @@ -89,7 +90,6 @@ "gulp-shell": "^0.4.1", "gulp-sourcemaps": "^1.5.2", "gulp-util": "^3.0.4", - "gulp": "^3.8.11", "jest-cli": "kitematic/jest", "jsxhint": "^0.14.0", "minimist": "^1.1.1", diff --git a/src/ContainerDetails.react.js b/src/ContainerDetails.react.js index f101b603ba..b18d69819b 100644 --- a/src/ContainerDetails.react.js +++ b/src/ContainerDetails.react.js @@ -5,7 +5,9 @@ var ContainerDetailsSubheader = require('./ContainerDetailsSubheader.react'); var Router = require('react-router'); var ContainerDetail = React.createClass({ - mixins: [Router.State, Router.Navigation], + contextTypes: { + router: React.PropTypes.func + }, getInitialState: function () { return { currentRoute: null @@ -18,9 +20,9 @@ var ContainerDetail = React.createClass({ this.init(); }, init: function () { - var currentRoute = _.last(this.getRoutes()).name; + var currentRoute = _.last(this.context.router.getCurrentRoutes()).name; if (currentRoute === 'containerDetails') { - this.transitionTo('containerHome', {name: this.getParams().name}); + this.context.router.transitionTo('containerHome', {name: this.context.router.getCurrentParams().name}); } }, render: function () { diff --git a/src/ContainerDetailsSubheader.react.js b/src/ContainerDetailsSubheader.react.js index 8b44ea8c62..377dfcfa72 100644 --- a/src/ContainerDetailsSubheader.react.js +++ b/src/ContainerDetailsSubheader.react.js @@ -1,6 +1,6 @@ var _ = require('underscore'); var $ = require('jquery'); -var React = require('react/addons'); +var React = require('react'); var exec = require('exec'); var path = require('path'); var metrics = require('./Metrics'); @@ -8,11 +8,13 @@ var ContainerStore = require('./ContainerStore'); var ContainerUtil = require('./ContainerUtil'); var machine = require('./DockerMachine'); var RetinaImage = require('react-retina-image'); -var Router = require('react-router'); var webPorts = require('./Util').webPorts; +var classNames = require('classNames'); var ContainerDetailsSubheader = React.createClass({ - mixins: [Router.State, Router.Navigation], + contextTypes: { + router: React.PropTypes.func + }, getInitialState: function () { return { defaultPort: null @@ -26,9 +28,9 @@ var ContainerDetailsSubheader = React.createClass({ }, init: function () { this.setState({ - currentRoute: _.last(this.getRoutes()).name + currentRoute: _.last(this.context.router.getCurrentRoutes()).name }); - var container = ContainerStore.container(this.getParams().name); + var container = ContainerStore.container(this.context.router.getCurrentParams().name); if (!container) { return; } @@ -69,19 +71,19 @@ var ContainerDetailsSubheader = React.createClass({ metrics.track('Viewed Home', { from: 'header' }); - this.transitionTo('containerHome', {name: this.getParams().name}); + this.context.router.transitionTo('containerHome', {name: this.context.router.getCurrentParams().name}); } }, showLogs: function () { if (!this.disableTab()) { metrics.track('Viewed Logs'); - this.transitionTo('containerLogs', {name: this.getParams().name}); + this.context.router.transitionTo('containerLogs', {name: this.context.router.getCurrentParams().name}); } }, showSettings: function () { if (!this.disableTab()) { metrics.track('Viewed Settings'); - this.transitionTo('containerSettings', {name: this.getParams().name}); + this.context.router.transitionTo('containerSettings', {name: this.context.router.getCurrentParams().name}); } }, handleRun: function () { @@ -141,29 +143,29 @@ var ContainerDetailsSubheader = React.createClass({ $action.css("visibility", "hidden"); }, render: function () { - var runActionClass = React.addons.classSet({ + var runActionClass = classNames({ action: true, disabled: this.disableRun() }); - var restartActionClass = React.addons.classSet({ + var restartActionClass = classNames({ action: true, disabled: this.disableRestart() }); - var terminalActionClass = React.addons.classSet({ + var terminalActionClass = classNames({ action: true, disabled: this.disableTerminal() }); - var tabHomeClasses = React.addons.classSet({ + var tabHomeClasses = classNames({ 'tab': true, 'active': this.state.currentRoute === 'containerHome', disabled: this.disableTab() }); - var tabLogsClasses = React.addons.classSet({ + var tabLogsClasses = classNames({ 'tab': true, 'active': this.state.currentRoute === 'containerLogs', disabled: this.disableTab() }); - var tabSettingsClasses = React.addons.classSet({ + var tabSettingsClasses = classNames({ 'tab': true, 'active': this.state.currentRoute && (this.state.currentRoute.indexOf('containerSettings') >= 0), disabled: this.disableTab() diff --git a/src/ContainerHome.react.js b/src/ContainerHome.react.js index a25fa678b5..9495a2f235 100644 --- a/src/ContainerHome.react.js +++ b/src/ContainerHome.react.js @@ -2,7 +2,6 @@ var _ = require('underscore'); var $ = require('jquery'); var React = require('react/addons'); var ContainerStore = require('./ContainerStore'); -var Router = require('react-router'); var Radial = require('./Radial.react'); var ContainerHomePreview = require('./ContainerHomePreview.react'); var ContainerHomeLogs = require('./ContainerHomeLogs.react'); @@ -16,7 +15,9 @@ var resizeWindow = function () { }; var ContainerHome = React.createClass({ - mixins: [Router.State, Router.Navigation], + contextTypes: { + router: React.PropTypes.func + }, getInitialState: function () { return { ports: {}, @@ -47,7 +48,7 @@ var ContainerHome = React.createClass({ resizeWindow(); }, init: function () { - var container = ContainerStore.container(this.getParams().name); + var container = ContainerStore.container(this.context.router.getCurrentParams().name); if (!container) { return; } @@ -57,12 +58,12 @@ var ContainerHome = React.createClass({ defaultPort: _.find(_.keys(ports), function (port) { return util.webPorts.indexOf(port) !== -1; }), - progress: ContainerStore.progress(this.getParams().name), - blocked: ContainerStore.blocked(this.getParams().name) + progress: ContainerStore.progress(this.context.router.getCurrentParams().name), + blocked: ContainerStore.blocked(this.context.router.getCurrentParams().name) }); }, updateProgress: function (name) { - if (name === this.getParams().name) { + if (name === this.context.router.getCurrentParams().name) { this.setState({ blocked: ContainerStore.blocked(name), progress: ContainerStore.progress(name) diff --git a/src/ContainerHomeFolders.react.js b/src/ContainerHomeFolders.react.js index 1ace6d4e90..ca2760c3db 100644 --- a/src/ContainerHomeFolders.react.js +++ b/src/ContainerHomeFolders.react.js @@ -5,11 +5,12 @@ var path = require('path'); 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], + contextTypes: { + router: React.PropTypes.func + }, handleClickFolder: function (hostVolume, containerVolume) { metrics.track('Opened Volume Directory', { from: 'home' @@ -39,7 +40,7 @@ var ContainerHomeFolder = React.createClass({ metrics.track('Viewed Volume Settings', { from: 'preview' }); - this.transitionTo('containerSettingsVolumes', {name: this.getParams().name}); + this.context.router.transitionTo('containerSettingsVolumes', {name: this.context.router.getCurrentParams().name}); }, render: function () { if (!this.props.container) { diff --git a/src/ContainerHomeLogs.react.js b/src/ContainerHomeLogs.react.js index fba6a1b4f4..771765dfa9 100644 --- a/src/ContainerHomeLogs.react.js +++ b/src/ContainerHomeLogs.react.js @@ -44,9 +44,12 @@ module.exports = React.createClass({ metrics.track('Viewed Logs', { from: 'preview' }); - this.transitionTo('containerLogs', {name: this.props.container.Name}); + this.context.router.transitionTo('containerLogs', {name: this.props.container.Name}); }, update: function () { + if (!this.props.container) { + return; + } this.setState({ logs: LogStore.logs(this.props.container.Name) }); diff --git a/src/ContainerHomePreview.react.js b/src/ContainerHomePreview.react.js index e03c448411..34fa82bd26 100644 --- a/src/ContainerHomePreview.react.js +++ b/src/ContainerHomePreview.react.js @@ -3,13 +3,14 @@ var React = require('react/addons'); var exec = require('exec'); var ContainerStore = require('./ContainerStore'); var ContainerUtil = require('./ContainerUtil'); -var Router = require('react-router'); var request = require('request'); var metrics = require('./Metrics'); var webPorts = require('./Util').webPorts; var ContainerHomePreview = React.createClass({ - mixins: [Router.State, Router.Navigation], + contextTypes: { + router: React.PropTypes.func + }, getInitialState: function () { return { ports: {}, @@ -41,7 +42,7 @@ var ContainerHomePreview = React.createClass({ clearInterval(this.timer); }, init: function () { - var container = ContainerStore.container(this.getParams().name); + var container = ContainerStore.container(this.context.router.getCurrentParams().name); if (!container) { return; } @@ -67,7 +68,7 @@ var ContainerHomePreview = React.createClass({ metrics.track('Viewed Port Settings', { from: 'preview' }); - this.transitionTo('containerSettingsPorts', {name: this.getParams().name}); + this.context.router.transitionTo('containerSettingsPorts', {name: this.context.router.getCurrentParams().name}); }, render: function () { var preview; diff --git a/src/ContainerListNewItem.react.js b/src/ContainerListNewItem.react.js index 21c3d53c45..108e7b78e4 100644 --- a/src/ContainerListNewItem.react.js +++ b/src/ContainerListNewItem.react.js @@ -5,7 +5,6 @@ var ContainerStore = require('./ContainerStore'); var metrics = require('./Metrics'); var ContainerListNewItem = React.createClass({ - mixins: [Router.State, Router.Navigation], handleItemMouseEnter: function () { var $action = $(this.getDOMNode()).find('.action'); $action.show(); diff --git a/src/ContainerLogs.react.js b/src/ContainerLogs.react.js index f7b0b24064..36689c44af 100644 --- a/src/ContainerLogs.react.js +++ b/src/ContainerLogs.react.js @@ -20,6 +20,10 @@ module.exports = React.createClass({ LogStore.fetch(this.props.container.Name); }, componentWillUnmount: function() { + if (!this.props.container) { + return; + } + LogStore.detach(this.props.container.Name); LogStore.removeListener(LogStore.SERVER_LOGS_EVENT, this.update); }, @@ -34,6 +38,9 @@ module.exports = React.createClass({ _prevBottom = parent[0].scrollHeight - parent.height(); }, update: function () { + if (!this.props.container) { + return; + } this.setState({ logs: LogStore.logs(this.props.container.Name) }); diff --git a/src/ContainerSettings.react.js b/src/ContainerSettings.react.js index 3b0ba56e88..7a25dd73ae 100644 --- a/src/ContainerSettings.react.js +++ b/src/ContainerSettings.react.js @@ -3,7 +3,9 @@ var React = require('react/addons'); var Router = require('react-router'); var ContainerSettings = React.createClass({ - mixins: [Router.State, Router.Navigation], + contextTypes: { + router: React.PropTypes.func + }, componentWillReceiveProps: function () { this.init(); }, @@ -11,9 +13,9 @@ var ContainerSettings = React.createClass({ this.init(); }, init: function () { - var currentRoute = _.last(this.getRoutes()).name; + var currentRoute = _.last(this.context.router.getCurrentRoutes()).name; if (currentRoute === 'containerSettings') { - this.transitionTo('containerSettingsGeneral', {name: this.getParams().name}); + this.context.router.transitionTo('containerSettingsGeneral', {name: this.context.router.getCurrentParams().name}); } }, render: function () { diff --git a/src/ContainerSettingsGeneral.react.js b/src/ContainerSettingsGeneral.react.js index d44a8baa58..f54728cff7 100644 --- a/src/ContainerSettingsGeneral.react.js +++ b/src/ContainerSettingsGeneral.react.js @@ -28,7 +28,9 @@ var containerNameSlugify = function (text) { }; var ContainerSettingsGeneral = React.createClass({ - mixins: [Router.State, Router.Navigation], + contextTypes: { + router: React.PropTypes.func + }, getInitialState: function () { return { slugName: null, @@ -44,7 +46,7 @@ var ContainerSettingsGeneral = React.createClass({ this.init(); }, init: function () { - var container = ContainerStore.container(this.getParams().name); + var container = ContainerStore.container(this.context.router.getCurrentParams().name); if (!container) { return; } @@ -98,7 +100,7 @@ var ContainerSettingsGeneral = React.createClass({ return; } metrics.track('Changed Container Name'); - this.transitionTo('containerSettingsGeneral', {name: newName}); + this.context.router.transitionTo('containerSettingsGeneral', {name: newName}); var oldPath = path.join(process.env.HOME, 'Kitematic', oldName); var newPath = path.join(process.env.HOME, 'Kitematic', newName); rimraf(newPath, () => { diff --git a/src/ContainerSettingsPorts.react.js b/src/ContainerSettingsPorts.react.js index 64239a084d..21581e76bd 100644 --- a/src/ContainerSettingsPorts.react.js +++ b/src/ContainerSettingsPorts.react.js @@ -1,6 +1,5 @@ var _ = require('underscore'); var React = require('react/addons'); -var Router = require('react-router'); var exec = require('exec'); var ContainerStore = require('./ContainerStore'); var ContainerUtil = require('./ContainerUtil'); @@ -8,7 +7,9 @@ var metrics = require('./Metrics'); var webPorts = require('./Util').webPorts; var ContainerSettingsPorts = React.createClass({ - mixins: [Router.State, Router.Navigation], + contextTypes: { + router: React.PropTypes.func + }, getInitialState: function () { return { ports: {}, @@ -22,7 +23,7 @@ var ContainerSettingsPorts = React.createClass({ this.init(); }, init: function () { - var container = ContainerStore.container(this.getParams().name); + var container = ContainerStore.container(this.context.router.getCurrentParams().name); if (!container) { return; } @@ -43,7 +44,6 @@ var ContainerSettingsPorts = React.createClass({ }); }, handleChangeDefaultPort: function (port, e) { - console.log(e.target.checked); if (e.target.checked) { this.setState({ defaultPort: port diff --git a/src/ContainerSettingsVolumes.react.js b/src/ContainerSettingsVolumes.react.js index cb470e75aa..6108398a0f 100644 --- a/src/ContainerSettingsVolumes.react.js +++ b/src/ContainerSettingsVolumes.react.js @@ -1,6 +1,5 @@ var _ = require('underscore'); var React = require('react/addons'); -var Router = require('react-router'); var remote = require('remote'); var exec = require('exec'); var dialog = remote.require('dialog'); @@ -8,7 +7,6 @@ var metrics = require('./Metrics'); var ContainerStore = require('./ContainerStore'); var ContainerSettingsVolumes = React.createClass({ - mixins: [Router.State, Router.Navigation], handleChooseVolumeClick: function (dockerVol) { var self = this; dialog.showOpenDialog({properties: ['openDirectory', 'createDirectory']}, function (filenames) { diff --git a/src/Containers.react.js b/src/Containers.react.js index af151dabca..c0275e22cd 100644 --- a/src/Containers.react.js +++ b/src/Containers.react.js @@ -15,7 +15,9 @@ var Tooltip = require('react-bootstrap').Tooltip; var util = require('./Util'); var Containers = React.createClass({ - mixins: [Router.Navigation, Router.State], + contextTypes: { + router: React.PropTypes.func + }, getInitialState: function () { return { sidebarOffset: 0, @@ -34,7 +36,7 @@ var Containers = React.createClass({ ContainerStore.on(ContainerStore.CLIENT_CONTAINER_EVENT, this.updateFromClient); if (this.state.sorted.length) { - this.transitionTo('containerHome', {name: this.state.sorted[0].Name}); + this.context.router.transitionTo('containerHome', {name: this.state.sorted[0].Name}); } ipc.on('application:update-available', () => { @@ -50,9 +52,9 @@ var Containers = React.createClass({ }, onDestroy: function () { if (this.state.sorted.length) { - this.transitionTo('containerHome', {name: this.state.sorted[0].Name}); + this.context.router.transitionTo('containerHome', {name: this.state.sorted[0].Name}); } else { - this.transitionTo('containers'); + this.context.router.transitionTo('containers'); } }, updateError: function (err) { @@ -77,7 +79,7 @@ var Containers = React.createClass({ downloading: ContainerStore.downloading() }); if (status === 'create') { - this.transitionTo('containerHome', {name: name}); + this.context.router.transitionTo('containerHome', {name: name}); } else if (status === 'destroy') { this.onDestroy(); } @@ -95,7 +97,7 @@ var Containers = React.createClass({ }, handleNewContainer: function () { $(this.getDOMNode()).find('.new-container-item').parent().fadeIn(); - this.transitionTo('new'); + this.context.router.transitionTo('new'); metrics.track('Pressed New Container'); }, handleAutoUpdateClick: function () { @@ -106,7 +108,7 @@ var Containers = React.createClass({ metrics.track('Opened Preferences', { from: 'app' }); - this.transitionTo('preferences'); + this.context.router.transitionTo('preferences'); }, handleClickDockerTerminal: function () { metrics.track('Opened Docker Terminal', { @@ -173,7 +175,7 @@ var Containers = React.createClass({ button = ; } - var container = this.getParams().name ? this.state.containers[this.getParams().name] : {}; + var container = this.context.router.getCurrentParams().name ? this.state.containers[this.context.router.getCurrentParams().name] : {}; return (