diff --git a/README.md b/README.md index c36cbea653..42cd060282 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ as described above. An example of this is expressed in `platform/framework`, which follows bundle conventions. -### Regression Testing +### Functional Testing The tests described above are all at the unit-level; an additional test suite using [Protractor](https://angular.github.io/protractor/) @@ -76,9 +76,9 @@ us under development, in the `protractor` folder. To run: * Install protractor following the instructions above. -* `webdriver-manager start` -* `node app.js -p 1984 -x platform/persistence/elastic -i example/persistence -* `protractor protractor/conf.js` +* `cd protractor` +* `npm install` +* `npm run all` ## Build diff --git a/bundles.json b/bundles.json index 0b97f1abab..898ca3d738 100644 --- a/bundles.json +++ b/bundles.json @@ -21,6 +21,7 @@ "platform/persistence/queue", "platform/policy", "platform/entanglement", + "platform/search", "example/imagery", "example/persistence", diff --git a/circle.yml b/circle.yml index b8f367a604..2a79a5ed93 100644 --- a/circle.yml +++ b/circle.yml @@ -4,3 +4,7 @@ deployment: commands: - ./build-docs.sh - git push git@heroku.com:openmctweb-demo.git $CIRCLE_SHA1:refs/heads/master + openmctweb-staging-un: + branch: search + heroku: + appname: openmctweb-staging-un diff --git a/platform/commonUI/general/res/css/forms.css b/platform/commonUI/general/res/css/forms.css index ec41844773..b7b08b89e8 100644 --- a/platform/commonUI/general/res/css/forms.css +++ b/platform/commonUI/general/res/css/forms.css @@ -69,6 +69,7 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ +/*********************************************** FORM ELEMENTS */ /* @mixin invokeMenu($baseColor: $colorBodyFg) { $c: $baseColor; @@ -182,27 +183,21 @@ line-height: 14px; margin-right: 5px; } /* line 89, ../sass/forms/_elems.scss */ - .form .form-row .controls input[type="text"] { - height: 22px; - line-height: 22px; - margin-top: -4px; - vertical-align: baseline; } - /* line 96, ../sass/forms/_elems.scss */ .form .form-row .controls .l-med input[type="text"] { width: 200px; } - /* line 100, ../sass/forms/_elems.scss */ + /* line 93, ../sass/forms/_elems.scss */ .form .form-row .controls .l-small input[type="text"] { width: 50px; } - /* line 104, ../sass/forms/_elems.scss */ + /* line 97, ../sass/forms/_elems.scss */ .form .form-row .controls .l-numeric input[type="text"] { text-align: right; } - /* line 108, ../sass/forms/_elems.scss */ + /* line 101, ../sass/forms/_elems.scss */ .form .form-row .controls .select { margin-right: 5px; } - /* line 113, ../sass/forms/_elems.scss */ + /* line 106, ../sass/forms/_elems.scss */ .form .form-row .field-hints { color: #666666; } - /* line 117, ../sass/forms/_elems.scss */ + /* line 110, ../sass/forms/_elems.scss */ .form .form-row .selector-list { -moz-border-radius: 2px; -webkit-border-radius: 2px; @@ -215,7 +210,7 @@ position: relative; height: 150px; overflow: auto; } - /* line 128, ../sass/forms/_elems.scss */ + /* line 121, ../sass/forms/_elems.scss */ .form .form-row .selector-list .wrapper { overflow-y: auto; position: absolute; @@ -224,24 +219,24 @@ bottom: 5px; left: 5px; } -/* line 142, ../sass/forms/_elems.scss */ +/* line 135, ../sass/forms/_elems.scss */ label.form-control.checkbox input { margin-right: 5px; vertical-align: top; } -/* line 148, ../sass/forms/_elems.scss */ +/* line 141, ../sass/forms/_elems.scss */ .hint, .s-hint { font-size: 0.9em; } -/* line 153, ../sass/forms/_elems.scss */ +/* line 146, ../sass/forms/_elems.scss */ .l-result { display: inline-block; min-width: 32px; min-height: 32px; position: relative; vertical-align: top; } - /* line 160, ../sass/forms/_elems.scss */ + /* line 153, ../sass/forms/_elems.scss */ .l-result div.s-hint { -moz-border-radius: 2px; -webkit-border-radius: 2px; @@ -276,18 +271,17 @@ label.form-control.checkbox input { .edit-main textarea { -moz-appearance: none; -webkit-appearance: none; - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; - -moz-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; - -webkit-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; - box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; + -moz-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; + -webkit-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; + box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; background: rgba(255, 255, 255, 0.1); border: none; - border-bottom: 1px solid rgba(255, 255, 255, 0.1); color: #cccccc; outline: none; padding: 5px; @@ -323,18 +317,17 @@ label.form-control.checkbox input { input[type="text"] { -moz-appearance: none; -webkit-appearance: none; - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; - -moz-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; - -webkit-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; - box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; + -moz-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; + -webkit-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; + box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; background: rgba(255, 255, 255, 0.1); border: none; - border-bottom: 1px solid rgba(255, 255, 255, 0.1); color: #cccccc; outline: none; padding: 0 3px; } @@ -374,9 +367,9 @@ input[type="text"] { background-image: -moz-linear-gradient(#525252, #454545); background-image: -webkit-linear-gradient(#525252, #454545); background-image: linear-gradient(#525252, #454545); - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; @@ -463,18 +456,17 @@ input[type="text"] { .channel-selector .treeview { -moz-appearance: none; -webkit-appearance: none; - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; - -moz-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; - -webkit-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; - box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; + -moz-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; + -webkit-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; + box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; background: rgba(255, 255, 255, 0.1); border: none; - border-bottom: 1px solid rgba(255, 255, 255, 0.1); color: #cccccc; outline: none; padding: 0 3px; diff --git a/platform/commonUI/general/res/css/items.css b/platform/commonUI/general/res/css/items.css index c0ba5edecf..5caa262048 100644 --- a/platform/commonUI/general/res/css/items.css +++ b/platform/commonUI/general/res/css/items.css @@ -69,6 +69,7 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ +/*********************************************** FORM ELEMENTS */ /* @mixin invokeMenu($baseColor: $colorBodyFg) { $c: $baseColor; @@ -115,9 +116,9 @@ background-image: -moz-linear-gradient(#5e5e5e, #525252); background-image: -webkit-linear-gradient(#5e5e5e, #525252); background-image: linear-gradient(#5e5e5e, #525252); - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; @@ -255,9 +256,9 @@ background-image: -moz-linear-gradient(#0ac2ff, #00b4f0); background-image: -webkit-linear-gradient(#0ac2ff, #00b4f0); background-image: linear-gradient(#0ac2ff, #00b4f0); - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; diff --git a/platform/commonUI/general/res/css/theme-espresso.css b/platform/commonUI/general/res/css/theme-espresso.css index e4e1243d5a..b6c9a43edc 100644 --- a/platform/commonUI/general/res/css/theme-espresso.css +++ b/platform/commonUI/general/res/css/theme-espresso.css @@ -169,13 +169,14 @@ article, aside, details, figcaption, figure, footer, header, hgroup, main, menu, * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ +/*********************************************** FORM ELEMENTS */ /* @mixin invokeMenu($baseColor: $colorBodyFg) { - $c: $baseColor; - color: $c; - &:hover { - color: lighten($c, $ltGamma); - } + $c: $baseColor; + color: $c; + &:hover { + color: lighten($c, $ltGamma); + } } */ /***************************************************************************** @@ -316,10 +317,15 @@ input, textarea { font-family: Helvetica, Arial, sans-serif; } /* line 53, ../sass/_global.scss */ +input[type="text"] { + vertical-align: baseline; + padding: 3px 5px !important; } + +/* line 58, ../sass/_global.scss */ h1, h2, h3 { margin: 0; } -/* line 57, ../sass/_global.scss */ +/* line 62, ../sass/_global.scss */ h1 { font-size: 1.7em; font-weight: normal !important; @@ -327,21 +333,21 @@ h1 { margin-bottom: 20px; margin-top: 0; } -/* line 65, ../sass/_global.scss */ +/* line 70, ../sass/_global.scss */ p { margin-bottom: 10px; } -/* line 69, ../sass/_global.scss */ +/* line 74, ../sass/_global.scss */ span { /* 618 DEBUG box-sizing: border-box; */ } -/* line 75, ../sass/_global.scss */ +/* line 80, ../sass/_global.scss */ mct-container { display: block; } -/* line 79, ../sass/_global.scss */ +/* line 84, ../sass/_global.scss */ .abs, .btn-menu span.l-click-area { position: absolute; top: 0; @@ -351,51 +357,51 @@ mct-container { height: auto; width: auto; } -/* line 89, ../sass/_global.scss */ +/* line 94, ../sass/_global.scss */ .code, .codehilite { font-family: "Lucida Console", monospace; font-size: 0.7em; line-height: 150%; white-space: pre; } -/* line 96, ../sass/_global.scss */ +/* line 101, ../sass/_global.scss */ .codehilite { background-color: rgba(255, 255, 255, 0.1); padding: 1em; } -/* line 102, ../sass/_global.scss */ +/* line 107, ../sass/_global.scss */ .align-right { text-align: right; } -/* line 106, ../sass/_global.scss */ +/* line 111, ../sass/_global.scss */ .centered { text-align: center; } -/* line 110, ../sass/_global.scss */ +/* line 115, ../sass/_global.scss */ .no-margin { margin: 0; } -/* line 114, ../sass/_global.scss */ +/* line 119, ../sass/_global.scss */ .colorKey { color: #0099cc; } -/* line 118, ../sass/_global.scss */ +/* line 123, ../sass/_global.scss */ .ds { -moz-box-shadow: rgba(0, 0, 0, 0.7) 0 4px 10px 2px; -webkit-box-shadow: rgba(0, 0, 0, 0.7) 0 4px 10px 2px; box-shadow: rgba(0, 0, 0, 0.7) 0 4px 10px 2px; } -/* line 122, ../sass/_global.scss */ +/* line 127, ../sass/_global.scss */ .hide, .hidden { display: none !important; } -/* line 128, ../sass/_global.scss */ +/* line 133, ../sass/_global.scss */ .paused:not(.s-btn):not(.icon-btn) { border-color: #c56f01 !important; color: #c56f01 !important; } -/* line 134, ../sass/_global.scss */ +/* line 139, ../sass/_global.scss */ .sep { color: rgba(255, 255, 255, 0.2); } @@ -955,67 +961,6 @@ mct-container { .s-text h3 { margin-top: 2em; } -/***************************************************************************** - * 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. - *****************************************************************************/ -/* line 22, ../sass/_badges.scss */ -.badge { - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2ZmZDIzMyIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2ZmYzcwMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; - background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffd233), color-stop(100%, #ffc700)); - background-image: -moz-linear-gradient(#ffd233, #ffc700); - background-image: -webkit-linear-gradient(#ffd233, #ffc700); - background-image: linear-gradient(#ffd233, #ffc700); - color: #333; - display: inline-block; - text-align: center; } - -/* line 29, ../sass/_badges.scss */ -.top-bar .badge { - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - border-radius: 3px; - font-size: 1.4em; - height: 25px; - line-height: 25px; - margin-right: 5px; - width: 35px; - vertical-align: middle; } - -/* line 54, ../sass/_badges.scss */ -.super-menu .badge { - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwYmZmZiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwOTljYyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; - background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #00bfff), color-stop(100%, #0099cc)); - background-image: -moz-linear-gradient(#00bfff, #0099cc); - background-image: -webkit-linear-gradient(#00bfff, #0099cc); - background-image: linear-gradient(#00bfff, #0099cc); - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; - -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px; - -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px; - box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px; - padding: 2px 7px; } - /***************************************************************************** * Open MCT Web, Copyright (c) 2014-2015, United States Government * as represented by the Administrator of the National Aeronautics and Space @@ -1104,27 +1049,27 @@ mct-container { /*.s-limit-upr, .s-limit-lwr { - $a: 0.5; - $l: 30%; - white-space: nowrap; - &:before { - display: inline-block; - font-family: symbolsfont; - font-size: 0.85em; - font-style: normal !important; - margin-right: $interiorMarginSm; - vertical-align: middle; - } + $a: 0.5; + $l: 30%; + white-space: nowrap; + &:before { + display: inline-block; + font-family: symbolsfont; + font-size: 0.85em; + font-style: normal !important; + margin-right: $interiorMarginSm; + vertical-align: middle; + } } .s-limit-upr { - &.s-limit-yellow { @include limit($colorLimitYellow, "\0000ed"); } - &.s-limit-red { @include limit($colorLimitRed, "\0000eb"); } + &.s-limit-yellow { @include limit($colorLimitYellow, "\0000ed"); } + &.s-limit-red { @include limit($colorLimitRed, "\0000eb"); } } .s-limit-lwr { - &.s-limit-yellow { @include limit($colorLimitYellow, "\0000ec"); } - &.s-limit-red { @include limit($colorLimitRed, "\0000ee"); } + &.s-limit-yellow { @include limit($colorLimitYellow, "\0000ec"); } + &.s-limit-red { @include limit($colorLimitRed, "\0000ee"); } }*/ /* line 35, ../sass/_limits.scss */ [class*="s-limit"] { @@ -1206,7 +1151,8 @@ mct-container { height: 100%; } /* line 27, ../sass/lists/_tabular.scss */ -.tabular { +.tabular, +table { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; @@ -1214,98 +1160,187 @@ mct-container { border-collapse: collapse; color: #fff; display: table; - font-size: 0.75em; + font-size: 0.75rem; position: relative; width: 100%; } - /* line 37, ../sass/lists/_tabular.scss */ + /* line 38, ../sass/lists/_tabular.scss */ .tabular thead, .tabular .thead, - .tabular tbody tr, .tabular .tbody .tr { + .tabular tbody tr, .tabular .tbody .tr, + table thead, + table .thead, + table tbody tr, + table .tbody .tr { 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%; - height: 18px; - background: rgba(255, 255, 255, 0.15); } - /* line 58, ../sass/lists/_tabular.scss */ - .tabular tbody, .tabular .tbody { + /* line 44, ../sass/lists/_tabular.scss */ + .tabular thead, .tabular .thead, + table thead, + table .thead { + border-bottom: 1px solid #333; } + /* line 47, ../sass/lists/_tabular.scss */ + .tabular tbody, .tabular .tbody, + table tbody, + table .tbody { 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 { + /* line 54, ../sass/lists/_tabular.scss */ + .tabular tbody tr:hover, .tabular tbody .tr:hover, .tabular .tbody tr:hover, .tabular .tbody .tr:hover, + table tbody tr:hover, + table tbody .tr:hover, + table .tbody tr:hover, + table .tbody .tr:hover { background: rgba(255, 255, 255, 0.1); } - /* line 70, ../sass/lists/_tabular.scss */ - .tabular tr, .tabular .tr { + /* line 59, ../sass/lists/_tabular.scss */ + .tabular tr, .tabular .tr, + table tr, + table .tr { display: table-row; } - /* line 72, ../sass/lists/_tabular.scss */ - .tabular tr:first-child .td, .tabular .tr:first-child .td { + /* line 61, ../sass/lists/_tabular.scss */ + .tabular tr:first-child .td, .tabular .tr:first-child .td, + table tr:first-child .td, + table .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 { + /* line 65, ../sass/lists/_tabular.scss */ + .tabular tr.group-header td, .tabular tr.group-header .td, .tabular .tr.group-header td, .tabular .tr.group-header .td, + table tr.group-header td, + table tr.group-header .td, + table .tr.group-header td, + table .tr.group-header .td { + background-color: #404040; + color: #a6a6a6; } + /* line 71, ../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, + table tr th, + table tr .th, + table tr td, + table tr .td, + table .tr th, + table .tr .th, + table .tr td, + table .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); + /* line 74, ../sass/lists/_tabular.scss */ + .tabular tr th, .tabular tr .th, .tabular .tr th, .tabular .tr .th, + table tr th, + table tr .th, + table .tr th, + table .tr .th { + background-color: #4d4d4d; + border-left: 1px solid #333; color: #b3b3b3; - padding: 0 5px; + padding: 5px 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 { + /* line 81, ../sass/lists/_tabular.scss */ + .tabular tr th:first-child, .tabular tr .th:first-child, .tabular .tr th:first-child, .tabular .tr .th:first-child, + table tr th:first-child, + table tr .th:first-child, + table .tr th:first-child, + table .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 { + /* line 85, ../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, + table tr th.sort .icon-sorting:before, + table tr .th.sort .icon-sorting:before, + table .tr th.sort .icon-sorting:before, + table .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 { + /* line 90, ../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, + table tr th.sort.asc .icon-sorting:before, + table tr .th.sort.asc .icon-sorting:before, + table .tr th.sort.asc .icon-sorting:before, + table .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 { + /* line 93, ../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, + table tr th.sort.desc .icon-sorting:before, + table tr .th.sort.desc .icon-sorting:before, + table .tr th.sort.desc .icon-sorting:before, + table .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; + /* line 98, ../sass/lists/_tabular.scss */ + .tabular tr td, .tabular tr .td, .tabular .tr td, .tabular .tr .td, + table tr td, + table tr .td, + table .tr td, + table .tr .td { + border-bottom: 1px solid rgba(255, 255, 255, 0.1); + min-width: 20px; color: #fff; - padding: 2px 5px; + padding: 3px 5px; + word-wrap: break-word; vertical-align: top; } + /* line 105, ../sass/lists/_tabular.scss */ + .tabular tr td.numeric, .tabular tr .td.numeric, .tabular .tr td.numeric, .tabular .tr .td.numeric, + table tr td.numeric, + table tr .td.numeric, + table .tr td.numeric, + table .tr .td.numeric { + text-align: right; } /* line 108, ../sass/lists/_tabular.scss */ - .tabular tr td.numeric, .tabular tr .td.numeric, .tabular .tr td.numeric, .tabular .tr .td.numeric { + .tabular tr td.s-cell-type-value, .tabular tr .td.s-cell-type-value, .tabular .tr td.s-cell-type-value, .tabular .tr .td.s-cell-type-value, + table tr td.s-cell-type-value, + table tr .td.s-cell-type-value, + table .tr td.s-cell-type-value, + table .tr .td.s-cell-type-value { text-align: right; } - /* line 111, ../sass/lists/_tabular.scss */ - .tabular tr td.s-cell-type-value, .tabular tr .td.s-cell-type-value, .tabular .tr td.s-cell-type-value, .tabular .tr .td.s-cell-type-value { - text-align: right; } - /* line 113, ../sass/lists/_tabular.scss */ - .tabular tr td.s-cell-type-value .l-cell-contents, .tabular tr .td.s-cell-type-value .l-cell-contents, .tabular .tr td.s-cell-type-value .l-cell-contents, .tabular .tr .td.s-cell-type-value .l-cell-contents { + /* line 110, ../sass/lists/_tabular.scss */ + .tabular tr td.s-cell-type-value .l-cell-contents, .tabular tr .td.s-cell-type-value .l-cell-contents, .tabular .tr td.s-cell-type-value .l-cell-contents, .tabular .tr .td.s-cell-type-value .l-cell-contents, + table tr td.s-cell-type-value .l-cell-contents, + table tr .td.s-cell-type-value .l-cell-contents, + table .tr td.s-cell-type-value .l-cell-contents, + table .tr .td.s-cell-type-value .l-cell-contents { -moz-border-radius: 2px; -webkit-border-radius: 2px; border-radius: 2px; padding-left: 5px; padding-right: 5px; } - /* line 122, ../sass/lists/_tabular.scss */ - .tabular.filterable tbody, .tabular.filterable .tbody { - top: 36px; } - /* line 127, ../sass/lists/_tabular.scss */ - .tabular.fixed-header { + /* line 126, ../sass/lists/_tabular.scss */ + .tabular.filterable tbody, .tabular.filterable .tbody, + table.filterable tbody, + table.filterable .tbody { + top: 44px; } + /* line 129, ../sass/lists/_tabular.scss */ + .tabular.filterable input[type="text"], + table.filterable input[type="text"] { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + width: 100%; } + /* line 135, ../sass/lists/_tabular.scss */ + .tabular.fixed-header, + table.fixed-header { height: 100%; } - /* line 129, ../sass/lists/_tabular.scss */ + /* line 137, ../sass/lists/_tabular.scss */ .tabular.fixed-header thead, .tabular.fixed-header .thead, - .tabular.fixed-header tbody tr, .tabular.fixed-header .tbody .tr { + .tabular.fixed-header tbody tr, .tabular.fixed-header .tbody .tr, + table.fixed-header thead, + table.fixed-header .thead, + table.fixed-header tbody tr, + table.fixed-header .tbody .tr { display: table; table-layout: fixed; } - /* line 134, ../sass/lists/_tabular.scss */ - .tabular.fixed-header thead, .tabular.fixed-header .thead { + /* line 142, ../sass/lists/_tabular.scss */ + .tabular.fixed-header thead, .tabular.fixed-header .thead, + table.fixed-header thead, + table.fixed-header .thead { width: calc(100% - 10px); } - /* line 137, ../sass/lists/_tabular.scss */ - .tabular.fixed-header tbody, .tabular.fixed-header .tbody { + /* line 144, ../sass/lists/_tabular.scss */ + .tabular.fixed-header thead:before, .tabular.fixed-header .thead:before, + table.fixed-header thead:before, + table.fixed-header .thead:before { + content: ""; + display: block; + z-index: 0; + position: absolute; + width: 100%; + height: 22px; + background: rgba(255, 255, 255, 0.15); } + /* line 154, ../sass/lists/_tabular.scss */ + .tabular.fixed-header tbody, .tabular.fixed-header .tbody, + table.fixed-header tbody, + table.fixed-header .tbody { overflow: hidden; position: absolute; top: 0; @@ -1314,11 +1349,13 @@ mct-container { left: 0; width: auto; height: auto; - top: 18px; + top: 22px; display: block; overflow-y: scroll; } - /* line 145, ../sass/lists/_tabular.scss */ - .tabular.t-event-messages td, .tabular.t-event-messages .td { + /* line 162, ../sass/lists/_tabular.scss */ + .tabular.t-event-messages td, .tabular.t-event-messages .td, + table.t-event-messages td, + table.t-event-messages .td { min-width: 150px; } /* line 1, ../sass/controls/_breadcrumb.scss */ @@ -1418,9 +1455,9 @@ mct-container { .s-btn, .icon-btn, .s-icon-btn { - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; @@ -1438,9 +1475,9 @@ mct-container { background-image: -moz-linear-gradient(#0ac2ff, #00b4f0); background-image: -webkit-linear-gradient(#0ac2ff, #00b4f0); background-image: linear-gradient(#0ac2ff, #00b4f0); - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; @@ -1487,9 +1524,9 @@ mct-container { background-image: -moz-linear-gradient(#24c8ff, #0ac2ff); background-image: -webkit-linear-gradient(#24c8ff, #0ac2ff); background-image: linear-gradient(#24c8ff, #0ac2ff); - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; @@ -1541,9 +1578,9 @@ mct-container { background-image: -moz-linear-gradient(#858585, #787878); background-image: -webkit-linear-gradient(#858585, #787878); background-image: linear-gradient(#858585, #787878); - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; @@ -1592,9 +1629,9 @@ mct-container { background-image: -moz-linear-gradient(#525252, #454545); background-image: -webkit-linear-gradient(#525252, #454545); background-image: linear-gradient(#525252, #454545); - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; @@ -1652,9 +1689,9 @@ mct-container { background-image: -moz-linear-gradient(#fe9105, #e98301); background-image: -webkit-linear-gradient(#fe9105, #e98301); background-image: linear-gradient(#fe9105, #e98301); - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; @@ -1735,11 +1772,11 @@ mct-container { /* line 132, ../sass/controls/_buttons.scss */ .icon-btn.pause-play, .s-icon-btn.pause-play { - /* &.paused { - .icon { - @include pulse(500ms); - } - }*/ } + /* &.paused { + .icon { + @include pulse(500ms); + } + }*/ } /* line 138, ../sass/controls/_buttons.scss */ .icon-btn.pause-play .icon:before, .s-icon-btn.pause-play .icon:before { @@ -1862,32 +1899,32 @@ a.l-btn span { * at runtime from the About dialog for additional information. *****************************************************************************/ /*.control { - // UNUSED? - &.view-control { - .icon { - display: inline-block; - margin: -1px 5px 1px 2px; - vertical-align: middle; - &.triangle-down { - margin: 2px 2px -2px 0px; - } - } + // UNUSED? + &.view-control { + .icon { + display: inline-block; + margin: -1px 5px 1px 2px; + vertical-align: middle; + &.triangle-down { + margin: 2px 2px -2px 0px; + } + } - .label { - display: inline-block; - font-size: 11px; - vertical-align: middle; - } + .label { + display: inline-block; + font-size: 11px; + vertical-align: middle; + } - .toggle { - @include border-radius(3px); - display: inline-block; - padding: 1px 6px 4px 4px; - &:hover { - background: rgba(white, 0.1); - } - } - } + .toggle { + @include border-radius(3px); + display: inline-block; + padding: 1px 6px 4px 4px; + &:hover { + background: rgba(white, 0.1); + } + } + } }*/ /* line 51, ../sass/controls/_controls.scss */ .accordion { @@ -1997,21 +2034,21 @@ a.l-btn span { .btn-set .btn:first-child, .btn-set .t-btn:first-child { border-left: none; - -moz-border-radius-topleft: 2px; - -webkit-border-top-left-radius: 2px; - border-top-left-radius: 2px; - -moz-border-radius-bottomleft: 2px; - -webkit-border-bottom-left-radius: 2px; - border-bottom-left-radius: 2px; } + -moz-border-radius-topleft: 3px; + -webkit-border-top-left-radius: 3px; + border-top-left-radius: 3px; + -moz-border-radius-bottomleft: 3px; + -webkit-border-bottom-left-radius: 3px; + border-bottom-left-radius: 3px; } /* line 169, ../sass/controls/_controls.scss */ .btn-set .btn:last-child, .btn-set .t-btn:last-child { - -moz-border-radius-topright: 2px; - -webkit-border-top-right-radius: 2px; - border-top-right-radius: 2px; - -moz-border-radius-bottomright: 2px; - -webkit-border-bottom-right-radius: 2px; - border-bottom-right-radius: 2px; } + -moz-border-radius-topright: 3px; + -webkit-border-top-right-radius: 3px; + border-top-right-radius: 3px; + -moz-border-radius-bottomright: 3px; + -webkit-border-bottom-right-radius: 3px; + border-bottom-right-radius: 3px; } /* line 175, ../sass/controls/_controls.scss */ .object-browse-bar .btn, @@ -2111,9 +2148,9 @@ label.checkbox.custom { background-image: -moz-linear-gradient(#525252, #454545); background-image: -webkit-linear-gradient(#525252, #454545); background-image: linear-gradient(#525252, #454545); - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; @@ -2124,23 +2161,23 @@ label.checkbox.custom { border-top: 1px solid #575757; color: #999; display: inline-block; - /* height: $h; - line-height: $h; - &.dropdown { - padding-left: $p; - padding-right: $p; - }*/ - /* &.context-available { - // An element like the invoke-menu triangle; - // Indicates that this element has a dropdown menu available; - // Currently unused - $c: $colorKey; - color: $c; - padding: 0 5px; - &:hover { - color: lighten($c, 10%); - } - }*/ } + /* height: $h; + line-height: $h; + &.dropdown { + padding-left: $p; + padding-right: $p; + }*/ + /* &.context-available { + // An element like the invoke-menu triangle; + // Indicates that this element has a dropdown menu available; + // Currently unused + $c: $colorKey; + color: $c; + padding: 0 5px; + &:hover { + color: lighten($c, 10%); + } + }*/ } /* line 162, ../sass/_mixins.scss */ .btn-menu:not(.disabled):hover { background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzYzNjM2MyIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzU3NTc1NyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); @@ -2182,9 +2219,9 @@ label.checkbox.custom { padding-left: 25px; } /* line 335, ../sass/controls/_controls.scss */ .top-bar .btn-menu.browse-btn .badge { - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - border-radius: 3px; + -moz-border-radius: 4.5px; + -webkit-border-radius: 4.5px; + border-radius: 4.5px; display: block; font-size: 1em; line-height: 15px; @@ -2278,9 +2315,9 @@ label.checkbox.custom { background-image: -moz-linear-gradient(#525252, #454545); background-image: -webkit-linear-gradient(#525252, #454545); background-image: linear-gradient(#525252, #454545); - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; @@ -2492,9 +2529,9 @@ label.checkbox.custom { background-image: -moz-linear-gradient(#5e5e5e, #525252); background-image: -webkit-linear-gradient(#5e5e5e, #525252); background-image: linear-gradient(#5e5e5e, #525252); - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; @@ -2517,7 +2554,7 @@ label.checkbox.custom { .menu-element .menu ul { margin: 0; padding: 0; } - /* line 276, ../sass/_mixins.scss */ + /* line 308, ../sass/_mixins.scss */ .menu-element .menu ul li { list-style-type: none; margin: 0; @@ -2555,9 +2592,9 @@ label.checkbox.custom { background-image: -moz-linear-gradient(#8c8c8c, #808080); background-image: -webkit-linear-gradient(#8c8c8c, #808080); background-image: linear-gradient(#8c8c8c, #808080); - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; @@ -2623,9 +2660,9 @@ label.checkbox.custom { overflow-y: auto; } /* line 119, ../sass/controls/_menus.scss */ .menu-element .super-menu .pane.left ul li { - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; padding-left: 30px; border-top: none; } /* line 126, ../sass/controls/_menus.scss */ @@ -3116,27 +3153,6 @@ label.checkbox.custom { font-size: 0.65em; vertical-align: top; } -/***************************************************************************** - * 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. - *****************************************************************************/ /***************************************************************************** * Open MCT Web, Copyright (c) 2014-2015, United States Government * as represented by the Administrator of the National Aeronautics and Space @@ -3220,27 +3236,21 @@ label.checkbox.custom { line-height: 14px; margin-right: 5px; } /* line 89, ../sass/forms/_elems.scss */ - .form .form-row .controls input[type="text"] { - height: 22px; - line-height: 22px; - margin-top: -4px; - vertical-align: baseline; } - /* line 96, ../sass/forms/_elems.scss */ .form .form-row .controls .l-med input[type="text"] { width: 200px; } - /* line 100, ../sass/forms/_elems.scss */ + /* line 93, ../sass/forms/_elems.scss */ .form .form-row .controls .l-small input[type="text"] { width: 50px; } - /* line 104, ../sass/forms/_elems.scss */ + /* line 97, ../sass/forms/_elems.scss */ .form .form-row .controls .l-numeric input[type="text"] { text-align: right; } - /* line 108, ../sass/forms/_elems.scss */ + /* line 101, ../sass/forms/_elems.scss */ .form .form-row .controls .select { margin-right: 5px; } - /* line 113, ../sass/forms/_elems.scss */ + /* line 106, ../sass/forms/_elems.scss */ .form .form-row .field-hints { color: #666666; } - /* line 117, ../sass/forms/_elems.scss */ + /* line 110, ../sass/forms/_elems.scss */ .form .form-row .selector-list { -moz-border-radius: 2px; -webkit-border-radius: 2px; @@ -3253,7 +3263,7 @@ label.checkbox.custom { position: relative; height: 150px; overflow: auto; } - /* line 128, ../sass/forms/_elems.scss */ + /* line 121, ../sass/forms/_elems.scss */ .form .form-row .selector-list .wrapper { overflow-y: auto; position: absolute; @@ -3262,24 +3272,24 @@ label.checkbox.custom { bottom: 5px; left: 5px; } -/* line 142, ../sass/forms/_elems.scss */ +/* line 135, ../sass/forms/_elems.scss */ label.form-control.checkbox input { margin-right: 5px; vertical-align: top; } -/* line 148, ../sass/forms/_elems.scss */ +/* line 141, ../sass/forms/_elems.scss */ .hint, .s-hint { font-size: 0.9em; } -/* line 153, ../sass/forms/_elems.scss */ +/* line 146, ../sass/forms/_elems.scss */ .l-result { display: inline-block; min-width: 32px; min-height: 32px; position: relative; vertical-align: top; } - /* line 160, ../sass/forms/_elems.scss */ + /* line 153, ../sass/forms/_elems.scss */ .l-result div.s-hint { -moz-border-radius: 2px; -webkit-border-radius: 2px; @@ -3373,22 +3383,21 @@ span.req { input[type="text"] { -moz-appearance: none; -webkit-appearance: none; - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; - -moz-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; - -webkit-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; - box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; + -moz-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; + -webkit-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; + box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; background: rgba(255, 255, 255, 0.1); border: none; - border-bottom: 1px solid rgba(255, 255, 255, 0.1); color: #cccccc; outline: none; padding: 0 3px; } - /* line 33, ../sass/forms/_mixins.scss */ + /* line 274, ../sass/_mixins.scss */ input[type="text"].error { background: rgba(255, 0, 0, 0.5); } /* line 29, ../sass/forms/_text-input.scss */ @@ -3424,9 +3433,9 @@ input[type="text"] { background-image: -moz-linear-gradient(#525252, #454545); background-image: -webkit-linear-gradient(#525252, #454545); background-image: linear-gradient(#525252, #454545); - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; @@ -3513,18 +3522,17 @@ input[type="text"] { .channel-selector .treeview { -moz-appearance: none; -webkit-appearance: none; - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; - -moz-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; - -webkit-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; - box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; + -moz-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; + -webkit-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; + box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; background: rgba(255, 255, 255, 0.1); border: none; - border-bottom: 1px solid rgba(255, 255, 255, 0.1); color: #cccccc; outline: none; padding: 0 3px; @@ -3534,7 +3542,7 @@ input[type="text"] { max-height: 400px; overflow: auto; padding: 5px; } - /* line 33, ../sass/forms/_mixins.scss */ + /* line 274, ../sass/_mixins.scss */ .channel-selector .treeview.error { background: rgba(255, 0, 0, 0.5); } /* line 36, ../sass/forms/_channel-selector.scss */ @@ -3618,24 +3626,23 @@ input[type="text"] { .t-filter input.t-filter-input { -moz-appearance: none; -webkit-appearance: none; - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; - -moz-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; - -webkit-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; - box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; + -moz-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; + -webkit-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; + box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; background: rgba(255, 255, 255, 0.1); border: none; - border-bottom: 1px solid rgba(255, 255, 255, 0.1); color: #cccccc; outline: none; padding: 0 3px; background: #3b3b3b; border-bottom: 1px solid #4d4d4d; } - /* line 33, ../sass/forms/_mixins.scss */ + /* line 274, ../sass/_mixins.scss */ .filter input.filter.error, .filter input.t-filter-input.error, .t-filter input.filter.error, @@ -3653,9 +3660,9 @@ input[type="text"] { /* line 42, ../sass/forms/_filter.scss */ .filter .icon.ui-symbol, .t-filter .icon.ui-symbol { - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; display: inline-block; font-size: 1.3em; height: 22px; @@ -3669,9 +3676,9 @@ input[type="text"] { /* line 54, ../sass/forms/_filter.scss */ .filter .s-a-clear.ui-symbol, .t-filter .s-a-clear.ui-symbol { - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; @@ -3769,9 +3776,9 @@ input[type="text"] { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; background: black; color: #e6e6e6; padding: 2px 5px; @@ -4051,9 +4058,9 @@ input[type="text"] { background-image: -moz-linear-gradient(#525252, #454545); background-image: -webkit-linear-gradient(#525252, #454545); background-image: linear-gradient(#525252, #454545); - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; @@ -4746,27 +4753,34 @@ input[type="text"] { margin-top: -5%; margin-left: -5%; z-index: 2; } + /* line 53, ../sass/helpers/_wait-spinner.scss */ + .t-wait-spinner.inline, + .wait-spinner.inline { + display: inline-block !important; + margin-right: 5px; + position: relative !important; + vertical-align: middle; } -/* line 55, ../sass/helpers/_wait-spinner.scss */ +/* line 61, ../sass/helpers/_wait-spinner.scss */ .l-wait-spinner-holder { pointer-events: none; position: absolute; } - /* line 59, ../sass/helpers/_wait-spinner.scss */ + /* line 65, ../sass/helpers/_wait-spinner.scss */ .l-wait-spinner-holder.align-left .t-wait-spinner { left: 0; margin-left: 0; } - /* line 64, ../sass/helpers/_wait-spinner.scss */ + /* line 70, ../sass/helpers/_wait-spinner.scss */ .l-wait-spinner-holder.full-size { display: inline-block; height: 100%; width: 100%; } - /* line 67, ../sass/helpers/_wait-spinner.scss */ + /* line 73, ../sass/helpers/_wait-spinner.scss */ .l-wait-spinner-holder.full-size .t-wait-spinner { top: 0; margin-top: 0; padding: 30%; } -/* line 76, ../sass/helpers/_wait-spinner.scss */ +/* line 82, ../sass/helpers/_wait-spinner.scss */ .treeview .wait-spinner { display: block; position: absolute; @@ -4786,6 +4800,27 @@ input[type="text"] { top: 2px; left: 0; } +/* line 91, ../sass/helpers/_wait-spinner.scss */ +.wait-spinner.sm { + display: block; + position: absolute; + -webkit-animation: rotation .6s infinite linear; + -moz-animation: rotation .6s infinite linear; + -o-animation: rotation .6s infinite linear; + animation: rotation .6s infinite linear; + border-color: rgba(0, 153, 204, 0.25); + border-top-color: #0099cc; + border-style: solid; + border-width: 0.25em; + border-radius: 100%; + height: 13px; + width: 13px; + margin-left: 0 !important; + margin-top: 0 !important; + padding: 0 !important; + top: 0; + left: 0; } + /***************************************************************************** * Open MCT Web, Copyright (c) 2014-2015, United States Government * as represented by the Administrator of the National Aeronautics and Space @@ -4990,6 +5025,18 @@ input[type="text"] { height: 100%; width: 100%; } +/* Styles for messages */ +/* line 4, ../sass/_messages.scss */ +.message.block { + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + border-radius: 2px; + padding: 10px; } +/* line 8, ../sass/_messages.scss */ +.message.error { + background-color: rgba(255, 60, 0, 0.3); + color: #ff8a66; } + /* line 5, ../sass/_initialization.scss */ .browse-mode .split-layout .split-pane-component.pane.left { width: 15%; } @@ -5029,3 +5076,31 @@ input[type="text"] { /* line 32, ../sass/_hide-non-functional.scss */ .browse-mode .browse-area.holder { top: 10px; } + +/* Styles for sub-dividing views generically */ +/* line 3, ../sass/_views.scss */ +.l-view-section { + overflow: hidden; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + width: auto; + height: auto; + font-size: 0.8rem; } + /* line 6, ../sass/_views.scss */ + .l-view-section h2 { + color: #fff; + margin-bottom: 5px; } + /* line 10, ../sass/_views.scss */ + .l-view-section.fixed { + font-size: 0.8em; } + /* line 13, ../sass/_views.scss */ + .l-view-section.scrolling { + overflow: auto; } + /* line 16, ../sass/_views.scss */ + .l-view-section .controls, + .l-view-section label, + .l-view-section .inline-block { + display: inline-block; } diff --git a/platform/commonUI/general/res/css/tree.css b/platform/commonUI/general/res/css/tree.css index e7400b5d04..8f3ac4871a 100644 --- a/platform/commonUI/general/res/css/tree.css +++ b/platform/commonUI/general/res/css/tree.css @@ -69,6 +69,7 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ +/*********************************************** FORM ELEMENTS */ /* @mixin invokeMenu($baseColor: $colorBodyFg) { $c: $baseColor; @@ -103,7 +104,7 @@ ul.tree { margin: 0; padding: 0; } - /* line 276, ../sass/_mixins.scss */ + /* line 308, ../sass/_mixins.scss */ ul.tree li { list-style-type: none; margin: 0; diff --git a/platform/commonUI/general/res/fonts/symbols/iconmoon.io-WTD-Symbols-v2.0.json b/platform/commonUI/general/res/fonts/symbols/icomoon.io-WTD-symbols-project.json similarity index 99% rename from platform/commonUI/general/res/fonts/symbols/iconmoon.io-WTD-Symbols-v2.0.json rename to platform/commonUI/general/res/fonts/symbols/icomoon.io-WTD-symbols-project.json index e2215bed12..502ce67f79 100644 --- a/platform/commonUI/general/res/fonts/symbols/iconmoon.io-WTD-Symbols-v2.0.json +++ b/platform/commonUI/general/res/fonts/symbols/icomoon.io-WTD-symbols-project.json @@ -1,19 +1,59 @@ { "metadata": { - "name": "WTD Symbols v2.", - "lastOpened": 1435765696898, - "created": 1435764071891 + "name": "WTD Symbols v2.1", + "lastOpened": 1439844340068, + "created": 1439844318831 }, "iconSets": [ { "selection": [ + { + "order": 77, + "id": 83, + "prevSize": 32, + "code": 58881, + "name": "icon-datatable", + "tempChar": "" + }, + { + "order": 78, + "id": 82, + "prevSize": 32, + "code": 58882, + "name": "icon-tabular-scrolling", + "tempChar": "" + }, + { + "order": 79, + "id": 81, + "prevSize": 32, + "code": 58884, + "name": "icon-tabular", + "tempChar": "" + }, + { + "order": 80, + "id": 80, + "prevSize": 32, + "code": 58885, + "name": "icon-calendar", + "tempChar": "" + }, + { + "order": 81, + "id": 78, + "prevSize": 32, + "code": 58886, + "name": "icon-paint-bucket", + "tempChar": "" + }, { "order": 1, "id": 75, "prevSize": 32, "code": 123, "name": "icon-pointer-left", - "tempChar": "" + "tempChar": "" }, { "order": 3, @@ -21,7 +61,7 @@ "prevSize": 32, "code": 125, "name": "icon-pointer-right", - "tempChar": "" + "tempChar": "" }, { "order": 4, @@ -29,7 +69,7 @@ "prevSize": 32, "code": 80, "name": "icon-person", - "tempChar": "" + "tempChar": "" }, { "order": 5, @@ -37,7 +77,7 @@ "prevSize": 32, "code": 232, "name": "icon-chain-links", - "tempChar": "" + "tempChar": "" }, { "order": 6, @@ -45,7 +85,7 @@ "prevSize": 32, "code": 115, "name": "icon-database-in-brackets", - "tempChar": "" + "tempChar": "" }, { "order": 7, @@ -53,7 +93,7 @@ "prevSize": 32, "code": 114, "name": "icon-refresh", - "tempChar": "" + "tempChar": "" }, { "order": 8, @@ -61,7 +101,7 @@ "prevSize": 32, "code": 108, "name": "icon-lock", - "tempChar": "" + "tempChar": "" }, { "order": 9, @@ -69,7 +109,7 @@ "prevSize": 32, "code": 51, "name": "icon-box-with-dashed-lines", - "tempChar": "" + "tempChar": "" }, { "order": 10, @@ -77,7 +117,7 @@ "prevSize": 32, "code": 58880, "name": "icon-box-with-arrow-cursor", - "tempChar": "" + "tempChar": "" }, { "order": 11, @@ -85,7 +125,7 @@ "prevSize": 32, "code": 65, "name": "icon-activity-mode", - "tempChar": "" + "tempChar": "" }, { "order": 12, @@ -93,7 +133,7 @@ "prevSize": 32, "code": 97, "name": "icon-activity", - "tempChar": "" + "tempChar": "" }, { "order": 13, @@ -101,7 +141,7 @@ "prevSize": 32, "code": 33, "name": "icon-alert-rect", - "tempChar": "" + "tempChar": "" }, { "order": 14, @@ -109,7 +149,7 @@ "prevSize": 32, "code": 58883, "name": "icon-alert-triangle", - "tempChar": "" + "tempChar": "" }, { "order": 15, @@ -117,7 +157,7 @@ "prevSize": 32, "code": 238, "name": "icon-arrow-double-down", - "tempChar": "" + "tempChar": "" }, { "order": 16, @@ -125,7 +165,7 @@ "prevSize": 32, "code": 235, "name": "icon-arrow-double-up", - "tempChar": "" + "tempChar": "" }, { "order": 2, @@ -133,7 +173,7 @@ "prevSize": 32, "code": 118, "name": "icon-arrow-down", - "tempChar": "" + "tempChar": "" }, { "order": 19, @@ -141,7 +181,7 @@ "prevSize": 32, "code": 60, "name": "icon-arrow-left", - "tempChar": "" + "tempChar": "" }, { "order": 20, @@ -149,7 +189,7 @@ "prevSize": 32, "code": 62, "name": "icon-arrow-right", - "tempChar": "" + "tempChar": "" }, { "order": 21, @@ -157,7 +197,7 @@ "prevSize": 32, "code": 236, "name": "icon-arrow-tall-down", - "tempChar": "" + "tempChar": "" }, { "order": 22, @@ -165,7 +205,7 @@ "prevSize": 32, "code": 237, "name": "icon-arrow-tall-up", - "tempChar": "" + "tempChar": "" }, { "order": 23, @@ -173,7 +213,7 @@ "prevSize": 32, "code": 94, "name": "icon-arrow-up", - "tempChar": "" + "tempChar": "" }, { "order": 24, @@ -181,7 +221,7 @@ "prevSize": 32, "code": 73, "name": "icon-arrows-out", - "tempChar": "" + "tempChar": "" }, { "order": 25, @@ -189,7 +229,7 @@ "prevSize": 32, "code": 58893, "name": "icon-arrows-right-left", - "tempChar": "" + "tempChar": "" }, { "order": 33, @@ -197,7 +237,7 @@ "prevSize": 32, "code": 53, "name": "icon-arrows-up-down", - "tempChar": "" + "tempChar": "" }, { "order": 26, @@ -205,7 +245,7 @@ "prevSize": 32, "code": 42, "name": "icon-asterisk", - "tempChar": "" + "tempChar": "" }, { "order": 27, @@ -213,7 +253,7 @@ "prevSize": 32, "code": 72, "name": "icon-autoflow-tabular", - "tempChar": "" + "tempChar": "" }, { "order": 28, @@ -221,7 +261,7 @@ "prevSize": 32, "code": 224, "name": "icon-box-round-corners", - "tempChar": "" + "tempChar": "" }, { "order": 29, @@ -229,7 +269,7 @@ "prevSize": 32, "code": 50, "name": "icon-check", - "tempChar": "" + "tempChar": "" }, { "order": 30, @@ -237,7 +277,7 @@ "prevSize": 32, "code": 67, "name": "icon-clock", - "tempChar": "" + "tempChar": "" }, { "order": 31, @@ -245,7 +285,7 @@ "prevSize": 32, "code": 46, "name": "icon-connectivity", - "tempChar": "" + "tempChar": "" }, { "order": 32, @@ -253,7 +293,7 @@ "prevSize": 32, "code": 100, "name": "icon-database-query", - "tempChar": "" + "tempChar": "" }, { "order": 17, @@ -261,7 +301,7 @@ "prevSize": 32, "code": 68, "name": "icon-database", - "tempChar": "" + "tempChar": "" }, { "order": 35, @@ -269,7 +309,7 @@ "prevSize": 32, "code": 81, "name": "icon-dictionary", - "tempChar": "" + "tempChar": "" }, { "order": 36, @@ -277,7 +317,7 @@ "prevSize": 32, "code": 242, "name": "icon-duplicate", - "tempChar": "" + "tempChar": "" }, { "order": 37, @@ -285,7 +325,7 @@ "prevSize": 32, "code": 102, "name": "icon-folder-new", - "tempChar": "" + "tempChar": "" }, { "order": 38, @@ -293,7 +333,7 @@ "prevSize": 32, "code": 70, "name": "icon-folder", - "tempChar": "" + "tempChar": "" }, { "order": 39, @@ -301,7 +341,7 @@ "prevSize": 32, "code": 95, "name": "icon-fullscreen-collapse", - "tempChar": "" + "tempChar": "" }, { "order": 40, @@ -309,7 +349,7 @@ "prevSize": 32, "code": 122, "name": "icon-fullscreen-expand", - "tempChar": "" + "tempChar": "" }, { "order": 41, @@ -317,7 +357,7 @@ "prevSize": 32, "code": 71, "name": "icon-gear", - "tempChar": "" + "tempChar": "" }, { "order": 49, @@ -325,7 +365,7 @@ "prevSize": 32, "code": 227, "name": "icon-image", - "tempChar": "" + "tempChar": "" }, { "order": 42, @@ -333,7 +373,7 @@ "prevSize": 32, "code": 225, "name": "icon-layers", - "tempChar": "" + "tempChar": "" }, { "order": 43, @@ -341,7 +381,7 @@ "prevSize": 32, "code": 76, "name": "icon-layout", - "tempChar": "" + "tempChar": "" }, { "order": 44, @@ -349,7 +389,7 @@ "prevSize": 32, "code": 226, "name": "icon-line-horz", - "tempChar": "" + "tempChar": "" }, { "order": 75, @@ -357,7 +397,7 @@ "prevSize": 32, "code": 244, "name": "icon-link", - "tempChar": "" + "tempChar": "" }, { "order": 46, @@ -365,7 +405,7 @@ "prevSize": 32, "code": 88, "name": "icon-magnify-in", - "tempChar": "" + "tempChar": "" }, { "order": 47, @@ -373,7 +413,7 @@ "prevSize": 32, "code": 89, "name": "icon-magnify-out", - "tempChar": "" + "tempChar": "" }, { "order": 48, @@ -381,7 +421,7 @@ "prevSize": 32, "code": 77, "name": "icon-magnify", - "tempChar": "" + "tempChar": "" }, { "order": 34, @@ -389,7 +429,7 @@ "prevSize": 32, "code": 109, "name": "icon-menu", - "tempChar": "" + "tempChar": "" }, { "order": 50, @@ -397,7 +437,7 @@ "prevSize": 32, "code": 243, "name": "icon-move", - "tempChar": "" + "tempChar": "" }, { "order": 51, @@ -405,7 +445,7 @@ "prevSize": 32, "code": 121, "name": "icon-new-window", - "tempChar": "" + "tempChar": "" }, { "order": 52, @@ -413,7 +453,7 @@ "prevSize": 32, "code": 111, "name": "icon-object", - "tempChar": "" + "tempChar": "" }, { "order": 73, @@ -421,7 +461,7 @@ "prevSize": 32, "code": 63, "name": "icon-object-unknown", - "tempChar": "" + "tempChar": "" }, { "order": 53, @@ -429,7 +469,7 @@ "prevSize": 32, "code": 86, "name": "icon-packet", - "tempChar": "" + "tempChar": "" }, { "order": 54, @@ -437,7 +477,7 @@ "prevSize": 32, "code": 234, "name": "icon-page", - "tempChar": "" + "tempChar": "" }, { "order": 55, @@ -445,7 +485,7 @@ "prevSize": 32, "code": 241, "name": "icon-pause", - "tempChar": "" + "tempChar": "" }, { "order": 56, @@ -453,7 +493,7 @@ "prevSize": 32, "code": 112, "name": "icon-pencil", - "tempChar": "" + "tempChar": "" }, { "order": 65, @@ -461,7 +501,7 @@ "prevSize": 32, "code": 79, "name": "icon-people", - "tempChar": "" + "tempChar": "" }, { "order": 57, @@ -469,7 +509,7 @@ "prevSize": 32, "code": 239, "name": "icon-play", - "tempChar": "" + "tempChar": "" }, { "order": 58, @@ -477,7 +517,7 @@ "prevSize": 32, "code": 233, "name": "icon-plot-resource", - "tempChar": "" + "tempChar": "" }, { "order": 59, @@ -485,7 +525,7 @@ "prevSize": 32, "code": 43, "name": "icon-plus", - "tempChar": "" + "tempChar": "" }, { "order": 60, @@ -493,7 +533,7 @@ "prevSize": 32, "code": 45, "name": "icon-minus", - "tempChar": "" + "tempChar": "" }, { "order": 61, @@ -501,7 +541,7 @@ "prevSize": 32, "code": 54, "name": "icon-sine", - "tempChar": "" + "tempChar": "" }, { "order": 62, @@ -509,7 +549,7 @@ "prevSize": 32, "code": 228, "name": "icon-T", - "tempChar": "" + "tempChar": "" }, { "order": 63, @@ -517,7 +557,7 @@ "prevSize": 32, "code": 116, "name": "icon-telemetry-panel", - "tempChar": "" + "tempChar": "" }, { "order": 64, @@ -525,7 +565,7 @@ "prevSize": 32, "code": 84, "name": "icon-telemetry", - "tempChar": "" + "tempChar": "" }, { "order": 18, @@ -533,7 +573,7 @@ "prevSize": 32, "code": 246, "name": "icon-thumbs-strip", - "tempChar": "" + "tempChar": "" }, { "order": 67, @@ -541,7 +581,7 @@ "prevSize": 32, "code": 83, "name": "icon-timeline", - "tempChar": "" + "tempChar": "" }, { "order": 68, @@ -549,7 +589,7 @@ "prevSize": 32, "code": 245, "name": "icon-timer", - "tempChar": "" + "tempChar": "" }, { "order": 69, @@ -557,7 +597,7 @@ "prevSize": 32, "code": 90, "name": "icon-trash", - "tempChar": "" + "tempChar": "" }, { "order": 70, @@ -565,7 +605,7 @@ "prevSize": 32, "code": 229, "name": "icon-two-parts-both", - "tempChar": "" + "tempChar": "" }, { "order": 71, @@ -573,7 +613,7 @@ "prevSize": 32, "code": 231, "name": "icon-two-parts-one-only", - "tempChar": "" + "tempChar": "" }, { "order": 72, @@ -581,7 +621,7 @@ "prevSize": 32, "code": 120, "name": "icon-x-heavy", - "tempChar": "" + "tempChar": "" }, { "order": 66, @@ -589,7 +629,7 @@ "prevSize": 32, "code": 58946, "name": "icon-x", - "tempChar": "" + "tempChar": "" } ], "id": 2, @@ -604,6 +644,182 @@ "height": 1024, "prevSize": 32, "icons": [ + { + "id": 83, + "paths": [ + "M1024 192c0 106.039-229.23 192-512 192s-512-85.961-512-192c0-106.039 229.23-192 512-192s512 85.961 512 192z", + "M512 512c-282.8 0-512-86-512-192v512c0 106 229.2 192 512 192s512-86 512-192v-512c0 106-229.2 192-512 192zM896 575v256c-36.6 15.6-79.8 28.8-128 39.4v-256c48.2-10.6 91.4-23.8 128-39.4zM256 614.4v256c-48.2-10.4-91.4-23.8-128-39.4v-256c36.6 15.6 79.8 28.8 128 39.4zM384 890v-256c41 4 83.8 6 128 6s87-2.2 128-6v256c-41 4-83.8 6-128 6s-87-2.2-128-6z" + ], + "attrs": [ + { + "fill": "rgb(6,161,75)", + "opacity": 1 + }, + { + "fill": "rgb(6,161,75)", + "opacity": 1 + } + ], + "isMulticolor": false, + "grid": 0, + "tags": [ + "icon-datatable" + ], + "colorPermutations": { + "125525525516161751": [ + 1, + 1 + ] + } + }, + { + "id": 82, + "paths": [ + "M64 0c-35.2 0-64 28.8-64 64v192h448v-256h-384z", + "M1024 256v-192c0-35.2-28.8-64-64-64h-384v256h448z", + "M0 384v192c0 35.2 28.8 64 64 64h384v-256h-448z", + "M960 640c35.2 0 64-28.8 64-64v-192h-448v256h384z", + "M512 1024l-256-256h512z" + ], + "attrs": [ + { + "fill": "rgb(6,161,75)", + "opacity": 1 + }, + { + "fill": "rgb(6,161,75)", + "opacity": 1 + }, + { + "fill": "rgb(6,161,75)", + "opacity": 1 + }, + { + "fill": "rgb(6,161,75)", + "opacity": 1 + }, + { + "fill": "rgb(6,161,75)", + "opacity": 1 + } + ], + "isMulticolor": false, + "grid": 0, + "tags": [ + "icon-tabular-scrolling" + ], + "colorPermutations": { + "125525525516161751": [ + 1, + 1, + 1, + 1, + 1 + ] + } + }, + { + "id": 81, + "paths": [ + "M0 64v192h448v-256h-384c-35.2 0-64 28.8-64 64z", + "M960 0h-384v256h448v-192c0-35.2-28.8-64-64-64z", + "M576 384h448v256h-448v-256z", + "M0 384h448v256h-448v-256z", + "M0 960c0 35.2 28.8 64 64 64h384v-256h-448v192z", + "M576 1024h384c35.2 0 64-28.8 64-64v-192h-448v256z" + ], + "attrs": [ + { + "fill": "#000", + "opacity": 1 + }, + { + "fill": "#000", + "opacity": 1 + }, + { + "fill": "#000", + "opacity": 1 + }, + { + "fill": "#000", + "opacity": 1 + }, + { + "fill": "#000", + "opacity": 1 + }, + { + "fill": "#000", + "opacity": 1 + } + ], + "isMulticolor": false, + "grid": 0, + "tags": [ + "icon-tabular" + ], + "colorPermutations": { + "125525525516161751": [ + 0, + 0, + 0, + 0, + 0, + 0 + ] + } + }, + { + "id": 80, + "paths": [ + "M896 0h-768c-70.4 0-128 57.6-128 128v768c0 70.4 57.6 128 128 128h768c70.4 0 128-57.6 128-128v-768c0-70.4-57.6-128-128-128zM640 448h-256v-192h256v192zM384 512h256v192h-256v-192zM320 704h-256v-192h256v192zM320 256v192h-256v-192h256zM128 960c-17 0-33-6.6-45.2-18.8s-18.8-28.2-18.8-45.2v-128h256v192h-192zM384 960v-192h256v192h-256zM960 896c0 17-6.6 33-18.8 45.2s-28.2 18.8-45.2 18.8h-192v-192h256v128zM960 704h-256v-192h256v192zM960 448h-256v-192h256v192z" + ], + "attrs": [ + { + "fill": "rgb(6,161,75)", + "opacity": 1 + } + ], + "isMulticolor": false, + "grid": 0, + "tags": [ + "icon-calendar" + ], + "colorPermutations": { + "125525525516161751": [ + 1 + ] + } + }, + { + "id": 78, + "paths": [ + "M896 640c0 0-130 188-128 256 2 70.6 57.4 128 128 128s126-57.4 128-128c2-68-128-256-128-256z", + "M449 129l0.2-64.8c0-35.4-28.4-64-63.8-64.2 0 0-0.2 0-0.2 0-35.2 0-63.8 28.6-64 63.8l-0.6 190.8-294 292.6c-50 50-12.4 215.2 112.4 340s290 162.4 340 112.4l417-423.6-447-447zM384 640c-70.6 0-128-57.4-128-128 0-47.4 25.8-89 64.4-111l-0.4 110.8c0 35.4 28.4 64 63.8 64.2 0 0 0.2 0 0.2 0 35.2 0 63.8-28.6 64-63.8l0.4-110.8c38 22.2 63.6 63.4 63.6 110.6 0 70.6-57.4 128-128 128z" + ], + "attrs": [ + { + "fill": "rgb(6,161,75)", + "opacity": 1 + }, + { + "fill": "rgb(6,161,75)", + "opacity": 1 + } + ], + "isMulticolor": false, + "grid": 0, + "tags": [ + "icon-paint-bucket" + ], + "colorPermutations": { + "125525525516161751": [ + 1, + 1 + ] + } + }, { "id": 75, "paths": [ @@ -1767,7 +1983,24 @@ ] } ], - "invisible": false + "invisible": false, + "colorThemes": [ + [ + [ + 0, + 0, + 0, + 1 + ], + [ + 6, + 161, + 75, + 1 + ] + ] + ], + "colorThemeIdx": 0 }, { "selection": [ @@ -14510,7 +14743,8 @@ "selector": "class", "classSelector": ".ui-symbol", "showMetrics": true, - "showMetadata": true + "showMetadata": true, + "embed": false }, "imagePref": { "prefix": "icon-", diff --git a/platform/commonUI/general/res/fonts/symbols/wtdsymbols.eot b/platform/commonUI/general/res/fonts/symbols/wtdsymbols.eot index 278460b5a8..2f4f938076 100755 Binary files a/platform/commonUI/general/res/fonts/symbols/wtdsymbols.eot and b/platform/commonUI/general/res/fonts/symbols/wtdsymbols.eot differ diff --git a/platform/commonUI/general/res/fonts/symbols/wtdsymbols.svg b/platform/commonUI/general/res/fonts/symbols/wtdsymbols.svg index 9c9d712d2d..d31a879fc3 100755 --- a/platform/commonUI/general/res/fonts/symbols/wtdsymbols.svg +++ b/platform/commonUI/general/res/fonts/symbols/wtdsymbols.svg @@ -6,78 +6,83 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/commonUI/general/res/fonts/symbols/wtdsymbols.ttf b/platform/commonUI/general/res/fonts/symbols/wtdsymbols.ttf index b113a531a4..37af03fa79 100755 Binary files a/platform/commonUI/general/res/fonts/symbols/wtdsymbols.ttf and b/platform/commonUI/general/res/fonts/symbols/wtdsymbols.ttf differ diff --git a/platform/commonUI/general/res/fonts/symbols/wtdsymbols.woff b/platform/commonUI/general/res/fonts/symbols/wtdsymbols.woff index 5989698d98..c93e44215c 100755 Binary files a/platform/commonUI/general/res/fonts/symbols/wtdsymbols.woff and b/platform/commonUI/general/res/fonts/symbols/wtdsymbols.woff differ diff --git a/platform/commonUI/general/res/sass/_constants.scss b/platform/commonUI/general/res/sass/_constants.scss index 3051dc616c..22518172da 100644 --- a/platform/commonUI/general/res/sass/_constants.scss +++ b/platform/commonUI/general/res/sass/_constants.scss @@ -29,7 +29,7 @@ $interiorMargin: 5px; $interiorMarginLg: $interiorMargin * 2; $interiorMarginSm: 3px; $basicCr: 2px; -$controlCr: 2px; +$controlCr: 3px; $smallCr: 2px; $badgeW: 35px; @@ -84,6 +84,7 @@ $tabularColorBodyBg: darken($colorBodyBg, 10%); $tabularColorBodyFg: lighten($tabularColorBodyBg, 40%); $tabularColorHeaderBg: lighten($colorBodyBg, 10%); $tabularColorHeaderFg: lighten($tabularColorHeaderBg, 40%); +$tabularColorHeaderBorder: $colorBodyBg; /************************** RATIOS */ $ltGamma: 20%; @@ -115,9 +116,9 @@ $colorItemTreeIcon: $colorKey; $colorItemTreeIconHover: lighten($colorItemTreeIcon, 20%); $colorItemTreeVCHover: $colorAlt1; // Tabular -$tabularHeaderH: 18px; +$tabularHeaderH: 22px; //18px $tabularTdPadLR: $itemPadLR; -$tabularTdPadTB: 2px; +$tabularTdPadTB: 3px; // Imagery $imageMainControlBarH: 22px; $imageThumbsD: 120px; @@ -141,7 +142,6 @@ $reqSymbolM: $interiorMargin * 2; $reqSymbolFontSize: 0.7em; /************************** CONTROLS */ -$controlCr: $basicCr; $controlDisabledOpacity: 0.3; $formLabelW: 20%; $formInputH: 22px; diff --git a/platform/commonUI/general/res/sass/_global.scss b/platform/commonUI/general/res/sass/_global.scss index 3c28d54c7d..94fe8e151c 100644 --- a/platform/commonUI/general/res/sass/_global.scss +++ b/platform/commonUI/general/res/sass/_global.scss @@ -50,6 +50,11 @@ input, textarea { font-family: Helvetica, Arial, sans-serif; } +input[type="text"] { + vertical-align: baseline; + padding: 3px 5px !important; +} + h1, h2, h3 { margin: 0; } diff --git a/platform/commonUI/general/res/sass/_main.scss b/platform/commonUI/general/res/sass/_main.scss index d56c55aca5..5866aee700 100644 --- a/platform/commonUI/general/res/sass/_main.scss +++ b/platform/commonUI/general/res/sass/_main.scss @@ -34,7 +34,6 @@ @import "fixed-position"; @import "about"; @import "text"; -@import "badges"; @import "icons"; @import "limits"; @import "data-status"; @@ -49,7 +48,6 @@ @import "edit/editor"; @import "features/imagery"; @import "features/time-display"; -@import "forms/mixins"; @import "forms/elems"; @import "forms/validation"; @import "forms/text-input"; @@ -70,5 +68,7 @@ @import "properties"; @import "autoflow"; @import "iframe"; +@import "messages"; @import "initialization"; @import "hide-non-functional"; +@import "views"; diff --git a/platform/commonUI/general/res/sass/_messages.scss b/platform/commonUI/general/res/sass/_messages.scss new file mode 100644 index 0000000000..db4de4c946 --- /dev/null +++ b/platform/commonUI/general/res/sass/_messages.scss @@ -0,0 +1,12 @@ +/* Styles for messages */ + +.message { + &.block { + @include border-radius($basicCr); + padding: $interiorMarginLg; + } + &.error { + background-color: rgba($colorAlert,0.3); + color: lighten($colorAlert, 20%); + } +} \ No newline at end of file diff --git a/platform/commonUI/general/res/sass/_mixins.scss b/platform/commonUI/general/res/sass/_mixins.scss index dc37d94fb6..08dd72cd00 100644 --- a/platform/commonUI/general/res/sass/_mixins.scss +++ b/platform/commonUI/general/res/sass/_mixins.scss @@ -259,6 +259,38 @@ @include text-shadow(rgba(black, $sVal) 0 3px 7px); } +/*********************************************** FORM ELEMENTS */ +@mixin input-base($bg: $colorBodyBg, $fg: $colorBodyFg) { + @include appearance(none); + @include border-radius($controlCr); + @include box-sizing(border-box); + @include box-shadow(inset rgba(black, 0.65) 0 1px 4px); + // background: lighten($bg, 20%); + background: rgba(#fff, 0.1); + border: none; + //border-bottom: 1px solid rgba(#fff, 0.1); + color: lighten($fg, 20%); + outline: none; + &.error { + background: rgba(red, 0.5); + } +} + +@mixin nice-input($bg: $colorBodyBg, $fg: $colorBodyFg) { + @include input-base($bg, $fg); + padding: 0 $interiorMarginSm; +} + +@mixin nice-textarea($bg: $colorBodyBg, $fg: $colorBodyFg) { + @include input-base($bg, $fg); + padding: $interiorMargin; +} + +@mixin subdued-input($bg: $colorBodyBg, $fg: $colorBodyFg) { + @include nice-input($bg, $fg); + background: lighten($bg, 3%); + border-bottom: 1px solid lighten($bg, 10%); +} /* @mixin invokeMenu($baseColor: $colorBodyFg) { diff --git a/platform/commonUI/general/res/sass/_views.scss b/platform/commonUI/general/res/sass/_views.scss new file mode 100644 index 0000000000..ef83e3c29b --- /dev/null +++ b/platform/commonUI/general/res/sass/_views.scss @@ -0,0 +1,21 @@ +/* Styles for sub-dividing views generically */ + +.l-view-section { + @include absPosDefault(0); + font-size: 0.8rem; + h2 { + color: #fff; + margin-bottom: $interiorMargin; + } + &.fixed { + font-size: 0.8em; + } + &.scrolling { + overflow: auto; + } + .controls, + label, + .inline-block { + display: inline-block; + } +} \ No newline at end of file diff --git a/platform/commonUI/general/res/sass/forms/_elems.scss b/platform/commonUI/general/res/sass/forms/_elems.scss index a47cdc2484..9a2adab2e3 100644 --- a/platform/commonUI/general/res/sass/forms/_elems.scss +++ b/platform/commonUI/general/res/sass/forms/_elems.scss @@ -86,13 +86,6 @@ } } - input[type="text"] { - height: $formInputH; - line-height: $formInputH; - margin-top: -4px; - vertical-align: baseline; - } - .l-med input[type="text"] { width: 200px; } diff --git a/platform/commonUI/general/res/sass/forms/_mixins.scss b/platform/commonUI/general/res/sass/forms/_mixins.scss index fae98a588f..e80999174c 100644 --- a/platform/commonUI/general/res/sass/forms/_mixins.scss +++ b/platform/commonUI/general/res/sass/forms/_mixins.scss @@ -23,11 +23,11 @@ @include appearance(none); @include border-radius($controlCr); @include box-sizing(border-box); - @include box-shadow(inset rgba(black, 0.5) 0 1px 5px); + @include box-shadow(inset rgba(black, 0.65) 0 1px 4px); // background: lighten($bg, 20%); background: rgba(#fff, 0.1); border: none; - border-bottom: 1px solid rgba(#fff, 0.1); + //border-bottom: 1px solid rgba(#fff, 0.1); color: lighten($fg, 20%); outline: none; &.error { diff --git a/platform/commonUI/general/res/sass/helpers/_wait-spinner.scss b/platform/commonUI/general/res/sass/helpers/_wait-spinner.scss index fafae5e9ea..f80c1f1971 100644 --- a/platform/commonUI/general/res/sass/helpers/_wait-spinner.scss +++ b/platform/commonUI/general/res/sass/helpers/_wait-spinner.scss @@ -50,6 +50,12 @@ margin-top: $d / -1; margin-left: $d / -1; z-index: 2; + &.inline { + display: inline-block !important; + margin-right: $interiorMargin; + position: relative !important; + vertical-align: middle; + } } .l-wait-spinner-holder { @@ -80,4 +86,14 @@ margin: 0 !important; padding: 0 !important; top: 2px; left: 0; +} + +.wait-spinner.sm { + $d: 13px; + @include wait-spinner(0.25em, $colorKey); + height: $d; width: $d; + margin-left: 0 !important; + margin-top: 0 !important; + padding: 0 !important; + top: 0; left: 0; } \ No newline at end of file diff --git a/platform/commonUI/general/res/sass/lists/_tabular.scss b/platform/commonUI/general/res/sass/lists/_tabular.scss index 0b449baccf..629cac9d1a 100644 --- a/platform/commonUI/general/res/sass/lists/_tabular.scss +++ b/platform/commonUI/general/res/sass/lists/_tabular.scss @@ -24,13 +24,14 @@ height: 100%; } -.tabular { +.tabular, +table { @include box-sizing(border-box); border-spacing: 0; border-collapse: collapse; color: #fff; display: table; - font-size: 0.75em; + font-size: 0.75rem; position: relative; //height: 100%; MOVED width: 100%; @@ -41,19 +42,7 @@ //table-layout: fixed; MOVED } thead, .thead { - //width: calc(100% - 10px); MOVED - tr, .tr { - height: $tabularHeaderH; - } - &:before { - content: ""; - display: block; - z-index: 0; - position: absolute; - width: 100%; - height: $tabularHeaderH; - background: rgba(#fff, 0.15); - } + border-bottom: 1px solid $tabularColorHeaderBorder; } tbody, .tbody { //@include absPosDefault(0); MOVED @@ -72,14 +61,21 @@ &:first-child .td { border-top: none; } + &.group-header { + td, .td { + $d: 5%; + background-color: darken($tabularColorHeaderBg, $d); + color: darken($tabularColorHeaderFg, $d); + } + } th, .th, td, .td { display: table-cell; } th, .th { - border: none; - border-left: 1px solid $tabularColorBorder; + background-color: $tabularColorHeaderBg; + border-left: 1px solid $tabularColorHeaderBorder; color: $tabularColorHeaderFg; - padding: 0 $tabularTdPadLR; + padding: $tabularTdPadLR $tabularTdPadLR; white-space: nowrap; vertical-align: middle; // This is crucial to hiding f**king 4px height injected by browser by default &:first-child { @@ -100,10 +96,11 @@ } } td, .td { - border-top: 1px solid $tabularColorBorder; - min-width: 110px; + border-bottom: 1px solid $tabularColorBorder; + min-width: 20px; color: $colorTelemFresh; padding: $tabularTdPadTB $tabularTdPadLR; + word-wrap: break-word; vertical-align: top; &.numeric { text-align: right; @@ -119,9 +116,20 @@ } } &.filterable { + thead, .thead { + tr.s-filters, .tr.s-filters { + th, .th { + //border-left: none; + } + } + } tbody, .tbody { top: $tabularHeaderH * 2; } + input[type="text"] { + @include box-sizing(border-box); + width: 100%; //50px; + } } &.fixed-header { @@ -133,6 +141,15 @@ } thead, .thead { width: calc(100% - 10px); + &:before { + content: ""; + display: block; + z-index: 0; + position: absolute; + width: 100%; + height: $tabularHeaderH; + background: rgba(#fff, 0.15); + } } tbody, .tbody { @include absPosDefault(0); diff --git a/platform/persistence/elastic/src/ElasticsearchSearchProvider.js b/platform/persistence/elastic/src/ElasticsearchSearchProvider.js new file mode 100644 index 0000000000..af13628af9 --- /dev/null +++ b/platform/persistence/elastic/src/ElasticsearchSearchProvider.js @@ -0,0 +1,213 @@ +/***************************************************************************** + * 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 ElasticsearchSearchProvider. Created by shale on 07/16/2015. + * This is not currently included in the bundle definition. + */ +define( + [], + function () { + "use strict"; + + // JSLint doesn't like underscore-prefixed properties, + // so hide them here. + var ID = "_id", + SCORE = "_score", + DEFAULT_MAX_RESULTS = 100; + + /** + * A search service which searches through domain objects in + * the filetree using ElasticSearch. + * + * @constructor + * @param $http Angular's $http service, for working with urls. + * @param {ObjectService} objectService the service from which + * domain objects can be gotten. + * @param ROOT the constant ELASTIC_ROOT which allows us to + * interact with ElasticSearch. + */ + function ElasticsearchSearchProvider($http, objectService, ROOT) { + + // Add the fuzziness operator to the search term + function addFuzziness(searchTerm, editDistance) { + if (!editDistance) { + editDistance = ''; + } + + return searchTerm.split(' ').map(function (s) { + // Don't add fuzziness for quoted strings + if (s.indexOf('"') !== -1) { + return s; + } else { + return s + '~' + editDistance; + } + }).join(' '); + } + + // Currently specific to elasticsearch + function processSearchTerm(searchTerm) { + var spaceIndex; + + // Cut out any extra spaces + while (searchTerm.substr(0, 1) === ' ') { + searchTerm = searchTerm.substring(1, searchTerm.length); + } + while (searchTerm.substr(searchTerm.length - 1, 1) === ' ') { + searchTerm = searchTerm.substring(0, searchTerm.length - 1); + } + spaceIndex = searchTerm.indexOf(' '); + while (spaceIndex !== -1) { + searchTerm = searchTerm.substring(0, spaceIndex) + + searchTerm.substring(spaceIndex + 1, searchTerm.length); + spaceIndex = searchTerm.indexOf(' '); + } + + // Add fuzziness for completeness + searchTerm = addFuzziness(searchTerm); + + return searchTerm; + } + + // Processes results from the format that elasticsearch returns to + // a list of searchResult objects, then returns a result object + // (See documentation for query for object descriptions) + function processResults(rawResults, timestamp) { + var results = rawResults.data.hits.hits, + resultsLength = results.length, + ids = [], + scores = {}, + searchResults = [], + i; + + // Get the result objects' IDs + for (i = 0; i < resultsLength; i += 1) { + ids.push(results[i][ID]); + } + + // Get the result objects' scores + for (i = 0; i < resultsLength; i += 1) { + scores[ids[i]] = results[i][SCORE]; + } + + // Get the domain objects from their IDs + return objectService.getObjects(ids).then(function (objects) { + var j, + id; + + for (j = 0; j < resultsLength; j += 1) { + id = ids[j]; + + // Include items we can get models for + if (objects[id].getModel) { + // Format the results as searchResult objects + searchResults.push({ + id: id, + object: objects[id], + score: scores[id] + }); + } + } + + return { + hits: searchResults, + total: rawResults.data.hits.total, + timedOut: rawResults.data.timed_out + }; + }); + } + + // For documentation, see query below. + function query(searchTerm, timestamp, maxResults, timeout) { + var esQuery; + + // Check to see if the user provided a maximum + // number of results to display + if (!maxResults) { + // Else, we provide a default value. + maxResults = DEFAULT_MAX_RESULTS; + } + + // If the user input is empty, we want to have no search results. + if (searchTerm !== '' && searchTerm !== undefined) { + // Process the search term + searchTerm = processSearchTerm(searchTerm); + + // Create the query to elasticsearch + esQuery = ROOT + "/_search/?q=" + searchTerm + + "&size=" + maxResults; + if (timeout) { + esQuery += "&timeout=" + timeout; + } + + // Get the data... + return $http({ + method: "GET", + url: esQuery + }).then(function (rawResults) { + // ...then process the data + return processResults(rawResults, timestamp); + }, function (err) { + // In case of error, return nothing. (To prevent + // infinite loading time.) + return {hits: [], total: 0}; + }); + } else { + return {hits: [], total: 0}; + } + } + + return { + /** + * Searches through the filetree for domain objects using a search + * term. This is done through querying elasticsearch. Returns a + * promise for a result object that has the format + * {hits: searchResult[], total: number, timedOut: boolean} + * where a searchResult has the format + * {id: string, object: domainObject, score: number} + * + * Notes: + * * The order of the results is from highest to lowest score, + * as elsaticsearch determines them to be. + * * Uses the fuzziness operator to get more results. + * * More about this search's behavior at + * https://www.elastic.co/guide/en/elasticsearch/reference/current/search-uri-request.html + * + * @param searchTerm The text input that is the query. + * @param timestamp The time at which this function was called. + * This timestamp is used as a unique identifier for this + * query and the corresponding results. + * @param maxResults (optional) The maximum number of results + * that this function should return. + * @param timeout (optional) The time after which the search should + * stop calculations and return partial results. Elasticsearch + * does not guarentee that this timeout will be strictly followed. + */ + query: query + }; + } + + + return ElasticsearchSearchProvider; + } +); \ No newline at end of file diff --git a/platform/persistence/elastic/test/ElasticsearchSearchProviderSpec.js b/platform/persistence/elastic/test/ElasticsearchSearchProviderSpec.js new file mode 100644 index 0000000000..1202ef77e6 --- /dev/null +++ b/platform/persistence/elastic/test/ElasticsearchSearchProviderSpec.js @@ -0,0 +1,115 @@ +/***************************************************************************** + * 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*/ + +/** + * SearchSpec. Created by shale on 07/31/2015. + */ +define( + ["../src/ElasticsearchSearchProvider"], + function (ElasticsearchSearchProvider) { + "use strict"; + + // JSLint doesn't like underscore-prefixed properties, + // so hide them here. + var ID = "_id", + SCORE = "_score"; + + describe("The ElasticSearch search provider ", function () { + var mockHttp, + mockHttpPromise, + mockObjectPromise, + mockObjectService, + mockDomainObject, + provider, + mockProviderResults; + + beforeEach(function () { + mockHttp = jasmine.createSpy("$http"); + mockHttpPromise = jasmine.createSpyObj( + "promise", + [ "then" ] + ); + mockHttp.andReturn(mockHttpPromise); + // allow chaining of promise.then().catch(); + mockHttpPromise.then.andReturn(mockHttpPromise); + + mockObjectService = jasmine.createSpyObj( + "objectService", + [ "getObjects" ] + ); + mockObjectPromise = jasmine.createSpyObj( + "promise", + [ "then" ] + ); + mockObjectService.getObjects.andReturn(mockObjectPromise); + + mockDomainObject = jasmine.createSpyObj( + "domainObject", + [ "getId", "getModel" ] + ); + + provider = new ElasticsearchSearchProvider(mockHttp, mockObjectService, ""); + provider.query(' test "query" ', 0, undefined, 1000); + }); + + it("sends a query to ElasticSearch", function () { + expect(mockHttp).toHaveBeenCalled(); + }); + + it("gets data from ElasticSearch", function () { + var data = { + hits: { + hits: [ + {}, + {} + ], + total: 0 + }, + timed_out: false + }; + data.hits.hits[0][ID] = 1; + data.hits.hits[0][SCORE] = 1; + data.hits.hits[1][ID] = 2; + data.hits.hits[1][SCORE] = 2; + + mockProviderResults = mockHttpPromise.then.mostRecentCall.args[0]({data: data}); + + expect( + mockObjectPromise.then.mostRecentCall.args[0]({ + 1: mockDomainObject, + 2: mockDomainObject + }).hits.length + ).toEqual(2); + }); + + it("returns nothing for an empty string query", function () { + expect(provider.query("").hits).toEqual([]); + }); + + it("returns something when there is an ElasticSearch error", function () { + mockProviderResults = mockHttpPromise.then.mostRecentCall.args[1](); + expect(mockProviderResults).toBeDefined(); + }); + }); + } +); \ No newline at end of file diff --git a/platform/persistence/elastic/test/suite.json b/platform/persistence/elastic/test/suite.json index cc8dc2ce0c..939244c089 100644 --- a/platform/persistence/elastic/test/suite.json +++ b/platform/persistence/elastic/test/suite.json @@ -1,4 +1,5 @@ [ "ElasticIndicator", - "ElasticPersistenceProvider" + "ElasticPersistenceProvider", + "ElasticsearchSearchProvider" ] diff --git a/platform/representation/src/actions/ContextMenuAction.js b/platform/representation/src/actions/ContextMenuAction.js index 390531053e..67b48536c3 100644 --- a/platform/representation/src/actions/ContextMenuAction.js +++ b/platform/representation/src/actions/ContextMenuAction.js @@ -31,7 +31,7 @@ define( var MENU_TEMPLATE = "" + "", dismissExistingMenu; @@ -48,7 +48,7 @@ define( * should be performed */ function ContextMenuAction($compile, $document, $window, $rootScope, actionContext) { - + function perform() { var winDim = [$window.innerWidth, $window.innerHeight], eventCoors = [actionContext.event.pageX, actionContext.event.pageY], @@ -62,7 +62,7 @@ define( // Remove the context menu function dismiss() { menu.remove(); - body.off("click", dismiss); + body.off("mousedown", dismiss); dismissExistingMenu = undefined; } @@ -92,20 +92,21 @@ define( // Add the menu to the body body.append(menu); - + // Stop propagation so that clicks on the menu do not close the menu menu.on('mousedown', function (event) { event.stopPropagation(); }); - + // Dismiss the menu when body is clicked elsewhere // ('mousedown' because 'click' breaks left-click context menus) body.on('mousedown', dismiss); + menu.on('click', dismiss); // Don't launch browser's context menu actionContext.event.preventDefault(); } - + return { perform: perform }; @@ -113,4 +114,4 @@ define( return ContextMenuAction; } -); \ No newline at end of file +); diff --git a/platform/representation/test/actions/ContextMenuActionSpec.js b/platform/representation/test/actions/ContextMenuActionSpec.js index 73b877ddc3..03298162b4 100644 --- a/platform/representation/test/actions/ContextMenuActionSpec.js +++ b/platform/representation/test/actions/ContextMenuActionSpec.js @@ -69,7 +69,7 @@ define( mockCompiledTemplate.andReturn(mockMenu); mockDocument.find.andReturn(mockBody); mockRootScope.$new.andReturn(mockScope); - + mockActionContext = {key: 'menu', domainObject: mockDomainObject, event: mockEvent}; action = new ContextMenuAction( @@ -118,9 +118,9 @@ define( it("removes a menu when body is clicked", function () { // Show the menu action.perform(); - + // Verify precondition - expect(mockBody.off).not.toHaveBeenCalled(); + expect(mockBody.remove).not.toHaveBeenCalled(); // Find and fire body's mousedown listener mockBody.on.calls.forEach(function (call) { @@ -133,8 +133,29 @@ define( expect(mockMenu.remove).toHaveBeenCalled(); // Listener should have been detached from body - expect(mockBody.off).toHaveBeenCalled(); + expect(mockBody.off).toHaveBeenCalledWith( + 'mousedown', + jasmine.any(Function) + ); + }); + + it("removes a menu when it is clicked", function () { + // Show the menu + action.perform(); + + // Verify precondition + expect(mockMenu.remove).not.toHaveBeenCalled(); + + // Find and fire body's mousedown listener + mockMenu.on.calls.forEach(function (call) { + if (call.args[0] === 'click') { + call.args[1](); + } + }); + + // Menu should have been removed + expect(mockMenu.remove).toHaveBeenCalled(); }); }); } -); \ No newline at end of file +); diff --git a/platform/search/bundle.json b/platform/search/bundle.json new file mode 100644 index 0000000000..6668022939 --- /dev/null +++ b/platform/search/bundle.json @@ -0,0 +1,33 @@ +{ + "name": "Search", + "description": "Allows the user to search through the file tree.", + "extensions": { + "constants": [ + { + "key": "GENERIC_SEARCH_ROOTS", + "value": [ "ROOT" ], + "priority": "fallback" + } + ], + "components": [ + { + "provides": "searchService", + "type": "provider", + "implementation": "GenericSearchProvider.js", + "depends": [ "$q", "$timeout", "objectService", "workerService", "GENERIC_SEARCH_ROOTS" ] + }, + { + "provides": "searchService", + "type": "aggregator", + "implementation": "SearchAggregator.js", + "depends": [ "$q" ] + } + ], + "workers": [ + { + "key": "genericSearchWorker", + "scriptUrl": "GenericSearchWorker.js" + } + ] + } +} diff --git a/platform/search/src/GenericSearchProvider.js b/platform/search/src/GenericSearchProvider.js new file mode 100644 index 0000000000..dae2cab9a9 --- /dev/null +++ b/platform/search/src/GenericSearchProvider.js @@ -0,0 +1,268 @@ +/***************************************************************************** + * 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 GenericSearchProvider. Created by shale on 07/16/2015. + */ +define( + [], + function () { + "use strict"; + + var DEFAULT_MAX_RESULTS = 100, + DEFAULT_TIMEOUT = 1000, + stopTime; + + /** + * A search service which searches through domain objects in + * the filetree without using external search implementations. + * + * @constructor + * @param $q Angular's $q, for promise consolidation. + * @param $timeout Angular's $timeout, for delayed function execution. + * @param {ObjectService} objectService The service from which + * domain objects can be gotten. + * @param {WorkerService} workerService The service which allows + * more easy creation of web workers. + * @param {GENERIC_SEARCH_ROOTS} ROOTS An array of the root + * domain objects' IDs. + */ + function GenericSearchProvider($q, $timeout, objectService, workerService, ROOTS) { + var worker = workerService.run('genericSearchWorker'), + indexed = {}, + pendingQueries = {}; + // pendingQueries is a dictionary with the key value pairs st + // the key is the timestamp and the value is the promise + + // Tell the web worker to add a domain object's model to its list of items. + function indexItem(domainObject) { + var message; + + // undefined check + if (domainObject && domainObject.getModel) { + // Using model instead of whole domain object because + // it's a JSON object. + message = { + request: 'index', + model: domainObject.getModel(), + id: domainObject.getId() + }; + worker.postMessage(message); + } + } + + // Tell the worker to search for items it has that match this searchInput. + // Takes the searchInput, as well as a max number of results (will return + // less than that if there are fewer matches). + function workerSearch(searchInput, maxResults, timestamp, timeout) { + var message = { + request: 'search', + input: searchInput, + maxNumber: maxResults, + timestamp: timestamp, + timeout: timeout + }; + worker.postMessage(message); + } + + // Handles responses from the web worker. Namely, the results of + // a search request. + function handleResponse(event) { + var ids = [], + id; + + // If we have the results from a search + if (event.data.request === 'search') { + // Convert the ids given from the web worker into domain objects + for (id in event.data.results) { + ids.push(id); + } + objectService.getObjects(ids).then(function (objects) { + var searchResults = [], + id; + + // Create searchResult objects + for (id in objects) { + searchResults.push({ + object: objects[id], + id: id, + score: event.data.results[id] + }); + } + + // Resove the promise corresponding to this + pendingQueries[event.data.timestamp].resolve({ + hits: searchResults, + total: event.data.total, + timedOut: event.data.timedOut + }); + }); + } + } + + worker.onmessage = handleResponse; + + // Helper function for getItems(). Indexes the tree. + function indexItems(nodes) { + nodes.forEach(function (node) { + var id = node && node.getId && node.getId(); + + // If we have already indexed this item, stop here + if (indexed[id]) { + return; + } + + // Index each item with the web worker + indexItem(node); + indexed[id] = true; + + + // If this node has children, index those + if (node && node.hasCapability && node.hasCapability('composition')) { + // Make sure that this is async, so doesn't block up page + $timeout(function () { + // Get the children... + node.useCapability('composition').then(function (children) { + $timeout(function () { + // ... then index the children + if (children.constructor === Array) { + indexItems(children); + } else { + indexItems([children]); + } + }, 0); + }); + }, 0); + } + + // Watch for changes to this item, in case it gets new children + if (node && node.hasCapability && node.hasCapability('mutation')) { + node.getCapability('mutation').listen(function (listener) { + if (listener && listener.composition) { + // If the node was mutated to have children, get the child domain objects + objectService.getObjects(listener.composition).then(function (objectsById) { + var objects = [], + id; + + // Get each of the domain objects in objectsById + for (id in objectsById) { + objects.push(objectsById[id]); + } + + indexItems(objects); + }); + } + }); + } + }); + } + + // Converts the filetree into a list + function getItems() { + // Aquire root objects + objectService.getObjects(ROOTS).then(function (objectsById) { + var objects = [], + id; + + // Get each of the domain objects in objectsById + for (id in objectsById) { + objects.push(objectsById[id]); + } + + // Index all of the roots' descendents + indexItems(objects); + }); + } + + // For documentation, see query below + function query(input, timestamp, maxResults, timeout) { + var terms = [], + searchResults = [], + defer = $q.defer(); + + // If the input is nonempty, do a search + if (input !== '' && input !== undefined) { + + // Allow us to access this promise later to resolve it later + pendingQueries[timestamp] = defer; + + // Check to see if the user provided a maximum + // number of results to display + if (!maxResults) { + // Else, we provide a default value + maxResults = DEFAULT_MAX_RESULTS; + } + // Similarly, check if timeout was provided + if (!timeout) { + timeout = DEFAULT_TIMEOUT; + } + + // Send the query to the worker + workerSearch(input, maxResults, timestamp, timeout); + + return defer.promise; + } else { + // Otherwise return an empty result + return {hits: [], total: 0}; + } + } + + // Index the tree's contents once at the beginning + getItems(); + + return { + /** + * Searches through the filetree for domain objects which match + * the search term. This function is to be used as a fallback + * in the case where other search services are not avaliable. + * Returns a promise for a result object that has the format + * {hits: searchResult[], total: number, timedOut: boolean} + * where a searchResult has the format + * {id: string, object: domainObject, score: number} + * + * Notes: + * * The order of the results is not guarenteed. + * * A domain object qualifies as a match for a search input if + * the object's name property contains any of the search terms + * (which are generated by splitting the input at spaces). + * * Scores are higher for matches that have more of the terms + * as substrings. + * + * @param input The text input that is the query. + * @param timestamp The time at which this function was called. + * This timestamp is used as a unique identifier for this + * query and the corresponding results. + * @param maxResults (optional) The maximum number of results + * that this function should return. + * @param timeout (optional) The time after which the search should + * stop calculations and return partial results. + */ + query: query + + }; + } + + + return GenericSearchProvider; + } +); \ No newline at end of file diff --git a/platform/search/src/GenericSearchWorker.js b/platform/search/src/GenericSearchWorker.js new file mode 100644 index 0000000000..69e4104602 --- /dev/null +++ b/platform/search/src/GenericSearchWorker.js @@ -0,0 +1,185 @@ +/***************************************************************************** + * 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 self*/ + +/** + * Module defining GenericSearchWorker. Created by shale on 07/21/2015. + */ +(function () { + "use strict"; + + // An array of objects composed of domain object IDs and models + // {id: domainObject's ID, model: domainObject's model} + var indexedItems = []; + + // Helper function for index() + // Checks whether an item with this ID is already indexed + function conainsItem(id) { + var i; + for (i = 0; i < indexedItems.length; i += 1) { + if (indexedItems[i].id === id) { + return true; + } + } + return false; + } + + /** + * Indexes an item to indexedItems. + * + * @param data An object which contains: + * * model: The model of the domain object + * * id: The ID of the domain object + */ + function index(data) { + var message; + + if (!conainsItem(data.id)) { + indexedItems.push({ + id: data.id, + model: data.model + }); + } + } + + // Helper function for serach() + function convertToTerms(input) { + var terms = input; + // Shave any spaces off of the ends of the input + while (terms.substr(0, 1) === ' ') { + terms = terms.substring(1, terms.length); + } + while (terms.substr(terms.length - 1, 1) === ' ') { + terms = terms.substring(0, terms.length - 1); + } + + // Then split it at spaces and asterisks + terms = terms.split(/ |\*/); + + // Remove any empty strings from the terms + while (terms.indexOf('') !== -1) { + terms.splice(terms.indexOf(''), 1); + } + + return terms; + } + + // Helper function for search() + function scoreItem(item, input, terms) { + var name = item.model.name.toLocaleLowerCase(), + weight = 0.65, + score = 0.0, + i; + + // Make the score really big if the item name and + // the original search input are the same + if (name === input) { + score = 42; + } + + for (i = 0; i < terms.length; i += 1) { + // Increase the score if the term is in the item name + if (name.indexOf(terms[i]) !== -1) { + score += 1; + + // Add extra to the score if the search term exists + // as its own term within the items + if (name.split(' ').indexOf(terms[i]) !== -1) { + score += 0.5; + } + } + } + + return score * weight; + } + + /** + * Gets search results from the indexedItems based on provided search + * input. Returns matching results from indexedItems, as well as the + * timestamp that was passed to it. + * + * @param data An object which contains: + * * input: The original string which we are searching with + * * maxNumber: The maximum number of search results desired + * * timestamp: The time identifier from when the query was made + */ + function search(data) { + // This results dictionary will have domain object ID keys which + // point to the value the domain object's score. + var results = {}, + input = data.input.toLocaleLowerCase(), + terms = convertToTerms(input), + message = { + request: 'search', + results: {}, + total: 0, + timestamp: data.timestamp, + timedOut: false + }, + score, + i, + id; + + // If the user input is empty, we want to have no search results. + if (input !== '') { + for (i = 0; i < indexedItems.length; i += 1) { + // If this is taking too long, then stop + if (Date.now() > data.timestamp + data.timeout) { + message.timedOut = true; + break; + } + + // Score and add items + score = scoreItem(indexedItems[i], input, terms); + if (score > 0) { + results[indexedItems[i].id] = score; + message.total += 1; + } + } + } + + // Truncate results if there are more than maxResults + if (message.total > data.maxResults) { + i = 0; + for (id in results) { + message.results[id] = results[id]; + i += 1; + if (i >= data.maxResults) { + break; + } + } + // TODO: This seems inefficient. + } else { + message.results = results; + } + + return message; + } + + self.onmessage = function (event) { + if (event.data.request === 'index') { + index(event.data); + } else if (event.data.request === 'search') { + self.postMessage(search(event.data)); + } + }; +}()); \ No newline at end of file diff --git a/platform/search/src/SearchAggregator.js b/platform/search/src/SearchAggregator.js new file mode 100644 index 0000000000..da267214bf --- /dev/null +++ b/platform/search/src/SearchAggregator.js @@ -0,0 +1,146 @@ +/***************************************************************************** + * 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 SearchAggregator. Created by shale on 07/16/2015. + */ +define( + [], + function () { + "use strict"; + + var DEFUALT_TIMEOUT = 1000, + DEFAULT_MAX_RESULTS = 100; + + /** + * Allows multiple services which provide search functionality + * to be treated as one. + * + * @constructor + * @param $q Angular's $q, for promise consolidation. + * @param {SearchProvider[]} providers The search providers to be + * aggregated. + */ + function SearchAggregator($q, providers) { + + // Remove duplicate objects that have the same ID. Modifies the passed + // array, and returns the number that were removed. + function filterDuplicates(results, total) { + var ids = {}, + numRemoved = 0, + i; + + for (i = 0; i < results.length; i += 1) { + if (ids[results[i].id]) { + // If this result's ID is already there, remove the object + results.splice(i, 1); + numRemoved += 1; + + // Reduce loop index because we shortened the array + i -= 1; + } else { + // Otherwise add the ID to the list of the ones we have seen + ids[results[i].id] = true; + } + } + + return numRemoved; + } + + // Order the objects from highest to lowest score in the array. + // Modifies the passed array, as well as returns the modified array. + function orderByScore(results) { + results.sort(function (a, b) { + if (a.score > b.score) { + return -1; + } else if (b.score > a.score) { + return 1; + } else { + return 0; + } + }); + return results; + } + + // For documentation, see query below. + function queryAll(inputText, maxResults) { + var i, + timestamp = Date.now(), + resultPromises = []; + + if (!maxResults) { + maxResults = DEFAULT_MAX_RESULTS; + } + + // Send the query to all the providers + for (i = 0; i < providers.length; i += 1) { + resultPromises.push( + providers[i].query(inputText, timestamp, maxResults, DEFUALT_TIMEOUT) + ); + } + + // Get promises for results arrays + return $q.all(resultPromises).then(function (resultObjects) { + var results = [], + totalSum = 0, + i; + + // Merge results + for (i = 0; i < resultObjects.length; i += 1) { + results = results.concat(resultObjects[i].hits); + totalSum += resultObjects[i].total; + } + // Order by score first, so that when removing repeats we keep the higher scored ones + orderByScore(results); + totalSum -= filterDuplicates(results, totalSum); + + return { + hits: results, + total: totalSum, + timedOut: resultObjects.some(function (obj) { + return obj.timedOut; + }) + }; + }); + } + + return { + /** + * Sends a query to each of the providers. Returns a promise for + * a result object that has the format + * {hits: searchResult[], total: number, timedOut: boolean} + * where a searchResult has the format + * {id: string, object: domainObject, score: number} + * + * @param inputText The text input that is the query. + * @param maxResults (optional) The maximum number of results + * that this function should return. If not provided, a + * default of 100 will be used. + */ + query: queryAll + }; + } + + return SearchAggregator; + } +); \ No newline at end of file diff --git a/platform/search/test/GenericSearchProviderSpec.js b/platform/search/test/GenericSearchProviderSpec.js new file mode 100644 index 0000000000..bec02653b8 --- /dev/null +++ b/platform/search/test/GenericSearchProviderSpec.js @@ -0,0 +1,157 @@ +/***************************************************************************** + * 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*/ + +/** + * SearchSpec. Created by shale on 07/31/2015. + */ +define( + ["../src/GenericSearchProvider"], + function (GenericSearchProvider) { + "use strict"; + + describe("The generic search provider ", function () { + var mockQ, + mockTimeout, + mockDeferred, + mockObjectService, + mockObjectPromise, + mockDomainObjects, + mockCapability, + mockCapabilityPromise, + mockWorkerService, + mockWorker, + mockRoots = ['root1', 'root2'], + provider, + mockProviderResults; + + beforeEach(function () { + var i; + + mockQ = jasmine.createSpyObj( + "$q", + [ "defer" ] + ); + mockDeferred = jasmine.createSpyObj( + "deferred", + [ "resolve", "reject"] + ); + mockDeferred.promise = "mock promise"; + mockQ.defer.andReturn(mockDeferred); + + mockTimeout = jasmine.createSpy("$timeout"); + + mockObjectService = jasmine.createSpyObj( + "objectService", + [ "getObjects" ] + ); + mockObjectPromise = jasmine.createSpyObj( + "promise", + [ "then", "catch" ] + ); + mockObjectService.getObjects.andReturn(mockObjectPromise); + + + mockWorkerService = jasmine.createSpyObj( + "workerService", + [ "run" ] + ); + mockWorker = jasmine.createSpyObj( + "worker", + [ "postMessage" ] + ); + mockWorkerService.run.andReturn(mockWorker); + + mockDomainObjects = {}; + for (i = 0; i < 4; i += 1) { + mockDomainObjects[i] = ( + jasmine.createSpyObj( + "domainObject", + [ "getId", "getModel", "hasCapability", "getCapability", "useCapability" ] + ) + ); + mockDomainObjects[i].getId.andReturn(i); + mockDomainObjects[i].getCapability.andReturn(mockCapability); + } + // Give the first object children + mockDomainObjects[0].hasCapability.andReturn(true); + mockCapability = jasmine.createSpyObj( + "capability", + [ "invoke", "listen" ] + ); + mockCapabilityPromise = jasmine.createSpyObj( + "promise", + [ "then", "catch" ] + ); + mockCapability.invoke.andReturn(mockCapabilityPromise); + mockDomainObjects[0].getCapability.andReturn(mockCapability); + + provider = new GenericSearchProvider(mockQ, mockTimeout, mockObjectService, mockWorkerService, mockRoots); + }); + + it("indexes tree on initialization", function () { + expect(mockObjectService.getObjects).toHaveBeenCalled(); + expect(mockObjectPromise.then).toHaveBeenCalled(); + + mockObjectPromise.then.mostRecentCall.args[0](mockDomainObjects); + + //mockCapabilityPromise.then.mostRecentCall.args[0](mockDomainObjects[1]); + + expect(mockWorker.postMessage).toHaveBeenCalled(); + }); + + it("sends search queries to the worker", function () { + var timestamp = Date.now(); + provider.query(' test "query" ', timestamp, 1, 2); + expect(mockWorker.postMessage).toHaveBeenCalledWith({ + request: "search", + input: ' test "query" ', + timestamp: timestamp, + maxNumber: 1, + timeout: 2 + }); + }); + + it("handles responses from the worker", function () { + var timestamp = Date.now(), + event = { + data: { + request: "search", + results: { + 1: 1, + 2: 2 + }, + total: 2, + timedOut: false, + timestamp: timestamp + } + }; + + provider.query(' test "query" ', timestamp); + mockWorker.onmessage(event); + mockObjectPromise.then.mostRecentCall.args[0](mockDomainObjects); + expect(mockDeferred.resolve).toHaveBeenCalled(); + }); + + }); + } +); \ No newline at end of file diff --git a/platform/search/test/GenericSearchWorkerSpec.js b/platform/search/test/GenericSearchWorkerSpec.js new file mode 100644 index 0000000000..2e17858400 --- /dev/null +++ b/platform/search/test/GenericSearchWorkerSpec.js @@ -0,0 +1,132 @@ +/***************************************************************************** + * 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,runs,waitsFor,beforeEach,jasmine,Worker,require*/ + +/** + * SearchSpec. Created by shale on 07/31/2015. + */ +define( + [], + function () { + "use strict"; + + describe("The generic search worker ", function () { + // If this test fails, make sure this path is correct + var worker = new Worker(require.toUrl('platform/search/src/GenericSearchWorker.js')), + numObjects = 5; + + beforeEach(function () { + var i; + for (i = 0; i < numObjects; i += 1) { + worker.postMessage( + { + request: "index", + id: i, + model: { + name: "object " + i, + id: i, + type: "something" + } + } + ); + } + }); + + it("searches can reach all objects", function () { + var flag = false, + workerOutput, + resultsLength = 0; + + // Search something that should return all objects + runs(function () { + worker.postMessage( + { + request: "search", + input: "object", + maxNumber: 100, + timestamp: Date.now(), + timeout: 1000 + } + ); + }); + + worker.onmessage = function (event) { + var id; + + workerOutput = event.data; + for (id in workerOutput.results) { + resultsLength += 1; + } + flag = true; + }; + + waitsFor(function () { + return flag; + }, "The worker should be searching", 1000); + + runs(function () { + expect(workerOutput).toBeDefined(); + expect(resultsLength).toEqual(numObjects); + }); + }); + + it("searches return only matches", function () { + var flag = false, + workerOutput, + resultsLength = 0; + + // Search something that should return 1 object + runs(function () { + worker.postMessage( + { + request: "search", + input: "2", + maxNumber: 100, + timestamp: Date.now(), + timeout: 1000 + } + ); + }); + + worker.onmessage = function (event) { + var id; + + workerOutput = event.data; + for (id in workerOutput.results) { + resultsLength += 1; + } + flag = true; + }; + + waitsFor(function () { + return flag; + }, "The worker should be searching", 1000); + + runs(function () { + expect(workerOutput).toBeDefined(); + expect(resultsLength).toEqual(1); + expect(workerOutput.results[2]).toBeDefined(); + }); + }); + }); + } +); \ No newline at end of file diff --git a/platform/search/test/SearchAggregatorSpec.js b/platform/search/test/SearchAggregatorSpec.js new file mode 100644 index 0000000000..cf35e2928e --- /dev/null +++ b/platform/search/test/SearchAggregatorSpec.js @@ -0,0 +1,101 @@ +/***************************************************************************** + * 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*/ + +/** + * SearchSpec. Created by shale on 07/31/2015. + */ +define( + ["../src/SearchAggregator"], + function (SearchAggregator) { + "use strict"; + + describe("The search aggregator ", function () { + var mockQ, + mockPromise, + mockProviders = [], + aggregator, + mockProviderResults = [], + mockAggregatorResults, + i; + + beforeEach(function () { + mockQ = jasmine.createSpyObj( + "$q", + [ "all" ] + ); + mockPromise = jasmine.createSpyObj( + "promise", + [ "then" ] + ); + for (i = 0; i < 3; i += 1) { + mockProviders.push( + jasmine.createSpyObj( + "mockProvider" + i, + [ "query" ] + ) + ); + mockProviders[i].query.andReturn(mockPromise); + } + mockQ.all.andReturn(mockPromise); + + aggregator = new SearchAggregator(mockQ, mockProviders); + aggregator.query(); + + for (i = 0; i < mockProviders.length; i += 1) { + mockProviderResults.push({ + hits: [ + { + id: i, + score: 42 - i + }, + { + id: i + 1, + score: 42 - (2 * i) + } + ] + }); + } + mockAggregatorResults = mockPromise.then.mostRecentCall.args[0](mockProviderResults); + }); + + it("sends queries to all providers", function () { + for (i = 0; i < mockProviders.length; i += 1) { + expect(mockProviders[i].query).toHaveBeenCalled(); + } + }); + + it("filters out duplicate objects", function () { + expect(mockAggregatorResults.hits.length).toEqual(mockProviders.length + 1); + expect(mockAggregatorResults.total).not.toBeLessThan(mockAggregatorResults.hits.length); + }); + + it("orders results by score", function () { + for (i = 1; i < mockAggregatorResults.hits.length; i += 1) { + expect(mockAggregatorResults.hits[i].score) + .not.toBeGreaterThan(mockAggregatorResults.hits[i - 1].score); + } + }); + + }); + } +); \ No newline at end of file diff --git a/platform/search/test/suite.json b/platform/search/test/suite.json new file mode 100644 index 0000000000..5097bde635 --- /dev/null +++ b/platform/search/test/suite.json @@ -0,0 +1,5 @@ +[ + "SearchAggregator", + "GenericSearchProvider", + "GenericSearchWorker" +] diff --git a/pom.xml b/pom.xml index 8ca3cd6edb..3acfe38fa1 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ gov.nasa.arc.wtd open-mct-web Open MCT Web - 0.8.0-SNAPSHOT + 0.8.1-SNAPSHOT war diff --git a/protractor/README b/protractor/README new file mode 100644 index 0000000000..5734e5702d --- /dev/null +++ b/protractor/README @@ -0,0 +1,69 @@ +E2e Protractor Tests. + +1. Instructions: + + 1. 3 Control Scripts located in bin/. + run.js : node script used to start tests + start.js: node script used to setup test(starts node,localstorage and webdriver) + stop.js : node script, kills the 3 process started in start.js. + clean.js: node script used to remove the node_module directory.(clean up directory). + + 2. Use npm(Node Package Mangager) to Run Scripts. + a. cd protractor; + b. npm install; + c. To Run: + -npm start : will start processes need by protractor + -npm stop : will stop the processes need by protractor + -npm run-script run : will execute Protractor Script + -npm run-script all : will execute "start", "run", and "stop" script + +2. Directory Hierachy: + + -protractor: base directory + -common: contains prototype javascript functions that all other tests use. + -Buttons: common prototype functions related to enter fullscreen + -CreateItem: common prototype functions related to creating an item + -drag: common functions to test drag and drop. + -editItem: common functions used to test edit functionality. + -Launch: common script used to navigate the specified website. + -RightMenu: common functions for right click menu(remove). + -create + -e2e tests that creates the specified object. + -delete + -e2e tests that removes the specified object + -logs + -ctrl.sh redirects console output of MMAP, webdriver and elastic search and pipes them to log files. + -UI + -Contains tests that test the UI(drag drop, fullscreen, info bubble) + -conf.js: + -protractor config file. Explained below + -stressTest: + Tests that are used to test for memory leaks. You can use the new tab option on WARP and then open the + timeline in the new tab during the browser.sleep(). Once the test is do the browser will pause and you + can look a the timeline results in the new tab. + + NOTE: Cannot open chrome dev tools on same tab as the test are run on. Protractor uses the dev tools to + exectute the tests. + + -StressTest will create and delete folders. + -StressTestBubble.js: creates manny bubbles. + (Delay variable in InfoGesture.js was changed to 0) +3. Conf.js + Conf.js is used by protractor to setup and execute the tests. + -allScriptsTimeout: gives more time for protractor to synchronize with the page. + -jasmineNodeOpts: Protractor uses jasmine for the tests and jasmine has a default time out 30 seconds + per "it" test. Changed to maximume allowed time 360000 ms + -seleniumAddress: Protractor uses a Selenium server as a "proxy" between the test scripts and the browser + driver. A stand a lone version comes with protractor and to run use "webdriver-manager" + default address is: http://localhost:4444/wd/hub. + -specs[]: Is an array of files. Each File should have a "describe, it" test to be executed by protractor. + -capabilities: Tells protractor what browser to use and any browser arguments. + +4. bundle.json + bundle.json is used by npm to determine dependencies and location of script files. + -Dependencies: + "protractor": Contains protractor and webdriver package. + "psnode": Window/Unix Command, used for list/kill process.(ps aux) + "shelljs": Window/Unix Common JS Commands. eg rm,ls,exec + "sleep": Window/Unix Commands used to sleep the script + "string": Window/Unix Commands for string manipulation. \ No newline at end of file diff --git a/protractor/UI/Fullscreen.js b/protractor/UI/Fullscreen.js index 3c1c785228..532ad318d8 100644 --- a/protractor/UI/Fullscreen.js +++ b/protractor/UI/Fullscreen.js @@ -22,7 +22,7 @@ //TODO Add filter for duplications/ var fullScreenFile = require("../common/Buttons"); -describe('Test Fullscreen', function() { +describe('Enable Fullscreen', function() { var fullScreenClass = new fullScreenFile(); beforeEach(require('../common/Launch')); diff --git a/protractor/UI/InfoBubble.js b/protractor/UI/InfoBubble.js index 274b7966b0..c88e9018d0 100644 --- a/protractor/UI/InfoBubble.js +++ b/protractor/UI/InfoBubble.js @@ -25,7 +25,7 @@ var itemEdit = require("../common/EditItem"); var rightMenu = require("../common/RightMenu"); var Drag = require("../common/drag"); -describe('Test Info Bubble', function() { +describe('Info Bubble', function() { var fullScreenClass = new fullScreenFile(); var createClass = new createItem(); var editItemClass = new itemEdit(); diff --git a/protractor/UI/NewWindow.js b/protractor/UI/NewWindow.js index 7a714d79a2..1e98bbc8b4 100644 --- a/protractor/UI/NewWindow.js +++ b/protractor/UI/NewWindow.js @@ -24,7 +24,7 @@ var createClassFile = require("../common/CreateItem") var itemEdit = require("../common/EditItem"); var rightMenu = require("../common/RightMenu.js"); -describe('Test New Window', function() { +describe('New Window', function() { var fullScreenClass = new fullScreenFile(); var createClass = new createClassFile(); var editItemClass = new itemEdit(); diff --git a/protractor/UI/RightClick.js b/protractor/UI/RightClick.js index 0ae4dd0708..5f7d389313 100644 --- a/protractor/UI/RightClick.js +++ b/protractor/UI/RightClick.js @@ -21,28 +21,64 @@ *****************************************************************************/ var right_click = require("../common/RightMenu.js"); var Create = require("../common/CreateItem") -describe('Right Click Interations', function() { +var itemEdit = require("../common/EditItem"); + +describe('The Right Menu', function() { var clickClass = new right_click(); var createClass = new Create(); + var editItemClass = new itemEdit(); var ITEM_NAME = "Folder"; var ITEM_TYPE = "folder"; var ITEM_MENU_GLYPH = 'F\nFolder'; + var ITEM_GRID_SELECT = 'P\nF\nFolder\n0 Items'; beforeEach(require('../common/Launch')); - it('should delete the specified object', function(){ - createClass.createButton().click(); - var folder = createClass.selectNewItem(ITEM_TYPE); - expect(folder.getText()).toEqual([ ITEM_MENU_GLYPH ]); - browser.sleep(1000); - folder.click() - browser.sleep(1000); - browser.wait(function () { - return element.all(by.model('ngModel[field]')).isDisplayed(); + it('should Dissapear After Delete', function(){ + browser.wait(function() { + createClass.createButton().click(); + return true; + }).then(function (){ + var folder = createClass.selectNewItem(ITEM_TYPE); + expect(folder.getText()).toEqual([ ITEM_MENU_GLYPH ]); + browser.sleep(1000); + folder.click() + }).then(function() { + browser.wait(function () { + return element.all(by.model('ngModel[field]')).isDisplayed(); + }) + createClass.fillFolderForum(ITEM_NAME, ITEM_TYPE).click(); + browser.sleep(1000); + }).then(function (){ + var item = editItemClass.SelectItem(ITEM_GRID_SELECT); + expect(item.count()).toBe(1); + browser.sleep(1000); + }).then(function () { + var MyItem = ">\nF\nMy Items" + element.all(by.repeater('child in composition')).filter(function (ele){ + return ele.getText().then(function(text) { + return text === MyItem; + }); + }).all(by.css('.ui-symbol.view-control.ng-binding.ng-scope')).click(); + var object = element.all(by.repeater('child in composition')).filter(function (ele){ + return ele.getText().then(function(text) { + return text === ">\nF\nFolder"; + }); + }); + browser.sleep(1000) + browser.actions().mouseMove(object.get(0)).perform(); + browser.actions().click(protractor.Button.RIGHT).perform(); + browser.sleep(1000) + var menu = element.all(by.css('.ng-binding')).filter(function (ele){ + return ele.getText().then(function (text) { + return text == "Z\nRemove"; + }) + }) + menu.click(); + browser.sleep(1000) + + expect(menu.isDisplayed()).toBe(false); }) - createClass.fillFolderForum(ITEM_NAME, ITEM_TYPE).click(); - clickClass.delete(ITEM_NAME); - browser.sleep(1000); }); }); diff --git a/protractor/bin/clean.js b/protractor/bin/clean.js new file mode 100755 index 0000000000..82e776901f --- /dev/null +++ b/protractor/bin/clean.js @@ -0,0 +1,15 @@ +#! /usr/bin/env node +var shell = require("shelljs/global"); + +var startdir = process.cwd(); +var command = "npm unlink"; + +console.log("Cleaning Directory") +exec(command, function(code, output) { + if(code != 0){ + console.log('Exit code:', code); + console.log('Program output:', output); + } +}); +console.log("rm -rf node_modules") +rm('-rf', __dirname + "/../node_modules") diff --git a/protractor/bin/ctrl.sh b/protractor/bin/ctrl.sh new file mode 100755 index 0000000000..faf385d2ad --- /dev/null +++ b/protractor/bin/ctrl.sh @@ -0,0 +1,90 @@ +#! /bin/bash +ARGUMENT=$1; + +if [ $# != 1 ]; then + echo "Expected 1 Aurgument. Received " $# 1>&2; + exit 1 +fi +#Start webdrive and http-server +if [ $ARGUMENT == start ]; then + echo "Creating Log Directory ..." + mkdir logs; + + cd .. + node app.js -p 1984 -x platform/persistence/elastic -i example/persistence > protractor/logs/nodeApp.log 2>&1 & + sleep 3; + if grep -iq "Error" protractor/logs/nodeApp.log; then + if grep -iq "minimist" protractor/logs/nodeApp.log; then + echo " Node Failed Because Minimist is not installed" + echo " Installng Minimist ..." + npm install minimist express > protractor/logs/minimist.log 2>&1 & + wait $! + if [ $? != 0 ]; then + echo " Error: minimist" + echo " Check Log file" + echo + else + echo " Started: Minimist" + echo + node app.js -p 1984 -x platform/persistence/elastic -i example/persistence > protractor/logs/nodeApp.log 2>&1 & + if grep -iq "Error" protractor/logs/nodeApp.log; then + echo " Error: node app failed" + echo " Check Log file" + echo + else + echo " Started: node app.js" + echo + fi + fi + else + echo " Error: node app failed" + echo " Check Log file" + echo + fi + else + echo " Started: node app.js" + echo + fi + echo "Starting webdriver ..." + + cd protractor; + webdriver-manager start > logs/webdriver.log 2>&1 & + sleep 3; + if grep -iq "Exception" logs/webdriver.log; then + echo " Error: webdriver-manager" + echo " Check Log file" + echo + else + echo " Started: webdriver-manager" + fi + echo "Starting Elastic Search..." + + elasticsearch > logs/elasticSearch.log 2>&1 & + sleep 3; + if grep -iq "Exception" logs/elasticSearch.log; then + echo " Error: ElasticSearch" + echo " Check Log file" + echo + else + echo " Started: ElasticSearch" + fi +#Runs Protractor tests +elif [ $ARGUMENT == run ]; then + protractor ./conf.js +#Kill Process +elif [ $ARGUMENT == stop ]; then + echo "Removing logs" + rm -rf logs + echo "Stopping Node" + kill $(ps aux | grep "[n]ode app.js"| awk '{print $2}'); + + echo "Stopping webdriver ..." + kill $(ps aux | grep "[p]rotractor" | awk '{print $2}'); + kill $(ps aux | grep "[w]ebdriver-manager" | awk '{print $2}'); + sleep 1; + echo "Stopping Elastic..." + kill $(ps aux | grep "[e]lastic" | awk '{print $2}'); + sleep 1; +else + echo "Unkown: Command" $1; +fi diff --git a/protractor/bin/run.js b/protractor/bin/run.js new file mode 100755 index 0000000000..316caa11d0 --- /dev/null +++ b/protractor/bin/run.js @@ -0,0 +1,12 @@ +#! /usr/bin/env node +var shell = require("shelljs/global"); +var sleep = require('sleep'); + +var command = __dirname + "/../node_modules/protractor/bin/protractor " +__dirname + "/../conf.js"; +console.log("Executing Protractor Test") +exec(command, function(code, output) { + if(code != 0){ + console.log('Exit code:', code); + console.log('Program output:', output); + } +}); \ No newline at end of file diff --git a/protractor/bin/start.js b/protractor/bin/start.js new file mode 100755 index 0000000000..21aacc7efe --- /dev/null +++ b/protractor/bin/start.js @@ -0,0 +1,40 @@ +#! /usr/bin/env node +var shell,sleep; +try { + shell = require("shelljs/global"); + sleep = require('sleep'); +}catch (e){ + console.log("Dependencies Error"); + console.log("Run npm install"); + throw (e); +} +///Users/jsanderf/git/elastic/wtd/protractor/bin +var startdir = process.cwd(); +var command; +mkdir(__dirname + '/../logs'); + +command = __dirname + "/../node_modules/protractor/bin/webdriver-manager update"; +console.log("Installing Webdriver"); +exec(command,{async:false}); +sleep.sleep(1); + +console.log(); +cd(__dirname + '/../../'); +console.log('Installing Dependencies'); +exec("npm install minimist express", {async:false}); +console.log('Starting Node'); +sleep.sleep(1); +exec("node app.js -p 1984 -x example/persistence -x platform/persistence/elastic -i example/localstorage > protractor/logs/nodeApp.log 2>&1 &", {async:false}); +console.log(' Started Node'); + +console.log(); +console.log('Starting Webdriver'); +sleep.sleep(1); +exec("protractor/node_modules/protractor/bin/webdriver-manager start --standalone> protractor/logs/webdriver.log 2>&1 &",{async:false}); +if(error() == null){ + console.log(" Webdriver Started"); +}else{ + console.log(" Error : ", error()); +} +sleep.sleep(1); +cd(startdir); diff --git a/protractor/bin/stop.js b/protractor/bin/stop.js new file mode 100755 index 0000000000..ac2c3b4295 --- /dev/null +++ b/protractor/bin/stop.js @@ -0,0 +1,44 @@ +#! /usr/bin/env node + +var shell = require("shelljs/global"); +var ps = require('psnode'); +var S = require('string'); +var sleep = require('sleep'); + +// A simple pid lookup +ps.list(function(err, results) { + + results.forEach(function( process ){ + //Killing Node + if(S(process.command).contains("node app.js")) { + console.log(); + console.log( 'Killing Node: %s', process.command); + ps.kill(process.pid, function(err, stdout) { + if (err) { + throw new Error(err); + } + console.log(stdout); + }); + }else if(S(process.command).contains("webdriver")) { + console.log(); + console.log( 'Killing WebDriver: %s', process.command); + ps.kill(process.pid, function(err, stdout) { + if (err){ + throw new Error(err); + } + console.log(stdout); + }); + }else if(S(process.command).contains("protractor")) { + console.log(); + console.log( 'Killing Chrome Drive: %s', process.command); + ps.kill(process.pid, function(err, stdout) { + if (err){ + throw new Error(err); + } + console.log(stdout); + }); + } + }); +}); + + diff --git a/protractor/common/Launch.js b/protractor/common/Launch.js index 2b700672cc..fd745f94c3 100644 --- a/protractor/common/Launch.js +++ b/protractor/common/Launch.js @@ -24,6 +24,6 @@ module.exports = function launch() { 'use strict'; browser.ignoreSynchronization = true; - browser.get('http://localhost:1984/'); - browser.sleep(2000); // 20 seconds + browser.get('http://localhost:1984'); + browser.sleep(2000); // 2 seconds }; diff --git a/protractor/common/RightMenu.js b/protractor/common/RightMenu.js index 490d876d87..d1375d0533 100644 --- a/protractor/common/RightMenu.js +++ b/protractor/common/RightMenu.js @@ -24,18 +24,25 @@ var RightMenu = (function () { function RightMenu() { } + function carrotMyItem(){ + var MyItem = ">\nF\nMy Items" + element.all(by.repeater('child in composition')).filter(function (ele){ + return ele.getText().then(function(text) { + return text === MyItem; + }); + }).all(by.css('.ui-symbol.view-control.ng-binding.ng-scope')).click(); + } //RightMenu Click on Object RightMenu.prototype.delete = function (name, flag) { if(typeof flag === 'undefined'){ flag = true; } if(flag === true){ - var carrot = element.all(by.css('.ui-symbol.view-control.ng-binding.ng-scope')).get(0).click(); + carrotMyItem(); } browser.sleep(1000) var object = element.all(by.repeater('child in composition')).filter(function (ele){ return ele.getText().then(function(text) { - //expect(text).toEqual("3"); return text === name; }); }); @@ -43,7 +50,7 @@ var RightMenu = (function () { browser.actions().mouseMove(object.get(0)).perform(); browser.actions().click(protractor.Button.RIGHT).perform(); browser.sleep(1000) - var remove = element.all(by.css('.ng-binding')).filter(function (ele){ + element.all(by.css('.ng-binding')).filter(function (ele){ return ele.getText().then(function (text) { return text == "Z\nRemove"; }) @@ -58,11 +65,10 @@ var RightMenu = (function () { }); }; RightMenu.prototype.reset = function (name) { - var carrot = element.all(by.css('.ui-symbol.view-control.ng-binding.ng-scope')).click(); + carrotMyItem(); browser.sleep(1000) var object = element.all(by.repeater('child in composition')).filter(function (ele){ return ele.getText().then(function(text) { - //expect(text).toEqual("3"); return text === name; }); }).click(); @@ -75,19 +81,19 @@ var RightMenu = (function () { return text == "r\nRestart at 0"; }) }).click(); + browser.sleep(1000) }; + //click '<', true==yes false==no RightMenu.prototype.select = function(name, flag){ if(typeof flag == "undefined"){ flag = true; } - //click '<', true==yes false==no if(flag == true){ - var carrot = element.all(by.css('.ui-symbol.view-control.ng-binding.ng-scope')).click(); + carrotMyItem(); } browser.sleep(1000) return element.all(by.repeater('child in composition')).filter(function (ele){ return ele.getText().then(function(text) { - // expect(text).toEqual("3"); return text === name; }); }); @@ -96,7 +102,6 @@ var RightMenu = (function () { RightMenu.prototype.dragDrop = function(name){ var object = element.all(by.repeater('child in composition')).filter(function (ele){ return ele.getText().then(function(text) { - //expect(text).toEqual("3"); return text === name; }); }); diff --git a/protractor/conf.js b/protractor/conf.js index c33e196157..8b828fcbd7 100644 --- a/protractor/conf.js +++ b/protractor/conf.js @@ -24,34 +24,34 @@ // conf.js exports.config = { allScriptsTimeout: 500000, - defaultTimeoutInterval: 60000, + jasmineNodeOpts: {defaultTimeoutInterval: 360000}, seleniumAddress: 'http://localhost:4444/wd/hub', - //specs: ['StressTest.js'], + //specs: ['StressTestCarrot.js'], specs: [ - //'create/CreateActivity.js', - //'delete/DeleteActivity.js', - //'create/CreateActivityMode.js', - //'delete/DeleteActivityMode.js', - //'create/CreateActivityMode.js', - //'create/CreateClock.js', - //'delete/DeleteClock.js', + // 'create/CreateActivity.js', + // 'delete/DeleteActivity.js', + // 'create/CreateActivityMode.js', + // 'delete/DeleteActivityMode.js', + // 'create/CreateClock.js', + // 'delete/DeleteClock.js', 'create/CreateDisplay.js', - //'delete/DeleteDisplay.js', + 'delete/DeleteDisplay.js', 'create/CreateFolder.js', - //'delete/DeleteFolder.js', - 'create/CreateTelemetry.js', - //'delete/DeleteTelemetry.js', - //'create/CreateTimeline.js', - //'delete/DeleteTimeline.js', - //'create/CreateTimer.js', - //'delete/DeleteTimer.js', + 'delete/DeleteFolder.js', + // 'create/CreateTelemetry.js', + // 'delete/DeleteTelemetry.js', + // 'create/CreateTimeline.js', + // 'delete/DeleteTimeline.js', + // 'create/CreateTimer.js', + // 'delete/DeleteTimer.js', 'create/CreateWebPage.js', - //'delete/DeleteWebPage.js', + 'delete/DeleteWebPage.js', 'UI/Fullscreen.js', 'create/CreateButton.js', //"UI/DragDrop.js", - //"UI/NewWindow.js", - 'UI/InfoBubble.js' + "UI/NewWindow.js" + //'UI/InfoBubble.js', + //'UI/RightClick.js' ], capabilities: { 'browserName': 'chrome', // or 'safari' @@ -61,7 +61,7 @@ exports.config = { // Allow specifying binary location as an environment variable, // for cases where Chrome is not installed in a usual location. -if (process.env.PROTRACTOR_CHROME_BINARY) { +if (process.env.CHROME_BIN) { exports.config.capabilities.chromeOptions.binary = - process.env.PROTRACTOR_CHROME_BINARY; + process.env.CHROME_BIN; } diff --git a/protractor/create/CreateActivityMode.js b/protractor/create/CreateActivityMode.js index e9469749aa..17ed700ae6 100644 --- a/protractor/create/CreateActivityMode.js +++ b/protractor/create/CreateActivityMode.js @@ -22,7 +22,7 @@ var itemCreate = require("../common/CreateItem"); var itemEdit = require("../common/EditItem"); -describe('Create Web Page', function() { +describe('Create Activity Mode', function() { var createClass = new itemCreate(); var editItemClass = new itemEdit(); var ITEM_NAME = "Activity Mode"; diff --git a/protractor/create/CreateClock.js b/protractor/create/CreateClock.js index d1dc781b58..940db62af4 100644 --- a/protractor/create/CreateClock.js +++ b/protractor/create/CreateClock.js @@ -57,7 +57,7 @@ describe('Create Clock', function() { }); it('should check clock', function () { - function getTime() { + function getTime(flag) { function addZero(time){ if(time < 10){ return '0' + time; @@ -66,7 +66,6 @@ describe('Create Clock', function() { } var currentdate = new Date(); - var month = currentdate.getMonth() + 1; month = addZero(month); @@ -77,6 +76,9 @@ describe('Create Clock', function() { hour = addZero(hour); var second = currentdate.getSeconds(); + if(flag == true) { + second = second + 1; + } second = addZero(second); var minute = currentdate.getMinutes(); @@ -85,17 +87,23 @@ describe('Create Clock', function() { return ("UTC " + currentdate.getFullYear() + "/" + (month) + "/" + day + " " + (hour) + ":" + minute + ":" + second + " PM"); } - - var current,clock; - rightClickClass.select(ITEM_MENU_GLYPH, true).click().then(function () { - browser.sleep(1000); - current = browser.executeScript(getTime); - }).then(function () { - clock = element(by.css('.l-time-display.l-digital.l-clock.s-clock.ng-scope')); - clock.getText().then(function (time) { - expect(current).toEqual(time); - }) + this.addMatchers({ + toBeIn: function(expected){ + var posibilities = Array.isArray(this.actual) ? this.actual : [this.actual]; + return posibilities.indexOf(expected) > -1; + } }) - + rightClickClass.select(ITEM_MENU_GLYPH, true).click().then(function () { + browser.sleep(1000); + browser.executeScript(getTime, false).then(function(current){ + browser.executeScript(getTime, true).then(function(current1) { + var clock = element(by.css('.l-time-display.l-digital.l-clock.s-clock.ng-scope')); + clock.getText().then(function (ele) { + expect([current,current1]).toBeIn(ele); + }) + }); + }); + + }) }); }); diff --git a/protractor/create/CreateTimer.js b/protractor/create/CreateTimer.js index d8059c1f59..e83fedfedf 100644 --- a/protractor/create/CreateTimer.js +++ b/protractor/create/CreateTimer.js @@ -63,7 +63,11 @@ describe('Create Timer', function() { browser.sleep(1000) var timer = element(by.css('.value.ng-binding.active')) timer.getText().then(function (time) { - expect(time).toEqual("0D 00:00:01") + var timerChecker = false; + if(time == "0D 00:00:01" || time == "0D 00:00:02"){ + timerChecker = true; + } + expect(timerChecker).toEqual(true) }) }); diff --git a/protractor/package.json b/protractor/package.json new file mode 100644 index 0000000000..b43b9b1cdb --- /dev/null +++ b/protractor/package.json @@ -0,0 +1,20 @@ +{ + "name": "ProtractorLauncher", + "version": "1.0.0", + "scripts" : { + "start" : "bin/start.js", + "protractor" : "bin/run.js", + "stop" : "bin/stop.js", + "all" : "bin/start.js; bin/run.js; bin/stop.js;", + "clean" : "bin/clean.js" + }, + "dependencies": { + "protractor": "^2.1.0", + "psnode": "0.0.1", + "shelljs": "^0.5.2", + "sleep": "^3.0.0", + "string": "^3.3.1" + }, + "description": "E2e Protractor Tests.", + "license": "ISC" +} diff --git a/protractor/StressTest.js b/protractor/stressTest/StressTest.js similarity index 74% rename from protractor/StressTest.js rename to protractor/stressTest/StressTest.js index 5e4a8b1507..108e431868 100644 --- a/protractor/StressTest.js +++ b/protractor/stressTest/StressTest.js @@ -19,10 +19,9 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ -//TODO Add filter for duplications/ -var itemCreate = require("./common/CreateItem"); -var itemEdit = require("./common/EditItem"); -var right_click = require("./common/RightMenu.js"); +var itemCreate = require("../common/CreateItem"); +var itemEdit = require("../common/EditItem"); +var right_click = require("../common/RightMenu.js"); describe('Create Folder', function() { var clickClass = new right_click(); @@ -41,31 +40,35 @@ describe('Create Folder', function() { }); it('should Create new Folder', function(){ browser.sleep(5000); - for(var i=0; i < 50; i++){ + for(var i=0; i < 25; i++){ browser.wait(function() { createClass.createButton().click(); return true; }).then(function (){ var folder = createClass.selectNewItem(ITEM_TYPE); expect(folder.getText()).toEqual([ ITEM_MENU_GLYPH ]); - browser.sleep(1000); + browser.sleep(500); folder.click() }).then(function() { browser.wait(function () { return element.all(by.model('ngModel[field]')).isDisplayed(); }) createClass.fillFolderForum(ITEM_NAME, ITEM_TYPE).click(); - browser.sleep(1000); + browser.sleep(500); }).then(function (){ - browser.sleep(1000); - // if(i === 1){ - clickClass.delete(ITEM_SIDE_SELECT, true); - element.all(by.css('.ui-symbol.view-control.ng-binding.ng-scope')).click(); - // }else{ - browser.sleep(1000); - + browser.sleep(500); + clickClass.delete(ITEM_SIDE_SELECT, true); + //element.all(by.css('.ui-symbol.view-control.ng-binding.ng-scope')).click(); + + + var MyItem = ">\nF\nMy Items" + element.all(by.repeater('child in composition')).filter(function (ele){ + return ele.getText().then(function(text) { + //expect(text).toEqual(MyItem); + return text === MyItem; + }); + }).all(by.css('.ui-symbol.view-control.ng-binding.ng-scope')).click(); // clickClass.delete(ITEM_SIDE_SELECT, false); - // } }); } browser.pause(); diff --git a/protractor/stressTest/StressTestBubble.js b/protractor/stressTest/StressTestBubble.js new file mode 100644 index 0000000000..b06b29c1b9 --- /dev/null +++ b/protractor/stressTest/StressTestBubble.js @@ -0,0 +1,59 @@ +/***************************************************************************** + * 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. + *****************************************************************************/StressTestBubble.jsStressTestBubble.js +var itemCreate = require("../common/CreateItem"); +var itemEdit = require("../common/EditItem"); +var right_click = require("../common/RightMenu.js"); + +describe('Create Folder', function() { + var clickClass = new right_click(); + var createClass = new itemCreate(); + var editItemClass = new itemEdit(); + var ITEM_NAME = "Folder"; + var ITEM_TYPE = "folder"; + var ITEM_MENU_GLYPH = 'F\nFolder'; + var ITEM_GRID_SELECT = 'P\nF\nFolder\n0 Items'; + var ITEM_SIDE_SELECT = ">\nF\nFolder" + + beforeEach(function() { + browser.ignoreSynchronization = true; + browser.get('http://localhost:1984/warp/'); + browser.sleep(2000); // 20 seconds + }); + it('should Create new Folder', function(){ + browser.sleep(10000); + for(var i=0; i < 1000; i++){ + var object = element.all(by.repeater('child in composition')).filter(function (ele){ + return ele.getText().then(function(text) { + return text === ">\nF\nMy Items"; + }); + }); + //browser.sleep(1000) + browser.actions().mouseMove(object.get(0)).perform(); + //browser.actions().click(protractor.Button.RIGHT).perform(); + + element.all(by.css('.items-holder.grid.abs.ng-scope')).click(); + } + browser.pause(); + + }); + +}); diff --git a/protractor/stressTest/StressTestCreateButton.js b/protractor/stressTest/StressTestCreateButton.js new file mode 100644 index 0000000000..25debf3bba --- /dev/null +++ b/protractor/stressTest/StressTestCreateButton.js @@ -0,0 +1,56 @@ +/***************************************************************************** + * 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. + *****************************************************************************/ +var itemCreate = require("../common/CreateItem"); +var itemEdit = require("../common/EditItem"); +var right_click = require("../common/RightMenu.js"); + +describe('Create Folder', function() { + var clickClass = new right_click(); + var createClass = new itemCreate(); + var editItemClass = new itemEdit(); + var ITEM_NAME = "Folder"; + var ITEM_TYPE = "folder"; + var ITEM_MENU_GLYPH = 'F\nFolder'; + var ITEM_GRID_SELECT = 'P\nF\nFolder\n0 Items'; + var ITEM_SIDE_SELECT = ">\nF\nFolder" + + beforeEach(function() { + browser.ignoreSynchronization = true; + browser.get('http://localhost:1984/warp/'); + browser.sleep(2000); // 20 seconds + }); + it('should Create new Folder', function(){ + browser.sleep(10000); + for(var i=0; i < 1000; i++){ + createClass.createButton().click(); + + //browser.sleep(1000) + //browser.actions().mouseMove(object.get(0)).perform(); + //browser.actions().click(protractor.Button.RIGHT).perform(); + + element.all(by.css('.items-holder.grid.abs.ng-scope')).click(); + } + browser.pause(); + + }); + +}); diff --git a/protractor/stressTest/StressTestMenu.js b/protractor/stressTest/StressTestMenu.js new file mode 100644 index 0000000000..d6e30bc5b2 --- /dev/null +++ b/protractor/stressTest/StressTestMenu.js @@ -0,0 +1,55 @@ +/***************************************************************************** + * 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. + *****************************************************************************/ +var itemCreate = require("../common/CreateItem"); +var itemEdit = require("../common/EditItem"); +var right_click = require("../common/RightMenu.js"); + +describe('Create Folder', function() { + var clickClass = new right_click(); + var createClass = new itemCreate(); + var editItemClass = new itemEdit(); + var ITEM_NAME = "Folder"; + var ITEM_TYPE = "folder"; + var ITEM_MENU_GLYPH = 'F\nFolder'; + var ITEM_GRID_SELECT = 'P\nF\nFolder\n0 Items'; + var ITEM_SIDE_SELECT = ">\nF\nFolder" + + beforeEach(function() { + browser.ignoreSynchronization = true; + browser.get('http://localhost:1984/warp/'); + browser.sleep(2000); // 20 seconds + }); + it('should Create new Folder', function(){ + browser.sleep(10000); + for(var i=0; i < 1000; i++){ + browser.wait(function() { + createClass.createButton().click(); + return true; + }).then(function (){ + element.all(by.css('.items-holder.grid.abs.ng-scope')).click(); + }) + } + browser.pause(); + + }); + +}); diff --git a/protractor/stressTest/StressTestNewPage.js b/protractor/stressTest/StressTestNewPage.js new file mode 100644 index 0000000000..2b0e82fbb1 --- /dev/null +++ b/protractor/stressTest/StressTestNewPage.js @@ -0,0 +1,61 @@ +/***************************************************************************** + * 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. + *****************************************************************************/ +var itemCreate = require("../common/CreateItem"); +var itemEdit = require("../common/EditItem"); +var right_click = require("../common/RightMenu.js"); +var fullScreenFile = require("../common/FullScreen"); + +describe('Create Folder', function() { + var clickClass = new right_click(); + var createClass = new itemCreate(); + var editItemClass = new itemEdit(); + var fullScreenClass = new fullScreenFile(); + + var ITEM_NAME = "Folder"; + var ITEM_TYPE = "folder"; + var ITEM_MENU_GLYPH = 'F\nFolder'; + var ITEM_GRID_SELECT = 'P\nF\nFolder\n0 Items'; + var ITEM_SIDE_SELECT = ">\nF\nFolder" + + beforeEach(function() { + browser.ignoreSynchronization = true; + browser.get('http://localhost:1984/warp/'); + browser.sleep(2000); // 20 seconds + }); + it('should Create new Folder', function(){ + browser.sleep(15000); + for(var i=0; i < 1000; i++){ + fullScreenClass.newWidnow().click(); + + browser.getAllWindowHandles().then(function (handles) { + //browser.driver.switchTo().window(handles[1]); + browser.sleep(1000); + browser.driver.close(); + browser.sleep(1000); + // browser.driver.switchTo().window(handles[0]); + }); + } + browser.pause(); + + }); + +}); diff --git a/protractor/stressTest/StressTestRightClick.js b/protractor/stressTest/StressTestRightClick.js new file mode 100644 index 0000000000..f16f876a90 --- /dev/null +++ b/protractor/stressTest/StressTestRightClick.js @@ -0,0 +1,59 @@ +/***************************************************************************** + * 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. + *****************************************************************************/ +var itemCreate = require("../common/CreateItem"); +var itemEdit = require("../common/EditItem"); +var right_click = require("../common/RightMenu.js"); + +describe('Create Folder', function() { + var clickClass = new right_click(); + var createClass = new itemCreate(); + var editItemClass = new itemEdit(); + var ITEM_NAME = "Folder"; + var ITEM_TYPE = "folder"; + var ITEM_MENU_GLYPH = 'F\nFolder'; + var ITEM_GRID_SELECT = 'P\nF\nFolder\n0 Items'; + var ITEM_SIDE_SELECT = ">\nF\nFolder" + + beforeEach(function() { + browser.ignoreSynchronization = true; + browser.get('http://localhost:1984/warp/'); + browser.sleep(2000); // 20 seconds + }); + it('should Create new Folder', function(){ + browser.sleep(8000); + for(var i=0; i < 1000; i++){ + var object = element.all(by.repeater('child in composition')).filter(function (ele){ + return ele.getText().then(function(text) { + return text === ">\nF\nMy Items"; + }); + }); + //browser.sleep(1000) + browser.actions().mouseMove(object.get(0)).perform(); + browser.actions().click(protractor.Button.RIGHT).perform(); + + element.all(by.css('.items-holder.grid.abs.ng-scope')).click(); + } + browser.pause(); + + }); + +});