From 5033e2cdbb1170168baccd3bcb65ac3d7955ebec Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 8 Feb 2016 13:04:41 -0800 Subject: [PATCH 001/164] [Timeline] Begin adding Export as CSV Sketch in solution for https://developer.nasa.gov/mct/warp/issues/135 --- .../src/actions/ExportTimelineAsCSVAction.js | 44 +++++++++++++++++++ .../src/actions/ExportTimelineAsCSVTask.js | 42 ++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 platform/features/timeline/src/actions/ExportTimelineAsCSVAction.js create mode 100644 platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js diff --git a/platform/features/timeline/src/actions/ExportTimelineAsCSVAction.js b/platform/features/timeline/src/actions/ExportTimelineAsCSVAction.js new file mode 100644 index 0000000000..2e0dc71589 --- /dev/null +++ b/platform/features/timeline/src/actions/ExportTimelineAsCSVAction.js @@ -0,0 +1,44 @@ +/***************************************************************************** + * 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(["./ExportTimelineAsCSVTask"], function (ExportTimelineAsCSVTask) { + 'use strict'; + + function ExportTimelineAsCSVAction(taskService, context) { + this.task = new ExportTimelineAsCSVTask(context.domainObject); + this.taskService = taskService; + } + + ExportTimelineAsCSVAction.prototype.perform = function () { + return this.taskService.run(this.task); + }; + + ExportTimelineAsCSVAction.appliesTo = function (context) { + return context.domainObject && + context.domainObject.hasCapability('type') && + context.domainObject.getCapability('type') + .instanceOf('timeline'); + }; + + 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 new file mode 100644 index 0000000000..82ee47b9a4 --- /dev/null +++ b/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js @@ -0,0 +1,42 @@ +/***************************************************************************** + * 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,Promise*/ + +/** + * Module defining ExportTimelineAsCSVTask. Created by vwoeltje on 2/8/16. + */ +define([], function () { + "use strict"; + + /** + * + * @constructor + * @memberof {platform/features/timeline} + */ + function ExportTimelineAsCSVTask(domainObject) { + this.domainObject = domainObject; + } + + + + return ExportTimelineAsCSVTask; +}); From d8b1e570d98292986c6ef817657a7c4207195c38 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 8 Feb 2016 13:36:25 -0800 Subject: [PATCH 002/164] [CSV Export] Begin implementing Begin implementing initial step, wherein timelines composition is traversed to build up a list of objects to export. --- .../src/actions/ExportTimelineAsCSVTask.js | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js b/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js index 82ee47b9a4..889788090c 100644 --- a/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js +++ b/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js @@ -36,7 +36,63 @@ define([], function () { this.domainObject = domainObject; } + /** + * @private + */ + ExportTimelineAsCSVTask.prototype.buildObjectList = function () { + var idSet = {}, + objects = []; + function addObject(domainObject) { + var id = domainObject.getId(), + subtasks = []; + + function addCompositionObjects() { + return domainObject.useCapability('composition') + .then(function (childObjects) { + return Promise.all(childObjects.map(addObject)); + }); + } + + function addRelationships() { + var relationship = domainObject.getCapability('relationship'); + relationship.getRelatedObjects('modes') + .then(function (modeObjects) { + return Promise.all(modeObjects.map(addObject)); + }); + } + + if (!idSet[id]) { + idSet[id] = true; + objects.push(domainObject); + if (domainObject.hasCapability('composition')) { + subtasks.push(addCompositionObjects()); + } + if (domainObject.hasCapability('relationship')) { + subtasks.push(addRelationships()); + } + } + + return Promise.all(subtasks); + } + + return addObject(this.domainObject).then(function () { + return objects; + }); + }; + + + ExportTimelineAsCSVTask.prototype.run = function (progressCallback) { + var name = this.domainObject.getModel().name; + + progressCallback({ + title: "Preparing to export " + name + }); + + this.buildObjectList().then(function (objects) { + + }); + }; return ExportTimelineAsCSVTask; }); From 4adb075a2b16a63a93fa8a2f2e47e96aeb3bbe72 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 8 Feb 2016 13:59:34 -0800 Subject: [PATCH 003/164] [Timelines] Separate out timeline traversal ...from rest of CSV export. --- .../src/actions/ExportTimelineAsCSVTask.js | 70 +++++------------- .../timeline/src/actions/TimelineTraverser.js | 74 +++++++++++++++++++ 2 files changed, 92 insertions(+), 52 deletions(-) create mode 100644 platform/features/timeline/src/actions/TimelineTraverser.js diff --git a/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js b/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js index 889788090c..57379d01d4 100644 --- a/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js +++ b/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js @@ -24,74 +24,40 @@ /** * Module defining ExportTimelineAsCSVTask. Created by vwoeltje on 2/8/16. */ -define([], function () { +define([ + "TimelineTraverser" +], function (TimelineTraverser, TimelineCSVExporter) { "use strict"; /** * * @constructor * @memberof {platform/features/timeline} + * @implements {Task} */ - function ExportTimelineAsCSVTask(domainObject) { + function ExportTimelineAsCSVTask(exportService, domainObject) { this.domainObject = domainObject; + this.exportService = exportService; } - /** - * @private - */ - ExportTimelineAsCSVTask.prototype.buildObjectList = function () { - var idSet = {}, - objects = []; + ExportTimelineAsCSVTask.prototype.run = function (progress) { + var name = this.domainObject.getModel().name, + exportService = this.exportService; - function addObject(domainObject) { - var id = domainObject.getId(), - subtasks = []; - - function addCompositionObjects() { - return domainObject.useCapability('composition') - .then(function (childObjects) { - return Promise.all(childObjects.map(addObject)); - }); - } - - function addRelationships() { - var relationship = domainObject.getCapability('relationship'); - relationship.getRelatedObjects('modes') - .then(function (modeObjects) { - return Promise.all(modeObjects.map(addObject)); - }); - } - - if (!idSet[id]) { - idSet[id] = true; - objects.push(domainObject); - if (domainObject.hasCapability('composition')) { - subtasks.push(addCompositionObjects()); - } - if (domainObject.hasCapability('relationship')) { - subtasks.push(addRelationships()); - } - } - - return Promise.all(subtasks); + function doExport(objects) { + var exporter = new TimelineCSVExporter(objects); + return exportService.exportCSV( + exporter.rows(), + exporter.options() + ); } - return addObject(this.domainObject).then(function () { - return objects; - }); - }; - - - ExportTimelineAsCSVTask.prototype.run = function (progressCallback) { - var name = this.domainObject.getModel().name; - - progressCallback({ + progress({ title: "Preparing to export " + name }); - this.buildObjectList().then(function (objects) { - - }); + return new TimelineTraverser().buildObjectList() + .then(doExport); }; return ExportTimelineAsCSVTask; diff --git a/platform/features/timeline/src/actions/TimelineTraverser.js b/platform/features/timeline/src/actions/TimelineTraverser.js new file mode 100644 index 0000000000..0f701a4799 --- /dev/null +++ b/platform/features/timeline/src/actions/TimelineTraverser.js @@ -0,0 +1,74 @@ +/***************************************************************************** + * 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,Promise*/ + +define([], function () { + + function TimelineTraverser(domainObject) { + this.domainObject = domainObject; + } + + TimelineTraverser.prototype.buildObjectList = function () { + var idSet = {}, + objects = []; + + function addObject(domainObject) { + var id = domainObject.getId(), + subtasks = []; + + function addCompositionObjects() { + return domainObject.useCapability('composition') + .then(function (childObjects) { + return Promise.all(childObjects.map(addObject)); + }); + } + + function addRelationships() { + var relationship = domainObject.getCapability('relationship'); + relationship.getRelatedObjects('modes') + .then(function (modeObjects) { + return Promise.all(modeObjects.map(addObject)); + }); + } + + if (!idSet[id]) { + idSet[id] = true; + objects.push(domainObject); + if (domainObject.hasCapability('composition')) { + subtasks.push(addCompositionObjects()); + } + if (domainObject.hasCapability('relationship')) { + subtasks.push(addRelationships()); + } + } + + return Promise.all(subtasks); + } + + return addObject(this.domainObject).then(function () { + return objects; + }); + }; + + return TimelineTraverser; + +}); \ No newline at end of file From 32fc50bbd35bce53777a7d2256b0795a9988a5d0 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 8 Feb 2016 15:04:39 -0800 Subject: [PATCH 004/164] [Timelines] Begin sketching in taskService ...to separate out immediate commonality with other long-running actions which need to show a blocking progress dialog. --- .../execution/src/TaskProgressReporter.js | 36 +++++++++ platform/execution/src/TaskService.js | 74 +++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 platform/execution/src/TaskProgressReporter.js create mode 100644 platform/execution/src/TaskService.js diff --git a/platform/execution/src/TaskProgressReporter.js b/platform/execution/src/TaskProgressReporter.js new file mode 100644 index 0000000000..f993a1a835 --- /dev/null +++ b/platform/execution/src/TaskProgressReporter.js @@ -0,0 +1,36 @@ +/***************************************************************************** + * 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"; + + function TaskProgressReporter(dialogService, notificationService) { + this.dialogService = dialogService; + this.notificationService = notificationService; + } + + TaskProgressReporter.prototype.cancel = function () { + + }; + +}); diff --git a/platform/execution/src/TaskService.js b/platform/execution/src/TaskService.js new file mode 100644 index 0000000000..a5f5c06697 --- /dev/null +++ b/platform/execution/src/TaskService.js @@ -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*/ + + +/** + * This bundle contains services for managing the flow of execution, + * such as support for running web workers on background threads. + * @namespace platform/execution + */ +define( + [], + function () { + "use strict"; + + /** + * Runs long-running tasks with progress reporting. + * @memberof platform/execution + * @constructor + */ + function TaskService(dialogService, notificationService) { + this.dialogService = dialogService; + this.notificationService = notificationService; + } + + /** + * Invoked to update progress associated with a running task. + * @callback TaskService~progressCallback + * @param {NotificationModel} model current progress to show + */ + + /** + * Initiate a new task. + * + * @param {function(progress : TaskService~progressCallback} : Task)} + * taskFactory a function which, when provided a + * progress-reporting callback, will return the task to run. + * @returns {Promise} a promise for the result of the task + */ + TaskService.prototype.run = function (task) { + var model = {}, + dialogService = this.dialogService, + notificationService = this.notificationService; + + function reportProgress(progressModel) { + + } + + return task.run(reportProgress); + }; + + return TaskService; + } +); + From a126e432867a45963d0f35496d4c1ab719934b57 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 8 Feb 2016 16:11:00 -0800 Subject: [PATCH 005/164] [Timelines] Handle columns during CSV export --- .../timeline/src/actions/CompositionColumn.js | 38 ++++++++ .../src/actions/ExportTimelineAsCSVTask.js | 4 - .../timeline/src/actions/MetadataColumn.js | 41 ++++++++ .../timeline/src/actions/ModeColumn.js | 38 ++++++++ .../src/actions/TimelineCSVExporter.js | 97 +++++++++++++++++++ 5 files changed, 214 insertions(+), 4 deletions(-) create mode 100644 platform/features/timeline/src/actions/CompositionColumn.js create mode 100644 platform/features/timeline/src/actions/MetadataColumn.js create mode 100644 platform/features/timeline/src/actions/ModeColumn.js create mode 100644 platform/features/timeline/src/actions/TimelineCSVExporter.js diff --git a/platform/features/timeline/src/actions/CompositionColumn.js b/platform/features/timeline/src/actions/CompositionColumn.js new file mode 100644 index 0000000000..35cbd75f69 --- /dev/null +++ b/platform/features/timeline/src/actions/CompositionColumn.js @@ -0,0 +1,38 @@ +/***************************************************************************** + * 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 () { + function CompositionColumn(index) { + this.index = index; + } + + CompositionColumn.prototype.name = function () { + return "Child " + (this.index + 1); + }; + + CompositionColumn.prototype.value = function (domainObject) { + var model = domainObject.getModel(), + composition = model.composition || []; + return (composition[this.index]) || ""; + }; +}); diff --git a/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js b/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js index 57379d01d4..45ebdffd2f 100644 --- a/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js +++ b/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js @@ -52,10 +52,6 @@ define([ ); } - progress({ - title: "Preparing to export " + name - }); - return new TimelineTraverser().buildObjectList() .then(doExport); }; diff --git a/platform/features/timeline/src/actions/MetadataColumn.js b/platform/features/timeline/src/actions/MetadataColumn.js new file mode 100644 index 0000000000..d31ae1a329 --- /dev/null +++ b/platform/features/timeline/src/actions/MetadataColumn.js @@ -0,0 +1,41 @@ +/***************************************************************************** + * 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 () { + function MetadataColumn(property) { + this.property = property; + } + + MetadataColumn.prototype.name = function () { + return this.property.name; + }; + + MetadataColumn.prototype.value = function (domainObject) { + var properties = domainObject.useCapability('metadata'), + name = this.property.name, + property = properties.find(function (p) { + return p.name === name; + }); + return property ? property.value : ""; + }; +}); diff --git a/platform/features/timeline/src/actions/ModeColumn.js b/platform/features/timeline/src/actions/ModeColumn.js new file mode 100644 index 0000000000..545bdc19fc --- /dev/null +++ b/platform/features/timeline/src/actions/ModeColumn.js @@ -0,0 +1,38 @@ +/***************************************************************************** + * 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 () { + function ModeColumn(index) { + this.index = index; + } + + ModeColumn.prototype.name = function () { + return "Mode " + (this.index + 1); + }; + + ModeColumn.prototype.value = function (domainObject) { + var model = domainObject.getModel(), + composition = (model.relationships || {}).modes || []; + return (composition[this.index]) || ""; + }; +}); diff --git a/platform/features/timeline/src/actions/TimelineCSVExporter.js b/platform/features/timeline/src/actions/TimelineCSVExporter.js new file mode 100644 index 0000000000..b42debad93 --- /dev/null +++ b/platform/features/timeline/src/actions/TimelineCSVExporter.js @@ -0,0 +1,97 @@ +/***************************************************************************** + * 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,Promise*/ + +define([ + "ModeColumn", + "CompositionColumn", + "MetadataColumn" +], function (ModeColumn, CompositionColumn, MetadataColumn) { + 'use strict'; + + function TimelineCSVExporter(domainObjects) { + var maxComposition = 0, + maxRelationships = 0, + columnNames = {}, + columns = [], + i; + + function addMetadataProperty(property) { + var name = property.name; + if (!columnNames[name]) { + columnNames[name] = true; + columns.push(new MetadataColumn(name)) + } + } + + domainObjects.forEach(function (domainObject) { + var model = domainObject.getModel(), + compositionLength = model.composition ? + model.composition.length : 0, + relationshipLength = (model.relationships || {}).modes ? + model.relationships.modes.length : + 0, + metadataProperties = + domainObject.useCapability('metadata') || []; + + maxComposition = Math.max(maxComposition, compositionLength); + maxRelationships = Math.max(maxRelationships, relationshipLength); + + metadataProperties.forEach(addMetadataProperty); + }); + + for (i = 0; i < maxComposition; i += 1) { + columns.push(new CompositionColumn(i)); + } + + for (i = 0; i < maxRelationships; i += 1) { + columns.push(new RelationshipColumn(i)); + } + + this.domainObjects = domainObjects; + this.columns = columns; + } + + TimelineCSVExporter.prototype.rows = function () { + var columns = this.columns; + + function toRow(domainObject) { + var row = {}; + columns.forEach(function (column) { + row[column.name()] = column.value(domainObject); + }); + return row; + } + + return this.domainObjects.map(toRow); + }; + + TimelineCSVExporter.prototype.options = function () { + return { + headers: this.columns.map(function (column) { + return column.name(); + }) + }; + }; + + return TimelineCSVExporter; +}); \ No newline at end of file From a444fc01ad6941af3d9035a390d03af24ae4cab4 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 8 Feb 2016 17:34:10 -0800 Subject: [PATCH 006/164] [Timeline] Fix column module definitions --- platform/features/timeline/src/actions/CompositionColumn.js | 4 ++++ platform/features/timeline/src/actions/MetadataColumn.js | 4 ++++ platform/features/timeline/src/actions/ModeColumn.js | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/platform/features/timeline/src/actions/CompositionColumn.js b/platform/features/timeline/src/actions/CompositionColumn.js index 35cbd75f69..6ee7fa010c 100644 --- a/platform/features/timeline/src/actions/CompositionColumn.js +++ b/platform/features/timeline/src/actions/CompositionColumn.js @@ -22,6 +22,8 @@ /*global define*/ define([], function () { + "use strict"; + function CompositionColumn(index) { this.index = index; } @@ -35,4 +37,6 @@ define([], function () { composition = model.composition || []; return (composition[this.index]) || ""; }; + + return CompositionColumn; }); diff --git a/platform/features/timeline/src/actions/MetadataColumn.js b/platform/features/timeline/src/actions/MetadataColumn.js index d31ae1a329..c798b229bc 100644 --- a/platform/features/timeline/src/actions/MetadataColumn.js +++ b/platform/features/timeline/src/actions/MetadataColumn.js @@ -22,6 +22,8 @@ /*global define*/ define([], function () { + "use strict"; + function MetadataColumn(property) { this.property = property; } @@ -38,4 +40,6 @@ define([], function () { }); return property ? property.value : ""; }; + + return MetadataColumn; }); diff --git a/platform/features/timeline/src/actions/ModeColumn.js b/platform/features/timeline/src/actions/ModeColumn.js index 545bdc19fc..0a88437211 100644 --- a/platform/features/timeline/src/actions/ModeColumn.js +++ b/platform/features/timeline/src/actions/ModeColumn.js @@ -22,6 +22,8 @@ /*global define*/ define([], function () { + "use strict"; + function ModeColumn(index) { this.index = index; } @@ -35,4 +37,6 @@ define([], function () { composition = (model.relationships || {}).modes || []; return (composition[this.index]) || ""; }; + + return ModeColumn; }); From b42ccebd5aa174acc448a907d5bab59c86781d79 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 8 Feb 2016 17:42:26 -0800 Subject: [PATCH 007/164] [Timeline] Fix imports, dependencies Fix imports and dependencies needed by Export Timeline as CSV --- platform/features/timeline/bundle.js | 11 +++++++++++ .../src/actions/ExportTimelineAsCSVAction.js | 12 ++++++++---- .../timeline/src/actions/ExportTimelineAsCSVTask.js | 3 ++- .../timeline/src/actions/TimelineCSVExporter.js | 6 +++--- .../timeline/src/actions/TimelineTraverser.js | 1 + 5 files changed, 25 insertions(+), 8 deletions(-) diff --git a/platform/features/timeline/bundle.js b/platform/features/timeline/bundle.js index a791fc4fb0..3cf2935bc6 100644 --- a/platform/features/timeline/bundle.js +++ b/platform/features/timeline/bundle.js @@ -22,6 +22,7 @@ /*global define*/ define([ + "./src/actions/ExportTimelineAsCSVAction", "./src/controllers/TimelineController", "./src/controllers/TimelineGraphController", "./src/controllers/TimelineDateTimeController", @@ -40,6 +41,7 @@ define([ "./src/services/ObjectLoader", 'legacyRegistry' ], function ( + ExportTimelineAsCSVAction, TimelineController, TimelineGraphController, TimelineDateTimeController, @@ -65,6 +67,15 @@ define([ "description": "Resources, templates, CSS, and code for Timelines.", "resources": "res", "extensions": { + "actions": [ + { + "key": "timeline.export", + "name": "Export Timeline as CSV", + "category": "contextual", + "implementation": ExportTimelineAsCSVAction, + "depends": [ "exportService" ] + } + ], "constants": [ { "key": "TIMELINE_MINIMUM_DURATION", diff --git a/platform/features/timeline/src/actions/ExportTimelineAsCSVAction.js b/platform/features/timeline/src/actions/ExportTimelineAsCSVAction.js index 2e0dc71589..099261256f 100644 --- a/platform/features/timeline/src/actions/ExportTimelineAsCSVAction.js +++ b/platform/features/timeline/src/actions/ExportTimelineAsCSVAction.js @@ -24,13 +24,17 @@ define(["./ExportTimelineAsCSVTask"], function (ExportTimelineAsCSVTask) { 'use strict'; - function ExportTimelineAsCSVAction(taskService, context) { - this.task = new ExportTimelineAsCSVTask(context.domainObject); - this.taskService = taskService; + function ExportTimelineAsCSVAction(exportService, context) { + this.task = new ExportTimelineAsCSVTask( + exportService, + context.domainObject + ); + //this.taskService = taskService; } ExportTimelineAsCSVAction.prototype.perform = function () { - return this.taskService.run(this.task); + return this.task.run(); + //return this.taskService.run(this.task); }; ExportTimelineAsCSVAction.appliesTo = function (context) { diff --git a/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js b/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js index 45ebdffd2f..a854716367 100644 --- a/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js +++ b/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js @@ -25,7 +25,8 @@ * Module defining ExportTimelineAsCSVTask. Created by vwoeltje on 2/8/16. */ define([ - "TimelineTraverser" + "./TimelineTraverser", + "./TimelineCSVExporter" ], function (TimelineTraverser, TimelineCSVExporter) { "use strict"; diff --git a/platform/features/timeline/src/actions/TimelineCSVExporter.js b/platform/features/timeline/src/actions/TimelineCSVExporter.js index b42debad93..8364ab2c01 100644 --- a/platform/features/timeline/src/actions/TimelineCSVExporter.js +++ b/platform/features/timeline/src/actions/TimelineCSVExporter.js @@ -22,9 +22,9 @@ /*global define,Promise*/ define([ - "ModeColumn", - "CompositionColumn", - "MetadataColumn" + "./ModeColumn", + "./CompositionColumn", + "./MetadataColumn" ], function (ModeColumn, CompositionColumn, MetadataColumn) { 'use strict'; diff --git a/platform/features/timeline/src/actions/TimelineTraverser.js b/platform/features/timeline/src/actions/TimelineTraverser.js index 0f701a4799..48817b6963 100644 --- a/platform/features/timeline/src/actions/TimelineTraverser.js +++ b/platform/features/timeline/src/actions/TimelineTraverser.js @@ -22,6 +22,7 @@ /*global define,Promise*/ define([], function () { + "use strict"; function TimelineTraverser(domainObject) { this.domainObject = domainObject; From 273cf1c14f171a5d33d0af20d85ddb32fe62ac0f Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 8 Feb 2016 18:07:03 -0800 Subject: [PATCH 008/164] [Timeline] Fix columns exported --- .../timeline/src/actions/ExportTimelineAsCSVTask.js | 3 ++- platform/features/timeline/src/actions/MetadataColumn.js | 8 ++++---- .../features/timeline/src/actions/TimelineCSVExporter.js | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js b/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js index a854716367..77f0702497 100644 --- a/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js +++ b/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js @@ -53,7 +53,8 @@ define([ ); } - return new TimelineTraverser().buildObjectList() + return new TimelineTraverser(this.domainObject) + .buildObjectList() .then(doExport); }; diff --git a/platform/features/timeline/src/actions/MetadataColumn.js b/platform/features/timeline/src/actions/MetadataColumn.js index c798b229bc..64a0d5b2bb 100644 --- a/platform/features/timeline/src/actions/MetadataColumn.js +++ b/platform/features/timeline/src/actions/MetadataColumn.js @@ -24,17 +24,17 @@ define([], function () { "use strict"; - function MetadataColumn(property) { - this.property = property; + function MetadataColumn(propertyName) { + this.propertyName = propertyName; } MetadataColumn.prototype.name = function () { - return this.property.name; + return this.propertyName; }; MetadataColumn.prototype.value = function (domainObject) { var properties = domainObject.useCapability('metadata'), - name = this.property.name, + name = this.propertyName, property = properties.find(function (p) { return p.name === name; }); diff --git a/platform/features/timeline/src/actions/TimelineCSVExporter.js b/platform/features/timeline/src/actions/TimelineCSVExporter.js index 8364ab2c01..ed7bf2b953 100644 --- a/platform/features/timeline/src/actions/TimelineCSVExporter.js +++ b/platform/features/timeline/src/actions/TimelineCSVExporter.js @@ -64,7 +64,7 @@ define([ } for (i = 0; i < maxRelationships; i += 1) { - columns.push(new RelationshipColumn(i)); + columns.push(new ModeColumn(i)); } this.domainObjects = domainObjects; From 071a908c10cc79290b936b79e1ebf827c94a7897 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Thu, 3 Mar 2016 15:58:28 -0800 Subject: [PATCH 009/164] [Info Bubble] Don't clobber arrow classes #716 --- platform/commonUI/inspect/src/services/InfoService.js | 1 - 1 file changed, 1 deletion(-) diff --git a/platform/commonUI/inspect/src/services/InfoService.js b/platform/commonUI/inspect/src/services/InfoService.js index eb929027ac..667b7ee892 100644 --- a/platform/commonUI/inspect/src/services/InfoService.js +++ b/platform/commonUI/inspect/src/services/InfoService.js @@ -85,7 +85,6 @@ define( popup.goesUp() ? 'arw-btm' : 'arw-top', popup.goesLeft() ? 'arw-right' : 'arw-left' ].join(' '); - scope.bubbleLayout = 'arw-top arw-left'; // Create the info bubble, now that we know how to // point the arrow... From f302bd6cb2787f6b2b43a16463dc39b573eff876 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Thu, 3 Mar 2016 16:17:01 -0800 Subject: [PATCH 010/164] [Info Bubble] Test arrow class application #716 --- .../inspect/test/services/InfoServiceSpec.js | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/platform/commonUI/inspect/test/services/InfoServiceSpec.js b/platform/commonUI/inspect/test/services/InfoServiceSpec.js index f55d72d04f..ca0f20283b 100644 --- a/platform/commonUI/inspect/test/services/InfoServiceSpec.js +++ b/platform/commonUI/inspect/test/services/InfoServiceSpec.js @@ -109,6 +109,35 @@ define( ); }); + [ false, true ].forEach(function (goesLeft) { + [ false, true].forEach(function (goesUp) { + var vertical = goesUp ? "up" : "down", + horizontal = goesLeft ? "left" : "right", + location = [ vertical, horizontal].join('-'); + describe("when bubble goes " + location, function () { + var expectedLocation = [ + goesUp ? "bottom" : "top", + goesLeft ? "right" : "left" + ].join('-'); + + beforeEach(function () { + mockPopup.goesUp.andReturn(goesUp); + mockPopup.goesDown.andReturn(!goesUp); + mockPopup.goesLeft.andReturn(goesLeft); + mockPopup.goesRight.andReturn(!goesLeft); + service.display('', '', {}, [ 10, 10 ]); + }); + + it("positions the arrow in the " + expectedLocation, function () { + expect(mockScope.bubbleLayout).toEqual([ + goesUp ? "arw-btm" : "arw-top", + goesLeft ? "arw-right" : "arw-left" + ].join(' ')); + }); + }); + }); + }); + }); } ); From 18167eddf8e1fa1139ceaabdf17e8083511c8c9a Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Thu, 3 Mar 2016 17:14:04 -0800 Subject: [PATCH 011/164] [Build] Enforce code coverage threshold Addresses #672 --- karma.conf.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/karma.conf.js b/karma.conf.js index 20624e4713..578a869484 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -81,7 +81,12 @@ module.exports = function(config) { coverageReporter: { dir: process.env.CIRCLE_ARTIFACTS ? process.env.CIRCLE_ARTIFACTS + '/coverage' : - "dist/coverage" + "dist/coverage", + check: { + global: { + lines: 80 + } + } }, // HTML test reporting. From 7c2ddf39267e80ff4de8f1ef52b98c83eb381862 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 4 Mar 2016 13:48:31 -0800 Subject: [PATCH 012/164] [Build] Remove snapshot status ...to close sprint Ellison, https://github.com/nasa/openmctweb/milestones/Ellison --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c0afb1c9ce..961b38a40f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openmctweb", - "version": "0.9.2-SNAPSHOT", + "version": "0.9.2", "description": "The Open MCT Web core platform", "dependencies": { "express": "^4.13.1", From ff5f37dfbedef91b416d557c3bf702fd3c0a395e Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 4 Mar 2016 13:59:41 -0800 Subject: [PATCH 013/164] [Build] Bump version number ...and add SNAPSHOT status, to begin sprint Gibson. https://github.com/nasa/openmctweb/milestones/Gibson --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 961b38a40f..37725e7d24 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openmctweb", - "version": "0.9.2", + "version": "0.9.3-SNAPSHOT", "description": "The Open MCT Web core platform", "dependencies": { "express": "^4.13.1", From 2d305415b3de4191a718d38c81c395bf84542715 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 7 Mar 2016 14:42:40 -0800 Subject: [PATCH 014/164] [Search] Index directly on mutation Pass model directly when indexing is triggered via object mutation, to avoid issuing an extra, unnecessary request to the server. Additionally supports indexing of objects which have been created but not yet persisted. Addresses #377. --- platform/search/src/services/GenericSearchProvider.js | 6 +++--- .../search/test/services/GenericSearchProviderSpec.js | 9 ++++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/platform/search/src/services/GenericSearchProvider.js b/platform/search/src/services/GenericSearchProvider.js index 71dfe8c0ed..251b0d98ff 100644 --- a/platform/search/src/services/GenericSearchProvider.js +++ b/platform/search/src/services/GenericSearchProvider.js @@ -121,9 +121,9 @@ define([ provider = this; mutationTopic.listen(function (mutatedObject) { - var id = mutatedObject.getId(); - provider.indexedIds[id] = false; - provider.scheduleForIndexing(id); + var id = mutatedObject.getId(), + model = mutatedObject.getModel(); + provider.index(id, model); }); }; diff --git a/platform/search/test/services/GenericSearchProviderSpec.js b/platform/search/test/services/GenericSearchProviderSpec.js index cc80e4210d..9934d5130a 100644 --- a/platform/search/test/services/GenericSearchProviderSpec.js +++ b/platform/search/test/services/GenericSearchProviderSpec.js @@ -99,12 +99,15 @@ define([ .toHaveBeenCalledWith(jasmine.any(Function)); }); - it('reschedules indexing when mutation occurs', function () { + it('re-indexes when mutation occurs', function () { var mockDomainObject = - jasmine.createSpyObj('domainObj', ['getId']); + jasmine.createSpyObj('domainObj', ['getId', 'getModel']), + testModel = { some: 'model' }; mockDomainObject.getId.andReturn("some-id"); + mockDomainObject.getModel.andReturn(testModel); + spyOn(provider, 'index').andCallThrough(); mutationTopic.listen.mostRecentCall.args[0](mockDomainObject); - expect(provider.scheduleForIndexing).toHaveBeenCalledWith('some-id'); + expect(provider.index).toHaveBeenCalledWith('some-id', testModel); }); it('starts indexing roots', function () { From a509dfb840976997c4bf166a5fda0f537de6ea4f Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 7 Mar 2016 15:30:57 -0800 Subject: [PATCH 015/164] [Timelines] Remove unused TaskService https://developer.nasa.gov/mct/warp/issues/135 --- .../execution/src/TaskProgressReporter.js | 36 --------- platform/execution/src/TaskService.js | 74 ------------------- 2 files changed, 110 deletions(-) delete mode 100644 platform/execution/src/TaskProgressReporter.js delete mode 100644 platform/execution/src/TaskService.js diff --git a/platform/execution/src/TaskProgressReporter.js b/platform/execution/src/TaskProgressReporter.js deleted file mode 100644 index f993a1a835..0000000000 --- a/platform/execution/src/TaskProgressReporter.js +++ /dev/null @@ -1,36 +0,0 @@ -/***************************************************************************** - * 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"; - - function TaskProgressReporter(dialogService, notificationService) { - this.dialogService = dialogService; - this.notificationService = notificationService; - } - - TaskProgressReporter.prototype.cancel = function () { - - }; - -}); diff --git a/platform/execution/src/TaskService.js b/platform/execution/src/TaskService.js deleted file mode 100644 index a5f5c06697..0000000000 --- a/platform/execution/src/TaskService.js +++ /dev/null @@ -1,74 +0,0 @@ -/***************************************************************************** - * 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*/ - - -/** - * This bundle contains services for managing the flow of execution, - * such as support for running web workers on background threads. - * @namespace platform/execution - */ -define( - [], - function () { - "use strict"; - - /** - * Runs long-running tasks with progress reporting. - * @memberof platform/execution - * @constructor - */ - function TaskService(dialogService, notificationService) { - this.dialogService = dialogService; - this.notificationService = notificationService; - } - - /** - * Invoked to update progress associated with a running task. - * @callback TaskService~progressCallback - * @param {NotificationModel} model current progress to show - */ - - /** - * Initiate a new task. - * - * @param {function(progress : TaskService~progressCallback} : Task)} - * taskFactory a function which, when provided a - * progress-reporting callback, will return the task to run. - * @returns {Promise} a promise for the result of the task - */ - TaskService.prototype.run = function (task) { - var model = {}, - dialogService = this.dialogService, - notificationService = this.notificationService; - - function reportProgress(progressModel) { - - } - - return task.run(reportProgress); - }; - - return TaskService; - } -); - From b383921f2a913b6a64a95a6a4866b286c80978f6 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 7 Mar 2016 16:00:13 -0800 Subject: [PATCH 016/164] [Timeline] Export start/end to CSV --- .../src/actions/ExportTimelineAsCSVTask.js | 12 +++-- .../src/actions/TimelineCSVExporter.js | 24 ++++++---- .../timeline/src/actions/TimespanColumn.js | 44 +++++++++++++++++++ 3 files changed, 65 insertions(+), 15 deletions(-) create mode 100644 platform/features/timeline/src/actions/TimespanColumn.js diff --git a/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js b/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js index 77f0702497..8a0b60ca94 100644 --- a/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js +++ b/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js @@ -41,16 +41,14 @@ define([ this.exportService = exportService; } - ExportTimelineAsCSVTask.prototype.run = function (progress) { - var name = this.domainObject.getModel().name, - exportService = this.exportService; + ExportTimelineAsCSVTask.prototype.run = function () { + var exportService = this.exportService; function doExport(objects) { var exporter = new TimelineCSVExporter(objects); - return exportService.exportCSV( - exporter.rows(), - exporter.options() - ); + return exporter.rows().then(function (rows) { + return exportService.exportCSV(rows, exporter.options()); + }); } return new TimelineTraverser(this.domainObject) diff --git a/platform/features/timeline/src/actions/TimelineCSVExporter.js b/platform/features/timeline/src/actions/TimelineCSVExporter.js index ed7bf2b953..4ef27b3bc3 100644 --- a/platform/features/timeline/src/actions/TimelineCSVExporter.js +++ b/platform/features/timeline/src/actions/TimelineCSVExporter.js @@ -24,8 +24,9 @@ define([ "./ModeColumn", "./CompositionColumn", - "./MetadataColumn" -], function (ModeColumn, CompositionColumn, MetadataColumn) { + "./MetadataColumn", + "./TimespanColumn" +], function (ModeColumn, CompositionColumn, MetadataColumn, TimespanColumn) { 'use strict'; function TimelineCSVExporter(domainObjects) { @@ -33,6 +34,7 @@ define([ maxRelationships = 0, columnNames = {}, columns = [], + foundTimespan = false, i; function addMetadataProperty(property) { @@ -56,9 +58,17 @@ define([ maxComposition = Math.max(maxComposition, compositionLength); maxRelationships = Math.max(maxRelationships, relationshipLength); + foundTimespan = + foundTimespan || domainObject.hasCapability('timespan'); + metadataProperties.forEach(addMetadataProperty); }); + if (foundTimespan) { + columns.push(new TimespanColumn(true)); + columns.push(new TimespanColumn(false)); + } + for (i = 0; i < maxComposition; i += 1) { columns.push(new CompositionColumn(i)); } @@ -75,14 +85,12 @@ define([ var columns = this.columns; function toRow(domainObject) { - var row = {}; - columns.forEach(function (column) { - row[column.name()] = column.value(domainObject); - }); - return row; + return Promise.all(columns.map(function (column) { + return column.value(domainObject); + })); } - return this.domainObjects.map(toRow); + return Promise.all(this.domainObjects.map(toRow)); }; TimelineCSVExporter.prototype.options = function () { diff --git a/platform/features/timeline/src/actions/TimespanColumn.js b/platform/features/timeline/src/actions/TimespanColumn.js new file mode 100644 index 0000000000..e6cb118591 --- /dev/null +++ b/platform/features/timeline/src/actions/TimespanColumn.js @@ -0,0 +1,44 @@ +/***************************************************************************** + * 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"; + + function TimespanColumn(isStart) { + this.isStart = isStart; + } + + TimespanColumn.prototype.name = function () { + return this.isStart ? "Start" : "End"; + }; + + TimespanColumn.prototype.value = function (domainObject) { + var isStart = this.isStart; + return domainObject.hasCapability('timespan') ? + domainObject.useCapability('timespan').then(function (timespan) { + return isStart ? timespan.getStart() : timespan.getEnd(); + }) : ""; + }; + + return TimespanColumn; +}); From 14b8e02f27b5baba7c7c89154eb12a6ea148452d Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 7 Mar 2016 16:02:33 -0800 Subject: [PATCH 017/164] [Timeline] Format exported start/end times --- platform/features/timeline/src/actions/TimespanColumn.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/platform/features/timeline/src/actions/TimespanColumn.js b/platform/features/timeline/src/actions/TimespanColumn.js index e6cb118591..b970143f07 100644 --- a/platform/features/timeline/src/actions/TimespanColumn.js +++ b/platform/features/timeline/src/actions/TimespanColumn.js @@ -21,9 +21,11 @@ *****************************************************************************/ /*global define*/ -define([], function () { +define(['../TimelineFormatter'], function (TimelineFormatter) { "use strict"; + var FORMATTER = new TimelineFormatter(); + function TimespanColumn(isStart) { this.isStart = isStart; } @@ -36,7 +38,9 @@ define([], function () { var isStart = this.isStart; return domainObject.hasCapability('timespan') ? domainObject.useCapability('timespan').then(function (timespan) { - return isStart ? timespan.getStart() : timespan.getEnd(); + return FORMATTER.format( + isStart ? timespan.getStart() : timespan.getEnd() + ); }) : ""; }; From c4f1c4ad1f356dd1274a1f5e5691284102d20413 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 7 Mar 2016 16:09:23 -0800 Subject: [PATCH 018/164] [Timeline] Show progress notification during export --- platform/features/timeline/bundle.js | 2 +- .../src/actions/ExportTimelineAsCSVAction.js | 20 +++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/platform/features/timeline/bundle.js b/platform/features/timeline/bundle.js index 3da27cd925..f298cb887e 100644 --- a/platform/features/timeline/bundle.js +++ b/platform/features/timeline/bundle.js @@ -93,7 +93,7 @@ define([ "name": "Export Timeline as CSV", "category": "contextual", "implementation": ExportTimelineAsCSVAction, - "depends": [ "exportService" ] + "depends": [ "exportService", "notificationService" ] } ], "constants": [ diff --git a/platform/features/timeline/src/actions/ExportTimelineAsCSVAction.js b/platform/features/timeline/src/actions/ExportTimelineAsCSVAction.js index 099261256f..37c1fddbf0 100644 --- a/platform/features/timeline/src/actions/ExportTimelineAsCSVAction.js +++ b/platform/features/timeline/src/actions/ExportTimelineAsCSVAction.js @@ -24,17 +24,29 @@ define(["./ExportTimelineAsCSVTask"], function (ExportTimelineAsCSVTask) { 'use strict'; - function ExportTimelineAsCSVAction(exportService, context) { + function ExportTimelineAsCSVAction(exportService, notificationService, context) { this.task = new ExportTimelineAsCSVTask( exportService, context.domainObject ); - //this.taskService = taskService; + this.notificationService = notificationService; } ExportTimelineAsCSVAction.prototype.perform = function () { - return this.task.run(); - //return this.taskService.run(this.task); + var notificationService = this.notificationService, + notification = notificationService.notify({ + title: "Exporting CSV", + unknownProgress: true + }); + + return this.task.run() + .then(function () { + notification.dismiss(); + }) + .catch(function () { + notification.dismiss(); + notificationService.error("Error exporting CSV"); + }); }; ExportTimelineAsCSVAction.appliesTo = function (context) { From 5d771edcf7bc5b7c027fc4bd51c1b39a78dd4540 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 7 Mar 2016 16:13:23 -0800 Subject: [PATCH 019/164] [Timeline] Begin testing CSV Export --- .../test/actions/CompositionColumnSpec.js | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 platform/features/timeline/test/actions/CompositionColumnSpec.js diff --git a/platform/features/timeline/test/actions/CompositionColumnSpec.js b/platform/features/timeline/test/actions/CompositionColumnSpec.js new file mode 100644 index 0000000000..d9b340604a --- /dev/null +++ b/platform/features/timeline/test/actions/CompositionColumnSpec.js @@ -0,0 +1,42 @@ +/***************************************************************************** + * 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,describe,it,expect,beforeEach,waitsFor,jasmine,window,afterEach*/ + +define( + ['../../src/actions/CompositionColumn'], + function (CompositionColumn) { + describe("CompositionColumn", function () { + var testIndex, + column; + + beforeEach(function () { + testIndex = 42; + column = new CompositionColumn(testIndex); + }); + + it("includes a one-based index in its name", function () { + expect(column.name().indexOf(String(testIndex + 1))) + .not.toEqual(-1); + }); + }); + } +); \ No newline at end of file From cdac0ad67fb3dfb99fb2ae637b11b670db133f25 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 7 Mar 2016 16:17:19 -0800 Subject: [PATCH 020/164] [Timeline] Add test cases for CSV Export --- .../test/actions/CompositionColumnSpec.js | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/platform/features/timeline/test/actions/CompositionColumnSpec.js b/platform/features/timeline/test/actions/CompositionColumnSpec.js index d9b340604a..99e23d5597 100644 --- a/platform/features/timeline/test/actions/CompositionColumnSpec.js +++ b/platform/features/timeline/test/actions/CompositionColumnSpec.js @@ -29,7 +29,7 @@ define( column; beforeEach(function () { - testIndex = 42; + testIndex = 3; column = new CompositionColumn(testIndex); }); @@ -37,6 +37,38 @@ define( expect(column.name().indexOf(String(testIndex + 1))) .not.toEqual(-1); }); + + describe("value", function () { + var mockDomainObject, + testModel; + + beforeEach(function () { + mockDomainObject = jasmine.createSpyObj( + 'domainObject', + [ 'getId', 'getModel', 'getCapability' ] + ); + testModel = { + composition: [ 'a', 'b', 'c', 'd', 'e', 'f' ] + }; + mockDomainObject.getModel.andReturn(testModel); + }); + + it("returns a corresponding identifier", function () { + expect(column.value(mockDomainObject)) + .toEqual(testModel.composition[testIndex]); + }); + + it("returns nothing when composition is exceeded", function () { + testModel.composition = [ 'foo' ]; + expect(column.value(mockDomainObject)).toEqual(""); + }); + + it("returns nothing when composition is absent", function () { + delete testModel.composition; + expect(column.value(mockDomainObject)).toEqual(""); + }); + }); + }); } ); \ No newline at end of file From f9ff9921a94488c749b966941407fc363b233a12 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 7 Mar 2016 16:22:39 -0800 Subject: [PATCH 021/164] [Timelines] Continue testing CSV Export ...with initial test cases for the action itself. --- .../actions/ExportTimelineAsCSVActionSpec.js | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 platform/features/timeline/test/actions/ExportTimelineAsCSVActionSpec.js diff --git a/platform/features/timeline/test/actions/ExportTimelineAsCSVActionSpec.js b/platform/features/timeline/test/actions/ExportTimelineAsCSVActionSpec.js new file mode 100644 index 0000000000..5c2a561728 --- /dev/null +++ b/platform/features/timeline/test/actions/ExportTimelineAsCSVActionSpec.js @@ -0,0 +1,63 @@ +/***************************************************************************** + * 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,describe,it,expect,beforeEach,waitsFor,jasmine,window,afterEach*/ + +define( + ['../../src/actions/ExportTimelineAsCSVAction'], + function (ExportTimelineAsCSVAction) { + describe("ExportTimelineAsCSVAction", function () { + var mockDomainObject, + mockType, + testContext, + testType, + action; + + beforeEach(function () { + mockDomainObject = jasmine.createSpyObj( + 'domainObject', + [ 'getId', 'getModel', 'getCapability', 'hasCapability' ] + ); + mockType = jasmine.createSpyObj('type', [ 'instanceOf' ]); + + mockDomainObject.hasCapability.andReturn(true); + mockDomainObject.getCapability.andReturn(mockType); + mockType.instanceOf.andCallFake(function (type) { + return type === testType; + }); + + testContext = { domainObject: mockDomainObject }; + }); + + it("is applicable to timelines", function () { + testType = 'timeline'; + expect(ExportTimelineAsCSVAction.appliesTo(testContext)) + .toBe(true); + }); + + it("is not applicable to non-timelines", function () { + testType = 'folder'; + expect(ExportTimelineAsCSVAction.appliesTo(testContext)) + .toBe(false); + }); + }); + } +); \ No newline at end of file From 7c140c06dc42cc231e509c95212ecb7121f9cca7 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 7 Mar 2016 16:33:03 -0800 Subject: [PATCH 022/164] [Timeline] Test CSV Export action itself --- .../actions/ExportTimelineAsCSVActionSpec.js | 92 ++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) diff --git a/platform/features/timeline/test/actions/ExportTimelineAsCSVActionSpec.js b/platform/features/timeline/test/actions/ExportTimelineAsCSVActionSpec.js index 5c2a561728..3d5cd8b01c 100644 --- a/platform/features/timeline/test/actions/ExportTimelineAsCSVActionSpec.js +++ b/platform/features/timeline/test/actions/ExportTimelineAsCSVActionSpec.js @@ -25,7 +25,10 @@ define( ['../../src/actions/ExportTimelineAsCSVAction'], function (ExportTimelineAsCSVAction) { describe("ExportTimelineAsCSVAction", function () { - var mockDomainObject, + var mockExportService, + mockNotificationService, + mockNotification, + mockDomainObject, mockType, testContext, testType, @@ -37,6 +40,20 @@ define( [ 'getId', 'getModel', 'getCapability', 'hasCapability' ] ); mockType = jasmine.createSpyObj('type', [ 'instanceOf' ]); + mockExportService = jasmine.createSpyObj( + 'exportService', + [ 'exportCSV' ] + ); + mockNotificationService = jasmine.createSpyObj( + 'notificationService', + [ 'notify', 'error' ] + ); + mockNotification = jasmine.createSpyObj( + 'notification', + [ 'dismiss' ] + ); + + mockNotificationService.notify.andReturn(mockNotification); mockDomainObject.hasCapability.andReturn(true); mockDomainObject.getCapability.andReturn(mockType); @@ -45,6 +62,12 @@ define( }); testContext = { domainObject: mockDomainObject }; + + action = new ExportTimelineAsCSVAction( + mockExportService, + mockNotificationService, + testContext + ); }); it("is applicable to timelines", function () { @@ -58,6 +81,73 @@ define( expect(ExportTimelineAsCSVAction.appliesTo(testContext)) .toBe(false); }); + + describe("when performed", function () { + var testPromise, + mockCallback; + + beforeEach(function () { + mockCallback = jasmine.createSpy('callback'); + // White-boxy; we know most work is delegated + // to the associated Task, so stub out that interaction. + spyOn(action.task, "run").andCallFake(function () { + return new Promise(function (resolve, reject) { + testPromise = { + resolve: resolve, + reject: reject + }; + }); + }); + action.perform().then(mockCallback); + }); + + it("shows a notification", function () { + expect(mockNotificationService.notify) + .toHaveBeenCalled(); + }); + + it("starts an export task", function () { + expect(action.task.run).toHaveBeenCalled(); + }); + + describe("and completed", function () { + beforeEach(function () { + testPromise.resolve(); + waitsFor(function () { + return mockCallback.calls.length > 0; + }); + }); + + it("dismisses the displayed notification", function () { + expect(mockNotification.dismiss) + .toHaveBeenCalled(); + }); + + it("shows no error messages", function () { + expect(mockNotificationService.error) + .not.toHaveBeenCalled(); + }); + }); + + describe("and an error occurs", function () { + beforeEach(function () { + testPromise.reject(); + waitsFor(function () { + return mockCallback.calls.length > 0; + }); + }); + + it("dismisses the displayed notification", function () { + expect(mockNotification.dismiss) + .toHaveBeenCalled(); + }); + + it("shows an error message", function () { + expect(mockNotificationService.error) + .toHaveBeenCalledWith(jasmine.any(String)); + }); + }); + }); }); } ); \ No newline at end of file From d5283d57e4331ca58638723fa3e34306e4e4ce7c Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 7 Mar 2016 16:35:40 -0800 Subject: [PATCH 023/164] [Timeline] Add missing semicolon --- platform/features/timeline/src/actions/TimelineCSVExporter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/features/timeline/src/actions/TimelineCSVExporter.js b/platform/features/timeline/src/actions/TimelineCSVExporter.js index 4ef27b3bc3..bc73d6f782 100644 --- a/platform/features/timeline/src/actions/TimelineCSVExporter.js +++ b/platform/features/timeline/src/actions/TimelineCSVExporter.js @@ -41,7 +41,7 @@ define([ var name = property.name; if (!columnNames[name]) { columnNames[name] = true; - columns.push(new MetadataColumn(name)) + columns.push(new MetadataColumn(name)); } } From dd66cb60d8bdf98b7ccae39c725015d2cd4b8860 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 8 Mar 2016 09:47:09 -0800 Subject: [PATCH 024/164] [Timeline] Test export task --- .../actions/ExportTimelineAsCSVTaskSpec.js | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 platform/features/timeline/test/actions/ExportTimelineAsCSVTaskSpec.js diff --git a/platform/features/timeline/test/actions/ExportTimelineAsCSVTaskSpec.js b/platform/features/timeline/test/actions/ExportTimelineAsCSVTaskSpec.js new file mode 100644 index 0000000000..7979104ee5 --- /dev/null +++ b/platform/features/timeline/test/actions/ExportTimelineAsCSVTaskSpec.js @@ -0,0 +1,79 @@ +/***************************************************************************** + * 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,describe,it,expect,beforeEach,waitsFor,jasmine,window,afterEach*/ + +define( + ['../../src/actions/ExportTimelineAsCSVTask'], + function (ExportTimelineAsCSVTask) { + 'use strict'; + + // Note that most responsibility is delegated to helper + // classes, so testing here is minimal. + describe("EXportTimelineAsCSVTask", function () { + var mockExportService, + mockDomainObject, + task; + + beforeEach(function () { + mockExportService = jasmine.createSpyObj( + 'exportService', + [ 'exportCSV' ] + ); + mockDomainObject = jasmine.createSpyObj( + 'domainObject', + [ + 'getCapability', + 'useCapability', + 'hasCapability', + 'getId', + 'getModel' + ] + ); + + mockDomainObject.getId.andReturn('mock'); + mockDomainObject.getModel.andReturn({}); + + task = new ExportTimelineAsCSVTask( + mockExportService, + mockDomainObject + ); + }); + + describe("when run", function () { + var mockCallback; + + beforeEach(function () { + mockCallback = jasmine.createSpy('callback'); + task.run().then(mockCallback); + waitsFor(function () { + return mockCallback.calls.length > 0; + }); + }); + + it("exports to CSV", function () { + expect(mockExportService.exportCSV) + .toHaveBeenCalled(); + }); + }); + }); + } +); From ed679756b36301e4bf77faec1aa54888aa3aa6e2 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 8 Mar 2016 09:56:21 -0800 Subject: [PATCH 025/164] [Timelines] Test metadata columns in CSV Export ...and additionally refactor to run in a test environment (don't use Array.prototype.find) --- .../timeline/src/actions/MetadataColumn.js | 10 +-- .../test/actions/MetadataColumnSpec.js | 76 +++++++++++++++++++ 2 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 platform/features/timeline/test/actions/MetadataColumnSpec.js diff --git a/platform/features/timeline/src/actions/MetadataColumn.js b/platform/features/timeline/src/actions/MetadataColumn.js index 64a0d5b2bb..ee8694082b 100644 --- a/platform/features/timeline/src/actions/MetadataColumn.js +++ b/platform/features/timeline/src/actions/MetadataColumn.js @@ -34,11 +34,11 @@ define([], function () { MetadataColumn.prototype.value = function (domainObject) { var properties = domainObject.useCapability('metadata'), - name = this.propertyName, - property = properties.find(function (p) { - return p.name === name; - }); - return property ? property.value : ""; + name = this.propertyName; + return properties.reduce(function (value, property) { + return property.name === name ? + property.value : value; + }, ""); }; return MetadataColumn; diff --git a/platform/features/timeline/test/actions/MetadataColumnSpec.js b/platform/features/timeline/test/actions/MetadataColumnSpec.js new file mode 100644 index 0000000000..ba38fc83c0 --- /dev/null +++ b/platform/features/timeline/test/actions/MetadataColumnSpec.js @@ -0,0 +1,76 @@ +/***************************************************************************** + * 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,describe,it,expect,beforeEach,waitsFor,jasmine,window,afterEach*/ + +define( + ['../../src/actions/MetadataColumn'], + function (MetadataColumn) { + describe("MetadataColumn", function () { + var testName, + column; + + beforeEach(function () { + testName = 'Foo'; + column = new MetadataColumn(testName); + }); + + it("reports its property name", function () { + expect(column.name()).toEqual(testName); + }); + + describe("value", function () { + var mockDomainObject, + testMetadata, + testIndex; + + beforeEach(function () { + mockDomainObject = jasmine.createSpyObj( + 'domainObject', + [ 'getId', 'getModel', 'getCapability', 'useCapability' ] + ); + testMetadata = [ + { name: "Something else", value: 123 }, + { value: 456 }, + { name: "And something else", value: 789 } + ]; + testIndex = 1; + testMetadata[testIndex].name = testName; + + mockDomainObject.useCapability.andCallFake(function (c) { + return (c === 'metadata') && testMetadata; + }); + }); + + it("returns a corresponding value", function () { + expect(column.value(mockDomainObject)) + .toEqual(testMetadata[testIndex].value); + }); + + it("returns nothing when no such property is present", function () { + testMetadata[testIndex].name = "Not " + testName; + expect(column.value(mockDomainObject)).toEqual(""); + }); + }); + + }); + } +); \ No newline at end of file From 75d6803c9f35cbca753618e5ccdd11072e4c9e7a Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 8 Mar 2016 09:59:54 -0800 Subject: [PATCH 026/164] [Timeline] Test mode columns in CSV Export --- .../timeline/src/actions/ModeColumn.js | 2 +- .../timeline/test/actions/ModeColumnSpec.js | 76 +++++++++++++++++++ 2 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 platform/features/timeline/test/actions/ModeColumnSpec.js diff --git a/platform/features/timeline/src/actions/ModeColumn.js b/platform/features/timeline/src/actions/ModeColumn.js index 0a88437211..20a9de0e50 100644 --- a/platform/features/timeline/src/actions/ModeColumn.js +++ b/platform/features/timeline/src/actions/ModeColumn.js @@ -29,7 +29,7 @@ define([], function () { } ModeColumn.prototype.name = function () { - return "Mode " + (this.index + 1); + return "Activity Mode " + (this.index + 1); }; ModeColumn.prototype.value = function (domainObject) { diff --git a/platform/features/timeline/test/actions/ModeColumnSpec.js b/platform/features/timeline/test/actions/ModeColumnSpec.js new file mode 100644 index 0000000000..ab15d696c2 --- /dev/null +++ b/platform/features/timeline/test/actions/ModeColumnSpec.js @@ -0,0 +1,76 @@ +/***************************************************************************** + * 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,describe,it,expect,beforeEach,waitsFor,jasmine,window,afterEach*/ + +define( + ['../../src/actions/ModeColumn'], + function (ModeColumn) { + describe("ModeColumn", function () { + var testIndex, + column; + + beforeEach(function () { + testIndex = 3; + column = new ModeColumn(testIndex); + }); + + it("includes a one-based index in its name", function () { + expect(column.name().indexOf(String(testIndex + 1))) + .not.toEqual(-1); + }); + + describe("value", function () { + var mockDomainObject, + testModel; + + beforeEach(function () { + mockDomainObject = jasmine.createSpyObj( + 'domainObject', + [ 'getId', 'getModel', 'getCapability' ] + ); + testModel = { + relationships: { + modes: [ 'a', 'b', 'c', 'd', 'e', 'f' ] + } + }; + mockDomainObject.getModel.andReturn(testModel); + }); + + it("returns a corresponding identifier", function () { + expect(column.value(mockDomainObject)) + .toEqual(testModel.relationships.modes[testIndex]); + }); + + it("returns nothing when relationships are exceeded", function () { + testModel.relationships.modes = [ 'foo' ]; + expect(column.value(mockDomainObject)).toEqual(""); + }); + + it("returns nothing when mode relationships are absent", function () { + delete testModel.relationships.modes; + expect(column.value(mockDomainObject)).toEqual(""); + }); + }); + + }); + } +); \ No newline at end of file From 43db52fd702e156025141e4d2e7a61871f5751df Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 8 Mar 2016 10:04:09 -0800 Subject: [PATCH 027/164] [Timeline] Simplify interface ...such that responsibility for knowing exportService interface is more localized. --- .../timeline/src/actions/ExportTimelineAsCSVTask.js | 5 +++-- .../timeline/src/actions/TimelineCSVExporter.js | 10 ++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js b/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js index 8a0b60ca94..790b165fd7 100644 --- a/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js +++ b/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js @@ -45,9 +45,10 @@ define([ var exportService = this.exportService; function doExport(objects) { - var exporter = new TimelineCSVExporter(objects); + var exporter = new TimelineCSVExporter(objects), + options = { headers: exporter.headers() }; return exporter.rows().then(function (rows) { - return exportService.exportCSV(rows, exporter.options()); + return exportService.exportCSV(rows, options); }); } diff --git a/platform/features/timeline/src/actions/TimelineCSVExporter.js b/platform/features/timeline/src/actions/TimelineCSVExporter.js index bc73d6f782..3ebe37db1c 100644 --- a/platform/features/timeline/src/actions/TimelineCSVExporter.js +++ b/platform/features/timeline/src/actions/TimelineCSVExporter.js @@ -93,12 +93,10 @@ define([ return Promise.all(this.domainObjects.map(toRow)); }; - TimelineCSVExporter.prototype.options = function () { - return { - headers: this.columns.map(function (column) { - return column.name(); - }) - }; + TimelineCSVExporter.prototype.headers = function () { + return this.columns.map(function (column) { + return column.name(); + }); }; return TimelineCSVExporter; From 40895ec1b97bad45600527fb6f05c024f7b8b501 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 8 Mar 2016 10:07:21 -0800 Subject: [PATCH 028/164] [Timelines] Begin spec for exporter --- .../test/actions/TimelineCSVExporterSpec.js | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 platform/features/timeline/test/actions/TimelineCSVExporterSpec.js diff --git a/platform/features/timeline/test/actions/TimelineCSVExporterSpec.js b/platform/features/timeline/test/actions/TimelineCSVExporterSpec.js new file mode 100644 index 0000000000..c07eb29756 --- /dev/null +++ b/platform/features/timeline/test/actions/TimelineCSVExporterSpec.js @@ -0,0 +1,51 @@ +/***************************************************************************** + * 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,describe,it,expect,beforeEach,waitsFor,jasmine,window,afterEach*/ + +define( + ['../../src/actions/TimelineCSVExporter'], + function (TimelineCSVExporter) { + describe("TimelineCSVExporter", function () { + var mockDomainObjects, + exporter; + + beforeEach(function () { + mockDomainObjects = []; + exporter = new TimelineCSVExporter(mockDomainObjects); + }); + + it("includes one row per domain object", function () { + var mockCallback = jasmine.createSpy('callback'); + exporter.rows().then(mockCallback); + waitsFor(function () { + return mockCallback.calls.length > 0; + }); + runs(function () { + expect(mockCallback.mostRecentCall.args[0].length) + .toEqual(mockDomainObjects.length); + }); + }); + + + }); + } +); \ No newline at end of file From 9e6e33983b7f4a9017387519298553d3b80f46c1 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 8 Mar 2016 10:17:10 -0800 Subject: [PATCH 029/164] [Timeline] Add more objects to test case --- .../test/actions/TimelineCSVExporterSpec.js | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/platform/features/timeline/test/actions/TimelineCSVExporterSpec.js b/platform/features/timeline/test/actions/TimelineCSVExporterSpec.js index c07eb29756..0fb602e2ce 100644 --- a/platform/features/timeline/test/actions/TimelineCSVExporterSpec.js +++ b/platform/features/timeline/test/actions/TimelineCSVExporterSpec.js @@ -28,8 +28,29 @@ define( var mockDomainObjects, exporter; + function makeMockDomainObject(model, index) { + var mockDomainObject = jasmine.createSpyObj( + 'domainObject-' + index, + [ + 'getId', + 'getCapability', + 'useCapability', + 'hasCapability', + 'getModel' + ] + ); + mockDomainObject.getId.andReturn('id-' + index); + mockDomainObject.getModel.andReturn(model); + return mockDomainObject; + } + beforeEach(function () { - mockDomainObjects = []; + mockDomainObjects = [ + { composition: [ 'a', 'b', 'c' ] }, + { relationships: { modes: [ 'x', 'y' ] } }, + { } + ].map(makeMockDomainObject); + exporter = new TimelineCSVExporter(mockDomainObjects); }); From 938c266b4e718ad1e5ddcba35c1250ba741f144b Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 8 Mar 2016 10:20:25 -0800 Subject: [PATCH 030/164] [Timeline] Add Id column to CSV export --- .../features/timeline/src/actions/IdColumn.js | 39 +++++++++++++++++++ .../src/actions/TimelineCSVExporter.js | 11 +++++- 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 platform/features/timeline/src/actions/IdColumn.js diff --git a/platform/features/timeline/src/actions/IdColumn.js b/platform/features/timeline/src/actions/IdColumn.js new file mode 100644 index 0000000000..6efeb104d3 --- /dev/null +++ b/platform/features/timeline/src/actions/IdColumn.js @@ -0,0 +1,39 @@ +/***************************************************************************** + * 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"; + + function IdColumn() { + } + + IdColumn.prototype.name = function () { + return "Identifier"; + }; + + IdColumn.prototype.value = function (domainObject) { + return domainObject.getId(); + }; + + return IdColumn; +}); diff --git a/platform/features/timeline/src/actions/TimelineCSVExporter.js b/platform/features/timeline/src/actions/TimelineCSVExporter.js index 3ebe37db1c..f0d3efd953 100644 --- a/platform/features/timeline/src/actions/TimelineCSVExporter.js +++ b/platform/features/timeline/src/actions/TimelineCSVExporter.js @@ -22,11 +22,18 @@ /*global define,Promise*/ define([ + "./IdColumn", "./ModeColumn", "./CompositionColumn", "./MetadataColumn", "./TimespanColumn" -], function (ModeColumn, CompositionColumn, MetadataColumn, TimespanColumn) { +], function ( + IdColumn, + ModeColumn, + CompositionColumn, + MetadataColumn, + TimespanColumn +) { 'use strict'; function TimelineCSVExporter(domainObjects) { @@ -45,6 +52,8 @@ define([ } } + columns.push(new IdColumn()); + domainObjects.forEach(function (domainObject) { var model = domainObject.getModel(), compositionLength = model.composition ? From fd92c5f97088868dd277dfbb3f75db9674823bd0 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 8 Mar 2016 10:22:46 -0800 Subject: [PATCH 031/164] [Timeline] Add more tests for rows --- .../test/actions/TimelineCSVExporterSpec.js | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/platform/features/timeline/test/actions/TimelineCSVExporterSpec.js b/platform/features/timeline/test/actions/TimelineCSVExporterSpec.js index 0fb602e2ce..cbe382c988 100644 --- a/platform/features/timeline/test/actions/TimelineCSVExporterSpec.js +++ b/platform/features/timeline/test/actions/TimelineCSVExporterSpec.js @@ -54,19 +54,33 @@ define( exporter = new TimelineCSVExporter(mockDomainObjects); }); - it("includes one row per domain object", function () { - var mockCallback = jasmine.createSpy('callback'); - exporter.rows().then(mockCallback); - waitsFor(function () { - return mockCallback.calls.length > 0; + describe("rows", function () { + var rows; + + beforeEach(function () { + exporter.rows().then(function (r) { + rows = r; + }); + waitsFor(function () { + return rows !== undefined; + }); }); - runs(function () { - expect(mockCallback.mostRecentCall.args[0].length) - .toEqual(mockDomainObjects.length); + + + 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); + }); }); }); + }); } ); \ No newline at end of file From 0c2285719e66088301266131cbfd7c73267191bf Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 8 Mar 2016 10:27:50 -0800 Subject: [PATCH 032/164] [Timeline] Test inclusion of metadata headers --- .../test/actions/TimelineCSVExporterSpec.js | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/platform/features/timeline/test/actions/TimelineCSVExporterSpec.js b/platform/features/timeline/test/actions/TimelineCSVExporterSpec.js index cbe382c988..d406db43b7 100644 --- a/platform/features/timeline/test/actions/TimelineCSVExporterSpec.js +++ b/platform/features/timeline/test/actions/TimelineCSVExporterSpec.js @@ -26,6 +26,7 @@ define( function (TimelineCSVExporter) { describe("TimelineCSVExporter", function () { var mockDomainObjects, + testMetadata, exporter; function makeMockDomainObject(model, index) { @@ -41,16 +42,28 @@ define( ); mockDomainObject.getId.andReturn('id-' + index); mockDomainObject.getModel.andReturn(model); + mockDomainObject.useCapability.andCallFake(function (c) { + return c === 'metadata' && []; + }); return mockDomainObject; } beforeEach(function () { + testMetadata = [ + { name: "abc", value: 123 }, + { name: "xyz", value: 456 } + ]; + mockDomainObjects = [ { composition: [ 'a', 'b', 'c' ] }, { relationships: { modes: [ 'x', 'y' ] } }, { } ].map(makeMockDomainObject); + mockDomainObjects[2].useCapability.andCallFake(function (c) { + return c === 'metadata' && testMetadata; + }); + exporter = new TimelineCSVExporter(mockDomainObjects); }); @@ -79,7 +92,20 @@ define( }); }); + describe("headers", function () { + var headers; + beforeEach(function () { + headers = exporter.headers(); + }); + + it("contains all metadata properties", function () { + testMetadata.forEach(function (property) { + expect(headers.indexOf(property.name)) + .not.toEqual(-1); + }); + }); + }); }); } From c23c2b84bf127824dfde959c1ce53c2376393a3f Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 8 Mar 2016 10:31:25 -0800 Subject: [PATCH 033/164] [Timeline] Test inclusion of timespan properties ...in prepared data for CSV export --- .../test/actions/TimelineCSVExporterSpec.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/platform/features/timeline/test/actions/TimelineCSVExporterSpec.js b/platform/features/timeline/test/actions/TimelineCSVExporterSpec.js index d406db43b7..4267f95a1b 100644 --- a/platform/features/timeline/test/actions/TimelineCSVExporterSpec.js +++ b/platform/features/timeline/test/actions/TimelineCSVExporterSpec.js @@ -49,6 +49,11 @@ define( } beforeEach(function () { + var mockTimespan = jasmine.createSpyObj( + 'timespan', + [ 'getStart', 'getEnd' ] + ); + testMetadata = [ { name: "abc", value: 123 }, { name: "xyz", value: 456 } @@ -60,6 +65,13 @@ define( { } ].map(makeMockDomainObject); + mockDomainObjects[1].hasCapability.andCallFake(function (c) { + return c === 'timespan'; + }); + mockDomainObjects[1].useCapability.andCallFake(function (c) { + return c === 'timespan' ? Promise.resolve(mockTimespan) : + c === 'metadata' ? [] : undefined; + }); mockDomainObjects[2].useCapability.andCallFake(function (c) { return c === 'metadata' && testMetadata; }); @@ -105,6 +117,11 @@ define( .not.toEqual(-1); }); }); + + it("contains timespan properties", function () { + expect(headers.indexOf("Start")).not.toEqual(-1); + expect(headers.indexOf("End")).not.toEqual(-1); + }); }); }); From 66b1a92554a67d9186b338a74c684edd254c2e4f Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 8 Mar 2016 10:43:13 -0800 Subject: [PATCH 034/164] [Timeline] Add test cases for TimelineTraverser --- .../test/actions/TimelineTraverserSpec.js | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 platform/features/timeline/test/actions/TimelineTraverserSpec.js diff --git a/platform/features/timeline/test/actions/TimelineTraverserSpec.js b/platform/features/timeline/test/actions/TimelineTraverserSpec.js new file mode 100644 index 0000000000..3d9dcfdb4b --- /dev/null +++ b/platform/features/timeline/test/actions/TimelineTraverserSpec.js @@ -0,0 +1,107 @@ +/***************************************************************************** + * 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,describe,it,expect,beforeEach,waitsFor,jasmine,window,afterEach*/ + +define([ + "../../src/actions/TimelineTraverser" +], function (TimelineTraverser) { + 'use strict'; + + describe("TimelineTraverser", function () { + var testModels, + mockDomainObjects, + traverser; + + function addMockDomainObject(id) { + var mockDomainObject = jasmine.createSpyObj( + 'domainObject-' + id, + [ + 'getId', + 'getCapability', + 'useCapability', + 'hasCapability', + 'getModel' + ] + ), + model = testModels[id]; + + mockDomainObject.getId.andReturn(id); + mockDomainObject.getModel.andReturn(model); + + mockDomainObject.hasCapability.andCallFake(function (c) { + return c === 'composition' ? !!model.composition : + c === 'relationship' ? !!model.relationships : + false; + }); + + mockDomainObjects[id] = mockDomainObject; + } + + beforeEach(function () { + testModels = { + a: { composition: [ 'b', 'c' ]}, + b: { composition: [ 'c' ] }, + c: { relationships: { modes: [ 'd' ] } }, + d: {}, + unreachable: {} + }; + + mockDomainObjects = {}; + Object.keys(testModels).forEach(addMockDomainObject); + + + traverser = new TimelineTraverser(mockDomainObjects.a); + }); + + describe("buildObjectList", function () { + var objects; + + function contains(id) { + return objects.indexOf(mockDomainObjects[id]) !== -1; + } + + beforeEach(function () { + traverser.buildObjectList().then(function (objectList) { + objects = objectList; + }); + }); + + it("includes the object originally passed in", function () { + expect(contains('a')).toBe(true); + }); + + it("includes objects reachable via composition", function () { + expect(contains('b')).toBe(true); + expect(contains('c')).toBe(true); + }); + + it("includes objects reachable via relationships", function () { + expect(contains('d')).toBe(true); + }); + + it("does not include unreachable objects", function () { + expect(contains('unreachable')).toBe(false); + }); + }); + + }); +}); \ No newline at end of file From 5ee5e7fea18d1130cd7aeb07a9cb7b1bb9c3d1b9 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 8 Mar 2016 10:47:01 -0800 Subject: [PATCH 035/164] [Timeline] Add capabilities to test inputs --- .../test/actions/TimelineTraverserSpec.js | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/platform/features/timeline/test/actions/TimelineTraverserSpec.js b/platform/features/timeline/test/actions/TimelineTraverserSpec.js index 3d9dcfdb4b..1ccb7625c3 100644 --- a/platform/features/timeline/test/actions/TimelineTraverserSpec.js +++ b/platform/features/timeline/test/actions/TimelineTraverserSpec.js @@ -42,6 +42,7 @@ define([ 'getModel' ] ), + mockRelationships, model = testModels[id]; mockDomainObject.getId.andReturn(id); @@ -53,6 +54,31 @@ define([ false; }); + if (!!model.composition) { + mockDomainObject.useCapability.andCallFake(function (c) { + return c === 'composition' && + Promise.resolve(model.composition.map(function (id) { + return mockDomainObjects[id] + })); + }); + } + + if (!!model.relationships) { + mockRelationships = jasmine.createSpyObj( + 'relationship', + ['getRelatedObjects'] + ); + mockRelationships.getRelatedObjects.andCallFake(function (k) { + var ids = model.relationships[k] || []; + return Promise.resolve(ids.map(function (id) { + return mockDomainObjects[id]; + })); + }); + mockDomainObject.getCapability.andCallFake(function (c) { + return c === 'relationship' && mockRelationships; + }); + } + mockDomainObjects[id] = mockDomainObject; } From 0d419fa5fd756c7869f3dd0a126fde288bbfbcc8 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 8 Mar 2016 11:30:26 -0800 Subject: [PATCH 036/164] [Timeline] Test TimelineTraverser --- .../timeline/test/actions/TimelineTraverserSpec.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/platform/features/timeline/test/actions/TimelineTraverserSpec.js b/platform/features/timeline/test/actions/TimelineTraverserSpec.js index 1ccb7625c3..56674c7a6e 100644 --- a/platform/features/timeline/test/actions/TimelineTraverserSpec.js +++ b/platform/features/timeline/test/actions/TimelineTraverserSpec.js @@ -94,7 +94,6 @@ define([ mockDomainObjects = {}; Object.keys(testModels).forEach(addMockDomainObject); - traverser = new TimelineTraverser(mockDomainObjects.a); }); @@ -102,13 +101,18 @@ define([ var objects; function contains(id) { - return objects.indexOf(mockDomainObjects[id]) !== -1; + return objects.some(function (object) { + return object.getId() === id; + }); } beforeEach(function () { traverser.buildObjectList().then(function (objectList) { objects = objectList; }); + waitsFor(function () { + return objects !== undefined; + }); }); it("includes the object originally passed in", function () { From bd7cb98a4c0e74acb1ae7ab52211f8e87d2aeb9d Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 8 Mar 2016 11:40:54 -0800 Subject: [PATCH 037/164] [Timeline] Add missing semicolon ...to pass code style checks --- .../features/timeline/test/actions/TimelineTraverserSpec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/features/timeline/test/actions/TimelineTraverserSpec.js b/platform/features/timeline/test/actions/TimelineTraverserSpec.js index 56674c7a6e..6962373ff9 100644 --- a/platform/features/timeline/test/actions/TimelineTraverserSpec.js +++ b/platform/features/timeline/test/actions/TimelineTraverserSpec.js @@ -58,7 +58,7 @@ define([ mockDomainObject.useCapability.andCallFake(function (c) { return c === 'composition' && Promise.resolve(model.composition.map(function (id) { - return mockDomainObjects[id] + return mockDomainObjects[id]; })); }); } From 9e4e3e9c437d8490334e2159cc48f50b206251eb Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 8 Mar 2016 11:59:53 -0800 Subject: [PATCH 038/164] [Timeline] Add JSDoc Add JSDoc to classes implemented Export Timeline as CSV --- .../timeline/src/actions/CompositionColumn.js | 8 ++++ .../src/actions/ExportTimelineAsCSVAction.js | 10 +++++ .../src/actions/ExportTimelineAsCSVTask.js | 11 ++++- .../features/timeline/src/actions/IdColumn.js | 5 +++ .../timeline/src/actions/MetadataColumn.js | 5 +++ .../timeline/src/actions/ModeColumn.js | 7 +++ .../src/actions/TimelineCSVExporter.js | 44 +++++++++++++++++++ .../timeline/src/actions/TimelineTraverser.js | 10 +++++ .../timeline/src/actions/TimespanColumn.js | 7 +++ 9 files changed, 106 insertions(+), 1 deletion(-) diff --git a/platform/features/timeline/src/actions/CompositionColumn.js b/platform/features/timeline/src/actions/CompositionColumn.js index 6ee7fa010c..b7208c3e92 100644 --- a/platform/features/timeline/src/actions/CompositionColumn.js +++ b/platform/features/timeline/src/actions/CompositionColumn.js @@ -24,6 +24,14 @@ define([], function () { "use strict"; + /** + * A column containing references to other objects contained + * in a domain object's composition. + * @param {number} index the zero-based index of the composition + * element associated with this column + * @constructor + * @implements {platform/features/timeline.TimelineCSVColumn} + */ function CompositionColumn(index) { this.index = index; } diff --git a/platform/features/timeline/src/actions/ExportTimelineAsCSVAction.js b/platform/features/timeline/src/actions/ExportTimelineAsCSVAction.js index 37c1fddbf0..387c0839a0 100644 --- a/platform/features/timeline/src/actions/ExportTimelineAsCSVAction.js +++ b/platform/features/timeline/src/actions/ExportTimelineAsCSVAction.js @@ -24,6 +24,16 @@ define(["./ExportTimelineAsCSVTask"], function (ExportTimelineAsCSVTask) { 'use strict'; + /** + * Implements the "Export Timeline as CSV" action. + * + * @param exportService the service used to perform the CSV export + * @param notificationService the service used to show notifications + * @param context the Action's context + * @implements {Action} + * @constructor + * @memberof {platform/features/timeline} + */ function ExportTimelineAsCSVAction(exportService, notificationService, context) { this.task = new ExportTimelineAsCSVTask( exportService, diff --git a/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js b/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js index 790b165fd7..2193c6510f 100644 --- a/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js +++ b/platform/features/timeline/src/actions/ExportTimelineAsCSVTask.js @@ -31,16 +31,25 @@ define([ "use strict"; /** + * Runs (and coordinates) the preparation and export of CSV data + * for the "Export Timeline as CSV" action. * * @constructor * @memberof {platform/features/timeline} - * @implements {Task} + * @param exportService the service used to export as CSV + * @param {DomainObject} domainObject the timeline being exported */ function ExportTimelineAsCSVTask(exportService, domainObject) { this.domainObject = domainObject; this.exportService = exportService; } + /** + * Run this CSV export task. + * + * @returns {Promise} a promise that will be resolved when the + * export has finished (or rejected if there are problems.) + */ ExportTimelineAsCSVTask.prototype.run = function () { var exportService = this.exportService; diff --git a/platform/features/timeline/src/actions/IdColumn.js b/platform/features/timeline/src/actions/IdColumn.js index 6efeb104d3..56ddfe385f 100644 --- a/platform/features/timeline/src/actions/IdColumn.js +++ b/platform/features/timeline/src/actions/IdColumn.js @@ -24,6 +24,11 @@ define([], function () { "use strict"; + /** + * A column showing domain object identifiers. + * @constructor + * @implements {platform/features/timeline.TimelineCSVColumn} + */ function IdColumn() { } diff --git a/platform/features/timeline/src/actions/MetadataColumn.js b/platform/features/timeline/src/actions/MetadataColumn.js index ee8694082b..c94237a917 100644 --- a/platform/features/timeline/src/actions/MetadataColumn.js +++ b/platform/features/timeline/src/actions/MetadataColumn.js @@ -24,6 +24,11 @@ define([], function () { "use strict"; + /** + * A column reflecting properties from domain object metadata. + * @constructor + * @implements {platform/features/timeline.TimelineCSVColumn} + */ function MetadataColumn(propertyName) { this.propertyName = propertyName; } diff --git a/platform/features/timeline/src/actions/ModeColumn.js b/platform/features/timeline/src/actions/ModeColumn.js index 20a9de0e50..4ae61b30d3 100644 --- a/platform/features/timeline/src/actions/ModeColumn.js +++ b/platform/features/timeline/src/actions/ModeColumn.js @@ -24,6 +24,13 @@ define([], function () { "use strict"; + /** + * A column showing relationships to activity modes. + * @constructor + * @param {number} index the zero-based index of the composition + * element associated with this column + * @implements {platform/features/timeline.TimelineCSVColumn} + */ function ModeColumn(index) { this.index = index; } diff --git a/platform/features/timeline/src/actions/TimelineCSVExporter.js b/platform/features/timeline/src/actions/TimelineCSVExporter.js index f0d3efd953..17d8941865 100644 --- a/platform/features/timeline/src/actions/TimelineCSVExporter.js +++ b/platform/features/timeline/src/actions/TimelineCSVExporter.js @@ -36,6 +36,38 @@ define([ ) { 'use strict'; + /** + * A description of how to populate a given column within a + * prepared table of domain object data, for CSV export. + * @interface platform/features/timeline.TimelineCSVColumn + */ + + /** + * Get the value that belongs in this column for a given + * domain object. + * @memberof {platform/features/timeline.TimelineCSVColumn#} + * @method value + * @param {DomainObject} domainObject the domain object + * represented by this row + * @returns {string|Promise} the value for this cell + */ + + /** + * Get the name of this column, as belongs in a header. + * @memberof {platform/features/timeline.TimelineCSVColumn#} + * @method name + * @returns {string} the name of this column + */ + + /** + * Handles conversion of a list of domain objects to a table + * representation appropriate for CSV export. + * + * @param {DomainObject[]} domainObjects the objects to include + * in the exported data + * @constructor + * @memberof {platform/features/timeline} + */ function TimelineCSVExporter(domainObjects) { var maxComposition = 0, maxRelationships = 0, @@ -90,6 +122,13 @@ define([ this.columns = columns; } + /** + * Get a tabular representation of domain object data. + * Each row corresponds to a single object; each element + * in each row corresponds to a property designated by + * the `headers`, correlated by index. + * @returns {Promise.} domain object data + */ TimelineCSVExporter.prototype.rows = function () { var columns = this.columns; @@ -102,6 +141,11 @@ define([ return Promise.all(this.domainObjects.map(toRow)); }; + /** + * Get the column headers associated with this tabular + * representation of objects. + * @returns {string[]} column headers + */ TimelineCSVExporter.prototype.headers = function () { return this.columns.map(function (column) { return column.name(); diff --git a/platform/features/timeline/src/actions/TimelineTraverser.js b/platform/features/timeline/src/actions/TimelineTraverser.js index 48817b6963..f6857658fb 100644 --- a/platform/features/timeline/src/actions/TimelineTraverser.js +++ b/platform/features/timeline/src/actions/TimelineTraverser.js @@ -24,10 +24,20 @@ define([], function () { "use strict"; + /** + * Builds a list of domain objects which should be included + * in the CSV export of a given timeline. + * @param {DomainObject} domainObject the object being exported + * @constructor + */ function TimelineTraverser(domainObject) { this.domainObject = domainObject; } + /** + * Get a list of domain objects for CSV export. + * @returns {Promise.} a list of domain objects + */ TimelineTraverser.prototype.buildObjectList = function () { var idSet = {}, objects = []; diff --git a/platform/features/timeline/src/actions/TimespanColumn.js b/platform/features/timeline/src/actions/TimespanColumn.js index b970143f07..6d0c4e05a9 100644 --- a/platform/features/timeline/src/actions/TimespanColumn.js +++ b/platform/features/timeline/src/actions/TimespanColumn.js @@ -26,6 +26,13 @@ define(['../TimelineFormatter'], function (TimelineFormatter) { var FORMATTER = new TimelineFormatter(); + /** + * A column showing start or end times associated with a domain object. + * @constructor + * @param {boolean} isStart true if this column refers to the object's + * start time; false if it refers to the object's end time + * @implements {platform/features/timeline.TimelineCSVColumn} + */ function TimespanColumn(isStart) { this.isStart = isStart; } From 406a31889ef4ca05861207c4e136ed710f88ff10 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 8 Mar 2016 12:34:08 -0800 Subject: [PATCH 039/164] [Timeline] Add specs for remaining columns --- .../timeline/test/actions/IdColumnSpec.js | 59 ++++++++++++ .../test/actions/TimespanColumnSpec.js | 94 +++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 platform/features/timeline/test/actions/IdColumnSpec.js create mode 100644 platform/features/timeline/test/actions/TimespanColumnSpec.js diff --git a/platform/features/timeline/test/actions/IdColumnSpec.js b/platform/features/timeline/test/actions/IdColumnSpec.js new file mode 100644 index 0000000000..a12b6145a9 --- /dev/null +++ b/platform/features/timeline/test/actions/IdColumnSpec.js @@ -0,0 +1,59 @@ +/***************************************************************************** + * 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,describe,it,expect,beforeEach,waitsFor,jasmine,window,afterEach*/ + +define( + ['../../src/actions/IdColumn'], + function (IdColumn) { + describe("IdColumn", function () { + var column; + + beforeEach(function () { + column = new IdColumn(); + }); + + it("has a name", function () { + expect(column.name()).toEqual(jasmine.any(String)); + }); + + describe("value", function () { + var mockDomainObject, + testId; + + beforeEach(function () { + testId = "foo"; + mockDomainObject = jasmine.createSpyObj( + 'domainObject', + [ 'getId', 'getModel', 'getCapability' ] + ); + mockDomainObject.getId.andReturn(testId); + }); + + it("provides a domain object's identifier", function () { + expect(column.value(mockDomainObject)) + .toEqual(testId); + }); + }); + + }); + } +); \ No newline at end of file diff --git a/platform/features/timeline/test/actions/TimespanColumnSpec.js b/platform/features/timeline/test/actions/TimespanColumnSpec.js new file mode 100644 index 0000000000..f4970b778e --- /dev/null +++ b/platform/features/timeline/test/actions/TimespanColumnSpec.js @@ -0,0 +1,94 @@ +/***************************************************************************** + * 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,describe,it,expect,beforeEach,waitsFor,jasmine,window,afterEach*/ + +define( + ['../../src/actions/TimespanColumn', '../../src/TimelineFormatter'], + function (TimespanColumn, TimelineFormatter) { + describe("TimespanColumn", function () { + var testTimes, + mockTimespan, + mockDomainObject, + column; + + beforeEach(function () { + testTimes = { + start: 101000, + end: 987654321 + }; + mockTimespan = jasmine.createSpyObj( + 'timespan', + [ 'getStart', 'getEnd' ] + ); + mockDomainObject = jasmine.createSpyObj( + 'domainObject', + [ 'useCapability', 'hasCapability' ] + ); + mockTimespan.getStart.andReturn(testTimes.start); + mockTimespan.getEnd.andReturn(testTimes.end); + mockDomainObject.useCapability.andCallFake(function (c) { + return c === 'timespan' && Promise.resolve(mockTimespan); + }); + mockDomainObject.hasCapability.andCallFake(function (c) { + return c === 'timespan'; + }); + }); + + [ "start", "end" ].forEach(function (bound) { + describe("when referring to " + bound + " times", function () { + var name = bound.charAt(0).toUpperCase() + bound.slice(1); + + beforeEach(function () { + column = new TimespanColumn(bound === "start"); + }); + + it("is named \"" + name + "\"", function () { + expect(column.name()).toEqual(name); + }); + + describe("value", function () { + var testFormatter, + value; + + beforeEach(function () { + value = undefined; + testFormatter = new TimelineFormatter(); + column.value(mockDomainObject).then(function (v) { + value = v; + }); + waitsFor(function () { + return value !== undefined; + }); + }); + + it("returns a formatted " + bound + " time", function () { + var expected = + testFormatter.format(testTimes[bound]); + expect(value).toEqual(expected); + }); + }); + }); + }); + + }); + } +); \ No newline at end of file From 318df9878dca993689a05dbd5f08d4d9f75363d9 Mon Sep 17 00:00:00 2001 From: Charles Hacskaylo Date: Wed, 9 Mar 2016 17:22:41 -0800 Subject: [PATCH 040/164] [Frontend] Cleanups to Inspector config elements open #729 In-progress! Markup and CSS modified to cleanup control layout and styling in Plot and Table config options; gulpfile.js modified to include SASS source line numbers in rendered CSS; --- gulpfile.js | 3 +- .../commonUI/general/res/sass/_inspector.scss | 18 +++++- .../general/res/sass/forms/_elems.scss | 24 ++++---- .../res/templates/plot-options-browse.html | 58 ++++++++++--------- .../res/templates/table-options-edit.html | 2 +- 5 files changed, 61 insertions(+), 44 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index fa832d1aa6..0df0aa2ae6 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -60,7 +60,8 @@ var gulp = require('gulp'), singleRun: true }, sass: { - includePaths: bourbon.includePaths + includePaths: bourbon.includePaths, + sourceComments: true }, replace: { variables: { diff --git a/platform/commonUI/general/res/sass/_inspector.scss b/platform/commonUI/general/res/sass/_inspector.scss index 7ee9cadf27..b371dd65d1 100644 --- a/platform/commonUI/general/res/sass/_inspector.scss +++ b/platform/commonUI/general/res/sass/_inspector.scss @@ -61,9 +61,23 @@ .l-inspector-part { box-sizing: border-box; padding-right: $interiorMargin; - .form { + .tree .form { margin-left: $treeVCW + $interiorMarginLg; - margin-bottom: $interiorMarginLg; + } + .section-header { + background: none; + color: $colorInspectorPropName; + border-radius: unset; + font-size: inherit; + padding: $interiorMarginSm 0; + } + + mct-form:not(:last-child) .form { + border-bottom: 1px solid $colorInspectorSectionHeaderBg; + } + + .form { + margin-bottom: $interiorMargin; .form-section { margin-bottom: 0; &:not(.first) { diff --git a/platform/commonUI/general/res/sass/forms/_elems.scss b/platform/commonUI/general/res/sass/forms/_elems.scss index 4c5cbc5c3a..a48a8cfda4 100644 --- a/platform/commonUI/general/res/sass/forms/_elems.scss +++ b/platform/commonUI/general/res/sass/forms/_elems.scss @@ -19,16 +19,6 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ -.section-header { - border-radius: $basicCr; - background: $colorFormSectionHeader; - $c: lighten($colorBodyFg, 20%); - color: $c; - font-size: 0.8em; - padding: $formTBPad $formLRPad; - text-transform: uppercase; -} - .form { color: $colorFormText; width: 100%; @@ -37,6 +27,16 @@ margin-bottom: $interiorMarginLg * 2; } + .section-header { + border-radius: $basicCr; + background: $colorFormSectionHeader; + $c: lighten($colorBodyFg, 20%); + color: $c; + font-size: 0.8em; + padding: $formTBPad $formLRPad; + text-transform: uppercase; + } + .form-row { $m: $interiorMargin; box-sizing: border-box; @@ -52,9 +52,9 @@ >.label, >.controls { box-sizing: border-box; - @include clearfix; + //@include clearfix; font-size: 0.8rem; - line-height: $formInputH; + //line-height: $formInputH; min-height: $formInputH; } diff --git a/platform/features/plot/res/templates/plot-options-browse.html b/platform/features/plot/res/templates/plot-options-browse.html index 8def5cdc9c..123ed43194 100644 --- a/platform/features/plot/res/templates/plot-options-browse.html +++ b/platform/features/plot/res/templates/plot-options-browse.html @@ -41,36 +41,38 @@ name="yAxisFormState" class="flex-elem l-flex-row no-validate no-margin reduced-min-width"> -
- Plot Series -
-