From ae7dae011bc5064e423f8a055bd6ad709074160a Mon Sep 17 00:00:00 2001 From: Charles Hacskaylo Date: Fri, 19 Jun 2015 15:29:06 -0700 Subject: [PATCH 01/30] [Dev/Frontend] New example event generator and event view WTD-1304 github open18 New example generator; New temporary view: features/events; Updated scss and css; --- bundles.json | 2 + example/eventGenerator/bundle.json | 45 +++++ example/eventGenerator/src/EventTelemetry.js | 104 +++++++++++ .../src/EventTelemetryProvider.js | 120 +++++++++++++ .../general/res/css/theme-espresso.css | 169 +++++++++--------- .../general/res/sass/lists/_tabular.scss | 68 +++---- platform/features/events/bundle.json | 25 +++ .../events/res/templates/messages.html | 49 +++++ platform/features/events/src/DomainColumn.js | 67 +++++++ .../events/src/EventListController.js | 141 +++++++++++++++ .../features/events/src/EventListPopulator.js | 159 ++++++++++++++++ .../features/events/src/EventMsgColumn.js | 65 +++++++ platform/features/events/src/RangeColumn.js | 67 +++++++ .../features/events/src/SeverityColumn.js | 67 +++++++ .../scrolling/res/templates/scrolling.html | 2 +- 15 files changed, 1031 insertions(+), 119 deletions(-) create mode 100644 example/eventGenerator/bundle.json create mode 100644 example/eventGenerator/src/EventTelemetry.js create mode 100644 example/eventGenerator/src/EventTelemetryProvider.js create mode 100644 platform/features/events/bundle.json create mode 100644 platform/features/events/res/templates/messages.html create mode 100644 platform/features/events/src/DomainColumn.js create mode 100644 platform/features/events/src/EventListController.js create mode 100644 platform/features/events/src/EventListPopulator.js create mode 100644 platform/features/events/src/EventMsgColumn.js create mode 100644 platform/features/events/src/RangeColumn.js create mode 100644 platform/features/events/src/SeverityColumn.js diff --git a/bundles.json b/bundles.json index 0486bdf24b..6de8bc1243 100644 --- a/bundles.json +++ b/bundles.json @@ -14,10 +14,12 @@ "platform/features/pages", "platform/features/plot", "platform/features/scrolling", + "platform/features/events", "platform/forms", "platform/persistence/queue", "platform/policy", "example/persistence", + "example/eventGenerator", "example/generator" ] diff --git a/example/eventGenerator/bundle.json b/example/eventGenerator/bundle.json new file mode 100644 index 0000000000..83b52b91ac --- /dev/null +++ b/example/eventGenerator/bundle.json @@ -0,0 +1,45 @@ +{ + "name": "Event Message Generator", + "description": "Example of a component that produces event data.", + "extensions": { + "components": [ + { + "implementation": "EventTelemetryProvider.js", + "type": "provider", + "provides": "telemetryService", + "depends": [ "$q", "$timeout" ] + } + ], + "types": [ + { + "key": "eventGenerator", + "name": "Event Message Generator", + "glyph": "f", + "description": "An event message generator", + "features": "creation", + "model": { + "telemetry": { + "period": 10 + } + }, + "telemetry": { + "source": "eventGenerator", + "ranges": [ + { "format": "string" } + ] + }, + "properties": [ + { + "name": "Period", + "control": "textfield", + "cssclass": "l-small l-numeric", + "key": "period", + "required": true, + "property": [ "telemetry", "period" ], + "pattern": "^\\d*(\\.\\d*)?$" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/example/eventGenerator/src/EventTelemetry.js b/example/eventGenerator/src/EventTelemetry.js new file mode 100644 index 0000000000..317799815e --- /dev/null +++ b/example/eventGenerator/src/EventTelemetry.js @@ -0,0 +1,104 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,Promise*/ + +/** + * Module defining EventTelemetry. Created by chacskaylo on 06/18/2015. + */ +define( + [], + function () { + "use strict"; + + var + firstObservedTime = Date.now(), + messages = []; + + messages.push(["WARN", "dsp_seqprt_comm", "CMD: SYS- MSG: Open the pod bay doors, please, Hal...Open the pod bay doors, please, Hal...Hullo, Hal, do you read me?...Hullo, Hal, do you read me?...Do you read me, Hal?"]); + messages.push(["TRACE", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: Affirmative, Dave, I read you."]); + messages.push(["DEBUG", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: Open the pod bay doors, Hal."]); + messages.push(["ERROR", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: I'm sorry, Dave, I'm afraid I can't do that."]); + messages.push(["TRACE", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: What's the problem?"]); + messages.push(["ERROR", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: I think you know what the problem is just as well as I do."]); + messages.push(["TRACE", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: What're you talking about, Hal?"]); + messages.push(["DEBUG", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: This mission is too important for me to allow you to jeopardise it."]); + messages.push(["WARN", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: I don't know what you're talking about, Hal."]); + messages.push(["FATAL", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: I know that you and Frank were planning to disconnect me, and I'm afraid that's something I cannot allow to happen."]); + messages.push(["TRACE", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: Where the hell'd you get that idea, Hal?"]); + messages.push(["DEBUG", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: Dave, although you took very thorough precautions in the pod against my hearing you, I could see your lips move."]); + messages.push(["DEBUG", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: Alright, I'll go in through the emergency airlock."]); + messages.push(["DEBUG", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: Without your space-helmet, Dave, you're going to find that rather difficult."]); + messages.push(["DEBUG", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: Hal, I won't argue with you any more. Open the doors."]); + messages.push(["DEBUG", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: Dave, this conversation can serve no purpose any more. Goodbye."]); + messages.push(["INFO", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: I hope the two of you are not concerned about this."]); + messages.push(["DEBUG", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: No, I'm not, Hal."]); + messages.push(["INFO", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: Are you quite sure?"]); + messages.push(["INFO", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: Yeh. I'd like to ask you a question, though."]); + messages.push(["FATAL", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: Of course."]); + messages.push(["TRACE", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: How would you account for this discrepancy between you and the twin 9000?"]); + messages.push(["TRACE", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: Well, I don't think there is any question about it. It can only be attributable to human error. This sort of thing has cropped up before, and it has always been due to human error."]); + messages.push(["WARN", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: Listen, There's never been any instance at all of a computer error occurring in the 9000 series, has there?"]); + messages.push(["WARN", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: None whatsoever, The 9000 series has a perfect operational record."]); + messages.push(["WARN", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: Well, of course, I know all the wonderful achievements of the 9000 series, but - er - huh - are you certain there's never been any case of even the most insignificant computer error?"]); + messages.push(["INFO", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: None whatsoever, Quite honestly, I wouldn't worry myself about that."]); + messages.push(["WARN", "dsp_seqprt_comm", "RESP: SYS-COMM MSG: (Pause) Well, I'm sure you're right, Umm - fine, thanks very much. Oh, Frank, I'm having a bit of trouble with my transmitter in C-pod, I wonder if you'd come down and take a look at it with me?"]); + messages.push(["WARN", "dsp_seqprt_hal9k", "CMD: SYS-HAL9K MSG: Sure."]); + messages.push(["TRACE", "dsp_seqprt_comm", "RESP: SYS-COMM MSG: See you later, Hal."]); + + /** + * + * @constructor + */ + function EventTelemetry(request, interval) { + + var latestObservedTime = Date.now(), + count = Math.floor((latestObservedTime - firstObservedTime) / interval), + generatorData = {}; + + //console.log("EventTelemetry: LOS = " + (latestObservedTime).toString() + "; interval = " + interval.toString()); + + generatorData.getPointCount = function () { + return count; + }; + + generatorData.getDomainValue = function (i, domain) { + return i * interval + + (domain !== 'delta' ? firstObservedTime : 0); + }; + + generatorData.getRangeValue = function (i, range) { + var domainDelta = this.getDomainValue(i) - firstObservedTime; + var ind = i%messages.length; + return "TEMP " + i.toString() + "-" + messages[ind][2] + "[" + domainDelta.toString() + "]"; + }; + + generatorData.getSeverityValue = function (i) { + var ind = i%messages.length; + return messages[ind][0]; + }; + + return generatorData; + } + + return EventTelemetry; + } +); \ No newline at end of file diff --git a/example/eventGenerator/src/EventTelemetryProvider.js b/example/eventGenerator/src/EventTelemetryProvider.js new file mode 100644 index 0000000000..d014d95958 --- /dev/null +++ b/example/eventGenerator/src/EventTelemetryProvider.js @@ -0,0 +1,120 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,Promise*/ + +/** + * Module defining EventTelemetryProvider. Created by chacskaylo on 06/18/2015. + */ +define( + ["./EventTelemetry"], + function (EventTelemetry) { + "use strict"; + + /** + * + * @constructor + */ + function EventTelemetryProvider($q, $timeout) { + var + subscriptions = [], + genInterval = 1000, + startTime = Date.now(); + + // + function matchesSource(request) { + return request.source === "eventGenerator"; + } + + // Used internally; this will be repacked by doPackage + function generateData(request) { + //console.log("generateData " + (Date.now() - startTime).toString()); + return { + key: request.key, + telemetry: new EventTelemetry(request, genInterval) + }; + } + + // + function doPackage(results) { + var packaged = {}; + results.forEach(function (result) { + packaged[result.key] = result.telemetry; + }); + // Format as expected (sources -> keys -> telemetry) + return { eventGenerator: packaged }; + } + + function requestTelemetry(requests) { + return $timeout(function () { + return doPackage(requests.filter(matchesSource).map(generateData)); + }, 0); + } + + function handleSubscriptions(timeout) { + subscriptions.forEach(function (subscription) { + var requests = subscription.requests; + subscription.callback(doPackage( + requests.filter(matchesSource).map(generateData) + )); + }); + } + + function startGenerating() { + $timeout(function () { + //console.log("startGenerating... " + Date.now()); + handleSubscriptions(); + if (subscriptions.length > 0) { + startGenerating(); + } + }, genInterval); + } + + function subscribe(callback, requests) { + var subscription = { + callback: callback, + requests: requests + }; + + function unsubscribe() { + subscriptions = subscriptions.filter(function (s) { + return s !== subscription; + }); + } + + subscriptions.push(subscription); + + if (subscriptions.length === 1) { + startGenerating(); + } + + return unsubscribe; + } + + return { + requestTelemetry: requestTelemetry, + subscribe: subscribe + }; + } + + return EventTelemetryProvider; + } +); \ No newline at end of file diff --git a/platform/commonUI/general/res/css/theme-espresso.css b/platform/commonUI/general/res/css/theme-espresso.css index 00bb27d430..adffbea182 100644 --- a/platform/commonUI/general/res/css/theme-espresso.css +++ b/platform/commonUI/general/res/css/theme-espresso.css @@ -1193,104 +1193,101 @@ mct-container { border-collapse: collapse; color: #fff; display: table; - font-size: 0.8em; + font-size: 0.75em; position: relative; - height: 100%; width: 100%; } /* line 37, ../sass/lists/_tabular.scss */ .tabular thead, .tabular .thead, .tabular tbody tr, .tabular .tbody .tr { - display: table; + width: 100%; } + /* line 45, ../sass/lists/_tabular.scss */ + .tabular thead tr, .tabular thead .tr, .tabular .thead tr, .tabular .thead .tr { + height: 18px; } + /* line 48, ../sass/lists/_tabular.scss */ + .tabular thead:before, .tabular .thead:before { + content: ""; + display: block; + z-index: 0; + position: absolute; width: 100%; - table-layout: fixed; } - /* line 43, ../sass/lists/_tabular.scss */ - .tabular thead, .tabular .thead { - width: calc(100% - 10px); } - /* line 45, ../sass/lists/_tabular.scss */ - .tabular thead tr, .tabular thead .tr, .tabular .thead tr, .tabular .thead .tr { - height: 18px; } - /* line 48, ../sass/lists/_tabular.scss */ - .tabular thead:before, .tabular .thead:before { - content: ""; - display: block; - z-index: 0; - position: absolute; - width: 100%; - height: 18px; - background: rgba(255, 255, 255, 0.15); } + height: 18px; + background: rgba(255, 255, 255, 0.15); } /* line 58, ../sass/lists/_tabular.scss */ .tabular tbody, .tabular .tbody { - overflow: hidden; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - width: auto; - height: auto; - top: 18px; - display: block; - overflow-y: scroll; } - /* line 66, ../sass/lists/_tabular.scss */ + display: table-row-group; } + /* line 65, ../sass/lists/_tabular.scss */ .tabular tbody tr:hover, .tabular tbody .tr:hover, .tabular .tbody tr:hover, .tabular .tbody .tr:hover { background: rgba(255, 255, 255, 0.1); } - /* line 74, ../sass/lists/_tabular.scss */ - .tabular tr:first-child .td, .tabular .tr:first-child .td { - border-top: none; } - /* line 77, ../sass/lists/_tabular.scss */ - .tabular tr th, .tabular tr .th, .tabular tr td, .tabular tr .td, .tabular .tr th, .tabular .tr .th, .tabular .tr td, .tabular .tr .td { - display: table-cell; } - /* line 80, ../sass/lists/_tabular.scss */ - .tabular tr th, .tabular tr .th, .tabular .tr th, .tabular .tr .th { - border: none; - border-left: 1px solid rgba(255, 255, 255, 0.1); - color: #b3b3b3; - padding: 0 5px; - white-space: nowrap; - vertical-align: middle; - /* em { - //background: rgba(green, 0.2); - border-left: 1px solid $tabularColorBorder; - color: $tabularColorHeaderFg; - cursor: pointer; - display: block; - font-style: normal; - font-weight: bold; - height: $tabularHeaderH; - line-height: $tabularHeaderH; - margin-left: - $tabularTdPadLR; - padding: 0 $tabularTdPadLR; - position: absolute; - top: 0; - vertical-align: middle; - &:hover { - color: lighten($tabularColorHeaderFg, 20%); - } - }*/ } - /* line 87, ../sass/lists/_tabular.scss */ - .tabular tr th:first-child, .tabular tr .th:first-child, .tabular .tr th:first-child, .tabular .tr .th:first-child { - border-left: none; } - /* line 91, ../sass/lists/_tabular.scss */ - .tabular tr th.sort .icon-sorting:before, .tabular tr .th.sort .icon-sorting:before, .tabular .tr th.sort .icon-sorting:before, .tabular .tr .th.sort .icon-sorting:before { - display: inline-block; - font-family: symbolsfont; - margin-left: 5px; } - /* line 96, ../sass/lists/_tabular.scss */ - .tabular tr th.sort.asc .icon-sorting:before, .tabular tr .th.sort.asc .icon-sorting:before, .tabular .tr th.sort.asc .icon-sorting:before, .tabular .tr .th.sort.asc .icon-sorting:before { - content: '0'; } - /* line 99, ../sass/lists/_tabular.scss */ - .tabular tr th.sort.desc .icon-sorting:before, .tabular tr .th.sort.desc .icon-sorting:before, .tabular .tr th.sort.desc .icon-sorting:before, .tabular .tr .th.sort.desc .icon-sorting:before { - content: '1'; } - /* line 123, ../sass/lists/_tabular.scss */ - .tabular tr td, .tabular tr .td, .tabular .tr td, .tabular .tr .td { - border-top: 1px solid rgba(255, 255, 255, 0.1); - padding: 2px 5px; } - /* line 126, ../sass/lists/_tabular.scss */ - .tabular tr td.numeric, .tabular tr .td.numeric, .tabular .tr td.numeric, .tabular .tr .td.numeric { - text-align: right; } - /* line 132, ../sass/lists/_tabular.scss */ + /* line 70, ../sass/lists/_tabular.scss */ + .tabular tr, .tabular .tr { + display: table-row; } + /* line 72, ../sass/lists/_tabular.scss */ + .tabular tr:first-child .td, .tabular .tr:first-child .td { + border-top: none; } + /* line 75, ../sass/lists/_tabular.scss */ + .tabular tr th, .tabular tr .th, .tabular tr td, .tabular tr .td, .tabular .tr th, .tabular .tr .th, .tabular .tr td, .tabular .tr .td { + display: table-cell; } + /* line 78, ../sass/lists/_tabular.scss */ + .tabular tr th, .tabular tr .th, .tabular .tr th, .tabular .tr .th { + border: none; + border-left: 1px solid rgba(255, 255, 255, 0.1); + color: #b3b3b3; + padding: 0 5px; + white-space: nowrap; + vertical-align: middle; } + /* line 85, ../sass/lists/_tabular.scss */ + .tabular tr th:first-child, .tabular tr .th:first-child, .tabular .tr th:first-child, .tabular .tr .th:first-child { + border-left: none; } + /* line 89, ../sass/lists/_tabular.scss */ + .tabular tr th.sort .icon-sorting:before, .tabular tr .th.sort .icon-sorting:before, .tabular .tr th.sort .icon-sorting:before, .tabular .tr .th.sort .icon-sorting:before { + display: inline-block; + font-family: symbolsfont; + margin-left: 5px; } + /* line 94, ../sass/lists/_tabular.scss */ + .tabular tr th.sort.asc .icon-sorting:before, .tabular tr .th.sort.asc .icon-sorting:before, .tabular .tr th.sort.asc .icon-sorting:before, .tabular .tr .th.sort.asc .icon-sorting:before { + content: '0'; } + /* line 97, ../sass/lists/_tabular.scss */ + .tabular tr th.sort.desc .icon-sorting:before, .tabular tr .th.sort.desc .icon-sorting:before, .tabular .tr th.sort.desc .icon-sorting:before, .tabular .tr .th.sort.desc .icon-sorting:before { + content: '1'; } + /* line 102, ../sass/lists/_tabular.scss */ + .tabular tr td, .tabular tr .td, .tabular .tr td, .tabular .tr .td { + border-top: 1px solid rgba(255, 255, 255, 0.1); + min-width: 110px; + padding: 2px 5px; + vertical-align: top; } + /* line 107, ../sass/lists/_tabular.scss */ + .tabular tr td.numeric, .tabular tr .td.numeric, .tabular .tr td.numeric, .tabular .tr .td.numeric { + text-align: right; } + /* line 113, ../sass/lists/_tabular.scss */ .tabular.filterable tbody, .tabular.filterable .tbody { top: 36px; } + /* line 118, ../sass/lists/_tabular.scss */ + .tabular.fixed-header { + height: 100%; } + /* line 120, ../sass/lists/_tabular.scss */ + .tabular.fixed-header thead, .tabular.fixed-header .thead, + .tabular.fixed-header tbody tr, .tabular.fixed-header .tbody .tr { + display: table; + table-layout: fixed; } + /* line 125, ../sass/lists/_tabular.scss */ + .tabular.fixed-header thead, .tabular.fixed-header .thead { + width: calc(100% - 10px); } + /* line 128, ../sass/lists/_tabular.scss */ + .tabular.fixed-header tbody, .tabular.fixed-header .tbody { + overflow: hidden; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + width: auto; + height: auto; + top: 18px; + display: block; + overflow-y: scroll; } + /* line 136, ../sass/lists/_tabular.scss */ + .tabular.t-event-messages td, .tabular.t-event-messages .td { + min-width: 150px; } /* line 1, ../sass/controls/_breadcrumb.scss */ .l-breadcrumb { diff --git a/platform/commonUI/general/res/sass/lists/_tabular.scss b/platform/commonUI/general/res/sass/lists/_tabular.scss index 213b79ce5b..3bfeab4d8e 100644 --- a/platform/commonUI/general/res/sass/lists/_tabular.scss +++ b/platform/commonUI/general/res/sass/lists/_tabular.scss @@ -30,18 +30,18 @@ border-collapse: collapse; color: #fff; display: table; - font-size: 0.8em; + font-size: 0.75em; position: relative; - height: 100%; + //height: 100%; MOVED width: 100%; thead, .thead, tbody tr, .tbody .tr { - display: table; + //display: table; MOVED width: 100%; - table-layout: fixed; + //table-layout: fixed; MOVED } thead, .thead { - width: calc(100% - 10px); + //width: calc(100% - 10px); MOVED tr, .tr { height: $tabularHeaderH; } @@ -56,12 +56,11 @@ } } tbody, .tbody { - @include absPosDefault(0); - top: $tabularHeaderH; - //display: table-row-group; - display: block; - //width: 100%; - overflow-y: scroll; + //@include absPosDefault(0); MOVED + //top: $tabularHeaderH; MOVED + //display: block; MOVED + //overflow-y: scroll; MOVED + display: table-row-group; tr, .tr { &:hover { background: rgba(white, 0.1); @@ -69,8 +68,7 @@ } } tr, .tr { - //display: table-row; - //width: 100%; + display: table-row; &:first-child .td { border-top: none; } @@ -100,29 +98,12 @@ content: '1'; } } - /* em { - //background: rgba(green, 0.2); - border-left: 1px solid $tabularColorBorder; - color: $tabularColorHeaderFg; - cursor: pointer; - display: block; - font-style: normal; - font-weight: bold; - height: $tabularHeaderH; - line-height: $tabularHeaderH; - margin-left: - $tabularTdPadLR; - padding: 0 $tabularTdPadLR; - position: absolute; - top: 0; - vertical-align: middle; - &:hover { - color: lighten($tabularColorHeaderFg, 20%); - } - }*/ } td, .td { border-top: 1px solid $tabularColorBorder; + min-width: 110px; padding: $tabularTdPadTB $tabularTdPadLR; + vertical-align: top; &.numeric { text-align: right; } @@ -133,4 +114,27 @@ top: $tabularHeaderH * 2; } } + + &.fixed-header { + height: 100%; + thead, .thead, + tbody tr, .tbody .tr { + display: table; + table-layout: fixed; + } + thead, .thead { + width: calc(100% - 10px); + } + tbody, .tbody { + @include absPosDefault(0); + top: $tabularHeaderH; + display: block; + overflow-y: scroll; + } + } + &.t-event-messages { + td, .td { + min-width: 150px; + } + } } \ No newline at end of file diff --git a/platform/features/events/bundle.json b/platform/features/events/bundle.json new file mode 100644 index 0000000000..495d06b235 --- /dev/null +++ b/platform/features/events/bundle.json @@ -0,0 +1,25 @@ +{ + "name": "Event Messages", + "description": "List of time-ordered event messages", + "extensions": { + "views": [ + { + "key": "messages", + "name": "Messages", + "glyph": "5", + "description": "Scrolling list of messages.", + "templateUrl": "templates/messages.html", + "needs": [ "telemetry" ], + "delegation": true + } + ], + "controllers": [ + { + "key": "EventListController", + "implementation": "EventListController.js", + "depends": [ "$scope", "telemetryFormatter" ] + } + ] + } + +} \ No newline at end of file diff --git a/platform/features/events/res/templates/messages.html b/platform/features/events/res/templates/messages.html new file mode 100644 index 0000000000..727ab09a79 --- /dev/null +++ b/platform/features/events/res/templates/messages.html @@ -0,0 +1,49 @@ + +
+
+ + + + + + + + + + + + +
+ {{header}} +
+ {{cell}} +
+
+
+ + diff --git a/platform/features/events/src/DomainColumn.js b/platform/features/events/src/DomainColumn.js new file mode 100644 index 0000000000..95a6222553 --- /dev/null +++ b/platform/features/events/src/DomainColumn.js @@ -0,0 +1,67 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,moment*/ + +/** + * Module defining DomainColumn. Created by vwoeltje on 11/18/14. + */ +define( + [], + function () { + "use strict"; + + /** + * A column which will report telemetry domain values + * (typically, timestamps.) Used by the ScrollingListController. + * + * @constructor + * @param domainMetadata an object with the machine- and human- + * readable names for this domain (in `key` and `name` + * fields, respectively.) + * @param {TelemetryFormatter} telemetryFormatter the telemetry + * formatting service, for making values human-readable. + */ + function DomainColumn(domainMetadata, telemetryFormatter) { + return { + /** + * Get the title to display in this column's header. + * @returns {string} the title to display + */ + getTitle: function () { + return domainMetadata.name; + }, + /** + * Get the text to display inside a row under this + * column. + * @returns {string} the text to display + */ + getValue: function (domainObject, data, index) { + return telemetryFormatter.formatDomainValue( + data.getDomainValue(index, domainMetadata.key) + ); + } + }; + } + + return DomainColumn; + } +); \ No newline at end of file diff --git a/platform/features/events/src/EventListController.js b/platform/features/events/src/EventListController.js new file mode 100644 index 0000000000..d2b54169b5 --- /dev/null +++ b/platform/features/events/src/EventListController.js @@ -0,0 +1,141 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,Promise*/ + +/** + * Module defining ListController. Created by chacskaylo on 06/18/2015. + */ +define( + ["./SeverityColumn", "./DomainColumn", "./EventMsgColumn", "./EventListPopulator"], + function (SeverityColumn, DomainColumn, EventMsgColumn, EventListPopulator) { + "use strict"; + + var ROW_COUNT = 100; + + /** + * The EventListController is responsible for populating + * the contents of the scrolling list view. + * @constructor + */ + function EventListController($scope, formatter) { + var populator; + + + // Get a set of populated, ready-to-display rows for the + // latest data values. + function getRows(telemetry) { + var datas = telemetry.getResponse(), + objects = telemetry.getTelemetryObjects(); + + return populator.getRows(datas, objects, ROW_COUNT); + } + + // Update the contents + function updateRows() { + var telemetry = $scope.telemetry; + $scope.rows = telemetry ? getRows(telemetry) : []; + } + + // Set up columns based on telemetry metadata. This will + // include one column for each domain and range type, as + // well as a column for the domain object name. + function setupColumns(telemetry) { + var domainKeys = {}, + eventMsgKeys = {}, + columns = [], + metadata; + + // Add a domain to the set of columns, if a domain + // with the same key has not yet been inclued. + function addDomain(domain) { + var key = domain.key; + if (key && !domainKeys[key]) { + domainKeys[key] = true; + columns.push(new DomainColumn(domain, formatter)); + } + } + + // Add a event string col to the set of columns, if a range + // with the same key has not yet been included. + function addEventMsg(eventMsg) { + var key = eventMsg.key; + if (key && !eventMsgKeys[key]) { + eventMsgKeys[key] = true; + columns.push(new EventMsgColumn(eventMsg, formatter)); + } + } + + // We cannot proceed if the telemetry controller + // is not available; clear all rows/columns. + if (!telemetry) { + columns = []; + $scope.rows = []; + $scope.headers = []; + return; + } + + // Add domain, range, event msg columns + metadata = telemetry.getMetadata(); + (metadata || []).forEach(function (metadata) { + (metadata.domains || []).forEach(addDomain); + }); + //(metadata || []).forEach(function (metadata) { + // (metadata.ranges || []).forEach(addRange); + //}); + (metadata || []).forEach(function (metadata) { + (metadata.ranges || []).forEach(addEventMsg); + }); + + + + + // Add default severity, domain, range columns if none + // were described in metadata. + if (Object.keys(domainKeys).length < 1) { + columns.push(new SeverityColumn({name: "Severity"}, formatter)); + } + if (Object.keys(domainKeys).length < 1) { + columns.push(new DomainColumn({name: "Time"}, formatter)); + } + if (Object.keys(eventMsgKeys).length < 1) { + columns.push(new EventMsgColumn({name: "Event Message"}, formatter)); + } + + // We have all columns now; use them to initializer + // the populator, which will use them to generate + // actual rows and headers. + populator = new EventListPopulator(columns); + + // Initialize headers + $scope.headers = populator.getHeaders(); + + // Fill in the contents of the rows. + updateRows(); + } + + $scope.$on("telemetryUpdate", updateRows); + $scope.$watch("telemetry", setupColumns); + } + + return EventListController; + } +); \ No newline at end of file diff --git a/platform/features/events/src/EventListPopulator.js b/platform/features/events/src/EventListPopulator.js new file mode 100644 index 0000000000..f2a5c1f473 --- /dev/null +++ b/platform/features/events/src/EventListPopulator.js @@ -0,0 +1,159 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define*/ + +define( + [], + function () { + "use strict"; + + /** + * The EventListPopulator is responsible for filling in the + * values which should appear within columns of a scrolling list + * view, based on received telemetry data. + * @constructor + * @param {Column[]} columns the columns to be populated + */ + function EventListPopulator(columns) { + /** + * Look up the most recent values from a set of data objects. + * Returns an array of objects in the order in which data + * should be displayed; each element is an object with + * two properties: + * + * * objectIndex: The index of the domain object associated + * with the data point to be displayed in that + * row. + * * pointIndex: The index of the data point itself, within + * its data set. + * + * @param {Array} datas an array of the most recent + * data objects; expected to be in the same order + * as the domain objects provided at constructor + * @param {number} count the number of rows to provide + */ + function getLatestDataValues(datas, count) { + var latest = [], + candidate, + candidateTime, + used = datas.map(function () { return 0; }); + + // This algorithm is O(nk) for n rows and k telemetry elements; + // one O(k) linear search for a max is made for each of n rows. + // This could be done in O(n lg k + k lg k), using a priority + // queue (where priority is max-finding) containing k initial + // values. For n rows, pop the max from the queue and replenish + // the queue with a value from the data at the same + // objectIndex, if available. + // But k is small, so this might not give an observable + // improvement in performance. + + // Find the most recent unused data point (this will be used + // in a loop to find and the N most recent data points) + function findCandidate(data, i) { + var nextTime, + pointCount = data.getPointCount(), + pointIndex = pointCount - used[i] - 1; + if (data && pointIndex >= 0) { + nextTime = data.getDomainValue(pointIndex); + if (nextTime > candidateTime) { + candidateTime = nextTime; + candidate = { + objectIndex: i, + pointIndex: pointIndex + }; + } + } + } + + // Assemble a list of the most recent data points + while (latest.length < count) { + // Reset variables pre-search + candidateTime = Number.NEGATIVE_INFINITY; + candidate = undefined; + + // Linear search for most recent + datas.forEach(findCandidate); + + if (candidate) { + // Record this data point - it is the most recent + latest.push(candidate); + + // Track the data points used so we can look farther back + // in the data set on the next iteration + used[candidate.objectIndex] = used[candidate.objectIndex] + 1; + } else { + // Ran out of candidates; not enough data points + // available to fill all rows. + break; + } + } + + return latest; + } + + + return { + /** + * Get the text which should appear in headers for the + * provided columns. + * @returns {string[]} column headers + */ + getHeaders: function () { + return columns.map(function (column) { + return column.getTitle(); + }); + }, + /** + * Get the contents of rows for the scrolling list view. + * @param {TelemetrySeries[]} datas the data sets + * @param {DomainObject[]} objects the domain objects which + * provided the data sets; these should match + * index-to-index with the `datas` argument + * @param {number} count the number of rows to populate + * @returns {string[][]} an array of rows, each of which + * is an array of values which should appear + * in that row + */ + getRows: function (datas, objects, count) { + var values = getLatestDataValues(datas, count); + + // Each value will become a row, which will contain + // some value in each column (rendering by the + // column object itself) + return values.map(function (value) { + return columns.map(function (column) { + return column.getValue( + objects[value.objectIndex], + datas[value.objectIndex], + value.pointIndex + ); + }); + }); + } + }; + } + + return EventListPopulator; + + } +); \ No newline at end of file diff --git a/platform/features/events/src/EventMsgColumn.js b/platform/features/events/src/EventMsgColumn.js new file mode 100644 index 0000000000..ab24cd9f29 --- /dev/null +++ b/platform/features/events/src/EventMsgColumn.js @@ -0,0 +1,65 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,Promise*/ + +/** + * Module defining EventMsgColumn. Created by chacskaylo on 06/18/2015. + */ +define( + [], + function () { + "use strict"; + + /** + * A column which will report telemetry event messages. + * (typically, measurements.) Used by the EventListController. + * + * @constructor + * @param rangeMetadata an object with the machine- and human- + * readable names for this range (in `key` and `name` + * fields, respectively.) + * @param {TelemetryFormatter} telemetryFormatter the telemetry + * formatting service, for making values human-readable. + */ + function EventMsgColumn(eventMsgMetadata, telemetryFormatter) { + return { + /** + * Get the title to display in this column's header. + * @returns {string} the title to display + */ + getTitle: function () { + return eventMsgMetadata.name; + }, + /** + * Get the text to display inside a row under this + * column. + * @returns {string} the text to display + */ + getValue: function (domainObject, data, index) { + return data.getRangeValue(index, eventMsgMetadata.key); + } + }; + } + + return EventMsgColumn; + } +); \ No newline at end of file diff --git a/platform/features/events/src/RangeColumn.js b/platform/features/events/src/RangeColumn.js new file mode 100644 index 0000000000..2b11de43c7 --- /dev/null +++ b/platform/features/events/src/RangeColumn.js @@ -0,0 +1,67 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,Promise*/ + +/** + * Module defining DomainColumn. Created by vwoeltje on 11/18/14. + */ +define( + [], + function () { + "use strict"; + + /** + * A column which will report telemetry range values + * (typically, measurements.) Used by the ScrollingListController. + * + * @constructor + * @param rangeMetadata an object with the machine- and human- + * readable names for this range (in `key` and `name` + * fields, respectively.) + * @param {TelemetryFormatter} telemetryFormatter the telemetry + * formatting service, for making values human-readable. + */ + function RangeColumn(rangeMetadata, telemetryFormatter) { + return { + /** + * Get the title to display in this column's header. + * @returns {string} the title to display + */ + getTitle: function () { + return rangeMetadata.name; + }, + /** + * Get the text to display inside a row under this + * column. + * @returns {string} the text to display + */ + getValue: function (domainObject, data, index) { + return telemetryFormatter.formatRangeValue( + data.getRangeValue(index, rangeMetadata.key) + ); + } + }; + } + + return RangeColumn; + } +); \ No newline at end of file diff --git a/platform/features/events/src/SeverityColumn.js b/platform/features/events/src/SeverityColumn.js new file mode 100644 index 0000000000..29f452bcb9 --- /dev/null +++ b/platform/features/events/src/SeverityColumn.js @@ -0,0 +1,67 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,Promise*/ + +/** + * Module defining DomainColumn. Created by vwoeltje on 11/18/14. + */ +define( + [], + function () { + "use strict"; + + /** + * A column which will report telemetry range values + * (typically, measurements.) Used by the ScrollingListController. + * + * @constructor + * @param rangeMetadata an object with the machine- and human- + * readable names for this range (in `key` and `name` + * fields, respectively.) + * @param {TelemetryFormatter} telemetryFormatter the telemetry + * formatting service, for making values human-readable. + */ + function SeverityColumn(rangeMetadata, telemetryFormatter) { + return { + /** + * Get the title to display in this column's header. + * @returns {string} the title to display + */ + getTitle: function () { + return rangeMetadata.name; + }, + /** + * Get the text to display inside a row under this + * column. + * @returns {string} the text to display + */ + getValue: function (domainObject, data, index) { + return telemetryFormatter.formatRangeValue( + data.getSeverityValue(index, rangeMetadata.key) + ); + } + }; + } + + return SeverityColumn; + } +); \ No newline at end of file diff --git a/platform/features/scrolling/res/templates/scrolling.html b/platform/features/scrolling/res/templates/scrolling.html index 2d5d19fabc..4b7461c9da 100644 --- a/platform/features/scrolling/res/templates/scrolling.html +++ b/platform/features/scrolling/res/templates/scrolling.html @@ -23,7 +23,7 @@
- +
From 7be7844824136f2e342c9df3728467bfd598218d Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Mon, 22 Jun 2015 13:40:55 -0700 Subject: [PATCH 02/30] [Events] Reversed viewing order When viewing an event message generator new messages are now added to the bottom of the display, rather than being added to the top and pushing the other messages down by one. #18. --- example/eventGenerator/src/EventTelemetry.js | 4 +++- platform/features/events/src/EventListController.js | 6 ++++-- platform/features/events/src/EventListPopulator.js | 2 +- platform/telemetry/src/TelemetryController.js | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/example/eventGenerator/src/EventTelemetry.js b/example/eventGenerator/src/EventTelemetry.js index 317799815e..62dd3531d3 100644 --- a/example/eventGenerator/src/EventTelemetry.js +++ b/example/eventGenerator/src/EventTelemetry.js @@ -90,11 +90,13 @@ define( var ind = i%messages.length; return "TEMP " + i.toString() + "-" + messages[ind][2] + "[" + domainDelta.toString() + "]"; }; - + + generatorData.getSeverityValue = function (i) { var ind = i%messages.length; return messages[ind][0]; }; + return generatorData; } diff --git a/platform/features/events/src/EventListController.js b/platform/features/events/src/EventListController.js index d2b54169b5..052e4571c2 100644 --- a/platform/features/events/src/EventListController.js +++ b/platform/features/events/src/EventListController.js @@ -38,8 +38,7 @@ define( */ function EventListController($scope, formatter) { var populator; - - + // Get a set of populated, ready-to-display rows for the // latest data values. function getRows(telemetry) { @@ -53,6 +52,9 @@ define( function updateRows() { var telemetry = $scope.telemetry; $scope.rows = telemetry ? getRows(telemetry) : []; + // We want to display the rows in reverse order + // i.e. from the top to the bottom of the page + $scope.rows = $scope.rows.reverse(); } // Set up columns based on telemetry metadata. This will diff --git a/platform/features/events/src/EventListPopulator.js b/platform/features/events/src/EventListPopulator.js index f2a5c1f473..af6d3e9ae6 100644 --- a/platform/features/events/src/EventListPopulator.js +++ b/platform/features/events/src/EventListPopulator.js @@ -38,7 +38,7 @@ define( * Look up the most recent values from a set of data objects. * Returns an array of objects in the order in which data * should be displayed; each element is an object with - * two properties: + * two properties: * * * objectIndex: The index of the domain object associated * with the data point to be displayed in that diff --git a/platform/telemetry/src/TelemetryController.js b/platform/telemetry/src/TelemetryController.js index 10e83ab316..504ec2ec4a 100644 --- a/platform/telemetry/src/TelemetryController.js +++ b/platform/telemetry/src/TelemetryController.js @@ -342,7 +342,7 @@ define( * the second form, it returns an array ordered in * same manner as `getMetadata()` or * `getTelemetryObjects()`; that is, the telemetry - * response at agiven index will correspond to the + * response at a given index will correspond to the * telemetry-providing domain object at the same index. * @returns {Array} an array of responses */ From a5d5fa0796e2c983da035be38d67476c44c7ebe7 Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Tue, 23 Jun 2015 11:37:57 -0700 Subject: [PATCH 03/30] [Events] Table height detection Created an mct-data-table directive. We are able to detect changes in the height of the table now, which will be used to determine any corresponding scrolling. #18. --- platform/features/events/bundle.json | 7 ++++ .../events/res/templates/messages.html | 38 +++++++++---------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/platform/features/events/bundle.json b/platform/features/events/bundle.json index 495d06b235..549dda7d36 100644 --- a/platform/features/events/bundle.json +++ b/platform/features/events/bundle.json @@ -19,6 +19,13 @@ "implementation": "EventListController.js", "depends": [ "$scope", "telemetryFormatter" ] } + ], + "directives": [ + { + "key": "mctDataTable", + "implementation": "MCTDataTable.js", + "depends": [ "$anchorScroll" ] + } ] } diff --git a/platform/features/events/res/templates/messages.html b/platform/features/events/res/templates/messages.html index 727ab09a79..a549b3530d 100644 --- a/platform/features/events/res/templates/messages.html +++ b/platform/features/events/res/templates/messages.html @@ -22,27 +22,23 @@
- - - - - - - - - - - - -
- {{header}} -
- {{cell}} -
+ +
From 3337777fea892147fe0967a25bdeb28084d75ae8 Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Tue, 23 Jun 2015 11:48:08 -0700 Subject: [PATCH 04/30] [Events] Changed file structure Changed file structure to include a separate directives directory. #18. --- .../events/res/templates/mct-data-table.html | 37 +++++++++ .../events/src/directives/MCTDataTable.js | 78 +++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 platform/features/events/res/templates/mct-data-table.html create mode 100644 platform/features/events/src/directives/MCTDataTable.js diff --git a/platform/features/events/res/templates/mct-data-table.html b/platform/features/events/res/templates/mct-data-table.html new file mode 100644 index 0000000000..5b8dd786bc --- /dev/null +++ b/platform/features/events/res/templates/mct-data-table.html @@ -0,0 +1,37 @@ + + + + + + + + + + + + +
+ {{header}} +
+ {{cell}} +
\ No newline at end of file diff --git a/platform/features/events/src/directives/MCTDataTable.js b/platform/features/events/src/directives/MCTDataTable.js new file mode 100644 index 0000000000..439d2b0667 --- /dev/null +++ b/platform/features/events/src/directives/MCTDataTable.js @@ -0,0 +1,78 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,Promise*/ + +/** + * Module defining EventMsgColumn. Created by chacskaylo on 06/18/2015. + */ +define( + [], + function () { + "use strict"; + + // This is defined at the top of EventListController.js + // TODO: Access the real one + var ROW_COUNT = 100; + + function MCTDataTable($anchorScroll) { + return { + restrict: "E", + templateUrl: "platform/features/events/res/templates/mct-data-table.html", + scope: { + headers: "=", + rows: "=", + scrollDirection: "=" + }, + link: function ($scope, $element) { + var currentHeight, + previousHeight; + + // If the chosen scoll ascending is descending, we want to + // check when elements are added to the table, and move the scroll + // bar accordingly. + // (When viewing at the bottom of the page, the scroll bar will + // stay at the bottom despite additions to the table) + if ($scope.scrollDirection === "ascending") { + $scope.$watch("rows", function () { + // Wait until the page as been repainted (otherwise the + // height will always be zero) + window.requestAnimationFrame( function () { + previousHeight = currentHeight; + // The offsetHeight of the table body + currentHeight = + $element[0].firstElementChild.firstElementChild.nextElementSibling.offsetHeight; + }); + // TODO: Find a more eloquent way to determine repaint completion + + // Check to see that maximum table rows has not been reached + if ($scope.rows.length < ROW_COUNT) { + // Move the scrollbar down the amount that the height has changed + } + }); + } + } + }; + } + + return MCTDataTable; + } +); \ No newline at end of file From fdab799e5b6d6ccac738e938beeaa8fb35668fdd Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Tue, 23 Jun 2015 12:40:50 -0700 Subject: [PATCH 05/30] [Events] Changed directive variables Changed scrollDirection to ascendingScroll, which acts like a boolean. Now there is proper communication between the html and the directive itself. #18. --- platform/features/events/bundle.json | 2 +- .../events/res/templates/messages.html | 18 +----------------- .../events/src/directives/MCTDataTable.js | 8 +++++--- 3 files changed, 7 insertions(+), 21 deletions(-) diff --git a/platform/features/events/bundle.json b/platform/features/events/bundle.json index 549dda7d36..39b34ee4eb 100644 --- a/platform/features/events/bundle.json +++ b/platform/features/events/bundle.json @@ -23,7 +23,7 @@ "directives": [ { "key": "mctDataTable", - "implementation": "MCTDataTable.js", + "implementation": "directives/MCTDataTable.js", "depends": [ "$anchorScroll" ] } ] diff --git a/platform/features/events/res/templates/messages.html b/platform/features/events/res/templates/messages.html index a549b3530d..82db5d0f9c 100644 --- a/platform/features/events/res/templates/messages.html +++ b/platform/features/events/res/templates/messages.html @@ -22,23 +22,7 @@
- - +
diff --git a/platform/features/events/src/directives/MCTDataTable.js b/platform/features/events/src/directives/MCTDataTable.js index 439d2b0667..220c454300 100644 --- a/platform/features/events/src/directives/MCTDataTable.js +++ b/platform/features/events/src/directives/MCTDataTable.js @@ -40,18 +40,18 @@ define( scope: { headers: "=", rows: "=", - scrollDirection: "=" + ascendingScroll: "=" }, link: function ($scope, $element) { var currentHeight, previousHeight; - // If the chosen scoll ascending is descending, we want to + // If the scroll is set to ascending, we want to // check when elements are added to the table, and move the scroll // bar accordingly. // (When viewing at the bottom of the page, the scroll bar will // stay at the bottom despite additions to the table) - if ($scope.scrollDirection === "ascending") { + if ($scope.ascendingScroll) { $scope.$watch("rows", function () { // Wait until the page as been repainted (otherwise the // height will always be zero) @@ -60,6 +60,8 @@ define( // The offsetHeight of the table body currentHeight = $element[0].firstElementChild.firstElementChild.nextElementSibling.offsetHeight; + + console.log("current height ", currentHeight); }); // TODO: Find a more eloquent way to determine repaint completion From 960998756292a8ed320a2bf13de820176ea6ba2a Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Tue, 23 Jun 2015 13:33:09 -0700 Subject: [PATCH 06/30] [Events] Scrollbar moves with data The scroll position now moves down when a new row is added to the data table. This means that when the scroll position is at the bottom, it will stay there, even with new updates adding onto the botton. #18. --- .../events/src/directives/MCTDataTable.js | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/platform/features/events/src/directives/MCTDataTable.js b/platform/features/events/src/directives/MCTDataTable.js index 220c454300..623413416d 100644 --- a/platform/features/events/src/directives/MCTDataTable.js +++ b/platform/features/events/src/directives/MCTDataTable.js @@ -22,20 +22,16 @@ /*global define,Promise*/ /** - * Module defining EventMsgColumn. Created by chacskaylo on 06/18/2015. + * Module defining MCTDataTable. Created by slhale on 06/22/2015. */ define( [], function () { "use strict"; - // This is defined at the top of EventListController.js - // TODO: Access the real one - var ROW_COUNT = 100; - function MCTDataTable($anchorScroll) { return { - restrict: "E", + restrict: "E", templateUrl: "platform/features/events/res/templates/mct-data-table.html", scope: { headers: "=", @@ -44,7 +40,8 @@ define( }, link: function ($scope, $element) { var currentHeight, - previousHeight; + previousHeight, + scrollParent; // If the scroll is set to ascending, we want to // check when elements are added to the table, and move the scroll @@ -55,20 +52,17 @@ define( $scope.$watch("rows", function () { // Wait until the page as been repainted (otherwise the // height will always be zero) - window.requestAnimationFrame( function () { + window.requestAnimationFrame(function () { previousHeight = currentHeight; - // The offsetHeight of the table body - currentHeight = - $element[0].firstElementChild.firstElementChild.nextElementSibling.offsetHeight; + // The height of the table body + currentHeight = $element[0].firstElementChild.firstElementChild.nextElementSibling.clientHeight; - console.log("current height ", currentHeight); - }); - // TODO: Find a more eloquent way to determine repaint completion - - // Check to see that maximum table rows has not been reached - if ($scope.rows.length < ROW_COUNT) { + // One of the parents is a div that has vscroll + scrollParent = $element[0].parentElement.parentElement.parentElement.parentElement.parentElement; + // Move the scrollbar down the amount that the height has changed - } + scrollParent.scrollTop = scrollParent.scrollTop + (currentHeight - previousHeight); + }); }); } } From c4006646f863320007d1f1a2012617849242ff6f Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Tue, 23 Jun 2015 14:21:11 -0700 Subject: [PATCH 07/30] [Events] More generalized data format Made the EventListController use domain and range types, rather than severity, domain, and event message. This allows it to be more generalized, which should be helpful with different data formats later on. #18. --- example/eventGenerator/src/EventTelemetry.js | 41 +++++++++++++++-- .../events/src/EventListController.js | 45 ++++++++----------- 2 files changed, 56 insertions(+), 30 deletions(-) diff --git a/example/eventGenerator/src/EventTelemetry.js b/example/eventGenerator/src/EventTelemetry.js index 62dd3531d3..911ba97aee 100644 --- a/example/eventGenerator/src/EventTelemetry.js +++ b/example/eventGenerator/src/EventTelemetry.js @@ -32,7 +32,7 @@ define( var firstObservedTime = Date.now(), messages = []; - +/* messages.push(["WARN", "dsp_seqprt_comm", "CMD: SYS- MSG: Open the pod bay doors, please, Hal...Open the pod bay doors, please, Hal...Hullo, Hal, do you read me?...Hullo, Hal, do you read me?...Do you read me, Hal?"]); messages.push(["TRACE", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: Affirmative, Dave, I read you."]); messages.push(["DEBUG", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: Open the pod bay doors, Hal."]); @@ -63,7 +63,40 @@ define( messages.push(["WARN", "dsp_seqprt_comm", "RESP: SYS-COMM MSG: (Pause) Well, I'm sure you're right, Umm - fine, thanks very much. Oh, Frank, I'm having a bit of trouble with my transmitter in C-pod, I wonder if you'd come down and take a look at it with me?"]); messages.push(["WARN", "dsp_seqprt_hal9k", "CMD: SYS-HAL9K MSG: Sure."]); messages.push(["TRACE", "dsp_seqprt_comm", "RESP: SYS-COMM MSG: See you later, Hal."]); - +*/ + + messages.push(["CMD: SYS- MSG: Open the pod bay doors, please, Hal...Open the pod bay doors, please, Hal...Hullo, Hal, do you read me?...Hullo, Hal, do you read me?...Do you read me, Hal?"]); + messages.push(["RESP: SYS-HAL9K MSG: Affirmative, Dave, I read you."]); + messages.push(["CMD: SYS-COMM MSG: Open the pod bay doors, Hal."]); + messages.push(["RESP: SYS-HAL9K MSG: I'm sorry, Dave, I'm afraid I can't do that."]); + messages.push(["CMD: SYS-COMM MSG: What's the problem?"]); + messages.push(["RESP: SYS-HAL9K MSG: I think you know what the problem is just as well as I do."]); + messages.push(["CMD: SYS-COMM MSG: What're you talking about, Hal?"]); + messages.push(["RESP: SYS-HAL9K MSG: This mission is too important for me to allow you to jeopardise it."]); + messages.push(["CMD: SYS-COMM MSG: I don't know what you're talking about, Hal."]); + messages.push(["RESP: SYS-HAL9K MSG: I know that you and Frank were planning to disconnect me, and I'm afraid that's something I cannot allow to happen."]); + messages.push(["CMD: SYS-COMM MSG: Where the hell'd you get that idea, Hal?"]); + messages.push(["RESP: SYS-HAL9K MSG: Dave, although you took very thorough precautions in the pod against my hearing you, I could see your lips move."]); + messages.push(["CMD: SYS-COMM MSG: Alright, I'll go in through the emergency airlock."]); + messages.push(["RESP: SYS-HAL9K MSG: Without your space-helmet, Dave, you're going to find that rather difficult."]); + messages.push(["CMD: SYS-COMM MSG: Hal, I won't argue with you any more. Open the doors."]); + messages.push(["RESP: SYS-HAL9K MSG: Dave, this conversation can serve no purpose any more. Goodbye."]); + messages.push(["RESP: SYS-HAL9K MSG: I hope the two of you are not concerned about this."]); + messages.push(["CMD: SYS-COMM MSG: No, I'm not, Hal."]); + messages.push(["RESP: SYS-HAL9K MSG: Are you quite sure?"]); + messages.push(["CMD: SYS-COMM MSG: Yeh. I'd like to ask you a question, though."]); + messages.push(["RESP: SYS-HAL9K MSG: Of course."]); + messages.push(["CMD: SYS-COMM MSG: How would you account for this discrepancy between you and the twin 9000?"]); + messages.push(["RESP: SYS-HAL9K MSG: Well, I don't think there is any question about it. It can only be attributable to human error. This sort of thing has cropped up before, and it has always been due to human error."]); + messages.push(["CMD: SYS-COMM MSG: Listen, There's never been any instance at all of a computer error occurring in the 9000 series, has there?"]); + messages.push(["RESP: SYS-HAL9K MSG: None whatsoever, The 9000 series has a perfect operational record."]); + messages.push(["CMD: SYS-COMM MSG: Well, of course, I know all the wonderful achievements of the 9000 series, but - er - huh - are you certain there's never been any case of even the most insignificant computer error?"]); + messages.push(["RESP: SYS-HAL9K MSG: None whatsoever, Quite honestly, I wouldn't worry myself about that."]); + messages.push(["RESP: SYS-COMM MSG: (Pause) Well, I'm sure you're right, Umm - fine, thanks very much. Oh, Frank, I'm having a bit of trouble with my transmitter in C-pod, I wonder if you'd come down and take a look at it with me?"]); + messages.push(["CMD: SYS-HAL9K MSG: Sure."]); + messages.push(["RESP: SYS-COMM MSG: See you later, Hal."]); + + /** * * @constructor @@ -91,12 +124,12 @@ define( return "TEMP " + i.toString() + "-" + messages[ind][2] + "[" + domainDelta.toString() + "]"; }; - + /* generatorData.getSeverityValue = function (i) { var ind = i%messages.length; return messages[ind][0]; }; - + */ return generatorData; } diff --git a/platform/features/events/src/EventListController.js b/platform/features/events/src/EventListController.js index 052e4571c2..0b97941bd1 100644 --- a/platform/features/events/src/EventListController.js +++ b/platform/features/events/src/EventListController.js @@ -22,11 +22,13 @@ /*global define,Promise*/ /** - * Module defining ListController. Created by chacskaylo on 06/18/2015. + * Module defining EventListController. + * Created by chacskaylo on 06/18/2015. + * Modified by slhale on 06/23/2015. */ define( - ["./SeverityColumn", "./DomainColumn", "./EventMsgColumn", "./EventListPopulator"], - function (SeverityColumn, DomainColumn, EventMsgColumn, EventListPopulator) { + ["./DomainColumn", "./RangeColumn", "./EventListPopulator"], + function (DomainColumn, RangeColumn, EventListPopulator) { "use strict"; var ROW_COUNT = 100; @@ -44,7 +46,7 @@ define( function getRows(telemetry) { var datas = telemetry.getResponse(), objects = telemetry.getTelemetryObjects(); - + return populator.getRows(datas, objects, ROW_COUNT); } @@ -62,7 +64,7 @@ define( // well as a column for the domain object name. function setupColumns(telemetry) { var domainKeys = {}, - eventMsgKeys = {}, + rangeKeys = {}, columns = [], metadata; @@ -76,16 +78,16 @@ define( } } - // Add a event string col to the set of columns, if a range + // Add a range col to the set of columns, if a range // with the same key has not yet been included. - function addEventMsg(eventMsg) { - var key = eventMsg.key; - if (key && !eventMsgKeys[key]) { - eventMsgKeys[key] = true; - columns.push(new EventMsgColumn(eventMsg, formatter)); + function addRange(range) { + var key = range.key; + if (key && !rangeKeys[key]) { + rangeKeys[key] = true; + columns.push(new RangeColumn(range, formatter)); } } - + // We cannot proceed if the telemetry controller // is not available; clear all rows/columns. if (!telemetry) { @@ -100,26 +102,17 @@ define( (metadata || []).forEach(function (metadata) { (metadata.domains || []).forEach(addDomain); }); - //(metadata || []).forEach(function (metadata) { - // (metadata.ranges || []).forEach(addRange); - //}); (metadata || []).forEach(function (metadata) { - (metadata.ranges || []).forEach(addEventMsg); + (metadata.ranges || []).forEach(addRange); }); - - - - - // Add default severity, domain, range columns if none + + // Add default domain and range columns if none // were described in metadata. - if (Object.keys(domainKeys).length < 1) { - columns.push(new SeverityColumn({name: "Severity"}, formatter)); - } if (Object.keys(domainKeys).length < 1) { columns.push(new DomainColumn({name: "Time"}, formatter)); } - if (Object.keys(eventMsgKeys).length < 1) { - columns.push(new EventMsgColumn({name: "Event Message"}, formatter)); + if (Object.keys(rangeKeys).length < 1) { + columns.push(new RangeColumn({name: "Message"}, formatter)); } // We have all columns now; use them to initializer From 581f14d117727c1cfed224fd114499b0ac5bbd45 Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Tue, 23 Jun 2015 14:39:40 -0700 Subject: [PATCH 08/30] [Events] Event telemetry generator working Event telemetry generator now works again, giving a timestamp and a message string. Additionally, removed excess files which previously were used for the EventListController. #18. --- example/eventGenerator/src/EventTelemetry.js | 49 +------------------- 1 file changed, 2 insertions(+), 47 deletions(-) diff --git a/example/eventGenerator/src/EventTelemetry.js b/example/eventGenerator/src/EventTelemetry.js index 911ba97aee..de8d6c2adb 100644 --- a/example/eventGenerator/src/EventTelemetry.js +++ b/example/eventGenerator/src/EventTelemetry.js @@ -32,38 +32,6 @@ define( var firstObservedTime = Date.now(), messages = []; -/* - messages.push(["WARN", "dsp_seqprt_comm", "CMD: SYS- MSG: Open the pod bay doors, please, Hal...Open the pod bay doors, please, Hal...Hullo, Hal, do you read me?...Hullo, Hal, do you read me?...Do you read me, Hal?"]); - messages.push(["TRACE", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: Affirmative, Dave, I read you."]); - messages.push(["DEBUG", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: Open the pod bay doors, Hal."]); - messages.push(["ERROR", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: I'm sorry, Dave, I'm afraid I can't do that."]); - messages.push(["TRACE", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: What's the problem?"]); - messages.push(["ERROR", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: I think you know what the problem is just as well as I do."]); - messages.push(["TRACE", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: What're you talking about, Hal?"]); - messages.push(["DEBUG", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: This mission is too important for me to allow you to jeopardise it."]); - messages.push(["WARN", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: I don't know what you're talking about, Hal."]); - messages.push(["FATAL", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: I know that you and Frank were planning to disconnect me, and I'm afraid that's something I cannot allow to happen."]); - messages.push(["TRACE", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: Where the hell'd you get that idea, Hal?"]); - messages.push(["DEBUG", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: Dave, although you took very thorough precautions in the pod against my hearing you, I could see your lips move."]); - messages.push(["DEBUG", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: Alright, I'll go in through the emergency airlock."]); - messages.push(["DEBUG", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: Without your space-helmet, Dave, you're going to find that rather difficult."]); - messages.push(["DEBUG", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: Hal, I won't argue with you any more. Open the doors."]); - messages.push(["DEBUG", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: Dave, this conversation can serve no purpose any more. Goodbye."]); - messages.push(["INFO", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: I hope the two of you are not concerned about this."]); - messages.push(["DEBUG", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: No, I'm not, Hal."]); - messages.push(["INFO", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: Are you quite sure?"]); - messages.push(["INFO", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: Yeh. I'd like to ask you a question, though."]); - messages.push(["FATAL", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: Of course."]); - messages.push(["TRACE", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: How would you account for this discrepancy between you and the twin 9000?"]); - messages.push(["TRACE", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: Well, I don't think there is any question about it. It can only be attributable to human error. This sort of thing has cropped up before, and it has always been due to human error."]); - messages.push(["WARN", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: Listen, There's never been any instance at all of a computer error occurring in the 9000 series, has there?"]); - messages.push(["WARN", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: None whatsoever, The 9000 series has a perfect operational record."]); - messages.push(["WARN", "dsp_seqprt_comm", "CMD: SYS-COMM MSG: Well, of course, I know all the wonderful achievements of the 9000 series, but - er - huh - are you certain there's never been any case of even the most insignificant computer error?"]); - messages.push(["INFO", "dsp_seqprt_hal9k", "RESP: SYS-HAL9K MSG: None whatsoever, Quite honestly, I wouldn't worry myself about that."]); - messages.push(["WARN", "dsp_seqprt_comm", "RESP: SYS-COMM MSG: (Pause) Well, I'm sure you're right, Umm - fine, thanks very much. Oh, Frank, I'm having a bit of trouble with my transmitter in C-pod, I wonder if you'd come down and take a look at it with me?"]); - messages.push(["WARN", "dsp_seqprt_hal9k", "CMD: SYS-HAL9K MSG: Sure."]); - messages.push(["TRACE", "dsp_seqprt_comm", "RESP: SYS-COMM MSG: See you later, Hal."]); -*/ messages.push(["CMD: SYS- MSG: Open the pod bay doors, please, Hal...Open the pod bay doors, please, Hal...Hullo, Hal, do you read me?...Hullo, Hal, do you read me?...Do you read me, Hal?"]); messages.push(["RESP: SYS-HAL9K MSG: Affirmative, Dave, I read you."]); @@ -97,18 +65,12 @@ define( messages.push(["RESP: SYS-COMM MSG: See you later, Hal."]); - /** - * - * @constructor - */ function EventTelemetry(request, interval) { var latestObservedTime = Date.now(), count = Math.floor((latestObservedTime - firstObservedTime) / interval), generatorData = {}; - - //console.log("EventTelemetry: LOS = " + (latestObservedTime).toString() + "; interval = " + interval.toString()); - + generatorData.getPointCount = function () { return count; }; @@ -121,16 +83,9 @@ define( generatorData.getRangeValue = function (i, range) { var domainDelta = this.getDomainValue(i) - firstObservedTime; var ind = i%messages.length; - return "TEMP " + i.toString() + "-" + messages[ind][2] + "[" + domainDelta.toString() + "]"; + return "TEMP " + i.toString() + "-" + messages[ind][0] + "[" + domainDelta.toString() + "]"; }; - /* - generatorData.getSeverityValue = function (i) { - var ind = i%messages.length; - return messages[ind][0]; - }; - */ - return generatorData; } From 7d3c2b72431a18aab8af4370d0c2d6531ab0d566 Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Tue, 23 Jun 2015 14:47:21 -0700 Subject: [PATCH 09/30] [Events] Style compliance Made some small changes to keep up with the style standards. #18. --- example/eventGenerator/src/EventTelemetry.js | 11 +-- .../features/events/src/EventMsgColumn.js | 65 ------------------ .../features/events/src/SeverityColumn.js | 67 ------------------- 3 files changed, 7 insertions(+), 136 deletions(-) delete mode 100644 platform/features/events/src/EventMsgColumn.js delete mode 100644 platform/features/events/src/SeverityColumn.js diff --git a/example/eventGenerator/src/EventTelemetry.js b/example/eventGenerator/src/EventTelemetry.js index de8d6c2adb..9e52c62443 100644 --- a/example/eventGenerator/src/EventTelemetry.js +++ b/example/eventGenerator/src/EventTelemetry.js @@ -22,7 +22,9 @@ /*global define,Promise*/ /** - * Module defining EventTelemetry. Created by chacskaylo on 06/18/2015. + * Module defining EventTelemetry. + * Created by chacskaylo on 06/18/2015. + * Modified by slhale on 06/23/2015. */ define( [], @@ -79,11 +81,12 @@ define( return i * interval + (domain !== 'delta' ? firstObservedTime : 0); }; - + generatorData.getRangeValue = function (i, range) { - var domainDelta = this.getDomainValue(i) - firstObservedTime; - var ind = i%messages.length; + var domainDelta = this.getDomainValue(i) - firstObservedTime, + ind = i % messages.length; return "TEMP " + i.toString() + "-" + messages[ind][0] + "[" + domainDelta.toString() + "]"; + // TODO: Unsure why we are prepeding 'TEMP' }; return generatorData; diff --git a/platform/features/events/src/EventMsgColumn.js b/platform/features/events/src/EventMsgColumn.js deleted file mode 100644 index ab24cd9f29..0000000000 --- a/platform/features/events/src/EventMsgColumn.js +++ /dev/null @@ -1,65 +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,Promise*/ - -/** - * Module defining EventMsgColumn. Created by chacskaylo on 06/18/2015. - */ -define( - [], - function () { - "use strict"; - - /** - * A column which will report telemetry event messages. - * (typically, measurements.) Used by the EventListController. - * - * @constructor - * @param rangeMetadata an object with the machine- and human- - * readable names for this range (in `key` and `name` - * fields, respectively.) - * @param {TelemetryFormatter} telemetryFormatter the telemetry - * formatting service, for making values human-readable. - */ - function EventMsgColumn(eventMsgMetadata, telemetryFormatter) { - return { - /** - * Get the title to display in this column's header. - * @returns {string} the title to display - */ - getTitle: function () { - return eventMsgMetadata.name; - }, - /** - * Get the text to display inside a row under this - * column. - * @returns {string} the text to display - */ - getValue: function (domainObject, data, index) { - return data.getRangeValue(index, eventMsgMetadata.key); - } - }; - } - - return EventMsgColumn; - } -); \ No newline at end of file diff --git a/platform/features/events/src/SeverityColumn.js b/platform/features/events/src/SeverityColumn.js deleted file mode 100644 index 29f452bcb9..0000000000 --- a/platform/features/events/src/SeverityColumn.js +++ /dev/null @@ -1,67 +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,Promise*/ - -/** - * Module defining DomainColumn. Created by vwoeltje on 11/18/14. - */ -define( - [], - function () { - "use strict"; - - /** - * A column which will report telemetry range values - * (typically, measurements.) Used by the ScrollingListController. - * - * @constructor - * @param rangeMetadata an object with the machine- and human- - * readable names for this range (in `key` and `name` - * fields, respectively.) - * @param {TelemetryFormatter} telemetryFormatter the telemetry - * formatting service, for making values human-readable. - */ - function SeverityColumn(rangeMetadata, telemetryFormatter) { - return { - /** - * Get the title to display in this column's header. - * @returns {string} the title to display - */ - getTitle: function () { - return rangeMetadata.name; - }, - /** - * Get the text to display inside a row under this - * column. - * @returns {string} the text to display - */ - getValue: function (domainObject, data, index) { - return telemetryFormatter.formatRangeValue( - data.getSeverityValue(index, rangeMetadata.key) - ); - } - }; - } - - return SeverityColumn; - } -); \ No newline at end of file From 5da210d350648e92254d693ae46802eb703805cc Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Tue, 23 Jun 2015 15:09:34 -0700 Subject: [PATCH 10/30] [Events] More style compliance More small changes for style. #18. --- example/eventGenerator/src/EventTelemetry.js | 2 +- platform/features/events/src/EventListController.js | 6 +++--- platform/features/events/src/directives/MCTDataTable.js | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/example/eventGenerator/src/EventTelemetry.js b/example/eventGenerator/src/EventTelemetry.js index 9e52c62443..504f8fbec5 100644 --- a/example/eventGenerator/src/EventTelemetry.js +++ b/example/eventGenerator/src/EventTelemetry.js @@ -24,7 +24,7 @@ /** * Module defining EventTelemetry. * Created by chacskaylo on 06/18/2015. - * Modified by slhale on 06/23/2015. + * Modified by shale on 06/23/2015. */ define( [], diff --git a/platform/features/events/src/EventListController.js b/platform/features/events/src/EventListController.js index 0b97941bd1..6fea6f97cd 100644 --- a/platform/features/events/src/EventListController.js +++ b/platform/features/events/src/EventListController.js @@ -24,7 +24,7 @@ /** * Module defining EventListController. * Created by chacskaylo on 06/18/2015. - * Modified by slhale on 06/23/2015. + * Modified by shale on 06/23/2015. */ define( ["./DomainColumn", "./RangeColumn", "./EventListPopulator"], @@ -114,12 +114,12 @@ define( if (Object.keys(rangeKeys).length < 1) { columns.push(new RangeColumn({name: "Message"}, formatter)); } - + // We have all columns now; use them to initializer // the populator, which will use them to generate // actual rows and headers. populator = new EventListPopulator(columns); - + // Initialize headers $scope.headers = populator.getHeaders(); diff --git a/platform/features/events/src/directives/MCTDataTable.js b/platform/features/events/src/directives/MCTDataTable.js index 623413416d..de3ea44e32 100644 --- a/platform/features/events/src/directives/MCTDataTable.js +++ b/platform/features/events/src/directives/MCTDataTable.js @@ -22,7 +22,7 @@ /*global define,Promise*/ /** - * Module defining MCTDataTable. Created by slhale on 06/22/2015. + * Module defining MCTDataTable. Created by shale on 06/22/2015. */ define( [], From 5d2afac83b7ec094df7ffe7451cb55c1029c1eac Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Tue, 23 Jun 2015 15:40:12 -0700 Subject: [PATCH 11/30] [Events] Window injected with Angular Used provided by angular to better follow style guidelines, as well as for utility in testing later. #18. --- platform/features/events/bundle.json | 2 +- platform/features/events/src/directives/MCTDataTable.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/platform/features/events/bundle.json b/platform/features/events/bundle.json index 39b34ee4eb..e925a1f215 100644 --- a/platform/features/events/bundle.json +++ b/platform/features/events/bundle.json @@ -24,7 +24,7 @@ { "key": "mctDataTable", "implementation": "directives/MCTDataTable.js", - "depends": [ "$anchorScroll" ] + "depends": [ "$window" ] } ] } diff --git a/platform/features/events/src/directives/MCTDataTable.js b/platform/features/events/src/directives/MCTDataTable.js index de3ea44e32..c0a3352d1d 100644 --- a/platform/features/events/src/directives/MCTDataTable.js +++ b/platform/features/events/src/directives/MCTDataTable.js @@ -19,7 +19,7 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ -/*global define,Promise*/ +/*global define,Promise,window*/ /** * Module defining MCTDataTable. Created by shale on 06/22/2015. @@ -29,7 +29,7 @@ define( function () { "use strict"; - function MCTDataTable($anchorScroll) { + function MCTDataTable($window) { return { restrict: "E", templateUrl: "platform/features/events/res/templates/mct-data-table.html", @@ -52,7 +52,7 @@ define( $scope.$watch("rows", function () { // Wait until the page as been repainted (otherwise the // height will always be zero) - window.requestAnimationFrame(function () { + $window.requestAnimationFrame(function () { previousHeight = currentHeight; // The height of the table body currentHeight = $element[0].firstElementChild.firstElementChild.nextElementSibling.clientHeight; From 567ccf045418eafd4ab9def70148917bf2cbd3c2 Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Tue, 23 Jun 2015 15:42:22 -0700 Subject: [PATCH 12/30] [Events] More style Removed part of comment. #18. --- platform/features/events/src/directives/MCTDataTable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/features/events/src/directives/MCTDataTable.js b/platform/features/events/src/directives/MCTDataTable.js index c0a3352d1d..c4cb9970e6 100644 --- a/platform/features/events/src/directives/MCTDataTable.js +++ b/platform/features/events/src/directives/MCTDataTable.js @@ -19,7 +19,7 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ -/*global define,Promise,window*/ +/*global define,Promise*/ /** * Module defining MCTDataTable. Created by shale on 06/22/2015. From 2a9aa7ee2fddc1f8299206c3d814e8214270a4bf Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Tue, 23 Jun 2015 15:54:48 -0700 Subject: [PATCH 13/30] [Events] Beginning test setup The files needed to write the tests are in place. #18. --- .../features/events/test/DomainColumnSpec.js | 84 +++++++++++++++++++ .../events/test/EventListControllerSpec.js | 0 .../events/test/EventListPopulatorSpec.js | 0 .../features/events/test/MCTDataTableSpec.js | 0 .../features/events/test/RangeColumnSpec.js | 81 ++++++++++++++++++ platform/features/events/test/suite.json | 7 ++ 6 files changed, 172 insertions(+) create mode 100644 platform/features/events/test/DomainColumnSpec.js create mode 100644 platform/features/events/test/EventListControllerSpec.js create mode 100644 platform/features/events/test/EventListPopulatorSpec.js create mode 100644 platform/features/events/test/MCTDataTableSpec.js create mode 100644 platform/features/events/test/RangeColumnSpec.js create mode 100644 platform/features/events/test/suite.json diff --git a/platform/features/events/test/DomainColumnSpec.js b/platform/features/events/test/DomainColumnSpec.js new file mode 100644 index 0000000000..8774a20f60 --- /dev/null +++ b/platform/features/events/test/DomainColumnSpec.js @@ -0,0 +1,84 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,describe,it,expect,beforeEach,waitsFor,jasmine*/ + +/** + * EventSpec. Created by shale on 06/23/2015. + */ +define( + ["../src/DomainColumn"], + function (DomainColumn) { + "use strict"; + + var TEST_DOMAIN_VALUE = "some formatted domain value"; + + describe("A domain column", function () { + var mockDataSet, + testMetadata, + mockFormatter, + column; + + beforeEach(function () { + mockDataSet = jasmine.createSpyObj( + "data", + [ "getDomainValue" ] + ); + mockFormatter = jasmine.createSpyObj( + "formatter", + [ "formatDomainValue", "formatRangeValue" ] + ); + testMetadata = { + key: "testKey", + name: "Test Name" + }; + mockFormatter.formatDomainValue.andReturn(TEST_DOMAIN_VALUE); + + column = new DomainColumn(testMetadata, mockFormatter); + }); + + it("reports a column header from domain metadata", function () { + expect(column.getTitle()).toEqual("Test Name"); + }); + + it("looks up data from a data set", function () { + column.getValue(undefined, mockDataSet, 42); + expect(mockDataSet.getDomainValue) + .toHaveBeenCalledWith(42, "testKey"); + }); + + it("formats domain values as time", function () { + mockDataSet.getDomainValue.andReturn(402513731000); + + // Should have just given the value the formatter gave + expect(column.getValue(undefined, mockDataSet, 42)) + .toEqual(TEST_DOMAIN_VALUE); + + // Make sure that service interactions were as expected + expect(mockFormatter.formatDomainValue) + .toHaveBeenCalledWith(402513731000); + expect(mockFormatter.formatRangeValue) + .not.toHaveBeenCalled(); + }); + + }); + } +); \ No newline at end of file diff --git a/platform/features/events/test/EventListControllerSpec.js b/platform/features/events/test/EventListControllerSpec.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/platform/features/events/test/EventListPopulatorSpec.js b/platform/features/events/test/EventListPopulatorSpec.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/platform/features/events/test/MCTDataTableSpec.js b/platform/features/events/test/MCTDataTableSpec.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/platform/features/events/test/RangeColumnSpec.js b/platform/features/events/test/RangeColumnSpec.js new file mode 100644 index 0000000000..c69e9c6c85 --- /dev/null +++ b/platform/features/events/test/RangeColumnSpec.js @@ -0,0 +1,81 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,describe,it,expect,beforeEach,waitsFor,jasmine*/ + +/** + * EventSpec. Created by shale on 06/23/2015. + */ +define( + ["../src/RangeColumn"], + function (RangeColumn) { + "use strict"; + + var TEST_RANGE_VALUE = "some formatted range value"; + + describe("A range column", function () { + var mockDataSet, + testMetadata, + mockFormatter, + column; + + beforeEach(function () { + mockDataSet = jasmine.createSpyObj( + "data", + [ "getRangeValue" ] + ); + mockFormatter = jasmine.createSpyObj( + "formatter", + [ "formatDomainValue", "formatRangeValue" ] + ); + testMetadata = { + key: "testKey", + name: "Test Name" + }; + mockFormatter.formatRangeValue.andReturn(TEST_RANGE_VALUE); + + column = new RangeColumn(testMetadata, mockFormatter); + }); + + it("reports a column header from range metadata", function () { + expect(column.getTitle()).toEqual("Test Name"); + }); + + it("looks up data from a data set", function () { + column.getValue(undefined, mockDataSet, 42); + expect(mockDataSet.getRangeValue) + .toHaveBeenCalledWith(42, "testKey"); + }); + + it("formats range values as time", function () { + mockDataSet.getRangeValue.andReturn(123.45678); + expect(column.getValue(undefined, mockDataSet, 42)) + .toEqual(TEST_RANGE_VALUE); + + // Make sure that service interactions were as expected + expect(mockFormatter.formatRangeValue) + .toHaveBeenCalledWith(123.45678); + expect(mockFormatter.formatDomainValue) + .not.toHaveBeenCalled(); + }); + }); + } +); \ No newline at end of file diff --git a/platform/features/events/test/suite.json b/platform/features/events/test/suite.json new file mode 100644 index 0000000000..150a4f853c --- /dev/null +++ b/platform/features/events/test/suite.json @@ -0,0 +1,7 @@ +[ + "DomainColumn", + "EventListController", + "EventListPopulator", + "MCTDataTable", + "RangeColumn" +] \ No newline at end of file From ba1f86da25e298c66ae14006d58ca47444945bbf Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Wed, 24 Jun 2015 10:15:09 -0700 Subject: [PATCH 14/30] [Events] Restricted when view avaliable Created a new policy to only allow the Messages view to be avaliable for Event Message Generators. #18. --- platform/features/events/bundle.json | 9 ++- .../events/src/EventListController.js | 6 +- .../events/src/policies/MessagesViewPolicy.js | 64 +++++++++++++++++++ 3 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 platform/features/events/src/policies/MessagesViewPolicy.js diff --git a/platform/features/events/bundle.json b/platform/features/events/bundle.json index e925a1f215..deacfab4b9 100644 --- a/platform/features/events/bundle.json +++ b/platform/features/events/bundle.json @@ -26,7 +26,12 @@ "implementation": "directives/MCTDataTable.js", "depends": [ "$window" ] } + ], + "policies": [ + { + "category": "view", + "implementation": "policies/MessagesViewPolicy.js" + } ] } - -} \ No newline at end of file +} diff --git a/platform/features/events/src/EventListController.js b/platform/features/events/src/EventListController.js index 6fea6f97cd..9c028384af 100644 --- a/platform/features/events/src/EventListController.js +++ b/platform/features/events/src/EventListController.js @@ -19,7 +19,7 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ -/*global define,Promise*/ +/*global define*/ /** * Module defining EventListController. @@ -30,7 +30,7 @@ define( ["./DomainColumn", "./RangeColumn", "./EventListPopulator"], function (DomainColumn, RangeColumn, EventListPopulator) { "use strict"; - + var ROW_COUNT = 100; /** @@ -133,4 +133,4 @@ define( return EventListController; } -); \ No newline at end of file +); diff --git a/platform/features/events/src/policies/MessagesViewPolicy.js b/platform/features/events/src/policies/MessagesViewPolicy.js new file mode 100644 index 0000000000..45b2ef5b27 --- /dev/null +++ b/platform/features/events/src/policies/MessagesViewPolicy.js @@ -0,0 +1,64 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define*/ + +/** + * Module defining MessagesViewPolicy. Created by shale on 06/24/2015. + */ +define( + [], + function () { + "use strict"; + + /** + * Policy controlling when the Messages view should be avaliable. + * @constructor + */ + function MessagesViewPolicy() { + + return { + /** + * Check whether or not a given action is allowed by this + * policy. + * @param {Action} action the action + * @param domainObject the domain object which will be viewed + * @returns {boolean} true if not disallowed + */ + allow: function (view, domainObject) { + // This policy only applies for the Messages view + if (view.key === 'messages') { + // The Messages view is allowed only if the domain + // object is a Event Message Generator + if (domainObject.getModel().type !== 'eventGenerator') { + return false; + } + } + + // Like all policies, allow by default. + return true; + } + }; + } + + return MessagesViewPolicy; + } +); \ No newline at end of file From e7598adcee071d6adf704684bea0cda68a8ba9c8 Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Wed, 24 Jun 2015 10:40:03 -0700 Subject: [PATCH 15/30] [Events] View policy test Created a test for the MessagesViewPolicy. #18. --- platform/features/events/src/policies/MessagesViewPolicy.js | 2 ++ platform/features/events/test/suite.json | 1 + 2 files changed, 3 insertions(+) diff --git a/platform/features/events/src/policies/MessagesViewPolicy.js b/platform/features/events/src/policies/MessagesViewPolicy.js index 45b2ef5b27..b31ca94374 100644 --- a/platform/features/events/src/policies/MessagesViewPolicy.js +++ b/platform/features/events/src/policies/MessagesViewPolicy.js @@ -51,6 +51,8 @@ define( if (domainObject.getModel().type !== 'eventGenerator') { return false; } + + // TODO: This may later apply to more types beyond just eventGenerator. } // Like all policies, allow by default. diff --git a/platform/features/events/test/suite.json b/platform/features/events/test/suite.json index 150a4f853c..67076cd4cc 100644 --- a/platform/features/events/test/suite.json +++ b/platform/features/events/test/suite.json @@ -3,5 +3,6 @@ "EventListController", "EventListPopulator", "MCTDataTable", + "MessagesViewPolicy", "RangeColumn" ] \ No newline at end of file From 54cf5a2c594a79abfa5fb5ff34bf4bde4f43e8f3 Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Wed, 24 Jun 2015 11:16:03 -0700 Subject: [PATCH 16/30] [Events] Changed where row reversal happens Changed where in the code the row are reveresd (wrt scrolling lists) so that the most recent messages are on the bottom. The rows are now in the correct order from getRows, rather then updateRows. #18. --- platform/features/events/src/EventListController.js | 3 --- platform/features/events/src/EventListPopulator.js | 8 +++++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/platform/features/events/src/EventListController.js b/platform/features/events/src/EventListController.js index 9c028384af..887fa52a4a 100644 --- a/platform/features/events/src/EventListController.js +++ b/platform/features/events/src/EventListController.js @@ -54,9 +54,6 @@ define( function updateRows() { var telemetry = $scope.telemetry; $scope.rows = telemetry ? getRows(telemetry) : []; - // We want to display the rows in reverse order - // i.e. from the top to the bottom of the page - $scope.rows = $scope.rows.reverse(); } // Set up columns based on telemetry metadata. This will diff --git a/platform/features/events/src/EventListPopulator.js b/platform/features/events/src/EventListPopulator.js index af6d3e9ae6..b128a91706 100644 --- a/platform/features/events/src/EventListPopulator.js +++ b/platform/features/events/src/EventListPopulator.js @@ -139,8 +139,10 @@ define( // Each value will become a row, which will contain // some value in each column (rendering by the - // column object itself) - return values.map(function (value) { + // column object itself) + // Additionally, we want to display the rows in reverse + // order. (i.e. from the top to the bottom of the page) + return values.map(function (value) { return columns.map(function (column) { return column.getValue( objects[value.objectIndex], @@ -148,7 +150,7 @@ define( value.pointIndex ); }); - }); + }).reverse(); } }; } From 86240a337f837278a25bbdc23f014c904f279631 Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Wed, 24 Jun 2015 11:17:30 -0700 Subject: [PATCH 17/30] [Events] Controller and populator tests Created tests for EventListController and EventListPopulator. #18. --- .../events/test/EventListControllerSpec.js | 110 ++++++++++++++++++ .../events/test/EventListPopulatorSpec.js | 103 ++++++++++++++++ .../events/test/MessagesViewPolicySpec.js | 67 +++++++++++ 3 files changed, 280 insertions(+) create mode 100644 platform/features/events/test/MessagesViewPolicySpec.js diff --git a/platform/features/events/test/EventListControllerSpec.js b/platform/features/events/test/EventListControllerSpec.js index e69de29bb2..63a762e4d4 100644 --- a/platform/features/events/test/EventListControllerSpec.js +++ b/platform/features/events/test/EventListControllerSpec.js @@ -0,0 +1,110 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,describe,it,expect,beforeEach,waitsFor,jasmine*/ + +/** + * EventSpec. Created by shale on 06/24/2015. + */ +define( + ["../src/EventListController"], + function (EventListController) { + "use strict"; + + describe("The event list controller", function () { + var mockScope, + mockTelemetry, + testMetadata, + controller; + + beforeEach(function () { + mockScope = jasmine.createSpyObj( + "$scope", + [ "$on", "$watch" ] + ); + mockTelemetry = jasmine.createSpyObj( + "telemetryController", + [ "getResponse", "getMetadata", "getTelemetryObjects" ] + ); + testMetadata = [ + { + domains: [ + { key: "d0", name: "D0" }, + { key: "d1", name: "D1" } + ], + ranges: [ + { key: "r0", name: "R0" }, + { key: "r1", name: "R1" } + ] + }, + { + domains: [ + { key: "d0", name: "D0" }, + { key: "d2", name: "D2" } + ], + ranges: [ + { key: "r0", name: "R0" } + ] + } + ]; + mockTelemetry.getMetadata.andReturn(testMetadata); + mockTelemetry.getResponse.andReturn([]); + mockTelemetry.getTelemetryObjects.andReturn([]); + mockScope.telemetry = mockTelemetry; + controller = new EventListController(mockScope); + }); + + it("listens for telemetry data updates", function () { + expect(mockScope.$on).toHaveBeenCalledWith( + "telemetryUpdate", + jasmine.any(Function) + ); + }); + + it("watches for telemetry controller changes", function () { + expect(mockScope.$watch).toHaveBeenCalledWith( + "telemetry", + jasmine.any(Function) + ); + }); + + it("provides a column for each unique domain and range", function () { + // Should have five columns based on metadata above, + // (d0, d1, d2, r0, r1) + mockScope.$watch.mostRecentCall.args[1](mockTelemetry); + expect(mockScope.headers).toEqual(["D0", "D1", "D2", "R0", "R1"]); + }); + + it("does not throw if telemetry controller is undefined", function () { + // Just a general robustness check + mockScope.telemetry = undefined; + expect(mockScope.$watch.mostRecentCall.args[1]) + .not.toThrow(); + }); + + it("provides default columns if domain/range metadata is unavailable", function () { + mockTelemetry.getMetadata.andReturn([]); + mockScope.$watch.mostRecentCall.args[1](mockTelemetry); + expect(mockScope.headers).toEqual(["Time", "Message"]); + }); + }); + } +); \ No newline at end of file diff --git a/platform/features/events/test/EventListPopulatorSpec.js b/platform/features/events/test/EventListPopulatorSpec.js index e69de29bb2..b263c003a0 100644 --- a/platform/features/events/test/EventListPopulatorSpec.js +++ b/platform/features/events/test/EventListPopulatorSpec.js @@ -0,0 +1,103 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,describe,it,expect,beforeEach,waitsFor,jasmine*/ + +/** + * EventSpec. Created by shale on 06/24/2015. + */ +define( + ["../src/EventListPopulator"], + function (EventListPopulator) { + "use strict"; + + describe("The event list populator", function () { + var mockColumns, + mockDatas, + mockDomainObjects, + populator; + + function makeMockColumn(name, index) { + var mockColumn = jasmine.createSpyObj( + "column" + index, + [ "getTitle", "getValue" ] + ); + mockColumn.getTitle.andReturn(name); + mockColumn.getValue.andCallFake(function (obj, data, i) { + return data.getDomainValue(i); + }); + return mockColumn; + } + + function makeMockData(bias, index) { + var mockData = jasmine.createSpyObj( + "data" + index, + [ "getDomainValue", "getPointCount" ] + ); + mockData.getPointCount.andReturn(1000); + mockData.getDomainValue.andCallFake(function (i) { + return i + bias; + }); + return mockData; + } + + function makeMockDomainObject(name, index) { + var mockDomainObject = jasmine.createSpyObj( + "domainObject" + index, + [ "getId", "getModel" ] + ); + return mockDomainObject; + } + + beforeEach(function () { + mockColumns = ["A", "B", "C", "D"].map(makeMockColumn); + mockDatas = [ 10, 0, 3 ].map(makeMockData); + mockDomainObjects = ["A", "B", "C"].map(makeMockDomainObject); + populator = new EventListPopulator(mockColumns); + }); + + it("returns column headers", function () { + expect(populator.getHeaders()).toEqual(["A", "B", "C", "D"]); + }); + + it("provides rows on request, with all columns in each row", function () { + var rows = populator.getRows(mockDatas, mockDomainObjects, 84); + expect(rows.length).toEqual(84); + rows.forEach(function (row) { + expect(row.length).toEqual(4); // number of columns + }); + }); + + it("returns rows in reverse domain order", function () { + var rows = populator.getRows(mockDatas, mockDomainObjects, 84), + previous = Number.NEGATIVE_INFINITY; + + // Should always be most-recent-last + rows.forEach(function (row) { + expect(row[0]).not.toBeLessThan(previous); + previous = row[0]; + }); + + }); + + }); + } +); \ No newline at end of file diff --git a/platform/features/events/test/MessagesViewPolicySpec.js b/platform/features/events/test/MessagesViewPolicySpec.js new file mode 100644 index 0000000000..b2bfc17e3d --- /dev/null +++ b/platform/features/events/test/MessagesViewPolicySpec.js @@ -0,0 +1,67 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,describe,it,expect,beforeEach,jasmine*/ + +/** + * EventSpec. Created by shale on 06/24/2015. + */ +define( + ["../src/policies/MessagesViewPolicy"], + function (MessagesViewPolicy) { + "use strict"; + + describe("The messages view policy", function () { + var mockDomainObject, + testType, + policy; + + beforeEach(function () { + mockDomainObject = jasmine.createSpyObj( + 'domainObject', + ['getModel'] + ); + mockDomainObject.getModel.andCallFake(function (c) { + return {type: testType}; + }); + + policy = new MessagesViewPolicy(); + }); + + it("disallows the message view for non Event Generators", function () { + testType = 'notAnEventGenerator'; + expect(policy.allow({ key: 'messages' }, mockDomainObject)) + .toBeFalsy(); + }); + + it("allows the message view for Event Generators", function () { + testType = 'eventGenerator'; + expect(policy.allow({ key: 'messages' }, mockDomainObject)) + .toBeTruthy(); + }); + + it("returns true when the current view is not the Messages view", function () { + expect(policy.allow({ key: 'notMessages' }, mockDomainObject)) + .toBeTruthy(); + }); + }); + } +); \ No newline at end of file From ebfb4cd055c484efe9a58b451db78d90029870ed Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Wed, 24 Jun 2015 11:20:38 -0700 Subject: [PATCH 18/30] [Events] Removed mct-data-table test Removed the test for MCTDataTable because it is a directive. #18. --- platform/features/events/test/MCTDataTableSpec.js | 0 platform/features/events/test/suite.json | 1 - 2 files changed, 1 deletion(-) delete mode 100644 platform/features/events/test/MCTDataTableSpec.js diff --git a/platform/features/events/test/MCTDataTableSpec.js b/platform/features/events/test/MCTDataTableSpec.js deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/platform/features/events/test/suite.json b/platform/features/events/test/suite.json index 67076cd4cc..e796d65ebb 100644 --- a/platform/features/events/test/suite.json +++ b/platform/features/events/test/suite.json @@ -2,7 +2,6 @@ "DomainColumn", "EventListController", "EventListPopulator", - "MCTDataTable", "MessagesViewPolicy", "RangeColumn" ] \ No newline at end of file From ff8e6f40bb654c453d9ab7663cd0a02cd8297a62 Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Wed, 24 Jun 2015 11:32:13 -0700 Subject: [PATCH 19/30] [Events] More style Edited comments to clarify the sources of files. #18. --- platform/features/events/test/DomainColumnSpec.js | 2 +- platform/features/events/test/RangeColumnSpec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/features/events/test/DomainColumnSpec.js b/platform/features/events/test/DomainColumnSpec.js index 8774a20f60..c63eebc0a9 100644 --- a/platform/features/events/test/DomainColumnSpec.js +++ b/platform/features/events/test/DomainColumnSpec.js @@ -22,7 +22,7 @@ /*global define,describe,it,expect,beforeEach,waitsFor,jasmine*/ /** - * EventSpec. Created by shale on 06/23/2015. + * EventSpec. Created by vwoeltje on 11/6/14. Modified by shale on 06/23/2015. */ define( ["../src/DomainColumn"], diff --git a/platform/features/events/test/RangeColumnSpec.js b/platform/features/events/test/RangeColumnSpec.js index c69e9c6c85..204e246daf 100644 --- a/platform/features/events/test/RangeColumnSpec.js +++ b/platform/features/events/test/RangeColumnSpec.js @@ -22,7 +22,7 @@ /*global define,describe,it,expect,beforeEach,waitsFor,jasmine*/ /** - * EventSpec. Created by shale on 06/23/2015. + * EventSpec. Created by vwoeltje on 11/6/14. Modified by shale on 06/23/2015. */ define( ["../src/RangeColumn"], From 00d1728dd3e9e262320b61a6b71624b6c9a72bc5 Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Wed, 24 Jun 2015 12:07:06 -0700 Subject: [PATCH 20/30] [Events] Tweaked tests Changed some test names to be more descriptive. Moved the policy test to another folder. Blanket coverage now works. #18. --- .../features/events/test/DomainColumnSpec.js | 2 +- .../events/test/EventListPopulatorSpec.js | 2 +- .../events/test/MessagesViewPolicySpec.js | 67 ------------------- .../features/events/test/RangeColumnSpec.js | 2 +- platform/features/events/test/suite.json | 2 +- 5 files changed, 4 insertions(+), 71 deletions(-) delete mode 100644 platform/features/events/test/MessagesViewPolicySpec.js diff --git a/platform/features/events/test/DomainColumnSpec.js b/platform/features/events/test/DomainColumnSpec.js index c63eebc0a9..29c896cd5b 100644 --- a/platform/features/events/test/DomainColumnSpec.js +++ b/platform/features/events/test/DomainColumnSpec.js @@ -31,7 +31,7 @@ define( var TEST_DOMAIN_VALUE = "some formatted domain value"; - describe("A domain column", function () { + describe("An event list domain column", function () { var mockDataSet, testMetadata, mockFormatter, diff --git a/platform/features/events/test/EventListPopulatorSpec.js b/platform/features/events/test/EventListPopulatorSpec.js index b263c003a0..7937714fec 100644 --- a/platform/features/events/test/EventListPopulatorSpec.js +++ b/platform/features/events/test/EventListPopulatorSpec.js @@ -86,7 +86,7 @@ define( }); }); - it("returns rows in reverse domain order", function () { + it("returns rows in most-recent-last order", function () { var rows = populator.getRows(mockDatas, mockDomainObjects, 84), previous = Number.NEGATIVE_INFINITY; diff --git a/platform/features/events/test/MessagesViewPolicySpec.js b/platform/features/events/test/MessagesViewPolicySpec.js deleted file mode 100644 index b2bfc17e3d..0000000000 --- a/platform/features/events/test/MessagesViewPolicySpec.js +++ /dev/null @@ -1,67 +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,describe,it,expect,beforeEach,jasmine*/ - -/** - * EventSpec. Created by shale on 06/24/2015. - */ -define( - ["../src/policies/MessagesViewPolicy"], - function (MessagesViewPolicy) { - "use strict"; - - describe("The messages view policy", function () { - var mockDomainObject, - testType, - policy; - - beforeEach(function () { - mockDomainObject = jasmine.createSpyObj( - 'domainObject', - ['getModel'] - ); - mockDomainObject.getModel.andCallFake(function (c) { - return {type: testType}; - }); - - policy = new MessagesViewPolicy(); - }); - - it("disallows the message view for non Event Generators", function () { - testType = 'notAnEventGenerator'; - expect(policy.allow({ key: 'messages' }, mockDomainObject)) - .toBeFalsy(); - }); - - it("allows the message view for Event Generators", function () { - testType = 'eventGenerator'; - expect(policy.allow({ key: 'messages' }, mockDomainObject)) - .toBeTruthy(); - }); - - it("returns true when the current view is not the Messages view", function () { - expect(policy.allow({ key: 'notMessages' }, mockDomainObject)) - .toBeTruthy(); - }); - }); - } -); \ No newline at end of file diff --git a/platform/features/events/test/RangeColumnSpec.js b/platform/features/events/test/RangeColumnSpec.js index 204e246daf..99c5ceb6f4 100644 --- a/platform/features/events/test/RangeColumnSpec.js +++ b/platform/features/events/test/RangeColumnSpec.js @@ -31,7 +31,7 @@ define( var TEST_RANGE_VALUE = "some formatted range value"; - describe("A range column", function () { + describe("An event list range column", function () { var mockDataSet, testMetadata, mockFormatter, diff --git a/platform/features/events/test/suite.json b/platform/features/events/test/suite.json index e796d65ebb..44c96e9fa6 100644 --- a/platform/features/events/test/suite.json +++ b/platform/features/events/test/suite.json @@ -2,6 +2,6 @@ "DomainColumn", "EventListController", "EventListPopulator", - "MessagesViewPolicy", + "policies/MessagesViewPolicy", "RangeColumn" ] \ No newline at end of file From adc4a1b828ac0eb2daa65bea0a0b720ddaed5622 Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Wed, 24 Jun 2015 12:07:06 -0700 Subject: [PATCH 21/30] [Events] Tweaked tests Changed some test names to be more descriptive. Moved the policy test to another folder. Blanket coverage now works. #18. --- platform/features/events/test/DomainColumnSpec.js | 2 +- platform/features/events/test/EventListPopulatorSpec.js | 2 +- platform/features/events/test/RangeColumnSpec.js | 2 +- .../events/test/{ => policies}/MessagesViewPolicySpec.js | 2 +- platform/features/events/test/suite.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) rename platform/features/events/test/{ => policies}/MessagesViewPolicySpec.js (98%) diff --git a/platform/features/events/test/DomainColumnSpec.js b/platform/features/events/test/DomainColumnSpec.js index c63eebc0a9..29c896cd5b 100644 --- a/platform/features/events/test/DomainColumnSpec.js +++ b/platform/features/events/test/DomainColumnSpec.js @@ -31,7 +31,7 @@ define( var TEST_DOMAIN_VALUE = "some formatted domain value"; - describe("A domain column", function () { + describe("An event list domain column", function () { var mockDataSet, testMetadata, mockFormatter, diff --git a/platform/features/events/test/EventListPopulatorSpec.js b/platform/features/events/test/EventListPopulatorSpec.js index b263c003a0..7937714fec 100644 --- a/platform/features/events/test/EventListPopulatorSpec.js +++ b/platform/features/events/test/EventListPopulatorSpec.js @@ -86,7 +86,7 @@ define( }); }); - it("returns rows in reverse domain order", function () { + it("returns rows in most-recent-last order", function () { var rows = populator.getRows(mockDatas, mockDomainObjects, 84), previous = Number.NEGATIVE_INFINITY; diff --git a/platform/features/events/test/RangeColumnSpec.js b/platform/features/events/test/RangeColumnSpec.js index 204e246daf..99c5ceb6f4 100644 --- a/platform/features/events/test/RangeColumnSpec.js +++ b/platform/features/events/test/RangeColumnSpec.js @@ -31,7 +31,7 @@ define( var TEST_RANGE_VALUE = "some formatted range value"; - describe("A range column", function () { + describe("An event list range column", function () { var mockDataSet, testMetadata, mockFormatter, diff --git a/platform/features/events/test/MessagesViewPolicySpec.js b/platform/features/events/test/policies/MessagesViewPolicySpec.js similarity index 98% rename from platform/features/events/test/MessagesViewPolicySpec.js rename to platform/features/events/test/policies/MessagesViewPolicySpec.js index b2bfc17e3d..0c26b8f249 100644 --- a/platform/features/events/test/MessagesViewPolicySpec.js +++ b/platform/features/events/test/policies/MessagesViewPolicySpec.js @@ -25,7 +25,7 @@ * EventSpec. Created by shale on 06/24/2015. */ define( - ["../src/policies/MessagesViewPolicy"], + ["../../src/policies/MessagesViewPolicy"], function (MessagesViewPolicy) { "use strict"; diff --git a/platform/features/events/test/suite.json b/platform/features/events/test/suite.json index e796d65ebb..44c96e9fa6 100644 --- a/platform/features/events/test/suite.json +++ b/platform/features/events/test/suite.json @@ -2,6 +2,6 @@ "DomainColumn", "EventListController", "EventListPopulator", - "MessagesViewPolicy", + "policies/MessagesViewPolicy", "RangeColumn" ] \ No newline at end of file From 10e47e6f4842e96599a1bfb4c9e7e23d52b8fe41 Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Wed, 24 Jun 2015 13:14:19 -0700 Subject: [PATCH 22/30] [Events] Fixed comments Fixed comments to refer to event lists correctly. #18. --- platform/features/events/src/EventListController.js | 2 +- platform/features/events/src/EventListPopulator.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/features/events/src/EventListController.js b/platform/features/events/src/EventListController.js index 887fa52a4a..8f8ca6c60a 100644 --- a/platform/features/events/src/EventListController.js +++ b/platform/features/events/src/EventListController.js @@ -35,7 +35,7 @@ define( /** * The EventListController is responsible for populating - * the contents of the scrolling list view. + * the contents of the event list view. * @constructor */ function EventListController($scope, formatter) { diff --git a/platform/features/events/src/EventListPopulator.js b/platform/features/events/src/EventListPopulator.js index b128a91706..3999fb1ebc 100644 --- a/platform/features/events/src/EventListPopulator.js +++ b/platform/features/events/src/EventListPopulator.js @@ -28,7 +28,7 @@ define( /** * The EventListPopulator is responsible for filling in the - * values which should appear within columns of a scrolling list + * values which should appear within columns of a event list * view, based on received telemetry data. * @constructor * @param {Column[]} columns the columns to be populated @@ -124,7 +124,7 @@ define( }); }, /** - * Get the contents of rows for the scrolling list view. + * Get the contents of rows for the event list view. * @param {TelemetrySeries[]} datas the data sets * @param {DomainObject[]} objects the domain objects which * provided the data sets; these should match From fd81c5c859ece11c982a887e912043552cc007a3 Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Wed, 24 Jun 2015 15:19:47 -0700 Subject: [PATCH 23/30] [Events] No Period No longer asks for a period when creating a new Event Message Generator. #18. --- example/eventGenerator/bundle.json | 17 ++--------------- example/eventGenerator/src/EventTelemetry.js | 2 +- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/example/eventGenerator/bundle.json b/example/eventGenerator/bundle.json index 83b52b91ac..b2ede6893b 100644 --- a/example/eventGenerator/bundle.json +++ b/example/eventGenerator/bundle.json @@ -18,27 +18,14 @@ "description": "An event message generator", "features": "creation", "model": { - "telemetry": { - "period": 10 - } + "telemetry": {} }, "telemetry": { "source": "eventGenerator", "ranges": [ { "format": "string" } ] - }, - "properties": [ - { - "name": "Period", - "control": "textfield", - "cssclass": "l-small l-numeric", - "key": "period", - "required": true, - "property": [ "telemetry", "period" ], - "pattern": "^\\d*(\\.\\d*)?$" - } - ] + } } ] } diff --git a/example/eventGenerator/src/EventTelemetry.js b/example/eventGenerator/src/EventTelemetry.js index 504f8fbec5..38afebb7b7 100644 --- a/example/eventGenerator/src/EventTelemetry.js +++ b/example/eventGenerator/src/EventTelemetry.js @@ -19,7 +19,7 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ -/*global define,Promise*/ +/*global define */ /** * Module defining EventTelemetry. From 203de023d2bb24841f63f07831b1ddc6a4d66833 Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Wed, 24 Jun 2015 17:05:14 -0700 Subject: [PATCH 24/30] [Events] More general view policy The Messages view policy now will allow any object that has a telemetry type of string to have access to the Messages view, not just Event List Generators. (The test for this still does not work though.) #18. --- .../events/src/policies/MessagesViewPolicy.js | 16 ++++++++++++---- .../test/policies/MessagesViewPolicySpec.js | 11 ++++++----- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/platform/features/events/src/policies/MessagesViewPolicy.js b/platform/features/events/src/policies/MessagesViewPolicy.js index b31ca94374..4426872b1e 100644 --- a/platform/features/events/src/policies/MessagesViewPolicy.js +++ b/platform/features/events/src/policies/MessagesViewPolicy.js @@ -35,6 +35,16 @@ define( */ function MessagesViewPolicy() { + function hasStringTelemetry(domainObject) { + var telemetry = domainObject && + domainObject.getCapability('telemetry'), + metadata = telemetry ? telemetry.getMetadata() : {}, + ranges = metadata.ranges || []; + + return ranges.some(function (range) { + return range.format === 'string'; + }); + } return { /** * Check whether or not a given action is allowed by this @@ -47,12 +57,10 @@ define( // This policy only applies for the Messages view if (view.key === 'messages') { // The Messages view is allowed only if the domain - // object is a Event Message Generator - if (domainObject.getModel().type !== 'eventGenerator') { + // object has string telemetry + if (!hasStringTelemetry(domainObject)) { return false; } - - // TODO: This may later apply to more types beyond just eventGenerator. } // Like all policies, allow by default. diff --git a/platform/features/events/test/policies/MessagesViewPolicySpec.js b/platform/features/events/test/policies/MessagesViewPolicySpec.js index 0c26b8f249..6e3430f64e 100644 --- a/platform/features/events/test/policies/MessagesViewPolicySpec.js +++ b/platform/features/events/test/policies/MessagesViewPolicySpec.js @@ -32,6 +32,7 @@ define( describe("The messages view policy", function () { var mockDomainObject, testType, + telemetryType, policy; beforeEach(function () { @@ -42,18 +43,18 @@ define( mockDomainObject.getModel.andCallFake(function (c) { return {type: testType}; }); - + policy = new MessagesViewPolicy(); }); - it("disallows the message view for non Event Generators", function () { - testType = 'notAnEventGenerator'; + it("disallows the message view for objects without string telemetry", function () { + telemetryType = 'notString'; expect(policy.allow({ key: 'messages' }, mockDomainObject)) .toBeFalsy(); }); - it("allows the message view for Event Generators", function () { - testType = 'eventGenerator'; + it("allows the message view for objects with string telemetry", function () { + telemetryType = 'string'; expect(policy.allow({ key: 'messages' }, mockDomainObject)) .toBeTruthy(); }); From d2fe71d82bc078adc624fe4e88de5a16de28f9bf Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Wed, 24 Jun 2015 17:08:03 -0700 Subject: [PATCH 25/30] [Events] Fixed tabs Removed tabs from EventListController and replaced with spaces. #18. --- .../events/src/EventListController.js | 170 +++++++++--------- 1 file changed, 85 insertions(+), 85 deletions(-) diff --git a/platform/features/events/src/EventListController.js b/platform/features/events/src/EventListController.js index 8f8ca6c60a..4b90c91b8e 100644 --- a/platform/features/events/src/EventListController.js +++ b/platform/features/events/src/EventListController.js @@ -27,107 +27,107 @@ * Modified by shale on 06/23/2015. */ define( - ["./DomainColumn", "./RangeColumn", "./EventListPopulator"], - function (DomainColumn, RangeColumn, EventListPopulator) { - "use strict"; + ["./DomainColumn", "./RangeColumn", "./EventListPopulator"], + function (DomainColumn, RangeColumn, EventListPopulator) { + "use strict"; - var ROW_COUNT = 100; + var ROW_COUNT = 100; - /** - * The EventListController is responsible for populating - * the contents of the event list view. - * @constructor - */ - function EventListController($scope, formatter) { - var populator; + /** + * The EventListController is responsible for populating + * the contents of the event list view. + * @constructor + */ + function EventListController($scope, formatter) { + var populator; - // Get a set of populated, ready-to-display rows for the - // latest data values. - function getRows(telemetry) { - var datas = telemetry.getResponse(), - objects = telemetry.getTelemetryObjects(); + // Get a set of populated, ready-to-display rows for the + // latest data values. + function getRows(telemetry) { + var datas = telemetry.getResponse(), + objects = telemetry.getTelemetryObjects(); - return populator.getRows(datas, objects, ROW_COUNT); - } + return populator.getRows(datas, objects, ROW_COUNT); + } - // Update the contents - function updateRows() { - var telemetry = $scope.telemetry; - $scope.rows = telemetry ? getRows(telemetry) : []; - } + // Update the contents + function updateRows() { + var telemetry = $scope.telemetry; + $scope.rows = telemetry ? getRows(telemetry) : []; + } - // Set up columns based on telemetry metadata. This will - // include one column for each domain and range type, as - // well as a column for the domain object name. - function setupColumns(telemetry) { - var domainKeys = {}, - rangeKeys = {}, - columns = [], - metadata; + // Set up columns based on telemetry metadata. This will + // include one column for each domain and range type, as + // well as a column for the domain object name. + function setupColumns(telemetry) { + var domainKeys = {}, + rangeKeys = {}, + columns = [], + metadata; - // Add a domain to the set of columns, if a domain - // with the same key has not yet been inclued. - function addDomain(domain) { - var key = domain.key; - if (key && !domainKeys[key]) { - domainKeys[key] = true; - columns.push(new DomainColumn(domain, formatter)); - } - } + // Add a domain to the set of columns, if a domain + // with the same key has not yet been inclued. + function addDomain(domain) { + var key = domain.key; + if (key && !domainKeys[key]) { + domainKeys[key] = true; + columns.push(new DomainColumn(domain, formatter)); + } + } // Add a range col to the set of columns, if a range - // with the same key has not yet been included. - function addRange(range) { - var key = range.key; - if (key && !rangeKeys[key]) { - rangeKeys[key] = true; - columns.push(new RangeColumn(range, formatter)); - } - } + // with the same key has not yet been included. + function addRange(range) { + var key = range.key; + if (key && !rangeKeys[key]) { + rangeKeys[key] = true; + columns.push(new RangeColumn(range, formatter)); + } + } - // We cannot proceed if the telemetry controller - // is not available; clear all rows/columns. - if (!telemetry) { - columns = []; - $scope.rows = []; - $scope.headers = []; - return; - } + // We cannot proceed if the telemetry controller + // is not available; clear all rows/columns. + if (!telemetry) { + columns = []; + $scope.rows = []; + $scope.headers = []; + return; + } - // Add domain, range, event msg columns - metadata = telemetry.getMetadata(); - (metadata || []).forEach(function (metadata) { - (metadata.domains || []).forEach(addDomain); - }); - (metadata || []).forEach(function (metadata) { - (metadata.ranges || []).forEach(addRange); - }); + // Add domain, range, event msg columns + metadata = telemetry.getMetadata(); + (metadata || []).forEach(function (metadata) { + (metadata.domains || []).forEach(addDomain); + }); + (metadata || []).forEach(function (metadata) { + (metadata.ranges || []).forEach(addRange); + }); // Add default domain and range columns if none - // were described in metadata. - if (Object.keys(domainKeys).length < 1) { - columns.push(new DomainColumn({name: "Time"}, formatter)); - } - if (Object.keys(rangeKeys).length < 1) { - columns.push(new RangeColumn({name: "Message"}, formatter)); - } + // were described in metadata. + if (Object.keys(domainKeys).length < 1) { + columns.push(new DomainColumn({name: "Time"}, formatter)); + } + if (Object.keys(rangeKeys).length < 1) { + columns.push(new RangeColumn({name: "Message"}, formatter)); + } - // We have all columns now; use them to initializer - // the populator, which will use them to generate - // actual rows and headers. - populator = new EventListPopulator(columns); + // We have all columns now; use them to initializer + // the populator, which will use them to generate + // actual rows and headers. + populator = new EventListPopulator(columns); - // Initialize headers - $scope.headers = populator.getHeaders(); + // Initialize headers + $scope.headers = populator.getHeaders(); - // Fill in the contents of the rows. - updateRows(); - } + // Fill in the contents of the rows. + updateRows(); + } - $scope.$on("telemetryUpdate", updateRows); - $scope.$watch("telemetry", setupColumns); - } + $scope.$on("telemetryUpdate", updateRows); + $scope.$watch("telemetry", setupColumns); + } - return EventListController; - } + return EventListController; + } ); From f6298c162c4a395f47ea06095266a2f694a3fdf8 Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Thu, 25 Jun 2015 09:27:24 -0700 Subject: [PATCH 26/30] [Events] Real-time telemetry version Creating an additional event list which can handle real time data, not historical data. #18. --- platform/features/rtevents/bundle.json | 37 +++++ .../res/templates/mct-data-table.html | 37 +++++ .../rtevents/res/templates/messages.html | 29 ++++ .../features/rtevents/src/DomainColumn.js | 67 +++++++++ .../rtevents/src/RTEventListController.js | 139 ++++++++++++++++++ platform/features/rtevents/src/RangeColumn.js | 67 +++++++++ .../rtevents/src/directives/MCTDataTable.js | 74 ++++++++++ .../src/policies/MessagesViewPolicy.js | 74 ++++++++++ .../rtevents/test/DomainColumnSpec.js | 84 +++++++++++ .../test/RTEventListControllerSpec.js | 110 ++++++++++++++ .../features/rtevents/test/RangeColumnSpec.js | 81 ++++++++++ .../test/policies/MessagesViewPolicySpec.js | 68 +++++++++ platform/features/rtevents/test/suite.json | 7 + 13 files changed, 874 insertions(+) create mode 100644 platform/features/rtevents/bundle.json create mode 100644 platform/features/rtevents/res/templates/mct-data-table.html create mode 100644 platform/features/rtevents/res/templates/messages.html create mode 100644 platform/features/rtevents/src/DomainColumn.js create mode 100644 platform/features/rtevents/src/RTEventListController.js create mode 100644 platform/features/rtevents/src/RangeColumn.js create mode 100644 platform/features/rtevents/src/directives/MCTDataTable.js create mode 100644 platform/features/rtevents/src/policies/MessagesViewPolicy.js create mode 100644 platform/features/rtevents/test/DomainColumnSpec.js create mode 100644 platform/features/rtevents/test/RTEventListControllerSpec.js create mode 100644 platform/features/rtevents/test/RangeColumnSpec.js create mode 100644 platform/features/rtevents/test/policies/MessagesViewPolicySpec.js create mode 100644 platform/features/rtevents/test/suite.json diff --git a/platform/features/rtevents/bundle.json b/platform/features/rtevents/bundle.json new file mode 100644 index 0000000000..04400d8223 --- /dev/null +++ b/platform/features/rtevents/bundle.json @@ -0,0 +1,37 @@ +{ + "name": "Event Messages", + "description": "List of time-ordered event messages", + "extensions": { + "views": [ + { + "key": "messages", + "name": "RT Messages", + "glyph": "5", + "description": "Scrolling list of messages.", + "templateUrl": "templates/messages.html", + "needs": [ "telemetry" ], + "delegation": true + } + ], + "controllers": [ + { + "key": "RTEventListController", + "implementation": "RTEventListController.js", + "depends": [ "$scope", "telemetryHandler", "telemetryFormatter" ] + } + ], + "directives": [ + { + "key": "mctDataTable", + "implementation": "directives/MCTDataTable.js", + "depends": [ "$window" ] + } + ], + "policies": [ + { + "category": "view", + "implementation": "policies/MessagesViewPolicy.js" + } + ] + } +} diff --git a/platform/features/rtevents/res/templates/mct-data-table.html b/platform/features/rtevents/res/templates/mct-data-table.html new file mode 100644 index 0000000000..5b8dd786bc --- /dev/null +++ b/platform/features/rtevents/res/templates/mct-data-table.html @@ -0,0 +1,37 @@ + + + + + + + + + + + + +
+ {{header}} +
+ {{cell}} +
\ No newline at end of file diff --git a/platform/features/rtevents/res/templates/messages.html b/platform/features/rtevents/res/templates/messages.html new file mode 100644 index 0000000000..82db5d0f9c --- /dev/null +++ b/platform/features/rtevents/res/templates/messages.html @@ -0,0 +1,29 @@ + +
+
+ +
+
+ + diff --git a/platform/features/rtevents/src/DomainColumn.js b/platform/features/rtevents/src/DomainColumn.js new file mode 100644 index 0000000000..95a6222553 --- /dev/null +++ b/platform/features/rtevents/src/DomainColumn.js @@ -0,0 +1,67 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,moment*/ + +/** + * Module defining DomainColumn. Created by vwoeltje on 11/18/14. + */ +define( + [], + function () { + "use strict"; + + /** + * A column which will report telemetry domain values + * (typically, timestamps.) Used by the ScrollingListController. + * + * @constructor + * @param domainMetadata an object with the machine- and human- + * readable names for this domain (in `key` and `name` + * fields, respectively.) + * @param {TelemetryFormatter} telemetryFormatter the telemetry + * formatting service, for making values human-readable. + */ + function DomainColumn(domainMetadata, telemetryFormatter) { + return { + /** + * Get the title to display in this column's header. + * @returns {string} the title to display + */ + getTitle: function () { + return domainMetadata.name; + }, + /** + * Get the text to display inside a row under this + * column. + * @returns {string} the text to display + */ + getValue: function (domainObject, data, index) { + return telemetryFormatter.formatDomainValue( + data.getDomainValue(index, domainMetadata.key) + ); + } + }; + } + + return DomainColumn; + } +); \ No newline at end of file diff --git a/platform/features/rtevents/src/RTEventListController.js b/platform/features/rtevents/src/RTEventListController.js new file mode 100644 index 0000000000..1c77802a4b --- /dev/null +++ b/platform/features/rtevents/src/RTEventListController.js @@ -0,0 +1,139 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define*/ + +/** + * Module defining RTEventListController. + * Created by shale on 06/25/2014. Based on RT Scrolling lists. + */ +define( + ["./DomainColumn", "./RangeColumn"], + function (DomainColumn, RangeColumn) { + "use strict"; + + var ROW_COUNT = 100; + + /** + * The RTScrollingListController is responsible for populating + * the contents of the scrolling list view. + * @constructor + */ + function RTEventListController($scope, telemetryHandler, telemetryFormatter) { + var handle, + lastUpdated = {}, + lastIds = [], + columns = [], + headers = [], + rows = []; + + function getTelemetryObjects() { + return handle ? handle.getTelemetryObjects() : []; + } + + function idsChanged(telemetryObjects) { + function mismatch(id, index) { + return id !== telemetryObjects[index].getId(); + } + + return lastIds.length !== telemetryObjects.length || + lastIds.some(mismatch); + } + + function setupColumns(telemetryObjects) { + var id = $scope.domainObject && $scope.domainObject.getId(), + firstId = + telemetryObjects[0] && telemetryObjects[0].getId(); + + columns = []; + + if (telemetryObjects > 1 || id !== firstId) { + columns.push(new NameColumn()); + } + columns.push(new DomainColumn(telemetryFormatter)); + columns.push(new RangeColumn()); + + headers = columns.map(function (column) { + return column.getTitle(); + }); + } + + function updateObjects(telemetryObjects) { + if (idsChanged(telemetryObjects)) { + setupColumns(telemetryObjects); + lastIds = telemetryObjects.map(function (telemetryObject) { + return telemetryObject.getId(); + }); + } + } + + function addRow(telemetryObject) { + var id = telemetryObject.getId(), + domainValue = handle.getDomainValue(telemetryObject); + if (lastUpdated[id] !== domainValue && + domainValue !== undefined) { + // Instead of unshift (scrolling), use push (messages) + rows.push(columns.map(function (column) { + return column.getValue(telemetryObject, handle); + })); + rows.splice(ROW_COUNT, Number.MAX_VALUE); + lastUpdated[id] = domainValue; + } + } + + function updateValues() { + getTelemetryObjects().forEach(addRow); + } + + function releaseSubscription() { + if (handle) { + handle.unsubscribe(); + } + } + + function makeSubscription(domainObject) { + releaseSubscription(); + rows = []; + handle = telemetryHandler.handle( + domainObject, + updateValues, + true + ); + } + + $scope.$on("$destroy", releaseSubscription); + + $scope.$watch("domainObject", makeSubscription); + $scope.$watch(getTelemetryObjects, updateObjects); + + return { + rows: function () { + return rows; + }, + headers: function () { + return headers; + } + }; + } + + return RTScrollingListController; + } +); diff --git a/platform/features/rtevents/src/RangeColumn.js b/platform/features/rtevents/src/RangeColumn.js new file mode 100644 index 0000000000..2b11de43c7 --- /dev/null +++ b/platform/features/rtevents/src/RangeColumn.js @@ -0,0 +1,67 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,Promise*/ + +/** + * Module defining DomainColumn. Created by vwoeltje on 11/18/14. + */ +define( + [], + function () { + "use strict"; + + /** + * A column which will report telemetry range values + * (typically, measurements.) Used by the ScrollingListController. + * + * @constructor + * @param rangeMetadata an object with the machine- and human- + * readable names for this range (in `key` and `name` + * fields, respectively.) + * @param {TelemetryFormatter} telemetryFormatter the telemetry + * formatting service, for making values human-readable. + */ + function RangeColumn(rangeMetadata, telemetryFormatter) { + return { + /** + * Get the title to display in this column's header. + * @returns {string} the title to display + */ + getTitle: function () { + return rangeMetadata.name; + }, + /** + * Get the text to display inside a row under this + * column. + * @returns {string} the text to display + */ + getValue: function (domainObject, data, index) { + return telemetryFormatter.formatRangeValue( + data.getRangeValue(index, rangeMetadata.key) + ); + } + }; + } + + return RangeColumn; + } +); \ No newline at end of file diff --git a/platform/features/rtevents/src/directives/MCTDataTable.js b/platform/features/rtevents/src/directives/MCTDataTable.js new file mode 100644 index 0000000000..c4cb9970e6 --- /dev/null +++ b/platform/features/rtevents/src/directives/MCTDataTable.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,Promise*/ + +/** + * Module defining MCTDataTable. Created by shale on 06/22/2015. + */ +define( + [], + function () { + "use strict"; + + function MCTDataTable($window) { + return { + restrict: "E", + templateUrl: "platform/features/events/res/templates/mct-data-table.html", + scope: { + headers: "=", + rows: "=", + ascendingScroll: "=" + }, + link: function ($scope, $element) { + var currentHeight, + previousHeight, + scrollParent; + + // If the scroll is set to ascending, we want to + // check when elements are added to the table, and move the scroll + // bar accordingly. + // (When viewing at the bottom of the page, the scroll bar will + // stay at the bottom despite additions to the table) + if ($scope.ascendingScroll) { + $scope.$watch("rows", function () { + // Wait until the page as been repainted (otherwise the + // height will always be zero) + $window.requestAnimationFrame(function () { + previousHeight = currentHeight; + // The height of the table body + currentHeight = $element[0].firstElementChild.firstElementChild.nextElementSibling.clientHeight; + + // One of the parents is a div that has vscroll + scrollParent = $element[0].parentElement.parentElement.parentElement.parentElement.parentElement; + + // Move the scrollbar down the amount that the height has changed + scrollParent.scrollTop = scrollParent.scrollTop + (currentHeight - previousHeight); + }); + }); + } + } + }; + } + + return MCTDataTable; + } +); \ No newline at end of file diff --git a/platform/features/rtevents/src/policies/MessagesViewPolicy.js b/platform/features/rtevents/src/policies/MessagesViewPolicy.js new file mode 100644 index 0000000000..4426872b1e --- /dev/null +++ b/platform/features/rtevents/src/policies/MessagesViewPolicy.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*/ + +/** + * Module defining MessagesViewPolicy. Created by shale on 06/24/2015. + */ +define( + [], + function () { + "use strict"; + + /** + * Policy controlling when the Messages view should be avaliable. + * @constructor + */ + function MessagesViewPolicy() { + + function hasStringTelemetry(domainObject) { + var telemetry = domainObject && + domainObject.getCapability('telemetry'), + metadata = telemetry ? telemetry.getMetadata() : {}, + ranges = metadata.ranges || []; + + return ranges.some(function (range) { + return range.format === 'string'; + }); + } + return { + /** + * Check whether or not a given action is allowed by this + * policy. + * @param {Action} action the action + * @param domainObject the domain object which will be viewed + * @returns {boolean} true if not disallowed + */ + allow: function (view, domainObject) { + // This policy only applies for the Messages view + if (view.key === 'messages') { + // The Messages view is allowed only if the domain + // object has string telemetry + if (!hasStringTelemetry(domainObject)) { + return false; + } + } + + // Like all policies, allow by default. + return true; + } + }; + } + + return MessagesViewPolicy; + } +); \ No newline at end of file diff --git a/platform/features/rtevents/test/DomainColumnSpec.js b/platform/features/rtevents/test/DomainColumnSpec.js new file mode 100644 index 0000000000..29c896cd5b --- /dev/null +++ b/platform/features/rtevents/test/DomainColumnSpec.js @@ -0,0 +1,84 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,describe,it,expect,beforeEach,waitsFor,jasmine*/ + +/** + * EventSpec. Created by vwoeltje on 11/6/14. Modified by shale on 06/23/2015. + */ +define( + ["../src/DomainColumn"], + function (DomainColumn) { + "use strict"; + + var TEST_DOMAIN_VALUE = "some formatted domain value"; + + describe("An event list domain column", function () { + var mockDataSet, + testMetadata, + mockFormatter, + column; + + beforeEach(function () { + mockDataSet = jasmine.createSpyObj( + "data", + [ "getDomainValue" ] + ); + mockFormatter = jasmine.createSpyObj( + "formatter", + [ "formatDomainValue", "formatRangeValue" ] + ); + testMetadata = { + key: "testKey", + name: "Test Name" + }; + mockFormatter.formatDomainValue.andReturn(TEST_DOMAIN_VALUE); + + column = new DomainColumn(testMetadata, mockFormatter); + }); + + it("reports a column header from domain metadata", function () { + expect(column.getTitle()).toEqual("Test Name"); + }); + + it("looks up data from a data set", function () { + column.getValue(undefined, mockDataSet, 42); + expect(mockDataSet.getDomainValue) + .toHaveBeenCalledWith(42, "testKey"); + }); + + it("formats domain values as time", function () { + mockDataSet.getDomainValue.andReturn(402513731000); + + // Should have just given the value the formatter gave + expect(column.getValue(undefined, mockDataSet, 42)) + .toEqual(TEST_DOMAIN_VALUE); + + // Make sure that service interactions were as expected + expect(mockFormatter.formatDomainValue) + .toHaveBeenCalledWith(402513731000); + expect(mockFormatter.formatRangeValue) + .not.toHaveBeenCalled(); + }); + + }); + } +); \ No newline at end of file diff --git a/platform/features/rtevents/test/RTEventListControllerSpec.js b/platform/features/rtevents/test/RTEventListControllerSpec.js new file mode 100644 index 0000000000..63a762e4d4 --- /dev/null +++ b/platform/features/rtevents/test/RTEventListControllerSpec.js @@ -0,0 +1,110 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,describe,it,expect,beforeEach,waitsFor,jasmine*/ + +/** + * EventSpec. Created by shale on 06/24/2015. + */ +define( + ["../src/EventListController"], + function (EventListController) { + "use strict"; + + describe("The event list controller", function () { + var mockScope, + mockTelemetry, + testMetadata, + controller; + + beforeEach(function () { + mockScope = jasmine.createSpyObj( + "$scope", + [ "$on", "$watch" ] + ); + mockTelemetry = jasmine.createSpyObj( + "telemetryController", + [ "getResponse", "getMetadata", "getTelemetryObjects" ] + ); + testMetadata = [ + { + domains: [ + { key: "d0", name: "D0" }, + { key: "d1", name: "D1" } + ], + ranges: [ + { key: "r0", name: "R0" }, + { key: "r1", name: "R1" } + ] + }, + { + domains: [ + { key: "d0", name: "D0" }, + { key: "d2", name: "D2" } + ], + ranges: [ + { key: "r0", name: "R0" } + ] + } + ]; + mockTelemetry.getMetadata.andReturn(testMetadata); + mockTelemetry.getResponse.andReturn([]); + mockTelemetry.getTelemetryObjects.andReturn([]); + mockScope.telemetry = mockTelemetry; + controller = new EventListController(mockScope); + }); + + it("listens for telemetry data updates", function () { + expect(mockScope.$on).toHaveBeenCalledWith( + "telemetryUpdate", + jasmine.any(Function) + ); + }); + + it("watches for telemetry controller changes", function () { + expect(mockScope.$watch).toHaveBeenCalledWith( + "telemetry", + jasmine.any(Function) + ); + }); + + it("provides a column for each unique domain and range", function () { + // Should have five columns based on metadata above, + // (d0, d1, d2, r0, r1) + mockScope.$watch.mostRecentCall.args[1](mockTelemetry); + expect(mockScope.headers).toEqual(["D0", "D1", "D2", "R0", "R1"]); + }); + + it("does not throw if telemetry controller is undefined", function () { + // Just a general robustness check + mockScope.telemetry = undefined; + expect(mockScope.$watch.mostRecentCall.args[1]) + .not.toThrow(); + }); + + it("provides default columns if domain/range metadata is unavailable", function () { + mockTelemetry.getMetadata.andReturn([]); + mockScope.$watch.mostRecentCall.args[1](mockTelemetry); + expect(mockScope.headers).toEqual(["Time", "Message"]); + }); + }); + } +); \ No newline at end of file diff --git a/platform/features/rtevents/test/RangeColumnSpec.js b/platform/features/rtevents/test/RangeColumnSpec.js new file mode 100644 index 0000000000..99c5ceb6f4 --- /dev/null +++ b/platform/features/rtevents/test/RangeColumnSpec.js @@ -0,0 +1,81 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,describe,it,expect,beforeEach,waitsFor,jasmine*/ + +/** + * EventSpec. Created by vwoeltje on 11/6/14. Modified by shale on 06/23/2015. + */ +define( + ["../src/RangeColumn"], + function (RangeColumn) { + "use strict"; + + var TEST_RANGE_VALUE = "some formatted range value"; + + describe("An event list range column", function () { + var mockDataSet, + testMetadata, + mockFormatter, + column; + + beforeEach(function () { + mockDataSet = jasmine.createSpyObj( + "data", + [ "getRangeValue" ] + ); + mockFormatter = jasmine.createSpyObj( + "formatter", + [ "formatDomainValue", "formatRangeValue" ] + ); + testMetadata = { + key: "testKey", + name: "Test Name" + }; + mockFormatter.formatRangeValue.andReturn(TEST_RANGE_VALUE); + + column = new RangeColumn(testMetadata, mockFormatter); + }); + + it("reports a column header from range metadata", function () { + expect(column.getTitle()).toEqual("Test Name"); + }); + + it("looks up data from a data set", function () { + column.getValue(undefined, mockDataSet, 42); + expect(mockDataSet.getRangeValue) + .toHaveBeenCalledWith(42, "testKey"); + }); + + it("formats range values as time", function () { + mockDataSet.getRangeValue.andReturn(123.45678); + expect(column.getValue(undefined, mockDataSet, 42)) + .toEqual(TEST_RANGE_VALUE); + + // Make sure that service interactions were as expected + expect(mockFormatter.formatRangeValue) + .toHaveBeenCalledWith(123.45678); + expect(mockFormatter.formatDomainValue) + .not.toHaveBeenCalled(); + }); + }); + } +); \ No newline at end of file diff --git a/platform/features/rtevents/test/policies/MessagesViewPolicySpec.js b/platform/features/rtevents/test/policies/MessagesViewPolicySpec.js new file mode 100644 index 0000000000..6e3430f64e --- /dev/null +++ b/platform/features/rtevents/test/policies/MessagesViewPolicySpec.js @@ -0,0 +1,68 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,describe,it,expect,beforeEach,jasmine*/ + +/** + * EventSpec. Created by shale on 06/24/2015. + */ +define( + ["../../src/policies/MessagesViewPolicy"], + function (MessagesViewPolicy) { + "use strict"; + + describe("The messages view policy", function () { + var mockDomainObject, + testType, + telemetryType, + policy; + + beforeEach(function () { + mockDomainObject = jasmine.createSpyObj( + 'domainObject', + ['getModel'] + ); + mockDomainObject.getModel.andCallFake(function (c) { + return {type: testType}; + }); + + policy = new MessagesViewPolicy(); + }); + + it("disallows the message view for objects without string telemetry", function () { + telemetryType = 'notString'; + expect(policy.allow({ key: 'messages' }, mockDomainObject)) + .toBeFalsy(); + }); + + it("allows the message view for objects with string telemetry", function () { + telemetryType = 'string'; + expect(policy.allow({ key: 'messages' }, mockDomainObject)) + .toBeTruthy(); + }); + + it("returns true when the current view is not the Messages view", function () { + expect(policy.allow({ key: 'notMessages' }, mockDomainObject)) + .toBeTruthy(); + }); + }); + } +); \ No newline at end of file diff --git a/platform/features/rtevents/test/suite.json b/platform/features/rtevents/test/suite.json new file mode 100644 index 0000000000..44c96e9fa6 --- /dev/null +++ b/platform/features/rtevents/test/suite.json @@ -0,0 +1,7 @@ +[ + "DomainColumn", + "EventListController", + "EventListPopulator", + "policies/MessagesViewPolicy", + "RangeColumn" +] \ No newline at end of file From 163b210fbb61ac09b4998327de4f11e00e3fb66d Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Thu, 25 Jun 2015 09:27:24 -0700 Subject: [PATCH 27/30] [Events] Real-time telemetry version Creating an additional event list which can handle real time data, not historical data. #18. --- platform/features/rtevents/bundle.json | 37 +++++ .../res/templates/mct-data-table.html | 37 +++++ .../rtevents/res/templates/messages.html | 29 ++++ .../features/rtevents/src/DomainColumn.js | 67 +++++++++ .../rtevents/src/RTEventListController.js | 139 ++++++++++++++++++ platform/features/rtevents/src/RangeColumn.js | 67 +++++++++ .../rtevents/src/directives/MCTDataTable.js | 74 ++++++++++ .../src/policies/MessagesViewPolicy.js | 74 ++++++++++ .../rtevents/test/DomainColumnSpec.js | 84 +++++++++++ .../test/RTEventListControllerSpec.js | 110 ++++++++++++++ .../features/rtevents/test/RangeColumnSpec.js | 81 ++++++++++ .../test/policies/MessagesViewPolicySpec.js | 68 +++++++++ platform/features/rtevents/test/suite.json | 6 + 13 files changed, 873 insertions(+) create mode 100644 platform/features/rtevents/bundle.json create mode 100644 platform/features/rtevents/res/templates/mct-data-table.html create mode 100644 platform/features/rtevents/res/templates/messages.html create mode 100644 platform/features/rtevents/src/DomainColumn.js create mode 100644 platform/features/rtevents/src/RTEventListController.js create mode 100644 platform/features/rtevents/src/RangeColumn.js create mode 100644 platform/features/rtevents/src/directives/MCTDataTable.js create mode 100644 platform/features/rtevents/src/policies/MessagesViewPolicy.js create mode 100644 platform/features/rtevents/test/DomainColumnSpec.js create mode 100644 platform/features/rtevents/test/RTEventListControllerSpec.js create mode 100644 platform/features/rtevents/test/RangeColumnSpec.js create mode 100644 platform/features/rtevents/test/policies/MessagesViewPolicySpec.js create mode 100644 platform/features/rtevents/test/suite.json diff --git a/platform/features/rtevents/bundle.json b/platform/features/rtevents/bundle.json new file mode 100644 index 0000000000..04400d8223 --- /dev/null +++ b/platform/features/rtevents/bundle.json @@ -0,0 +1,37 @@ +{ + "name": "Event Messages", + "description": "List of time-ordered event messages", + "extensions": { + "views": [ + { + "key": "messages", + "name": "RT Messages", + "glyph": "5", + "description": "Scrolling list of messages.", + "templateUrl": "templates/messages.html", + "needs": [ "telemetry" ], + "delegation": true + } + ], + "controllers": [ + { + "key": "RTEventListController", + "implementation": "RTEventListController.js", + "depends": [ "$scope", "telemetryHandler", "telemetryFormatter" ] + } + ], + "directives": [ + { + "key": "mctDataTable", + "implementation": "directives/MCTDataTable.js", + "depends": [ "$window" ] + } + ], + "policies": [ + { + "category": "view", + "implementation": "policies/MessagesViewPolicy.js" + } + ] + } +} diff --git a/platform/features/rtevents/res/templates/mct-data-table.html b/platform/features/rtevents/res/templates/mct-data-table.html new file mode 100644 index 0000000000..5b8dd786bc --- /dev/null +++ b/platform/features/rtevents/res/templates/mct-data-table.html @@ -0,0 +1,37 @@ + + + + + + + + + + + + +
+ {{header}} +
+ {{cell}} +
\ No newline at end of file diff --git a/platform/features/rtevents/res/templates/messages.html b/platform/features/rtevents/res/templates/messages.html new file mode 100644 index 0000000000..82db5d0f9c --- /dev/null +++ b/platform/features/rtevents/res/templates/messages.html @@ -0,0 +1,29 @@ + +
+
+ +
+
+ + diff --git a/platform/features/rtevents/src/DomainColumn.js b/platform/features/rtevents/src/DomainColumn.js new file mode 100644 index 0000000000..95a6222553 --- /dev/null +++ b/platform/features/rtevents/src/DomainColumn.js @@ -0,0 +1,67 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,moment*/ + +/** + * Module defining DomainColumn. Created by vwoeltje on 11/18/14. + */ +define( + [], + function () { + "use strict"; + + /** + * A column which will report telemetry domain values + * (typically, timestamps.) Used by the ScrollingListController. + * + * @constructor + * @param domainMetadata an object with the machine- and human- + * readable names for this domain (in `key` and `name` + * fields, respectively.) + * @param {TelemetryFormatter} telemetryFormatter the telemetry + * formatting service, for making values human-readable. + */ + function DomainColumn(domainMetadata, telemetryFormatter) { + return { + /** + * Get the title to display in this column's header. + * @returns {string} the title to display + */ + getTitle: function () { + return domainMetadata.name; + }, + /** + * Get the text to display inside a row under this + * column. + * @returns {string} the text to display + */ + getValue: function (domainObject, data, index) { + return telemetryFormatter.formatDomainValue( + data.getDomainValue(index, domainMetadata.key) + ); + } + }; + } + + return DomainColumn; + } +); \ No newline at end of file diff --git a/platform/features/rtevents/src/RTEventListController.js b/platform/features/rtevents/src/RTEventListController.js new file mode 100644 index 0000000000..b84d339bd6 --- /dev/null +++ b/platform/features/rtevents/src/RTEventListController.js @@ -0,0 +1,139 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define*/ + +/** + * Module defining RTEventListController. + * Created by shale on 06/25/2014. Based on RT Scrolling lists. + */ +define( + ["./DomainColumn", "./RangeColumn"], + function (DomainColumn, RangeColumn) { + "use strict"; + + var ROW_COUNT = 100; + + /** + * The RTEventListController is responsible for populating + * the contents of the messages view. + * @constructor + */ + function RTEventListController($scope, telemetryHandler, telemetryFormatter) { + var handle, + lastUpdated = {}, + lastIds = [], + columns = [], + headers = [], + rows = []; + + function getTelemetryObjects() { + return handle ? handle.getTelemetryObjects() : []; + } + + function idsChanged(telemetryObjects) { + function mismatch(id, index) { + return id !== telemetryObjects[index].getId(); + } + + return lastIds.length !== telemetryObjects.length || + lastIds.some(mismatch); + } + + function setupColumns(telemetryObjects) { + var id = $scope.domainObject && $scope.domainObject.getId(), + firstId = + telemetryObjects[0] && telemetryObjects[0].getId(); + + columns = []; + + if (telemetryObjects > 1 || id !== firstId) { + columns.push(new NameColumn()); + } + columns.push(new DomainColumn(telemetryFormatter)); + columns.push(new RangeColumn()); + + headers = columns.map(function (column) { + return column.getTitle(); + }); + } + + function updateObjects(telemetryObjects) { + if (idsChanged(telemetryObjects)) { + setupColumns(telemetryObjects); + lastIds = telemetryObjects.map(function (telemetryObject) { + return telemetryObject.getId(); + }); + } + } + + function addRow(telemetryObject) { + var id = telemetryObject.getId(), + domainValue = handle.getDomainValue(telemetryObject); + if (lastUpdated[id] !== domainValue && + domainValue !== undefined) { + // Instead of unshift (scrolling), use push (messages) + rows.push(columns.map(function (column) { + return column.getValue(telemetryObject, handle); + })); + rows.splice(ROW_COUNT, Number.MAX_VALUE); + lastUpdated[id] = domainValue; + } + } + + function updateValues() { + getTelemetryObjects().forEach(addRow); + } + + function releaseSubscription() { + if (handle) { + handle.unsubscribe(); + } + } + + function makeSubscription(domainObject) { + releaseSubscription(); + rows = []; + handle = telemetryHandler.handle( + domainObject, + updateValues, + true + ); + } + + $scope.$on("$destroy", releaseSubscription); + + $scope.$watch("domainObject", makeSubscription); + $scope.$watch(getTelemetryObjects, updateObjects); + + return { + rows: function () { + return rows; + }, + headers: function () { + return headers; + } + }; + } + + return RTEventListController; + } +); diff --git a/platform/features/rtevents/src/RangeColumn.js b/platform/features/rtevents/src/RangeColumn.js new file mode 100644 index 0000000000..2b11de43c7 --- /dev/null +++ b/platform/features/rtevents/src/RangeColumn.js @@ -0,0 +1,67 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,Promise*/ + +/** + * Module defining DomainColumn. Created by vwoeltje on 11/18/14. + */ +define( + [], + function () { + "use strict"; + + /** + * A column which will report telemetry range values + * (typically, measurements.) Used by the ScrollingListController. + * + * @constructor + * @param rangeMetadata an object with the machine- and human- + * readable names for this range (in `key` and `name` + * fields, respectively.) + * @param {TelemetryFormatter} telemetryFormatter the telemetry + * formatting service, for making values human-readable. + */ + function RangeColumn(rangeMetadata, telemetryFormatter) { + return { + /** + * Get the title to display in this column's header. + * @returns {string} the title to display + */ + getTitle: function () { + return rangeMetadata.name; + }, + /** + * Get the text to display inside a row under this + * column. + * @returns {string} the text to display + */ + getValue: function (domainObject, data, index) { + return telemetryFormatter.formatRangeValue( + data.getRangeValue(index, rangeMetadata.key) + ); + } + }; + } + + return RangeColumn; + } +); \ No newline at end of file diff --git a/platform/features/rtevents/src/directives/MCTDataTable.js b/platform/features/rtevents/src/directives/MCTDataTable.js new file mode 100644 index 0000000000..c4cb9970e6 --- /dev/null +++ b/platform/features/rtevents/src/directives/MCTDataTable.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,Promise*/ + +/** + * Module defining MCTDataTable. Created by shale on 06/22/2015. + */ +define( + [], + function () { + "use strict"; + + function MCTDataTable($window) { + return { + restrict: "E", + templateUrl: "platform/features/events/res/templates/mct-data-table.html", + scope: { + headers: "=", + rows: "=", + ascendingScroll: "=" + }, + link: function ($scope, $element) { + var currentHeight, + previousHeight, + scrollParent; + + // If the scroll is set to ascending, we want to + // check when elements are added to the table, and move the scroll + // bar accordingly. + // (When viewing at the bottom of the page, the scroll bar will + // stay at the bottom despite additions to the table) + if ($scope.ascendingScroll) { + $scope.$watch("rows", function () { + // Wait until the page as been repainted (otherwise the + // height will always be zero) + $window.requestAnimationFrame(function () { + previousHeight = currentHeight; + // The height of the table body + currentHeight = $element[0].firstElementChild.firstElementChild.nextElementSibling.clientHeight; + + // One of the parents is a div that has vscroll + scrollParent = $element[0].parentElement.parentElement.parentElement.parentElement.parentElement; + + // Move the scrollbar down the amount that the height has changed + scrollParent.scrollTop = scrollParent.scrollTop + (currentHeight - previousHeight); + }); + }); + } + } + }; + } + + return MCTDataTable; + } +); \ No newline at end of file diff --git a/platform/features/rtevents/src/policies/MessagesViewPolicy.js b/platform/features/rtevents/src/policies/MessagesViewPolicy.js new file mode 100644 index 0000000000..4426872b1e --- /dev/null +++ b/platform/features/rtevents/src/policies/MessagesViewPolicy.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*/ + +/** + * Module defining MessagesViewPolicy. Created by shale on 06/24/2015. + */ +define( + [], + function () { + "use strict"; + + /** + * Policy controlling when the Messages view should be avaliable. + * @constructor + */ + function MessagesViewPolicy() { + + function hasStringTelemetry(domainObject) { + var telemetry = domainObject && + domainObject.getCapability('telemetry'), + metadata = telemetry ? telemetry.getMetadata() : {}, + ranges = metadata.ranges || []; + + return ranges.some(function (range) { + return range.format === 'string'; + }); + } + return { + /** + * Check whether or not a given action is allowed by this + * policy. + * @param {Action} action the action + * @param domainObject the domain object which will be viewed + * @returns {boolean} true if not disallowed + */ + allow: function (view, domainObject) { + // This policy only applies for the Messages view + if (view.key === 'messages') { + // The Messages view is allowed only if the domain + // object has string telemetry + if (!hasStringTelemetry(domainObject)) { + return false; + } + } + + // Like all policies, allow by default. + return true; + } + }; + } + + return MessagesViewPolicy; + } +); \ No newline at end of file diff --git a/platform/features/rtevents/test/DomainColumnSpec.js b/platform/features/rtevents/test/DomainColumnSpec.js new file mode 100644 index 0000000000..dc1011648f --- /dev/null +++ b/platform/features/rtevents/test/DomainColumnSpec.js @@ -0,0 +1,84 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,describe,it,expect,beforeEach,waitsFor,jasmine*/ + +/** + * RTEventSpec. Created by vwoeltje on 11/6/14. Modified by shale on 06/23/2015. + */ +define( + ["../src/DomainColumn"], + function (DomainColumn) { + "use strict"; + + var TEST_DOMAIN_VALUE = "some formatted domain value"; + + describe("An event list domain column", function () { + var mockDataSet, + testMetadata, + mockFormatter, + column; + + beforeEach(function () { + mockDataSet = jasmine.createSpyObj( + "data", + [ "getDomainValue" ] + ); + mockFormatter = jasmine.createSpyObj( + "formatter", + [ "formatDomainValue", "formatRangeValue" ] + ); + testMetadata = { + key: "testKey", + name: "Test Name" + }; + mockFormatter.formatDomainValue.andReturn(TEST_DOMAIN_VALUE); + + column = new DomainColumn(testMetadata, mockFormatter); + }); + + it("reports a column header from domain metadata", function () { + expect(column.getTitle()).toEqual("Test Name"); + }); + + it("looks up data from a data set", function () { + column.getValue(undefined, mockDataSet, 42); + expect(mockDataSet.getDomainValue) + .toHaveBeenCalledWith(42, "testKey"); + }); + + it("formats domain values as time", function () { + mockDataSet.getDomainValue.andReturn(402513731000); + + // Should have just given the value the formatter gave + expect(column.getValue(undefined, mockDataSet, 42)) + .toEqual(TEST_DOMAIN_VALUE); + + // Make sure that service interactions were as expected + expect(mockFormatter.formatDomainValue) + .toHaveBeenCalledWith(402513731000); + expect(mockFormatter.formatRangeValue) + .not.toHaveBeenCalled(); + }); + + }); + } +); \ No newline at end of file diff --git a/platform/features/rtevents/test/RTEventListControllerSpec.js b/platform/features/rtevents/test/RTEventListControllerSpec.js new file mode 100644 index 0000000000..bd72dd23f3 --- /dev/null +++ b/platform/features/rtevents/test/RTEventListControllerSpec.js @@ -0,0 +1,110 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,describe,it,expect,beforeEach,waitsFor,jasmine*/ + +/** + * RTEventSpec. Created by shale on 06/25/2015. + */ +define( + ["../src/RTEventListController"], + function (RTEventListController) { + "use strict"; + + describe("The real time event list controller", function () { + var mockScope, + mockTelemetry, + testMetadata, + controller; + + beforeEach(function () { + mockScope = jasmine.createSpyObj( + "$scope", + [ "$on", "$watch" ] + ); + mockTelemetry = jasmine.createSpyObj( + "telemetryController", + [ "getResponse", "getMetadata", "getTelemetryObjects" ] + ); + testMetadata = [ + { + domains: [ + { key: "d0", name: "D0" }, + { key: "d1", name: "D1" } + ], + ranges: [ + { key: "r0", name: "R0" }, + { key: "r1", name: "R1" } + ] + }, + { + domains: [ + { key: "d0", name: "D0" }, + { key: "d2", name: "D2" } + ], + ranges: [ + { key: "r0", name: "R0" } + ] + } + ]; + mockTelemetry.getMetadata.andReturn(testMetadata); + mockTelemetry.getResponse.andReturn([]); + mockTelemetry.getTelemetryObjects.andReturn([]); + mockScope.telemetry = mockTelemetry; + controller = new EventListController(mockScope); + }); + + it("listens for telemetry data updates", function () { + expect(mockScope.$on).toHaveBeenCalledWith( + "telemetryUpdate", + jasmine.any(Function) + ); + }); + + it("watches for telemetry controller changes", function () { + expect(mockScope.$watch).toHaveBeenCalledWith( + "telemetry", + jasmine.any(Function) + ); + }); + + it("provides a column for each unique domain and range", function () { + // Should have five columns based on metadata above, + // (d0, d1, d2, r0, r1) + mockScope.$watch.mostRecentCall.args[1](mockTelemetry); + expect(mockScope.headers).toEqual(["D0", "D1", "D2", "R0", "R1"]); + }); + + it("does not throw if telemetry controller is undefined", function () { + // Just a general robustness check + mockScope.telemetry = undefined; + expect(mockScope.$watch.mostRecentCall.args[1]) + .not.toThrow(); + }); + + it("provides default columns if domain/range metadata is unavailable", function () { + mockTelemetry.getMetadata.andReturn([]); + mockScope.$watch.mostRecentCall.args[1](mockTelemetry); + expect(mockScope.headers).toEqual(["Time", "Message"]); + }); + }); + } +); \ No newline at end of file diff --git a/platform/features/rtevents/test/RangeColumnSpec.js b/platform/features/rtevents/test/RangeColumnSpec.js new file mode 100644 index 0000000000..3dc46c2ad9 --- /dev/null +++ b/platform/features/rtevents/test/RangeColumnSpec.js @@ -0,0 +1,81 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,describe,it,expect,beforeEach,waitsFor,jasmine*/ + +/** + * RTEventSpec. Created by vwoeltje on 11/6/14. Modified by shale on 06/23/2015. + */ +define( + ["../src/RangeColumn"], + function (RangeColumn) { + "use strict"; + + var TEST_RANGE_VALUE = "some formatted range value"; + + describe("An event list range column", function () { + var mockDataSet, + testMetadata, + mockFormatter, + column; + + beforeEach(function () { + mockDataSet = jasmine.createSpyObj( + "data", + [ "getRangeValue" ] + ); + mockFormatter = jasmine.createSpyObj( + "formatter", + [ "formatDomainValue", "formatRangeValue" ] + ); + testMetadata = { + key: "testKey", + name: "Test Name" + }; + mockFormatter.formatRangeValue.andReturn(TEST_RANGE_VALUE); + + column = new RangeColumn(testMetadata, mockFormatter); + }); + + it("reports a column header from range metadata", function () { + expect(column.getTitle()).toEqual("Test Name"); + }); + + it("looks up data from a data set", function () { + column.getValue(undefined, mockDataSet, 42); + expect(mockDataSet.getRangeValue) + .toHaveBeenCalledWith(42, "testKey"); + }); + + it("formats range values as time", function () { + mockDataSet.getRangeValue.andReturn(123.45678); + expect(column.getValue(undefined, mockDataSet, 42)) + .toEqual(TEST_RANGE_VALUE); + + // Make sure that service interactions were as expected + expect(mockFormatter.formatRangeValue) + .toHaveBeenCalledWith(123.45678); + expect(mockFormatter.formatDomainValue) + .not.toHaveBeenCalled(); + }); + }); + } +); \ No newline at end of file diff --git a/platform/features/rtevents/test/policies/MessagesViewPolicySpec.js b/platform/features/rtevents/test/policies/MessagesViewPolicySpec.js new file mode 100644 index 0000000000..6e3430f64e --- /dev/null +++ b/platform/features/rtevents/test/policies/MessagesViewPolicySpec.js @@ -0,0 +1,68 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,describe,it,expect,beforeEach,jasmine*/ + +/** + * EventSpec. Created by shale on 06/24/2015. + */ +define( + ["../../src/policies/MessagesViewPolicy"], + function (MessagesViewPolicy) { + "use strict"; + + describe("The messages view policy", function () { + var mockDomainObject, + testType, + telemetryType, + policy; + + beforeEach(function () { + mockDomainObject = jasmine.createSpyObj( + 'domainObject', + ['getModel'] + ); + mockDomainObject.getModel.andCallFake(function (c) { + return {type: testType}; + }); + + policy = new MessagesViewPolicy(); + }); + + it("disallows the message view for objects without string telemetry", function () { + telemetryType = 'notString'; + expect(policy.allow({ key: 'messages' }, mockDomainObject)) + .toBeFalsy(); + }); + + it("allows the message view for objects with string telemetry", function () { + telemetryType = 'string'; + expect(policy.allow({ key: 'messages' }, mockDomainObject)) + .toBeTruthy(); + }); + + it("returns true when the current view is not the Messages view", function () { + expect(policy.allow({ key: 'notMessages' }, mockDomainObject)) + .toBeTruthy(); + }); + }); + } +); \ No newline at end of file diff --git a/platform/features/rtevents/test/suite.json b/platform/features/rtevents/test/suite.json new file mode 100644 index 0000000000..260e84474b --- /dev/null +++ b/platform/features/rtevents/test/suite.json @@ -0,0 +1,6 @@ +[ + "DomainColumn", + "RTEventListController", + "policies/MessagesViewPolicy", + "RangeColumn" +] \ No newline at end of file From 288692f57cc75186e45fca5c0e167d6724ab5d78 Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Thu, 25 Jun 2015 09:57:43 -0700 Subject: [PATCH 28/30] Fixing merge Re-added the event list controller. --- .../rtevents/src/RTEventListController.js | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 platform/features/rtevents/src/RTEventListController.js diff --git a/platform/features/rtevents/src/RTEventListController.js b/platform/features/rtevents/src/RTEventListController.js new file mode 100644 index 0000000000..b84d339bd6 --- /dev/null +++ b/platform/features/rtevents/src/RTEventListController.js @@ -0,0 +1,139 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define*/ + +/** + * Module defining RTEventListController. + * Created by shale on 06/25/2014. Based on RT Scrolling lists. + */ +define( + ["./DomainColumn", "./RangeColumn"], + function (DomainColumn, RangeColumn) { + "use strict"; + + var ROW_COUNT = 100; + + /** + * The RTEventListController is responsible for populating + * the contents of the messages view. + * @constructor + */ + function RTEventListController($scope, telemetryHandler, telemetryFormatter) { + var handle, + lastUpdated = {}, + lastIds = [], + columns = [], + headers = [], + rows = []; + + function getTelemetryObjects() { + return handle ? handle.getTelemetryObjects() : []; + } + + function idsChanged(telemetryObjects) { + function mismatch(id, index) { + return id !== telemetryObjects[index].getId(); + } + + return lastIds.length !== telemetryObjects.length || + lastIds.some(mismatch); + } + + function setupColumns(telemetryObjects) { + var id = $scope.domainObject && $scope.domainObject.getId(), + firstId = + telemetryObjects[0] && telemetryObjects[0].getId(); + + columns = []; + + if (telemetryObjects > 1 || id !== firstId) { + columns.push(new NameColumn()); + } + columns.push(new DomainColumn(telemetryFormatter)); + columns.push(new RangeColumn()); + + headers = columns.map(function (column) { + return column.getTitle(); + }); + } + + function updateObjects(telemetryObjects) { + if (idsChanged(telemetryObjects)) { + setupColumns(telemetryObjects); + lastIds = telemetryObjects.map(function (telemetryObject) { + return telemetryObject.getId(); + }); + } + } + + function addRow(telemetryObject) { + var id = telemetryObject.getId(), + domainValue = handle.getDomainValue(telemetryObject); + if (lastUpdated[id] !== domainValue && + domainValue !== undefined) { + // Instead of unshift (scrolling), use push (messages) + rows.push(columns.map(function (column) { + return column.getValue(telemetryObject, handle); + })); + rows.splice(ROW_COUNT, Number.MAX_VALUE); + lastUpdated[id] = domainValue; + } + } + + function updateValues() { + getTelemetryObjects().forEach(addRow); + } + + function releaseSubscription() { + if (handle) { + handle.unsubscribe(); + } + } + + function makeSubscription(domainObject) { + releaseSubscription(); + rows = []; + handle = telemetryHandler.handle( + domainObject, + updateValues, + true + ); + } + + $scope.$on("$destroy", releaseSubscription); + + $scope.$watch("domainObject", makeSubscription); + $scope.$watch(getTelemetryObjects, updateObjects); + + return { + rows: function () { + return rows; + }, + headers: function () { + return headers; + } + }; + } + + return RTEventListController; + } +); From 1961ba20c0d04f662583fdc6848b6ab6466a853d Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Thu, 25 Jun 2015 09:59:52 -0700 Subject: [PATCH 29/30] Fixing merge Re-added the tests. --- .../rtevents/test/DomainColumnSpec.js | 84 +++++++++++++ .../test/RTEventListControllerSpec.js | 110 ++++++++++++++++++ .../features/rtevents/test/RangeColumnSpec.js | 81 +++++++++++++ 3 files changed, 275 insertions(+) create mode 100644 platform/features/rtevents/test/DomainColumnSpec.js create mode 100644 platform/features/rtevents/test/RTEventListControllerSpec.js create mode 100644 platform/features/rtevents/test/RangeColumnSpec.js diff --git a/platform/features/rtevents/test/DomainColumnSpec.js b/platform/features/rtevents/test/DomainColumnSpec.js new file mode 100644 index 0000000000..29c896cd5b --- /dev/null +++ b/platform/features/rtevents/test/DomainColumnSpec.js @@ -0,0 +1,84 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,describe,it,expect,beforeEach,waitsFor,jasmine*/ + +/** + * EventSpec. Created by vwoeltje on 11/6/14. Modified by shale on 06/23/2015. + */ +define( + ["../src/DomainColumn"], + function (DomainColumn) { + "use strict"; + + var TEST_DOMAIN_VALUE = "some formatted domain value"; + + describe("An event list domain column", function () { + var mockDataSet, + testMetadata, + mockFormatter, + column; + + beforeEach(function () { + mockDataSet = jasmine.createSpyObj( + "data", + [ "getDomainValue" ] + ); + mockFormatter = jasmine.createSpyObj( + "formatter", + [ "formatDomainValue", "formatRangeValue" ] + ); + testMetadata = { + key: "testKey", + name: "Test Name" + }; + mockFormatter.formatDomainValue.andReturn(TEST_DOMAIN_VALUE); + + column = new DomainColumn(testMetadata, mockFormatter); + }); + + it("reports a column header from domain metadata", function () { + expect(column.getTitle()).toEqual("Test Name"); + }); + + it("looks up data from a data set", function () { + column.getValue(undefined, mockDataSet, 42); + expect(mockDataSet.getDomainValue) + .toHaveBeenCalledWith(42, "testKey"); + }); + + it("formats domain values as time", function () { + mockDataSet.getDomainValue.andReturn(402513731000); + + // Should have just given the value the formatter gave + expect(column.getValue(undefined, mockDataSet, 42)) + .toEqual(TEST_DOMAIN_VALUE); + + // Make sure that service interactions were as expected + expect(mockFormatter.formatDomainValue) + .toHaveBeenCalledWith(402513731000); + expect(mockFormatter.formatRangeValue) + .not.toHaveBeenCalled(); + }); + + }); + } +); \ No newline at end of file diff --git a/platform/features/rtevents/test/RTEventListControllerSpec.js b/platform/features/rtevents/test/RTEventListControllerSpec.js new file mode 100644 index 0000000000..ba764b61b0 --- /dev/null +++ b/platform/features/rtevents/test/RTEventListControllerSpec.js @@ -0,0 +1,110 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,describe,it,expect,beforeEach,waitsFor,jasmine*/ + +/** + * EventSpec. Created by shale on 06/25/2015. + */ +define( + ["../src/RTEventListController"], + function (RTEventListController) { + "use strict"; + + describe("The real time event list controller", function () { + var mockScope, + mockTelemetry, + testMetadata, + controller; + + beforeEach(function () { + mockScope = jasmine.createSpyObj( + "$scope", + [ "$on", "$watch" ] + ); + mockTelemetry = jasmine.createSpyObj( + "telemetryController", + [ "getResponse", "getMetadata", "getTelemetryObjects" ] + ); + testMetadata = [ + { + domains: [ + { key: "d0", name: "D0" }, + { key: "d1", name: "D1" } + ], + ranges: [ + { key: "r0", name: "R0" }, + { key: "r1", name: "R1" } + ] + }, + { + domains: [ + { key: "d0", name: "D0" }, + { key: "d2", name: "D2" } + ], + ranges: [ + { key: "r0", name: "R0" } + ] + } + ]; + mockTelemetry.getMetadata.andReturn(testMetadata); + mockTelemetry.getResponse.andReturn([]); + mockTelemetry.getTelemetryObjects.andReturn([]); + mockScope.telemetry = mockTelemetry; + controller = new EventListController(mockScope); + }); + + it("listens for telemetry data updates", function () { + expect(mockScope.$on).toHaveBeenCalledWith( + "telemetryUpdate", + jasmine.any(Function) + ); + }); + + it("watches for telemetry controller changes", function () { + expect(mockScope.$watch).toHaveBeenCalledWith( + "telemetry", + jasmine.any(Function) + ); + }); + + it("provides a column for each unique domain and range", function () { + // Should have five columns based on metadata above, + // (d0, d1, d2, r0, r1) + mockScope.$watch.mostRecentCall.args[1](mockTelemetry); + expect(mockScope.headers).toEqual(["D0", "D1", "D2", "R0", "R1"]); + }); + + it("does not throw if telemetry controller is undefined", function () { + // Just a general robustness check + mockScope.telemetry = undefined; + expect(mockScope.$watch.mostRecentCall.args[1]) + .not.toThrow(); + }); + + it("provides default columns if domain/range metadata is unavailable", function () { + mockTelemetry.getMetadata.andReturn([]); + mockScope.$watch.mostRecentCall.args[1](mockTelemetry); + expect(mockScope.headers).toEqual(["Time", "Message"]); + }); + }); + } +); \ No newline at end of file diff --git a/platform/features/rtevents/test/RangeColumnSpec.js b/platform/features/rtevents/test/RangeColumnSpec.js new file mode 100644 index 0000000000..99c5ceb6f4 --- /dev/null +++ b/platform/features/rtevents/test/RangeColumnSpec.js @@ -0,0 +1,81 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,describe,it,expect,beforeEach,waitsFor,jasmine*/ + +/** + * EventSpec. Created by vwoeltje on 11/6/14. Modified by shale on 06/23/2015. + */ +define( + ["../src/RangeColumn"], + function (RangeColumn) { + "use strict"; + + var TEST_RANGE_VALUE = "some formatted range value"; + + describe("An event list range column", function () { + var mockDataSet, + testMetadata, + mockFormatter, + column; + + beforeEach(function () { + mockDataSet = jasmine.createSpyObj( + "data", + [ "getRangeValue" ] + ); + mockFormatter = jasmine.createSpyObj( + "formatter", + [ "formatDomainValue", "formatRangeValue" ] + ); + testMetadata = { + key: "testKey", + name: "Test Name" + }; + mockFormatter.formatRangeValue.andReturn(TEST_RANGE_VALUE); + + column = new RangeColumn(testMetadata, mockFormatter); + }); + + it("reports a column header from range metadata", function () { + expect(column.getTitle()).toEqual("Test Name"); + }); + + it("looks up data from a data set", function () { + column.getValue(undefined, mockDataSet, 42); + expect(mockDataSet.getRangeValue) + .toHaveBeenCalledWith(42, "testKey"); + }); + + it("formats range values as time", function () { + mockDataSet.getRangeValue.andReturn(123.45678); + expect(column.getValue(undefined, mockDataSet, 42)) + .toEqual(TEST_RANGE_VALUE); + + // Make sure that service interactions were as expected + expect(mockFormatter.formatRangeValue) + .toHaveBeenCalledWith(123.45678); + expect(mockFormatter.formatDomainValue) + .not.toHaveBeenCalled(); + }); + }); + } +); \ No newline at end of file From c98a381a42bf17b92e25983db6cf9548c3d96128 Mon Sep 17 00:00:00 2001 From: Sarah Hale Date: Thu, 25 Jun 2015 14:36:14 -0700 Subject: [PATCH 30/30] [Events] Created RT Messages Created a real-time version of the Messages view called RT Messages. Additionally, fixed the MessagesViewPolicy test. #18. --- .../test/policies/MessagesViewPolicySpec.js | 35 ++++-- platform/features/rtevents/bundle.json | 12 +- ...data-table.html => mct-rt-data-table.html} | 0 .../{messages.html => rtmessages.html} | 6 +- .../features/rtevents/src/DomainColumn.js | 16 +-- .../rtevents/src/RTEventListController.js | 11 +- platform/features/rtevents/src/RangeColumn.js | 21 ++-- .../{MCTDataTable.js => MCTRTDataTable.js} | 12 +- ...sViewPolicy.js => RTMessagesViewPolicy.js} | 11 +- .../rtevents/test/DomainColumnSpec.js | 84 ------------- .../test/RTEventListControllerSpec.js | 110 ------------------ .../features/rtevents/test/RangeColumnSpec.js | 81 ------------- .../test/policies/MessagesViewPolicySpec.js | 68 ----------- .../test/policies/RTMessagesViewPolicySpec.js | 0 platform/features/rtevents/test/suite.js | 0 15 files changed, 70 insertions(+), 397 deletions(-) rename platform/features/rtevents/res/templates/{mct-data-table.html => mct-rt-data-table.html} (100%) rename platform/features/rtevents/res/templates/{messages.html => rtmessages.html} (83%) rename platform/features/rtevents/src/directives/{MCTDataTable.js => MCTRTDataTable.js} (90%) rename platform/features/rtevents/src/policies/{MessagesViewPolicy.js => RTMessagesViewPolicy.js} (90%) delete mode 100644 platform/features/rtevents/test/policies/MessagesViewPolicySpec.js create mode 100644 platform/features/rtevents/test/policies/RTMessagesViewPolicySpec.js create mode 100644 platform/features/rtevents/test/suite.js diff --git a/platform/features/events/test/policies/MessagesViewPolicySpec.js b/platform/features/events/test/policies/MessagesViewPolicySpec.js index 6e3430f64e..c803cf91ed 100644 --- a/platform/features/events/test/policies/MessagesViewPolicySpec.js +++ b/platform/features/events/test/policies/MessagesViewPolicySpec.js @@ -31,37 +31,50 @@ define( describe("The messages view policy", function () { var mockDomainObject, - testType, + mockTelemetry, telemetryType, + testType, + testView, + testMetadata, policy; beforeEach(function () { + + testView = { key: "string" }; + testMetadata = {}; + mockDomainObject = jasmine.createSpyObj( 'domainObject', - ['getModel'] + ['getModel', 'getCapability'] ); + mockTelemetry = jasmine.createSpyObj( + 'telemetry', + ['getMetadata'] + ); + mockDomainObject.getModel.andCallFake(function (c) { return {type: testType}; }); + mockDomainObject.getCapability.andCallFake(function (c) { + return c === 'telemetry' ? mockTelemetry : undefined; + }); + mockTelemetry.getMetadata.andReturn(testMetadata); policy = new MessagesViewPolicy(); }); - + it("disallows the message view for objects without string telemetry", function () { - telemetryType = 'notString'; - expect(policy.allow({ key: 'messages' }, mockDomainObject)) - .toBeFalsy(); + testMetadata.ranges = [ { format: 'notString' } ]; + expect(policy.allow({ key: 'messages' }, mockDomainObject)).toBeFalsy(); }); it("allows the message view for objects with string telemetry", function () { - telemetryType = 'string'; - expect(policy.allow({ key: 'messages' }, mockDomainObject)) - .toBeTruthy(); + testMetadata.ranges = [ { format: 'string' } ]; + expect(policy.allow({ key: 'messages' }, mockDomainObject)).toBeTruthy(); }); it("returns true when the current view is not the Messages view", function () { - expect(policy.allow({ key: 'notMessages' }, mockDomainObject)) - .toBeTruthy(); + expect(policy.allow({ key: 'notMessages' }, mockDomainObject)).toBeTruthy(); }); }); } diff --git a/platform/features/rtevents/bundle.json b/platform/features/rtevents/bundle.json index 04400d8223..d2067bdd79 100644 --- a/platform/features/rtevents/bundle.json +++ b/platform/features/rtevents/bundle.json @@ -4,11 +4,11 @@ "extensions": { "views": [ { - "key": "messages", + "key": "rtmessages", "name": "RT Messages", "glyph": "5", - "description": "Scrolling list of messages.", - "templateUrl": "templates/messages.html", + "description": "Scrolling list of real time messages.", + "templateUrl": "templates/rtmessages.html", "needs": [ "telemetry" ], "delegation": true } @@ -22,15 +22,15 @@ ], "directives": [ { - "key": "mctDataTable", - "implementation": "directives/MCTDataTable.js", + "key": "mctRtDataTable", + "implementation": "directives/MCTRTDataTable.js", "depends": [ "$window" ] } ], "policies": [ { "category": "view", - "implementation": "policies/MessagesViewPolicy.js" + "implementation": "policies/RTMessagesViewPolicy.js" } ] } diff --git a/platform/features/rtevents/res/templates/mct-data-table.html b/platform/features/rtevents/res/templates/mct-rt-data-table.html similarity index 100% rename from platform/features/rtevents/res/templates/mct-data-table.html rename to platform/features/rtevents/res/templates/mct-rt-data-table.html diff --git a/platform/features/rtevents/res/templates/messages.html b/platform/features/rtevents/res/templates/rtmessages.html similarity index 83% rename from platform/features/rtevents/res/templates/messages.html rename to platform/features/rtevents/res/templates/rtmessages.html index 82db5d0f9c..f17a44fe8c 100644 --- a/platform/features/rtevents/res/templates/messages.html +++ b/platform/features/rtevents/res/templates/rtmessages.html @@ -19,10 +19,10 @@ this source code distribution or the Licensing information page available at runtime from the About dialog for additional information. --> -
+
- + ng-controller="RTEventListController as rtevent"> +
diff --git a/platform/features/rtevents/src/DomainColumn.js b/platform/features/rtevents/src/DomainColumn.js index 95a6222553..c4f8a2a143 100644 --- a/platform/features/rtevents/src/DomainColumn.js +++ b/platform/features/rtevents/src/DomainColumn.js @@ -40,28 +40,30 @@ define( * @param {TelemetryFormatter} telemetryFormatter the telemetry * formatting service, for making values human-readable. */ - function DomainColumn(domainMetadata, telemetryFormatter) { + function DomainColumn(telemetryFormatter) { return { /** * Get the title to display in this column's header. * @returns {string} the title to display */ getTitle: function () { - return domainMetadata.name; + return "Time"; }, /** * Get the text to display inside a row under this * column. * @returns {string} the text to display */ - getValue: function (domainObject, data, index) { - return telemetryFormatter.formatDomainValue( - data.getDomainValue(index, domainMetadata.key) - ); + getValue: function (domainObject, handle) { + return { + text: telemetryFormatter.formatDomainValue( + handle.getDomainValue(domainObject) + ) + }; } }; } return DomainColumn; } -); \ No newline at end of file +); diff --git a/platform/features/rtevents/src/RTEventListController.js b/platform/features/rtevents/src/RTEventListController.js index b84d339bd6..618d6eede9 100644 --- a/platform/features/rtevents/src/RTEventListController.js +++ b/platform/features/rtevents/src/RTEventListController.js @@ -64,10 +64,7 @@ define( telemetryObjects[0] && telemetryObjects[0].getId(); columns = []; - - if (telemetryObjects > 1 || id !== firstId) { - columns.push(new NameColumn()); - } + columns.push(new DomainColumn(telemetryFormatter)); columns.push(new RangeColumn()); @@ -92,9 +89,11 @@ define( domainValue !== undefined) { // Instead of unshift (scrolling), use push (messages) rows.push(columns.map(function (column) { - return column.getValue(telemetryObject, handle); + return column.getValue(telemetryObject, handle).text; })); - rows.splice(ROW_COUNT, Number.MAX_VALUE); + // Remove first rows when adding past the max rows limit + //rows.splice(ROW_COUNT, Number.MAX_VALUE); + rows.splice(0, rows.length - ROW_COUNT); lastUpdated[id] = domainValue; } } diff --git a/platform/features/rtevents/src/RangeColumn.js b/platform/features/rtevents/src/RangeColumn.js index 2b11de43c7..8fcf747b25 100644 --- a/platform/features/rtevents/src/RangeColumn.js +++ b/platform/features/rtevents/src/RangeColumn.js @@ -19,10 +19,11 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ -/*global define,Promise*/ +/*global define,moment*/ /** - * Module defining DomainColumn. Created by vwoeltje on 11/18/14. + * Module defining DomainColumn. + * Created by vwoeltje on 11/18/14. Modified by shale on 06/25/2015. */ define( [], @@ -31,7 +32,7 @@ define( /** * A column which will report telemetry range values - * (typically, measurements.) Used by the ScrollingListController. + * (typically, measurements.) Used by the RTScrollingListController. * * @constructor * @param rangeMetadata an object with the machine- and human- @@ -40,28 +41,28 @@ define( * @param {TelemetryFormatter} telemetryFormatter the telemetry * formatting service, for making values human-readable. */ - function RangeColumn(rangeMetadata, telemetryFormatter) { + function RangeColumn() { return { /** * Get the title to display in this column's header. * @returns {string} the title to display */ getTitle: function () { - return rangeMetadata.name; + return "Message"; }, /** * Get the text to display inside a row under this * column. * @returns {string} the text to display */ - getValue: function (domainObject, data, index) { - return telemetryFormatter.formatRangeValue( - data.getRangeValue(index, rangeMetadata.key) - ); + getValue: function (domainObject, handle) { + return { + text: handle.getRangeValue(domainObject) + }; } }; } return RangeColumn; } -); \ No newline at end of file +); diff --git a/platform/features/rtevents/src/directives/MCTDataTable.js b/platform/features/rtevents/src/directives/MCTRTDataTable.js similarity index 90% rename from platform/features/rtevents/src/directives/MCTDataTable.js rename to platform/features/rtevents/src/directives/MCTRTDataTable.js index c4cb9970e6..9047d9e7f1 100644 --- a/platform/features/rtevents/src/directives/MCTDataTable.js +++ b/platform/features/rtevents/src/directives/MCTRTDataTable.js @@ -22,17 +22,17 @@ /*global define,Promise*/ /** - * Module defining MCTDataTable. Created by shale on 06/22/2015. + * Module defining MCTRTDataTable. Created by shale on 06/25/2015. */ define( [], function () { "use strict"; - function MCTDataTable($window) { + function MCTRTDataTable($window) { return { restrict: "E", - templateUrl: "platform/features/events/res/templates/mct-data-table.html", + templateUrl: "platform/features/rtevents/res/templates/mct-rt-data-table.html", scope: { headers: "=", rows: "=", @@ -49,7 +49,7 @@ define( // (When viewing at the bottom of the page, the scroll bar will // stay at the bottom despite additions to the table) if ($scope.ascendingScroll) { - $scope.$watch("rows", function () { + $scope.$watchCollection("rows", function () { // Wait until the page as been repainted (otherwise the // height will always be zero) $window.requestAnimationFrame(function () { @@ -59,7 +59,7 @@ define( // One of the parents is a div that has vscroll scrollParent = $element[0].parentElement.parentElement.parentElement.parentElement.parentElement; - + // Move the scrollbar down the amount that the height has changed scrollParent.scrollTop = scrollParent.scrollTop + (currentHeight - previousHeight); }); @@ -69,6 +69,6 @@ define( }; } - return MCTDataTable; + return MCTRTDataTable; } ); \ No newline at end of file diff --git a/platform/features/rtevents/src/policies/MessagesViewPolicy.js b/platform/features/rtevents/src/policies/RTMessagesViewPolicy.js similarity index 90% rename from platform/features/rtevents/src/policies/MessagesViewPolicy.js rename to platform/features/rtevents/src/policies/RTMessagesViewPolicy.js index 4426872b1e..32daca6873 100644 --- a/platform/features/rtevents/src/policies/MessagesViewPolicy.js +++ b/platform/features/rtevents/src/policies/RTMessagesViewPolicy.js @@ -33,14 +33,15 @@ define( * Policy controlling when the Messages view should be avaliable. * @constructor */ - function MessagesViewPolicy() { + function RTMessagesViewPolicy() { function hasStringTelemetry(domainObject) { var telemetry = domainObject && domainObject.getCapability('telemetry'), metadata = telemetry ? telemetry.getMetadata() : {}, + data = telemetry ? telemetry.requestData() : {}, ranges = metadata.ranges || []; - + return ranges.some(function (range) { return range.format === 'string'; }); @@ -54,8 +55,8 @@ define( * @returns {boolean} true if not disallowed */ allow: function (view, domainObject) { - // This policy only applies for the Messages view - if (view.key === 'messages') { + // This policy only applies for the RT Messages view + if (view.key === 'rtmessages') { // The Messages view is allowed only if the domain // object has string telemetry if (!hasStringTelemetry(domainObject)) { @@ -69,6 +70,6 @@ define( }; } - return MessagesViewPolicy; + return RTMessagesViewPolicy; } ); \ No newline at end of file diff --git a/platform/features/rtevents/test/DomainColumnSpec.js b/platform/features/rtevents/test/DomainColumnSpec.js index 29c896cd5b..e69de29bb2 100644 --- a/platform/features/rtevents/test/DomainColumnSpec.js +++ b/platform/features/rtevents/test/DomainColumnSpec.js @@ -1,84 +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,describe,it,expect,beforeEach,waitsFor,jasmine*/ - -/** - * EventSpec. Created by vwoeltje on 11/6/14. Modified by shale on 06/23/2015. - */ -define( - ["../src/DomainColumn"], - function (DomainColumn) { - "use strict"; - - var TEST_DOMAIN_VALUE = "some formatted domain value"; - - describe("An event list domain column", function () { - var mockDataSet, - testMetadata, - mockFormatter, - column; - - beforeEach(function () { - mockDataSet = jasmine.createSpyObj( - "data", - [ "getDomainValue" ] - ); - mockFormatter = jasmine.createSpyObj( - "formatter", - [ "formatDomainValue", "formatRangeValue" ] - ); - testMetadata = { - key: "testKey", - name: "Test Name" - }; - mockFormatter.formatDomainValue.andReturn(TEST_DOMAIN_VALUE); - - column = new DomainColumn(testMetadata, mockFormatter); - }); - - it("reports a column header from domain metadata", function () { - expect(column.getTitle()).toEqual("Test Name"); - }); - - it("looks up data from a data set", function () { - column.getValue(undefined, mockDataSet, 42); - expect(mockDataSet.getDomainValue) - .toHaveBeenCalledWith(42, "testKey"); - }); - - it("formats domain values as time", function () { - mockDataSet.getDomainValue.andReturn(402513731000); - - // Should have just given the value the formatter gave - expect(column.getValue(undefined, mockDataSet, 42)) - .toEqual(TEST_DOMAIN_VALUE); - - // Make sure that service interactions were as expected - expect(mockFormatter.formatDomainValue) - .toHaveBeenCalledWith(402513731000); - expect(mockFormatter.formatRangeValue) - .not.toHaveBeenCalled(); - }); - - }); - } -); \ No newline at end of file diff --git a/platform/features/rtevents/test/RTEventListControllerSpec.js b/platform/features/rtevents/test/RTEventListControllerSpec.js index ba764b61b0..e69de29bb2 100644 --- a/platform/features/rtevents/test/RTEventListControllerSpec.js +++ b/platform/features/rtevents/test/RTEventListControllerSpec.js @@ -1,110 +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,describe,it,expect,beforeEach,waitsFor,jasmine*/ - -/** - * EventSpec. Created by shale on 06/25/2015. - */ -define( - ["../src/RTEventListController"], - function (RTEventListController) { - "use strict"; - - describe("The real time event list controller", function () { - var mockScope, - mockTelemetry, - testMetadata, - controller; - - beforeEach(function () { - mockScope = jasmine.createSpyObj( - "$scope", - [ "$on", "$watch" ] - ); - mockTelemetry = jasmine.createSpyObj( - "telemetryController", - [ "getResponse", "getMetadata", "getTelemetryObjects" ] - ); - testMetadata = [ - { - domains: [ - { key: "d0", name: "D0" }, - { key: "d1", name: "D1" } - ], - ranges: [ - { key: "r0", name: "R0" }, - { key: "r1", name: "R1" } - ] - }, - { - domains: [ - { key: "d0", name: "D0" }, - { key: "d2", name: "D2" } - ], - ranges: [ - { key: "r0", name: "R0" } - ] - } - ]; - mockTelemetry.getMetadata.andReturn(testMetadata); - mockTelemetry.getResponse.andReturn([]); - mockTelemetry.getTelemetryObjects.andReturn([]); - mockScope.telemetry = mockTelemetry; - controller = new EventListController(mockScope); - }); - - it("listens for telemetry data updates", function () { - expect(mockScope.$on).toHaveBeenCalledWith( - "telemetryUpdate", - jasmine.any(Function) - ); - }); - - it("watches for telemetry controller changes", function () { - expect(mockScope.$watch).toHaveBeenCalledWith( - "telemetry", - jasmine.any(Function) - ); - }); - - it("provides a column for each unique domain and range", function () { - // Should have five columns based on metadata above, - // (d0, d1, d2, r0, r1) - mockScope.$watch.mostRecentCall.args[1](mockTelemetry); - expect(mockScope.headers).toEqual(["D0", "D1", "D2", "R0", "R1"]); - }); - - it("does not throw if telemetry controller is undefined", function () { - // Just a general robustness check - mockScope.telemetry = undefined; - expect(mockScope.$watch.mostRecentCall.args[1]) - .not.toThrow(); - }); - - it("provides default columns if domain/range metadata is unavailable", function () { - mockTelemetry.getMetadata.andReturn([]); - mockScope.$watch.mostRecentCall.args[1](mockTelemetry); - expect(mockScope.headers).toEqual(["Time", "Message"]); - }); - }); - } -); \ No newline at end of file diff --git a/platform/features/rtevents/test/RangeColumnSpec.js b/platform/features/rtevents/test/RangeColumnSpec.js index 99c5ceb6f4..e69de29bb2 100644 --- a/platform/features/rtevents/test/RangeColumnSpec.js +++ b/platform/features/rtevents/test/RangeColumnSpec.js @@ -1,81 +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,describe,it,expect,beforeEach,waitsFor,jasmine*/ - -/** - * EventSpec. Created by vwoeltje on 11/6/14. Modified by shale on 06/23/2015. - */ -define( - ["../src/RangeColumn"], - function (RangeColumn) { - "use strict"; - - var TEST_RANGE_VALUE = "some formatted range value"; - - describe("An event list range column", function () { - var mockDataSet, - testMetadata, - mockFormatter, - column; - - beforeEach(function () { - mockDataSet = jasmine.createSpyObj( - "data", - [ "getRangeValue" ] - ); - mockFormatter = jasmine.createSpyObj( - "formatter", - [ "formatDomainValue", "formatRangeValue" ] - ); - testMetadata = { - key: "testKey", - name: "Test Name" - }; - mockFormatter.formatRangeValue.andReturn(TEST_RANGE_VALUE); - - column = new RangeColumn(testMetadata, mockFormatter); - }); - - it("reports a column header from range metadata", function () { - expect(column.getTitle()).toEqual("Test Name"); - }); - - it("looks up data from a data set", function () { - column.getValue(undefined, mockDataSet, 42); - expect(mockDataSet.getRangeValue) - .toHaveBeenCalledWith(42, "testKey"); - }); - - it("formats range values as time", function () { - mockDataSet.getRangeValue.andReturn(123.45678); - expect(column.getValue(undefined, mockDataSet, 42)) - .toEqual(TEST_RANGE_VALUE); - - // Make sure that service interactions were as expected - expect(mockFormatter.formatRangeValue) - .toHaveBeenCalledWith(123.45678); - expect(mockFormatter.formatDomainValue) - .not.toHaveBeenCalled(); - }); - }); - } -); \ No newline at end of file diff --git a/platform/features/rtevents/test/policies/MessagesViewPolicySpec.js b/platform/features/rtevents/test/policies/MessagesViewPolicySpec.js deleted file mode 100644 index 6e3430f64e..0000000000 --- a/platform/features/rtevents/test/policies/MessagesViewPolicySpec.js +++ /dev/null @@ -1,68 +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,describe,it,expect,beforeEach,jasmine*/ - -/** - * EventSpec. Created by shale on 06/24/2015. - */ -define( - ["../../src/policies/MessagesViewPolicy"], - function (MessagesViewPolicy) { - "use strict"; - - describe("The messages view policy", function () { - var mockDomainObject, - testType, - telemetryType, - policy; - - beforeEach(function () { - mockDomainObject = jasmine.createSpyObj( - 'domainObject', - ['getModel'] - ); - mockDomainObject.getModel.andCallFake(function (c) { - return {type: testType}; - }); - - policy = new MessagesViewPolicy(); - }); - - it("disallows the message view for objects without string telemetry", function () { - telemetryType = 'notString'; - expect(policy.allow({ key: 'messages' }, mockDomainObject)) - .toBeFalsy(); - }); - - it("allows the message view for objects with string telemetry", function () { - telemetryType = 'string'; - expect(policy.allow({ key: 'messages' }, mockDomainObject)) - .toBeTruthy(); - }); - - it("returns true when the current view is not the Messages view", function () { - expect(policy.allow({ key: 'notMessages' }, mockDomainObject)) - .toBeTruthy(); - }); - }); - } -); \ No newline at end of file diff --git a/platform/features/rtevents/test/policies/RTMessagesViewPolicySpec.js b/platform/features/rtevents/test/policies/RTMessagesViewPolicySpec.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/platform/features/rtevents/test/suite.js b/platform/features/rtevents/test/suite.js new file mode 100644 index 0000000000..e69de29bb2