[Time Conductor] Remove previous time conductor. Fixes #1234

This commit is contained in:
Henry 2016-11-28 16:46:21 -08:00
parent bf006b45e4
commit e121c0f8ac
53 changed files with 11 additions and 1451 deletions

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
define(['../../../platform/features/conductor-v2/conductor/src/timeSystems/LocalClock'], function (LocalClock) {
define(['../../../platform/features/conductor/core/src/timeSystems/LocalClock'], function (LocalClock) {
/**
* @implements TickSource
* @constructor

View File

@ -21,8 +21,8 @@
*****************************************************************************/
define([
'../../../platform/features/conductor-v2/conductor/src/timeSystems/TimeSystem',
'../../../platform/features/conductor-v2/conductor/src/timeSystems/LocalClock',
'../../../platform/features/conductor/core/src/timeSystems/TimeSystem',
'../../../platform/features/conductor/core/src/timeSystems/LocalClock',
'./LADTickSource'
], function (TimeSystem, LocalClock, LADTickSource) {
var THIRTY_MINUTES = 30 * 60 * 1000,

View File

@ -1,9 +0,0 @@
Provides the time conductor, a control which appears at the
bottom of the screen allowing telemetry start and end times
to be modified.
Note that the term "time controller" is generally preferred
outside of the code base (e.g. in UI documents, issues, etc.);
the term "time conductor" is being used in code to avoid
confusion with "controllers" in the Model-View-Controller
sense.

View File

@ -1,97 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, 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([
"./src/ConductorRepresenter",
"./src/ConductorTelemetryDecorator",
"./src/ConductorService",
"text!./res/templates/time-conductor.html",
'legacyRegistry'
], function (
ConductorRepresenter,
ConductorTelemetryDecorator,
ConductorService,
timeConductorTemplate,
legacyRegistry
) {
legacyRegistry.register("platform/features/conductor", {
"extensions": {
"representers": [
{
"implementation": ConductorRepresenter,
"depends": [
"throttle",
"conductorService",
"$compile",
"views[]"
]
}
],
"stylesheets": [
{
"stylesheetUrl": "css/time-conductor.css"
}
],
"components": [
{
"type": "decorator",
"provides": "telemetryService",
"implementation": ConductorTelemetryDecorator,
"depends": [
"conductorService"
]
}
],
"services": [
{
"key": "conductorService",
"implementation": ConductorService,
"depends": [
"now",
"TIME_CONDUCTOR_DOMAINS"
]
}
],
"templates": [
{
"key": "time-conductor",
"template": timeConductorTemplate
}
],
"constants": [
{
"key": "TIME_CONDUCTOR_DOMAINS",
"value": [
{
"key": "time",
"name": "UTC",
"format": "utc"
}
],
"priority": "fallback",
"comment": "Placeholder; to be replaced by inspection of available domains."
}
]
}
});
});

View File

@ -30,7 +30,7 @@ define([
legacyRegistry
) {
legacyRegistry.register("platform/features/conductor-v2/compatibility", {
legacyRegistry.register("platform/features/conductor/compatibility", {
"extensions": {
"representers": [
{

View File

@ -48,7 +48,7 @@ define([
legacyRegistry
) {
legacyRegistry.register("platform/features/conductor-v2/conductor", {
legacyRegistry.register("platform/features/conductor/core", {
"extensions": {
"services": [
{

View File

@ -1,300 +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.
*****************************************************************************/
@import "bourbon";
@import "../../../../commonUI/general/res/sass/constants";
@import "../../../../commonUI/general/res/sass/mixins";
@import "../../../../commonUI/general/res/sass/mobile/constants";
@import "../../../../commonUI/general/res/sass/mobile/mixins";
@import "../../../../commonUI/themes/espresso/res/sass/constants";
@import "../../../../commonUI/themes/espresso/res/sass/mixins";
$ueTimeConductorH: (33px, 18px, 20px);
@mixin toiLineHovEffects() {
&:before,
&:after {
background-color: $timeControllerToiLineColorHov;
}
}
.l-time-controller {
$minW: 500px;
$knobHOffset: 0px;
$knobM: ($sliderKnobW + $knobHOffset) * -1;
$rangeValPad: $interiorMargin;
$rangeValOffset: $sliderKnobW + $interiorMargin;
$timeRangeSliderLROffset: 150px + ($sliderKnobW * 2);
$r1H: nth($ueTimeConductorH,1);
$r2H: nth($ueTimeConductorH,2);
$r3H: nth($ueTimeConductorH,3);
min-width: $minW;
font-size: 0.8rem;
.l-time-range-inputs-holder,
.l-time-range-slider-holder,
.l-time-range-ticks-holder
{
box-sizing: border-box;
position: relative;
&:not(:first-child) {
margin-top: $interiorMargin;
}
}
.l-time-range-slider,
.l-time-range-ticks {
@include absPosDefault(0, visible);
left: $timeRangeSliderLROffset; right: $timeRangeSliderLROffset;
}
.l-time-range-inputs-holder {
border-top: 1px solid $colorInteriorBorder;
padding-top: $interiorMargin;
&.l-flex-row,
.l-flex-row {
@include align-items(center);
.flex-elem {
height: auto;
line-height: normal;
}
}
.type-icon {
font-size: 120%;
vertical-align: middle;
}
.l-time-range-input-w,
.l-time-range-inputs-elem {
margin-right: $interiorMargin;
.lbl {
color: $colorPlotLabelFg;
}
.ui-symbol.icon {
font-size: 11px;
}
}
.l-time-range-input-w {
// Wraps a datetime text input field
position: relative;
input[type="text"] {
width: 200px;
&.picker-icon {
padding-right: 20px;
}
}
.icon-calendar {
position: absolute;
right: 5px;
top: 5px;
}
}
}
.l-time-range-slider-holder {
height: $r2H;
.range-holder {
box-shadow: none;
background: none;
border: none;
.range {
.toi-line {
$myC: $timeControllerToiLineColor;
$myW: 8px;
@include transform(translateX(50%));
position: absolute;
top: 0; right: 0; bottom: 0px; left: auto;
width: $myW;
height: auto;
z-index: 2;
&:before {
// Vert line
background-color: $myC;
position: absolute;
content: "";
top: 0; right: auto; bottom: -10px; left: floor($myW/2) - 1;
width: 1px;
}
}
&:hover .toi-line {
@include toiLineHovEffects;
}
}
}
&:not(:active) {
.knob,
.range {
@include transition-property(left, right);
@include transition-duration(500ms);
@include transition-timing-function(ease-in-out);
}
}
}
.l-time-range-ticks-holder {
height: $r3H;
.l-time-range-ticks {
border-top: 1px solid $colorTick;
.tick {
background-color: $colorTick;
border:none;
height: 5px;
width: 1px;
margin-left: -1px;
position: absolute;
&:first-child {
margin-left: 0;
}
.l-time-range-tick-label {
@include transform(translateX(-50%));
color: $colorPlotLabelFg;
display: inline-block;
font-size: 0.7rem;
position: absolute;
top: 5px;
white-space: nowrap;
z-index: 2;
}
}
}
}
.knob {
z-index: 2;
&:before {
$mTB: 2px;
$grippyW: 3px;
$mLR: ($sliderKnobW - $grippyW)/2;
@include bgStripes($c: pullForward($sliderColorKnob, 20%), $a: 1, $bgsize: 4px, $angle: 0deg);
content: '';
display: block;
position: absolute;
top: $mTB; right: $mLR; bottom: $mTB; left: $mLR;
}
.range-value {
@include trans-prop-nice-fade(.25s);
font-size: 0.7rem;
position: absolute;
height: $r2H;
line-height: $r2H;
white-space: nowrap;
z-index: 1;
}
&:hover {
.range-value {
color: $sliderColorKnobHov;
}
}
&.knob-l {
margin-left: $knobM;
.range-value {
text-align: right;
right: $rangeValOffset;
}
}
&.knob-r {
margin-right: $knobM;
.range-value {
left: $rangeValOffset;
}
&:hover + .range-holder .range .toi-line {
@include toiLineHovEffects;
}
}
}
.l-time-domain-selector {
position: absolute;
right: 0px;
top: $interiorMargin;
}
}
.s-time-range-val {
border-radius: $controlCr;
background-color: $colorInputBg;
padding: 1px 1px 0 $interiorMargin;
}
/******************************************************************** MOBILE */
@include phoneandtablet {
.l-time-controller {
min-width: 0;
.l-time-range-slider-holder,
.l-time-range-ticks-holder {
display: none;
}
}
}
@include phone {
.l-time-controller {
.l-time-range-inputs-holder {
&.l-flex-row,
.l-flex-row {
@include align-items(flex-start);
}
.l-time-range-inputs-elem {
&.type-icon {
margin-top: 3px;
}
}
.t-inputs-w,
.l-time-range-inputs-elem {
@include flex-direction(column);
.l-time-range-input-w:not(:first-child) {
&:not(:first-child) {
margin-top: $interiorMargin;
}
margin-right: 0;
}
.l-time-range-inputs-elem {
&.lbl { display: none; }
}
}
}
}
}
@include phonePortrait {
.l-time-controller {
.l-time-range-inputs-holder {
.t-inputs-w,
.l-time-range-inputs-elem {
@include flex(1 1 auto);
padding-top: 25px; // Make room for the ever lovin' Time Domain Selector
.flex-elem {
@include flex(1 1 auto);
width: 100%;
}
input[type="text"] {
width: 100%;
}
}
}
}
.l-time-domain-selector {
right: auto;
left: 20px;
}
}

View File

@ -1,11 +0,0 @@
<mct-include key="'time-controller'"
parameters='parameters'
ng-model='ngModel.conductor'>
</mct-include>
<mct-control key="'select'"
ng-model='ngModel'
field="'domain'"
options="ngModel.options"
class="l-time-domain-selector"
>
</mct-control>

View File

@ -1,198 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, 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 () {
var TEMPLATE = [
"<mct-include key=\"'time-conductor'\" ",
"ng-model='ngModel' ",
"parameters='parameters' ",
"class='holder flex-elem flex-fixed l-time-controller'>",
"</mct-include>"
].join(''),
THROTTLE_MS = 200,
GLOBAL_SHOWING = false;
/**
* The ConductorRepresenter attaches the universal time conductor
* to views.
*
* @implements {Representer}
* @constructor
* @memberof platform/features/conductor
* @param {Function} throttle a function used to reduce the frequency
* of function invocations
* @param {platform/features/conductor.ConductorService} conductorService
* service which provides the active time conductor
* @param $compile Angular's $compile
* @param {ViewDefinition[]} views all defined views
* @param {Scope} the scope of the representation
* @param element the jqLite-wrapped representation element
*/
function ConductorRepresenter(
throttle,
conductorService,
$compile,
views,
scope,
element
) {
this.throttle = throttle;
this.scope = scope;
this.conductorService = conductorService;
this.element = element;
this.views = views;
this.$compile = $compile;
}
// Update the time conductor from the scope
ConductorRepresenter.prototype.wireScope = function () {
var conductor = this.conductorService.getConductor(),
conductorScope = this.conductorScope(),
repScope = this.scope,
lastObservedBounds,
broadcastBounds;
// Combine start/end times into a single object
function bounds() {
return {
start: conductor.displayStart(),
end: conductor.displayEnd(),
domain: conductor.domain().key
};
}
function boundsAreStable(newlyObservedBounds) {
return !lastObservedBounds ||
(lastObservedBounds.start === newlyObservedBounds.start &&
lastObservedBounds.end === newlyObservedBounds.end);
}
function updateConductorInner() {
var innerBounds = conductorScope.ngModel.conductor.inner;
conductor.displayStart(innerBounds.start);
conductor.displayEnd(innerBounds.end);
lastObservedBounds = lastObservedBounds || bounds();
broadcastBounds();
}
function updateDomain(value) {
var newDomain = conductor.domain(value);
conductorScope.parameters.format = newDomain.format;
broadcastBounds();
}
// telemetry domain metadata -> option for a select control
function makeOption(domainOption) {
return {
name: domainOption.name,
value: domainOption.key
};
}
broadcastBounds = this.throttle(function () {
var newlyObservedBounds = bounds();
if (boundsAreStable(newlyObservedBounds)) {
repScope.$broadcast('telemetry:display:bounds', bounds());
lastObservedBounds = undefined;
} else {
lastObservedBounds = newlyObservedBounds;
broadcastBounds();
}
}, THROTTLE_MS);
conductorScope.ngModel = {};
conductorScope.ngModel.conductor =
{ outer: bounds(), inner: bounds() };
conductorScope.ngModel.options =
conductor.domainOptions().map(makeOption);
conductorScope.ngModel.domain = conductor.domain().key;
conductorScope.parameters = {};
conductorScope
.$watch('ngModel.conductor.inner.start', updateConductorInner);
conductorScope
.$watch('ngModel.conductor.inner.end', updateConductorInner);
conductorScope
.$watch('ngModel.domain', updateDomain);
};
ConductorRepresenter.prototype.conductorScope = function (s) {
return (this.cScope = arguments.length > 0 ? s : this.cScope);
};
// Handle a specific representation of a specific domain object
ConductorRepresenter.prototype.represent = function represent(representation) {
this.destroy();
if (this.views.indexOf(representation) !== -1 && !GLOBAL_SHOWING) {
// Track original states
this.originalHeight = this.element.css('height');
this.hadAbs = this.element.hasClass('abs');
// Create a new scope for the conductor
this.conductorScope(this.scope.$new());
this.wireScope();
this.conductorElement =
this.$compile(TEMPLATE)(this.conductorScope());
this.element.parent().parent().after(this.conductorElement[0]);
this.element.parent().parent().addClass('l-controls-visible l-time-controller-visible');
GLOBAL_SHOWING = true;
}
};
// Respond to the destruction of the current representation.
ConductorRepresenter.prototype.destroy = function destroy() {
// We may not have decided to show in the first place,
// so circumvent any unnecessary cleanup
if (!this.conductorElement) {
return;
}
// Restore the original size of the mct-representation
if (!this.hadAbs) {
this.element.removeClass('abs');
}
this.element.css('height', this.originalHeight);
// ...and remove the conductor
if (this.conductorElement) {
this.conductorElement.remove();
this.conductorElement = undefined;
}
// Finally, destroy its scope
if (this.conductorScope()) {
this.conductorScope().$destroy();
this.conductorScope(undefined);
}
GLOBAL_SHOWING = false;
};
return ConductorRepresenter;
}
);

View File

@ -1,62 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, 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(
['./TimeConductor'],
function (TimeConductor) {
var ONE_DAY_IN_MS = 1000 * 60 * 60 * 24,
SIX_HOURS_IN_MS = ONE_DAY_IN_MS / 4;
/**
* Provides a single global instance of the time conductor, which
* controls both query ranges and displayed ranges for telemetry
* data.
*
* @constructor
* @memberof platform/features/conductor
* @param {Function} now a function which returns the current time
* as a UNIX timestamp, in milliseconds
*/
function ConductorService(now, domains) {
var initialEnd =
Math.ceil(now() / SIX_HOURS_IN_MS) * SIX_HOURS_IN_MS;
this.conductor = new TimeConductor(
initialEnd - ONE_DAY_IN_MS,
initialEnd,
domains
);
}
/**
* Get the global instance of the time conductor.
* @returns {platform/features/conductor.TimeConductor} the
* time conductor
*/
ConductorService.prototype.getConductor = function () {
return this.conductor;
};
return ConductorService;
}
);

View File

@ -1,71 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, 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 () {
/**
* Decorates the `telemetryService` such that requests are
* mediated by the time conductor.
*
* @constructor
* @memberof platform/features/conductor
* @implements {TelemetryService}
* @param {platform/features/conductor.ConductorService} conductorServe
* the service which exposes the global time conductor
* @param {TelemetryService} telemetryService the decorated service
*/
function ConductorTelemetryDecorator(conductorService, telemetryService) {
this.conductorService = conductorService;
this.telemetryService = telemetryService;
}
ConductorTelemetryDecorator.prototype.amendRequests = function (requests) {
var conductor = this.conductorService.getConductor(),
start = conductor.displayStart(),
end = conductor.displayEnd(),
domain = conductor.domain();
function amendRequest(request) {
request = request || {};
request.start = start;
request.end = end;
request.domain = domain.key;
return request;
}
return (requests || []).map(amendRequest);
};
ConductorTelemetryDecorator.prototype.requestTelemetry = function (requests) {
return this.telemetryService
.requestTelemetry(this.amendRequests(requests));
};
ConductorTelemetryDecorator.prototype.subscribe = function (callback, requests) {
return this.telemetryService
.subscribe(callback, this.amendRequests(requests));
};
return ConductorTelemetryDecorator;
}
);

View File

@ -1,103 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, 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.
*****************************************************************************/
/**
* The time conductor bundle adds a global control to the bottom of the
* outermost viewing area. This controls both the range for time-based
* queries and for time-based displays.
*
* @namespace platform/features/conductor
*/
define(
function () {
/**
* Tracks the current state of the time conductor.
*
* @memberof platform/features/conductor
* @constructor
* @param {number} start the initial start time
* @param {number} end the initial end time
*/
function TimeConductor(start, end, domains) {
this.range = { start: start, end: end };
this.domains = domains;
this.activeDomain = domains[0];
}
/**
* Get or set (if called with an argument) the start time for displays.
* @param {number} [value] the start time to set
* @returns {number} the start time
*/
TimeConductor.prototype.displayStart = function (value) {
if (arguments.length > 0) {
this.range.start = value;
}
return this.range.start;
};
/**
* Get or set (if called with an argument) the end time for displays.
* @param {number} [value] the end time to set
* @returns {number} the end time
*/
TimeConductor.prototype.displayEnd = function (value) {
if (arguments.length > 0) {
this.range.end = value;
}
return this.range.end;
};
/**
* Get available domain options which can be used to bound time
* selection.
* @returns {TelemetryDomainMetadata[]} available domains
*/
TimeConductor.prototype.domainOptions = function () {
return this.domains;
};
/**
* Get or set (if called with an argument) the active domain.
* @param {string} [key] the key identifying the domain choice
* @returns {TelemetryDomainMetadata} the active telemetry domain
*/
TimeConductor.prototype.domain = function (key) {
var i;
if (arguments.length > 0) {
for (i = 0; i < this.domains.length; i += 1) {
if (this.domains[i].key === key) {
return (this.activeDomain = this.domains[i]);
}
}
throw new Error("Unknown domain " + key);
}
return this.activeDomain;
};
return TimeConductor;
}
);

View File

@ -1,259 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, 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(
["../src/ConductorRepresenter", "./TestTimeConductor"],
function (ConductorRepresenter, TestTimeConductor) {
var SCOPE_METHODS = [
'$on',
'$watch',
'$broadcast',
'$emit',
'$new',
'$destroy'
],
ELEMENT_METHODS = [
'hasClass',
'addClass',
'removeClass',
'css',
'after',
'remove',
'parent'
];
describe("ConductorRepresenter", function () {
var mockThrottle,
mockConductorService,
mockCompile,
testViews,
mockScope,
mockElement,
mockConductor,
mockCompiledTemplate,
mockNewScope,
mockNewElement,
representer;
function fireWatch(scope, watch, value) {
scope.$watch.calls.forEach(function (call) {
if (call.args[0] === watch) {
call.args[1](value);
}
});
}
beforeEach(function () {
mockThrottle = jasmine.createSpy('throttle');
mockConductorService = jasmine.createSpyObj(
'conductorService',
['getConductor']
);
mockCompile = jasmine.createSpy('$compile');
testViews = [{ someKey: "some value" }];
mockScope = jasmine.createSpyObj('scope', SCOPE_METHODS);
mockElement = jasmine.createSpyObj('element', ELEMENT_METHODS);
mockElement.parent.andReturn(mockElement);
mockConductor = new TestTimeConductor();
mockCompiledTemplate = jasmine.createSpy('template');
mockNewScope = jasmine.createSpyObj('newScope', SCOPE_METHODS);
mockNewElement = jasmine.createSpyObj('newElement', ELEMENT_METHODS);
mockNewElement[0] = mockNewElement;
mockConductorService.getConductor.andReturn(mockConductor);
mockCompile.andReturn(mockCompiledTemplate);
mockCompiledTemplate.andReturn(mockNewElement);
mockScope.$new.andReturn(mockNewScope);
mockThrottle.andCallFake(function (fn) {
return fn;
});
representer = new ConductorRepresenter(
mockThrottle,
mockConductorService,
mockCompile,
testViews,
mockScope,
mockElement
);
});
afterEach(function () {
representer.destroy();
});
it("adds a conductor to views", function () {
representer.represent(testViews[0], {});
expect(mockElement.after).toHaveBeenCalledWith(mockNewElement);
});
it("adds nothing to non-view representations", function () {
representer.represent({ someKey: "something else" }, {});
expect(mockElement.after).not.toHaveBeenCalled();
});
it("removes the conductor when destroyed", function () {
representer.represent(testViews[0], {});
expect(mockNewElement.remove).not.toHaveBeenCalled();
representer.destroy();
expect(mockNewElement.remove).toHaveBeenCalled();
});
it("destroys any new scope created", function () {
representer.represent(testViews[0], {});
representer.destroy();
expect(mockNewScope.$destroy.calls.length)
.toEqual(mockScope.$new.calls.length);
});
it("exposes conductor state in scope", function () {
mockConductor.displayStart.andReturn(1977);
mockConductor.displayEnd.andReturn(1984);
mockConductor.domain.andReturn({ key: 'd' });
representer.represent(testViews[0], {});
expect(mockNewScope.ngModel.conductor).toEqual({
inner: { start: 1977, end: 1984, domain: 'd' },
outer: { start: 1977, end: 1984, domain: 'd' }
});
});
it("updates conductor state from scope", function () {
var testState = {
inner: { start: 42, end: 1984 },
outer: { start: -1977, end: 12321 }
};
representer.represent(testViews[0], {});
mockNewScope.ngModel.conductor = testState;
fireWatch(
mockNewScope,
'ngModel.conductor.inner.start',
testState.inner.start
);
expect(mockConductor.displayStart).toHaveBeenCalledWith(42);
fireWatch(
mockNewScope,
'ngModel.conductor.inner.end',
testState.inner.end
);
expect(mockConductor.displayEnd).toHaveBeenCalledWith(1984);
});
describe("when bounds are changing", function () {
var startWatch = "ngModel.conductor.inner.start",
endWatch = "ngModel.conductor.inner.end",
mockThrottledFn = jasmine.createSpy('throttledFn'),
testBounds;
function fireThrottledFn() {
mockThrottle.mostRecentCall.args[0]();
}
beforeEach(function () {
mockThrottle.andReturn(mockThrottledFn);
representer.represent(testViews[0], {});
testBounds = { start: 0, end: 1000 };
mockNewScope.ngModel.conductor.inner = testBounds;
mockConductor.displayStart.andCallFake(function () {
return testBounds.start;
});
mockConductor.displayEnd.andCallFake(function () {
return testBounds.end;
});
});
it("does not broadcast while bounds are changing", function () {
expect(mockScope.$broadcast).not.toHaveBeenCalled();
testBounds.start = 100;
fireWatch(mockNewScope, startWatch, testBounds.start);
testBounds.end = 500;
fireWatch(mockNewScope, endWatch, testBounds.end);
fireThrottledFn();
testBounds.start = 200;
fireWatch(mockNewScope, startWatch, testBounds.start);
testBounds.end = 400;
fireWatch(mockNewScope, endWatch, testBounds.end);
fireThrottledFn();
expect(mockScope.$broadcast).not.toHaveBeenCalled();
});
it("does broadcast when bounds have stabilized", function () {
expect(mockScope.$broadcast).not.toHaveBeenCalled();
testBounds.start = 100;
fireWatch(mockNewScope, startWatch, testBounds.start);
testBounds.end = 500;
fireWatch(mockNewScope, endWatch, testBounds.end);
fireThrottledFn();
fireWatch(mockNewScope, startWatch, testBounds.start);
fireWatch(mockNewScope, endWatch, testBounds.end);
fireThrottledFn();
expect(mockScope.$broadcast).toHaveBeenCalled();
});
});
it("exposes domain selection in scope", function () {
representer.represent(testViews[0], null);
expect(mockNewScope.ngModel.domain)
.toEqual(mockConductor.domain().key);
});
it("exposes domain options in scope", function () {
representer.represent(testViews[0], null);
mockConductor.domainOptions().forEach(function (option, i) {
expect(mockNewScope.ngModel.options[i].value)
.toEqual(option.key);
expect(mockNewScope.ngModel.options[i].name)
.toEqual(option.name);
});
});
it("updates domain selection from scope", function () {
var choice;
representer.represent(testViews[0], null);
// Choose a domain that isn't currently selected
mockNewScope.ngModel.options.forEach(function (option) {
if (option.value !== mockNewScope.ngModel.domain) {
choice = option.value;
}
});
expect(mockConductor.domain)
.not.toHaveBeenCalledWith(choice);
mockNewScope.ngModel.domain = choice;
fireWatch(mockNewScope, "ngModel.domain", choice);
expect(mockConductor.domain)
.toHaveBeenCalledWith(choice);
});
});
}
);

View File

@ -1,56 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, 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(
["../src/ConductorService"],
function (ConductorService) {
var TEST_NOW = 1020304050;
describe("ConductorService", function () {
var mockNow,
conductorService;
beforeEach(function () {
mockNow = jasmine.createSpy('now');
mockNow.andReturn(TEST_NOW);
conductorService = new ConductorService(mockNow, [
{ key: "d1", name: "Domain #1" },
{ key: "d2", name: "Domain #2" }
]);
});
it("initializes a time conductor around the current time", function () {
var conductor = conductorService.getConductor();
expect(conductor.displayStart() <= TEST_NOW).toBeTruthy();
expect(conductor.displayEnd() >= TEST_NOW).toBeTruthy();
expect(conductor.displayEnd() > conductor.displayStart())
.toBeTruthy();
});
it("provides a single shared time conductor instance", function () {
expect(conductorService.getConductor())
.toBe(conductorService.getConductor());
});
});
}
);

View File

@ -1,148 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, 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(
["../src/ConductorTelemetryDecorator", "./TestTimeConductor"],
function (ConductorTelemetryDecorator, TestTimeConductor) {
describe("ConductorTelemetryDecorator", function () {
var mockTelemetryService,
mockConductorService,
mockConductor,
mockPromise,
mockSeries,
decorator;
beforeEach(function () {
mockTelemetryService = jasmine.createSpyObj(
'telemetryService',
['requestTelemetry', 'subscribe']
);
mockConductorService = jasmine.createSpyObj(
'conductorService',
['getConductor']
);
mockConductor = new TestTimeConductor();
mockPromise = jasmine.createSpyObj(
'promise',
['then']
);
mockSeries = jasmine.createSpyObj(
'series',
['getPointCount', 'getDomainValue', 'getRangeValue']
);
mockTelemetryService.requestTelemetry.andReturn(mockPromise);
mockConductorService.getConductor.andReturn(mockConductor);
// Prepare test series; make sure it has a broad range of
// domain values, with at least some in the query-able range
mockSeries.getPointCount.andReturn(1000);
mockSeries.getDomainValue.andCallFake(function (i) {
var j = i - 500;
return j * j * j;
});
mockConductor.displayStart.andReturn(42);
mockConductor.displayEnd.andReturn(1977);
mockConductor.domain.andReturn({ key: "testDomain" });
decorator = new ConductorTelemetryDecorator(
mockConductorService,
mockTelemetryService
);
});
describe("decorates historical requests", function () {
var request;
beforeEach(function () {
decorator.requestTelemetry([{ someKey: "some value" }]);
request = mockTelemetryService.requestTelemetry
.mostRecentCall.args[0][0];
});
it("with start times", function () {
expect(request.start).toEqual(mockConductor.displayStart());
});
it("with end times", function () {
expect(request.end).toEqual(mockConductor.displayEnd());
});
it("with domain selection", function () {
expect(request.domain).toEqual(mockConductor.domain().key);
});
});
describe("decorates subscription requests", function () {
var request;
beforeEach(function () {
var mockCallback = jasmine.createSpy('callback');
decorator.subscribe(mockCallback, [{ someKey: "some value" }]);
request = mockTelemetryService.subscribe
.mostRecentCall.args[1][0];
});
it("with start times", function () {
expect(request.start).toEqual(mockConductor.displayStart());
});
it("with end times", function () {
expect(request.end).toEqual(mockConductor.displayEnd());
});
it("with domain selection", function () {
expect(request.domain).toEqual(mockConductor.domain().key);
});
});
it("adds display start/end times & domain selection to historical requests", function () {
decorator.requestTelemetry([{ someKey: "some value" }]);
expect(mockTelemetryService.requestTelemetry)
.toHaveBeenCalledWith([{
someKey: "some value",
start: mockConductor.displayStart(),
end: mockConductor.displayEnd(),
domain: jasmine.any(String)
}]);
});
it("adds display start/end times & domain selection to subscription requests", function () {
var mockCallback = jasmine.createSpy('callback');
decorator.subscribe(mockCallback, [{ someKey: "some value" }]);
expect(mockTelemetryService.subscribe)
.toHaveBeenCalledWith(jasmine.any(Function), [{
someKey: "some value",
start: mockConductor.displayStart(),
end: mockConductor.displayEnd(),
domain: jasmine.any(String)
}]);
});
});
}
);

View File

@ -1,49 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, 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.
*****************************************************************************/
/*global spyOn*/
define(
["../src/TimeConductor"],
function (TimeConductor) {
function TestTimeConductor() {
var self = this;
TimeConductor.apply(this, [
402514200000,
444546000000,
[
{ key: "domain0", name: "Domain #1" },
{ key: "domain1", name: "Domain #2" }
]
]);
Object.keys(TimeConductor.prototype).forEach(function (method) {
spyOn(self, method).andCallThrough();
});
}
TestTimeConductor.prototype = TimeConductor.prototype;
return TestTimeConductor;
}
);

View File

@ -1,76 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, 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(
["../src/TimeConductor"],
function (TimeConductor) {
describe("TimeConductor", function () {
var testStart,
testEnd,
testDomains,
conductor;
beforeEach(function () {
testStart = 42;
testEnd = 12321;
testDomains = [
{ key: "d1", name: "Domain #1" },
{ key: "d2", name: "Domain #2" }
];
conductor = new TimeConductor(testStart, testEnd, testDomains);
});
it("provides accessors for query/display start/end times", function () {
expect(conductor.displayStart()).toEqual(testStart);
expect(conductor.displayEnd()).toEqual(testEnd);
});
it("provides setters for query/display start/end times", function () {
expect(conductor.displayStart(3)).toEqual(3);
expect(conductor.displayEnd(4)).toEqual(4);
expect(conductor.displayStart()).toEqual(3);
expect(conductor.displayEnd()).toEqual(4);
});
it("exposes domain options", function () {
expect(conductor.domainOptions()).toEqual(testDomains);
});
it("exposes the current domain choice", function () {
expect(conductor.domain()).toEqual(testDomains[0]);
});
it("allows the domain choice to be changed", function () {
conductor.domain(testDomains[1].key);
expect(conductor.domain()).toEqual(testDomains[1]);
});
it("throws an error on attempts to set an invalid domain", function () {
expect(function () {
conductor.domain("invalid-domain");
}).toThrow();
});
});
}
);

View File

@ -27,7 +27,7 @@ define([
UTCTimeSystem,
legacyRegistry
) {
legacyRegistry.register("platform/features/conductor-v2/utcTimeSystem", {
legacyRegistry.register("platform/features/conductor/utcTimeSystem", {
"extensions": {
"timeSystems": [
{

View File

@ -21,8 +21,8 @@
*****************************************************************************/
define([
'../../conductor/src/timeSystems/TimeSystem',
'../../conductor/src/timeSystems/LocalClock'
'../../core/src/timeSystems/TimeSystem',
'../../core/src/timeSystems/LocalClock'
], function (TimeSystem, LocalClock) {
var FIFTEEN_MINUTES = 15 * 60 * 1000,
DEFAULT_PERIOD = 1000;

View File

@ -65,11 +65,10 @@ define([
'../platform/execution/bundle',
'../platform/exporters/bundle',
'../platform/features/clock/bundle',
'../platform/features/conductor/bundle',
'../platform/features/fixed/bundle',
'../platform/features/conductor-v2/conductor/bundle',
'../platform/features/conductor-v2/compatibility/bundle',
'../platform/features/conductor-v2/utcTimeSystem/bundle',
'../platform/features/conductor/core/bundle',
'../platform/features/conductor/compatibility/bundle',
'../platform/features/conductor/utcTimeSystem/bundle',
'../platform/features/imagery/bundle',
'../platform/features/layout/bundle',
'../platform/features/my-items/bundle',