From 987740c649b0d303e4c12a99a1800458e2f52d2f Mon Sep 17 00:00:00 2001 From: Andrew Henry Date: Wed, 26 Sep 2018 23:41:04 +0100 Subject: [PATCH] Reimplementation of time conductor in Vue.js (#2173) * Refactoring conductor to use Vue * Conditionally render Time Conductor * Created ConductorOptions SFC * Copyright notice examples * Added time system selector component * Use capture for event bubbling with popups * Added Conductor Axis. Simplified Axis formatting and removed scale formatting from formatters. Added date picker. * Sync axis on zoom * Fixed sync between conductor and axis * Changed 'InspectorComponent' to 'ConductorComponent' in Layout. Fixed race condition with panning and RequestAnimationFrame * Renamed properties in conductor to clarify their role. Fixed some bugs * Removed old conductor * Fix layout issue with legacy Conductor markup * Added missing copyright notice --- .../commonUI/formats/src/UTCTimeFormat.js | 58 +- .../formats/test/UTCTimeFormatSpec.js | 62 -- .../conductor/compatibility/bundle.js | 43 -- .../compatibility/src/ConductorRepresenter.js | 95 --- platform/features/conductor/core/bundle.js | 148 ----- .../templates/mode-selector/mode-menu.html | 46 -- .../mode-selector/mode-selector.html | 33 -- .../core/res/templates/time-conductor.html | 117 ---- .../core/res/templates/time-of-interest.html | 12 - .../core/src/ui/ConductorAxisController.js | 236 -------- .../src/ui/ConductorAxisControllerSpec.js | 169 ------ .../core/src/ui/ConductorAxisDirective.js | 56 -- .../core/src/ui/ConductorTOIController.js | 123 ---- .../core/src/ui/ConductorTOIControllerSpec.js | 153 ----- .../core/src/ui/ConductorTOIDirective.js | 63 -- .../conductor/core/src/ui/NumberFormat.js | 54 -- .../conductor/core/src/ui/NumberFormatSpec.js | 49 -- .../core/src/ui/TimeConductorController.js | 554 ------------------ .../src/ui/TimeConductorControllerSpec.js | 513 ---------------- .../core/src/ui/TimeConductorValidation.js | 69 --- .../src/ui/TimeConductorValidationSpec.js | 73 --- .../core/src/ui/TimeConductorViewService.js | 97 --- .../core/src/ui/TimeOfInterestController.js | 109 ---- src/MCT.js | 1 - src/defaultRegistry.js | 2 - .../localTimeSystem/LocalTimeFormat.js | 52 -- .../localTimeSystem/LocalTimeSystem.js | 2 +- src/plugins/plugins.js | 2 +- src/plugins/timeConductor/Conductor.vue | 353 +++++++++++ src/plugins/timeConductor/ConductorAxis.vue | 177 ++++++ src/plugins/timeConductor/ConductorMode.vue | 196 +++++++ .../timeConductor/ConductorTimeSystem.vue | 132 +++++ src/plugins/timeConductor/DatePicker.vue | 242 ++++++++ src/plugins/timeConductor/plugin.js | 172 +++--- .../timeConductor/utcMultiTimeFormat.js | 65 +- src/ui/components/layout/Conductor.vue | 15 - src/ui/components/layout/Layout.vue | 10 +- 37 files changed, 1234 insertions(+), 3119 deletions(-) delete mode 100644 platform/commonUI/formats/test/UTCTimeFormatSpec.js delete mode 100644 platform/features/conductor/compatibility/bundle.js delete mode 100644 platform/features/conductor/compatibility/src/ConductorRepresenter.js delete mode 100644 platform/features/conductor/core/bundle.js delete mode 100644 platform/features/conductor/core/res/templates/mode-selector/mode-menu.html delete mode 100644 platform/features/conductor/core/res/templates/mode-selector/mode-selector.html delete mode 100644 platform/features/conductor/core/res/templates/time-conductor.html delete mode 100644 platform/features/conductor/core/res/templates/time-of-interest.html delete mode 100644 platform/features/conductor/core/src/ui/ConductorAxisController.js delete mode 100644 platform/features/conductor/core/src/ui/ConductorAxisControllerSpec.js delete mode 100644 platform/features/conductor/core/src/ui/ConductorAxisDirective.js delete mode 100644 platform/features/conductor/core/src/ui/ConductorTOIController.js delete mode 100644 platform/features/conductor/core/src/ui/ConductorTOIControllerSpec.js delete mode 100644 platform/features/conductor/core/src/ui/ConductorTOIDirective.js delete mode 100644 platform/features/conductor/core/src/ui/NumberFormat.js delete mode 100644 platform/features/conductor/core/src/ui/NumberFormatSpec.js delete mode 100644 platform/features/conductor/core/src/ui/TimeConductorController.js delete mode 100644 platform/features/conductor/core/src/ui/TimeConductorControllerSpec.js delete mode 100644 platform/features/conductor/core/src/ui/TimeConductorValidation.js delete mode 100644 platform/features/conductor/core/src/ui/TimeConductorValidationSpec.js delete mode 100644 platform/features/conductor/core/src/ui/TimeConductorViewService.js delete mode 100644 platform/features/conductor/core/src/ui/TimeOfInterestController.js create mode 100644 src/plugins/timeConductor/Conductor.vue create mode 100644 src/plugins/timeConductor/ConductorAxis.vue create mode 100644 src/plugins/timeConductor/ConductorMode.vue create mode 100644 src/plugins/timeConductor/ConductorTimeSystem.vue create mode 100644 src/plugins/timeConductor/DatePicker.vue rename platform/features/conductor/core/src/ui/StringFormat.js => src/plugins/timeConductor/utcMultiTimeFormat.js (53%) delete mode 100644 src/ui/components/layout/Conductor.vue diff --git a/platform/commonUI/formats/src/UTCTimeFormat.js b/platform/commonUI/formats/src/UTCTimeFormat.js index 6bbf7352cf..cd0002e370 100644 --- a/platform/commonUI/formats/src/UTCTimeFormat.js +++ b/platform/commonUI/formats/src/UTCTimeFormat.js @@ -52,70 +52,14 @@ define([ this.key = "utc"; } - /** - * Returns an appropriate time format based on the provided value and - * the threshold required. - * @private - */ - function getScaledFormat(d) { - var momentified = moment.utc(d); - /** - * Uses logic from d3 Time-Scales, v3 of the API. See - * https://github.com/d3/d3-3.x-api-reference/blob/master/Time-Scales.md - * - * Licensed - */ - var format = [ - [".SSS", function (m) { - return m.milliseconds(); - }], - [":ss", function (m) { - return m.seconds(); - }], - ["HH:mm", function (m) { - return m.minutes(); - }], - ["HH", function (m) { - return m.hours(); - }], - ["ddd DD", function (m) { - return m.days() && - m.date() !== 1; - }], - ["MMM DD", function (m) { - return m.date() !== 1; - }], - ["MMMM", function (m) { - return m.month(); - }], - ["YYYY", function () { - return true; - }] - ].filter(function (row) { - return row[1](momentified); - })[0][0]; - - if (format !== undefined) { - return moment.utc(d).format(format); - } - } - /** * @param {number} value The value to format. - * @param {number} [minValue] Contextual information for scaled formatting used in linear scales such as conductor - * and plot axes. Specifies the smallest number on the scale. - * @param {number} [maxValue] Contextual information for scaled formatting used in linear scales such as conductor - * and plot axes. Specifies the largest number on the scale - * @param {number} [count] Contextual information for scaled formatting used in linear scales such as conductor - * and plot axes. The number of labels on the scale. * @returns {string} the formatted date(s). If multiple values were requested, then an array of * formatted values will be returned. Where a value could not be formatted, `undefined` will be returned at its position * in the array. */ UTCTimeFormat.prototype.format = function (value) { - if (arguments.length > 1) { - return getScaledFormat(value); - } else if (value !== undefined) { + if (value !== undefined) { return moment.utc(value).format(DATE_FORMAT) + "Z"; } else { return value; diff --git a/platform/commonUI/formats/test/UTCTimeFormatSpec.js b/platform/commonUI/formats/test/UTCTimeFormatSpec.js deleted file mode 100644 index d5f3ce2d8e..0000000000 --- a/platform/commonUI/formats/test/UTCTimeFormatSpec.js +++ /dev/null @@ -1,62 +0,0 @@ -/***************************************************************************** - * 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([ - "../src/UTCTimeFormat", - "moment" -], function ( - UTCTimeFormat, - moment -) { - describe("The UTCTimeFormat class", function () { - var format; - var scale; - - beforeEach(function () { - format = new UTCTimeFormat(); - scale = {min: 0, max: 0}; - }); - - it("Provides an appropriately scaled time format based on the input" + - " time", function () { - var TWO_HUNDRED_MS = 200; - var THREE_SECONDS = 3000; - var FIVE_MINUTES = 5 * 60 * 1000; - var ONE_HOUR_TWENTY_MINS = (1 * 60 * 60 * 1000) + (20 * 60 * 1000); - var TEN_HOURS = (10 * 60 * 60 * 1000); - - var JUNE_THIRD = moment.utc("2016-06-03", "YYYY-MM-DD"); - var APRIL = moment.utc("2016-04", "YYYY-MM"); - var TWENTY_SIXTEEN = moment.utc("2016", "YYYY"); - - expect(format.format(TWO_HUNDRED_MS, scale)).toBe(".200"); - expect(format.format(THREE_SECONDS, scale)).toBe(":03"); - expect(format.format(FIVE_MINUTES, scale)).toBe("00:05"); - expect(format.format(ONE_HOUR_TWENTY_MINS, scale)).toBe("01:20"); - expect(format.format(TEN_HOURS, scale)).toBe("10"); - - expect(format.format(JUNE_THIRD, scale)).toBe("Fri 03"); - expect(format.format(APRIL, scale)).toBe("April"); - expect(format.format(TWENTY_SIXTEEN, scale)).toBe("2016"); - }); - }); -}); diff --git a/platform/features/conductor/compatibility/bundle.js b/platform/features/conductor/compatibility/bundle.js deleted file mode 100644 index ee945a5b15..0000000000 --- a/platform/features/conductor/compatibility/bundle.js +++ /dev/null @@ -1,43 +0,0 @@ -/***************************************************************************** - * 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([ - "./src/ConductorRepresenter", - 'legacyRegistry' -], function ( - ConductorRepresenter, - legacyRegistry -) { - - legacyRegistry.register("platform/features/conductor/compatibility", { - "extensions": { - "representers": [ - { - "implementation": ConductorRepresenter, - "depends": [ - "openmct" - ] - } - ] - } - }); -}); diff --git a/platform/features/conductor/compatibility/src/ConductorRepresenter.js b/platform/features/conductor/compatibility/src/ConductorRepresenter.js deleted file mode 100644 index 6969e86ff5..0000000000 --- a/platform/features/conductor/compatibility/src/ConductorRepresenter.js +++ /dev/null @@ -1,95 +0,0 @@ -/***************************************************************************** - * 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( - [], - function () { - - /** - * Representer that provides a compatibility layer between the new - * time conductor and existing representations / views. Listens to - * the v2 time conductor API and generates v1 style events using the - * Angular event bus. This is transitional code code and will be - * removed. - * - * Deprecated immediately as this is temporary code - * - * @deprecated - * @constructor - */ - function ConductorRepresenter( - openmct, - scope, - element - ) { - this.timeAPI = openmct.time; - this.scope = scope; - this.element = element; - - this.boundsListener = this.boundsListener.bind(this); - this.timeSystemListener = this.timeSystemListener.bind(this); - this.followListener = this.followListener.bind(this); - } - - ConductorRepresenter.prototype.boundsListener = function (bounds) { - var timeSystem = this.timeAPI.timeSystem(); - this.scope.$broadcast('telemetry:display:bounds', { - start: bounds.start, - end: bounds.end, - domain: timeSystem.key - }, this.timeAPI.clock() !== undefined); - }; - - ConductorRepresenter.prototype.timeSystemListener = function (timeSystem) { - var bounds = this.timeAPI.bounds(); - this.scope.$broadcast('telemetry:display:bounds', { - start: bounds.start, - end: bounds.end, - domain: timeSystem.key - }, this.timeAPI.clock() !== undefined); - }; - - ConductorRepresenter.prototype.followListener = function () { - this.boundsListener(this.timeAPI.bounds()); - }; - - // Handle a specific representation of a specific domain object - ConductorRepresenter.prototype.represent = function represent(representation) { - if (representation.key === 'browse-object') { - this.destroy(); - - this.timeAPI.on("bounds", this.boundsListener); - this.timeAPI.on("timeSystem", this.timeSystemListener); - this.timeAPI.on("follow", this.followListener); - } - }; - - ConductorRepresenter.prototype.destroy = function destroy() { - this.timeAPI.off("bounds", this.boundsListener); - this.timeAPI.off("timeSystem", this.timeSystemListener); - this.timeAPI.off("follow", this.followListener); - }; - - return ConductorRepresenter; - } -); - diff --git a/platform/features/conductor/core/bundle.js b/platform/features/conductor/core/bundle.js deleted file mode 100644 index e0417b166f..0000000000 --- a/platform/features/conductor/core/bundle.js +++ /dev/null @@ -1,148 +0,0 @@ -/***************************************************************************** - * 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([ - "./src/ui/TimeConductorController", - "./src/ui/ConductorAxisController", - "./src/ui/ConductorTOIController", - "./src/ui/ConductorTOIDirective", - "./src/ui/TimeOfInterestController", - "./src/ui/ConductorAxisDirective", - "./src/ui/NumberFormat", - "./src/ui/StringFormat", - "./res/templates/time-conductor.html", - "./res/templates/mode-selector/mode-selector.html", - "./res/templates/mode-selector/mode-menu.html", - "./res/templates/time-of-interest.html", - "legacyRegistry" -], function ( - TimeConductorController, - ConductorAxisController, - ConductorTOIController, - ConductorTOIDirective, - TimeOfInterestController, - ConductorAxisDirective, - NumberFormat, - StringFormat, - timeConductorTemplate, - modeSelectorTemplate, - modeMenuTemplate, - timeOfInterest, - legacyRegistry -) { - - legacyRegistry.register("platform/features/conductor/core", { - "extensions": { - "controllers": [ - { - "key": "TimeConductorController", - "implementation": TimeConductorController, - "depends": [ - "$scope", - "$window", - "openmct", - "formatService", - "CONDUCTOR_CONFIG" - ] - }, - { - "key": "ConductorTOIController", - "implementation": ConductorTOIController, - "depends": [ - "$scope", - "openmct", - "formatService" - ] - }, - { - "key": "TimeOfInterestController", - "implementation": TimeOfInterestController, - "depends": [ - "$scope", - "openmct", - "formatService" - ] - } - ], - "directives": [ - { - "key": "conductorAxis", - "implementation": ConductorAxisDirective, - "depends": [ - "openmct", - "formatService" - ] - }, - { - "key": "conductorToi", - "implementation": ConductorTOIDirective - } - ], - "templates": [ - { - "key": "conductor", - "template": timeConductorTemplate - }, - { - "key": "mode-menu", - "template": modeMenuTemplate - }, - { - "key": "mode-selector", - "template": modeSelectorTemplate - }, - { - "key": "time-of-interest", - "template": timeOfInterest - } - ], - "representations": [ - { - "key": "time-conductor", - "template": timeConductorTemplate - } - ], - "licenses": [ - { - "name": "D3: Data-Driven Documents", - "version": "4.1.0", - "author": "Mike Bostock", - "description": "D3 (or D3.js) is a JavaScript library for visualizing data using web standards. D3 helps you bring data to life using SVG, Canvas and HTML. D3 combines powerful visualization and interaction techniques with a data-driven approach to DOM manipulation, giving you the full capabilities of modern browsers and the freedom to design the right visual interface for your data.", - "website": "https://d3js.org/", - "copyright": "Copyright 2010-2016 Mike Bostock", - "license": "BSD-3-Clause", - "link": "https://github.com/d3/d3/blob/master/LICENSE" - } - ], - "formats": [ - { - "key": "number", - "implementation": NumberFormat - }, - { - "key": "string", - "implementation": StringFormat - } - ] - } - }); -}); diff --git a/platform/features/conductor/core/res/templates/mode-selector/mode-menu.html b/platform/features/conductor/core/res/templates/mode-selector/mode-menu.html deleted file mode 100644 index 1609a07858..0000000000 --- a/platform/features/conductor/core/res/templates/mode-selector/mode-menu.html +++ /dev/null @@ -1,46 +0,0 @@ - -
- - -
diff --git a/platform/features/conductor/core/res/templates/mode-selector/mode-selector.html b/platform/features/conductor/core/res/templates/mode-selector/mode-selector.html deleted file mode 100644 index 9c698300c2..0000000000 --- a/platform/features/conductor/core/res/templates/mode-selector/mode-selector.html +++ /dev/null @@ -1,33 +0,0 @@ - - -
- {{ngModel.selected.name}} -
- -
diff --git a/platform/features/conductor/core/res/templates/time-conductor.html b/platform/features/conductor/core/res/templates/time-conductor.html deleted file mode 100644 index 46b2ac3293..0000000000 --- a/platform/features/conductor/core/res/templates/time-conductor.html +++ /dev/null @@ -1,117 +0,0 @@ - -
-
-
-
-
- -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - -
- -
- - -
- - - - - -
- {{currentZoom}} - {{timeUnits}} - -
-
- -
-
diff --git a/platform/features/conductor/core/res/templates/time-of-interest.html b/platform/features/conductor/core/res/templates/time-of-interest.html deleted file mode 100644 index 6ab9dee609..0000000000 --- a/platform/features/conductor/core/res/templates/time-of-interest.html +++ /dev/null @@ -1,12 +0,0 @@ -
-
- - - - - {{toi.toiText}} -
-
diff --git a/platform/features/conductor/core/src/ui/ConductorAxisController.js b/platform/features/conductor/core/src/ui/ConductorAxisController.js deleted file mode 100644 index 8b8fd3baa1..0000000000 --- a/platform/features/conductor/core/src/ui/ConductorAxisController.js +++ /dev/null @@ -1,236 +0,0 @@ -/***************************************************************************** - * 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-selection", - "d3-scale", - "d3-axis" - ], - function (d3Selection, d3Scale, d3Axis) { - var PADDING = 1; - - /** - * Controller that renders a horizontal time scale spanning the current bounds defined in the time conductor. - * Used by the mct-conductor-axis directive - * @constructor - */ - function ConductorAxisController(openmct, formatService, scope, element) { - // Dependencies - this.formatService = formatService; - this.timeAPI = openmct.time; - - this.scope = scope; - - this.bounds = this.timeAPI.bounds(); - - //Bind all class functions to 'this' - Object.keys(ConductorAxisController.prototype).filter(function (key) { - return typeof ConductorAxisController.prototype[key] === 'function'; - }).forEach(function (key) { - this[key] = ConductorAxisController.prototype[key].bind(this); - }.bind(this)); - - this.initialize(element); - } - - /** - * @private - */ - ConductorAxisController.prototype.destroy = function () { - this.timeAPI.off('timeSystem', this.changeTimeSystem); - this.timeAPI.off('bounds', this.changeBounds); - this.viewService.off("zoom", this.onZoom); - this.viewService.off("zoom-stop", this.onZoomStop); - }; - - /** - * @private - */ - ConductorAxisController.prototype.initialize = function (element) { - this.target = element[0].firstChild; - var height = this.target.offsetHeight; - var vis = d3Selection.select(this.target) - .append("svg:svg") - .attr("width", "100%") - .attr("height", height); - - this.xAxis = d3Axis.axisTop(); - - // draw x axis with labels. CSS is used to position them. - this.axisElement = vis.append("g"); - - if (this.timeAPI.timeSystem() !== undefined) { - this.changeTimeSystem(this.timeAPI.timeSystem()); - this.setScale(); - } - - //Respond to changes in conductor - this.timeAPI.on("timeSystem", this.changeTimeSystem); - this.timeAPI.on("bounds", this.changeBounds); - - this.scope.$on("$destroy", this.destroy); - - this.viewService.on("zoom", this.onZoom); - this.viewService.on("zoom-stop", this.onZoomStop); - }; - - /** - * @private - */ - ConductorAxisController.prototype.changeBounds = function (bounds) { - this.bounds = bounds; - if (!this.zooming) { - this.setScale(); - } - }; - - /** - * Set the scale of the axis, based on current conductor bounds. - */ - ConductorAxisController.prototype.setScale = function () { - var width = this.target.offsetWidth; - var timeSystem = this.timeAPI.timeSystem(); - var bounds = this.bounds; - - if (timeSystem.isUTCBased) { - this.xScale = this.xScale || d3Scale.scaleUtc(); - this.xScale.domain([new Date(bounds.start), new Date(bounds.end)]); - } else { - this.xScale = this.xScale || d3Scale.scaleLinear(); - this.xScale.domain([bounds.start, bounds.end]); - } - - this.xAxis.scale(this.xScale); - - this.xScale.range([PADDING, width - PADDING * 2]); - this.axisElement.call(this.xAxis); - - this.msPerPixel = (bounds.end - bounds.start) / width; - }; - - /** - * When the time system changes, update the scale and formatter used for showing times. - * @param timeSystem - */ - ConductorAxisController.prototype.changeTimeSystem = function (timeSystem) { - var key = timeSystem.timeFormat; - if (key !== undefined) { - var format = this.formatService.getFormat(key); - var bounds = this.timeAPI.bounds(); - - //The D3 scale used depends on the type of time system as d3 - // supports UTC out of the box. - if (timeSystem.isUTCBased) { - this.xScale = d3Scale.scaleUtc(); - } else { - this.xScale = d3Scale.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); - } - }; - - /** - * The user has stopped panning the time conductor scale element. - * @event panStop - */ - /** - * Called on release of mouse button after dragging the scale left or right. - * @fires platform.features.conductor.ConductorAxisController~panStop - */ - ConductorAxisController.prototype.panStop = function () { - //resync view bounds with time conductor bounds - this.viewService.emit("pan-stop"); - this.timeAPI.bounds(this.bounds); - }; - - /** - * Rescales the axis when the user zooms. Although zoom ultimately results in a bounds change once the user - * releases the zoom slider, dragging the slider will not immediately change the conductor bounds. It will - * however immediately update the scale and the bounds displayed in the UI. - * @private - * @param {ZoomLevel} - */ - ConductorAxisController.prototype.onZoom = function (zoom) { - this.zooming = true; - - this.bounds = zoom.bounds; - this.setScale(); - }; - - /** - * @private - */ - ConductorAxisController.prototype.onZoomStop = function (zoom) { - this.zooming = false; - }; - - /** - * @event platform.features.conductor.ConductorAxisController~pan - * Fired when the time conductor is panned - */ - /** - * Initiate panning via a click + drag gesture on the time conductor - * scale. Panning triggers a "pan" event - * @param {number} delta the offset from the original click event - * @see TimeConductorViewService# - * @fires platform.features.conductor.ConductorAxisController~pan - */ - ConductorAxisController.prototype.pan = function (delta) { - if (this.timeAPI.clock() === undefined) { - var deltaInMs = delta[0] * this.msPerPixel; - var bounds = this.timeAPI.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.viewService.emit("pan", this.bounds); - } - }; - - /** - * Invoked on element resize. Will rebuild the scale based on the new dimensions of the element. - */ - ConductorAxisController.prototype.resize = function () { - this.setScale(); - }; - - return ConductorAxisController; - } -); diff --git a/platform/features/conductor/core/src/ui/ConductorAxisControllerSpec.js b/platform/features/conductor/core/src/ui/ConductorAxisControllerSpec.js deleted file mode 100644 index 93ed5abae2..0000000000 --- a/platform/features/conductor/core/src/ui/ConductorAxisControllerSpec.js +++ /dev/null @@ -1,169 +0,0 @@ -/***************************************************************************** - * 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([ - './ConductorAxisController', - 'zepto', - 'd3-selection', - 'd3-scale' -], function ( - ConductorAxisController, - $, - d3Selection, - d3Scale -) { - describe("The ConductorAxisController", function () { - var controller, - mockConductor, - mockConductorViewService, - mockFormatService, - mockScope, - mockBounds, - element, - mockTimeSystem, - mockFormat; - - function getCallback(target, name) { - return target.calls.all().filter(function (call) { - return call.args[0] === name; - })[0].args[1]; - } - - beforeEach(function () { - mockScope = jasmine.createSpyObj("scope", [ - "$on" - ]); - - //Add some HTML elements - mockBounds = { - start: 100, - end: 200 - }; - mockConductor = jasmine.createSpyObj("conductor", [ - "timeSystem", - "bounds", - "on", - "off", - "clock" - ]); - mockConductor.bounds.and.returnValue(mockBounds); - - mockFormatService = jasmine.createSpyObj("formatService", [ - "getFormat" - ]); - - mockConductorViewService = jasmine.createSpyObj("conductorViewService", [ - "on", - "off", - "emit" - ]); - - spyOn(d3Scale, 'scaleUtc').and.callThrough(); - spyOn(d3Scale, 'scaleLinear').and.callThrough(); - - element = $('
'); - $(document).find('body').append(element); - ConductorAxisController.prototype.viewService = mockConductorViewService; - controller = new ConductorAxisController({time: mockConductor}, mockFormatService, mockScope, element); - - mockTimeSystem = {}; - mockFormat = jasmine.createSpyObj("format", [ - "format" - ]); - - mockTimeSystem.timeFormat = "mockFormat"; - mockFormatService.getFormat.and.returnValue(mockFormat); - mockConductor.timeSystem.and.returnValue(mockTimeSystem); - mockTimeSystem.isUTCBased = false; - }); - - it("listens for changes to time system and bounds", function () { - expect(mockConductor.on).toHaveBeenCalledWith("timeSystem", controller.changeTimeSystem); - expect(mockConductor.on).toHaveBeenCalledWith("bounds", controller.changeBounds); - }); - - it("on scope destruction, deregisters listeners", function () { - expect(mockScope.$on).toHaveBeenCalledWith("$destroy", controller.destroy); - controller.destroy(); - expect(mockConductor.off).toHaveBeenCalledWith("timeSystem", controller.changeTimeSystem); - expect(mockConductor.off).toHaveBeenCalledWith("bounds", controller.changeBounds); - }); - - describe("when the time system changes", function () { - it("uses a UTC scale for UTC time systems", function () { - mockTimeSystem.isUTCBased = true; - controller.changeTimeSystem(mockTimeSystem); - - expect(d3Scale.scaleUtc).toHaveBeenCalled(); - expect(d3Scale.scaleLinear).not.toHaveBeenCalled(); - }); - - it("uses a linear scale for non-UTC time systems", function () { - mockTimeSystem.isUTCBased = false; - controller.changeTimeSystem(mockTimeSystem); - expect(d3Scale.scaleLinear).toHaveBeenCalled(); - expect(d3Scale.scaleUtc).not.toHaveBeenCalled(); - }); - - it("sets axis domain to time conductor bounds", function () { - mockTimeSystem.isUTCBased = false; - controller.setScale(); - expect(controller.xScale.domain()).toEqual([mockBounds.start, mockBounds.end]); - }); - - it("uses the format specified by the time system to format tick" + - " labels", function () { - controller.changeTimeSystem(mockTimeSystem); - expect(mockFormat.format).toHaveBeenCalled(); - }); - - it('responds to zoom events', function () { - expect(mockConductorViewService.on).toHaveBeenCalledWith("zoom", controller.onZoom); - var cb = getCallback(mockConductorViewService.on, "zoom"); - spyOn(controller, 'setScale').and.callThrough(); - cb({bounds: {start: 0, end: 100}}); - expect(controller.setScale).toHaveBeenCalled(); - }); - - it('adjusts scale on pan', function () { - spyOn(controller, 'setScale').and.callThrough(); - controller.pan(100); - expect(controller.setScale).toHaveBeenCalled(); - }); - - it('emits event on pan', function () { - spyOn(controller, 'setScale').and.callThrough(); - controller.pan(100); - expect(mockConductorViewService.emit).toHaveBeenCalledWith("pan", jasmine.any(Object)); - }); - - it('cleans up listeners on destruction', function () { - controller.destroy(); - expect(mockConductor.off).toHaveBeenCalledWith("bounds", controller.changeBounds); - expect(mockConductor.off).toHaveBeenCalledWith("timeSystem", controller.changeTimeSystem); - - expect(mockConductorViewService.off).toHaveBeenCalledWith("zoom", controller.onZoom); - }); - - }); - }); -}); diff --git a/platform/features/conductor/core/src/ui/ConductorAxisDirective.js b/platform/features/conductor/core/src/ui/ConductorAxisDirective.js deleted file mode 100644 index 11dd3c31ed..0000000000 --- a/platform/features/conductor/core/src/ui/ConductorAxisDirective.js +++ /dev/null @@ -1,56 +0,0 @@ -/***************************************************************************** - * 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(['./ConductorAxisController'], function (ConductorAxisController) { - function ConductorAxisDirective() { - /** - * 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: [ - 'openmct', - 'formatService', - '$scope', - '$element', - ConductorAxisController - ], - controllerAs: 'axis', - scope: { - viewService: "=" - }, - bindToController: true, - - restrict: 'E', - priority: 1000, - - template: '
' - }; - } - - return ConductorAxisDirective; -}); diff --git a/platform/features/conductor/core/src/ui/ConductorTOIController.js b/platform/features/conductor/core/src/ui/ConductorTOIController.js deleted file mode 100644 index 8c02127561..0000000000 --- a/platform/features/conductor/core/src/ui/ConductorTOIController.js +++ /dev/null @@ -1,123 +0,0 @@ -/***************************************************************************** - * 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( - ["zepto"], - function ($) { - - /** - * Controller for the Time of Interest indicator in the conductor itself. Sets the horizontal position of the - * TOI indicator based on the current value of the TOI, and the width of the TOI conductor. - * @memberof platform.features.conductor - */ - function ConductorTOIController($scope, openmct) { - this.timeAPI = openmct.time; - - //Bind all class functions to 'this' - Object.keys(ConductorTOIController.prototype).filter(function (key) { - return typeof ConductorTOIController.prototype[key] === 'function'; - }).forEach(function (key) { - this[key] = ConductorTOIController.prototype[key].bind(this); - }.bind(this)); - - this.timeAPI.on('timeOfInterest', this.changeTimeOfInterest); - this.viewService.on('zoom', this.setOffsetFromZoom); - this.viewService.on('pan', this.setOffsetFromBounds); - - var timeOfInterest = this.timeAPI.timeOfInterest(); - if (timeOfInterest) { - this.changeTimeOfInterest(timeOfInterest); - } - - $scope.$on('$destroy', this.destroy); - } - - /** - * @private - */ - ConductorTOIController.prototype.destroy = function () { - this.timeAPI.off('timeOfInterest', this.changeTimeOfInterest); - this.viewService.off('zoom', this.setOffsetFromZoom); - this.viewService.off('pan', this.setOffsetFromBounds); - }; - - /** - * Given some bounds, set horizontal position of TOI indicator based - * on current conductor TOI value. Bounds are provided so that - * ephemeral bounds from zoom and pan events can be used as well - * as current conductor bounds, allowing TOI to be updated in - * realtime during scroll and zoom. - * @param {TimeConductorBounds} bounds - */ - ConductorTOIController.prototype.setOffsetFromBounds = function (bounds) { - var toi = this.timeAPI.timeOfInterest(); - if (toi !== undefined) { - var offset = toi - bounds.start; - var duration = bounds.end - bounds.start; - this.left = offset / duration * 100; - this.pinned = true; - } else { - this.left = 0; - this.pinned = false; - } - }; - - /** - * @private - */ - ConductorTOIController.prototype.setOffsetFromZoom = function (zoom) { - return this.setOffsetFromBounds(zoom.bounds); - }; - - /** - * Invoked when time of interest changes. Will set the horizontal offset of the TOI indicator. - * @private - */ - ConductorTOIController.prototype.changeTimeOfInterest = function () { - var bounds = this.timeAPI.bounds(); - if (bounds) { - this.setOffsetFromBounds(bounds); - } - }; - - /** - * On a mouse click event within the TOI element, convert position within element to a time of interest, and - * set the time of interest on the conductor. - * @param e The angular $event object - */ - ConductorTOIController.prototype.setTOIFromPosition = function (e) { - //TOI is set using the alt key modified + primary click - if (e.altKey) { - var element = $(e.currentTarget); - var width = element.width(); - var relativeX = e.pageX - element.offset().left; - var percX = relativeX / width; - var bounds = this.timeAPI.bounds(); - var timeRange = bounds.end - bounds.start; - - this.timeAPI.timeOfInterest(timeRange * percX + bounds.start); - } - }; - - return ConductorTOIController; - } -); diff --git a/platform/features/conductor/core/src/ui/ConductorTOIControllerSpec.js b/platform/features/conductor/core/src/ui/ConductorTOIControllerSpec.js deleted file mode 100644 index 7b2aa5004a..0000000000 --- a/platform/features/conductor/core/src/ui/ConductorTOIControllerSpec.js +++ /dev/null @@ -1,153 +0,0 @@ -/***************************************************************************** - * 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([ - './ConductorTOIController' -], function ( - ConductorTOIController -) { - var mockConductor; - var mockConductorViewService; - var mockScope; - var mockAPI; - var conductorTOIController; - - function getNamedCallback(thing, name) { - return thing.calls.all().filter(function (call) { - return call.args[0] === name; - }).map(function (call) { - return call.args; - })[0][1]; - } - - describe("The ConductorTOIController", function () { - beforeEach(function () { - mockConductor = jasmine.createSpyObj("conductor", [ - "bounds", - "timeOfInterest", - "on", - "off" - ]); - mockAPI = {time: mockConductor}; - - mockConductorViewService = jasmine.createSpyObj("conductorViewService", [ - "on", - "off" - ]); - - mockScope = jasmine.createSpyObj("openMCT", [ - "$on" - ]); - ConductorTOIController.prototype.viewService = mockConductorViewService; - conductorTOIController = new ConductorTOIController(mockScope, mockAPI); - }); - - it("listens to changes in the time of interest on the conductor", function () { - expect(mockConductor.on).toHaveBeenCalledWith("timeOfInterest", jasmine.any(Function)); - }); - - describe("when responding to changes in the time of interest", function () { - var toiCallback; - beforeEach(function () { - var bounds = { - start: 0, - end: 200 - }; - mockConductor.bounds.and.returnValue(bounds); - toiCallback = getNamedCallback(mockConductor.on, "timeOfInterest"); - }); - - it("calculates the correct horizontal offset based on bounds and current TOI", function () { - //Expect time of interest position to be 50% of element width - mockConductor.timeOfInterest.and.returnValue(100); - toiCallback(); - expect(conductorTOIController.left).toBe(50); - - //Expect time of interest position to be 25% of element width - mockConductor.timeOfInterest.and.returnValue(50); - toiCallback(); - expect(conductorTOIController.left).toBe(25); - - //Expect time of interest position to be 0% of element width - mockConductor.timeOfInterest.and.returnValue(0); - toiCallback(); - expect(conductorTOIController.left).toBe(0); - - //Expect time of interest position to be 100% of element width - mockConductor.timeOfInterest.and.returnValue(200); - toiCallback(); - expect(conductorTOIController.left).toBe(100); - }); - - it("renders the TOI indicator visible", function () { - expect(conductorTOIController.pinned).toBeFalsy(); - mockConductor.timeOfInterest.and.returnValue(100); - toiCallback(); - expect(conductorTOIController.pinned).toBe(true); - }); - }); - - it("responds to zoom events", function () { - var mockZoom = { - bounds: { - start: 500, - end: 1000 - } - }; - expect(mockConductorViewService.on).toHaveBeenCalledWith("zoom", jasmine.any(Function)); - - // Should correspond to horizontal offset of 50% - mockConductor.timeOfInterest.and.returnValue(750); - var zoomCallback = getNamedCallback(mockConductorViewService.on, "zoom"); - zoomCallback(mockZoom); - expect(conductorTOIController.left).toBe(50); - }); - - it("responds to pan events", function () { - var mockPanBounds = { - start: 1000, - end: 3000 - }; - - expect(mockConductorViewService.on).toHaveBeenCalledWith("pan", jasmine.any(Function)); - - // Should correspond to horizontal offset of 25% - mockConductor.timeOfInterest.and.returnValue(1500); - var panCallback = getNamedCallback(mockConductorViewService.on, "pan"); - panCallback(mockPanBounds); - expect(conductorTOIController.left).toBe(25); - }); - - - it("Cleans up all listeners when controller destroyed", function () { - var zoomCB = getNamedCallback(mockConductorViewService.on, "zoom"); - var panCB = getNamedCallback(mockConductorViewService.on, "pan"); - var toiCB = getNamedCallback(mockConductor.on, "timeOfInterest"); - - expect(mockScope.$on).toHaveBeenCalledWith("$destroy", jasmine.any(Function)); - getNamedCallback(mockScope.$on, "$destroy")(); - expect(mockConductorViewService.off).toHaveBeenCalledWith("zoom", zoomCB); - expect(mockConductorViewService.off).toHaveBeenCalledWith("pan", panCB); - expect(mockConductor.off).toHaveBeenCalledWith("timeOfInterest", toiCB); - }); - }); -}); diff --git a/platform/features/conductor/core/src/ui/ConductorTOIDirective.js b/platform/features/conductor/core/src/ui/ConductorTOIDirective.js deleted file mode 100644 index 24e86200f1..0000000000 --- a/platform/features/conductor/core/src/ui/ConductorTOIDirective.js +++ /dev/null @@ -1,63 +0,0 @@ -/***************************************************************************** - * 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(['./ConductorTOIController'], function (ConductorTOIController) { - /** - * A directive that encapsulates the TOI specific behavior of the Time Conductor UI. - * @constructor - */ - function ConductorTOIDirective() { - /** - * 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: [ - '$scope', - 'openmct', - ConductorTOIController - ], - controllerAs: 'toi', - scope: { - viewService: "=" - }, - bindToController: true, - - restrict: 'E', - priority: 1000, - - template: - '
' + - ' ' + - '
' + - ' ' + - '
' + - ' ' + - '
' - }; - } - - return ConductorTOIDirective; -}); diff --git a/platform/features/conductor/core/src/ui/NumberFormat.js b/platform/features/conductor/core/src/ui/NumberFormat.js deleted file mode 100644 index f9f1cab4f8..0000000000 --- a/platform/features/conductor/core/src/ui/NumberFormat.js +++ /dev/null @@ -1,54 +0,0 @@ -/***************************************************************************** - * Open MCT, Copyright (c) 2014-2018, United States Government - * as represented by the Administrator of the National Aeronautics and Space - * Administration. All rights reserved. - * - * Open MCT 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 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([], function () { - - /** - * Formatter for basic numbers. Provides basic support for non-UTC - * numbering systems - * - * @implements {Format} - * @constructor - * @memberof platform/commonUI/formats - */ - function NumberFormat() { - this.key = 'number'; - } - - NumberFormat.prototype.format = function (value) { - if (isNaN(value)) { - return ''; - } else { - return '' + value; - } - }; - - NumberFormat.prototype.parse = function (text) { - return parseFloat(text); - }; - - NumberFormat.prototype.validate = function (text) { - return !isNaN(text); - }; - - return NumberFormat; -}); diff --git a/platform/features/conductor/core/src/ui/NumberFormatSpec.js b/platform/features/conductor/core/src/ui/NumberFormatSpec.js deleted file mode 100644 index f56c6e67d3..0000000000 --- a/platform/features/conductor/core/src/ui/NumberFormatSpec.js +++ /dev/null @@ -1,49 +0,0 @@ -/***************************************************************************** - * 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(['./NumberFormat'], function (NumberFormat) { - describe("The NumberFormat class", function () { - var format; - beforeEach(function () { - format = new NumberFormat(); - }); - - it("The format function takes a string and produces a number", function () { - var text = format.format(1); - expect(text).toBe("1"); - expect(typeof text).toBe("string"); - }); - - it("The parse function takes a string and produces a number", function () { - var number = format.parse("1"); - expect(number).toBe(1); - expect(typeof number).toBe("number"); - }); - - it("validates that the input is a number", function () { - expect(format.validate("1")).toBe(true); - expect(format.validate(1)).toBe(true); - expect(format.validate("1.1")).toBe(true); - expect(format.validate("abc")).toBe(false); - }); - }); -}); diff --git a/platform/features/conductor/core/src/ui/TimeConductorController.js b/platform/features/conductor/core/src/ui/TimeConductorController.js deleted file mode 100644 index 7c53f23992..0000000000 --- a/platform/features/conductor/core/src/ui/TimeConductorController.js +++ /dev/null @@ -1,554 +0,0 @@ -/***************************************************************************** - * 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( - [ - 'moment', - './TimeConductorValidation', - './TimeConductorViewService' - ], - function ( - moment, - TimeConductorValidation, - TimeConductorViewService - ) { - - var timeUnitsMegastructure = [ - ["Decades", function (r) { - return r.years() > 15; - }], - ["Years", function (r) { - return r.years() > 1; - }], - ["Months", function (r) { - return r.years() === 1 || r.months() > 1; - }], - ["Days", function (r) { - return r.months() === 1 || r.days() > 1; - }], - ["Hours", function (r) { - return r.days() === 1 || r.hours() > 1; - }], - ["Minutes", function (r) { - return r.hours() === 1 || r.minutes() > 1; - }], - ["Seconds", function (r) { - return r.minutes() === 1 || r.seconds() > 1; - }], - ["Milliseconds", function (r) { - return true; - }] - ]; - - /** - * Controller for the Time Conductor UI element. The Time Conductor - * includes form fields for specifying time bounds and relative time - * offsets for queries, as well as controls for selection mode, - * time systems, and zooming. - * @memberof platform.features.conductor - * @constructor - */ - function TimeConductorController( - $scope, - $window, - openmct, - formatService, - config - ) { - - //Bind functions that are used as callbacks to 'this'. - [ - "selectMenuOption", - "onPan", - "onPanStop", - "setViewFromBounds", - "setViewFromClock", - "setViewFromOffsets", - "setViewFromTimeSystem", - "setTimeSystemFromView", - "destroy" - ].forEach(function (name) { - this[name] = this[name].bind(this); - }.bind(this)); - - this.$scope = $scope; - this.$window = $window; - this.timeAPI = openmct.time; - this.conductorViewService = new TimeConductorViewService(openmct); - this.validation = new TimeConductorValidation(this.timeAPI); - this.formatService = formatService; - this.config = config; - this.timeSystemsForClocks = {}; - this.$scope.timeSystemModel = {}; - this.$scope.boundsModel = {}; - - this.timeSystems = this.timeAPI.getAllTimeSystems().reduce(function (map, timeSystem) { - map[timeSystem.key] = timeSystem; - return map; - }, {}); - - this.isFixed = this.timeAPI.clock() === undefined; - - var options = this.optionsFromConfig(config); - this.menu = { - selected: undefined, - options: options, - select: this.selectMenuOption - }; - - //Set the initial state of the UI from the conductor state - var timeSystem = this.timeAPI.timeSystem(); - if (timeSystem) { - this.setViewFromTimeSystem(timeSystem); - } - - this.setViewFromClock(this.timeAPI.clock()); - - var offsets = this.timeAPI.clockOffsets(); - if (offsets) { - this.setViewFromOffsets(offsets); - } - - var bounds = this.timeAPI.bounds(); - if (bounds && bounds.start !== undefined && bounds.end !== undefined) { - this.setViewFromBounds(bounds); - } - - this.conductorViewService.on('pan', this.onPan); - this.conductorViewService.on('pan-stop', this.onPanStop); - - //Respond to any subsequent conductor changes - this.timeAPI.on('bounds', this.setViewFromBounds); - this.timeAPI.on('timeSystem', this.setViewFromTimeSystem); - this.timeAPI.on('clock', this.setViewFromClock); - this.timeAPI.on('clockOffsets', this.setViewFromOffsets); - this.$scope.$on('$destroy', this.destroy); - } - - /** - * Given a key for a clock, retrieve the clock object. - * @private - * @param key - * @returns {Clock} - */ - TimeConductorController.prototype.getClock = function (key) { - return this.timeAPI.getAllClocks().filter(function (clock) { - return clock.key === key; - })[0]; - }; - - /** - * Activate the selected menu option. Menu options correspond to clocks. - * A distinction is made to avoid confusion between the menu options and - * their metadata, and actual {@link Clock} objects. - * - * @private - * @param newOption - */ - TimeConductorController.prototype.selectMenuOption = function (newOption) { - if (this.menu.selected.key === newOption.key) { - return; - } - this.menu.selected = newOption; - - var config = this.getConfig(this.timeAPI.timeSystem(), newOption.clock); - if (!config) { - // Clock does not support this timeSystem, fallback to first - // option provided for clock. - config = this.config.menuOptions.filter(function (menuOption) { - return menuOption.clock === (newOption.clock && newOption.clock.key); - })[0]; - } - - if (config.clock) { - this.timeAPI.clock(config.clock, config.clockOffsets); - this.timeAPI.timeSystem(config.timeSystem); - } else { - this.timeAPI.stopClock(); - this.timeAPI.timeSystem(config.timeSystem, config.bounds); - } - }; - - /** - * From the provided configuration, build the available menu options. - * @private - * @param config - * @returns {*[]} - */ - TimeConductorController.prototype.optionsFromConfig = function (config) { - /* - * "Fixed Mode" is always the first available option. - */ - var options = [{ - key: 'fixed', - name: 'Fixed Timespan Mode', - description: 'Query and explore data that falls between two fixed datetimes.', - cssClass: 'icon-calendar' - }]; - var clocks = {}; - var timeSystemsForClocks = this.timeSystemsForClocks; - - (config.menuOptions || []).forEach(function (menuOption) { - var clockKey = menuOption.clock || 'fixed'; - var clock = this.getClock(clockKey); - - if (clock !== undefined) { - clocks[clock.key] = clock; - } - - var timeSystem = this.timeSystems[menuOption.timeSystem]; - if (timeSystem !== undefined) { - timeSystemsForClocks[clockKey] = timeSystemsForClocks[clockKey] || []; - timeSystemsForClocks[clockKey].push(timeSystem); - } - }, this); - - /* - * Populate the clocks menu with metadata from the available clocks - */ - Object.values(clocks).forEach(function (clock) { - options.push({ - key: clock.key, - name: clock.name, - description: "Monitor streaming data in real-time. The Time " + - "Conductor and displays will automatically advance themselves based on this clock. " + clock.description, - cssClass: clock.cssClass || 'icon-clock', - clock: clock - }); - }.bind(this)); - - return options; - }; - - /** - * When bounds change, set UI values from the new bounds. - * @param {TimeBounds} bounds the bounds - */ - TimeConductorController.prototype.setViewFromBounds = function (bounds) { - if (!this.zooming && !this.panning) { - this.$scope.boundsModel.start = bounds.start; - this.$scope.boundsModel.end = bounds.end; - - if (this.supportsZoom()) { - var config = this.getConfig(this.timeAPI.timeSystem(), this.timeAPI.clock()); - this.currentZoom = this.toSliderValue(bounds.end - bounds.start, config.zoomOutLimit, config.zoomInLimit); - this.toTimeUnits(bounds.end - bounds.start); - } - - /* - Ensure that a digest occurs, capped at the browser's refresh - rate. - */ - if (!this.pendingUpdate) { - this.pendingUpdate = true; - this.$window.requestAnimationFrame(function () { - this.pendingUpdate = false; - this.$scope.$digest(); - }.bind(this)); - } - } - }; - - /** - * Retrieve any configuration defined for the provided time system and - * clock - * @private - * @param timeSystem - * @param clock - * @returns {object} The Time Conductor configuration corresponding to - * the provided combination of time system and clock - */ - TimeConductorController.prototype.getConfig = function (timeSystem, clock) { - var clockKey = clock && clock.key; - var timeSystemKey = timeSystem && timeSystem.key; - - var option = this.config.menuOptions.filter(function (menuOption) { - return menuOption.timeSystem === timeSystemKey && menuOption.clock === clockKey; - })[0]; - return option; - }; - - /** - * When the clock offsets change, update the values in the UI - * @param {ClockOffsets} offsets - * @private - */ - TimeConductorController.prototype.setViewFromOffsets = function (offsets) { - this.$scope.boundsModel.startOffset = Math.abs(offsets.start); - this.$scope.boundsModel.endOffset = offsets.end; - }; - - /** - * When form values for bounds change, update the bounds in the Time API - * to trigger an application-wide bounds change. - * @param {object} boundsModel - */ - TimeConductorController.prototype.setBoundsFromView = function (boundsModel) { - var bounds = this.timeAPI.bounds(); - if (boundsModel.start !== bounds.start || boundsModel.end !== bounds.end) { - this.timeAPI.bounds({ - start: boundsModel.start, - end: boundsModel.end - }); - } - }; - - /** - * When form values for bounds change, update the bounds in the Time API - * to trigger an application-wide bounds change. - * @param {object} formModel - */ - TimeConductorController.prototype.setOffsetsFromView = function (boundsModel) { - if (this.validation.validateStartOffset(boundsModel.startOffset) && this.validation.validateEndOffset(boundsModel.endOffset)) { - var offsets = { - start: 0 - boundsModel.startOffset, - end: boundsModel.endOffset - }; - var existingOffsets = this.timeAPI.clockOffsets(); - - if (offsets.start !== existingOffsets.start || offsets.end !== existingOffsets.end) { - //Sychronize offsets between form and time API - this.timeAPI.clockOffsets(offsets); - } - } - }; - - /** - * @private - * @returns {boolean} - */ - TimeConductorController.prototype.supportsZoom = function () { - var config = this.getConfig(this.timeAPI.timeSystem(), this.timeAPI.clock()); - return config && (config.zoomInLimit !== undefined && config.zoomOutLimit !== undefined); - }; - - /** - * Update the UI state to reflect a change in clock. Provided conductor - * configuration will be checked for compatibility between the new clock - * and the currently selected time system. If configuration is not available, - * an attempt will be made to default to a time system that is compatible - * with the new clock - * - * @private - * @param {Clock} clock - */ - TimeConductorController.prototype.setViewFromClock = function (clock) { - var newClockKey = clock ? clock.key : 'fixed'; - var timeSystems = this.timeSystemsForClocks[newClockKey]; - var menuOption = this.menu.options.filter(function (option) { - return option.key === (newClockKey); - })[0]; - - this.menu.selected = menuOption; - - //Try to find currently selected time system in time systems for clock - var selectedTimeSystem = timeSystems.filter(function (timeSystem) { - return timeSystem.key === this.$scope.timeSystemModel.selected.key; - }.bind(this))[0]; - - var config = this.getConfig(selectedTimeSystem, clock); - - if (selectedTimeSystem === undefined) { - selectedTimeSystem = timeSystems[0]; - config = this.getConfig(selectedTimeSystem, clock); - - if (clock === undefined) { - this.timeAPI.timeSystem(selectedTimeSystem, config.bounds); - } else { - //When time system changes, some start bounds need to be provided - this.timeAPI.timeSystem(selectedTimeSystem, { - start: clock.currentValue() + config.clockOffsets.start, - end: clock.currentValue() + config.clockOffsets.end - }); - } - } - - this.isFixed = clock === undefined; - - if (clock === undefined) { - this.setViewFromBounds(this.timeAPI.bounds()); - } - - this.zoom = this.supportsZoom(); - this.$scope.timeSystemModel.options = timeSystems; - }; - - /** - * Respond to time system selection from UI - * - * Allows time system to be changed by key. This supports selection - * from the menu. Resolves a TimeSystem object and then invokes - * TimeConductorController#setTimeSystem - * @param key - * @see TimeConductorController#setTimeSystem - */ - TimeConductorController.prototype.setTimeSystemFromView = function (key) { - var clock = this.menu.selected.clock; - var timeSystem = this.timeSystems[key]; - var config = this.getConfig(timeSystem, clock); - - this.$scope.timeSystemModel.selected = timeSystem; - this.$scope.timeSystemModel.format = timeSystem.timeFormat; - - if (clock === undefined) { - this.timeAPI.timeSystem(timeSystem, config.bounds); - } else { - this.timeAPI.clock(clock, config.clockOffsets); - this.timeAPI.timeSystem(timeSystem); - } - }; - - /** - * Handles time system change from time conductor - * - * Sets the selected time system. Will populate form with the default - * bounds and offsets defined in the selected time system. - * - * @param newTimeSystem - */ - TimeConductorController.prototype.setViewFromTimeSystem = function (timeSystem) { - var oldKey = (this.$scope.timeSystemModel.selected || {}).key; - var timeSystemModel = this.$scope.timeSystemModel; - - if (timeSystem && (timeSystem.key !== oldKey)) { - var config = this.getConfig(timeSystem, this.timeAPI.clock()); - - timeSystemModel.selected = timeSystem; - timeSystemModel.format = timeSystem.timeFormat; - timeSystemModel.durationFormat = timeSystem.durationFormat; - - if (this.supportsZoom()) { - timeSystemModel.minZoom = config.zoomOutLimit; - timeSystemModel.maxZoom = config.zoomInLimit; - } - } - this.zoom = this.supportsZoom(); - }; - - /** - * Takes a time span and calculates a slider increment value, used - * to set the horizontal offset of the slider. - * @private - * @param {number} timeSpan a duration of time, in ms - * @returns {number} a value between 0.01 and 0.99, in increments of .01 - */ - TimeConductorController.prototype.toSliderValue = function (timeSpan, zoomOutLimit, zoomInLimit) { - var perc = timeSpan / (zoomOutLimit - zoomInLimit); - return 1 - Math.pow(perc, 1 / 4); - }; - - /** - * Given a time span, set a label for the units of time that it, - * roughly, represents. Leverages - * @param {TimeSpan} timeSpan - */ - TimeConductorController.prototype.toTimeUnits = function (timeSpan) { - var timeSystem = this.timeAPI.timeSystem(); - if (timeSystem && timeSystem.isUTCBased) { - var momentified = moment.duration(timeSpan); - - this.$scope.timeUnits = timeUnitsMegastructure.filter(function (row) { - return row[1](momentified); - })[0][0]; - } - }; - - /** - * Zooming occurs when the user manipulates the zoom slider. - * Zooming updates the scale and bounds fields immediately, but does - * not trigger a bounds change to other views until the mouse button - * is released. - * @param bounds - */ - TimeConductorController.prototype.onZoom = function (sliderValue) { - var config = this.getConfig(this.timeAPI.timeSystem(), this.timeAPI.clock()); - var timeSpan = Math.pow((1 - sliderValue), 4) * (config.zoomOutLimit - config.zoomInLimit); - - var zoom = this.conductorViewService.zoom(timeSpan); - this.zooming = true; - - this.$scope.boundsModel.start = zoom.bounds.start; - this.$scope.boundsModel.end = zoom.bounds.end; - this.toTimeUnits(zoom.bounds.end - zoom.bounds.start); - - if (zoom.offsets) { - this.setViewFromOffsets(zoom.offsets); - } - }; - - /** - * Fired when user has released the zoom slider - * @event platform.features.conductor.TimeConductorController~zoomStop - */ - /** - * Invoked when zoom slider is released by user. Will update the time conductor with the new bounds, triggering - * a global bounds change event. - * @fires platform.features.conductor.TimeConductorController~zoomStop - */ - TimeConductorController.prototype.onZoomStop = function () { - if (this.timeAPI.clock() !== undefined) { - this.setOffsetsFromView(this.$scope.boundsModel); - } - this.setBoundsFromView(this.$scope.boundsModel); - - this.zooming = false; - this.conductorViewService.emit('zoom-stop'); - }; - - /** - * Panning occurs when the user grabs the conductor scale and drags - * it left or right to slide the window of time represented by the - * conductor. Panning updates the scale and bounds fields - * immediately, but does not trigger a bounds change to other views - * until the mouse button is released. - * @param {TimeConductorBounds} bounds - */ - TimeConductorController.prototype.onPan = function (bounds) { - this.panning = true; - this.$scope.boundsModel.start = bounds.start; - this.$scope.boundsModel.end = bounds.end; - }; - - /** - * Called when the user releases the mouse button after panning. - */ - TimeConductorController.prototype.onPanStop = function () { - this.panning = false; - }; - - /** - * @private - */ - TimeConductorController.prototype.destroy = function () { - this.timeAPI.off('bounds', this.setViewFromBounds); - this.timeAPI.off('timeSystem', this.setViewFromTimeSystem); - this.timeAPI.off('clock', this.setViewFromClock); - this.timeAPI.off('follow', this.setFollow); - this.timeAPI.off('clockOffsets', this.setViewFromOffsets); - - this.conductorViewService.off('pan', this.onPan); - this.conductorViewService.off('pan-stop', this.onPanStop); - }; - - return TimeConductorController; - } -); diff --git a/platform/features/conductor/core/src/ui/TimeConductorControllerSpec.js b/platform/features/conductor/core/src/ui/TimeConductorControllerSpec.js deleted file mode 100644 index 8fb7d5972d..0000000000 --- a/platform/features/conductor/core/src/ui/TimeConductorControllerSpec.js +++ /dev/null @@ -1,513 +0,0 @@ -/***************************************************************************** - * 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(['./TimeConductorController'], function (TimeConductorController) { - xdescribe("The time conductor controller", function () { - var mockScope; - var mockWindow; - var mockTimeConductor; - var mockConductorViewService; - var mockTimeSystems; - var controller; - var mockFormatService; - var mockFormat; - var mockLocation; - - beforeEach(function () { - mockScope = jasmine.createSpyObj("$scope", [ - "$watch", - "$on" - ]); - - mockWindow = jasmine.createSpyObj("$window", ["requestAnimationFrame"]); - mockTimeConductor = jasmine.createSpyObj( - "TimeConductor", - [ - "bounds", - "timeSystem", - "on", - "off" - ] - ); - mockTimeConductor.bounds.and.returnValue({start: undefined, end: undefined}); - - mockConductorViewService = jasmine.createSpyObj( - "ConductorViewService", - [ - "availableModes", - "mode", - "availableTimeSystems", - "deltas", - "deltas", - "on", - "off" - ] - ); - mockConductorViewService.availableModes.and.returnValue([]); - mockConductorViewService.availableTimeSystems.and.returnValue([]); - - mockFormatService = jasmine.createSpyObj('formatService', [ - 'getFormat' - ]); - mockFormat = jasmine.createSpyObj('format', [ - 'format' - ]); - mockFormatService.getFormat.and.returnValue(mockFormat); - mockLocation = jasmine.createSpyObj('location', [ - 'search' - ]); - mockLocation.search.and.returnValue({}); - - mockTimeSystems = []; - }); - - function getListener(target, event) { - return target.calls.all().filter(function (call) { - return call.args[0] === event; - })[0].args[1]; - } - - describe("when time conductor state changes", function () { - var mockDeltaFormat; - var defaultBounds; - var defaultDeltas; - var mockDefaults; - var timeSystem; - var tsListener; - - beforeEach(function () { - mockFormat = {}; - mockDeltaFormat = {}; - defaultBounds = { - start: 2, - end: 3 - }; - defaultDeltas = { - start: 10, - end: 20 - }; - mockDefaults = { - deltas: defaultDeltas, - bounds: defaultBounds - }; - timeSystem = { - metadata: { - key: 'mock' - }, - formats: function () { - return [mockFormat]; - }, - deltaFormat: function () { - return mockDeltaFormat; - }, - defaults: function () { - return mockDefaults; - } - }; - - controller = new TimeConductorController( - mockScope, - mockWindow, - mockLocation, - {conductor: mockTimeConductor}, - mockConductorViewService, - mockFormatService, - 'fixed', - true - - ); - - tsListener = getListener(mockTimeConductor.on, "timeSystem"); - }); - - it("listens for changes to conductor state", function () { - expect(mockTimeConductor.on).toHaveBeenCalledWith("timeSystem", controller.changeTimeSystem); - expect(mockTimeConductor.on).toHaveBeenCalledWith("bounds", controller.changeBounds); - }); - - it("deregisters conductor listens when scope is destroyed", function () { - expect(mockScope.$on).toHaveBeenCalledWith("$destroy", controller.destroy); - - controller.destroy(); - expect(mockTimeConductor.off).toHaveBeenCalledWith("timeSystem", controller.changeTimeSystem); - expect(mockTimeConductor.off).toHaveBeenCalledWith("bounds", controller.changeBounds); - }); - - it("when time system changes, sets time system on scope", function () { - expect(tsListener).toBeDefined(); - tsListener(timeSystem); - - expect(mockScope.timeSystemModel).toBeDefined(); - expect(mockScope.timeSystemModel.selected).toBe(timeSystem); - expect(mockScope.timeSystemModel.format).toBe(mockFormat); - expect(mockScope.timeSystemModel.deltaFormat).toBe(mockDeltaFormat); - }); - - it("when time system changes, sets defaults on scope", function () { - mockDefaults.zoom = { - min: 100, - max: 10 - }; - mockTimeConductor.timeSystem.and.returnValue(timeSystem); - tsListener(timeSystem); - - expect(mockScope.boundsModel.start).toEqual(defaultBounds.start); - expect(mockScope.boundsModel.end).toEqual(defaultBounds.end); - - expect(mockScope.boundsModel.startDelta).toEqual(defaultDeltas.start); - expect(mockScope.boundsModel.endDelta).toEqual(defaultDeltas.end); - - expect(mockScope.timeSystemModel.minZoom).toBe(mockDefaults.zoom.min); - expect(mockScope.timeSystemModel.maxZoom).toBe(mockDefaults.zoom.max); - }); - - it("supports zoom if time system defines zoom defaults", function () { - - mockDefaults.zoom = undefined; - - tsListener(timeSystem); - expect(controller.supportsZoom).toBe(false); - - mockDefaults.zoom = { - min: 100, - max: 10 - }; - - var anotherTimeSystem = Object.create(timeSystem); - timeSystem.defaults = function () { - return mockDefaults; - }; - - tsListener(anotherTimeSystem); - expect(controller.supportsZoom).toBe(true); - - }); - - it("when bounds change, sets the correct zoom slider value", function () { - var bounds = { - start: 0, - end: 50 - }; - mockDefaults.zoom = { - min: 100, - max: 0 - }; - - function exponentializer(rawValue) { - return 1 - Math.pow(rawValue, 1 / 4); - } - - mockTimeConductor.timeSystem.and.returnValue(timeSystem); - //Set zoom defaults - tsListener(timeSystem); - - controller.changeBounds(bounds); - expect(controller.currentZoom).toEqual(exponentializer(0.5)); - - }); - - it("when bounds change, sets them on scope", function () { - var bounds = { - start: 1, - end: 2 - }; - - var boundsListener = getListener(mockTimeConductor.on, "bounds"); - expect(boundsListener).toBeDefined(); - boundsListener(bounds); - - expect(mockScope.boundsModel).toBeDefined(); - expect(mockScope.boundsModel.start).toEqual(bounds.start); - expect(mockScope.boundsModel.end).toEqual(bounds.end); - }); - }); - - describe("when user makes changes from UI", function () { - var mode = "realtime"; - var ts1Metadata; - var ts2Metadata; - var ts3Metadata; - - beforeEach(function () { - mode = "realtime"; - ts1Metadata = { - 'key': 'ts1', - 'name': 'Time System One', - 'cssClass': 'cssClassOne' - }; - ts2Metadata = { - 'key': 'ts2', - 'name': 'Time System Two', - 'cssClass': 'cssClassTwo' - }; - ts3Metadata = { - 'key': 'ts3', - 'name': 'Time System Three', - 'cssClass': 'cssClassThree' - }; - mockTimeSystems = [ - { - metadata: ts1Metadata - }, - { - metadata: ts2Metadata - }, - { - metadata: ts3Metadata - } - ]; - - //Wrap in mock constructors - mockConductorViewService.systems = mockTimeSystems; - - controller = new TimeConductorController( - mockScope, - mockWindow, - mockLocation, - {conductor: mockTimeConductor}, - mockConductorViewService, - mockFormatService, - "fixed", - true - ); - }); - - it("sets the mode on scope", function () { - mockConductorViewService.availableTimeSystems.and.returnValue(mockTimeSystems); - controller.setMode(mode); - - expect(mockScope.modeModel.selectedKey).toEqual(mode); - }); - - it("sets available time systems on scope when mode changes", function () { - mockConductorViewService.availableTimeSystems.and.returnValue(mockTimeSystems); - controller.setMode(mode); - - expect(mockScope.timeSystemModel.options.length).toEqual(3); - expect(mockScope.timeSystemModel.options[0]).toEqual(ts1Metadata); - expect(mockScope.timeSystemModel.options[1]).toEqual(ts2Metadata); - expect(mockScope.timeSystemModel.options[2]).toEqual(ts3Metadata); - }); - - it("sets bounds on the time conductor", function () { - var formModel = { - start: 1, - end: 10 - }; - - controller.setBounds(formModel); - expect(mockTimeConductor.bounds).toHaveBeenCalledWith(formModel); - }); - - it("applies deltas when they change in form", function () { - var deltas = { - start: 1000, - end: 2000 - }; - var formModel = { - startDelta: deltas.start, - endDelta: deltas.end - }; - - controller.setDeltas(formModel); - expect(mockConductorViewService.deltas).toHaveBeenCalledWith(deltas); - }); - - it("sets the time system on the time conductor", function () { - var defaultBounds = { - start: 5, - end: 6 - }; - var timeSystem = { - metadata: { - key: 'testTimeSystem' - }, - defaults: function () { - return { - bounds: defaultBounds - }; - } - }; - - controller.timeSystems = [timeSystem]; - - controller.selectTimeSystemByKey('testTimeSystem'); - expect(mockTimeConductor.timeSystem).toHaveBeenCalledWith(timeSystem, defaultBounds); - }); - - it("updates form bounds during pan events", function () { - var testBounds = { - start: 10, - end: 20 - }; - - expect(controller.$scope.boundsModel.start).not.toBe(testBounds.start); - expect(controller.$scope.boundsModel.end).not.toBe(testBounds.end); - - expect(controller.conductorViewService.on).toHaveBeenCalledWith("pan", - controller.onPan); - - getListener(controller.conductorViewService.on, "pan")(testBounds); - - expect(controller.$scope.boundsModel.start).toBe(testBounds.start); - expect(controller.$scope.boundsModel.end).toBe(testBounds.end); - }); - }); - - describe("when the URL defines conductor state", function () { - var urlBounds; - var urlTimeSystem; - var urlDeltas; - - var mockDeltaFormat; - var defaultBounds; - var defaultDeltas; - var mockDefaults; - var timeSystem; - var otherTimeSystem; - var mockSearchObject; - - beforeEach(function () { - - mockFormat = {}; - mockDeltaFormat = {}; - defaultBounds = { - start: 2, - end: 3 - }; - defaultDeltas = { - start: 10, - end: 20 - }; - mockDefaults = { - deltas: defaultDeltas, - bounds: defaultBounds - }; - timeSystem = { - metadata: { - key: 'mockTimeSystem' - }, - formats: function () { - return [mockFormat]; - }, - deltaFormat: function () { - return mockDeltaFormat; - }, - defaults: function () { - return mockDefaults; - } - }; - otherTimeSystem = { - metadata: { - key: 'otherTimeSystem' - }, - formats: function () { - return [mockFormat]; - }, - deltaFormat: function () { - return mockDeltaFormat; - }, - defaults: function () { - return mockDefaults; - } - }; - - mockConductorViewService.systems = [timeSystem, otherTimeSystem]; - - urlBounds = { - start: 100, - end: 200 - }; - urlTimeSystem = "otherTimeSystem"; - urlDeltas = { - start: 300, - end: 400 - }; - mockSearchObject = { - "tc.startBound": urlBounds.start, - "tc.endBound": urlBounds.end, - "tc.startDelta": urlDeltas.start, - "tc.endDelta": urlDeltas.end, - "tc.timeSystem": urlTimeSystem - }; - mockLocation.search.and.returnValue(mockSearchObject); - mockTimeConductor.timeSystem.and.returnValue(timeSystem); - - controller = new TimeConductorController( - mockScope, - mockWindow, - mockLocation, - {conductor: mockTimeConductor}, - mockConductorViewService, - mockFormatService, - "fixed", - true - ); - - spyOn(controller, "setMode"); - spyOn(controller, "selectTimeSystemByKey"); - }); - - it("sets conductor state from URL", function () { - mockSearchObject["tc.mode"] = "fixed"; - controller.setStateFromSearchParams(mockSearchObject); - expect(controller.selectTimeSystemByKey).toHaveBeenCalledWith("otherTimeSystem"); - expect(mockTimeConductor.bounds).toHaveBeenCalledWith(urlBounds); - }); - - it("sets mode from URL", function () { - mockTimeConductor.bounds.reset(); - mockSearchObject["tc.mode"] = "realtime"; - controller.setStateFromSearchParams(mockSearchObject); - expect(controller.setMode).toHaveBeenCalledWith("realtime"); - expect(controller.selectTimeSystemByKey).toHaveBeenCalledWith("otherTimeSystem"); - expect(mockConductorViewService.deltas).toHaveBeenCalledWith(urlDeltas); - expect(mockTimeConductor.bounds).not.toHaveBeenCalled(); - }); - - describe("when conductor state changes", function () { - it("updates the URL with the mode", function () { - controller.setMode("realtime", "fixed"); - expect(mockLocation.search).toHaveBeenCalledWith("tc.mode", "fixed"); - }); - - it("updates the URL with the bounds", function () { - mockConductorViewService.mode.and.returnValue("fixed"); - controller.changeBounds({start: 500, end: 600}); - expect(mockLocation.search).toHaveBeenCalledWith("tc.startBound", 500); - expect(mockLocation.search).toHaveBeenCalledWith("tc.endBound", 600); - }); - - it("updates the URL with the deltas", function () { - controller.setDeltas({startDelta: 700, endDelta: 800}); - expect(mockLocation.search).toHaveBeenCalledWith("tc.startDelta", 700); - expect(mockLocation.search).toHaveBeenCalledWith("tc.endDelta", 800); - }); - - it("updates the URL with the time system", function () { - controller.changeTimeSystem(otherTimeSystem); - expect(mockLocation.search).toHaveBeenCalledWith("tc.timeSystem", "otherTimeSystem"); - }); - }); - }); - }); -}); diff --git a/platform/features/conductor/core/src/ui/TimeConductorValidation.js b/platform/features/conductor/core/src/ui/TimeConductorValidation.js deleted file mode 100644 index 8f012452ee..0000000000 --- a/platform/features/conductor/core/src/ui/TimeConductorValidation.js +++ /dev/null @@ -1,69 +0,0 @@ -/***************************************************************************** - * 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( - [], - function () { - - /** - * Form validation for the TimeConductorController. - * @param conductor - * @constructor - */ - function TimeConductorValidation(timeAPI) { - var self = this; - this.timeAPI = timeAPI; - - /* - * Bind all class functions to 'this' - */ - Object.keys(TimeConductorValidation.prototype).filter(function (key) { - return typeof TimeConductorValidation.prototype[key] === 'function'; - }).forEach(function (key) { - self[key] = self[key].bind(self); - }); - } - - /** - * Validation methods below are invoked directly from controls in the TimeConductor form - */ - TimeConductorValidation.prototype.validateStart = function (start) { - var bounds = this.timeAPI.bounds(); - return this.timeAPI.validateBounds({start: start, end: bounds.end}) === true; - }; - - TimeConductorValidation.prototype.validateEnd = function (end) { - var bounds = this.timeAPI.bounds(); - return this.timeAPI.validateBounds({start: bounds.start, end: end}) === true; - }; - - TimeConductorValidation.prototype.validateStartOffset = function (startOffset) { - return !isNaN(startOffset) && startOffset > 0; - }; - - TimeConductorValidation.prototype.validateEndOffset = function (endOffset) { - return !isNaN(endOffset) && endOffset >= 0; - }; - - return TimeConductorValidation; - } -); diff --git a/platform/features/conductor/core/src/ui/TimeConductorValidationSpec.js b/platform/features/conductor/core/src/ui/TimeConductorValidationSpec.js deleted file mode 100644 index c5951db2a7..0000000000 --- a/platform/features/conductor/core/src/ui/TimeConductorValidationSpec.js +++ /dev/null @@ -1,73 +0,0 @@ -/***************************************************************************** - * 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(['./TimeConductorValidation'], function (TimeConductorValidation) { - describe("The Time Conductor Validation class", function () { - var timeConductorValidation, - mockTimeConductor; - - beforeEach(function () { - mockTimeConductor = jasmine.createSpyObj("timeConductor", [ - "validateBounds", - "bounds" - ]); - timeConductorValidation = new TimeConductorValidation(mockTimeConductor); - }); - - describe("Validates start and end values using Time Conductor", function () { - beforeEach(function () { - var mockBounds = { - start: 10, - end: 20 - }; - - mockTimeConductor.bounds.and.returnValue(mockBounds); - - }); - it("Validates start values using Time Conductor", function () { - var startValue = 30; - timeConductorValidation.validateStart(startValue); - expect(mockTimeConductor.validateBounds).toHaveBeenCalled(); - }); - it("Validates end values using Time Conductor", function () { - var endValue = 40; - timeConductorValidation.validateEnd(endValue); - expect(mockTimeConductor.validateBounds).toHaveBeenCalled(); - }); - }); - - it("Validates that start Offset is valid number > 0", function () { - expect(timeConductorValidation.validateStartOffset(-1)).toBe(false); - expect(timeConductorValidation.validateStartOffset("abc")).toBe(false); - expect(timeConductorValidation.validateStartOffset("1")).toBe(true); - expect(timeConductorValidation.validateStartOffset(1)).toBe(true); - }); - - it("Validates that end Offset is valid number >= 0", function () { - expect(timeConductorValidation.validateEndOffset(-1)).toBe(false); - expect(timeConductorValidation.validateEndOffset("abc")).toBe(false); - expect(timeConductorValidation.validateEndOffset("1")).toBe(true); - expect(timeConductorValidation.validateEndOffset(0)).toBe(true); - expect(timeConductorValidation.validateEndOffset(1)).toBe(true); - }); - }); -}); diff --git a/platform/features/conductor/core/src/ui/TimeConductorViewService.js b/platform/features/conductor/core/src/ui/TimeConductorViewService.js deleted file mode 100644 index 001e8221d0..0000000000 --- a/platform/features/conductor/core/src/ui/TimeConductorViewService.js +++ /dev/null @@ -1,97 +0,0 @@ -/***************************************************************************** - * 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( - [ - 'EventEmitter' - ], - function (EventEmitter) { - - /** - * The TimeConductorViewService acts as an event bus between different - * elements of the Time Conductor UI. Zooming and panning occur via this - * service, as they are specific behaviour of the UI, and not general - * functions of the time API. - * - * Synchronization of conductor state between the Time API and the URL - * also occurs from the conductor view service, whose lifecycle persists - * between view changes. - * - * @memberof platform.features.conductor - * @param conductor - * @constructor - */ - function TimeConductorViewService(openmct) { - - EventEmitter.call(this); - - this.timeAPI = openmct.time; - } - - TimeConductorViewService.prototype = Object.create(EventEmitter.prototype); - - /** - * An event to indicate that zooming is taking place - * @event platform.features.conductor.TimeConductorViewService~zoom - * @property {ZoomLevel} zoom the new zoom level. - */ - /** - * Zoom to given time span. Will fire a zoom event with new zoom - * bounds. Zoom bounds emitted in this way are considered ephemeral - * and should be overridden by any time conductor bounds events. Does - * not set bounds globally. - * @param {number} zoom A time duration in ms - * @fires platform.features.conductor.TimeConductorViewService~zoom - * @see module:openmct.TimeConductor#bounds - */ - TimeConductorViewService.prototype.zoom = function (timeSpan) { - var zoom = {}; - - // If a tick source is defined, then the concept of 'now' is - // important. Calculate zoom based on 'now'. - if (this.timeAPI.clock() !== undefined) { - zoom.offsets = { - start: -timeSpan, - end: this.timeAPI.clockOffsets().end - }; - - var currentVal = this.timeAPI.clock().currentValue(); - - zoom.bounds = { - start: currentVal + zoom.offsets.start, - end: currentVal + zoom.offsets.end - }; - } else { - var bounds = this.timeAPI.bounds(); - var center = bounds.start + ((bounds.end - bounds.start)) / 2; - bounds.start = center - timeSpan / 2; - bounds.end = center + timeSpan / 2; - zoom.bounds = bounds; - } - - this.emit("zoom", zoom); - return zoom; - }; - - return TimeConductorViewService; - } -); diff --git a/platform/features/conductor/core/src/ui/TimeOfInterestController.js b/platform/features/conductor/core/src/ui/TimeOfInterestController.js deleted file mode 100644 index daaffcc69f..0000000000 --- a/platform/features/conductor/core/src/ui/TimeOfInterestController.js +++ /dev/null @@ -1,109 +0,0 @@ -/***************************************************************************** - * 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( - [], - function () { - - /** - * Controller for the Time of Interest element used in various views to display the TOI. Responsible for setting - * the text label for the current TOI, and for toggling the (un)pinned state which determines whether the TOI - * indicator is visible. - * @constructor - */ - function TimeOfInterestController($scope, openmct, formatService) { - this.timeAPI = openmct.time; - this.formatService = formatService; - this.format = undefined; - this.toiText = undefined; - this.$scope = $scope; - - //Bind all class functions to 'this' - Object.keys(TimeOfInterestController.prototype).filter(function (key) { - return typeof TimeOfInterestController.prototype[key] === 'function'; - }).forEach(function (key) { - this[key] = TimeOfInterestController.prototype[key].bind(this); - }.bind(this)); - - this.timeAPI.on('timeOfInterest', this.changeTimeOfInterest); - this.timeAPI.on('timeSystem', this.changeTimeSystem); - if (this.timeAPI.timeSystem() !== undefined) { - this.changeTimeSystem(this.timeAPI.timeSystem()); - var toi = this.timeAPI.timeOfInterest(); - if (toi) { - this.changeTimeOfInterest(toi); - } - } - - $scope.$on('$destroy', this.destroy); - } - - /** - * Called when the time of interest changes on the conductor. Will pin (display) the TOI indicator, and set the - * text using the default formatter of the currently active Time System. - * @private - * @param {integer} toi Current time of interest in ms - */ - TimeOfInterestController.prototype.changeTimeOfInterest = function (toi) { - if (toi !== undefined) { - this.$scope.pinned = true; - this.toiText = this.format.format(toi); - } else { - this.$scope.pinned = false; - } - }; - - /** - * When time system is changed, update the formatter used to - * display the current TOI label - */ - TimeOfInterestController.prototype.changeTimeSystem = function (timeSystem) { - this.format = this.formatService.getFormat(timeSystem.timeFormat); - }; - - /** - * @private - */ - TimeOfInterestController.prototype.destroy = function () { - this.timeAPI.off('timeOfInterest', this.changeTimeOfInterest); - this.timeAPI.off('timeSystem', this.changeTimeSystem); - }; - - /** - * Will unpin (hide) the TOI indicator. Has the effect of setting the time of interest to `undefined` on the - * Time Conductor - */ - TimeOfInterestController.prototype.dismiss = function () { - this.timeAPI.timeOfInterest(undefined); - }; - - /** - * Sends out a time of interest event with the effect of resetting - * the TOI displayed in views. - */ - TimeOfInterestController.prototype.resync = function () { - this.timeAPI.timeOfInterest(this.timeAPI.timeOfInterest()); - }; - - return TimeOfInterestController; - } -); diff --git a/src/MCT.js b/src/MCT.js index 209d048b65..1d97e19a3a 100644 --- a/src/MCT.js +++ b/src/MCT.js @@ -316,7 +316,6 @@ define([ } }); domElement.appendChild(appLayout.$mount().$el); - this.layout = appLayout; Browse(this); this.router.start(); diff --git a/src/defaultRegistry.js b/src/defaultRegistry.js index c75cd3f0b2..0437e0d04e 100644 --- a/src/defaultRegistry.js +++ b/src/defaultRegistry.js @@ -55,8 +55,6 @@ define([ '../platform/exporters/bundle', '../platform/features/clock/bundle', '../platform/features/fixed/bundle', - '../platform/features/conductor/core/bundle', - '../platform/features/conductor/compatibility/bundle', '../platform/features/imagery/bundle', '../platform/features/layout/bundle', '../platform/features/listview/bundle', diff --git a/src/plugins/localTimeSystem/LocalTimeFormat.js b/src/plugins/localTimeSystem/LocalTimeFormat.js index 86c12ccd6a..9536bf82cd 100644 --- a/src/plugins/localTimeSystem/LocalTimeFormat.js +++ b/src/plugins/localTimeSystem/LocalTimeFormat.js @@ -51,64 +51,12 @@ define([ function LocalTimeFormat() { } - /** - * Returns an appropriate time format based on the provided value and - * the threshold required. - * @private - */ - function getScaledFormat(d) { - var momentified = moment.utc(d); - /** - * Uses logic from d3 Time-Scales, v3 of the API. See - * https://github.com/d3/d3-3.x-api-reference/blob/master/Time-Scales.md - * - * Licensed - */ - return [ - [".SSS", function (m) { - return m.milliseconds(); - }], - [":ss", function (m) { - return m.seconds(); - }], - ["hh:mma", function (m) { - return m.minutes(); - }], - ["hha", function (m) { - return m.hours(); - }], - ["ddd DD", function (m) { - return m.days() && - m.date() !== 1; - }], - ["MMM DD", function (m) { - return m.date() !== 1; - }], - ["MMMM", function (m) { - return m.month(); - }], - ["YYYY", function () { - return true; - }] - ].filter(function (row) { - return row[1](momentified); - })[0][0]; - } - /** * * @param value - * @param {Scale} [scale] Optionally provides context to the - * format request, allowing for scale-appropriate formatting. * @returns {string} the formatted date */ LocalTimeFormat.prototype.format = function (value, scale) { - if (scale !== undefined) { - var scaledFormat = getScaledFormat(value, scale); - if (scaledFormat) { - return moment.utc(value).format(scaledFormat); - } - } return moment(value).format(DATE_FORMAT); }; diff --git a/src/plugins/localTimeSystem/LocalTimeSystem.js b/src/plugins/localTimeSystem/LocalTimeSystem.js index 3f08d07fe4..fd37b334df 100644 --- a/src/plugins/localTimeSystem/LocalTimeSystem.js +++ b/src/plugins/localTimeSystem/LocalTimeSystem.js @@ -41,7 +41,7 @@ define([], function () { this.timeFormat = 'local-format'; this.durationFormat = 'duration'; - this.isUTCBased = true; + this.isUTCBased = false; } return LocalTimeSystem; diff --git a/src/plugins/plugins.js b/src/plugins/plugins.js index 2d98437c63..ab44dd2c2e 100644 --- a/src/plugins/plugins.js +++ b/src/plugins/plugins.js @@ -103,7 +103,7 @@ define([ */ plugins.AutoflowView = AutoflowPlugin; - plugins.Conductor = TimeConductorPlugin; + plugins.Conductor = TimeConductorPlugin.default; plugins.CouchDB = function (url) { return function (openmct) { diff --git a/src/plugins/timeConductor/Conductor.vue b/src/plugins/timeConductor/Conductor.vue new file mode 100644 index 0000000000..f240be2acb --- /dev/null +++ b/src/plugins/timeConductor/Conductor.vue @@ -0,0 +1,353 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2018, 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. + *****************************************************************************/ + + + + + + + diff --git a/src/plugins/timeConductor/ConductorAxis.vue b/src/plugins/timeConductor/ConductorAxis.vue new file mode 100644 index 0000000000..0d43747758 --- /dev/null +++ b/src/plugins/timeConductor/ConductorAxis.vue @@ -0,0 +1,177 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2018, 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. + *****************************************************************************/ + + + + + diff --git a/src/plugins/timeConductor/ConductorMode.vue b/src/plugins/timeConductor/ConductorMode.vue new file mode 100644 index 0000000000..4eb4df0cd1 --- /dev/null +++ b/src/plugins/timeConductor/ConductorMode.vue @@ -0,0 +1,196 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2018, 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. + *****************************************************************************/ + + + + + diff --git a/src/plugins/timeConductor/ConductorTimeSystem.vue b/src/plugins/timeConductor/ConductorTimeSystem.vue new file mode 100644 index 0000000000..3691150578 --- /dev/null +++ b/src/plugins/timeConductor/ConductorTimeSystem.vue @@ -0,0 +1,132 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2018, 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. + *****************************************************************************/ + + + + + diff --git a/src/plugins/timeConductor/DatePicker.vue b/src/plugins/timeConductor/DatePicker.vue new file mode 100644 index 0000000000..b32bfd7a93 --- /dev/null +++ b/src/plugins/timeConductor/DatePicker.vue @@ -0,0 +1,242 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2018, 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. + *****************************************************************************/ + + + + + diff --git a/src/plugins/timeConductor/plugin.js b/src/plugins/timeConductor/plugin.js index 8aea344388..cb309b260b 100644 --- a/src/plugins/timeConductor/plugin.js +++ b/src/plugins/timeConductor/plugin.js @@ -20,110 +20,108 @@ * at runtime from the About dialog for additional information. *****************************************************************************/ -define([], function () { +import Conductor from './Conductor.vue'; +import Vue from 'vue'; - function isTruthy(a) { - return !!a; +function isTruthy(a) { + return !!a; +} + +function validateMenuOption(menuOption, index) { + if (menuOption.clock && !menuOption.clockOffsets) { + return "clock-based menuOption at index " + index + " is " + + "missing required property 'clockOffsets'."; } - - function validateMenuOption(menuOption, index) { - if (menuOption.clock && !menuOption.clockOffsets) { - return "clock-based menuOption at index " + index + " is " + - "missing required property 'clockOffsets'."; - } - if (!menuOption.timeSystem) { - return "menuOption at index " + index + " is missing " + - "required property 'timeSystem'."; - } - if (!menuOption.bounds && !menuOption.clock) { - return "fixed-bounds menuOption at index " + index + " is " + - "missing required property 'bounds'"; - } + if (!menuOption.timeSystem) { + return "menuOption at index " + index + " is missing " + + "required property 'timeSystem'."; } - - function validateConfiguration(config) { - if (config === undefined || - config.menuOptions === undefined || - config.menuOptions.length === 0) { - return "You must specify one or more 'menuOptions'."; - } - if (config.menuOptions.some(validateMenuOption)) { - return config.menuOptions.map(validateMenuOption) - .filter(isTruthy) - .join('\n'); - } - return undefined; + if (!menuOption.bounds && !menuOption.clock) { + return "fixed-bounds menuOption at index " + index + " is " + + "missing required property 'bounds'"; } +} - function validateRuntimeConfiguration(config, openmct) { - var systems = openmct.time.getAllTimeSystems() - .reduce(function (m, ts) { - m[ts.key] = ts; - return m; - }, {}); - var clocks = openmct.time.getAllClocks() - .reduce(function (m, c) { - m[c.key] = c; - return m; - }, {}); - - return config.menuOptions.map(function (menuOption, index) { - if (menuOption.timeSystem && !systems[menuOption.timeSystem]) { - return "menuOption at index " + index + " specifies a " + - "timeSystem that does not exist: " + menuOption.timeSystem; - } - if (menuOption.clock && !clocks[menuOption.clock]) { - return "menuOption at index " + index + " specifies a " + - "clock that does not exist: " + menuOption.clock; - } - }) +function validateConfiguration(config) { + if (config === undefined || + config.menuOptions === undefined || + config.menuOptions.length === 0) { + return "You must specify one or more 'menuOptions'."; + } + if (config.menuOptions.some(validateMenuOption)) { + return config.menuOptions.map(validateMenuOption) .filter(isTruthy) .join('\n'); } + return undefined; +} - function throwConfigErrorIfExists(error) { - if (error) { - throw new Error("Invalid Time Conductor Configuration: \n" + - error + '\n' + - "https://github.com/nasa/openmct/blob/master/API.md#the-time-conductor"); +function validateRuntimeConfiguration(config, openmct) { + var systems = openmct.time.getAllTimeSystems() + .reduce(function (m, ts) { + m[ts.key] = ts; + return m; + }, {}); + var clocks = openmct.time.getAllClocks() + .reduce(function (m, c) { + m[c.key] = c; + return m; + }, {}); + + return config.menuOptions.map(function (menuOption, index) { + if (menuOption.timeSystem && !systems[menuOption.timeSystem]) { + return "menuOption at index " + index + " specifies a " + + "timeSystem that does not exist: " + menuOption.timeSystem; } + if (menuOption.clock && !clocks[menuOption.clock]) { + return "menuOption at index " + index + " specifies a " + + "clock that does not exist: " + menuOption.clock; + } + }).filter(isTruthy).join('\n'); +} + +function throwIfError(configResult) { + if (configResult) { + throw new Error("Invalid Time Conductor Configuration: \n" + + configResult + '\n' + + "https://github.com/nasa/openmct/blob/master/API.md#the-time-conductor"); } +} - return function (config) { +function mountComponent(openmct, configuration) { + openmct.layout.conductorComponent = Object.create({ + components: { + Conductor + }, + template: "", + provide: { + openmct: openmct, + configuration: configuration + } + }); +} - throwConfigErrorIfExists(validateConfiguration(config)); +export default function (config){ - return function (openmct) { + let configResult = validateConfiguration(config); + throwIfError(configResult); - openmct.legacyExtension('constants', { - key: 'CONDUCTOR_CONFIG', - value: config, - priority: 'mandatory' - }); + return function (openmct) { - openmct.legacyRegistry.enable('platform/features/conductor/core'); - openmct.legacyRegistry.enable('platform/features/conductor/compatibility'); + openmct.on('start', function () { + configResult = validateRuntimeConfiguration(config, openmct); + throwIfError(configResult); - openmct.on('start', function () { + var defaults = config.menuOptions[0]; + if (defaults.clock) { + openmct.time.clock(defaults.clock, defaults.clockOffsets); + openmct.time.timeSystem(defaults.timeSystem, openmct.time.bounds()); + } else { + openmct.time.timeSystem(defaults.timeSystem, defaults.bounds); + } - throwConfigErrorIfExists(validateRuntimeConfiguration(config, openmct)); + mountComponent(openmct, config); - /* - On app startup, default the conductor if not already set. - */ - if (openmct.time.timeSystem() !== undefined) { - return; - } - - var defaults = config.menuOptions[0]; - if (defaults.clock) { - openmct.time.clock(defaults.clock, defaults.clockOffsets); - openmct.time.timeSystem(defaults.timeSystem, openmct.time.bounds()); - } else { - openmct.time.timeSystem(defaults.timeSystem, defaults.bounds); - } - - }); - }; + }); }; -}); +}; diff --git a/platform/features/conductor/core/src/ui/StringFormat.js b/src/plugins/timeConductor/utcMultiTimeFormat.js similarity index 53% rename from platform/features/conductor/core/src/ui/StringFormat.js rename to src/plugins/timeConductor/utcMultiTimeFormat.js index 78061a4d5c..bae46eba25 100644 --- a/platform/features/conductor/core/src/ui/StringFormat.js +++ b/src/plugins/timeConductor/utcMultiTimeFormat.js @@ -20,34 +20,47 @@ * at runtime from the About dialog for additional information. *****************************************************************************/ -define([], function () { +import moment from 'moment'; +export default function multiFormat(date) { + var momentified = moment.utc(date); /** - * Formatter for basic strings. + * Uses logic from d3 Time-Scales, v3 of the API. See + * https://github.com/d3/d3-3.x-api-reference/blob/master/Time-Scales.md * - * @implements {Format} - * @constructor - * @memberof platform/commonUI/formats + * Licensed */ - function StringFormat() { - this.key = 'string'; + var format = [ + [".SSS", function (m) { + return m.milliseconds(); + }], + [":ss", function (m) { + return m.seconds(); + }], + ["HH:mm", function (m) { + return m.minutes(); + }], + ["HH:mm", function (m) { + return m.hours(); + }], + ["ddd DD", function (m) { + return m.days() && + m.date() !== 1; + }], + ["MMM DD", function (m) { + return m.date() !== 1; + }], + ["MMMM", function (m) { + return m.month(); + }], + ["YYYY", function () { + return true; + }] + ].filter(function (row) { + return row[1](momentified); + })[0][0]; + + if (format !== undefined) { + return moment.utc(date).format(format); } - - StringFormat.prototype.format = function (string) { - if (typeof string === 'string') { - return string; - } else { - return '' + string; - } - }; - - StringFormat.prototype.parse = function (string) { - return string; - }; - - StringFormat.prototype.validate = function (string) { - return typeof string === 'string'; - }; - - return StringFormat; -}); +} diff --git a/src/ui/components/layout/Conductor.vue b/src/ui/components/layout/Conductor.vue deleted file mode 100644 index 0f473bb2e5..0000000000 --- a/src/ui/components/layout/Conductor.vue +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - diff --git a/src/ui/components/layout/Layout.vue b/src/ui/components/layout/Layout.vue index 8baa552214..6c235cdfef 100644 --- a/src/ui/components/layout/Layout.vue +++ b/src/ui/components/layout/Layout.vue @@ -34,9 +34,8 @@ - - +