diff --git a/README.md b/README.md index c19be6ee1db..b9486dad3c8 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Differences between the two APIs include a move away from a declarative system o ## Building and Running Open MCT Locally Building and running Open MCT in your local dev environment is very easy. Be sure you have [Git](https://git-scm.com/downloads) and [Node.js](https://nodejs.org/) installed, then follow the directions below. Need additional information? Check out the [Getting Started](https://nasa.github.io/openmct/getting-started/) page on our website. +(These instructions assume you are installing as a non-root user; developers have [reported issues](https://github.com/nasa/openmct/issues/1151) running these steps with root privileges.) 1. Clone the source code diff --git a/app.js b/app.js index 20429a3a5f4..6b7b1bb6350 100644 --- a/app.js +++ b/app.js @@ -67,14 +67,10 @@ }); app.use('/proxyUrl', function proxyRequest(req, res, next) { - var targetUrl = req.query.url; - var queryParameters = req.query; - console.log('Proxying request to: ', targetUrl); - delete queryParameters['url']; + console.log('Proxying request to: ', req.query.url); req.pipe(request({ - url: targetUrl, - strictSSL: false, - qs: queryParameters + url: req.query.url, + strictSSL: false }).on('error', next)).pipe(res); }); diff --git a/gulpfile.js b/gulpfile.js index bf522248635..ff994c6a2c0 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -103,11 +103,6 @@ gulp.task('stylesheets', function () { .pipe(gulp.dest(__dirname)); }); -gulp.task('nsp', function (done) { - var nsp = require('gulp-nsp'); - nsp({package: __dirname + '/package.json'}, done); -}); - gulp.task('lint', function () { var nonspecs = paths.specs.map(function (glob) { return "!" + glob; @@ -157,6 +152,6 @@ gulp.task('develop', ['serve', 'stylesheets', 'watch']); gulp.task('install', [ 'static', 'scripts' ]); -gulp.task('verify', [ 'lint', 'test', 'checkstyle', 'nsp' ]); +gulp.task('verify', [ 'lint', 'test', 'checkstyle' ]); gulp.task('build', [ 'verify', 'install' ]); diff --git a/package.json b/package.json index 5563f65c82a..555375007ea 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,6 @@ "gulp-jscs": "^3.0.2", "gulp-jshint": "^2.0.0", "gulp-jshint-html-reporter": "^0.1.3", - "gulp-nsp": "^2.4.2", "gulp-rename": "^1.2.2", "gulp-replace-task": "^0.11.0", "gulp-requirejs-optimize": "^0.3.1", diff --git a/platform/features/conductor-v2/conductor/bundle.js b/platform/features/conductor-v2/conductor/bundle.js index 438cb33715d..1fbeebdea79 100644 --- a/platform/features/conductor-v2/conductor/bundle.js +++ b/platform/features/conductor-v2/conductor/bundle.js @@ -24,16 +24,18 @@ define([ "./src/ui/TimeConductorViewService", "./src/ui/TimeConductorController", "./src/TimeConductor", + "./src/ui/ConductorAxisController", "./src/ui/MctConductorAxis", "./src/ui/NumberFormat", "text!./res/templates/time-conductor.html", "text!./res/templates/mode-selector/mode-selector.html", "text!./res/templates/mode-selector/mode-menu.html", - 'legacyRegistry' + "legacyRegistry" ], function ( TimeConductorViewService, TimeConductorController, TimeConductor, + ConductorAxisController, MCTConductorAxis, NumberFormat, timeConductorTemplate, @@ -69,6 +71,14 @@ define([ "timeConductorViewService", "timeSystems[]" ] + }, + { + "key": "ConductorAxisController", + "implementation": ConductorAxisController, + "depends": [ + "timeConductor", + "formatService" + ] } ], "directives": [ diff --git a/platform/features/conductor-v2/conductor/res/sass/_time-conductor-base.scss b/platform/features/conductor-v2/conductor/res/sass/_time-conductor-base.scss index 0760d54d14d..22ad33925e2 100644 --- a/platform/features/conductor-v2/conductor/res/sass/_time-conductor-base.scss +++ b/platform/features/conductor-v2/conductor/res/sass/_time-conductor-base.scss @@ -137,6 +137,7 @@ bottom: 0; left: 0; z-index: 1; + pointer-events: none; .l-time-range-w { // Wraps a datetime text input field height: 100%; @@ -160,6 +161,9 @@ content: 'End'; } } + .l-time-conductor-inputs { + pointer-events: auto; + } input[type="text"] { @include trans-prop-nice(padding, 250ms); } diff --git a/platform/features/conductor-v2/conductor/res/templates/time-conductor.html b/platform/features/conductor-v2/conductor/res/templates/time-conductor.html index f04b09487dd..8873f5eb44c 100644 --- a/platform/features/conductor-v2/conductor/res/templates/time-conductor.html +++ b/platform/features/conductor-v2/conductor/res/templates/time-conductor.html @@ -1,6 +1,18 @@ +
+ class="holder grows flex-elem l-flex-row l-time-conductor {{modeModel.selectedKey}}-mode {{timeSystemModel.selected.metadata.key}}-time-system" + ng-class="{'status-panning': panning}">
@@ -13,63 +25,67 @@
- - - - - - - - - - + + + + + + + + - + + + - - - - - - - + - - + + + + + + + + + + + + diff --git a/platform/features/conductor-v2/conductor/src/ui/ConductorAxisController.js b/platform/features/conductor-v2/conductor/src/ui/ConductorAxisController.js new file mode 100644 index 00000000000..b88177181d2 --- /dev/null +++ b/platform/features/conductor-v2/conductor/src/ui/ConductorAxisController.js @@ -0,0 +1,169 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ + +define( + [ + "d3" + ], + function (d3) { + var PADDING = 1; + + /** + * The mct-conductor-axis renders a horizontal axis with regular + * labelled 'ticks'. It requires 'start' and 'end' integer values to + * be specified as attributes. + */ + function ConductorAxisController(conductor, formatService) { + // Dependencies + this.d3 = d3; + this.formatService = formatService; + this.conductor = conductor; + + // Runtime properties (set by 'link' function) + this.target = undefined; + this.xScale = undefined; + this.xAxis = undefined; + this.axisElement = undefined; + this.initialized = false; + this.msPerPixel = undefined; + + this.setScale = this.setScale.bind(this); + this.changeBounds = this.changeBounds.bind(this); + this.changeTimeSystem = this.changeTimeSystem.bind(this); + + this.bounds = conductor.bounds(); + this.timeSystem = conductor.timeSystem(); + } + + ConductorAxisController.prototype.changeBounds = function (bounds) { + this.bounds = bounds; + if (this.initialized) { + this.setScale(); + } + }; + + ConductorAxisController.prototype.setScale = function () { + var width = this.target.offsetWidth; + var timeSystem = this.conductor.timeSystem(); + var bounds = this.bounds; + + if (timeSystem.isUTCBased()) { + this.xScale = this.xScale || this.d3.scaleUtc(); + this.xScale.domain([new Date(bounds.start), new Date(bounds.end)]); + } else { + this.xScale = this.xScale || this.d3.scaleLinear(); + this.xScale.domain([bounds.start, bounds.end]); + } + + this.xScale.range([PADDING, width - PADDING * 2]); + this.axisElement.call(this.xAxis); + + this.msPerPixel = (bounds.end - bounds.start) / width; + }; + + ConductorAxisController.prototype.changeTimeSystem = function (timeSystem) { + this.timeSystem = timeSystem; + + var key = timeSystem.formats()[0]; + if (this.initialized && key !== undefined) { + var format = this.formatService.getFormat(key); + var bounds = this.conductor.bounds(); + + if (timeSystem.isUTCBased()) { + this.xScale = this.d3.scaleUtc(); + } else { + this.xScale = this.d3.scaleLinear(); + } + + this.xAxis.scale(this.xScale); + //Define a custom format function + this.xAxis.tickFormat(function (tickValue) { + // Normalize date representations to numbers + if (tickValue instanceof Date) { + tickValue = tickValue.getTime(); + } + return format.format(tickValue, { + min: bounds.start, + max: bounds.end + }); + }); + this.axisElement.call(this.xAxis); + } + }; + + ConductorAxisController.prototype.link = function (scope, element) { + this.target = element[0].firstChild; + this.scope = scope; + var height = this.target.offsetHeight; + var vis = this.d3.select(this.target) + .append("svg:svg") + .attr("width", "100%") + .attr("height", height); + + this.xAxis = this.d3.axisTop(); + + // draw x axis with labels and move to the bottom of the chart area + this.axisElement = vis.append("g") + .attr("transform", "translate(0," + (height - PADDING) + ")"); + + this.initialized = true; + + if (this.timeSystem !== undefined) { + this.changeTimeSystem(this.timeSystem); + this.setScale(this.bounds); + } + + //Respond to changes in conductor + this.conductor.on("timeSystem", this.changeTimeSystem); + this.conductor.on("bounds", this.changeBounds); + }; + + ConductorAxisController.prototype.panEnd = function () { + //resync view bounds with time conductor bounds + this.conductor.bounds(this.bounds); + this.scope.$emit("pan-stop"); + }; + + ConductorAxisController.prototype.pan = function (delta) { + if (!this.conductor.follow()) { + var deltaInMs = delta[0] * this.msPerPixel; + var bounds = this.conductor.bounds(); + var start = Math.floor((bounds.start - deltaInMs) / 1000) * 1000; + var end = Math.floor((bounds.end - deltaInMs) / 1000) * 1000; + this.bounds = { + start: start, + end: end + }; + this.setScale(); + this.scope.$emit("pan", this.bounds); + } + }; + + ConductorAxisController.prototype.resize = function () { + if (this.initialized) { + this.setScale(); + } + }; + + return ConductorAxisController; + } +); diff --git a/platform/features/conductor-v2/conductor/src/ui/MctConductorAxis.js b/platform/features/conductor-v2/conductor/src/ui/MctConductorAxis.js index 88bfc5f2a8c..8b874badf28 100644 --- a/platform/features/conductor-v2/conductor/src/ui/MctConductorAxis.js +++ b/platform/features/conductor-v2/conductor/src/ui/MctConductorAxis.js @@ -20,115 +20,33 @@ * at runtime from the About dialog for additional information. *****************************************************************************/ -define( - [ - "d3" - ], - function (d3) { - var PADDING = 1; - - /** - * The mct-conductor-axis renders a horizontal axis with regular - * labelled 'ticks'. It requires 'start' and 'end' integer values to - * be specified as attributes. - */ - function MCTConductorAxis(conductor, formatService) { - // Dependencies - this.d3 = d3; - this.conductor = conductor; - this.formatService = formatService; - - // Runtime properties (set by 'link' function) - this.target = undefined; - this.xScale = undefined; - this.xAxis = undefined; - this.axisElement = undefined; - this.setScale = this.setScale.bind(this); - this.changeTimeSystem = this.changeTimeSystem.bind(this); - - // Angular Directive interface - this.link = this.link.bind(this); - this.restrict = "E"; - this.template = - "
"; - this.priority = 1000; - } - - MCTConductorAxis.prototype.setScale = function () { - var width = this.target.offsetWidth; - var timeSystem = this.conductor.timeSystem(); - var bounds = this.conductor.bounds(); - - if (timeSystem.isUTCBased()) { - this.xScale = this.xScale || this.d3.scaleUtc(); - this.xScale.domain([new Date(bounds.start), new Date(bounds.end)]); - } else { - this.xScale = this.xScale || this.d3.scaleLinear(); - this.xScale.domain([bounds.start, bounds.end]); - } - - this.xScale.range([PADDING, width - PADDING * 2]); - this.axisElement.call(this.xAxis); - }; - - MCTConductorAxis.prototype.changeTimeSystem = function (timeSystem) { - var key = timeSystem.formats()[0]; - if (key !== undefined) { - var format = this.formatService.getFormat(key); - var bounds = this.conductor.bounds(); - - if (timeSystem.isUTCBased()) { - this.xScale = this.d3.scaleUtc(); - } else { - this.xScale = this.d3.scaleLinear(); - } - - this.xAxis.scale(this.xScale); - //Define a custom format function - this.xAxis.tickFormat(function (tickValue) { - // Normalize date representations to numbers - if (tickValue instanceof Date) { - tickValue = tickValue.getTime(); - } - return format.format(tickValue, { - min: bounds.start, - max: bounds.end - }); - }); - this.axisElement.call(this.xAxis); - } - }; - - MCTConductorAxis.prototype.link = function (scope, element) { - var conductor = this.conductor; - this.target = element[0].firstChild; - var height = this.target.offsetHeight; - var vis = this.d3.select(this.target) - .append('svg:svg') - .attr('width', '100%') - .attr('height', height); - - this.xAxis = this.d3.axisTop(); - - // draw x axis with labels and move to the bottom of the chart area - this.axisElement = vis.append("g") - .attr("transform", "translate(0," + (height - PADDING) + ")"); - - scope.resize = this.setScale; - - conductor.on('timeSystem', this.changeTimeSystem); - - //On conductor bounds changes, redraw ticks - conductor.on('bounds', this.setScale); - - if (conductor.timeSystem() !== undefined) { - this.changeTimeSystem(conductor.timeSystem()); - this.setScale(); +define([], function () { + + function MctConductorAxis() { + /** + * The mct-conductor-axis renders a horizontal axis with regular + * labelled 'ticks'. It requires 'start' and 'end' integer values to + * be specified as attributes. + */ + + return { + controller: 'ConductorAxisController', + controllerAs: 'axis', + link: function(scope, element, attrs, controller){ + controller.link(scope, element); + }, + + restrict: 'E', + priority: 1000, + + template: '
' } - }; + } - return function (conductor, formatService) { - return new MCTConductorAxis(conductor, formatService); - }; + return MctConductorAxis; } ); diff --git a/platform/features/conductor-v2/conductor/src/ui/TimeConductorController.js b/platform/features/conductor-v2/conductor/src/ui/TimeConductorController.js index c0964061aa3..3026232f184 100644 --- a/platform/features/conductor-v2/conductor/src/ui/TimeConductorController.js +++ b/platform/features/conductor-v2/conductor/src/ui/TimeConductorController.js @@ -100,6 +100,14 @@ define( // Watch scope for selection of mode or time system by user this.$scope.$watch('modeModel.selectedKey', this.setMode); + this.$scope.$on('pan', function (e, bounds) { + this.$scope.panning = true; + this.setFormFromBounds(bounds); + }.bind(this)); + + this.$scope.$on('pan-stop', function () { + this.$scope.panning = false; + }.bind(this)); }; /**