[Tables] Tests and style fixes

This commit is contained in:
Henry
2017-01-26 10:59:22 -08:00
parent ef8efbd53d
commit a3311e4c57
15 changed files with 970 additions and 1079 deletions

View File

@@ -52,23 +52,28 @@ define(
metadata.forEach(function (metadatum) {
var formatter = telemetryApi.getValueFormatter(metadatum);
self.addColumn({
metadata: metadatum,
self.columns.push({
getKey: function () {
return metadatum.key;
},
getTitle: function () {
return metadatum.name;
},
getValue: function(telemetryDatum, limitEvaluator) {
getValue: function (telemetryDatum, limitEvaluator) {
var isValueColumn = !!(metadatum.hints.y || metadatum.hints.range);
var alarm = isValueColumn &&
limitEvaluator &&
limitEvaluator.evaluate(telemetryDatum, metadatum);
return {
cssClass: alarm && alarm.cssClass,
var value = {
text: formatter ? formatter.format(telemetryDatum[metadatum.key])
: telemetryDatum[metadatum.key],
value: telemetryDatum[metadatum.key]
};
if (alarm) {
value.cssClass = alarm.cssClass;
}
return value;
}
});
});
@@ -76,36 +81,13 @@ define(
return this;
};
/**
* Add a column definition to this Table
* @param {RangeColumn | DomainColumn | NameColumn} column
* @param {Number} [index] Where the column should appear (will be
* affected by column filtering)
*/
TableConfiguration.prototype.addColumn = function (column, index) {
if (typeof index === 'undefined') {
this.columns.push(column);
} else {
this.columns.splice(index, 0, column);
}
};
/**
* @private
* @param column
* @returns {*|string}
*/
TableConfiguration.prototype.getColumnTitle = function (column) {
return column.getTitle();
};
/**
* Get a simple list of column titles
* @returns {Array} The titles of the columns
*/
TableConfiguration.prototype.getHeaders = function () {
return this.columns.map(function (column, i) {
return column.getTitle()|| 'Column ' + (i + 1);
return column.getTitle() || 'Column ' + (i + 1);
});
};
@@ -118,16 +100,15 @@ define(
* title, and the value is the formatted value from the provided datum.
*/
TableConfiguration.prototype.getRowValues = function (limitEvaluator, datum) {
var self = this;
return this.columns.reduce(function (rowObject, column, i) {
var columnTitle = self.getColumnTitle(column) || 'Column ' + (i + 1),
var columnTitle = column.getTitle() || 'Column ' + (i + 1),
columnValue = column.getValue(datum, limitEvaluator);
if (columnValue !== undefined && columnValue.text === undefined) {
columnValue.text = '';
}
// Don't replace something with nothing.
// This occurs when there are multiple columns with the
// This occurs when there are multiple columns with the same
// column title
if (rowObject[columnTitle] === undefined ||
rowObject[columnTitle].text === undefined ||

View File

@@ -26,6 +26,10 @@ define(
'EventEmitter'
],
function (_, EventEmitter) {
/**
* @constructor
*/
function TelemetryCollection() {
EventEmitter.call(this, arguments);
this.telemetry = [];
@@ -33,7 +37,7 @@ define(
this.sortField = undefined;
this.lastBounds = {};
_.bindAll(this,[
_.bindAll(this, [
'addOne',
'iteratee'
]);
@@ -41,15 +45,22 @@ define(
TelemetryCollection.prototype = Object.create(EventEmitter.prototype);
TelemetryCollection.prototype.iteratee = function (element) {
return _.get(element, this.sortField);
TelemetryCollection.prototype.iteratee = function (item) {
return _.get(item, this.sortField);
};
/**
* This function is optimized for ticking - it assumes that start and end bounds
* will only increase and as such this cannot be used for decreasing bounds changes.
* For arbitrary bounds changes, it's assumed that a telemetry requery is performed anyway, and the
* collection is cleared and repopulated.
* This function is optimized for ticking - it assumes that start and end
* bounds will only increase and as such this cannot be used for decreasing
* bounds changes.
*
* An implication of this is that data will not be discarded that exceeds
* the given end bounds. For arbitrary bounds changes, it's assumed that
* a telemetry requery is performed anyway, and the collection is cleared
* and repopulated.
*
* @fires TelemetryCollection#added
* @fires TelemetryCollection#discarded
* @param bounds
*/
TelemetryCollection.prototype.bounds = function (bounds) {
@@ -57,56 +68,92 @@ define(
var endChanged = this.lastBounds.end !== bounds.end;
var startIndex = 0;
var endIndex = 0;
var discarded = undefined;
var added = undefined;
var discarded;
var added;
var testValue;
if (startChanged){
var testValue = _.set({}, this.sortField, bounds.start);
// Calculate the new index of the first element within the bounds
// If collection is not sorted by a time field, we cannot respond to
// bounds events
if (this.sortField === undefined) {
return;
}
if (startChanged) {
testValue = _.set({}, this.sortField, bounds.start);
// Calculate the new index of the first item within the bounds
startIndex = _.sortedIndex(this.telemetry, testValue, this.sortField);
discarded = this.telemetry.splice(0, startIndex);
}
if (endChanged) {
var testValue = _.set({}, this.sortField, bounds.end);
// Calculate the new index of the last element in bounds
testValue = _.set({}, this.sortField, bounds.end);
// Calculate the new index of the last item in bounds
endIndex = _.sortedLastIndex(this.highBuffer, testValue, this.sortField);
added = this.highBuffer.splice(0, endIndex);
this.telemetry = this.telemetry.concat(added);
}
if (discarded && discarded.length > 0){
if (discarded && discarded.length > 0) {
/**
* A `discarded` event is thrown when telemetry data fall out of
* bounds due to a bounds change event
* @type {object[]} discarded the telemetry data
* discarded as a result of the bounds change
*/
this.emit('discarded', discarded);
}
if (added && added.length > 0) {
/**
* An `added` event is thrown when a bounds change results in
* received telemetry falling within the new bounds.
* @type {object[]} added the telemetry data that is now within bounds
*/
this.emit('added', added);
}
this.lastBounds = bounds;
};
TelemetryCollection.prototype.inBounds = function (element) {
/**
* Determines is a given telemetry datum is within the bounds currently
* defined for this telemetry collection.
* @private
* @param datum
* @returns {boolean}
*/
TelemetryCollection.prototype.inBounds = function (datum) {
var noBoundsDefined = !this.lastBounds || (this.lastBounds.start === undefined && this.lastBounds.end === undefined);
var withinBounds =
_.get(element, this.sortField) >= this.lastBounds.start &&
_.get(element, this.sortField) <= this.lastBounds.end;
_.get(datum, this.sortField) >= this.lastBounds.start &&
_.get(datum, this.sortField) <= this.lastBounds.end;
return noBoundsDefined || withinBounds;
};
/**
* Adds an individual item to the collection. Used internally only
* @private
* @param element
* @param item
*/
TelemetryCollection.prototype.addOne = function (element) {
TelemetryCollection.prototype.addOne = function (item) {
var isDuplicate = false;
var boundsDefined = this.lastBounds && (this.lastBounds.start && this.lastBounds.end);
var boundsDefined = this.lastBounds &&
(this.lastBounds.start !== undefined && this.lastBounds.end !== undefined);
var array;
var boundsLow;
var boundsHigh;
// If collection is not sorted by a time field, we cannot respond to
// bounds events, so no bounds checking necessary
if (this.sortField === undefined) {
this.telemetry.push(item);
return true;
}
// Insert into either in-bounds array, or the out of bounds high buffer.
// Data in the high buffer will be re-evaluated for possible insertion on next tick
if (boundsDefined) {
var boundsHigh = _.get(element, this.sortField) > this.lastBounds.end;
var boundsLow = _.get(element, this.sortField) < this.lastBounds.start;
boundsHigh = _.get(item, this.sortField) > this.lastBounds.end;
boundsLow = _.get(item, this.sortField) < this.lastBounds.start;
if (!boundsHigh && !boundsLow) {
array = this.telemetry;
@@ -119,26 +166,26 @@ define(
// If out of bounds low, disregard data
if (!boundsLow) {
// Going to check for duplicates. Bound the search problem to
// elements around the given time. Use sortedIndex because it
// items around the given time. Use sortedIndex because it
// employs a binary search which is O(log n). Can use binary search
// based on time stamp because the array is guaranteed ordered due
// to sorted insertion.
var startIx = _.sortedIndex(array, element, this.sortField);
var startIx = _.sortedIndex(array, item, this.sortField);
if (startIx !== array.length) {
var endIx = _.sortedLastIndex(array, element, this.sortField);
var endIx = _.sortedLastIndex(array, item, this.sortField);
// Create an array of potential dupes, based on having the
// same time stamp
var potentialDupes = array.slice(startIx, endIx + 1);
// Search potential dupes for exact dupe
isDuplicate = _.findIndex(potentialDupes, _.isEqual.bind(undefined, element)) > -1;
isDuplicate = _.findIndex(potentialDupes, _.isEqual.bind(undefined, item)) > -1;
}
if (!isDuplicate) {
array.splice(startIx, 0, element);
array.splice(startIx, 0, item);
//Return true if it was added and in bounds
return array === this.telemetry;
@@ -147,28 +194,60 @@ define(
return false;
};
TelemetryCollection.prototype.addAll = function (elements) {
var added = elements.filter(this.addOne);
/**
* Add an array of objects to this telemetry collection
* @fires TelemetryCollection#added
* @param {object[]} items
*/
TelemetryCollection.prototype.add = function (items) {
var added = items.filter(this.addOne);
this.emit('added', added);
};
//Todo: addAll for initial historical data
TelemetryCollection.prototype.add = function (element) {
if (this.addOne(element)){
this.emit('added', [element]);
return true;
} else {
return false;
}
};
/**
* Clears the contents of the telemetry collection
*/
TelemetryCollection.prototype.clear = function () {
this.telemetry = [];
};
TelemetryCollection.prototype.sort = function (sortField){
/**
* Sorts the telemetry collection based on the provided sort field
* specifier.
* @example
* // First build some mock telemetry for the purpose of an example
* let now = Date.now();
* let telemetry = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(function (value) {
* return {
* // define an object property to demonstrate nested paths
* timestamp: {
* ms: now - value * 1000,
* text:
* },
* value: value
* }
* });
* let collection = new TelemetryCollection();
*
* collection.add(telemetry);
*
* // Sort by telemetry value
* collection.sort("value");
*
* // Sort by ms since epoch
* collection.sort("timestamp.ms");
*
* // Sort by formatted date text
* collection.sort("timestamp.text");
*
*
* @param {string} sortField An object property path.
*/
TelemetryCollection.prototype.sort = function (sortField) {
this.sortField = sortField;
this.telemetry = _.sortBy(this.telemetry, this.iteratee);
if (sortField !== undefined) {
this.telemetry = _.sortBy(this.telemetry, this.iteratee);
}
};
return TelemetryCollection;

View File

@@ -1,7 +1,10 @@
define(
['zepto'],
function ($) {
[
'zepto',
'lodash'
],
function ($, _) {
/**
* A controller for the MCTTable directive. Populates scope with
@@ -134,7 +137,7 @@ define(
*/
$scope.$watch('defaultSort', function (newColumn, oldColumn) {
if (newColumn !== oldColumn) {
$scope.toggleSort(newColumn)
$scope.toggleSort(newColumn);
}
});
@@ -163,7 +166,7 @@ define(
}
}.bind(this));
$scope.$on('$destroy', function() {
$scope.$on('$destroy', function () {
this.scrollable.off('scroll', this.onScroll);
this.destroyConductorListeners();
@@ -172,7 +175,7 @@ define(
delete this.$scope;
}.bind(this));
};
}
MCTTableController.prototype.destroyConductorListeners = function () {
this.conductor.off('timeSystem', this.changeTimeSystem);
@@ -227,7 +230,7 @@ define(
*/
MCTTableController.prototype.removeRows = function (event, rows) {
var indexInDisplayRows;
rows.forEach(function (row){
rows.forEach(function (row) {
// Do a sequential search here. Only way of finding row is by
// object equality, so array is in effect unsorted.
indexInDisplayRows = this.$scope.displayRows.indexOf(row);
@@ -252,7 +255,7 @@ define(
* @private
*/
MCTTableController.prototype.onScroll = function (event) {
requestAnimationFrame(function () {
this.$window.requestAnimationFrame(function () {
this.setVisibleRows();
this.digest();
@@ -344,18 +347,11 @@ define(
this.$scope.visibleRows[this.$scope.visibleRows.length - 1]
.rowIndex === end) {
return this.digest();
//return Promise.resolve(); // don't update if no changes are required.
}
}
//Set visible rows from display rows, based on calculated offset.
this.$scope.visibleRows = this.$scope.displayRows.slice(start, end)
.map(function (row, i) {
/* var formattedRow = JSON.parse(JSON.stringify(row));
if (self.$scope.formatCell) {
Object.keys(formattedRow).forEach(function (header) {
formattedRow[header].text = self.$scope.formatCell(header, row[header].text);
});
} */
return {
rowIndex: start + i,
offsetY: ((start + i) * self.$scope.rowHeight) +
@@ -585,19 +581,20 @@ define(
MCTTableController.prototype.digest = function () {
var scope = this.$scope;
var self = this;
var requestAnimationFrame = this.$window.requestAnimationFrame;
var raf = this.$window.requestAnimationFrame;
var promise = this.digestPromise;
if (!this.digestPromise) {
this.digestPromise = new Promise(function (resolve) {
requestAnimationFrame(function() {
if (!promise) {
self.digestPromise = promise = new Promise(function (resolve) {
raf(function () {
scope.$digest();
delete self.digestPromise;
self.digestPromise = undefined;
resolve();
});
});
}
return this.digestPromise;
return promise;
};
/**
@@ -640,8 +637,10 @@ define(
}
this.$scope.displayRows = this.filterAndSort(newRows || []);
this.resize(newRows)
.then(this.setVisibleRows)
return this.resize(newRows)
.then(function (rows) {
return this.setVisibleRows(rows);
}.bind(this))
//Timeout following setVisibleRows to allow digest to
// perform DOM changes, otherwise scrollTo won't work.
.then(function () {
@@ -692,6 +691,7 @@ define(
};
/**
* Scroll the view to a given row index
* @param displayRowIndex {number} The index in the displayed rows
* to scroll to.
*/

View File

@@ -19,6 +19,7 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/* global console*/
/**
* This bundle adds a table view for displaying telemetry data.
@@ -28,10 +29,11 @@ define(
[
'../TableConfiguration',
'../../../../../src/api/objects/object-utils',
'../TelemetryCollection'
'../TelemetryCollection',
'lodash'
],
function (TableConfiguration, objectUtils, TelemetryCollection) {
function (TableConfiguration, objectUtils, TelemetryCollection, _) {
/**
* The TableController is responsible for getting data onto the page
@@ -46,6 +48,7 @@ define(
$timeout,
openmct
) {
this.$scope = $scope;
this.$timeout = $timeout;
this.openmct = openmct;
@@ -55,14 +58,14 @@ define(
* Initialization block
*/
this.columns = {}; //Range and Domain columns
this.deregisterListeners = [];
this.unobserveObject = undefined;
this.subscriptions = [];
this.timeColumns = [];
$scope.rows = [];
this.table = new TableConfiguration($scope.domainObject,
openmct);
this.lastBounds = this.openmct.conductor.bounds();
this.requestTime = 0;
this.lastRequestTime = 0;
this.telemetry = new TelemetryCollection();
/*
@@ -81,38 +84,45 @@ define(
'changeBounds',
'setScroll',
'addRowsToTable',
'removeRowsFromTable',
'removeRowsFromTable'
]);
this.getData();
this.registerChangeListeners();
// Retrieve data when domain object is available.
// Also deferring telemetry request makes testing easier as controller
// construction has no unintended consequences.
$scope.$watch("domainObject", function () {
this.getData();
this.registerChangeListeners();
}.bind(this));
this.openmct.conductor.on('follow', this.setScroll);
this.setScroll(this.openmct.conductor.follow());
this.telemetry.on('added', this.addRowsToTable);
this.telemetry.on('discarded', this.removeRowsFromTable);
this.$scope.$on("$destroy", this.destroy);
}
TelemetryTableController.prototype.setScroll = function (scroll){
/**
* @private
* @param {boolean} scroll
*/
TelemetryTableController.prototype.setScroll = function (scroll) {
this.$scope.autoScroll = scroll;
};
/**
* Based on the selected time system, find a matching domain column
* to sort by. By default will just match on key.
* @param timeSystem
*
* @private
* @param {TimeSystem} timeSystem
*/
TelemetryTableController.prototype.sortByTimeSystem = function (timeSystem) {
var scope = this.$scope;
var sortColumn = undefined;
var sortColumn;
scope.defaultSort = undefined;
if (timeSystem) {
this.table.columns.forEach(function (column) {
if (column.metadata.key === timeSystem.metadata.key) {
if (column.getKey() === timeSystem.metadata.key) {
sortColumn = column;
}
});
@@ -124,44 +134,66 @@ define(
};
/**
* Attach listeners to domain object to respond to changes due to
* composition, etc.
* Attaches listeners that respond to state change in domain object,
* conductor, and receipt of telemetry
*
* @private
*/
TelemetryTableController.prototype.registerChangeListeners = function () {
this.deregisterListeners.forEach(function (deregister){
deregister();
});
this.deregisterListeners = [];
if (this.unobserveObject) {
this.unobserveObject();
}
this.deregisterListeners.push(
this.openmct.objects.observe(this.newObject, "*",
function (domainObject){
this.unobserveObject = this.openmct.objects.observe(this.newObject, "*",
function (domainObject) {
this.newObject = domainObject;
this.getData();
}.bind(this)
)
);
);
this.openmct.conductor.on('timeSystem', this.sortByTimeSystem);
this.openmct.conductor.on('bounds', this.changeBounds);
this.openmct.conductor.on('follow', this.setScroll);
this.telemetry.on('added', this.addRowsToTable);
this.telemetry.on('discarded', this.removeRowsFromTable);
};
/**
* On receipt of new telemetry, informs mct-table directive that new rows
* are available and passes populated rows to it
*
* @private
* @param rows
*/
TelemetryTableController.prototype.addRowsToTable = function (rows) {
this.$scope.$broadcast('add:rows', rows);
};
/**
* When rows are to be removed, informs mct-table directive. Row removal
* happens when rows call outside the bounds of the time conductor
*
* @private
* @param rows
*/
TelemetryTableController.prototype.removeRowsFromTable = function (rows) {
this.$scope.$broadcast('remove:rows', rows);
};
/**
* On Time Conductor bounds change, update displayed telemetry. In the
* case of a tick, previously visible telemetry that is now out of band
* will be removed from the table.
* @param {openmct.TimeConductorBounds~TimeConductorBounds} bounds
*/
TelemetryTableController.prototype.changeBounds = function (bounds) {
//console.log('bounds.end: ' + bounds.end);
var follow = this.openmct.conductor.follow();
var isTick = follow &&
bounds.start !== this.lastBounds.start &&
bounds.end !== this.lastBounds.end;
if (isTick){
if (isTick) {
this.telemetry.bounds(bounds);
} else {
// Is fixed bounds change
@@ -171,7 +203,7 @@ define(
};
/**
* Release the current subscription (called when scope is destroyed)
* Clean controller, deregistering listeners etc.
*/
TelemetryTableController.prototype.destroy = function () {
@@ -182,11 +214,11 @@ define(
this.subscriptions.forEach(function (subscription) {
subscription();
});
this.deregisterListeners.forEach(function (deregister){
deregister();
});
if (this.unobserveObject) {
this.unobserveObject();
}
this.subscriptions = [];
this.deregisterListeners = [];
if (this.timeoutHandle) {
this.$timeout.cancel(this.timeoutHandle);
@@ -200,9 +232,10 @@ define(
};
/**
* For given objects, populate column metadata and table headers.
* @private
* @param objects
* @returns {*}
* @param {module:openmct.DomainObject[]} objects the domain objects for
* which columns should be populated
*/
TelemetryTableController.prototype.loadColumns = function (objects) {
var telemetryApi = this.openmct.telemetry;
@@ -220,25 +253,28 @@ define(
this.filterColumns();
// Default to no sort on underlying telemetry collection. Sorting
// is necessary to do bounds filtering, but this is only possible
// if data matches selected time system
this.telemetry.sort(undefined);
var timeSystem = this.openmct.conductor.timeSystem();
if (timeSystem) {
this.sortByTimeSystem(timeSystem);
}
if (!this.telemetry.sortColumn && domainColumns.length > 0) {
this.telemetry.sort(domainColumns[0].name + '.value');
}
}
return objects;
};
/**
* Request telemetry data from an historical store for given objects.
* @private
* @param objects The domain objects to request telemetry for
* @returns {*|{configFile}|app|boolean|Route|Object}
* @param {object[]} The domain objects to request telemetry for
* @returns {Promise} resolved when historical data is available
*/
TelemetryTableController.prototype.getHistoricalData = function (objects) {
var self = this;
var openmct = this.openmct;
var bounds = openmct.conductor.bounds();
var scope = this.$scope;
@@ -247,15 +283,22 @@ define(
var requestTime = this.lastRequestTime = Date.now();
var telemetryCollection = this.telemetry;
return new Promise(function (resolve, reject){
function finishProcessing(){
telemetryCollection.addAll(rowData);
var promise = new Promise(function (resolve, reject) {
/*
* On completion of batched processing, set the rows on scope
*/
function finishProcessing() {
telemetryCollection.add(rowData);
scope.rows = telemetryCollection.telemetry;
scope.loading = false;
resolve(scope.rows);
}
function processData(historicalData, index, limitEvaluator){
/*
* Process a batch of historical data
*/
function processData(historicalData, index, limitEvaluator) {
if (index >= historicalData.length) {
processedObjects++;
@@ -263,51 +306,57 @@ define(
finishProcessing();
}
} else {
rowData = rowData.concat(historicalData.slice(index, index + this.batchSize)
.map(this.table.getRowValues.bind(this.table, limitEvaluator)));
rowData = rowData.concat(historicalData.slice(index, index + self.batchSize)
.map(self.table.getRowValues.bind(self.table, limitEvaluator)));
this.timeoutHandle = this.$timeout(processData.bind(
this,
historicalData,
index + this.batchSize,
limitEvaluator
));
/*
Use timeout to yield process to other UI activities. On
return, process next batch
*/
self.timeoutHandle = self.$timeout(function () {
processData(historicalData, index + self.batchSize, limitEvaluator);
});
}
}
function makeTableRows(object, historicalData) {
// Only process one request at a time
if (requestTime === this.lastRequestTime) {
// Only process the most recent request
if (requestTime === self.lastRequestTime) {
var limitEvaluator = openmct.telemetry.limitEvaluator(object);
processData.call(this, historicalData, 0, limitEvaluator);
processData(historicalData, 0, limitEvaluator);
} else {
resolve(rowData);
}
}
function requestData (object) {
/*
Use the telemetry API to request telemetry for a given object
*/
function requestData(object) {
return openmct.telemetry.request(object, {
start: bounds.start,
end: bounds.end
}).then(makeTableRows.bind(this, object))
}).then(makeTableRows.bind(undefined, object))
.catch(reject);
}
this.$timeout.cancel(this.timeoutHandle);
if (objects.length > 0){
objects.forEach(requestData.bind(this));
if (objects.length > 0) {
objects.forEach(requestData);
} else {
scope.loading = false;
resolve([]);
}
}.bind(this));
return promise;
};
/**
* Subscribe to real-time data for the given objects.
* @private
* @param objects
* @returns {*}
* @param {object[]} objects The objects to subscribe to.
*/
TelemetryTableController.prototype.subscribeToNewData = function (objects) {
var telemetryApi = this.openmct.telemetry;
@@ -317,6 +366,8 @@ define(
var maxRows = Number.MAX_VALUE;
var limitEvaluator;
var added = false;
var scope = this.$scope;
var table = this.table;
this.subscriptions.forEach(function (subscription) {
subscription();
@@ -325,20 +376,20 @@ define(
function newData(domainObject, datum) {
limitEvaluator = telemetryApi.limitEvaluator(domainObject);
added = telemetryCollection.add(this.table.getRowValues(limitEvaluator, datum));
added = telemetryCollection.add([table.getRowValues(limitEvaluator, datum)]);
//Inform table that a new row has been added
if (this.$scope.rows.length > maxRows) {
this.$scope.$broadcast('remove:rows', this.$scope.rows[0]);
this.$scope.rows.shift();
if (scope.rows.length > maxRows) {
scope.$broadcast('remove:rows', scope.rows[0]);
scope.rows.shift();
}
if (!this.$scope.loading && added) {
this.$scope.$broadcast('add:row',
this.$scope.rows.length - 1);
if (!scope.loading && added) {
scope.$broadcast('add:row',
scope.rows.length - 1);
}
}
objects.forEach(function (object){
objects.forEach(function (object) {
this.subscriptions.push(
telemetryApi.subscribe(object, newData.bind(this, object), {}));
}.bind(this));
@@ -346,6 +397,12 @@ define(
return objects;
};
/**
* Request historical data, and subscribe to for real-time data.
* @private
* @returns {Promise} A promise that is resolved once subscription is
* established, and historical telemetry is received and processed.
*/
TelemetryTableController.prototype.getData = function () {
var telemetryApi = this.openmct.telemetry;
var compositionApi = this.openmct.composition;
@@ -359,41 +416,37 @@ define(
function error(e) {
scope.loading = false;
console.error(e);
console.error(e.stack);
}
function filterForTelemetry(objects){
function filterForTelemetry(objects) {
return objects.filter(telemetryApi.canProvideTelemetry.bind(telemetryApi));
}
function getDomainObjects() {
return new Promise(function (resolve, reject){
var objects = [newObject];
var composition = compositionApi.get(newObject);
var objects = [newObject];
var composition = compositionApi.get(newObject);
if (composition) {
composition
.load()
.then(function (children) {
return objects.concat(children);
})
.then(resolve)
.catch(reject);
} else {
return resolve(objects);
}
});
if (composition) {
return composition
.load()
.then(function (children) {
return objects.concat(children);
});
} else {
return Promise.resolve(objects);
}
}
scope.headers = [];
scope.rows = [];
getDomainObjects()
return getDomainObjects()
.then(filterForTelemetry)
.then(this.loadColumns)
.then(this.subscribeToNewData)
.then(this.getHistoricalData)
.catch(error)
.catch(error);
};
/**