Merge branch 'open-master' into open1233

This commit is contained in:
Victor Woeltjen
2015-06-26 11:50:48 -07:00
67 changed files with 3456 additions and 274 deletions

View File

@@ -0,0 +1,37 @@
{
"name": "Event Messages",
"description": "List of time-ordered event messages",
"extensions": {
"views": [
{
"key": "messages",
"name": "Messages",
"glyph": "5",
"description": "Scrolling list of messages.",
"templateUrl": "templates/messages.html",
"needs": [ "telemetry" ],
"delegation": true
}
],
"controllers": [
{
"key": "EventListController",
"implementation": "EventListController.js",
"depends": [ "$scope", "telemetryFormatter" ]
}
],
"directives": [
{
"key": "mctDataTable",
"implementation": "directives/MCTDataTable.js",
"depends": [ "$window" ]
}
],
"policies": [
{
"category": "view",
"implementation": "policies/MessagesViewPolicy.js"
}
]
}
}

View File

@@ -0,0 +1,37 @@
<!--
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.
-->
<table class="tabular">
<thead>
<tr>
<th ng-repeat="header in headers">
{{header}}
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in rows">
<td ng-repeat="cell in row">
{{cell}}
</td>
</tr>
</tbody>
</table>

View File

@@ -0,0 +1,29 @@
<!--
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.
-->
<div class="w1" ng-controller="TelemetryController as telemetry">
<div class="w2"
ng-controller="EventListController">
<mct-data-table headers="headers" rows="rows" ascending-scroll="true"></mct-data-table>
</div>
</div>

View File

@@ -0,0 +1,67 @@
/*****************************************************************************
* 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,moment*/
/**
* Module defining DomainColumn. Created by vwoeltje on 11/18/14.
*/
define(
[],
function () {
"use strict";
/**
* A column which will report telemetry domain values
* (typically, timestamps.) Used by the ScrollingListController.
*
* @constructor
* @param domainMetadata an object with the machine- and human-
* readable names for this domain (in `key` and `name`
* fields, respectively.)
* @param {TelemetryFormatter} telemetryFormatter the telemetry
* formatting service, for making values human-readable.
*/
function DomainColumn(domainMetadata, telemetryFormatter) {
return {
/**
* Get the title to display in this column's header.
* @returns {string} the title to display
*/
getTitle: function () {
return domainMetadata.name;
},
/**
* Get the text to display inside a row under this
* column.
* @returns {string} the text to display
*/
getValue: function (domainObject, data, index) {
return telemetryFormatter.formatDomainValue(
data.getDomainValue(index, domainMetadata.key)
);
}
};
}
return DomainColumn;
}
);

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*/
/**
* Module defining EventListController.
* Created by chacskaylo on 06/18/2015.
* Modified by shale on 06/23/2015.
*/
define(
["./DomainColumn", "./RangeColumn", "./EventListPopulator"],
function (DomainColumn, RangeColumn, EventListPopulator) {
"use strict";
var ROW_COUNT = 100;
/**
* The EventListController is responsible for populating
* the contents of the event list view.
* @constructor
*/
function EventListController($scope, formatter) {
var populator;
// Get a set of populated, ready-to-display rows for the
// latest data values.
function getRows(telemetry) {
var datas = telemetry.getResponse(),
objects = telemetry.getTelemetryObjects();
return populator.getRows(datas, objects, ROW_COUNT);
}
// Update the contents
function updateRows() {
var telemetry = $scope.telemetry;
$scope.rows = telemetry ? getRows(telemetry) : [];
}
// Set up columns based on telemetry metadata. This will
// include one column for each domain and range type, as
// well as a column for the domain object name.
function setupColumns(telemetry) {
var domainKeys = {},
rangeKeys = {},
columns = [],
metadata;
// Add a domain to the set of columns, if a domain
// with the same key has not yet been inclued.
function addDomain(domain) {
var key = domain.key;
if (key && !domainKeys[key]) {
domainKeys[key] = true;
columns.push(new DomainColumn(domain, formatter));
}
}
// Add a range col to the set of columns, if a range
// with the same key has not yet been included.
function addRange(range) {
var key = range.key;
if (key && !rangeKeys[key]) {
rangeKeys[key] = true;
columns.push(new RangeColumn(range, formatter));
}
}
// We cannot proceed if the telemetry controller
// is not available; clear all rows/columns.
if (!telemetry) {
columns = [];
$scope.rows = [];
$scope.headers = [];
return;
}
// Add domain, range, event msg columns
metadata = telemetry.getMetadata();
(metadata || []).forEach(function (metadata) {
(metadata.domains || []).forEach(addDomain);
});
(metadata || []).forEach(function (metadata) {
(metadata.ranges || []).forEach(addRange);
});
// Add default domain and range columns if none
// were described in metadata.
if (Object.keys(domainKeys).length < 1) {
columns.push(new DomainColumn({name: "Time"}, formatter));
}
if (Object.keys(rangeKeys).length < 1) {
columns.push(new RangeColumn({name: "Message"}, formatter));
}
// We have all columns now; use them to initializer
// the populator, which will use them to generate
// actual rows and headers.
populator = new EventListPopulator(columns);
// Initialize headers
$scope.headers = populator.getHeaders();
// Fill in the contents of the rows.
updateRows();
}
$scope.$on("telemetryUpdate", updateRows);
$scope.$watch("telemetry", setupColumns);
}
return EventListController;
}
);

View File

@@ -0,0 +1,161 @@
/*****************************************************************************
* 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";
/**
* The EventListPopulator is responsible for filling in the
* values which should appear within columns of a event list
* view, based on received telemetry data.
* @constructor
* @param {Column[]} columns the columns to be populated
*/
function EventListPopulator(columns) {
/**
* Look up the most recent values from a set of data objects.
* Returns an array of objects in the order in which data
* should be displayed; each element is an object with
* two properties:
*
* * objectIndex: The index of the domain object associated
* with the data point to be displayed in that
* row.
* * pointIndex: The index of the data point itself, within
* its data set.
*
* @param {Array<Telemetry>} datas an array of the most recent
* data objects; expected to be in the same order
* as the domain objects provided at constructor
* @param {number} count the number of rows to provide
*/
function getLatestDataValues(datas, count) {
var latest = [],
candidate,
candidateTime,
used = datas.map(function () { return 0; });
// This algorithm is O(nk) for n rows and k telemetry elements;
// one O(k) linear search for a max is made for each of n rows.
// This could be done in O(n lg k + k lg k), using a priority
// queue (where priority is max-finding) containing k initial
// values. For n rows, pop the max from the queue and replenish
// the queue with a value from the data at the same
// objectIndex, if available.
// But k is small, so this might not give an observable
// improvement in performance.
// Find the most recent unused data point (this will be used
// in a loop to find and the N most recent data points)
function findCandidate(data, i) {
var nextTime,
pointCount = data.getPointCount(),
pointIndex = pointCount - used[i] - 1;
if (data && pointIndex >= 0) {
nextTime = data.getDomainValue(pointIndex);
if (nextTime > candidateTime) {
candidateTime = nextTime;
candidate = {
objectIndex: i,
pointIndex: pointIndex
};
}
}
}
// Assemble a list of the most recent data points
while (latest.length < count) {
// Reset variables pre-search
candidateTime = Number.NEGATIVE_INFINITY;
candidate = undefined;
// Linear search for most recent
datas.forEach(findCandidate);
if (candidate) {
// Record this data point - it is the most recent
latest.push(candidate);
// Track the data points used so we can look farther back
// in the data set on the next iteration
used[candidate.objectIndex] = used[candidate.objectIndex] + 1;
} else {
// Ran out of candidates; not enough data points
// available to fill all rows.
break;
}
}
return latest;
}
return {
/**
* Get the text which should appear in headers for the
* provided columns.
* @returns {string[]} column headers
*/
getHeaders: function () {
return columns.map(function (column) {
return column.getTitle();
});
},
/**
* Get the contents of rows for the event list view.
* @param {TelemetrySeries[]} datas the data sets
* @param {DomainObject[]} objects the domain objects which
* provided the data sets; these should match
* index-to-index with the `datas` argument
* @param {number} count the number of rows to populate
* @returns {string[][]} an array of rows, each of which
* is an array of values which should appear
* in that row
*/
getRows: function (datas, objects, count) {
var values = getLatestDataValues(datas, count);
// Each value will become a row, which will contain
// some value in each column (rendering by the
// column object itself)
// Additionally, we want to display the rows in reverse
// order. (i.e. from the top to the bottom of the page)
return values.map(function (value) {
return columns.map(function (column) {
return column.getValue(
objects[value.objectIndex],
datas[value.objectIndex],
value.pointIndex
);
});
}).reverse();
}
};
}
return EventListPopulator;
}
);

View File

@@ -0,0 +1,67 @@
/*****************************************************************************
* 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 DomainColumn. Created by vwoeltje on 11/18/14.
*/
define(
[],
function () {
"use strict";
/**
* A column which will report telemetry range values
* (typically, measurements.) Used by the ScrollingListController.
*
* @constructor
* @param rangeMetadata an object with the machine- and human-
* readable names for this range (in `key` and `name`
* fields, respectively.)
* @param {TelemetryFormatter} telemetryFormatter the telemetry
* formatting service, for making values human-readable.
*/
function RangeColumn(rangeMetadata, telemetryFormatter) {
return {
/**
* Get the title to display in this column's header.
* @returns {string} the title to display
*/
getTitle: function () {
return rangeMetadata.name;
},
/**
* Get the text to display inside a row under this
* column.
* @returns {string} the text to display
*/
getValue: function (domainObject, data, index) {
return telemetryFormatter.formatRangeValue(
data.getRangeValue(index, rangeMetadata.key)
);
}
};
}
return RangeColumn;
}
);

View File

@@ -0,0 +1,74 @@
/*****************************************************************************
* 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 MCTDataTable. Created by shale on 06/22/2015.
*/
define(
[],
function () {
"use strict";
function MCTDataTable($window) {
return {
restrict: "E",
templateUrl: "platform/features/events/res/templates/mct-data-table.html",
scope: {
headers: "=",
rows: "=",
ascendingScroll: "="
},
link: function ($scope, $element) {
var currentHeight,
previousHeight,
scrollParent;
// If the scroll is set to ascending, we want to
// check when elements are added to the table, and move the scroll
// bar accordingly.
// (When viewing at the bottom of the page, the scroll bar will
// stay at the bottom despite additions to the table)
if ($scope.ascendingScroll) {
$scope.$watch("rows", function () {
// Wait until the page as been repainted (otherwise the
// height will always be zero)
$window.requestAnimationFrame(function () {
previousHeight = currentHeight;
// The height of the table body
currentHeight = $element[0].firstElementChild.firstElementChild.nextElementSibling.clientHeight;
// One of the parents is a div that has vscroll
scrollParent = $element[0].parentElement.parentElement.parentElement.parentElement.parentElement;
// Move the scrollbar down the amount that the height has changed
scrollParent.scrollTop = scrollParent.scrollTop + (currentHeight - previousHeight);
});
});
}
}
};
}
return MCTDataTable;
}
);

View File

@@ -0,0 +1,74 @@
/*****************************************************************************
* 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*/
/**
* Module defining MessagesViewPolicy. Created by shale on 06/24/2015.
*/
define(
[],
function () {
"use strict";
/**
* Policy controlling when the Messages view should be avaliable.
* @constructor
*/
function MessagesViewPolicy() {
function hasStringTelemetry(domainObject) {
var telemetry = domainObject &&
domainObject.getCapability('telemetry'),
metadata = telemetry ? telemetry.getMetadata() : {},
ranges = metadata.ranges || [];
return ranges.some(function (range) {
return range.format === 'string';
});
}
return {
/**
* Check whether or not a given action is allowed by this
* policy.
* @param {Action} action the action
* @param domainObject the domain object which will be viewed
* @returns {boolean} true if not disallowed
*/
allow: function (view, domainObject) {
// This policy only applies for the Messages view
if (view.key === 'messages') {
// The Messages view is allowed only if the domain
// object has string telemetry
if (!hasStringTelemetry(domainObject)) {
return false;
}
}
// Like all policies, allow by default.
return true;
}
};
}
return MessagesViewPolicy;
}
);

View File

@@ -0,0 +1,84 @@
/*****************************************************************************
* 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,waitsFor,jasmine*/
/**
* EventSpec. Created by vwoeltje on 11/6/14. Modified by shale on 06/23/2015.
*/
define(
["../src/DomainColumn"],
function (DomainColumn) {
"use strict";
var TEST_DOMAIN_VALUE = "some formatted domain value";
describe("An event list domain column", function () {
var mockDataSet,
testMetadata,
mockFormatter,
column;
beforeEach(function () {
mockDataSet = jasmine.createSpyObj(
"data",
[ "getDomainValue" ]
);
mockFormatter = jasmine.createSpyObj(
"formatter",
[ "formatDomainValue", "formatRangeValue" ]
);
testMetadata = {
key: "testKey",
name: "Test Name"
};
mockFormatter.formatDomainValue.andReturn(TEST_DOMAIN_VALUE);
column = new DomainColumn(testMetadata, mockFormatter);
});
it("reports a column header from domain metadata", function () {
expect(column.getTitle()).toEqual("Test Name");
});
it("looks up data from a data set", function () {
column.getValue(undefined, mockDataSet, 42);
expect(mockDataSet.getDomainValue)
.toHaveBeenCalledWith(42, "testKey");
});
it("formats domain values as time", function () {
mockDataSet.getDomainValue.andReturn(402513731000);
// Should have just given the value the formatter gave
expect(column.getValue(undefined, mockDataSet, 42))
.toEqual(TEST_DOMAIN_VALUE);
// Make sure that service interactions were as expected
expect(mockFormatter.formatDomainValue)
.toHaveBeenCalledWith(402513731000);
expect(mockFormatter.formatRangeValue)
.not.toHaveBeenCalled();
});
});
}
);

View File

@@ -0,0 +1,110 @@
/*****************************************************************************
* 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,waitsFor,jasmine*/
/**
* EventSpec. Created by shale on 06/24/2015.
*/
define(
["../src/EventListController"],
function (EventListController) {
"use strict";
describe("The event list controller", function () {
var mockScope,
mockTelemetry,
testMetadata,
controller;
beforeEach(function () {
mockScope = jasmine.createSpyObj(
"$scope",
[ "$on", "$watch" ]
);
mockTelemetry = jasmine.createSpyObj(
"telemetryController",
[ "getResponse", "getMetadata", "getTelemetryObjects" ]
);
testMetadata = [
{
domains: [
{ key: "d0", name: "D0" },
{ key: "d1", name: "D1" }
],
ranges: [
{ key: "r0", name: "R0" },
{ key: "r1", name: "R1" }
]
},
{
domains: [
{ key: "d0", name: "D0" },
{ key: "d2", name: "D2" }
],
ranges: [
{ key: "r0", name: "R0" }
]
}
];
mockTelemetry.getMetadata.andReturn(testMetadata);
mockTelemetry.getResponse.andReturn([]);
mockTelemetry.getTelemetryObjects.andReturn([]);
mockScope.telemetry = mockTelemetry;
controller = new EventListController(mockScope);
});
it("listens for telemetry data updates", function () {
expect(mockScope.$on).toHaveBeenCalledWith(
"telemetryUpdate",
jasmine.any(Function)
);
});
it("watches for telemetry controller changes", function () {
expect(mockScope.$watch).toHaveBeenCalledWith(
"telemetry",
jasmine.any(Function)
);
});
it("provides a column for each unique domain and range", function () {
// Should have five columns based on metadata above,
// (d0, d1, d2, r0, r1)
mockScope.$watch.mostRecentCall.args[1](mockTelemetry);
expect(mockScope.headers).toEqual(["D0", "D1", "D2", "R0", "R1"]);
});
it("does not throw if telemetry controller is undefined", function () {
// Just a general robustness check
mockScope.telemetry = undefined;
expect(mockScope.$watch.mostRecentCall.args[1])
.not.toThrow();
});
it("provides default columns if domain/range metadata is unavailable", function () {
mockTelemetry.getMetadata.andReturn([]);
mockScope.$watch.mostRecentCall.args[1](mockTelemetry);
expect(mockScope.headers).toEqual(["Time", "Message"]);
});
});
}
);

View File

@@ -0,0 +1,103 @@
/*****************************************************************************
* 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,waitsFor,jasmine*/
/**
* EventSpec. Created by shale on 06/24/2015.
*/
define(
["../src/EventListPopulator"],
function (EventListPopulator) {
"use strict";
describe("The event list populator", function () {
var mockColumns,
mockDatas,
mockDomainObjects,
populator;
function makeMockColumn(name, index) {
var mockColumn = jasmine.createSpyObj(
"column" + index,
[ "getTitle", "getValue" ]
);
mockColumn.getTitle.andReturn(name);
mockColumn.getValue.andCallFake(function (obj, data, i) {
return data.getDomainValue(i);
});
return mockColumn;
}
function makeMockData(bias, index) {
var mockData = jasmine.createSpyObj(
"data" + index,
[ "getDomainValue", "getPointCount" ]
);
mockData.getPointCount.andReturn(1000);
mockData.getDomainValue.andCallFake(function (i) {
return i + bias;
});
return mockData;
}
function makeMockDomainObject(name, index) {
var mockDomainObject = jasmine.createSpyObj(
"domainObject" + index,
[ "getId", "getModel" ]
);
return mockDomainObject;
}
beforeEach(function () {
mockColumns = ["A", "B", "C", "D"].map(makeMockColumn);
mockDatas = [ 10, 0, 3 ].map(makeMockData);
mockDomainObjects = ["A", "B", "C"].map(makeMockDomainObject);
populator = new EventListPopulator(mockColumns);
});
it("returns column headers", function () {
expect(populator.getHeaders()).toEqual(["A", "B", "C", "D"]);
});
it("provides rows on request, with all columns in each row", function () {
var rows = populator.getRows(mockDatas, mockDomainObjects, 84);
expect(rows.length).toEqual(84);
rows.forEach(function (row) {
expect(row.length).toEqual(4); // number of columns
});
});
it("returns rows in most-recent-last order", function () {
var rows = populator.getRows(mockDatas, mockDomainObjects, 84),
previous = Number.NEGATIVE_INFINITY;
// Should always be most-recent-last
rows.forEach(function (row) {
expect(row[0]).not.toBeLessThan(previous);
previous = row[0];
});
});
});
}
);

View File

@@ -0,0 +1,81 @@
/*****************************************************************************
* 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,waitsFor,jasmine*/
/**
* EventSpec. Created by vwoeltje on 11/6/14. Modified by shale on 06/23/2015.
*/
define(
["../src/RangeColumn"],
function (RangeColumn) {
"use strict";
var TEST_RANGE_VALUE = "some formatted range value";
describe("An event list range column", function () {
var mockDataSet,
testMetadata,
mockFormatter,
column;
beforeEach(function () {
mockDataSet = jasmine.createSpyObj(
"data",
[ "getRangeValue" ]
);
mockFormatter = jasmine.createSpyObj(
"formatter",
[ "formatDomainValue", "formatRangeValue" ]
);
testMetadata = {
key: "testKey",
name: "Test Name"
};
mockFormatter.formatRangeValue.andReturn(TEST_RANGE_VALUE);
column = new RangeColumn(testMetadata, mockFormatter);
});
it("reports a column header from range metadata", function () {
expect(column.getTitle()).toEqual("Test Name");
});
it("looks up data from a data set", function () {
column.getValue(undefined, mockDataSet, 42);
expect(mockDataSet.getRangeValue)
.toHaveBeenCalledWith(42, "testKey");
});
it("formats range values as time", function () {
mockDataSet.getRangeValue.andReturn(123.45678);
expect(column.getValue(undefined, mockDataSet, 42))
.toEqual(TEST_RANGE_VALUE);
// Make sure that service interactions were as expected
expect(mockFormatter.formatRangeValue)
.toHaveBeenCalledWith(123.45678);
expect(mockFormatter.formatDomainValue)
.not.toHaveBeenCalled();
});
});
}
);

View File

@@ -0,0 +1,81 @@
/*****************************************************************************
* 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*/
/**
* EventSpec. Created by shale on 06/24/2015.
*/
define(
["../../src/policies/MessagesViewPolicy"],
function (MessagesViewPolicy) {
"use strict";
describe("The messages view policy", function () {
var mockDomainObject,
mockTelemetry,
telemetryType,
testType,
testView,
testMetadata,
policy;
beforeEach(function () {
testView = { key: "string" };
testMetadata = {};
mockDomainObject = jasmine.createSpyObj(
'domainObject',
['getModel', 'getCapability']
);
mockTelemetry = jasmine.createSpyObj(
'telemetry',
['getMetadata']
);
mockDomainObject.getModel.andCallFake(function (c) {
return {type: testType};
});
mockDomainObject.getCapability.andCallFake(function (c) {
return c === 'telemetry' ? mockTelemetry : undefined;
});
mockTelemetry.getMetadata.andReturn(testMetadata);
policy = new MessagesViewPolicy();
});
it("disallows the message view for objects without string telemetry", function () {
testMetadata.ranges = [ { format: 'notString' } ];
expect(policy.allow({ key: 'messages' }, mockDomainObject)).toBeFalsy();
});
it("allows the message view for objects with string telemetry", function () {
testMetadata.ranges = [ { format: 'string' } ];
expect(policy.allow({ key: 'messages' }, mockDomainObject)).toBeTruthy();
});
it("returns true when the current view is not the Messages view", function () {
expect(policy.allow({ key: 'notMessages' }, mockDomainObject)).toBeTruthy();
});
});
}
);

View File

@@ -0,0 +1,7 @@
[
"DomainColumn",
"EventListController",
"EventListPopulator",
"policies/MessagesViewPolicy",
"RangeColumn"
]

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"
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"
ng-show="ngModel.element.titled"
>
{{ngModel.name}}
</div>
<div
class="l-elem l-value"
ng-class="{ 'telem-only': !ngModel.element.titled }"
>
{{ngModel.value}}
</div>
</span>
</div>

View File

@@ -25,6 +25,12 @@
"implementation": "PlotController.js",
"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",
"modes/PlotModeOptions",
"modes/PlotOverlayMode",
"modes/PlotStackMode"
"modes/PlotStackMode",
"policies/PlotViewPolicy"
]

View File

@@ -0,0 +1,37 @@
{
"name": "Event Messages",
"description": "List of time-ordered event messages",
"extensions": {
"views": [
{
"key": "rtmessages",
"name": "RT Messages",
"glyph": "5",
"description": "Scrolling list of real time messages.",
"templateUrl": "templates/rtmessages.html",
"needs": [ "telemetry" ],
"delegation": true
}
],
"controllers": [
{
"key": "RTEventListController",
"implementation": "RTEventListController.js",
"depends": [ "$scope", "telemetryHandler", "telemetryFormatter" ]
}
],
"directives": [
{
"key": "mctRtDataTable",
"implementation": "directives/MCTRTDataTable.js",
"depends": [ "$window" ]
}
],
"policies": [
{
"category": "view",
"implementation": "policies/RTMessagesViewPolicy.js"
}
]
}
}

View File

@@ -0,0 +1,37 @@
<!--
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.
-->
<table class="tabular">
<thead>
<tr>
<th ng-repeat="header in headers">
{{header}}
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in rows">
<td ng-repeat="cell in row">
{{cell}}
</td>
</tr>
</tbody>
</table>

View File

@@ -0,0 +1,29 @@
<!--
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.
-->
<div class="w1">
<div class="w2"
ng-controller="RTEventListController as rtevent">
<mct-rt-data-table headers="rtevent.headers()" rows="rtevent.rows()" ascending-scroll="true"></mct-rt-data-table>
</div>
</div>

View File

@@ -0,0 +1,69 @@
/*****************************************************************************
* 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,moment*/
/**
* Module defining DomainColumn. Created by vwoeltje on 11/18/14.
*/
define(
[],
function () {
"use strict";
/**
* A column which will report telemetry domain values
* (typically, timestamps.) Used by the ScrollingListController.
*
* @constructor
* @param domainMetadata an object with the machine- and human-
* readable names for this domain (in `key` and `name`
* fields, respectively.)
* @param {TelemetryFormatter} telemetryFormatter the telemetry
* formatting service, for making values human-readable.
*/
function DomainColumn(telemetryFormatter) {
return {
/**
* Get the title to display in this column's header.
* @returns {string} the title to display
*/
getTitle: function () {
return "Time";
},
/**
* Get the text to display inside a row under this
* column.
* @returns {string} the text to display
*/
getValue: function (domainObject, handle) {
return {
text: telemetryFormatter.formatDomainValue(
handle.getDomainValue(domainObject)
)
};
}
};
}
return DomainColumn;
}
);

View File

@@ -0,0 +1,138 @@
/*****************************************************************************
* 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*/
/**
* Module defining RTEventListController.
* Created by shale on 06/25/2014. Based on RT Scrolling lists.
*/
define(
["./DomainColumn", "./RangeColumn"],
function (DomainColumn, RangeColumn) {
"use strict";
var ROW_COUNT = 100;
/**
* The RTEventListController is responsible for populating
* the contents of the messages view.
* @constructor
*/
function RTEventListController($scope, telemetryHandler, telemetryFormatter) {
var handle,
lastUpdated = {},
lastIds = [],
columns = [],
headers = [],
rows = [];
function getTelemetryObjects() {
return handle ? handle.getTelemetryObjects() : [];
}
function idsChanged(telemetryObjects) {
function mismatch(id, index) {
return id !== telemetryObjects[index].getId();
}
return lastIds.length !== telemetryObjects.length ||
lastIds.some(mismatch);
}
function setupColumns(telemetryObjects) {
var id = $scope.domainObject && $scope.domainObject.getId(),
firstId =
telemetryObjects[0] && telemetryObjects[0].getId();
columns = [];
columns.push(new DomainColumn(telemetryFormatter));
columns.push(new RangeColumn());
headers = columns.map(function (column) {
return column.getTitle();
});
}
function updateObjects(telemetryObjects) {
if (idsChanged(telemetryObjects)) {
setupColumns(telemetryObjects);
lastIds = telemetryObjects.map(function (telemetryObject) {
return telemetryObject.getId();
});
}
}
function addRow(telemetryObject) {
var id = telemetryObject.getId(),
domainValue = handle.getDomainValue(telemetryObject);
if (lastUpdated[id] !== domainValue &&
domainValue !== undefined) {
// Instead of unshift (scrolling), use push (messages)
rows.push(columns.map(function (column) {
return column.getValue(telemetryObject, handle).text;
}));
// Remove first rows when adding past the max rows limit
//rows.splice(ROW_COUNT, Number.MAX_VALUE);
rows.splice(0, rows.length - ROW_COUNT);
lastUpdated[id] = domainValue;
}
}
function updateValues() {
getTelemetryObjects().forEach(addRow);
}
function releaseSubscription() {
if (handle) {
handle.unsubscribe();
}
}
function makeSubscription(domainObject) {
releaseSubscription();
rows = [];
handle = telemetryHandler.handle(
domainObject,
updateValues,
true
);
}
$scope.$on("$destroy", releaseSubscription);
$scope.$watch("domainObject", makeSubscription);
$scope.$watch(getTelemetryObjects, updateObjects);
return {
rows: function () {
return rows;
},
headers: function () {
return headers;
}
};
}
return RTEventListController;
}
);

View File

@@ -0,0 +1,68 @@
/*****************************************************************************
* 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,moment*/
/**
* Module defining DomainColumn.
* Created by vwoeltje on 11/18/14. Modified by shale on 06/25/2015.
*/
define(
[],
function () {
"use strict";
/**
* A column which will report telemetry range values
* (typically, measurements.) Used by the RTScrollingListController.
*
* @constructor
* @param rangeMetadata an object with the machine- and human-
* readable names for this range (in `key` and `name`
* fields, respectively.)
* @param {TelemetryFormatter} telemetryFormatter the telemetry
* formatting service, for making values human-readable.
*/
function RangeColumn() {
return {
/**
* Get the title to display in this column's header.
* @returns {string} the title to display
*/
getTitle: function () {
return "Message";
},
/**
* Get the text to display inside a row under this
* column.
* @returns {string} the text to display
*/
getValue: function (domainObject, handle) {
return {
text: handle.getRangeValue(domainObject)
};
}
};
}
return RangeColumn;
}
);

View File

@@ -0,0 +1,74 @@
/*****************************************************************************
* 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 MCTRTDataTable. Created by shale on 06/25/2015.
*/
define(
[],
function () {
"use strict";
function MCTRTDataTable($window) {
return {
restrict: "E",
templateUrl: "platform/features/rtevents/res/templates/mct-rt-data-table.html",
scope: {
headers: "=",
rows: "=",
ascendingScroll: "="
},
link: function ($scope, $element) {
var currentHeight,
previousHeight,
scrollParent;
// If the scroll is set to ascending, we want to
// check when elements are added to the table, and move the scroll
// bar accordingly.
// (When viewing at the bottom of the page, the scroll bar will
// stay at the bottom despite additions to the table)
if ($scope.ascendingScroll) {
$scope.$watchCollection("rows", function () {
// Wait until the page as been repainted (otherwise the
// height will always be zero)
$window.requestAnimationFrame(function () {
previousHeight = currentHeight;
// The height of the table body
currentHeight = $element[0].firstElementChild.firstElementChild.nextElementSibling.clientHeight;
// One of the parents is a div that has vscroll
scrollParent = $element[0].parentElement.parentElement.parentElement.parentElement.parentElement;
// Move the scrollbar down the amount that the height has changed
scrollParent.scrollTop = scrollParent.scrollTop + (currentHeight - previousHeight);
});
});
}
}
};
}
return MCTRTDataTable;
}
);

View File

@@ -0,0 +1,75 @@
/*****************************************************************************
* 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*/
/**
* Module defining MessagesViewPolicy. Created by shale on 06/24/2015.
*/
define(
[],
function () {
"use strict";
/**
* Policy controlling when the Messages view should be avaliable.
* @constructor
*/
function RTMessagesViewPolicy() {
function hasStringTelemetry(domainObject) {
var telemetry = domainObject &&
domainObject.getCapability('telemetry'),
metadata = telemetry ? telemetry.getMetadata() : {},
data = telemetry ? telemetry.requestData() : {},
ranges = metadata.ranges || [];
return ranges.some(function (range) {
return range.format === 'string';
});
}
return {
/**
* Check whether or not a given action is allowed by this
* policy.
* @param {Action} action the action
* @param domainObject the domain object which will be viewed
* @returns {boolean} true if not disallowed
*/
allow: function (view, domainObject) {
// This policy only applies for the RT Messages view
if (view.key === 'rtmessages') {
// The Messages view is allowed only if the domain
// object has string telemetry
if (!hasStringTelemetry(domainObject)) {
return false;
}
}
// Like all policies, allow by default.
return true;
}
};
}
return RTMessagesViewPolicy;
}
);

View File

View File

@@ -23,7 +23,7 @@
<div class="w2"
ng-controller="ScrollingListController">
<!-- To add filtering, add class 'filterable' to <table> and uncomment 2nd <tr> in <thead> -->
<table class="tabular">
<table class="tabular fixed-header">
<thead>
<tr>
<th ng-repeat="header in headers">