From 546cde56a8f410d0178ede21e6cc25a85280d4c3 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 15 Apr 2016 08:32:34 -0700 Subject: [PATCH 01/18] [Timeline] Expose internal resource utilization ...to allow this to be exported for CSV, #751 --- .../timeline/src/capabilities/UtilizationCapability.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/platform/features/timeline/src/capabilities/UtilizationCapability.js b/platform/features/timeline/src/capabilities/UtilizationCapability.js index 140f527c0d..33a7e4f793 100644 --- a/platform/features/timeline/src/capabilities/UtilizationCapability.js +++ b/platform/features/timeline/src/capabilities/UtilizationCapability.js @@ -195,6 +195,13 @@ define( * @returns {Promise.} a promise for resource identifiers */ resources: promiseResourceKeys, + /** + * Get the resource utilization associated with this object + * directly, not including any resource utilization associated + * with contained objects. + * @returns {Promise.} + */ + internal: promiseInternalUtilization, /** * Get the resource utilization associated with this * object. Results are not sorted. This requires looking From f683ca44a220359989c1c1841a3b7f66d7280fbb Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 15 Apr 2016 08:45:42 -0700 Subject: [PATCH 02/18] [Timeline] Read resource utilizations during CSV export --- .../src/actions/TimelineColumnizer.js | 19 +++++- .../timeline/src/actions/UtilizationColumn.js | 58 +++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 platform/features/timeline/src/actions/UtilizationColumn.js diff --git a/platform/features/timeline/src/actions/TimelineColumnizer.js b/platform/features/timeline/src/actions/TimelineColumnizer.js index 3069bd8b96..02d3ad6b69 100644 --- a/platform/features/timeline/src/actions/TimelineColumnizer.js +++ b/platform/features/timeline/src/actions/TimelineColumnizer.js @@ -68,11 +68,12 @@ define([ * @constructor * @memberof {platform/features/timeline} */ - function TimelineColumnizer(domainObjects) { + function TimelineColumnizer(domainObjects, resourceMap) { var maxComposition = 0, maxRelationships = 0, columnNames = {}, columns = [], + costKeys = [], foundTimespan = false, i; @@ -84,6 +85,14 @@ define([ } } + function addCostProperties(costCapability) { + costCapability.resources().forEach(function (key) { + if (costKeys.indexOf(key) === -1) { + costKeys.push(key); + } + }); + } + columns.push(new IdColumn()); domainObjects.forEach(function (domainObject) { @@ -105,6 +114,10 @@ define([ foundTimespan = true; } + if (domainObject.hasCapability('cost')) { + addCostProperties(domainObject.getCapability('cost')); + } + if (metadataProperties) { metadataProperties.forEach(addMetadataProperty); } @@ -115,6 +128,10 @@ define([ columns.push(new TimespanColumn(false)); } + costKeys.forEach(function (key) { + columns.push(new UtilizationColumn(resourceMap[key])); + }); + for (i = 0; i < maxComposition; i += 1) { columns.push(new CompositionColumn(i)); } diff --git a/platform/features/timeline/src/actions/UtilizationColumn.js b/platform/features/timeline/src/actions/UtilizationColumn.js new file mode 100644 index 0000000000..f2c8a56544 --- /dev/null +++ b/platform/features/timeline/src/actions/UtilizationColumn.js @@ -0,0 +1,58 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2009-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"; + + /** + * A column showing utilization costs associated with activities. + * @constructor + * @param {string} key the key for the particular cost + * @implements {platform/features/timeline.TimelineCSVColumn} + */ + function UtilizationColumn(resource) { + this.resource = resource; + } + + UtilizationColumn.prototype.name = function () { + return this.resource.name; + }; + + UtilizationColumn.prototype.value = function (domainObject) { + var resource = this.resource; + + function getUtilizationValue(utilizations) { + utilizations = utilizations.filter(function (utilization) { + return key === resource.key; + }); + return utilizations.length === 1 ? utilizations[0].value : ""; + } + + return !domainObject.hasCapability('utilization') ? + "" : + domainObject.getCapability('utilization').internal() + .then(getUtilizationValue); + }; + + return UtilizationColumn; +}); From f16a107105415cb470a9ba3a10515483e3d1655d Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 15 Apr 2016 08:51:22 -0700 Subject: [PATCH 03/18] [Timeline] Inject resources into CSV action --- platform/features/timeline/bundle.js | 6 +++++- .../timeline/src/actions/ExportTimelineAsCSVAction.js | 11 +++++++++-- .../timeline/src/actions/ExportTimelineAsCSVTask.js | 6 ++++-- .../timeline/src/actions/TimelineColumnizer.js | 11 +++-------- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/platform/features/timeline/bundle.js b/platform/features/timeline/bundle.js index 8e2a40ed7d..27420fd032 100644 --- a/platform/features/timeline/bundle.js +++ b/platform/features/timeline/bundle.js @@ -93,7 +93,11 @@ define([ "name": "Export Timeline as CSV", "category": "contextual", "implementation": ExportTimelineAsCSVAction, - "depends": [ "exportService", "notificationService" ] + "depends": [ + "exportService", + "notificationService", + "resources[]" + ] } ], "constants": [ diff --git a/platform/features/timeline/src/actions/ExportTimelineAsCSVAction.js b/platform/features/timeline/src/actions/ExportTimelineAsCSVAction.js index 387c0839a0..e50b9369db 100644 --- a/platform/features/timeline/src/actions/ExportTimelineAsCSVAction.js +++ b/platform/features/timeline/src/actions/ExportTimelineAsCSVAction.js @@ -29,14 +29,21 @@ define(["./ExportTimelineAsCSVTask"], function (ExportTimelineAsCSVTask) { * * @param exportService the service used to perform the CSV export * @param notificationService the service used to show notifications + * @param {Array} resources an array of `resources` extensions * @param context the Action's context * @implements {Action} * @constructor * @memberof {platform/features/timeline} */ - function ExportTimelineAsCSVAction(exportService, notificationService, context) { + function ExportTimelineAsCSVAction( + exportService, + notificationService, + resources, + context + ) { this.task = new ExportTimelineAsCSVTask( exportService, + resources, context.domainObject ); this.notificationService = notificationService; @@ -67,4 +74,4 @@ define(["./ExportTimelineAsCSVTask"], function (ExportTimelineAsCSVTask) { }; return ExportTimelineAsCSVAction; -}); \ No newline at end of file +}); diff --git a/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js b/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js index 253db5c8b9..5979347d3c 100644 --- a/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js +++ b/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js @@ -37,11 +37,13 @@ define([ * @constructor * @memberof {platform/features/timeline} * @param exportService the service used to export as CSV + * @param resources the `resources` extension category * @param {DomainObject} domainObject the timeline being exported */ - function ExportTimelineAsCSVTask(exportService, domainObject) { + function ExportTimelineAsCSVTask(exportService, resources, domainObject) { this.domainObject = domainObject; this.exportService = exportService; + this.resources = resources; } /** @@ -54,7 +56,7 @@ define([ var exportService = this.exportService; function doExport(objects) { - var exporter = new TimelineColumnizer(objects), + var exporter = new TimelineColumnizer(objects, this.resources), options = { headers: exporter.headers() }; return exporter.rows().then(function (rows) { return exportService.exportCSV(rows, options); diff --git a/platform/features/timeline/src/actions/TimelineColumnizer.js b/platform/features/timeline/src/actions/TimelineColumnizer.js index 02d3ad6b69..035496edc6 100644 --- a/platform/features/timeline/src/actions/TimelineColumnizer.js +++ b/platform/features/timeline/src/actions/TimelineColumnizer.js @@ -68,12 +68,11 @@ define([ * @constructor * @memberof {platform/features/timeline} */ - function TimelineColumnizer(domainObjects, resourceMap) { + function TimelineColumnizer(domainObjects, resources) { var maxComposition = 0, maxRelationships = 0, columnNames = {}, columns = [], - costKeys = [], foundTimespan = false, i; @@ -114,10 +113,6 @@ define([ foundTimespan = true; } - if (domainObject.hasCapability('cost')) { - addCostProperties(domainObject.getCapability('cost')); - } - if (metadataProperties) { metadataProperties.forEach(addMetadataProperty); } @@ -128,8 +123,8 @@ define([ columns.push(new TimespanColumn(false)); } - costKeys.forEach(function (key) { - columns.push(new UtilizationColumn(resourceMap[key])); + resources.forEach(function (resource) { + columns.push(new UtilizationColumn(resource)); }); for (i = 0; i < maxComposition; i += 1) { From ed519d89d70568f608eb41f12d3de2097921673d Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Wed, 25 May 2016 10:35:29 -0700 Subject: [PATCH 04/18] [Timeline] Log errors during CSV export #751 --- platform/features/timeline/bundle.js | 1 + .../timeline/src/actions/ExportTimelineAsCSVAction.js | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/platform/features/timeline/bundle.js b/platform/features/timeline/bundle.js index e44b27c589..4663a37fae 100644 --- a/platform/features/timeline/bundle.js +++ b/platform/features/timeline/bundle.js @@ -92,6 +92,7 @@ define([ "category": "contextual", "implementation": ExportTimelineAsCSVAction, "depends": [ + "$log", "exportService", "notificationService", "resources[]" diff --git a/platform/features/timeline/src/actions/ExportTimelineAsCSVAction.js b/platform/features/timeline/src/actions/ExportTimelineAsCSVAction.js index 57ac17c8a0..5b0e007e23 100644 --- a/platform/features/timeline/src/actions/ExportTimelineAsCSVAction.js +++ b/platform/features/timeline/src/actions/ExportTimelineAsCSVAction.js @@ -34,11 +34,13 @@ define(["./ExportTimelineAsCSVTask"], function (ExportTimelineAsCSVTask) { * @memberof {platform/features/timeline} */ function ExportTimelineAsCSVAction( + $log, exportService, notificationService, resources, context ) { + this.$log = $log; this.task = new ExportTimelineAsCSVTask( exportService, resources, @@ -52,13 +54,15 @@ define(["./ExportTimelineAsCSVTask"], function (ExportTimelineAsCSVTask) { notification = notificationService.notify({ title: "Exporting CSV", unknownProgress: true - }); + }), + $log = this.$log; return this.task.run() .then(function () { notification.dismiss(); }) - .catch(function () { + .catch(function (err) { + $log.warn(err); notification.dismiss(); notificationService.error("Error exporting CSV"); }); From 81624291061c43b13326b0da6156e2588be90482 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Wed, 25 May 2016 10:37:01 -0700 Subject: [PATCH 05/18] [Timeline] Pass in resources extensions --- .../features/timeline/src/actions/ExportTimelineAsCSVTask.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js b/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js index 1e9be7d97a..d026edff3a 100644 --- a/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js +++ b/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js @@ -52,9 +52,10 @@ define([ */ ExportTimelineAsCSVTask.prototype.run = function () { var exportService = this.exportService; + var resources = this.resources; function doExport(objects) { - var exporter = new TimelineColumnizer(objects, this.resources), + var exporter = new TimelineColumnizer(objects, resources), options = { headers: exporter.headers() }; return exporter.rows().then(function (rows) { return exportService.exportCSV(rows, options); From 0cc2ba75958c8824858136c2f3078e70b453cc19 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Wed, 25 May 2016 10:38:00 -0700 Subject: [PATCH 06/18] [Timeline] Import UtilizationColumn --- .../features/timeline/src/actions/TimelineColumnizer.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/platform/features/timeline/src/actions/TimelineColumnizer.js b/platform/features/timeline/src/actions/TimelineColumnizer.js index 5468add401..bfbd5e34c2 100644 --- a/platform/features/timeline/src/actions/TimelineColumnizer.js +++ b/platform/features/timeline/src/actions/TimelineColumnizer.js @@ -25,13 +25,15 @@ define([ "./ModeColumn", "./CompositionColumn", "./MetadataColumn", - "./TimespanColumn" + "./TimespanColumn", + "./UtilizationColumn" ], function ( IdColumn, ModeColumn, CompositionColumn, MetadataColumn, - TimespanColumn + TimespanColumn, + UtilizationColumn ) { /** From bb4f1ce7cd87781198705362c0a4c1ed3dcb6fd9 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Wed, 25 May 2016 10:52:25 -0700 Subject: [PATCH 07/18] [Timeline] Include utilization columns --- platform/features/timeline/bundle.js | 3 ++- .../timeline/src/actions/UtilizationColumn.js | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/platform/features/timeline/bundle.js b/platform/features/timeline/bundle.js index 4663a37fae..b8754f4916 100644 --- a/platform/features/timeline/bundle.js +++ b/platform/features/timeline/bundle.js @@ -557,7 +557,8 @@ define([ { "key": "comms", "name": "Comms", - "units": "Kbps" + "units": "Kbps", + "foo": "Kb" }, { "key": "battery", diff --git a/platform/features/timeline/src/actions/UtilizationColumn.js b/platform/features/timeline/src/actions/UtilizationColumn.js index f2c8a56544..e9e88a5896 100644 --- a/platform/features/timeline/src/actions/UtilizationColumn.js +++ b/platform/features/timeline/src/actions/UtilizationColumn.js @@ -41,11 +41,23 @@ define([], function () { UtilizationColumn.prototype.value = function (domainObject) { var resource = this.resource; + function getCost(utilization) { + var seconds = (utilization.end - utilization.start) / 1000; + return seconds * utilization.value; + } + function getUtilizationValue(utilizations) { utilizations = utilizations.filter(function (utilization) { - return key === resource.key; + return utilization.key === resource.key; }); - return utilizations.length === 1 ? utilizations[0].value : ""; + + if (utilizations.length === 0) { + return ""; + } + + return utilizations.map(getCost).reduce(function (a, b) { + return a + b; + }, 0); } return !domainObject.hasCapability('utilization') ? From 463f7ccf65024ea0c3048cdb2b8d8368132ca7a3 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Wed, 25 May 2016 12:07:35 -0700 Subject: [PATCH 08/18] [Timeline] Use indexes instead of UUIDs --- .../timeline/src/actions/CompositionColumn.js | 7 +++++-- platform/features/timeline/src/actions/IdColumn.js | 7 ++++--- platform/features/timeline/src/actions/ModeColumn.js | 8 +++++--- .../timeline/src/actions/TimelineColumnizer.js | 12 +++++++++--- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/platform/features/timeline/src/actions/CompositionColumn.js b/platform/features/timeline/src/actions/CompositionColumn.js index f9bede9983..3fff0bda37 100644 --- a/platform/features/timeline/src/actions/CompositionColumn.js +++ b/platform/features/timeline/src/actions/CompositionColumn.js @@ -30,8 +30,9 @@ define([], function () { * @constructor * @implements {platform/features/timeline.TimelineCSVColumn} */ - function CompositionColumn(index) { + function CompositionColumn(index, idMap) { this.index = index; + this.idMap = idMap; } CompositionColumn.prototype.name = function () { @@ -41,7 +42,9 @@ define([], function () { CompositionColumn.prototype.value = function (domainObject) { var model = domainObject.getModel(), composition = model.composition || []; - return (composition[this.index]) || ""; + + return composition.length > this.index ? + this.idMap[composition[this.index]] : ""; }; return CompositionColumn; diff --git a/platform/features/timeline/src/actions/IdColumn.js b/platform/features/timeline/src/actions/IdColumn.js index 38c8b9264e..b6ff15fe6c 100644 --- a/platform/features/timeline/src/actions/IdColumn.js +++ b/platform/features/timeline/src/actions/IdColumn.js @@ -27,15 +27,16 @@ define([], function () { * @constructor * @implements {platform/features/timeline.TimelineCSVColumn} */ - function IdColumn() { + function IdColumn(idMap) { + this.idMap = idMap; } IdColumn.prototype.name = function () { - return "Identifier"; + return "Index"; }; IdColumn.prototype.value = function (domainObject) { - return domainObject.getId(); + return this.idMap[domainObject.getId()]; }; return IdColumn; diff --git a/platform/features/timeline/src/actions/ModeColumn.js b/platform/features/timeline/src/actions/ModeColumn.js index fe2063566d..26b307cbd0 100644 --- a/platform/features/timeline/src/actions/ModeColumn.js +++ b/platform/features/timeline/src/actions/ModeColumn.js @@ -29,8 +29,9 @@ define([], function () { * element associated with this column * @implements {platform/features/timeline.TimelineCSVColumn} */ - function ModeColumn(index) { + function ModeColumn(index, idMap) { this.index = index; + this.idMap = idMap; } ModeColumn.prototype.name = function () { @@ -39,8 +40,9 @@ define([], function () { ModeColumn.prototype.value = function (domainObject) { var model = domainObject.getModel(), - composition = (model.relationships || {}).modes || []; - return (composition[this.index]) || ""; + modes = (model.relationships || {}).modes || []; + return modes.length > this.index ? + this.idMap[modes[this.index]] : ""; }; return ModeColumn; diff --git a/platform/features/timeline/src/actions/TimelineColumnizer.js b/platform/features/timeline/src/actions/TimelineColumnizer.js index bfbd5e34c2..fb0b80a7f7 100644 --- a/platform/features/timeline/src/actions/TimelineColumnizer.js +++ b/platform/features/timeline/src/actions/TimelineColumnizer.js @@ -74,6 +74,7 @@ define([ columnNames = {}, columns = [], foundTimespan = false, + idMap, i; function addMetadataProperty(property) { @@ -92,7 +93,12 @@ define([ }); } - columns.push(new IdColumn()); + idMap = domainObjects.reduce(function (map, domainObject, index) { + map[domainObject.getId()] = index + 1; + return map; + }, {}); + + columns.push(new IdColumn(idMap)); domainObjects.forEach(function (domainObject) { var model = domainObject.getModel(), @@ -128,11 +134,11 @@ define([ }); for (i = 0; i < maxComposition; i += 1) { - columns.push(new CompositionColumn(i)); + columns.push(new CompositionColumn(i, idMap)); } for (i = 0; i < maxRelationships; i += 1) { - columns.push(new ModeColumn(i)); + columns.push(new ModeColumn(i, idMap)); } this.domainObjects = domainObjects; From 23c71b7218a8c9392bda20c595b4b2e17fc7947d Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Wed, 25 May 2016 12:12:11 -0700 Subject: [PATCH 09/18] [Timeline] Include units for utilizations --- platform/features/timeline/bundle.js | 3 +-- .../features/timeline/src/actions/UtilizationColumn.js | 10 +++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/platform/features/timeline/bundle.js b/platform/features/timeline/bundle.js index b8754f4916..4663a37fae 100644 --- a/platform/features/timeline/bundle.js +++ b/platform/features/timeline/bundle.js @@ -557,8 +557,7 @@ define([ { "key": "comms", "name": "Comms", - "units": "Kbps", - "foo": "Kb" + "units": "Kbps" }, { "key": "battery", diff --git a/platform/features/timeline/src/actions/UtilizationColumn.js b/platform/features/timeline/src/actions/UtilizationColumn.js index e9e88a5896..7da7b6c890 100644 --- a/platform/features/timeline/src/actions/UtilizationColumn.js +++ b/platform/features/timeline/src/actions/UtilizationColumn.js @@ -34,6 +34,14 @@ define([], function () { this.resource = resource; } + UtilizationColumn.prototype.getUnits = function () { + var instantaneousUnits = this.resource.units; + return { + "Kbps": "Kb", + "Watts": "joules", + }[instantaneousUnits] || "unknown units"; + }; + UtilizationColumn.prototype.name = function () { return this.resource.name; }; @@ -57,7 +65,7 @@ define([], function () { return utilizations.map(getCost).reduce(function (a, b) { return a + b; - }, 0); + }, 0) + " (" + this.getUnits() + ")"; } return !domainObject.hasCapability('utilization') ? From a3bcaea7f95efc3a1f1305e994a8d24bfe32c468 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Wed, 25 May 2016 12:21:58 -0700 Subject: [PATCH 10/18] [Timeline] Show units in utilization headers --- .../timeline/src/actions/UtilizationColumn.js | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/platform/features/timeline/src/actions/UtilizationColumn.js b/platform/features/timeline/src/actions/UtilizationColumn.js index 7da7b6c890..e87794237b 100644 --- a/platform/features/timeline/src/actions/UtilizationColumn.js +++ b/platform/features/timeline/src/actions/UtilizationColumn.js @@ -34,16 +34,13 @@ define([], function () { this.resource = resource; } - UtilizationColumn.prototype.getUnits = function () { - var instantaneousUnits = this.resource.units; - return { - "Kbps": "Kb", - "Watts": "joules", - }[instantaneousUnits] || "unknown units"; - }; - UtilizationColumn.prototype.name = function () { - return this.resource.name; + var units = { + "Kbps": "Kb", + "watts": "watt-seconds" + }[this.resource.units] || "unknown units"; + + return this.resource.name + " (" + units + ")"; }; UtilizationColumn.prototype.value = function (domainObject) { @@ -65,7 +62,7 @@ define([], function () { return utilizations.map(getCost).reduce(function (a, b) { return a + b; - }, 0) + " (" + this.getUnits() + ")"; + }, 0); } return !domainObject.hasCapability('utilization') ? From d7f566088f22d4e5e67e4099d45adec756c8e716 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Wed, 25 May 2016 12:25:02 -0700 Subject: [PATCH 11/18] [Timeline] Update spec to include logging --- .../actions/ExportTimelineAsCSVActionSpec.js | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/platform/features/timeline/test/actions/ExportTimelineAsCSVActionSpec.js b/platform/features/timeline/test/actions/ExportTimelineAsCSVActionSpec.js index e0f09c3ae6..e31f25b074 100644 --- a/platform/features/timeline/test/actions/ExportTimelineAsCSVActionSpec.js +++ b/platform/features/timeline/test/actions/ExportTimelineAsCSVActionSpec.js @@ -24,7 +24,8 @@ define( ['../../src/actions/ExportTimelineAsCSVAction'], function (ExportTimelineAsCSVAction) { describe("ExportTimelineAsCSVAction", function () { - var mockExportService, + var mockLog, + mockExportService, mockNotificationService, mockNotification, mockDomainObject, @@ -39,6 +40,13 @@ define( ['getId', 'getModel', 'getCapability', 'hasCapability'] ); mockType = jasmine.createSpyObj('type', ['instanceOf']); + + mockLog = jasmine.createSpyObj('$log', [ + 'warn', + 'error', + 'info', + 'debug' + ]); mockExportService = jasmine.createSpyObj( 'exportService', ['exportCSV'] @@ -63,8 +71,10 @@ define( testContext = { domainObject: mockDomainObject }; action = new ExportTimelineAsCSVAction( + mockLog, mockExportService, mockNotificationService, + [], testContext ); }); @@ -129,8 +139,11 @@ define( }); describe("and an error occurs", function () { + var testError; + beforeEach(function () { - testPromise.reject(); + testError = { someProperty: "some value" }; + testPromise.reject(testError); waitsFor(function () { return mockCallback.calls.length > 0; }); @@ -145,6 +158,10 @@ define( expect(mockNotificationService.error) .toHaveBeenCalledWith(jasmine.any(String)); }); + + it("logs the root cause", function () { + expect(mockLog.warn).toHaveBeenCalledWith(testError); + }); }); }); }); From 80f5cb756d017f68165043cf31a88ef623ab5144 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Wed, 25 May 2016 12:25:58 -0700 Subject: [PATCH 12/18] [Timeline] Account for new argument in spec --- .../timeline/test/actions/ExportTimelineAsCSVTaskSpec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/features/timeline/test/actions/ExportTimelineAsCSVTaskSpec.js b/platform/features/timeline/test/actions/ExportTimelineAsCSVTaskSpec.js index 0330e86397..4deab99801 100644 --- a/platform/features/timeline/test/actions/ExportTimelineAsCSVTaskSpec.js +++ b/platform/features/timeline/test/actions/ExportTimelineAsCSVTaskSpec.js @@ -52,6 +52,7 @@ define( task = new ExportTimelineAsCSVTask( mockExportService, + [], mockDomainObject ); }); From ba0d9a186b2c38cf89c29a38a61130d2fcd18a9e Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Wed, 25 May 2016 12:26:47 -0700 Subject: [PATCH 13/18] [Timeline] Account for new argument in spec --- .../features/timeline/test/actions/TimelineColumnizerSpec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/features/timeline/test/actions/TimelineColumnizerSpec.js b/platform/features/timeline/test/actions/TimelineColumnizerSpec.js index d29bb14278..3c9b3de7e6 100644 --- a/platform/features/timeline/test/actions/TimelineColumnizerSpec.js +++ b/platform/features/timeline/test/actions/TimelineColumnizerSpec.js @@ -75,7 +75,7 @@ define( return c === 'metadata' && testMetadata; }); - exporter = new TimelineColumnizer(mockDomainObjects); + exporter = new TimelineColumnizer(mockDomainObjects, []); }); describe("rows", function () { From 73b922facfddf0070ed8e35f24c87df029e3cae7 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Wed, 25 May 2016 12:32:44 -0700 Subject: [PATCH 14/18] [Timeline] Update specs for indexes instead of ids --- .../test/actions/CompositionColumnSpec.js | 17 +++++++++++------ .../timeline/test/actions/IdColumnSpec.js | 10 ++++++---- .../timeline/test/actions/ModeColumnSpec.js | 15 +++++++++++---- .../test/actions/TimelineColumnizerSpec.js | 7 ------- 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/platform/features/timeline/test/actions/CompositionColumnSpec.js b/platform/features/timeline/test/actions/CompositionColumnSpec.js index 8cf566a080..df52d08db5 100644 --- a/platform/features/timeline/test/actions/CompositionColumnSpec.js +++ b/platform/features/timeline/test/actions/CompositionColumnSpec.js @@ -23,13 +23,20 @@ define( ['../../src/actions/CompositionColumn'], function (CompositionColumn) { + var TEST_IDS = ['a', 'b', 'c', 'd', 'e', 'f']; + describe("CompositionColumn", function () { var testIndex, + testIdMap, column; beforeEach(function () { testIndex = 3; - column = new CompositionColumn(testIndex); + testIdMap = TEST_IDS.reduce(function (map, id, index) { + map[id] = index; + return map; + }, {}); + column = new CompositionColumn(testIndex, testIdMap); }); it("includes a one-based index in its name", function () { @@ -46,15 +53,13 @@ define( 'domainObject', ['getId', 'getModel', 'getCapability'] ); - testModel = { - composition: ['a', 'b', 'c', 'd', 'e', 'f'] - }; + testModel = { composition: TEST_IDS }; mockDomainObject.getModel.andReturn(testModel); }); - it("returns a corresponding identifier", function () { + it("returns a corresponding value from the map", function () { expect(column.value(mockDomainObject)) - .toEqual(testModel.composition[testIndex]); + .toEqual(testIdMap[testModel.composition[testIndex]]); }); it("returns nothing when composition is exceeded", function () { diff --git a/platform/features/timeline/test/actions/IdColumnSpec.js b/platform/features/timeline/test/actions/IdColumnSpec.js index f44d255255..80b84680a4 100644 --- a/platform/features/timeline/test/actions/IdColumnSpec.js +++ b/platform/features/timeline/test/actions/IdColumnSpec.js @@ -24,10 +24,12 @@ define( ['../../src/actions/IdColumn'], function (IdColumn) { describe("IdColumn", function () { - var column; + var testIdMap, + column; beforeEach(function () { - column = new IdColumn(); + testIdMap = { "foo": "bar" }; + column = new IdColumn(testIdMap); }); it("has a name", function () { @@ -47,9 +49,9 @@ define( mockDomainObject.getId.andReturn(testId); }); - it("provides a domain object's identifier", function () { + it("provides a value mapped from domain object's identifier", function () { expect(column.value(mockDomainObject)) - .toEqual(testId); + .toEqual(testIdMap[testId]); }); }); diff --git a/platform/features/timeline/test/actions/ModeColumnSpec.js b/platform/features/timeline/test/actions/ModeColumnSpec.js index 446e3b1030..b828511266 100644 --- a/platform/features/timeline/test/actions/ModeColumnSpec.js +++ b/platform/features/timeline/test/actions/ModeColumnSpec.js @@ -23,13 +23,20 @@ define( ['../../src/actions/ModeColumn'], function (ModeColumn) { + var TEST_IDS = ['a', 'b', 'c', 'd', 'e', 'f'] + describe("ModeColumn", function () { var testIndex, + testIdMap, column; beforeEach(function () { testIndex = 3; - column = new ModeColumn(testIndex); + testIdMap = TEST_IDS.reduce(function (map, id, index) { + map[id] = index; + return map; + }, {}); + column = new ModeColumn(testIndex, testIdMap); }); it("includes a one-based index in its name", function () { @@ -48,15 +55,15 @@ define( ); testModel = { relationships: { - modes: ['a', 'b', 'c', 'd', 'e', 'f'] + modes: TEST_IDS } }; mockDomainObject.getModel.andReturn(testModel); }); - it("returns a corresponding identifier", function () { + it("returns a corresponding value from the map", function () { expect(column.value(mockDomainObject)) - .toEqual(testModel.relationships.modes[testIndex]); + .toEqual(testIdMap[testModel.relationships.modes[testIndex]]); }); it("returns nothing when relationships are exceeded", function () { diff --git a/platform/features/timeline/test/actions/TimelineColumnizerSpec.js b/platform/features/timeline/test/actions/TimelineColumnizerSpec.js index 3c9b3de7e6..980ed1e6c3 100644 --- a/platform/features/timeline/test/actions/TimelineColumnizerSpec.js +++ b/platform/features/timeline/test/actions/TimelineColumnizerSpec.js @@ -94,13 +94,6 @@ define( it("include one row per domain object", function () { expect(rows.length).toEqual(mockDomainObjects.length); }); - - it("includes identifiers for each domain object", function () { - rows.forEach(function (row, index) { - var id = mockDomainObjects[index].getId(); - expect(row.indexOf(id)).not.toEqual(-1); - }); - }); }); describe("headers", function () { From f9fd97230ff902929cbfceb03b703dc3e371375b Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Wed, 25 May 2016 12:37:03 -0700 Subject: [PATCH 15/18] [Timeline] Satisfy JSHint --- .../features/timeline/src/actions/TimelineColumnizer.js | 8 -------- .../features/timeline/src/actions/UtilizationColumn.js | 3 --- platform/features/timeline/test/actions/ModeColumnSpec.js | 2 +- 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/platform/features/timeline/src/actions/TimelineColumnizer.js b/platform/features/timeline/src/actions/TimelineColumnizer.js index fb0b80a7f7..011e87df9e 100644 --- a/platform/features/timeline/src/actions/TimelineColumnizer.js +++ b/platform/features/timeline/src/actions/TimelineColumnizer.js @@ -85,14 +85,6 @@ define([ } } - function addCostProperties(costCapability) { - costCapability.resources().forEach(function (key) { - if (costKeys.indexOf(key) === -1) { - costKeys.push(key); - } - }); - } - idMap = domainObjects.reduce(function (map, domainObject, index) { map[domainObject.getId()] = index + 1; return map; diff --git a/platform/features/timeline/src/actions/UtilizationColumn.js b/platform/features/timeline/src/actions/UtilizationColumn.js index e87794237b..9c9307271e 100644 --- a/platform/features/timeline/src/actions/UtilizationColumn.js +++ b/platform/features/timeline/src/actions/UtilizationColumn.js @@ -19,11 +19,8 @@ * 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"; - /** * A column showing utilization costs associated with activities. * @constructor diff --git a/platform/features/timeline/test/actions/ModeColumnSpec.js b/platform/features/timeline/test/actions/ModeColumnSpec.js index b828511266..037aa5c34f 100644 --- a/platform/features/timeline/test/actions/ModeColumnSpec.js +++ b/platform/features/timeline/test/actions/ModeColumnSpec.js @@ -23,7 +23,7 @@ define( ['../../src/actions/ModeColumn'], function (ModeColumn) { - var TEST_IDS = ['a', 'b', 'c', 'd', 'e', 'f'] + var TEST_IDS = ['a', 'b', 'c', 'd', 'e', 'f']; describe("ModeColumn", function () { var testIndex, From 568927995405c3d39d4bc956ddf5eb6931832986 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Thu, 26 May 2016 11:53:16 -0700 Subject: [PATCH 16/18] [Timeline] Add JSDoc for idMap https://github.com/nasa/openmct/pull/962#discussion_r64676750 https://github.com/nasa/openmct/pull/962#discussion_r64677198 --- platform/features/timeline/src/actions/CompositionColumn.js | 3 +++ platform/features/timeline/src/actions/IdColumn.js | 5 ++++- platform/features/timeline/src/actions/ModeColumn.js | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/platform/features/timeline/src/actions/CompositionColumn.js b/platform/features/timeline/src/actions/CompositionColumn.js index 3fff0bda37..e33f028f99 100644 --- a/platform/features/timeline/src/actions/CompositionColumn.js +++ b/platform/features/timeline/src/actions/CompositionColumn.js @@ -27,6 +27,9 @@ define([], function () { * in a domain object's composition. * @param {number} index the zero-based index of the composition * element associated with this column + * @param idMap an object containing key value pairs, where keys + * are domain object identifiers and values are whatever + * should appear in CSV output in their place * @constructor * @implements {platform/features/timeline.TimelineCSVColumn} */ diff --git a/platform/features/timeline/src/actions/IdColumn.js b/platform/features/timeline/src/actions/IdColumn.js index b6ff15fe6c..9148ef6a8b 100644 --- a/platform/features/timeline/src/actions/IdColumn.js +++ b/platform/features/timeline/src/actions/IdColumn.js @@ -23,8 +23,11 @@ define([], function () { /** - * A column showing domain object identifiers. + * A column showing identifying domain objects. * @constructor + * @param idMap an object containing key value pairs, where keys + * are domain object identifiers and values are whatever + * should appear in CSV output in their place * @implements {platform/features/timeline.TimelineCSVColumn} */ function IdColumn(idMap) { diff --git a/platform/features/timeline/src/actions/ModeColumn.js b/platform/features/timeline/src/actions/ModeColumn.js index 26b307cbd0..05eec7a30a 100644 --- a/platform/features/timeline/src/actions/ModeColumn.js +++ b/platform/features/timeline/src/actions/ModeColumn.js @@ -27,6 +27,9 @@ define([], function () { * @constructor * @param {number} index the zero-based index of the composition * element associated with this column + * @param idMap an object containing key value pairs, where keys + * are domain object identifiers and values are whatever + * should appear in CSV output in their place * @implements {platform/features/timeline.TimelineCSVColumn} */ function ModeColumn(index, idMap) { From e9cac6eff3d88a7524edfddcb864a212aa716440 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Thu, 26 May 2016 11:57:07 -0700 Subject: [PATCH 17/18] [Timeline] Add JSDoc for new parameter https://github.com/nasa/openmct/pull/962#discussion_r64677520 --- platform/features/timeline/src/actions/TimelineColumnizer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/features/timeline/src/actions/TimelineColumnizer.js b/platform/features/timeline/src/actions/TimelineColumnizer.js index 011e87df9e..92e54b1860 100644 --- a/platform/features/timeline/src/actions/TimelineColumnizer.js +++ b/platform/features/timeline/src/actions/TimelineColumnizer.js @@ -65,6 +65,7 @@ define([ * * @param {DomainObject[]} domainObjects the objects to include * in the exported data + * @param {Array} resources an array of `resources` extensions * @constructor * @memberof {platform/features/timeline} */ From dade6b2254f85b72b6cf61a5c198885d8c532eb6 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Thu, 26 May 2016 11:58:40 -0700 Subject: [PATCH 18/18] [Timeline] Use positive logic for clarity https://github.com/nasa/openmct/pull/962#discussion_r64678013 --- platform/features/timeline/src/actions/UtilizationColumn.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/features/timeline/src/actions/UtilizationColumn.js b/platform/features/timeline/src/actions/UtilizationColumn.js index 9c9307271e..7a92ce668e 100644 --- a/platform/features/timeline/src/actions/UtilizationColumn.js +++ b/platform/features/timeline/src/actions/UtilizationColumn.js @@ -62,10 +62,10 @@ define([], function () { }, 0); } - return !domainObject.hasCapability('utilization') ? - "" : + return domainObject.hasCapability('utilization') ? domainObject.getCapability('utilization').internal() - .then(getUtilizationValue); + .then(getUtilizationValue) : + ""; }; return UtilizationColumn;