Merge branch 'master' of https://github.com/nasa/openmctweb into open18

This commit is contained in:
Sarah Hale 2015-06-25 14:51:18 -07:00
commit bf8b0bae03
28 changed files with 1374 additions and 153 deletions

View File

@ -11,6 +11,7 @@
"platform/containment", "platform/containment",
"platform/execution", "platform/execution",
"platform/telemetry", "platform/telemetry",
"platform/features/imagery",
"platform/features/layout", "platform/features/layout",
"platform/features/pages", "platform/features/pages",
"platform/features/plot", "platform/features/plot",
@ -20,6 +21,7 @@
"platform/persistence/queue", "platform/persistence/queue",
"platform/policy", "platform/policy",
"example/imagery",
"example/persistence", "example/persistence",
"example/eventGenerator", "example/eventGenerator",
"example/generator" "example/generator"

View File

@ -0,0 +1,42 @@
{
"name": "Imagery",
"description": "Example of a component that produces image telemetry.",
"extensions": {
"components": [
{
"implementation": "ImageTelemetryProvider.js",
"type": "provider",
"provides": "telemetryService",
"depends": [ "$q", "$timeout" ]
}
],
"types": [
{
"key": "imagery",
"name": "Example Imagery",
"glyph": "T",
"features": "creation",
"model": {
"telemetry": {}
},
"telemetry": {
"source": "imagery",
"domains": [
{
"name": "Time",
"key": "time",
"format": "timestamp"
}
],
"ranges": [
{
"name": "Image",
"key": "url",
"format": "imageUrl"
}
]
}
}
]
}
}

View File

@ -0,0 +1,66 @@
/*****************************************************************************
* 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.
*****************************************************************************/
/*global define,Promise*/
/**
* Module defining ImageTelemetry. Created by vwoeltje on 06/22/15.
*/
define(
[],
function () {
"use strict";
var firstObservedTime = Date.now(),
images = [
"http://www.nasa.gov/393811main_Palomar_ao_bouchez_10s_after_impact_4x3_946-710.png",
"http://www.nasa.gov/393821main_Palomar_ao_bouchez_15s_after_impact_4x3_946-710.png",
"http://www.nasa.gov/images/content/393801main_CfhtVeillet2_4x3_516-387.jpg",
"http://www.nasa.gov/images/content/392790main_1024_768_GeminiNorth_NightBeforeImpact_946-710.jpg"
].map(function (url, index) {
return {
timestamp: firstObservedTime + 1000 * index,
url: url
};
});
/**
*
* @constructor
*/
function ImageTelemetry() {
return {
getPointCount: function () {
return Math.floor((Date.now() - firstObservedTime) / 1000);
},
getDomainValue: function (i, domain) {
return images[i % images.length].timestamp;
},
getRangeValue: function (i, range) {
return images[i % images.length].url;
}
};
}
return ImageTelemetry;
}
);

View File

@ -0,0 +1,115 @@
/*****************************************************************************
* 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.
*****************************************************************************/
/*global define,Promise*/
/**
* Module defining ImageTelemetryProvider. Created by vwoeltje on 06/22/15.
*/
define(
["./ImageTelemetry"],
function (ImageTelemetry) {
"use strict";
/**
*
* @constructor
*/
function ImageTelemetryProvider($q, $timeout) {
var subscriptions = [];
//
function matchesSource(request) {
return request.source === "imagery";
}
// Used internally; this will be repacked by doPackage
function generateData(request) {
return {
key: request.key,
telemetry: new ImageTelemetry()
};
}
//
function doPackage(results) {
var packaged = {};
results.forEach(function (result) {
packaged[result.key] = result.telemetry;
});
// Format as expected (sources -> keys -> telemetry)
return { imagery: packaged };
}
function requestTelemetry(requests) {
return $timeout(function () {
return doPackage(requests.filter(matchesSource).map(generateData));
}, 0);
}
function handleSubscriptions() {
subscriptions.forEach(function (subscription) {
var requests = subscription.requests;
subscription.callback(doPackage(
requests.filter(matchesSource).map(generateData)
));
});
}
function startGenerating() {
$timeout(function () {
handleSubscriptions();
if (subscriptions.length > 0) {
startGenerating();
}
}, 1000);
}
function subscribe(callback, requests) {
var subscription = {
callback: callback,
requests: requests
};
function unsubscribe() {
subscriptions = subscriptions.filter(function (s) {
return s !== subscription;
});
}
subscriptions.push(subscription);
if (subscriptions.length === 1) {
startGenerating();
}
return unsubscribe;
}
return {
requestTelemetry: requestTelemetry,
subscribe: subscribe
};
}
return ImageTelemetryProvider;
}
);

View File

@ -68,6 +68,8 @@ define(
* @returns {DomainObject} the domain object in an editable form * @returns {DomainObject} the domain object in an editable form
*/ */
getEditableObject: function (domainObject) { getEditableObject: function (domainObject) {
var type = domainObject.getCapability('type');
// Track the top-level domain object; this will have // Track the top-level domain object; this will have
// some special behavior for its context capability. // some special behavior for its context capability.
root = root || domainObject; root = root || domainObject;
@ -77,6 +79,11 @@ define(
return domainObject; return domainObject;
} }
// Don't bother wrapping non-editable objects
if (!type || !type.hasFeature('creation')) {
return domainObject;
}
// Provide an editable form of the object // Provide an editable form of the object
return new EditableDomainObject( return new EditableDomainObject(
domainObject, domainObject,
@ -142,4 +149,4 @@ define(
return EditableDomainObjectCache; return EditableDomainObjectCache;
} }
); );

View File

@ -31,7 +31,7 @@ define(
mockQ, mockQ,
mockNavigationService, mockNavigationService,
mockObject, mockObject,
mockCapability, mockType,
controller; controller;
beforeEach(function () { beforeEach(function () {
@ -48,15 +48,18 @@ define(
"domainObject", "domainObject",
[ "getId", "getModel", "getCapability", "hasCapability" ] [ "getId", "getModel", "getCapability", "hasCapability" ]
); );
mockCapability = jasmine.createSpyObj( mockType = jasmine.createSpyObj(
"capability", "type",
[ "invoke" ] [ "hasFeature" ]
); );
mockNavigationService.getNavigation.andReturn(mockObject); mockNavigationService.getNavigation.andReturn(mockObject);
mockObject.getId.andReturn("test"); mockObject.getId.andReturn("test");
mockObject.getModel.andReturn({ name: "Test object" }); mockObject.getModel.andReturn({ name: "Test object" });
mockObject.getCapability.andReturn(mockCapability); mockObject.getCapability.andCallFake(function (key) {
return key === 'type' && mockType;
});
mockType.hasFeature.andReturn(true);
controller = new EditController( controller = new EditController(
mockScope, mockScope,
@ -76,7 +79,7 @@ define(
.toBeDefined(); .toBeDefined();
// Shouldn't have been the mock capability we provided // Shouldn't have been the mock capability we provided
expect(controller.navigatedObject().getCapability("editor")) expect(controller.navigatedObject().getCapability("editor"))
.not.toEqual(mockCapability); .not.toEqual(mockType);
}); });
it("detaches its navigation listener when destroyed", function () { it("detaches its navigation listener when destroyed", function () {
@ -119,4 +122,4 @@ define(
}); });
} }
); );

View File

@ -32,6 +32,7 @@ define(
completionCapability, completionCapability,
object, object,
mockQ, mockQ,
mockType,
cache; cache;
@ -40,10 +41,13 @@ define(
return { return {
getId: function () { return id; }, getId: function () { return id; },
getModel: function () { return {}; }, getModel: function () { return {}; },
getCapability: function (name) { getCapability: function (key) {
return completionCapability; return {
editor: completionCapability,
type: mockType
}[key];
}, },
hasCapability: function (name) { hasCapability: function (key) {
return false; return false;
} }
}; };
@ -62,6 +66,8 @@ define(
beforeEach(function () { beforeEach(function () {
mockQ = jasmine.createSpyObj('$q', ['when', 'all']); mockQ = jasmine.createSpyObj('$q', ['when', 'all']);
mockType = jasmine.createSpyObj('type', ['hasFeature']);
mockType.hasFeature.andReturn(true);
captured = {}; captured = {};
completionCapability = { completionCapability = {
save: function () { save: function () {
@ -152,6 +158,17 @@ define(
.toBe(wrappedObject); .toBe(wrappedObject);
}); });
it("does not wrap non-editable objects", function () {
var domainObject = new TestObject('test-id');
mockType.hasFeature.andCallFake(function (key) {
return key !== 'creation';
});
expect(cache.getEditableObject(domainObject))
.toBe(domainObject);
});
}); });
} }

View File

@ -226,20 +226,20 @@ a.disabled {
@-moz-keyframes pulse { @-moz-keyframes pulse {
0% { 0% {
opacity: 0.5; } opacity: 0.2; }
100% { 100% {
opacity: 1; } } opacity: 1; } }
@-webkit-keyframes pulse { @-webkit-keyframes pulse {
0% { 0% {
opacity: 0.5; } opacity: 0.2; }
100% { 100% {
opacity: 1; } } opacity: 1; } }
@keyframes pulse { @keyframes pulse {
0% { 0% {
opacity: 0.5; } opacity: 0.2; }
100% { 100% {
opacity: 1; } } opacity: 1; } }
/* line 59, ../sass/_effects.scss */ /* line 69, ../sass/_effects.scss */
.pulse { .pulse {
-moz-animation-name: pulse; -moz-animation-name: pulse;
-webkit-animation-name: pulse; -webkit-animation-name: pulse;
@ -657,26 +657,26 @@ mct-container {
overflow-y: auto; } overflow-y: auto; }
/***************************************************************************** /*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government * Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space * as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved. * Administration. All rights reserved.
* *
* Open MCT Web is licensed under the Apache License, Version 2.0 (the * 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. * "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0. * http://www.apache.org/licenses/LICENSE-2.0.
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations * License for the specific language governing permissions and limitations
* under the License. * under the License.
* *
* Open MCT Web includes source code licensed under additional open source * Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with * licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available * this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information. * at runtime from the About dialog for additional information.
*****************************************************************************/ *****************************************************************************/
/* line 23, ../sass/_fixed-position.scss */ /* line 23, ../sass/_fixed-position.scss */
.t-fixed-position.l-fixed-position { .t-fixed-position.l-fixed-position {
position: absolute; position: absolute;
@ -686,33 +686,33 @@ mct-container {
left: 0; left: 0;
width: auto; width: auto;
height: auto; } height: auto; }
/* line 29, ../sass/_fixed-position.scss */ /* line 33, ../sass/_fixed-position.scss */
.t-fixed-position.l-fixed-position .l-grid-holder { .t-fixed-position.l-fixed-position .l-grid-holder {
position: relative; position: relative;
height: 100%; height: 100%;
width: 100%; } width: 100%; }
/* line 32, ../sass/_fixed-position.scss */ /* line 37, ../sass/_fixed-position.scss */
.t-fixed-position.l-fixed-position .l-grid-holder .l-grid { .t-fixed-position.l-fixed-position .l-grid-holder .l-grid {
position: absolute; position: absolute;
height: 100%; height: 100%;
width: 100%; width: 100%;
pointer-events: none; pointer-events: none;
z-index: 0; } z-index: 0; }
/* line 42, ../sass/_fixed-position.scss */ /* line 48, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item { .t-fixed-position .l-fixed-position-item {
position: absolute; position: absolute;
border: 1px solid transparent; } border: 1px solid transparent; }
/* line 46, ../sass/_fixed-position.scss */ /* line 52, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item.s-selected { .t-fixed-position .l-fixed-position-item.s-selected {
-moz-box-shadow: rgba(0, 0, 0, 0.7) 0 3px 10px; -moz-box-shadow: rgba(0, 0, 0, 0.7) 0 3px 10px;
-webkit-box-shadow: rgba(0, 0, 0, 0.7) 0 3px 10px; -webkit-box-shadow: rgba(0, 0, 0, 0.7) 0 3px 10px;
box-shadow: rgba(0, 0, 0, 0.7) 0 3px 10px; box-shadow: rgba(0, 0, 0, 0.7) 0 3px 10px;
border-color: #0099cc; border-color: #0099cc;
cursor: move; } cursor: move; }
/* line 51, ../sass/_fixed-position.scss */ /* line 57, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item.s-not-selected { .t-fixed-position .l-fixed-position-item.s-not-selected {
opacity: 0.8; } opacity: 0.8; }
/* line 55, ../sass/_fixed-position.scss */ /* line 61, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item .l-fixed-position-box, .t-fixed-position .l-fixed-position-item .l-fixed-position-box,
.t-fixed-position .l-fixed-position-item .l-fixed-position-image, .t-fixed-position .l-fixed-position-item .l-fixed-position-image,
.t-fixed-position .l-fixed-position-item .l-fixed-position-text { .t-fixed-position .l-fixed-position-item .l-fixed-position-text {
@ -721,62 +721,56 @@ mct-container {
box-sizing: border-box; box-sizing: border-box;
height: 100%; height: 100%;
width: 100%; } width: 100%; }
/* line 65, ../sass/_fixed-position.scss */ /* line 72, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item .l-fixed-position-image { .t-fixed-position .l-fixed-position-item .l-fixed-position-image {
background-size: cover; background-size: cover;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center; } background-position: center; }
/* line 71, ../sass/_fixed-position.scss */ /* line 78, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item .l-fixed-position-text { .t-fixed-position .l-fixed-position-item .l-fixed-position-text {
text-shadow: rgba(0, 0, 0, 0.1) 0 1px 2px; text-shadow: rgba(0, 0, 0, 0.1) 0 1px 2px;
border: 1px solid transparent; border: 1px solid transparent;
font-size: 0.8rem; font-size: 0.8rem;
line-height: 100%; } line-height: 100%; }
/* line 77, ../sass/_fixed-position.scss */ /* line 84, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item .l-fixed-position-text.l-static-text { .t-fixed-position .l-fixed-position-item .l-fixed-position-text.l-static-text {
padding: 1px; } padding: 1px; }
/* line 82, ../sass/_fixed-position.scss */ /* line 89, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item .l-fixed-position-text.l-telemetry .l-elem { .t-fixed-position .l-fixed-position-item .l-fixed-position-text.l-telemetry .l-elem {
overflow: hidden;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: auto;
height: auto;
-moz-box-sizing: border-box; -moz-box-sizing: border-box;
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;
box-sizing: border-box; box-sizing: border-box;
padding: 2px; display: block;
width: 50%; } padding: 2px; }
/* line 88, ../sass/_fixed-position.scss */ /* line 96, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item .l-fixed-position-text.l-telemetry .l-elem.l-title { .t-fixed-position .l-fixed-position-item .l-fixed-position-text.l-telemetry .l-elem.l-title {
right: auto; float: none;
left: 1px; } overflow: hidden;
/* line 92, ../sass/_fixed-position.scss */ text-overflow: ellipsis;
white-space: nowrap;
width: auto; }
/* line 105, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item .l-fixed-position-text.l-telemetry .l-elem.l-value { .t-fixed-position .l-fixed-position-item .l-fixed-position-text.l-telemetry .l-elem.l-value {
right: 1px; -moz-border-radius: 2px;
left: auto; -webkit-border-radius: 2px;
border-radius: 2px;
float: right;
margin-left: 5px;
padding-left: 5px;
padding-right: 5px;
text-align: right; } text-align: right; }
/* line 97, ../sass/_fixed-position.scss */ /* line 116, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item .l-fixed-position-text.l-telemetry .l-elem.l-value.telem-only { .t-fixed-position .l-fixed-position-item .l-fixed-position-text.l-telemetry .l-elem.l-value.telem-only {
left: 1px; margin-left: 0;
width: auto; } width: 100%; }
/* line 102, ../sass/_fixed-position.scss */ /* line 126, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item .l-fixed-position-text.l-telemetry .l-elem.l-value .l-value-bg {
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
padding: 0 4px; }
/* line 112, ../sass/_fixed-position.scss */
.t-fixed-position .l-fixed-position-item-handle { .t-fixed-position .l-fixed-position-item-handle {
background: rgba(0, 153, 204, 0.5); background: rgba(0, 153, 204, 0.5);
cursor: crosshair; cursor: crosshair;
border: 1px solid #0099cc; border: 1px solid #0099cc;
position: absolute; } position: absolute; }
/* line 126, ../sass/_fixed-position.scss */ /* line 140, ../sass/_fixed-position.scss */
.edit-mode .t-fixed-position.l-fixed-position .l-grid-holder .l-grid.l-grid-x { .edit-mode .t-fixed-position.l-fixed-position .l-grid-holder .l-grid.l-grid-x {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuMCIgeTE9IjAuNSIgeDI9IjEuMCIgeTI9IjAuNSI+PHN0b3Agb2Zmc2V0PSIxcHgiIHN0b3AtY29sb3I9IiNmZmZmZmYiIHN0b3Atb3BhY2l0eT0iMC4wNSIvPjxzdG9wIG9mZnNldD0iMXB4IiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2dyYWQpIiAvPjwvc3ZnPiA='); background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuMCIgeTE9IjAuNSIgeDI9IjEuMCIgeTI9IjAuNSI+PHN0b3Agb2Zmc2V0PSIxcHgiIHN0b3AtY29sb3I9IiNmZmZmZmYiIHN0b3Atb3BhY2l0eT0iMC4wNSIvPjxzdG9wIG9mZnNldD0iMXB4IiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2dyYWQpIiAvPjwvc3ZnPiA=');
background-size: 100%; background-size: 100%;
@ -784,7 +778,7 @@ mct-container {
background-image: -webkit-linear-gradient(0deg, rgba(255, 255, 255, 0.05) 1px, rgba(0, 0, 0, 0) 1px, rgba(0, 0, 0, 0) 100%); background-image: -webkit-linear-gradient(0deg, rgba(255, 255, 255, 0.05) 1px, rgba(0, 0, 0, 0) 1px, rgba(0, 0, 0, 0) 100%);
background-image: linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, rgba(0, 0, 0, 0) 1px, rgba(0, 0, 0, 0) 100%); background-image: linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, rgba(0, 0, 0, 0) 1px, rgba(0, 0, 0, 0) 100%);
background-repeat: repeat-x; } background-repeat: repeat-x; }
/* line 130, ../sass/_fixed-position.scss */ /* line 144, ../sass/_fixed-position.scss */
.edit-mode .t-fixed-position.l-fixed-position .l-grid-holder .l-grid.l-grid-y { .edit-mode .t-fixed-position.l-fixed-position .l-grid-holder .l-grid.l-grid-y {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjEuMCIgeDI9IjAuNSIgeTI9IjAuMCI+PHN0b3Agb2Zmc2V0PSIxcHgiIHN0b3AtY29sb3I9IiNmZmZmZmYiIHN0b3Atb3BhY2l0eT0iMC4wNSIvPjxzdG9wIG9mZnNldD0iMXB4IiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2dyYWQpIiAvPjwvc3ZnPiA='); background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjEuMCIgeDI9IjAuNSIgeTI9IjAuMCI+PHN0b3Agb2Zmc2V0PSIxcHgiIHN0b3AtY29sb3I9IiNmZmZmZmYiIHN0b3Atb3BhY2l0eT0iMC4wNSIvPjxzdG9wIG9mZnNldD0iMXB4IiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2dyYWQpIiAvPjwvc3ZnPiA=');
background-size: 100%; background-size: 100%;
@ -792,10 +786,10 @@ mct-container {
background-image: -webkit-linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, rgba(0, 0, 0, 0) 1px, rgba(0, 0, 0, 0) 100%); background-image: -webkit-linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, rgba(0, 0, 0, 0) 1px, rgba(0, 0, 0, 0) 100%);
background-image: linear-gradient(0deg, rgba(255, 255, 255, 0.05) 1px, rgba(0, 0, 0, 0) 1px, rgba(0, 0, 0, 0) 100%); background-image: linear-gradient(0deg, rgba(255, 255, 255, 0.05) 1px, rgba(0, 0, 0, 0) 1px, rgba(0, 0, 0, 0) 100%);
background-repeat: repeat-y; } background-repeat: repeat-y; }
/* line 138, ../sass/_fixed-position.scss */ /* line 152, ../sass/_fixed-position.scss */
.edit-mode .t-fixed-position .l-fixed-position-item:not(.s-selected) { .edit-mode .t-fixed-position .l-fixed-position-item:not(.s-selected) {
border: 1px dotted rgba(0, 153, 204, 0.75); } border: 1px dotted rgba(0, 153, 204, 0.75); }
/* line 140, ../sass/_fixed-position.scss */ /* line 154, ../sass/_fixed-position.scss */
.edit-mode .t-fixed-position .l-fixed-position-item:not(.s-selected):hover { .edit-mode .t-fixed-position .l-fixed-position-item:not(.s-selected):hover {
border: 1px dotted #0099cc; } border: 1px dotted #0099cc; }
@ -4744,20 +4738,24 @@ input[type="text"] {
.autoflow .l-autoflow-header { .autoflow .l-autoflow-header {
bottom: auto; bottom: auto;
height: 22px; height: 22px;
line-height: 22px; } line-height: 22px;
/* line 34, ../sass/_autoflow.scss */ min-width: 225px; }
/* line 35, ../sass/_autoflow.scss */
.autoflow .l-autoflow-header span { .autoflow .l-autoflow-header span {
vertical-align: middle; } vertical-align: middle; }
/* line 37, ../sass/_autoflow.scss */ /* line 38, ../sass/_autoflow.scss */
.autoflow .l-autoflow-header .l-filter { .autoflow .l-autoflow-header .l-filter {
margin-left: 5px; } margin-left: 5px; }
/* line 42, ../sass/_autoflow.scss */ /* line 40, ../sass/_autoflow.scss */
.autoflow .l-autoflow-header .l-filter input.t-filter-input {
width: 100px; }
/* line 46, ../sass/_autoflow.scss */
.autoflow .l-autoflow-items { .autoflow .l-autoflow-items {
overflow-x: scroll; overflow-x: scroll;
overflow-y: hidden; overflow-y: hidden;
top: 32px; top: 32px;
white-space: nowrap; } white-space: nowrap; }
/* line 48, ../sass/_autoflow.scss */ /* line 52, ../sass/_autoflow.scss */
.autoflow .l-autoflow-items .l-autoflow-col { .autoflow .l-autoflow-items .l-autoflow-col {
-moz-box-sizing: border-box; -moz-box-sizing: border-box;
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;
@ -4768,7 +4766,7 @@ input[type="text"] {
padding-right: 5px; padding-right: 5px;
vertical-align: top; vertical-align: top;
width: 225px; } width: 225px; }
/* line 58, ../sass/_autoflow.scss */ /* line 62, ../sass/_autoflow.scss */
.autoflow .l-autoflow-items .l-autoflow-col .l-autoflow-row { .autoflow .l-autoflow-items .l-autoflow-col .l-autoflow-row {
-moz-box-sizing: border-box; -moz-box-sizing: border-box;
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;
@ -4780,47 +4778,47 @@ input[type="text"] {
margin-bottom: 1px; margin-bottom: 1px;
margin-top: 1px; margin-top: 1px;
position: relative; } position: relative; }
/* line 67, ../sass/_autoflow.scss */ /* line 71, ../sass/_autoflow.scss */
.autoflow .l-autoflow-items .l-autoflow-col .l-autoflow-row:first-child { .autoflow .l-autoflow-items .l-autoflow-col .l-autoflow-row:first-child {
border-top: none; } border-top: none; }
/* line 70, ../sass/_autoflow.scss */ /* line 74, ../sass/_autoflow.scss */
.autoflow .l-autoflow-items .l-autoflow-col .l-autoflow-row:hover { .autoflow .l-autoflow-items .l-autoflow-col .l-autoflow-row:hover {
background: rgba(255, 255, 255, 0.1); } background: rgba(255, 255, 255, 0.1); }
/* line 75, ../sass/_autoflow.scss */ /* line 79, ../sass/_autoflow.scss */
.autoflow .l-autoflow-items .l-autoflow-col .l-autoflow-row.s-stale .l-autoflow-item.l { .autoflow .l-autoflow-items .l-autoflow-col .l-autoflow-row.s-stale .l-autoflow-item.l {
color: rgba(255, 255, 255, 0.3) !important; color: rgba(255, 255, 255, 0.3) !important;
font-style: italic; } font-style: italic; }
/* line 76, ../sass/_autoflow.scss */ /* line 80, ../sass/_autoflow.scss */
.autoflow .l-autoflow-items .l-autoflow-col .l-autoflow-row.s-stale .l-autoflow-item.r { .autoflow .l-autoflow-items .l-autoflow-col .l-autoflow-row.s-stale .l-autoflow-item.r {
color: rgba(255, 255, 255, 0.5) !important; color: rgba(255, 255, 255, 0.5) !important;
font-style: italic; } font-style: italic; }
/* line 79, ../sass/_autoflow.scss */ /* line 83, ../sass/_autoflow.scss */
.autoflow .l-autoflow-items .l-autoflow-col .l-autoflow-row:not(.s-stale) .l-autoflow-item.r { .autoflow .l-autoflow-items .l-autoflow-col .l-autoflow-row:not(.s-stale) .l-autoflow-item.r {
color: #b3b3b3; } color: #b3b3b3; }
/* line 83, ../sass/_autoflow.scss */ /* line 87, ../sass/_autoflow.scss */
.autoflow .l-autoflow-items .l-autoflow-col .l-autoflow-row.first-in-group { .autoflow .l-autoflow-items .l-autoflow-col .l-autoflow-row.first-in-group {
border-top: 1px solid gray; } border-top: 1px solid gray; }
/* line 86, ../sass/_autoflow.scss */ /* line 90, ../sass/_autoflow.scss */
.autoflow .l-autoflow-items .l-autoflow-col .l-autoflow-row .l-autoflow-item { .autoflow .l-autoflow-items .l-autoflow-col .l-autoflow-row .l-autoflow-item {
display: block; } display: block; }
/* line 88, ../sass/_autoflow.scss */ /* line 92, ../sass/_autoflow.scss */
.autoflow .l-autoflow-items .l-autoflow-col .l-autoflow-row .l-autoflow-item.l { .autoflow .l-autoflow-items .l-autoflow-col .l-autoflow-row .l-autoflow-item.l {
float: none; float: none;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
width: auto; } width: auto; }
/* line 95, ../sass/_autoflow.scss */ /* line 99, ../sass/_autoflow.scss */
.autoflow .l-autoflow-items .l-autoflow-col .l-autoflow-row .l-autoflow-item.r { .autoflow .l-autoflow-items .l-autoflow-col .l-autoflow-row .l-autoflow-item.r {
-moz-border-radius: 2px; -moz-border-radius: 2px;
-webkit-border-radius: 2px; -webkit-border-radius: 2px;
border-radius: 2px; border-radius: 2px;
float: right; float: right;
margin-left: 5px; margin-left: 5px;
padding-left: 2px; padding-left: 5px;
padding-right: 2px; padding-right: 5px;
text-align: right; } text-align: right; }
/* line 106, ../sass/_autoflow.scss */ /* line 110, ../sass/_autoflow.scss */
.autoflow .l-autoflow-items .l-autoflow-col:first-child { .autoflow .l-autoflow-items .l-autoflow-col:first-child {
border-left: none; border-left: none;
padding-left: 0; } padding-left: 0; }

View File

@ -24,18 +24,22 @@
$colMargin: $interiorMargin; $colMargin: $interiorMargin;
$colW: 225px; $colW: 225px;
$valW: 70px; $valW: 70px;
$valPad: 2px; $valPad: 5px;
$rowH: 15px; $rowH: 15px;
font-size: 0.75rem; font-size: 0.75rem;
.l-autoflow-header { .l-autoflow-header {
bottom: auto; bottom: auto;
height: $headerH; height: $headerH;
line-height: $headerH; line-height: $headerH;
min-width: $colW;
span { span {
vertical-align: middle; vertical-align: middle;
} }
.l-filter { .l-filter {
margin-left: $interiorMargin; margin-left: $interiorMargin;
input.t-filter-input {
width: 100px;
}
} }
} }

View File

@ -43,16 +43,26 @@ a.disabled {
@include test(); @include test();
} }
@mixin customKeyframes($animName: pulse, $op0: 0.5) {
@include keyframes($animName) {
0% { opacity: $op0; }
100% { opacity: 1; }
}
@include animation-name(pulse, 0.2);
}
@include keyframes(pulse) { @include keyframes(pulse) {
0% { opacity: 0.5; } 0% { opacity: 0.2; }
100% { opacity: 1; } 100% { opacity: 1; }
} }
@mixin pulse($dur: 500ms) {
@mixin pulse($dur: 500ms, $iteration: infinite) {
//@include customKeyframes(pulse, 0.2);
@include animation-name(pulse); @include animation-name(pulse);
@include animation-duration($dur); @include animation-duration($dur);
@include animation-direction(alternate); @include animation-direction(alternate);
@include animation-iteration-count(infinite); @include animation-iteration-count($iteration);
@include animation-timing-function(ease-in-out); @include animation-timing-function(ease-in-out);
} }

View File

@ -1,38 +1,44 @@
/***************************************************************************** /*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government * Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space * as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved. * Administration. All rights reserved.
* *
* Open MCT Web is licensed under the Apache License, Version 2.0 (the * 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. * "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0. * http://www.apache.org/licenses/LICENSE-2.0.
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations * License for the specific language governing permissions and limitations
* under the License. * under the License.
* *
* Open MCT Web includes source code licensed under additional open source * Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with * licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available * this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information. * at runtime from the About dialog for additional information.
*****************************************************************************/ *****************************************************************************/
.t-fixed-position { .t-fixed-position {
&.l-fixed-position { &.l-fixed-position {
// @include test(red); // @include test(red);
position: absolute; position: absolute;
top: 0; right: 0; bottom: 0; left: 0; top: 0;
width: auto; height: auto; right: 0;
bottom: 0;
left: 0;
width: auto;
height: auto;
.l-grid-holder { .l-grid-holder {
position: relative; position: relative;
height: 100%; width: 100%; height: 100%;
width: 100%;
.l-grid { .l-grid {
// @include test(orange); // @include test(orange);
position: absolute; position: absolute;
height: 100%; width: 100%; height: 100%;
width: 100%;
pointer-events: none; pointer-events: none;
z-index: 0; z-index: 0;
} }
@ -56,12 +62,13 @@
.l-fixed-position-image, .l-fixed-position-image,
.l-fixed-position-text { .l-fixed-position-text {
@include box-sizing(border-box); @include box-sizing(border-box);
height: 100%; width: 100%; height: 100%;
width: 100%;
} }
.l-fixed-position-box { .l-fixed-position-box {
} }
.l-fixed-position-image { .l-fixed-position-image {
background-size: cover; background-size: cover;
background-repeat: no-repeat; background-repeat: no-repeat;
@ -70,38 +77,45 @@
.l-fixed-position-text { .l-fixed-position-text {
@include txtShdwSubtle(); @include txtShdwSubtle();
border:1px solid transparent; border: 1px solid transparent;
font-size: 0.8rem; font-size: 0.8rem;
$p: 1px; //$interiorMarginSm; $p: 1px; //$interiorMarginSm;
line-height: 100%; line-height: 100%;
&.l-static-text { &.l-static-text {
// overflow: auto; // overflow: auto;
padding: $p; padding: $p;
} }
&.l-telemetry { &.l-telemetry {
.l-elem { .l-elem {
//@include absPosDefault($p); //@include absPosDefault($p);
@include absPosDefault(0); //@include absPosDefault(0);
@include box-sizing(border-box); @include box-sizing(border-box);
display: block;
padding: 2px; padding: 2px;
width: 50%; //width: 50%;
&.l-title { &.l-title {
right: auto; //right: auto;
left: $p; //left: $p;
float: none;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
width: auto;
} }
&.l-value { &.l-value {
// @include test(blue); // @include test(blue);
right: $p; // right: $p;
left: auto; // left: auto;
@include border-radius($smallCr);
$valPad: 5px;
float: right;
margin-left: $interiorMargin;
padding-left: $valPad;
padding-right: $valPad;
text-align: right; text-align: right;
&.telem-only { &.telem-only {
// @include test(red); margin-left: 0;
left: $p; width: 100%;
width: auto;
}
.l-value-bg {
@include border-radius($smallCr);
padding: 0 4px;
} }
} }
} }

View File

@ -26,7 +26,7 @@
width: auto; height: auto; width: auto; height: auto;
} }
@mixin trans-prop-nice($props, $t) { @mixin trans-prop-nice($props, $t: 500ms) {
@if $t == 0 { @if $t == 0 {
@include transition-property(none); @include transition-property(none);
} @else { } @else {

View File

@ -70,6 +70,12 @@
"type": "decorator", "type": "decorator",
"implementation": "models/CachingModelDecorator.js" "implementation": "models/CachingModelDecorator.js"
}, },
{
"provides": "modelService",
"type": "decorator",
"priority": "fallback",
"implementation": "models/MissingModelDecorator.js"
},
{ {
"provides": "typeService", "provides": "typeService",
"type": "provider", "type": "provider",
@ -132,6 +138,11 @@
"features": "creation", "features": "creation",
"description": "Useful for storing and organizing domain objects.", "description": "Useful for storing and organizing domain objects.",
"model": { "composition": [] } "model": { "composition": [] }
},
{
"key": "unknown",
"name": "Unknown Type",
"glyph": "?"
} }
], ],
"capabilities": [ "capabilities": [
@ -202,4 +213,4 @@
} }
] ]
} }
} }

View File

@ -0,0 +1,59 @@
/*****************************************************************************
* 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.
*****************************************************************************/
/*global define*/
define(
[],
function () {
"use strict";
/**
* Adds placeholder domain object models for any models which
* fail to load from the underlying model service.
* @implements {ModelService}
*/
function MissingModelDecorator(modelService) {
function missingModel(id) {
return {
type: "unknown",
name: "Missing: " + id
};
}
return {
getModels: function (ids) {
function addMissingModels(models) {
var result = {};
ids.forEach(function (id) {
result[id] = models[id] || missingModel(id);
});
return result;
}
return modelService.getModels(ids).then(addMissingModels);
}
};
}
return MissingModelDecorator;
}
);

View File

@ -0,0 +1,35 @@
{
"name": "Plot view for telemetry",
"extensions": {
"views": [
{
"name": "Imagery",
"key": "imagery",
"glyph": "\u00E3",
"templateUrl": "templates/imagery.html",
"priority": "preferred",
"needs": [ "telemetry" ]
}
],
"policies": [
{
"category": "view",
"implementation": "policies/ImageryViewPolicy.js"
}
],
"controllers": [
{
"key": "ImageryController",
"implementation": "controllers/ImageryController.js",
"depends": [ "$scope", "telemetryHandler" ]
}
],
"directives": [
{
"key": "mctBackgroundImage",
"implementation": "directives/MCTBackgroundImage.js",
"depends": [ "$document" ]
}
]
}
}

View File

@ -0,0 +1,67 @@
<div class="t-imagery" ng-controller="ImageryController as imagery">
<!-- Main image -->
<div
class="l-image-main-wrapper"
ng-mouseenter="showLocalControls = true;"
ng-mouseleave="showLocalControls = false;"
>
<div
class="l-local-controls s-local-controls"
ng-show="false && showLocalControls"
>
<a
class="t-btn l-btn s-btn s-icon-btn s-very-subtle"
ng-click="plot.stepBackPanZoom()"
ng-show="1"
title="Restore previous pan/zoom">
<span class="ui-symbol icon">&lt;</span>
</a>
<a
class="t-btn l-btn s-btn s-icon-btn s-very-subtle"
ng-click="plot.unzoom()"
ng-show="1"
title="Reset pan/zoom">
<span class="ui-symbol icon">I</span>
</a>
</div>
<div
class="l-image-main s-image-main"
ng-class="{ paused: imagery.paused(), stale:false }"
mct-background-image="imagery.getImageUrl()"
>
</div>
<div class="l-image-main-controlbar bar">
<div class="left">
<a
class="t-btn l-btn s-btn s-icon-btn s-very-subtle show-thumbs sm"
ng-click="showThumbsBubble = (showThumbsBubble)? false:true"
><span class="ui-symbol icon"></span></a>
<span class="l-timezone">{{imagery.getZone()}}</span>
<span class="l-time">{{imagery.getTime()}}</span>
<span class="l-date">{{imagery.getDate()}}</span>
</div>
<div class="right">
<a
class="t-btn l-btn s-btn s-icon-btn s-very-subtle pause-play sm"
ng-click="imagery.paused(!imagery.paused())"
ng-class="{ paused: imagery.paused() }"
><span class="ui-symbol icon"></span></a>
<a href="{{imagery.getImageUrl()}}"
ng-if="imagery.getImageUrl()"
target="_blank"
title="Open image in new tab."
class="t-btn l-btn s-btn s-icon-btn s-very-subtle sm">
<span class="ui-symbol icon">y</span></a>
<a href=""
class="l-btn s-btn s-icon-btn l-mag s-mag ui-symbol vsm"
ng-click="clipped = false"
ng-show="clipped === true"
title="Not all of image is visible; click to reset."
></a>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,133 @@
/*****************************************************************************
* 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.
*****************************************************************************/
/*global define*/
define(
['moment'],
function (moment) {
"use strict";
var DATE_FORMAT = "YYYY-MM-DD",
TIME_FORMAT = "HH:mm:ss.SSS";
/**
* Controller for the "Imagery" view of a domain object which
* provides image telemetry.
*/
function ImageryController($scope, telemetryHandler) {
var date = "",
time = "",
imageUrl = "",
paused = false,
handle;
function releaseSubscription() {
if (handle) {
handle.unsubscribe();
handle = undefined;
}
}
function updateValues() {
var imageObject = handle && handle.getTelemetryObjects()[0],
m;
if (imageObject && !paused) {
m = moment.utc(handle.getDomainValue(imageObject));
date = m.format(DATE_FORMAT);
time = m.format(TIME_FORMAT);
imageUrl = handle.getRangeValue(imageObject);
}
}
// Create a new subscription; telemetrySubscriber gets
// to do the meaningful work here.
function subscribe(domainObject) {
releaseSubscription();
date = "";
time = "";
imageUrl = "";
handle = domainObject && telemetryHandler.handle(
domainObject,
updateValues,
true // Lossless
);
}
// Subscribe to telemetry when a domain object becomes available
$scope.$watch('domainObject', subscribe);
// Unsubscribe when the plot is destroyed
$scope.$on("$destroy", releaseSubscription);
return {
/**
* Get the time portion (hours, minutes, seconds) of the
* timestamp associated with the incoming image telemetry.
* @returns {string} the time
*/
getTime: function () {
return time;
},
/**
* Get the date portion (month, year) of the
* timestamp associated with the incoming image telemetry.
* @returns {string} the date
*/
getDate: function () {
return date;
},
/**
* Get the time zone for the displayed time/date corresponding
* to the timestamp associated with the incoming image
* telemetry.
* @returns {string} the time
*/
getZone: function () {
return "UTC";
},
/**
* Get the URL of the image telemetry to display.
* @returns {string} URL for telemetry image
*/
getImageUrl: function () {
return imageUrl;
},
/**
* Getter-setter for paused state of the view (true means
* paused, false means not.)
* @param {boolean} [state] the state to set
* @returns {boolean} the current state
*/
paused: function (state) {
if (arguments.length > 0 && state !== paused) {
paused = state;
// Switch to latest image
updateValues();
}
return paused;
}
};
}
return ImageryController;
}
);

View File

@ -0,0 +1,89 @@
/*****************************************************************************
* 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.
*****************************************************************************/
/*global define*/
define(
function () {
"use strict";
/**
* Defines the `mct-background-image` directive.
*
* Used as an attribute, this will set the `background-image`
* property to the URL given in its value, but only after that
* image has loaded; this avoids "flashing" as images change.
*
* If `src` is falsy, no image will be displayed (immediately.)
*
*/
function MCTBackgroundImage($document) {
function link(scope, element, attrs) {
// General strategy here:
// - Keep count of how many images have been requested; this
// counter will be used as an internal identifier or sorts
// for each image that loads.
// - As the src attribute changes, begin loading those images.
// - When images do load, update the background-image property
// of the element, but only if a more recently
// requested image has not already been loaded.
// The order in which URLs are passed in and the order
// in which images are actually loaded may be different, so
// some strategy like this is necessary to ensure that images
// do not display out-of-order.
var div, requested = 0, loaded = 0;
function nextImage(url) {
var myCounter = requested,
image;
function useImage() {
if (loaded <= myCounter) {
loaded = myCounter;
element.css('background-image', "url('" + url + "')");
}
}
if (!url) {
loaded = myCounter;
element.css('background-image', undefined);
} else {
image = $document[0].createElement('img');
image.src = url;
image.onload = useImage;
}
requested += 1;
}
scope.$watch('mctBackgroundImage', nextImage);
}
return {
restrict: "A",
scope: { mctBackgroundImage: "=" },
link: link
};
}
return MCTBackgroundImage;
}
);

View File

@ -0,0 +1,59 @@
/*****************************************************************************
* 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.
*****************************************************************************/
/*global define*/
define(
function () {
"use strict";
/**
* Policy preventing the Imagery view from being made available for
* domain objects which do not have associated image telemetry.
* @implements {Policy}
*/
function ImageryViewPolicy() {
function hasImageTelemetry(domainObject) {
var telemetry = domainObject &&
domainObject.getCapability('telemetry'),
metadata = telemetry ? telemetry.getMetadata() : {},
ranges = metadata.ranges || [];
return ranges.some(function (range) {
return range.format === 'imageUrl' ||
range.format === 'image';
});
}
return {
allow: function (view, domainObject) {
if (view.key === 'imagery') {
return hasImageTelemetry(domainObject);
}
return true;
}
};
}
return ImageryViewPolicy;
}
);

View File

@ -0,0 +1,152 @@
/*****************************************************************************
* 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.
*****************************************************************************/
/*global define,describe,it,expect,beforeEach,jasmine,xit*/
define(
["../../src/controllers/ImageryController"],
function (ImageryController) {
"use strict";
describe("The Imagery controller", function () {
var mockScope,
mockTelemetryHandler,
mockHandle,
mockDomainObject,
controller;
function invokeWatch(expr, value) {
mockScope.$watch.calls.forEach(function (call) {
if (call.args[0] === expr) {
call.args[1](value);
}
});
}
beforeEach(function () {
mockScope = jasmine.createSpyObj('$scope', ['$on', '$watch']);
mockTelemetryHandler = jasmine.createSpyObj(
'telemetryHandler',
['handle']
);
mockHandle = jasmine.createSpyObj(
'handle',
[
'getDomainValue',
'getRangeValue',
'getTelemetryObjects',
'unsubscribe'
]
);
mockDomainObject = jasmine.createSpyObj(
'domainObject',
['getId', 'getModel', 'getCapability']
);
mockTelemetryHandler.handle.andReturn(mockHandle);
mockHandle.getTelemetryObjects.andReturn([mockDomainObject]);
controller = new ImageryController(
mockScope,
mockTelemetryHandler
);
invokeWatch('domainObject', mockDomainObject);
});
it("unsubscribes when scope is destroyed", function () {
expect(mockHandle.unsubscribe).not.toHaveBeenCalled();
// Find the $destroy listener and call it
mockScope.$on.calls.forEach(function (call) {
if (call.args[0] === '$destroy') {
call.args[1]();
}
});
expect(mockHandle.unsubscribe).toHaveBeenCalled();
});
it("exposes the latest telemetry values", function () {
// 06/18/2015 4:04am UTC
var testTimestamp = 1434600258123,
testUrl = "some/url",
nextTimestamp = 1434600259456, // 4:05.456
nextUrl = "some/other/url";
mockHandle.getDomainValue.andReturn(testTimestamp);
mockHandle.getRangeValue.andReturn(testUrl);
// Call the subscription listener
mockTelemetryHandler.handle.mostRecentCall.args[1]();
expect(controller.getTime()).toEqual("04:04:18.123");
expect(controller.getDate()).toEqual("2015-06-18");
expect(controller.getZone()).toEqual("UTC");
expect(controller.getImageUrl()).toEqual(testUrl);
mockHandle.getDomainValue.andReturn(nextTimestamp);
mockHandle.getRangeValue.andReturn(nextUrl);
mockTelemetryHandler.handle.mostRecentCall.args[1]();
expect(controller.getTime()).toEqual("04:04:19.456");
expect(controller.getDate()).toEqual("2015-06-18");
expect(controller.getZone()).toEqual("UTC");
expect(controller.getImageUrl()).toEqual(nextUrl);
});
it("allows updates to be paused", function () {
// 06/18/2015 4:04am UTC
var testTimestamp = 1434600258123,
testUrl = "some/url",
nextTimestamp = 1434600259456, // 4:05.456
nextUrl = "some/other/url";
// As above, but pause in between. Expect details
// not to change this time
mockHandle.getDomainValue.andReturn(testTimestamp);
mockHandle.getRangeValue.andReturn(testUrl);
// Call the subscription listener
mockTelemetryHandler.handle.mostRecentCall.args[1]();
expect(controller.getTime()).toEqual("04:04:18.123");
expect(controller.getDate()).toEqual("2015-06-18");
expect(controller.getZone()).toEqual("UTC");
expect(controller.getImageUrl()).toEqual(testUrl);
expect(controller.paused()).toBeFalsy();
controller.paused(true); // Pause!
expect(controller.paused()).toBeTruthy();
mockHandle.getDomainValue.andReturn(nextTimestamp);
mockHandle.getRangeValue.andReturn(nextUrl);
mockTelemetryHandler.handle.mostRecentCall.args[1]();
expect(controller.getTime()).toEqual("04:04:18.123");
expect(controller.getDate()).toEqual("2015-06-18");
expect(controller.getZone()).toEqual("UTC");
expect(controller.getImageUrl()).toEqual(testUrl);
});
});
}
);

View File

@ -0,0 +1,101 @@
/*****************************************************************************
* 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.
*****************************************************************************/
/*global define,describe,it,expect,beforeEach,jasmine,xit*/
define(
["../../src/directives/MCTBackgroundImage"],
function (MCTBackgroundImage) {
"use strict";
describe("The mct-background-image directive", function () {
var mockDocument,
mockScope,
mockElement,
testImage,
directive;
beforeEach(function () {
mockDocument = [
jasmine.createSpyObj('document', ['createElement'])
];
mockScope = jasmine.createSpyObj('scope', ['$watch']);
mockElement = jasmine.createSpyObj('element', [ 'css' ]);
testImage = {};
mockDocument[0].createElement.andReturn(testImage);
directive = new MCTBackgroundImage(mockDocument);
});
it("is applicable as an attribute", function () {
expect(directive.restrict).toEqual("A");
});
it("two-way-binds its own value", function () {
expect(directive.scope.mctBackgroundImage).toEqual("=");
});
it("watches for changes to the URL", function () {
directive.link(mockScope, mockElement, {});
expect(mockScope.$watch).toHaveBeenCalledWith(
'mctBackgroundImage',
jasmine.any(Function)
);
});
it("updates images in-order, even when they load out-of-order", function () {
var firstOnload;
directive.link(mockScope, mockElement);
mockScope.$watch.mostRecentCall.args[1]("some/url/0");
firstOnload = testImage.onload;
mockScope.$watch.mostRecentCall.args[1]("some/url/1");
// Resolve in a different order
testImage.onload();
firstOnload();
// Should still have taken the more recent value
expect(mockElement.css.mostRecentCall.args).toEqual([
"background-image",
"url('some/url/1')"
]);
});
it("clears the background image when undefined is passed in", function () {
directive.link(mockScope, mockElement);
mockScope.$watch.mostRecentCall.args[1]("some/url/0");
testImage.onload();
mockScope.$watch.mostRecentCall.args[1](undefined);
expect(mockElement.css.mostRecentCall.args).toEqual([
"background-image",
undefined
]);
});
});
}
);

View File

@ -0,0 +1,80 @@
/*****************************************************************************
* 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.
*****************************************************************************/
/*global define,describe,it,expect,beforeEach,jasmine,xit*/
define(
["../../src/policies/ImageryViewPolicy"],
function (ImageryViewPolicy) {
"use strict";
describe("Imagery view policy", function () {
var testView,
mockDomainObject,
mockTelemetry,
testMetadata,
policy;
beforeEach(function () {
testView = { key: "imagery" };
testMetadata = {};
mockDomainObject = jasmine.createSpyObj(
'domainObject',
['getId', 'getModel', 'getCapability']
);
mockTelemetry = jasmine.createSpyObj(
'telemetry',
['getMetadata']
);
mockDomainObject.getCapability.andCallFake(function (c) {
return c === 'telemetry' ? mockTelemetry : undefined;
});
mockTelemetry.getMetadata.andReturn(testMetadata);
policy = new ImageryViewPolicy();
});
it("allows the imagery view for domain objects with image telemetry", function () {
testMetadata.ranges = [ { key: "foo", format: "imageUrl" } ];
expect(policy.allow(testView, mockDomainObject)).toBeTruthy();
});
it("disallows the imagery view for domain objects without image telemetry", function () {
testMetadata.ranges = [ { key: "foo", format: "somethingElse" } ];
expect(policy.allow(testView, mockDomainObject)).toBeFalsy();
});
it("disallows the imagery view for domain objects without telemetry", function () {
testMetadata.ranges = [ { key: "foo", format: "imageUrl" } ];
mockDomainObject.getCapability.andReturn(undefined);
expect(policy.allow(testView, mockDomainObject)).toBeFalsy();
});
it("allows other views", function () {
testView.key = "somethingElse";
testMetadata.ranges = [ { key: "foo", format: "somethingElse" } ];
expect(policy.allow(testView, mockDomainObject)).toBeTruthy();
});
});
}
);

View File

@ -0,0 +1,5 @@
[
"controllers/ImageryController",
"directives/MCTBackgroundImage",
"policies/ImageryViewPolicy"
]

View File

@ -23,16 +23,17 @@
class="l-fixed-position-text l-telemetry" class="l-fixed-position-text l-telemetry"
ng-style="{ background: ngModel.fill(), 'border-color': ngModel.stroke(), color: ngModel.color() }" ng-style="{ background: ngModel.fill(), 'border-color': ngModel.stroke(), color: ngModel.color() }"
> >
<div <span
class="l-elem l-value l-obj-val-format"
data-value="{{ngModel.value}}"
ng-class="{ 'telem-only': !ngModel.element.titled }"
>
{{ngModel.value}}
</span>
<span
class="l-elem l-title" class="l-elem l-title"
ng-show="ngModel.element.titled" ng-show="ngModel.element.titled"
> >
{{ngModel.name}} {{ngModel.name}}
</div> </span>
<div
class="l-elem l-value"
ng-class="{ 'telem-only': !ngModel.element.titled }"
>
{{ngModel.value}}
</div>
</div> </div>

View File

@ -25,6 +25,12 @@
"implementation": "PlotController.js", "implementation": "PlotController.js",
"depends": [ "$scope", "telemetryFormatter", "telemetryHandler", "throttle" ] "depends": [ "$scope", "telemetryFormatter", "telemetryHandler", "throttle" ]
} }
],
"policies": [
{
"category": "view",
"implementation": "policies/PlotViewPolicy.js"
}
] ]
} }
} }

View File

@ -0,0 +1,65 @@
/*****************************************************************************
* 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.
*****************************************************************************/
/*global define*/
define(
function () {
"use strict";
/**
* Policy preventing the Plot view from being made available for
* domain objects which have non-numeric telemetry.
* @implements {Policy}
*/
function PlotViewPolicy() {
function hasImageTelemetry(domainObject) {
var telemetry = domainObject &&
domainObject.getCapability('telemetry'),
metadata = telemetry ? telemetry.getMetadata() : {},
ranges = metadata.ranges || [];
// Generally, we want to allow Plot for telemetry-providing
// objects (most telemetry is plottable.) We only want to
// suppress this for telemetry which only has explicitly
// non-numeric values.
return ranges.length === 0 || ranges.some(function (range) {
// Assume format is numeric if it is undefined
// (numeric telemetry is the common case)
return range.format === undefined ||
range.format === 'number';
});
}
return {
allow: function (view, domainObject) {
if (view.key === 'plot') {
return hasImageTelemetry(domainObject);
}
return true;
}
};
}
return PlotViewPolicy;
}
);

View File

@ -0,0 +1,79 @@
/*****************************************************************************
* 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.
*****************************************************************************/
/*global define,describe,it,expect,beforeEach,jasmine,xit*/
define(
["../../src/policies/PlotViewPolicy"],
function (PlotViewPolicy) {
"use strict";
describe("Plot view policy", function () {
var testView,
mockDomainObject,
mockTelemetry,
testMetadata,
policy;
beforeEach(function () {
testView = { key: "plot" };
testMetadata = {};
mockDomainObject = jasmine.createSpyObj(
'domainObject',
['getId', 'getModel', 'getCapability']
);
mockTelemetry = jasmine.createSpyObj(
'telemetry',
['getMetadata']
);
mockDomainObject.getCapability.andCallFake(function (c) {
return c === 'telemetry' ? mockTelemetry : undefined;
});
mockTelemetry.getMetadata.andReturn(testMetadata);
policy = new PlotViewPolicy();
});
it("allows the imagery view for domain objects with numeric telemetry", function () {
testMetadata.ranges = [ { key: "foo", format: "number" } ];
expect(policy.allow(testView, mockDomainObject)).toBeTruthy();
});
it("allows the imagery view for domain objects with unspecified telemetry", function () {
testMetadata.ranges = [ { key: "foo" } ];
expect(policy.allow(testView, mockDomainObject)).toBeTruthy();
});
it("disallows the imagery view for domain objects without image telemetry", function () {
testMetadata.ranges = [ { key: "foo", format: "somethingElse" } ];
expect(policy.allow(testView, mockDomainObject)).toBeFalsy();
});
it("allows other views", function () {
testView.key = "somethingElse";
testMetadata.ranges = [ { key: "foo", format: "somethingElse" } ];
expect(policy.allow(testView, mockDomainObject)).toBeTruthy();
});
});
}
);

View File

@ -18,6 +18,7 @@
"elements/PlotUpdater", "elements/PlotUpdater",
"modes/PlotModeOptions", "modes/PlotModeOptions",
"modes/PlotOverlayMode", "modes/PlotOverlayMode",
"modes/PlotStackMode" "modes/PlotStackMode",
"policies/PlotViewPolicy"
] ]