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}} + | +