From d304cc4343415bcc18c451a103f17b21ac512b25 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 2 Dec 2014 14:51:48 -0800 Subject: [PATCH] [Scrolling] Bring in scrolling list view Bring in scrolling list view from the sandbox branch in preparation for clean up, testing, and integration to complete transition of scrolling list views, WTD-534. --- platform/features/scrolling/bundle.json | 24 +++ .../scrolling/res/templates/scrolling.html | 25 +++ .../features/scrolling/src/DomainColumn.js | 31 ++++ platform/features/scrolling/src/NameColumn.js | 28 +++ .../features/scrolling/src/RangeColumn.js | 31 ++++ .../scrolling/src/ScrollingListController.js | 174 ++++++++++++++++++ 6 files changed, 313 insertions(+) create mode 100644 platform/features/scrolling/bundle.json create mode 100644 platform/features/scrolling/res/templates/scrolling.html create mode 100644 platform/features/scrolling/src/DomainColumn.js create mode 100644 platform/features/scrolling/src/NameColumn.js create mode 100644 platform/features/scrolling/src/RangeColumn.js create mode 100644 platform/features/scrolling/src/ScrollingListController.js diff --git a/platform/features/scrolling/bundle.json b/platform/features/scrolling/bundle.json new file mode 100644 index 0000000000..e2763b03fc --- /dev/null +++ b/platform/features/scrolling/bundle.json @@ -0,0 +1,24 @@ +{ + "name": "Scrolling Lists", + "description": "Time-ordered list of latest data.", + "extensions": { + "views": [ + { + "key": "scrolling", + "name": "Scrolling", + "description": "Scrolling list of data values.", + "templateUrl": "templates/scrolling.html", + "needs": [ "telemetry" ], + "delegation": true + } + ], + "controllers": [ + { + "key": "ScrollingListController", + "implementation": "ScrollingListController.js", + "depends": [ "$scope" ] + } + ] + } + +} \ No newline at end of file diff --git a/platform/features/scrolling/res/templates/scrolling.html b/platform/features/scrolling/res/templates/scrolling.html new file mode 100644 index 0000000000..a26fd6503e --- /dev/null +++ b/platform/features/scrolling/res/templates/scrolling.html @@ -0,0 +1,25 @@ +
+ +
+
+ +
+ +
+ {{header}}{{header}} +
+
+ +
+
+ {{cell}} +
+
+ +
+
+
+ + diff --git a/platform/features/scrolling/src/DomainColumn.js b/platform/features/scrolling/src/DomainColumn.js new file mode 100644 index 0000000000..7c8f03c788 --- /dev/null +++ b/platform/features/scrolling/src/DomainColumn.js @@ -0,0 +1,31 @@ +/*global define,Promise*/ + +/** + * Module defining DomainColumn. Created by vwoeltje on 11/18/14. + */ +define( + [], + function () { + "use strict"; + + /** + * + * @constructor + */ + function DomainColumn(domainMetadata) { + return { + getTitle: function () { + return domainMetadata.name; + }, + getValue: function (domainObject, data, index) { + return data.getDomainValue( + index, + domainMetadata.key + ); + } + }; + } + + return DomainColumn; + } +); \ No newline at end of file diff --git a/platform/features/scrolling/src/NameColumn.js b/platform/features/scrolling/src/NameColumn.js new file mode 100644 index 0000000000..a997b95d38 --- /dev/null +++ b/platform/features/scrolling/src/NameColumn.js @@ -0,0 +1,28 @@ +/*global define,Promise*/ + +/** + * Module defining NameColumn. Created by vwoeltje on 11/18/14. + */ +define( + [], + function () { + "use strict"; + + /** + * + * @constructor + */ + function NameColumn() { + return { + getTitle: function () { + return "Name"; + }, + getValue: function (domainObject) { + return domainObject.getModel().name; + } + }; + } + + return NameColumn; + } +); \ No newline at end of file diff --git a/platform/features/scrolling/src/RangeColumn.js b/platform/features/scrolling/src/RangeColumn.js new file mode 100644 index 0000000000..cf60f4ed80 --- /dev/null +++ b/platform/features/scrolling/src/RangeColumn.js @@ -0,0 +1,31 @@ +/*global define,Promise*/ + +/** + * Module defining DomainColumn. Created by vwoeltje on 11/18/14. + */ +define( + [], + function () { + "use strict"; + + /** + * + * @constructor + */ + function RangeColumn(rangeMetadata) { + return { + getTitle: function () { + return rangeMetadata.name; + }, + getValue: function (domainObject, data, index) { + return data.getRangeValue( + index, + rangeMetadata.key + ); + } + }; + } + + return RangeColumn; + } +); \ No newline at end of file diff --git a/platform/features/scrolling/src/ScrollingListController.js b/platform/features/scrolling/src/ScrollingListController.js new file mode 100644 index 0000000000..415a22eb67 --- /dev/null +++ b/platform/features/scrolling/src/ScrollingListController.js @@ -0,0 +1,174 @@ +/*global define,Promise*/ + +/** + * Module defining ListController. Created by vwoeltje on 11/18/14. + */ +define( + ["./NameColumn", "./DomainColumn", "./RangeColumn"], + function (NameColumn, DomainColumn, RangeColumn) { + "use strict"; + + var ROW_COUNT = 18; + + /** + * + * @constructor + */ + function ScrollingListController($scope) { + var columns = []; // Domain used + + /** + * 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} datas an array of the most recent + * data objects; expected to be in the same order + * as the domain objects provided at constructor + * @param {Array= 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 < ROW_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 { + break; // Ran out of candidates; not enough data points available + } + } + + return latest; + } + + function getRows(telemetry) { + var datas = telemetry.getResponse(), + objects = telemetry.getTelemetryObjects(), + values = getLatestDataValues(datas); + + return values.map(function (value) { + return columns.map(function (column) { + return column.getValue( + objects[value.objectIndex], + datas[value.objectIndex], + value.pointIndex + ); + }); + }); + } + + function updateRows() { + var telemetry = $scope.telemetry; + $scope.rows = telemetry ? getRows(telemetry) : []; + } + + function setupColumns() { + var telemetry = $scope.telemetry, + domainKeys = {}, + rangeKeys = {}, + metadata; + + function addDomain(domain) { + var key = domain.key; + if (key && !domainKeys[key]) { + columns.push(new DomainColumn(domain)); + } + } + + function addRange(range) { + var key = range.key; + if (key && !rangeKeys[key]) { + columns.push(new RangeColumn(range)); + } + } + + if (!telemetry) { + columns = []; + $scope.rows = []; + $scope.headers = []; + return; + } + + columns = [ new NameColumn() ]; + + // Add domain, range columns + metadata = telemetry.getMetadata(); + (metadata || []).forEach(function (metadata) { + (metadata.domains || []).forEach(addDomain); + (metadata.ranges || []).forEach(addRange); + }); + + // Add default domain, range columns if none + // were described in metadata. + if (Object.keys(domainKeys).length < 1) { + columns.push(new DomainColumn({ name: "Time" })); + } + if (Object.keys(rangeKeys).length < 1) { + columns.push(new RangeColumn({ name: "Value" })); + } + + $scope.headers = columns.map(function (column) { + return column.getTitle(); + }); + + updateRows(); + } + + $scope.$on("telemetryUpdate", updateRows); + $scope.$watch("telemetry", setupColumns); + } + + return ScrollingListController; + } +); \ No newline at end of file