Compare commits
	
		
			82 Commits
		
	
	
		
			issue-1826
			...
			summary-wi
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 28a3ada6af | ||
|   | ce0f24c86f | ||
|   | 6ca2a755dc | ||
|   | f6c1488ccd | ||
|   | 26be1ecf37 | ||
|   | 38f0f072bb | ||
|   | e5e969665f | ||
|   | ffbb662c99 | ||
|   | bd7b23f896 | ||
|   | c238def902 | ||
|   | 2d430ece7f | ||
|   | c92644a661 | ||
|   | 41ce3c04f7 | ||
|   | fcf77f359f | ||
|   | 40a2737915 | ||
|   | 216489d67f | ||
|   | 418a393b26 | ||
|   | 1f3d744494 | ||
|   | ff3f2dccba | ||
|   | e69973bd29 | ||
|   | 05b352cc36 | ||
|   | 9735548999 | ||
|   | f9529b1362 | ||
|   | c598cec702 | ||
|   | e9ea1c4a0f | ||
|   | e9238ff282 | ||
|   | 4cebd72cba | ||
|   | f8a44d6e71 | ||
|   | d0745b300b | ||
|   | 2a4e0a3081 | ||
|   | 1ff19f9574 | ||
|   | 7ef84cb50d | ||
|   | cd05c70d64 | ||
|   | 568473b82f | ||
|   | c61b074755 | ||
|   | 8ed66ab4ab | ||
|   | b2502dd998 | ||
|   | 856eedbf9d | ||
|   | 0c0ca6e6af | ||
|   | 498b797e49 | ||
|   | 02c33388ba | ||
|   | 8a8e3cc055 | ||
|   | 36d60b16e9 | ||
|   | de3114568b | ||
|   | eb5835faeb | ||
|   | ff1ddb0b79 | ||
|   | 15b127bb2e | ||
|   | e4ed881f6d | ||
|   | 7b62cf130c | ||
|   | 72fd2e531c | ||
|   | 4a5392ef78 | ||
|   | 0150a708ca | ||
|   | eacc181d5e | ||
|   | 405bb55881 | ||
|   | 4a35508459 | ||
|   | 98a9d71a2e | ||
|   | a1596d0b06 | ||
|   | 4b3be4c483 | ||
|   | 0fa8472db1 | ||
|   | e1e2dca1d8 | ||
|   | 755c013ec8 | ||
|   | eab702b763 | ||
|   | d15446ac91 | ||
|   | 500733afb2 | ||
|   | 2aa04b0a56 | ||
|   | c051f342af | ||
|   | 8aeb365f5f | ||
|   | 827a28313d | ||
|   | c83de8aad2 | ||
|   | b55f43b8df | ||
|   | 8466723a90 | ||
|   | a103b4dbff | ||
|   | 826ac3a947 | ||
|   | 597327f138 | ||
|   | bef79402ca | ||
|   | e68e0c381f | ||
|   | c73f7259c2 | ||
|   | 4c9235ba10 | ||
|   | 55e2a77df8 | ||
|   | cfbff02e7f | ||
|   | 54980fb296 | ||
|   | ba98d9315c | 
| @@ -21,6 +21,5 @@ | ||||
|     "shadow": "outer", | ||||
|     "strict": "implied", | ||||
|     "undef": true, | ||||
|     "unused": "vars", | ||||
|     "latedef": "nofunc" | ||||
|     "unused": "vars" | ||||
| } | ||||
|   | ||||
							
								
								
									
										17
									
								
								API.md
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								API.md
									
									
									
									
									
								
							| @@ -505,7 +505,7 @@ MCT, it will be pre-configured to use the UTC time system, which is installed an | ||||
|  | ||||
| The time bounds of an Open MCT application are defined as numbers, and a Time  | ||||
| System gives meaning and context to these numbers so that they can be correctly  | ||||
| interpreted. Time Systems are JavaScript objects that provide some information  | ||||
| interpreted. Time Systems are javscript objects that provide some information  | ||||
| about the current time reference frame. An example of defining and registering  | ||||
| a new time system is given below: | ||||
|  | ||||
| @@ -879,21 +879,6 @@ openmct.install(openmct.plugins.CouchDB('http://localhost:9200')) | ||||
| * `openmct.plugins.Espresso` and `openmct.plugins.Snow` are two different | ||||
|   themes (dark and light) available for Open MCT. Note that at least one | ||||
|   of these themes must be installed for Open MCT to appear correctly. | ||||
| * `openmct.plugins.URLIndicatorPlugin` adds an indicator which shows the | ||||
| availability of a URL with the following options:  | ||||
|   - `url` : URL to indicate the status of | ||||
|   - `cssClass`: Icon to show in the status bar, defaults to `icon-database`, [list of all icons](https://nasa.github.io/openmct/style-guide/#/browse/styleguide:home?view=items) | ||||
|   - `interval`: Interval between checking the connection, defaults to `10000` | ||||
|   - `label` Name showing up as text in the status bar, defaults to url | ||||
| ```javascript | ||||
| openmct.install(openmct.plugins.URLIndicatorPlugin({ | ||||
|   url: 'http://google.com', | ||||
|   cssClass: 'check', | ||||
|   interval: 10000, | ||||
|   label: 'Google' | ||||
|  }) | ||||
| ); | ||||
| ``` | ||||
| * `openmct.plugins.LocalStorage` provides persistence of user-created | ||||
|   objects in browser-local storage. This is particularly useful in | ||||
|   development environments. | ||||
|   | ||||
| @@ -88,7 +88,7 @@ and [`gulp`](http://gulpjs.com/). | ||||
|  | ||||
| To build Open MCT for deployment: | ||||
|  | ||||
| `npm run prepare` | ||||
| `npm run prepublish` | ||||
|  | ||||
| This will compile and minify JavaScript sources, as well as copy over assets. | ||||
| The contents of the `dist` folder will contain a runnable Open MCT | ||||
|   | ||||
| @@ -17,8 +17,8 @@ | ||||
|     "screenfull": "^3.0.0", | ||||
|     "node-uuid": "^1.4.7", | ||||
|     "comma-separated-values": "^3.6.4", | ||||
|     "file-saver": "^1.3.3", | ||||
|     "zepto": "^1.1.6", | ||||
|     "FileSaver.js": "^0.0.2", | ||||
|     "zepto": "1.2.0", | ||||
|     "eventemitter3": "^1.2.0", | ||||
|     "lodash": "3.10.1", | ||||
|     "almond": "~0.3.2", | ||||
|   | ||||
							
								
								
									
										16
									
								
								circle.yml
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								circle.yml
									
									
									
									
									
								
							| @@ -1,17 +1,15 @@ | ||||
| machine: | ||||
|   node: | ||||
|     version: 4.7.0 | ||||
|  | ||||
| dependencies: | ||||
|   pre: | ||||
|     - npm install -g npm@latest | ||||
|  | ||||
| deployment: | ||||
|   production: | ||||
|     branch: master | ||||
|     commands: | ||||
|         - npm install canvas nomnoml | ||||
|         - ./build-docs.sh | ||||
|         - git fetch --unshallow | ||||
|         - git push git@heroku.com:openmctweb-demo.git $CIRCLE_SHA1:refs/heads/master | ||||
|   openmct-demo: | ||||
|     branch: live_demo | ||||
|     heroku: | ||||
|       appname: openmct-demo | ||||
|   openmctweb-staging-deux: | ||||
|     branch: mobile | ||||
|     heroku: | ||||
| @@ -24,4 +22,4 @@ test: | ||||
| general: | ||||
|   branches: | ||||
|     ignore: | ||||
|       - gh-pages | ||||
|       - gh-pages | ||||
|   | ||||
| @@ -2283,7 +2283,7 @@ To install build dependencies (only needs to be run once): | ||||
|  | ||||
| To build: | ||||
|  | ||||
| `npm run prepare` | ||||
| `npm run prepublish` | ||||
|  | ||||
| This will compile and minify JavaScript sources, as well as copy over assets. | ||||
| The contents of the `dist` folder will contain a runnable Open MCT | ||||
|   | ||||
| @@ -78,8 +78,8 @@ define([ | ||||
|         return this.workerInterface.request(workerRequest); | ||||
|     }; | ||||
|  | ||||
|     GeneratorProvider.prototype.subscribe = function (domainObject, callback) { | ||||
|         var workerRequest = this.makeWorkerRequest(domainObject, {}); | ||||
|     GeneratorProvider.prototype.subscribe = function (domainObject, callback, request) { | ||||
|         var workerRequest = this.makeWorkerRequest(domainObject, request); | ||||
|         return this.workerInterface.subscribe(workerRequest, callback); | ||||
|     }; | ||||
|  | ||||
|   | ||||
| @@ -44,7 +44,9 @@ define([ | ||||
|         message = message.data; | ||||
|         var callback = this.callbacks[message.id]; | ||||
|         if (callback) { | ||||
|             callback(message); | ||||
|             if (callback(message)) { | ||||
|                 delete this.callbacks[message.id]; | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
|  | ||||
| @@ -70,7 +72,6 @@ define([ | ||||
|             deferred.resolve = resolve; | ||||
|             deferred.reject = reject; | ||||
|         }); | ||||
|         var messageId; | ||||
|  | ||||
|         function callback(message) { | ||||
|             if (message.error) { | ||||
| @@ -78,27 +79,33 @@ define([ | ||||
|             } else { | ||||
|                 deferred.resolve(message.data); | ||||
|             } | ||||
|             delete this.callbacks[messageId]; | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         messageId = this.dispatch('request', request, callback.bind(this)); | ||||
|         this.dispatch('request', request, callback); | ||||
|  | ||||
|         return promise; | ||||
|     }; | ||||
|  | ||||
|     WorkerInterface.prototype.subscribe = function (request, cb) { | ||||
|         function callback(message) { | ||||
|         var isCancelled = false; | ||||
|  | ||||
|         var callback = function (message) { | ||||
|             if (isCancelled) { | ||||
|                 return true; | ||||
|             } | ||||
|             cb(message.data); | ||||
|         }; | ||||
|  | ||||
|         var messageId = this.dispatch('subscribe', request, callback); | ||||
|         var messageId = this.dispatch('subscribe', request, callback) | ||||
|  | ||||
|         return function () { | ||||
|             isCancelled = true; | ||||
|             this.dispatch('unsubscribe', { | ||||
|                 id: messageId | ||||
|             }); | ||||
|             delete this.callbacks[messageId]; | ||||
|         }.bind(this); | ||||
|  | ||||
|     }; | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -16,7 +16,6 @@ define([ | ||||
|                 { "key": "styleguide.intro", "name": "Introduction", "cssClass": "icon-page", "description": "Introduction and overview to the style guide" }, | ||||
|                 { "key": "styleguide.standards", "name": "Standards", "cssClass": "icon-page", "description": "" }, | ||||
|                 { "key": "styleguide.colors", "name": "Colors", "cssClass": "icon-page", "description": "" }, | ||||
|                 { "key": "styleguide.status", "name": "status", "cssClass": "icon-page", "description": "Limits, telemetry paused, etc." }, | ||||
|                 { "key": "styleguide.glyphs", "name": "Glyphs", "cssClass": "icon-page", "description": "Glyphs overview" }, | ||||
|                 { "key": "styleguide.controls", "name": "Controls", "cssClass": "icon-page", "description": "Buttons, selects, HTML controls" }, | ||||
|                 { "key": "styleguide.input", "name": "Text Inputs", "cssClass": "icon-page", "description": "Various text inputs" }, | ||||
| @@ -26,7 +25,6 @@ define([ | ||||
|                 { "key": "styleguide.intro", "type": "styleguide.intro", "templateUrl": "templates/intro.html", "editable": false }, | ||||
|                 { "key": "styleguide.standards", "type": "styleguide.standards", "templateUrl": "templates/standards.html", "editable": false }, | ||||
|                 { "key": "styleguide.colors", "type": "styleguide.colors", "templateUrl": "templates/colors.html", "editable": false }, | ||||
|                 { "key": "styleguide.status", "type": "styleguide.status", "templateUrl": "templates/status.html", "editable": false }, | ||||
|                 { "key": "styleguide.glyphs", "type": "styleguide.glyphs", "templateUrl": "templates/glyphs.html", "editable": false }, | ||||
|                 { "key": "styleguide.controls", "type": "styleguide.controls", "templateUrl": "templates/controls.html", "editable": false }, | ||||
|                 { "key": "styleguide.input", "type": "styleguide.input", "templateUrl": "templates/input.html", "editable": false }, | ||||
| @@ -49,7 +47,6 @@ define([ | ||||
|                             "intro", | ||||
|                             "standards", | ||||
|                             "colors", | ||||
|                             "status", | ||||
|                             "glyphs", | ||||
|                             "styleguide:ui-elements" | ||||
|                         ] | ||||
|   | ||||
| @@ -28,8 +28,8 @@ | ||||
|         color: $colorKey; | ||||
|     } | ||||
|  | ||||
|     h1, h2, strong, b { | ||||
|         color: pullForward($colorBodyFg, 50%); | ||||
|     h1, h2 { | ||||
|         color: pullForward($colorBodyFg, 20%); | ||||
|     } | ||||
|  | ||||
|     h2 { | ||||
| @@ -45,10 +45,6 @@ | ||||
|         text-transform: uppercase; | ||||
|     } | ||||
|  | ||||
|     strong, b { | ||||
|         font-weight: normal; | ||||
|     } | ||||
|  | ||||
|     .w-markup { | ||||
|         //Wrap markup example "pre" element | ||||
|         background-color: $colorCode; | ||||
| @@ -58,12 +54,6 @@ | ||||
|         position: relative; | ||||
|     } | ||||
|  | ||||
|     .w-mct-example { | ||||
|         div { | ||||
|             margin-bottom: $interiorMarginLg; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     code, | ||||
|     pre { | ||||
|         font-size: 0.8rem; | ||||
|   | ||||
| @@ -127,8 +127,7 @@ | ||||
| { 'meaning': 'Timer object', 'cssClass': 'icon-timer', 'cssContent': 'e1127', 'htmlEntity': '&#xe1127' }, | ||||
| { 'meaning': 'Data Topic', 'cssClass': 'icon-topic', 'cssContent': 'e1128', 'htmlEntity': '&#xe1128' }, | ||||
| { 'meaning': 'Fixed Position object', 'cssClass': 'icon-box-with-dashed-lines', 'cssContent': 'e1129', 'htmlEntity': '&#xe1129' }, | ||||
| { 'meaning': 'Summary Widget', 'cssClass': 'icon-summary-widget', 'cssContent': 'e1130', 'htmlEntity': '&#xe1130' }, | ||||
| { 'meaning': 'Notebook object', 'cssClass': 'icon-notebook', 'cssContent': 'e1131', 'htmlEntity': '&#xe1131' } | ||||
| { 'meaning': 'Summary Widget', 'cssClass': 'icon-summary-widget', 'cssContent': 'e1130', 'htmlEntity': '&#xe1130' } | ||||
| ]; | ||||
| "></div> | ||||
|  | ||||
|   | ||||
| @@ -4,5 +4,5 @@ | ||||
|         <pre></pre> | ||||
|     </span> | ||||
|     <h3>Example</h3> | ||||
|     <div class="w-mct-example"></div> | ||||
|     <div></div> | ||||
| </div> | ||||
|   | ||||
| @@ -1,142 +0,0 @@ | ||||
| <!-- | ||||
|  Open MCT, Copyright (c) 2014-2016, United States Government | ||||
|  as represented by the Administrator of the National Aeronautics and Space | ||||
|  Administration. All rights reserved. | ||||
|  | ||||
|  Open MCT 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 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. | ||||
| --> | ||||
| <style> | ||||
|     .w-mct-example div[class*="s-limit"], | ||||
|     .w-mct-example div[class*="s-status"], | ||||
|     .w-mct-example div[class*="s-unsynced"], | ||||
|     .w-mct-example span[class*="s-limit"] { | ||||
|         border-radius: 4px; | ||||
|         padding: 3px 7px; | ||||
|     } | ||||
|     .w-mct-example table { | ||||
|         width: 100%; | ||||
|     } | ||||
| </style> | ||||
| <div class="l-style-guide s-text"> | ||||
|     <p class="doc-title">Open MCT Style Guide</p> | ||||
|     <h1>Status Indication</h1> | ||||
|  | ||||
|     <div class="l-section"> | ||||
|         <h2>Overview</h2> | ||||
|         <p>Many elements in Open MCT need to articulate a dynamic status; Open MCT provides the following styles and conventions to handle this:</p> | ||||
|         <ul> | ||||
|             <li><strong>Limits</strong>: when telemetry values exceed minimum or maximum values, they can be violating limits. Limit styles include both color and iconography; color is used to indicate severity while icons are used to indicate direction, upper or lower.</li> | ||||
|             <li><strong>Status</strong>: Open MCT also provides a number or built-in Status styles allowing telemetry or other displayed information to be visually classified by type. Common uses for these classes are to visually denote event records.</li> | ||||
|             <li><strong>Synchronization</strong>: When the system is displaying real-time data, it is very important that displays clearly indicate when they are not doing so, such as when a plot if frozen while panning or zooming. Open MCT provides a style for this.</li> | ||||
|         </ul> | ||||
|     </div> | ||||
|  | ||||
|     <div class="l-section"> | ||||
|         <h2>Limits</h2> | ||||
|         <div class="cols cols1-1"> | ||||
|             <div class="col"> | ||||
|                 <p>Limit CSS classes can be applied to any block or inline element. Open MCT limit classes set color and optionally an icon, but don't effect other properties. Yellow and red limit classes can be used as is, or allow the application of any custom icon available in Open MCT's glyphs library. "Level" limit classes - upper and lower - always use an icon in addition to a color; Open MCT doesn't support level limits without color.</p> | ||||
|                 <ul> | ||||
|                     <li>Color only</li> | ||||
|                     <ul> | ||||
|                         <li><code>s-limit-yellow</code>: A yellow limit.</li> | ||||
|                         <li><code>s-limit-red</code>: A red limit.</li> | ||||
|                     </ul> | ||||
|                     <li>Color and icon</li> | ||||
|                     <ul> | ||||
|                         <li><code>s-limit-yellow-icon</code>: A yellow limit with icon.</li> | ||||
|                         <li><code>s-limit-red-icon</code>: A red limit with icon.</li> | ||||
|                     </ul> | ||||
|                     <li>Upper and lower limit indicators. Must be used with a color limit class to be visible.</li> | ||||
|                     <ul> | ||||
|                         <li><code>s-limit-upr</code>: Upper limit. | ||||
|                         </li> | ||||
|                         <li><code>s-limit-lwr</code>: Lower limit. | ||||
|                         </li> | ||||
|                     </ul> | ||||
|                 </ul> | ||||
|             </div> | ||||
| <mct-example><div class="s-limit-yellow">Yellow limit</div> | ||||
| <div class="s-limit-red">Red limit</div> | ||||
| <div class="s-limit-yellow-icon">Yellow limit with icon</div> | ||||
| <div class="s-limit-red-icon">Red limit with icon</div> | ||||
| <div class="s-limit-yellow s-limit-lwr">Lower yellow limit</div> | ||||
| <div class="s-limit-red s-limit-upr">Upper red limit</div> | ||||
| <div class="s-limit-red icon-bell">Red Limit with a custom icon</div> | ||||
| <div>Some text with an <span class="s-limit-yellow-icon">inline element</span> showing a yellow limit.</div> | ||||
|  | ||||
| <!-- Limits applied in a table --> | ||||
| <table> | ||||
|     <tr class='header'><td>Name</td><td>Value 1</td><td>Value 2</td></tr> | ||||
|     <tr><td>ENG_PWR 4991</td><td>7.023</td><td class="s-limit-yellow s-limit-upr">70.23</td></tr> | ||||
|     <tr><td>ENG_PWR 4992</td><td>49.784</td><td class="s-limit-red s-limit-lwr">-121.22</td></tr> | ||||
|     <tr><td>ENG_PWR 4993</td><td class="s-limit-yellow icon-bell">0.451</td><td>1.007</td></tr> | ||||
| </table> | ||||
| </mct-example> | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
|     <div class="l-section"> | ||||
|         <h2>Status</h2> | ||||
|         <div class="cols cols1-1"> | ||||
|             <div class="col"> | ||||
|                 <p>Classes here can be applied to elements as needed.</p> | ||||
|                 <ul> | ||||
|                     <li>Color only</li> | ||||
|                     <ul> | ||||
|                         <li><code>s-status-warning-hi</code></li> | ||||
|                         <li><code>s-status-warning-lo</code></li> | ||||
|                         <li><code>s-status-diagnostic</code></li> | ||||
|                         <li><code>s-status-info</code></li> | ||||
|                         <li><code>s-status-ok</code></li> | ||||
|                     </ul> | ||||
|                     <li>Color and icon</li> | ||||
|                     <ul> | ||||
|                         <li><code>s-status-warning-hi-icon</code></li> | ||||
|                         <li><code>s-status-warning-lo-icon</code></li> | ||||
|                         <li><code>s-status-diagnostic-icon</code></li> | ||||
|                         <li><code>s-status-info-icon</code></li> | ||||
|                         <li><code>s-status-ok-icon</code></li> | ||||
|                     </ul> | ||||
|                 </ul> | ||||
|             </div> | ||||
| <mct-example><div class="s-status-warning-hi">WARNING HI</div> | ||||
| <div class="s-status-warning-lo">WARNING LOW</div> | ||||
| <div class="s-status-diagnostic">DIAGNOSTIC</div> | ||||
| <div class="s-status-info">INFO</div> | ||||
| <div class="s-status-ok">OK</div> | ||||
| <div class="s-status-warning-hi-icon">WARNING HI with icon</div> | ||||
| <div class="s-status-warning-lo-icon">WARNING LOW with icon</div> | ||||
| <div class="s-status-diagnostic-icon">DIAGNOSTIC with icon</div> | ||||
| <div class="s-status-info-icon">INFO with icon</div> | ||||
| <div class="s-status-ok-icon">OK with icon</div> | ||||
| <div class="s-status-warning-hi icon-gear">WARNING HI with custom icon</div> | ||||
| </mct-example> | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
|     <div class="l-section"> | ||||
|         <h2>Synchronization</h2> | ||||
|         <div class="cols cols1-1"> | ||||
|             <div class="col"> | ||||
|                 <p>When the system is operating in real-time streaming mode, it is important for views that display real-time data to clearly articulate when they are not, such as when a user zooms or pans a plot view, freezing that view. In that case, the CSS class <code>s-unsynced</code> should be applied to that view.</p> | ||||
|             </div> | ||||
| <mct-example><div class="s-unsynced">This element is unsynced</div> | ||||
| </mct-example> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
| @@ -34,7 +34,6 @@ define( | ||||
|             pages['standards'] = { name: "Standards", type: "styleguide.standards", location: "styleguide:home" }; | ||||
|             pages['colors'] = { name: "Colors", type: "styleguide.colors", location: "styleguide:home" }; | ||||
|             pages['glyphs'] = { name: "Glyphs", type: "styleguide.glyphs", location: "styleguide:home" }; | ||||
|             pages['status'] = { name: "Status Indication", type: "styleguide.status", location: "styleguide:home" }; | ||||
|             pages['controls'] = { name: "Controls", type: "styleguide.controls", location: "styleguide:ui-elements" }; | ||||
|             pages['input'] = { name: "Text Inputs", type: "styleguide.input", location: "styleguide:ui-elements" }; | ||||
|             pages['menus'] = { name: "Menus", type: "styleguide.menus", location: "styleguide:ui-elements" }; | ||||
|   | ||||
							
								
								
									
										32
									
								
								gulpfile.js
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								gulpfile.js
									
									
									
									
									
								
							| @@ -22,8 +22,6 @@ | ||||
|  | ||||
| /*global require,__dirname*/ | ||||
|  | ||||
| require("v8-compile-cache"); | ||||
|  | ||||
| var gulp = require('gulp'), | ||||
|     sourcemaps = require('gulp-sourcemaps'), | ||||
|     path = require('path'), | ||||
| @@ -48,22 +46,9 @@ var gulp = require('gulp'), | ||||
|             name: 'bower_components/almond/almond.js', | ||||
|             include: paths.main.replace('.js', ''), | ||||
|             wrap: { | ||||
|                 start: (function () { | ||||
|                     var buildVariables = { | ||||
|                         version: project.version, | ||||
|                         timestamp: moment.utc(Date.now()).format(), | ||||
|                         revision: fs.existsSync('.git') ? git.long() : 'Unknown', | ||||
|                         branch: fs.existsSync('.git') ? git.branch() : 'Unknown' | ||||
|                     }; | ||||
|                     return fs.readFileSync("src/start.frag", 'utf-8') | ||||
|                         .replace(/@@(\w+)/g, function (match, key) { | ||||
|                             return buildVariables[key]; | ||||
|                         });; | ||||
|                 }()), | ||||
|                 startFile: "src/start.frag", | ||||
|                 endFile: "src/end.frag" | ||||
|             }, | ||||
|             optimize: 'uglify2', | ||||
|             uglify2: { output: { comments: /@preserve/ } }, | ||||
|             mainConfigFile: paths.main, | ||||
|             wrapShim: true | ||||
|         }, | ||||
| @@ -73,6 +58,14 @@ var gulp = require('gulp'), | ||||
|         }, | ||||
|         sass: { | ||||
|             sourceComments: true | ||||
|         }, | ||||
|         replace: { | ||||
|             variables: { | ||||
|                 version: project.version, | ||||
|                 timestamp: moment.utc(Date.now()).format(), | ||||
|                 revision: fs.existsSync('.git') ? git.long() : 'Unknown', | ||||
|                 branch: fs.existsSync('.git') ? git.branch() : 'Unknown' | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
|  | ||||
| @@ -83,11 +76,16 @@ if (process.env.NODE_ENV === 'development') { | ||||
|  | ||||
| gulp.task('scripts', function () { | ||||
|     var requirejsOptimize = require('gulp-requirejs-optimize'); | ||||
|     var replace = require('gulp-replace-task'); | ||||
|     var header = require('gulp-header'); | ||||
|     var comment = fs.readFileSync('src/about.frag'); | ||||
|  | ||||
|     return gulp.src(paths.main) | ||||
|         .pipe(sourcemaps.init()) | ||||
|         .pipe(requirejsOptimize(options.requirejsOptimize)) | ||||
|         .pipe(sourcemaps.write('.')) | ||||
|         .pipe(replace(options.replace)) | ||||
|         .pipe(header(comment, options.replace.variables)) | ||||
|         .pipe(gulp.dest(paths.dist)); | ||||
| }); | ||||
|  | ||||
| @@ -179,4 +177,4 @@ gulp.task('install', [ 'assets', 'scripts' ]); | ||||
|  | ||||
| gulp.task('verify', [ 'lint', 'test', 'checkstyle' ]); | ||||
|  | ||||
| gulp.task('build', [ 'verify', 'install' ]); | ||||
| gulp.task('build', [ 'verify', 'install' ]); | ||||
|   | ||||
| @@ -42,17 +42,13 @@ | ||||
|             openmct.install(openmct.plugins.Generator()); | ||||
|             openmct.install(openmct.plugins.ExampleImagery()); | ||||
|             openmct.install(openmct.plugins.UTCTimeSystem()); | ||||
|             openmct.install(openmct.plugins.ImportExport()); | ||||
|             openmct.install(openmct.plugins.AutoflowView({ | ||||
|                 type: "telemetry.panel" | ||||
|             })); | ||||
|             openmct.install(openmct.plugins.Conductor({ | ||||
|                 menuOptions: [ | ||||
|                     { | ||||
|                         name: "Fixed", | ||||
|                         timeSystem: 'utc', | ||||
|                         bounds: { | ||||
|                             start: Date.now() - THIRTY_MINUTES, | ||||
|                             start: Date.now() - 30 * 60 * 1000, | ||||
|                             end: Date.now() | ||||
|                         } | ||||
|                     }, | ||||
|   | ||||
| @@ -36,7 +36,6 @@ module.exports = function(config) { | ||||
|         files: [ | ||||
|             {pattern: 'bower_components/**/*.js', included: false}, | ||||
|             {pattern: 'node_modules/d3-*/**/*.js', included: false}, | ||||
|             {pattern: 'node_modules/vue/**/*.js', included: false}, | ||||
|             {pattern: 'src/**/*.js', included: false}, | ||||
|             {pattern: 'example/**/*.html', included: false}, | ||||
|             {pattern: 'example/**/*.js', included: false}, | ||||
|   | ||||
							
								
								
									
										17
									
								
								openmct.js
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								openmct.js
									
									
									
									
									
								
							| @@ -19,7 +19,7 @@ | ||||
|  * this source code distribution or the Licensing information page available | ||||
|  * at runtime from the About dialog for additional information. | ||||
|  *****************************************************************************/ | ||||
| /*global requirejs,BUILD_CONSTANTS*/ | ||||
| /*global requirejs*/ | ||||
|  | ||||
| requirejs.config({ | ||||
|     "paths": { | ||||
| @@ -33,11 +33,10 @@ requirejs.config({ | ||||
|         "moment": "bower_components/moment/moment", | ||||
|         "moment-duration-format": "bower_components/moment-duration-format/lib/moment-duration-format", | ||||
|         "moment-timezone": "bower_components/moment-timezone/builds/moment-timezone-with-data", | ||||
|         "saveAs": "bower_components/file-saver/FileSaver.min", | ||||
|         "saveAs": "bower_components/FileSaver.js/FileSaver.min", | ||||
|         "screenfull": "bower_components/screenfull/dist/screenfull.min", | ||||
|         "text": "bower_components/text/text", | ||||
|         "uuid": "bower_components/node-uuid/uuid", | ||||
|         "vue": "node_modules/vue/dist/vue.min", | ||||
|         "zepto": "bower_components/zepto/zepto.min", | ||||
|         "lodash": "bower_components/lodash/lodash", | ||||
|         "d3-selection": "node_modules/d3-selection/build/d3-selection.min", | ||||
| @@ -67,9 +66,6 @@ requirejs.config({ | ||||
|         "moment-duration-format": { | ||||
|             "deps": ["moment"] | ||||
|         }, | ||||
|         "saveAs": { | ||||
|             "exports": "saveAs" | ||||
|         }, | ||||
|         "screenfull": { | ||||
|             "exports": "screenfull" | ||||
|         }, | ||||
| @@ -95,17 +91,12 @@ requirejs.config({ | ||||
| define([ | ||||
|     './platform/framework/src/Main', | ||||
|     './src/defaultRegistry', | ||||
|     './src/MCT', | ||||
|     './src/plugins/buildInfo/plugin' | ||||
| ], function (Main, defaultRegistry, MCT, buildInfo) { | ||||
|     './src/MCT' | ||||
| ], function (Main, defaultRegistry, MCT) { | ||||
|     var openmct = new MCT(); | ||||
|  | ||||
|     openmct.legacyRegistry = defaultRegistry; | ||||
|  | ||||
|     if (typeof BUILD_CONSTANTS !== 'undefined') { | ||||
|         openmct.install(buildInfo(BUILD_CONSTANTS)); | ||||
|     } | ||||
|  | ||||
|     openmct.on('start', function () { | ||||
|         return new Main().run(defaultRegistry); | ||||
|     }); | ||||
|   | ||||
							
								
								
									
										10
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								package.json
									
									
									
									
									
								
							| @@ -15,18 +15,19 @@ | ||||
|     "d3-time-format": "^2.0.3", | ||||
|     "express": "^4.13.1", | ||||
|     "minimist": "^1.1.1", | ||||
|     "request": "^2.69.0", | ||||
|     "vue": "^2.5.6" | ||||
|     "request": "^2.69.0" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "bower": "^1.7.7", | ||||
|     "git-rev-sync": "^1.4.0", | ||||
|     "glob": ">= 3.0.0", | ||||
|     "gulp": "^3.9.1", | ||||
|     "gulp-header": "^1.8.8", | ||||
|     "gulp-jscs": "^3.0.2", | ||||
|     "gulp-jshint": "^2.0.0", | ||||
|     "gulp-jshint-html-reporter": "^0.1.3", | ||||
|     "gulp-rename": "^1.2.2", | ||||
|     "gulp-replace-task": "^0.11.0", | ||||
|     "gulp-requirejs-optimize": "^0.3.1", | ||||
|     "gulp-sass": "^2.2.0", | ||||
|     "gulp-sourcemaps": "^1.6.0", | ||||
| @@ -50,8 +51,7 @@ | ||||
|     "moment": "^2.11.1", | ||||
|     "node-bourbon": "^4.2.3", | ||||
|     "requirejs": "2.1.x", | ||||
|     "split": "^1.0.0", | ||||
|     "v8-compile-cache": "^1.1.0" | ||||
|     "split": "^1.0.0" | ||||
|   }, | ||||
|   "scripts": { | ||||
|     "start": "node app.js", | ||||
| @@ -61,7 +61,7 @@ | ||||
|     "jsdoc": "jsdoc -c jsdoc.json -R API.md -r -d dist/docs/api", | ||||
|     "otherdoc": "node docs/gendocs.js --in docs/src --out dist/docs --suppress-toc 'docs/src/index.md|docs/src/process/index.md'", | ||||
|     "docs": "npm run jsdoc ; npm run otherdoc", | ||||
|     "prepare": "node ./node_modules/bower/bin/bower install && node ./node_modules/gulp/bin/gulp.js install" | ||||
|     "prepublish": "node ./node_modules/bower/bin/bower install && node ./node_modules/gulp/bin/gulp.js install" | ||||
|   }, | ||||
|   "repository": { | ||||
|     "type": "git", | ||||
|   | ||||
| @@ -26,7 +26,6 @@ define([ | ||||
|     "./src/InspectorPaneController", | ||||
|     "./src/BrowseObjectController", | ||||
|     "./src/MenuArrowController", | ||||
|     "./src/ObjectHeaderController", | ||||
|     "./src/navigation/NavigationService", | ||||
|     "./src/navigation/NavigateAction", | ||||
|     "./src/navigation/OrphanNavigationHandler", | ||||
| @@ -37,7 +36,6 @@ define([ | ||||
|     "text!./res/templates/browse-object.html", | ||||
|     "text!./res/templates/items/grid-item.html", | ||||
|     "text!./res/templates/browse/object-header.html", | ||||
|     "text!./res/templates/browse/object-header-frame.html", | ||||
|     "text!./res/templates/menu-arrow.html", | ||||
|     "text!./res/templates/back-arrow.html", | ||||
|     "text!./res/templates/items/items.html", | ||||
| @@ -50,7 +48,6 @@ define([ | ||||
|     InspectorPaneController, | ||||
|     BrowseObjectController, | ||||
|     MenuArrowController, | ||||
|     ObjectHeaderController, | ||||
|     NavigationService, | ||||
|     NavigateAction, | ||||
|     OrphanNavigationHandler, | ||||
| @@ -61,7 +58,6 @@ define([ | ||||
|     browseObjectTemplate, | ||||
|     gridItemTemplate, | ||||
|     objectHeaderTemplate, | ||||
|     objectHeaderFrameTemplate, | ||||
|     menuArrowTemplate, | ||||
|     backArrowTemplate, | ||||
|     itemsTemplate, | ||||
| @@ -144,13 +140,6 @@ define([ | ||||
|                         "$location", | ||||
|                         "$attrs" | ||||
|                     ] | ||||
|                 }, | ||||
|                 { | ||||
|                     "key": "ObjectHeaderController", | ||||
|                     "implementation": ObjectHeaderController, | ||||
|                     "depends": [ | ||||
|                         "$scope" | ||||
|                     ] | ||||
|                 } | ||||
|             ], | ||||
|             "representations": [ | ||||
| @@ -184,13 +173,6 @@ define([ | ||||
|                         "type" | ||||
|                     ] | ||||
|                 }, | ||||
|                 { | ||||
|                     "key": "object-header-frame", | ||||
|                     "template": objectHeaderFrameTemplate, | ||||
|                     "uses": [ | ||||
|                         "type" | ||||
|                     ] | ||||
|                 }, | ||||
|                 { | ||||
|                     "key": "menu-arrow", | ||||
|                     "template": menuArrowTemplate, | ||||
|   | ||||
| @@ -57,12 +57,7 @@ | ||||
|             </div> | ||||
|             <mct-representation key="representation.selected.key" | ||||
|                                 mct-object="representation.selected.key && domainObject" | ||||
|                                 class="abs flex-elem grows object-holder-main scroll" | ||||
|                                 mct-selectable="{ | ||||
|                                     item: domainObject.useCapability('adapter'), | ||||
|                                     oldItem: domainObject | ||||
|                                 }" | ||||
|                                 mct-init-select> | ||||
|                                 class="abs flex-elem grows object-holder-main scroll"> | ||||
|             </mct-representation> | ||||
|         </div> | ||||
|     </div> | ||||
|   | ||||
| @@ -19,21 +19,12 @@ | ||||
|  this source code distribution or the Licensing information page available | ||||
|  at runtime from the About dialog for additional information. | ||||
| --> | ||||
| <div ng-controller="InspectorController as controller"> | ||||
| <div ng-controller="InspectorController"> | ||||
|     <div ng-repeat="region in regions"> | ||||
|         <mct-representation | ||||
|                 key="'object-properties'" | ||||
|                 mct-object="controller.selectedItem()" | ||||
|                 key="region.content.key" | ||||
|                 mct-object="domainObject" | ||||
|                 ng-model="ngModel"> | ||||
|         </mct-representation> | ||||
|  | ||||
|         <div ng-if="!controller.hasProviderView()"> | ||||
|             <mct-representation | ||||
|                     key="inspectorKey" | ||||
|                     mct-object="controller.selectedItem()" | ||||
|                     ng-model="ngModel"> | ||||
|             </mct-representation> | ||||
|         </div> | ||||
|  | ||||
|         <div class='inspector-provider-view'> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
|   | ||||
| @@ -1,31 +0,0 @@ | ||||
| <!-- | ||||
|  Open MCT, Copyright (c) 2014-2017, United States Government | ||||
|  as represented by the Administrator of the National Aeronautics and Space | ||||
|  Administration. All rights reserved. | ||||
|  | ||||
|  Open MCT 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 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. | ||||
| --> | ||||
| <span class='type-icon flex-elem {{type.getCssClass()}}'></span> | ||||
| <span class="l-elem-wrapper l-flex-row flex-elem grows" ng-controller="ObjectHeaderController as controller"> | ||||
|     <span ng-if="parameters.mode" class='action flex-elem'>{{parameters.mode}}</span> | ||||
|     <span class='title-label flex-elem holder flex-can-shrink s-input-inline'>{{model.name}}</span> | ||||
|     <span class='t-object-alert t-alert-unsynced flex-elem holder' title='This object is not currently displaying real-time data'></span> | ||||
|     <mct-representation | ||||
|         key="'menu-arrow'" | ||||
|         mct-object='domainObject' | ||||
|         class="flex-elem context-available-w"></mct-representation> | ||||
| </span> | ||||
| @@ -20,13 +20,9 @@ | ||||
|  at runtime from the About dialog for additional information. | ||||
| --> | ||||
| <span class='type-icon flex-elem {{type.getCssClass()}}'></span> | ||||
| <span class="l-elem-wrapper l-flex-row flex-elem grows" ng-controller="ObjectHeaderController as controller"> | ||||
| <span class="l-elem-wrapper l-flex-row flex-elem grows"> | ||||
|     <span ng-if="parameters.mode" class='action flex-elem'>{{parameters.mode}}</span> | ||||
|     <span ng-attr-contenteditable="{{ controller.editable ? true : undefined }}" | ||||
| 		class='title-label flex-elem holder flex-can-shrink s-input-inline' | ||||
| 		ng-click="controller.edit()" | ||||
| 		ng-blur="controller.updateName($event)" | ||||
| 		ng-keypress="controller.updateName($event)">{{model.name}}</span> | ||||
|     <span class='title-label flex-elem holder flex-can-shrink'>{{model.name}}</span> | ||||
|     <span class='t-object-alert t-alert-unsynced flex-elem holder' title='This object is not currently displaying real-time data'></span> | ||||
|     <mct-representation | ||||
|         key="'menu-arrow'" | ||||
|   | ||||
| @@ -38,6 +38,8 @@ | ||||
|                   ng-class="{ last:($index + 1) === contextualParents.length }"> | ||||
|                 <mct-representation key="'label'" | ||||
|                                     mct-object="parent" | ||||
|                                     ng-model="ngModel" | ||||
|                                     ng-click="ngModel.selectedObject = parent" | ||||
|                                     class="location-item"> | ||||
|                 </mct-representation> | ||||
|             </span> | ||||
| @@ -49,6 +51,8 @@ | ||||
|                   ng-class="{ last:($index + 1) === primaryParents.length }"> | ||||
|                 <mct-representation key="'label'" | ||||
|                                     mct-object="parent" | ||||
|                                     ng-model="ngModel" | ||||
|                                     ng-click="ngModel.selectedObject = parent" | ||||
|                                     class="location-item"> | ||||
|                 </mct-representation> | ||||
|             </span> | ||||
|   | ||||
| @@ -1,92 +0,0 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2017, United States Government | ||||
|  * as represented by the Administrator of the National Aeronautics and Space | ||||
|  * Administration. All rights reserved. | ||||
|  * | ||||
|  * Open MCT 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 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. | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| define( | ||||
|     [], | ||||
|     function () { | ||||
|  | ||||
|         /** | ||||
|          * Controller to provide the ability to inline edit an object name. | ||||
|          * | ||||
|          * @constructor | ||||
|          * @memberof platform/commonUI/browse | ||||
|          */ | ||||
|         function ObjectHeaderController($scope) { | ||||
|             this.$scope = $scope; | ||||
|             this.domainObject = $scope.domainObject; | ||||
|             this.editable = this.allowEdit(); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Updates the object name on blur and enter keypress events. | ||||
|          * | ||||
|          * @param event the mouse event | ||||
|          */ | ||||
|         ObjectHeaderController.prototype.updateName = function (event) { | ||||
|             if (!event || !event.currentTarget) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             if (event.type === 'blur') { | ||||
|                 this.updateModel(event); | ||||
|             } else if (event.which === 13) { | ||||
|                 this.updateModel(event); | ||||
|                 event.currentTarget.blur(); | ||||
|                 window.getSelection().removeAllRanges(); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Updates the model. | ||||
|          * | ||||
|          * @param event the mouse event | ||||
|          * @param private | ||||
|          */ | ||||
|         ObjectHeaderController.prototype.updateModel = function (event) { | ||||
|             var name = event.currentTarget.textContent.replace(/\n/g, ' '); | ||||
|  | ||||
|             if (name.length === 0) { | ||||
|                 name = "Unnamed " + this.domainObject.getCapability("type").typeDef.name; | ||||
|                 event.currentTarget.textContent = name; | ||||
|             } | ||||
|  | ||||
|             if (name !== this.domainObject.getModel().name) { | ||||
|                 this.domainObject.getCapability('mutation').mutate(function (model) { | ||||
|                     model.name = name; | ||||
|                 }); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Checks if the domain object is editable. | ||||
|          * | ||||
|          * @private | ||||
|          * @return true if object is editable | ||||
|          */ | ||||
|         ObjectHeaderController.prototype.allowEdit = function () { | ||||
|             var type = this.domainObject && this.domainObject.getCapability('type'); | ||||
|             return !!(type && type.hasFeature('creation')); | ||||
|         }; | ||||
|  | ||||
|         return ObjectHeaderController; | ||||
|     } | ||||
| ); | ||||
| @@ -1,137 +0,0 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2017, United States Government | ||||
|  * as represented by the Administrator of the National Aeronautics and Space | ||||
|  * Administration. All rights reserved. | ||||
|  * | ||||
|  * Open MCT 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 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. | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| define( | ||||
|     ["../src/ObjectHeaderController"], | ||||
|     function (ObjectHeaderController) { | ||||
|  | ||||
|         describe("The object header controller", function () { | ||||
|             var mockScope, | ||||
|                 mockDomainObject, | ||||
|                 mockCapabilities, | ||||
|                 mockMutationCapability, | ||||
|                 mockTypeCapability, | ||||
|                 mockEvent, | ||||
|                 mockCurrentTarget, | ||||
|                 model, | ||||
|                 controller; | ||||
|  | ||||
|             beforeEach(function () { | ||||
|                 mockMutationCapability = jasmine.createSpyObj("mutation", ["mutate"]); | ||||
|                 mockTypeCapability = jasmine.createSpyObj("type", ["typeDef", "hasFeature"]); | ||||
|                 mockTypeCapability.typeDef = { name: ""}; | ||||
|                 mockTypeCapability.hasFeature.andCallFake(function (feature) { | ||||
|                     return feature === 'creation'; | ||||
|                 }); | ||||
|  | ||||
|                 mockCapabilities = { | ||||
|                     mutation: mockMutationCapability, | ||||
|                     type: mockTypeCapability | ||||
|                 }; | ||||
|  | ||||
|                 model = { | ||||
|                     name: "Test name" | ||||
|                 }; | ||||
|                 mockDomainObject = jasmine.createSpyObj("domainObject", ["getCapability", "getModel"]); | ||||
|                 mockDomainObject.getModel.andReturn(model); | ||||
|                 mockDomainObject.getCapability.andCallFake(function (key) { | ||||
|                     return mockCapabilities[key]; | ||||
|                 }); | ||||
|  | ||||
|                 mockScope = { | ||||
|                     domainObject: mockDomainObject | ||||
|                 }; | ||||
|  | ||||
|                 mockCurrentTarget = jasmine.createSpyObj("currentTarget", ["blur", "textContent"]); | ||||
|                 mockCurrentTarget.blur.andReturn(mockCurrentTarget); | ||||
|  | ||||
|                 mockEvent = { | ||||
|                     which: {}, | ||||
|                     type: {}, | ||||
|                     currentTarget: mockCurrentTarget | ||||
|                 }; | ||||
|  | ||||
|                 controller = new ObjectHeaderController(mockScope); | ||||
|             }); | ||||
|  | ||||
|             it("updates the model with new name on blur", function () { | ||||
|                 mockEvent.type = "blur"; | ||||
|                 mockCurrentTarget.textContent = "New name"; | ||||
|                 controller.updateName(mockEvent); | ||||
|  | ||||
|                 expect(mockMutationCapability.mutate).toHaveBeenCalled(); | ||||
|             }); | ||||
|  | ||||
|             it("updates the model with a default for blank names", function () { | ||||
|                 mockEvent.type = "blur"; | ||||
|                 mockCurrentTarget.textContent = ""; | ||||
|                 controller.updateName(mockEvent); | ||||
|  | ||||
|                 expect(mockCurrentTarget.textContent.length).not.toEqual(0); | ||||
|                 expect(mockMutationCapability.mutate).toHaveBeenCalled(); | ||||
|             }); | ||||
|  | ||||
|             it("does not update the model if the same name", function () { | ||||
|                 mockEvent.type = "blur"; | ||||
|                 mockCurrentTarget.textContent = mockDomainObject.getModel().name; | ||||
|                 controller.updateName(mockEvent); | ||||
|  | ||||
|                 expect(mockMutationCapability.mutate).not.toHaveBeenCalled(); | ||||
|             }); | ||||
|  | ||||
|             it("updates the model on enter keypress event only", function () { | ||||
|                 mockCurrentTarget.textContent = "New name"; | ||||
|                 controller.updateName(mockEvent); | ||||
|  | ||||
|                 expect(mockMutationCapability.mutate).not.toHaveBeenCalled(); | ||||
|  | ||||
|                 mockEvent.which = 13; | ||||
|                 controller.updateName(mockEvent); | ||||
|  | ||||
|                 expect(mockMutationCapability.mutate).toHaveBeenCalledWith(jasmine.any(Function)); | ||||
|  | ||||
|                 mockMutationCapability.mutate.mostRecentCall.args[0](model); | ||||
|  | ||||
|                 expect(mockDomainObject.getModel().name).toBe("New name"); | ||||
|             }); | ||||
|  | ||||
|             it("blurs the field on enter key press", function () { | ||||
|                 mockCurrentTarget.textContent = "New name"; | ||||
|                 mockEvent.which = 13; | ||||
|                 controller.updateName(mockEvent); | ||||
|  | ||||
|                 expect(mockEvent.currentTarget.blur).toHaveBeenCalled(); | ||||
|             }); | ||||
|  | ||||
|             it("allows editting name when object is creatable", function () { | ||||
|                 expect(controller.allowEdit()).toBe(true); | ||||
|             }); | ||||
|  | ||||
|             it("disallows editting name when object is non-creatable", function () { | ||||
|                 mockTypeCapability.hasFeature.andReturn(false); | ||||
|  | ||||
|                 expect(controller.allowEdit()).toBe(false); | ||||
|  | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
| ); | ||||
| @@ -20,7 +20,7 @@ | ||||
|  at runtime from the About dialog for additional information. | ||||
| --> | ||||
| <div class="abs top-bar"> | ||||
|     <div class="dialog-title">{{ngModel.title}}</div> | ||||
|     <div class="title">{{ngModel.title}}</div> | ||||
|     <div class="hint">All fields marked <span class="req icon-asterisk"></span> are required.</div> | ||||
| </div> | ||||
| <div class='abs editor'> | ||||
|   | ||||
| @@ -1,10 +1,11 @@ | ||||
| <div class="l-message" | ||||
|      ng-class="'message-severity-' + ngModel.severity"> | ||||
|     <div class="w-message-contents"> | ||||
|     <div class="ui-symbol type-icon message-type"></div> | ||||
|     <div class="message-contents"> | ||||
|         <div class="top-bar"> | ||||
|             <div class="title">{{ngModel.title}}</div> | ||||
|             <div class="hint" ng-hide="ngModel.hint === undefined">{{ngModel.hint}}</div> | ||||
|         </div> | ||||
|         <div class="hint" ng-hide="ngModel.hint === undefined">{{ngModel.hint}}</div> | ||||
|         <div class="message-body"> | ||||
|             <div class="message-action"> | ||||
|                 {{ngModel.actionText}} | ||||
| @@ -24,6 +25,8 @@ | ||||
|                ng-click="ngModel.primaryOption.callback()"> | ||||
|                 {{ngModel.primaryOption.label}} | ||||
|             </a> | ||||
|  | ||||
|         </div> | ||||
|  | ||||
|     </div> | ||||
| </div> | ||||
|   | ||||
| @@ -1,17 +1,17 @@ | ||||
| <mct-container key="overlay"> | ||||
|     <div class="t-message-list"> | ||||
|         <div class="top-bar"> | ||||
|             <div class="dialog-title">{{ngModel.dialog.title}}</div> | ||||
| <mct-container key="overlay" class="t-message-list"> | ||||
|     <div class="message-contents"> | ||||
|         <div class="abs top-bar"> | ||||
|             <div class="title">{{ngModel.dialog.title}}</div> | ||||
|             <div class="hint">Displaying {{ngModel.dialog.messages.length}} message<span ng-show="ngModel.dialog.messages.length > 1 || | ||||
|                                                                                                   ngModel.dialog.messages.length == 0">s</span> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="w-messages"> | ||||
|         <div class="abs message-body"> | ||||
|             <mct-include | ||||
|                 ng-repeat="msg in ngModel.dialog.messages | orderBy: '-'" | ||||
|                 key="'message'" ng-model="msg.model"></mct-include> | ||||
|                     ng-repeat="msg in ngModel.dialog.messages | orderBy: '-'" | ||||
|                     key="'message'" ng-model="msg.model"></mct-include> | ||||
|         </div> | ||||
|         <div class="bottom-bar"> | ||||
|         <div class="abs bottom-bar"> | ||||
|             <a ng-repeat="dialogAction in ngModel.dialog.actions" | ||||
|                class="s-button major" | ||||
|                ng-click="dialogAction.action()"> | ||||
|   | ||||
| @@ -21,7 +21,7 @@ | ||||
| --> | ||||
| <mct-container key="overlay"> | ||||
|     <div class="abs top-bar"> | ||||
|         <div class="dialog-title">{{ngModel.dialog.title}}</div> | ||||
|         <div class="title">{{ngModel.dialog.title}}</div> | ||||
|         <div class="hint">{{ngModel.dialog.hint}}</div> | ||||
|     </div> | ||||
|     <div class='abs editor'> | ||||
|   | ||||
| @@ -121,8 +121,7 @@ define([ | ||||
|                     "key": "ElementsController", | ||||
|                     "implementation": ElementsController, | ||||
|                     "depends": [ | ||||
|                         "$scope", | ||||
|                         "openmct" | ||||
|                         "$scope" | ||||
|                     ] | ||||
|                 }, | ||||
|                 { | ||||
| @@ -300,6 +299,9 @@ define([ | ||||
|                 { | ||||
|                     "key": "edit-elements", | ||||
|                     "template": elementsTemplate, | ||||
|                     "uses": [ | ||||
|                         "composition" | ||||
|                     ], | ||||
|                     "gestures": [ | ||||
|                         "drop" | ||||
|                     ] | ||||
| @@ -383,10 +385,7 @@ define([ | ||||
|                     ] | ||||
|                 }, | ||||
|                 { | ||||
|                     "implementation": EditToolbarRepresenter, | ||||
|                     "depends": [ | ||||
|                         "openmct" | ||||
|                     ] | ||||
|                     "implementation": EditToolbarRepresenter | ||||
|                 } | ||||
|             ], | ||||
|             "constants": [ | ||||
|   | ||||
| @@ -23,7 +23,7 @@ | ||||
|     <div class="s-menu-button major create-button" ng-click="createController.toggle()"> | ||||
| 		<span class="title-label">Create</span> | ||||
|     </div> | ||||
|     <div class="menu super-menu l-create-menu" ng-show="createController.isActive()"> | ||||
|     <div class="menu super-menu" ng-show="createController.isActive()"> | ||||
|         <mct-representation mct-object="domainObject" key="'create-menu'"> | ||||
|         </mct-representation> | ||||
|     </div> | ||||
|   | ||||
| @@ -19,8 +19,8 @@ | ||||
|  this source code distribution or the Licensing information page available | ||||
|  at runtime from the About dialog for additional information. | ||||
| --> | ||||
| <div class="w-menu" ng-controller="CreateMenuController"> | ||||
|     <div class="col menu-items"> | ||||
| <div class="contents" ng-controller="CreateMenuController"> | ||||
|     <div class="pane left menu-items"> | ||||
|         <ul> | ||||
|             <li ng-repeat="createAction in createActions" ng-click="createAction.perform()"> | ||||
|                 <a ng-mouseover="representation.activeMetadata = createAction.getMetadata()" | ||||
| @@ -31,15 +31,13 @@ | ||||
|             </li> | ||||
|         </ul> | ||||
|     </div> | ||||
|     <div class="col menu-item-description"> | ||||
|     <div class="pane right menu-item-description"> | ||||
|         <div class="desc-area icon {{ representation.activeMetadata.cssClass }}"></div> | ||||
|         <div class="w-title-desc"> | ||||
|             <div class="desc-area title"> | ||||
|                 {{representation.activeMetadata.name}} | ||||
|             </div> | ||||
|             <div class="desc-area description"> | ||||
|                 {{representation.activeMetadata.description}} | ||||
|             </div> | ||||
|         <div class="desc-area title"> | ||||
|             {{representation.activeMetadata.name}} | ||||
|         </div> | ||||
|         <div class="desc-area description"> | ||||
|             {{representation.activeMetadata.description}} | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
|   | ||||
| @@ -61,12 +61,7 @@ | ||||
|             <mct-representation key="representation.selected.key" | ||||
|                                 mct-object="representation.selected.key && domainObject" | ||||
|                                 class="abs flex-elem grows object-holder-main scroll" | ||||
|                                 toolbar="toolbar" | ||||
|                                 mct-selectable="{ | ||||
|                                     item: domainObject.useCapability('adapter'), | ||||
|                                     oldItem: domainObject | ||||
|                                 }" | ||||
|                                 mct-init-select> | ||||
|                                 toolbar="toolbar"> | ||||
|             </mct-representation> | ||||
|         </div><!--/ l-object-wrapper-inner --> | ||||
|     </div> | ||||
|   | ||||
| @@ -25,7 +25,7 @@ | ||||
|                  ng-model="filterBy"> | ||||
|     </mct-include> | ||||
|     <div class="flex-elem grows vscroll"> | ||||
|         <ul class="tree" ng-if="composition.length > 0"> | ||||
|         <ul class="tree"> | ||||
|             <li ng-repeat="containedObject in composition | filter:searchElements"> | ||||
|                 <span class="tree-item"> | ||||
|                     <mct-representation | ||||
| @@ -36,6 +36,5 @@ | ||||
|                 </span> | ||||
|             </li> | ||||
|         </ul> | ||||
|         <div ng-if="composition.length === 0">No contained elements</div>     | ||||
|     </div> | ||||
| </div> | ||||
|   | ||||
| @@ -101,15 +101,10 @@ define( | ||||
|          */ | ||||
|         EditorCapability.prototype.finish = function () { | ||||
|             var domainObject = this.domainObject; | ||||
|  | ||||
|             if (this.transactionService.isActive()) { | ||||
|                 return this.transactionService.cancel().then(function () { | ||||
|                     domainObject.getCapability("status").set("editing", false); | ||||
|                     return domainObject; | ||||
|                 }); | ||||
|             } else { | ||||
|                 return Promise.resolve(domainObject); | ||||
|             } | ||||
|             return this.transactionService.cancel().then(function () { | ||||
|                 domainObject.getCapability("status").set("editing", false); | ||||
|                 return domainObject; | ||||
|             }); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|   | ||||
| @@ -28,6 +28,16 @@ define( | ||||
|     [], | ||||
|     function () { | ||||
|  | ||||
|         function isDirty(domainObject) { | ||||
|             var navigatedObject = domainObject, | ||||
|                 editorCapability = navigatedObject && | ||||
|                     navigatedObject.getCapability("editor"); | ||||
|  | ||||
|             return editorCapability && | ||||
|                 editorCapability.isEditContextRoot() && | ||||
|                 editorCapability.dirty(); | ||||
|         } | ||||
|  | ||||
|         function cancelEditing(domainObject) { | ||||
|             var navigatedObject = domainObject, | ||||
|                 editorCapability = navigatedObject && | ||||
| @@ -49,7 +59,10 @@ define( | ||||
|  | ||||
|             var removeCheck = navigationService | ||||
|                 .checkBeforeNavigation(function () { | ||||
|                     return "Continuing will cause the loss of any unsaved changes."; | ||||
|                     if (isDirty(domainObject)) { | ||||
|                         return "Continuing will cause the loss of any unsaved changes."; | ||||
|                     } | ||||
|                     return false; | ||||
|                 }); | ||||
|  | ||||
|             $scope.$on('$destroy', function () { | ||||
|   | ||||
| @@ -29,11 +29,7 @@ define( | ||||
|          * | ||||
|          * @constructor | ||||
|          */ | ||||
|         function ElementsController($scope, openmct) { | ||||
|             this.scope = $scope; | ||||
|             this.scope.composition = []; | ||||
|             var self = this; | ||||
|  | ||||
|         function ElementsController($scope) { | ||||
|             function filterBy(text) { | ||||
|                 if (typeof text === 'undefined') { | ||||
|                     return $scope.searchText; | ||||
| @@ -51,45 +47,10 @@ define( | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             function setSelection(selection) { | ||||
|                 self.scope.selection = selection; | ||||
|                 self.refreshComposition(selection); | ||||
|             } | ||||
|  | ||||
|             $scope.filterBy = filterBy; | ||||
|             $scope.searchElements = searchElements; | ||||
|  | ||||
|             openmct.selection.on('change', setSelection); | ||||
|             setSelection(openmct.selection.get()); | ||||
|  | ||||
|             $scope.$on("$destroy", function () { | ||||
|                 openmct.selection.off("change", setSelection); | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Gets the composition for the selected object and populates the scope with it. | ||||
|          * | ||||
|          * @param selection the selection object | ||||
|          * @private | ||||
|          */ | ||||
|         ElementsController.prototype.refreshComposition = function (selection) { | ||||
|             if (!selection[0]) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             var selected = selection[0].context.oldItem; | ||||
|             var selectedObjectComposition = selected && selected.useCapability('composition'); | ||||
|  | ||||
|             if (selectedObjectComposition) { | ||||
|                 selectedObjectComposition.then(function (composition) { | ||||
|                     this.scope.composition = composition; | ||||
|                 }.bind(this)); | ||||
|             } else { | ||||
|                 this.scope.composition = []; | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         return ElementsController; | ||||
|     } | ||||
| ); | ||||
|   | ||||
| @@ -38,7 +38,7 @@ define( | ||||
|          * @constructor | ||||
|          * @implements {Representer} | ||||
|          */ | ||||
|         function EditToolbarRepresenter(openmct, scope, element, attrs) { | ||||
|         function EditToolbarRepresenter(scope, element, attrs) { | ||||
|             var self = this; | ||||
|  | ||||
|             // Mark changes as ready to persist | ||||
| @@ -109,7 +109,6 @@ define( | ||||
|             this.updateSelection = updateSelection; | ||||
|             this.toolbar = undefined; | ||||
|             this.toolbarObject = {}; | ||||
|             this.openmct = openmct; | ||||
|  | ||||
|             // If this representation exposes a toolbar, set up watches | ||||
|             // to synchronize with it. | ||||
| @@ -147,7 +146,7 @@ define( | ||||
|             // Expose the toolbar object to the parent scope | ||||
|             initialize(definition); | ||||
|             // Create a selection scope | ||||
|             this.setSelection(new EditToolbarSelection(this.openmct)); | ||||
|             this.setSelection(new EditToolbarSelection()); | ||||
|             // Initialize toolbar to an empty selection | ||||
|             this.updateSelection([]); | ||||
|         }; | ||||
|   | ||||
| @@ -38,24 +38,10 @@ define( | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @constructor | ||||
|          */ | ||||
|         function EditToolbarSelection(openmct) { | ||||
|         function EditToolbarSelection() { | ||||
|             this.selection = [{}]; | ||||
|             this.selecting = false; | ||||
|             this.selectedObj = undefined; | ||||
|  | ||||
|             openmct.selection.on('change', function (selection) { | ||||
|                 var selected = selection[0]; | ||||
|  | ||||
|                 if (selected && selected.context.toolbar) { | ||||
|                     this.select(selected.context.toolbar); | ||||
|                 } else { | ||||
|                     this.deselect(); | ||||
|                 } | ||||
|  | ||||
|                 if (selected && selected.context.viewProxy) { | ||||
|                     this.proxy(selected.context.viewProxy); | ||||
|                 } | ||||
|             }.bind(this)); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|   | ||||
| @@ -62,7 +62,6 @@ define( | ||||
|                 ); | ||||
|                 mockTransactionService.commit.andReturn(fastPromise()); | ||||
|                 mockTransactionService.cancel.andReturn(fastPromise()); | ||||
|                 mockTransactionService.isActive = jasmine.createSpy('isActive'); | ||||
|  | ||||
|                 mockStatusCapability = jasmine.createSpyObj( | ||||
|                     "statusCapability", | ||||
| @@ -142,7 +141,6 @@ define( | ||||
|  | ||||
|             describe("finish", function () { | ||||
|                 beforeEach(function () { | ||||
|                     mockTransactionService.isActive.andReturn(true); | ||||
|                     capability.edit(); | ||||
|                     capability.finish(); | ||||
|                 }); | ||||
| @@ -154,23 +152,6 @@ define( | ||||
|                 }); | ||||
|             }); | ||||
|  | ||||
|             describe("finish", function () { | ||||
|                 beforeEach(function () { | ||||
|                     mockTransactionService.isActive.andReturn(false); | ||||
|                     capability.edit(); | ||||
|                 }); | ||||
|  | ||||
|                 it("does not cancel transaction when transaction is not active", function () { | ||||
|                     capability.finish(); | ||||
|                     expect(mockTransactionService.cancel).not.toHaveBeenCalled(); | ||||
|                 }); | ||||
|  | ||||
|                 it("returns a promise", function () { | ||||
|                     expect(capability.finish() instanceof Promise).toBe(true); | ||||
|                 }); | ||||
|  | ||||
|             }); | ||||
|  | ||||
|             describe("dirty", function () { | ||||
|                 var model = {}; | ||||
|  | ||||
|   | ||||
| @@ -104,10 +104,10 @@ define( | ||||
|                 mockEditorCapability.isEditContextRoot.andReturn(false); | ||||
|                 mockEditorCapability.dirty.andReturn(false); | ||||
|  | ||||
|                 expect(checkFn()).toBe("Continuing will cause the loss of any unsaved changes."); | ||||
|                 expect(checkFn()).toBe(false); | ||||
|  | ||||
|                 mockEditorCapability.isEditContextRoot.andReturn(true); | ||||
|                 expect(checkFn()).toBe("Continuing will cause the loss of any unsaved changes."); | ||||
|                 expect(checkFn()).toBe(false); | ||||
|  | ||||
|                 mockEditorCapability.dirty.andReturn(true); | ||||
|                 expect(checkFn()) | ||||
|   | ||||
| @@ -27,23 +27,11 @@ define( | ||||
|  | ||||
|         describe("The Elements Pane controller", function () { | ||||
|             var mockScope, | ||||
|                 mockOpenMCT, | ||||
|                 mockSelection, | ||||
|                 controller; | ||||
|  | ||||
|             beforeEach(function () { | ||||
|                 mockScope = jasmine.createSpyObj("$scope", ['$on']); | ||||
|                 mockSelection = jasmine.createSpyObj("selection", [ | ||||
|                     'on', | ||||
|                     'off', | ||||
|                     'get' | ||||
|                 ]); | ||||
|                 mockSelection.get.andReturn([]); | ||||
|                 mockOpenMCT = { | ||||
|                     selection: mockSelection | ||||
|                 }; | ||||
|  | ||||
|                 controller = new ElementsController(mockScope, mockOpenMCT); | ||||
|                 mockScope = jasmine.createSpy("$scope"); | ||||
|                 controller = new ElementsController(mockScope); | ||||
|             }); | ||||
|  | ||||
|             function getModel(model) { | ||||
|   | ||||
| @@ -29,9 +29,7 @@ define( | ||||
|                 mockElement, | ||||
|                 testAttrs, | ||||
|                 mockUnwatch, | ||||
|                 representer, | ||||
|                 mockOpenMCT, | ||||
|                 mockSelection; | ||||
|                 representer; | ||||
|  | ||||
|             beforeEach(function () { | ||||
|                 mockScope = jasmine.createSpyObj( | ||||
| @@ -48,18 +46,7 @@ define( | ||||
|  | ||||
|                 mockScope.$parent.$watchCollection.andReturn(mockUnwatch); | ||||
|  | ||||
|                 mockSelection = jasmine.createSpyObj("selection", [ | ||||
|                     'on', | ||||
|                     'off', | ||||
|                     'get' | ||||
|                 ]); | ||||
|                 mockSelection.get.andReturn([]); | ||||
|                 mockOpenMCT = { | ||||
|                     selection: mockSelection | ||||
|                 }; | ||||
|  | ||||
|                 representer = new EditToolbarRepresenter( | ||||
|                     mockOpenMCT, | ||||
|                     mockScope, | ||||
|                     mockElement, | ||||
|                     testAttrs | ||||
|   | ||||
| @@ -28,25 +28,13 @@ define( | ||||
|             var testProxy, | ||||
|                 testElement, | ||||
|                 otherElement, | ||||
|                 selection, | ||||
|                 mockSelection, | ||||
|                 mockOpenMCT; | ||||
|                 selection; | ||||
|  | ||||
|             beforeEach(function () { | ||||
|                 testProxy = { someKey: "some value" }; | ||||
|                 testElement = { someOtherKey: "some other value" }; | ||||
|                 otherElement = { yetAnotherKey: 42 }; | ||||
|                 mockSelection = jasmine.createSpyObj("selection", [ | ||||
|                     // 'select', | ||||
|                     'on', | ||||
|                     'off', | ||||
|                     'get' | ||||
|                 ]); | ||||
|                 mockSelection.get.andReturn([]); | ||||
|                 mockOpenMCT = { | ||||
|                     selection: mockSelection | ||||
|                 }; | ||||
|                 selection = new EditToolbarSelection(mockOpenMCT); | ||||
|                 selection = new EditToolbarSelection(); | ||||
|                 selection.proxy(testProxy); | ||||
|             }); | ||||
|  | ||||
|   | ||||
| @@ -121,9 +121,6 @@ define([ | ||||
|     }; | ||||
|  | ||||
|     UTCTimeFormat.prototype.parse = function (text) { | ||||
|         if (typeof text === 'number') { | ||||
|             return text; | ||||
|         } | ||||
|         return moment.utc(text, DATE_FORMATS).valueOf(); | ||||
|     }; | ||||
|  | ||||
|   | ||||
| @@ -41,7 +41,6 @@ define([ | ||||
|     "./src/controllers/BannerController", | ||||
|     "./src/directives/MCTContainer", | ||||
|     "./src/directives/MCTDrag", | ||||
|     "./src/directives/MCTSelectable", | ||||
|     "./src/directives/MCTClickElsewhere", | ||||
|     "./src/directives/MCTResize", | ||||
|     "./src/directives/MCTPopup", | ||||
| @@ -91,7 +90,6 @@ define([ | ||||
|     BannerController, | ||||
|     MCTContainer, | ||||
|     MCTDrag, | ||||
|     MCTSelectable, | ||||
|     MCTClickElsewhere, | ||||
|     MCTResize, | ||||
|     MCTPopup, | ||||
| @@ -330,13 +328,6 @@ define([ | ||||
|                         "$document" | ||||
|                     ] | ||||
|                 }, | ||||
|                 { | ||||
|                     "key": "mctSelectable", | ||||
|                     "implementation": MCTSelectable, | ||||
|                     "depends": [ | ||||
|                         "openmct" | ||||
|                     ] | ||||
|                 }, | ||||
|                 { | ||||
|                     "key": "mctClickElsewhere", | ||||
|                     "implementation": MCTClickElsewhere, | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|   "metadata": { | ||||
|     "name": "openmct-symbols-16px", | ||||
|     "lastOpened": 0, | ||||
|     "created": 1506973656040 | ||||
|     "created": 1502487054429 | ||||
|   }, | ||||
|   "iconSets": [ | ||||
|     { | ||||
| @@ -636,29 +636,13 @@ | ||||
|           "code": 921670, | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 138, | ||||
|           "id": 115, | ||||
|           "name": "icon-import", | ||||
|           "prevSize": 24, | ||||
|           "code": 921671, | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 136, | ||||
|           "id": 116, | ||||
|           "name": "icon-export", | ||||
|           "prevSize": 24, | ||||
|           "code": 921672, | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 37, | ||||
|           "prevSize": 24, | ||||
|           "name": "icon-activity", | ||||
|           "id": 32, | ||||
|           "code": 921856, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 36, | ||||
| @@ -666,7 +650,7 @@ | ||||
|           "name": "icon-activity-mode", | ||||
|           "id": 31, | ||||
|           "code": 921857, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 52, | ||||
| @@ -674,7 +658,7 @@ | ||||
|           "name": "icon-autoflow-tabular", | ||||
|           "id": 47, | ||||
|           "code": 921858, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 55, | ||||
| @@ -682,7 +666,7 @@ | ||||
|           "name": "icon-clock", | ||||
|           "id": 50, | ||||
|           "code": 921859, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 58, | ||||
| @@ -690,7 +674,7 @@ | ||||
|           "name": "icon-database", | ||||
|           "id": 53, | ||||
|           "code": 921860, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 57, | ||||
| @@ -698,7 +682,7 @@ | ||||
|           "name": "icon-database-query", | ||||
|           "id": 52, | ||||
|           "code": 921861, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 17, | ||||
| @@ -706,7 +690,7 @@ | ||||
|           "name": "icon-dataset", | ||||
|           "id": 12, | ||||
|           "code": 921862, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 22, | ||||
| @@ -714,7 +698,7 @@ | ||||
|           "name": "icon-datatable", | ||||
|           "id": 17, | ||||
|           "code": 921863, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 59, | ||||
| @@ -722,7 +706,7 @@ | ||||
|           "name": "icon-dictionary", | ||||
|           "id": 54, | ||||
|           "code": 921864, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 62, | ||||
| @@ -730,7 +714,7 @@ | ||||
|           "name": "icon-folder", | ||||
|           "id": 57, | ||||
|           "code": 921865, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 66, | ||||
| @@ -738,7 +722,7 @@ | ||||
|           "name": "icon-image", | ||||
|           "id": 61, | ||||
|           "code": 921872, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 68, | ||||
| @@ -746,7 +730,7 @@ | ||||
|           "name": "icon-layout", | ||||
|           "id": 63, | ||||
|           "code": 921873, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 77, | ||||
| @@ -754,7 +738,7 @@ | ||||
|           "name": "icon-object", | ||||
|           "id": 72, | ||||
|           "code": 921874, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 78, | ||||
| @@ -762,7 +746,7 @@ | ||||
|           "name": "icon-object-unknown", | ||||
|           "id": 73, | ||||
|           "code": 921875, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 79, | ||||
| @@ -770,7 +754,7 @@ | ||||
|           "name": "icon-packet", | ||||
|           "id": 74, | ||||
|           "code": 921876, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 80, | ||||
| @@ -778,7 +762,7 @@ | ||||
|           "name": "icon-page", | ||||
|           "id": 75, | ||||
|           "code": 921877, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 135, | ||||
| @@ -786,7 +770,7 @@ | ||||
|           "name": "icon-plot-overlay", | ||||
|           "prevSize": 24, | ||||
|           "code": 921878, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 113, | ||||
| @@ -794,7 +778,7 @@ | ||||
|           "name": "icon-plot-stacked", | ||||
|           "prevSize": 24, | ||||
|           "code": 921879, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 10, | ||||
| @@ -802,7 +786,7 @@ | ||||
|           "name": "icon-session", | ||||
|           "id": 5, | ||||
|           "code": 921880, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 24, | ||||
| @@ -810,7 +794,7 @@ | ||||
|           "name": "icon-tabular", | ||||
|           "id": 19, | ||||
|           "code": 921881, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 7, | ||||
| @@ -818,7 +802,7 @@ | ||||
|           "name": "icon-tabular-lad", | ||||
|           "id": 2, | ||||
|           "code": 921888, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 6, | ||||
| @@ -826,7 +810,7 @@ | ||||
|           "name": "icon-tabular-lad-set", | ||||
|           "id": 1, | ||||
|           "code": 921889, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 8, | ||||
| @@ -834,7 +818,7 @@ | ||||
|           "name": "icon-tabular-realtime", | ||||
|           "id": 3, | ||||
|           "code": 921890, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 23, | ||||
| @@ -842,7 +826,7 @@ | ||||
|           "name": "icon-tabular-scrolling", | ||||
|           "id": 18, | ||||
|           "code": 921891, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 112, | ||||
| @@ -850,7 +834,7 @@ | ||||
|           "name": "icon-telemetry", | ||||
|           "id": 86, | ||||
|           "code": 921892, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 90, | ||||
| @@ -858,7 +842,7 @@ | ||||
|           "name": "icon-telemetry-panel", | ||||
|           "id": 85, | ||||
|           "code": 921893, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 93, | ||||
| @@ -866,7 +850,7 @@ | ||||
|           "name": "icon-timeline", | ||||
|           "id": 88, | ||||
|           "code": 921894, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 116, | ||||
| @@ -874,7 +858,7 @@ | ||||
|           "name": "icon-timer-v1.5", | ||||
|           "prevSize": 24, | ||||
|           "code": 921895, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 11, | ||||
| @@ -882,7 +866,7 @@ | ||||
|           "name": "icon-topic", | ||||
|           "id": 6, | ||||
|           "code": 921896, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 115, | ||||
| @@ -890,7 +874,7 @@ | ||||
|           "name": "icon-box-with-dashed-lines", | ||||
|           "id": 29, | ||||
|           "code": 921897, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 126, | ||||
| @@ -898,15 +882,7 @@ | ||||
|           "name": "icon-summary-widget", | ||||
|           "prevSize": 24, | ||||
|           "code": 921904, | ||||
|           "tempChar": "" | ||||
|         }, | ||||
|         { | ||||
|           "order": 139, | ||||
|           "id": 117, | ||||
|           "name": "icon-notebook", | ||||
|           "prevSize": 24, | ||||
|           "code": 921905, | ||||
|           "tempChar": "" | ||||
|           "tempChar": "" | ||||
|         } | ||||
|       ], | ||||
|       "metadata": { | ||||
| @@ -2707,52 +2683,6 @@ | ||||
|             ] | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "id": 115, | ||||
|           "paths": [ | ||||
|             "M832 192.4v639.4c0 0.2-0.2 0.2-0.4 0.4h-319.6v192h320c105.6 0 192-86.4 192-192v-640.2c0-105.6-86.4-192-192-192h-320v192h319.6c0.2 0 0.4 0.2 0.4 0.4z", | ||||
|             "M192 704v192l384-384-384-384v192h-192v384z" | ||||
|           ], | ||||
|           "attrs": [ | ||||
|             {}, | ||||
|             {} | ||||
|           ], | ||||
|           "grid": 16, | ||||
|           "tags": [ | ||||
|             "icon-import" | ||||
|           ], | ||||
|           "isMulticolor": false, | ||||
|           "isMulticolor2": false, | ||||
|           "colorPermutations": { | ||||
|             "1161751207457516161751": [ | ||||
|               {}, | ||||
|               {} | ||||
|             ] | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "id": 116, | ||||
|           "paths": [ | ||||
|             "M192 831.66v-639.32l0.34-0.34h319.66v-192h-320c-105.6 0-192 86.4-192 192v640c0 105.6 86.4 192 192 192h320v-192h-319.66z", | ||||
|             "M1024 512l-384-384v192h-192v384h192v192l384-384z" | ||||
|           ], | ||||
|           "attrs": [ | ||||
|             {}, | ||||
|             {} | ||||
|           ], | ||||
|           "isMulticolor": false, | ||||
|           "isMulticolor2": false, | ||||
|           "grid": 16, | ||||
|           "tags": [ | ||||
|             "icon-export" | ||||
|           ], | ||||
|           "colorPermutations": { | ||||
|             "1161751207457516161751": [ | ||||
|               {}, | ||||
|               {} | ||||
|             ] | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "paths": [ | ||||
|             "M576 64h-256l320 320h-290.256c-44.264-76.516-126.99-128-221.744-128h-128v512h128c94.754 0 177.48-51.484 221.744-128h290.256l-320 320h256l448-448-448-448z" | ||||
| @@ -3532,29 +3462,6 @@ | ||||
|               {} | ||||
|             ] | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "id": 117, | ||||
|           "paths": [ | ||||
|             "M896 110.8c0-79.8-55.4-127.4-123-105.4l-773 250.6h896v-145.2z", | ||||
|             "M896 320h-896v576c0 70.4 57.6 128 128 128h768c70.4 0 128-57.6 128-128v-448c0-70.4-57.6-128-128-128zM832 832h-384v-320h384v320z" | ||||
|           ], | ||||
|           "attrs": [ | ||||
|             {}, | ||||
|             {} | ||||
|           ], | ||||
|           "isMulticolor": false, | ||||
|           "isMulticolor2": false, | ||||
|           "grid": 16, | ||||
|           "tags": [ | ||||
|             "icon-notebook" | ||||
|           ], | ||||
|           "colorPermutations": { | ||||
|             "1161751207457516161751": [ | ||||
|               {}, | ||||
|               {} | ||||
|             ] | ||||
|           } | ||||
|         } | ||||
|       ], | ||||
|       "colorThemes": [ | ||||
|   | ||||
										
											Binary file not shown.
										
									
								
							| @@ -85,8 +85,6 @@ | ||||
| <glyph unicode="󡁄" glyph-name="icon-grid-snap-no" d="M768 384h192v-64h-192v64zM256 384h192v-64h-192v64zM0 384h192v-64h-192v64zM640 448h-64v-64h-64v-64h64v-64h64v64h64v64h-64zM576 704h64v-192h-64v192zM576 960h64v-192h-64v192zM576 192h64v-192h-64v192z" /> | ||||
| <glyph unicode="󡁅" glyph-name="icon-frame-show" d="M0 896v-896h1024v896h-1024zM896 128h-768v640h768v-640zM192 704h384v-128h-384v128z" /> | ||||
| <glyph unicode="󡁆" glyph-name="icon-frame-hide" d="M128 770h420l104 128h-652v-802.4l128 157.4zM896 130h-420l-104-128h652v802.4l-128-157.4zM832 962l-832-1024h192l832 1024zM392 578l104 128h-304v-128z" /> | ||||
| <glyph unicode="󡁇" glyph-name="icon-import" d="M832 767.6v-639.4c0-0.2-0.2-0.2-0.4-0.4h-319.6v-192h320c105.6 0 192 86.4 192 192v640.2c0 105.6-86.4 192-192 192h-320v-192h319.6c0.2 0 0.4-0.2 0.4-0.4zM192 256v-192l384 384-384 384v-192h-192v-384z" /> | ||||
| <glyph unicode="󡁈" glyph-name="icon-export" d="M192 128.34v639.32l0.34 0.34h319.66v192h-320c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h320v192h-319.66zM1024 448l-384 384v-192h-192v-384h192v-192l384 384z" /> | ||||
| <glyph unicode="󡄀" glyph-name="icon-activity" d="M576 896h-256l320-320h-290.256c-44.264 76.516-126.99 128-221.744 128h-128v-512h128c94.754 0 177.48 51.484 221.744 128h290.256l-320-320h256l448 448-448 448z" /> | ||||
| <glyph unicode="󡄁" glyph-name="icon-activity-mode" d="M512 960c-214.866 0-398.786-132.372-474.744-320h90.744c56.86 0 107.938-24.724 143.094-64h240.906l-192 192h256l320-320-320-320h-256l192 192h-240.906c-35.156-39.276-86.234-64-143.094-64h-90.744c75.958-187.628 259.878-320 474.744-320 282.77 0 512 229.23 512 512s-229.23 512-512 512z" /> | ||||
| <glyph unicode="󡄂" glyph-name="icon-autoflow-tabular" d="M192 960c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h64v1024h-64zM384 960h256v-1024h-256v1024zM832 960h-64v-704h256v512c0 105.6-86.4 192-192 192z" /> | ||||
| @@ -118,5 +116,4 @@ | ||||
| <glyph unicode="󡄨" glyph-name="icon-topic" d="M454.36 483.36l86.3 86.3c9.088 8.965 21.577 14.502 35.36 14.502s26.272-5.537 35.366-14.507l86.294-86.294c19.328-19.358 42.832-34.541 69.047-44.082l1.313 171.722-57.64 57.64c-34.407 34.33-81.9 55.558-134.35 55.558s-99.943-21.228-134.354-55.562l-86.296-86.297c-9.088-8.965-21.577-14.502-35.36-14.502s-26.272 5.537-35.366 14.507l-28.674 28.654v-172.14c19.045-7.022 41.040-11.084 63.984-11.084 52.463 0 99.966 21.239 134.379 55.587zM505.64 412.64l-86.3-86.3c-9.088-8.965-21.577-14.502-35.36-14.502s-26.272 5.537-35.366 14.507l-86.294 86.294c-2 2-4.2 4-6.36 6v-197.36c33.664-30.72 78.65-49.537 128.031-49.537 52.44 0 99.923 21.22 134.333 55.541l86.296 86.296c9.088 8.965 21.577 14.502 35.36 14.502s26.272-5.537 35.366-14.507l86.294-86.294c2-2 4.2-4 6.36-6v197.36c-33.664 30.72-78.65 49.537-128.031 49.537-52.44 0-99.923-21.22-134.333-55.541zM832 960h-128v-192h127.66l0.34-0.34v-639.32l-0.34-0.34h-127.66v-192h128c105.6 0 192 86.4 192 192v640c0 105.6-86.4 192-192 192zM320 128h-127.66l-0.34 0.34v639.32l0.34 0.34h127.66v192h-128c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h128v192z" /> | ||||
| <glyph unicode="󡄩" glyph-name="icon-box-with-dashed-lines" d="M0 576h128v-256h-128v256zM128 831.78l0.22 0.22h191.78v128h-192c-70.606-0.215-127.785-57.394-128-127.979v-192.021h128v191.78zM128 64.22v191.78h-128v-192c0.215-70.606 57.394-127.785 127.979-128h192.021v128h-191.78zM384 960h256v-128h-256v128zM896 64.22l-0.22-0.22h-191.78v-128h192c70.606 0.215 127.785 57.394 128 127.979v192.021h-128v-191.78zM896 960h-192v-128h191.78l0.22-0.22v-191.78h128v192c-0.215 70.606-57.394 127.785-127.979 128zM896 576h128v-256h-128v256zM384 64h256v-128h-256v128zM256 704h512v-512h-512v512z" /> | ||||
| <glyph unicode="󡄰" glyph-name="icon-summary-widget" d="M896 960h-768c-70.4 0-128-57.6-128-128v-768c0-70.4 57.6-128 128-128h768c70.4 0 128 57.6 128 128v768c0 70.4-57.6 128-128 128zM847.8 349.6l-82.6-143.2-189.6 131.6 19.2-230h-165.4l19.2 230-189.6-131.6-82.6 143.2 208.6 98.4-208.8 98.4 82.6 143.2 189.6-131.6-19.2 230h165.4l-19.2-230 189.6 131.6 82.6-143.2-208.6-98.4 208.8-98.4z" /> | ||||
| <glyph unicode="󡄱" glyph-name="icon-notebook" d="M896 849.2c0 79.8-55.4 127.4-123 105.4l-773-250.6h896v145.2zM896 640h-896v-576c0-70.4 57.6-128 128-128h768c70.4 0 128 57.6 128 128v448c0 70.4-57.6 128-128 128zM832 128h-384v320h384v-320z" /> | ||||
| </font></defs></svg> | ||||
| Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 43 KiB | 
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| @@ -21,7 +21,7 @@ | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| /********************************************* COLUMN LAYOUTS STYLES */ | ||||
| @mixin cols($totalCols, $span) { | ||||
| /*@mixin cols($totalCols, $span) { | ||||
|     $cw: 100% / $totalCols; | ||||
|     min-width: (500px / $totalCols) * $span; | ||||
|     @if ($totalCols != $span) { | ||||
| @@ -89,7 +89,7 @@ | ||||
|         @include clearfix; | ||||
|         padding: $interiorMargin 0; | ||||
|     } | ||||
| } | ||||
| }*/ | ||||
|  | ||||
| /********************************************* FLEX STYLES */ | ||||
| .l-flex-row, | ||||
| @@ -137,11 +137,6 @@ | ||||
|         min-height: 0; | ||||
|         &.holder:not(:last-child) { margin-bottom: $interiorMarginLg; } | ||||
|     } | ||||
|     &.l-flex-accordion .flex-accordion-holder { | ||||
|         display: flex; | ||||
|         flex-direction: column; | ||||
|         //overflow: hidden !important; | ||||
|     } | ||||
|     .flex-container { @include flex-direction(column); } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -21,7 +21,7 @@ | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| /************************** FEATURES */ | ||||
| $enableImageryThumbs: true; // Set to true if historical imagery thumbnails are supported | ||||
| $enableImageryThumbs: false; // Set to true if historical imagery thumbnails are supported | ||||
|  | ||||
| /************************** VERY INFLUENTIAL GLOBAL DIMENSIONS */ | ||||
| $bodyMargin: 10px; | ||||
| @@ -82,7 +82,7 @@ $tabularTdPadTB: 2px; | ||||
| /*************** Imagery */ | ||||
| $imageMainControlBarH: 25px; | ||||
| $imageThumbsD: 120px; | ||||
| $imageThumbsWrapperH: 155px; | ||||
| $imageThumbsWrapperH: $imageThumbsD * 1.4; | ||||
| $imageThumbPad: 1px; | ||||
| /*************** Ticks */ | ||||
| $ticksH: 25px; | ||||
| @@ -111,9 +111,7 @@ $bubbleMaxW: 300px; | ||||
| $reqSymbolW: 15px; | ||||
| $reqSymbolM: $interiorMargin * 2; | ||||
| $reqSymbolFontSize: 0.75em; | ||||
| $inputTextPTopBtm: 3px; | ||||
| $inputTextPLeftRight: 5px; | ||||
| $inputTextP: $inputTextPTopBtm $inputTextPLeftRight; | ||||
| $inputTextP: 3px 5px; | ||||
| /*************** Wait Spinner Defaults */ | ||||
| $waitSpinnerD: 32px; | ||||
| $waitSpinnerTreeD: 20px; | ||||
|   | ||||
| @@ -25,7 +25,6 @@ | ||||
| 	} | ||||
|  | ||||
| 	.l-fixed-position-item { | ||||
|         border-width: 1px; | ||||
| 		position: absolute; | ||||
| 		&.s-not-selected { | ||||
| 			opacity: 0.8; | ||||
| @@ -53,7 +52,6 @@ | ||||
| 			font-size: 0.8rem; | ||||
| 			$p: 1px; | ||||
| 			line-height: 100%; | ||||
|             overflow: hidden; | ||||
| 			&.l-static-text { | ||||
| 				padding: $p; | ||||
| 			} | ||||
|   | ||||
| @@ -1,24 +1,3 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2017, United States Government | ||||
|  * as represented by the Administrator of the National Aeronautics and Space | ||||
|  * Administration. All rights reserved. | ||||
|  * | ||||
|  * Open MCT 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 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. | ||||
|  *****************************************************************************/ | ||||
| @mixin glyphBefore($unicode, $family: 'symbolsfont') { | ||||
|     &:before { | ||||
|         content: $unicode; | ||||
| @@ -113,8 +92,6 @@ $glyph-icon-grid-snap-to: '\e1043'; | ||||
| $glyph-icon-grid-snap-no: '\e1044'; | ||||
| $glyph-icon-frame-show: '\e1045'; | ||||
| $glyph-icon-frame-hide: '\e1046'; | ||||
| $glyph-icon-import: '\e1047'; | ||||
| $glyph-icon-export: '\e1048'; | ||||
| $glyph-icon-activity: '\e1100'; | ||||
| $glyph-icon-activity-mode: '\e1101'; | ||||
| $glyph-icon-autoflow-tabular: '\e1102'; | ||||
| @@ -146,7 +123,6 @@ $glyph-icon-timer: '\e1127'; | ||||
| $glyph-icon-topic: '\e1128'; | ||||
| $glyph-icon-box-with-dashed-lines: '\e1129'; | ||||
| $glyph-icon-summary-widget: '\e1130'; | ||||
| $glyph-icon-notebook: '\e1131'; | ||||
|  | ||||
| /************************** 16 PX CLASSES */ | ||||
|  | ||||
| @@ -228,8 +204,6 @@ $glyph-icon-notebook: '\e1131'; | ||||
| .icon-grid-snap-no {  @include glyphBefore($glyph-icon-grid-snap-no); } | ||||
| .icon-frame-show {  @include glyphBefore($glyph-icon-frame-show); } | ||||
| .icon-frame-hide {  @include glyphBefore($glyph-icon-frame-hide); } | ||||
| .icon-import {  @include glyphBefore($glyph-icon-import); } | ||||
| .icon-export {  @include glyphBefore($glyph-icon-export); } | ||||
| .icon-activity {  @include glyphBefore($glyph-icon-activity); } | ||||
| .icon-activity-mode {  @include glyphBefore($glyph-icon-activity-mode); } | ||||
| .icon-autoflow-tabular {  @include glyphBefore($glyph-icon-autoflow-tabular); } | ||||
| @@ -261,7 +235,6 @@ $glyph-icon-notebook: '\e1131'; | ||||
| .icon-topic {  @include glyphBefore($glyph-icon-topic); } | ||||
| .icon-box-with-dashed-lines {  @include glyphBefore($glyph-icon-box-with-dashed-lines); } | ||||
| .icon-summary-widget {  @include glyphBefore($glyph-icon-summary-widget); } | ||||
| .icon-notebook {  @include glyphBefore($glyph-icon-notebook); } | ||||
|  | ||||
| /************************** 12 PX CLASSES */ | ||||
| .icon-crosshair-12px {  @include glyphBefore($glyph-icon-crosshair,'symbolsfont-12px'); } | ||||
|   | ||||
| @@ -26,6 +26,5 @@ | ||||
|         display: block; | ||||
|         height: 100%; | ||||
|         width: 100%; | ||||
|         border: none; | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										39
									
								
								platform/commonUI/general/res/sass/_limits.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								platform/commonUI/general/res/sass/_limits.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| @mixin limitGlyph($iconColor, $glyph: $glyph-icon-alert-triangle) { | ||||
|     &:before { | ||||
|         color: $iconColor; | ||||
|         content: $glyph; | ||||
|         font-family: symbolsfont; | ||||
|         font-size: 0.8em; | ||||
|         display: inline; | ||||
|         margin-right: $interiorMarginSm; | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| .s-limit-red { background: $colorLimitRedBg !important; } | ||||
| .s-limit-yellow { background: $colorLimitYellowBg !important; } | ||||
|  | ||||
| // Handle limit when applied to a tr | ||||
| tr[class*="s-limit"] { | ||||
|     &.s-limit-red td:first-child { | ||||
|         @include limitGlyph($colorLimitRedIc); | ||||
|     } | ||||
|     &.s-limit-yellow td:first-child { | ||||
|         @include limitGlyph($colorLimitYellowIc); | ||||
|     } | ||||
|     &.s-limit-upr td:first-child:before { content: $glyph-icon-arrow-double-up; } | ||||
|     &.s-limit-lwr td:first-child:before { content: $glyph-icon-arrow-double-down; } | ||||
| } | ||||
|  | ||||
| // Handle limit when applied directly to a non-tr element | ||||
| // Assume this is applied to the element that displays the limit value | ||||
| :not(tr)[class*="s-limit"] { | ||||
|     &.s-limit-red { | ||||
|         @include limitGlyph($colorLimitRedIc); | ||||
|     } | ||||
|     &.s-limit-yellow { | ||||
|         @include limitGlyph($colorLimitYellowIc); | ||||
|     } | ||||
|     &.s-limit-upr:before { content: $glyph-icon-arrow-double-up; } | ||||
|     &.s-limit-lwr:before { content: $glyph-icon-arrow-double-down; } | ||||
| } | ||||
| @@ -27,7 +27,7 @@ | ||||
| @import "about"; | ||||
| @import "text"; | ||||
| @import "icons"; | ||||
| @import "status"; | ||||
| @import "limits"; | ||||
| @import "data-status"; | ||||
| @import "helpers/bubbles"; | ||||
| @import "helpers/splitter"; | ||||
|   | ||||
| @@ -20,8 +20,8 @@ | ||||
|  * at runtime from the About dialog for additional information. | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| @mixin absPosDefault($offset: 0px, $overflowHidden: hidden) { | ||||
|     overflow: $overflowHidden; | ||||
| @mixin absPosDefault($offset: 0px, $overflow: hidden) { | ||||
|     overflow: $overflow; | ||||
|     position: absolute; | ||||
|     top: $offset; | ||||
|     right: $offset; | ||||
| @@ -316,28 +316,23 @@ | ||||
|     text-shadow: $shdwItemText; | ||||
| } | ||||
|  | ||||
| @mixin input-base() { | ||||
| @mixin input-base($bg: $colorInputBg, $fg: $colorInputFg, $shdw: rgba(black, 0.6) 0 1px 3px) { | ||||
| 	@include appearance(none); | ||||
| 	border-radius: $controlCr; | ||||
| 	box-sizing: border-box; | ||||
|     &:focus { outline: 0; } | ||||
| 	box-shadow: inset $shdw; | ||||
| 	background: $bg; | ||||
| 	border: none; | ||||
| 	color: $fg; | ||||
| 	outline: none; | ||||
| 	&.error { | ||||
| 		background-color: $colorFormFieldErrorBg; | ||||
|         color: $colorFormFieldErrorFg; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @mixin s-input($bg: $colorInputBg, $fg: $colorInputFg, $shdw: rgba(black, 0.6) 0 1px 3px) { | ||||
|     @include input-base(); | ||||
|     background: $bg; | ||||
|     box-shadow: inset $shdw; | ||||
|     color: $fg; | ||||
| } | ||||
|  | ||||
| @mixin nice-input($bg: $colorInputBg, $fg: $colorInputFg, $shdw: rgba(black, 0.6) 0 1px 3px) { | ||||
|     @include s-input($bg, $fg, $shdw); | ||||
|     border: none; | ||||
|     outline: none; | ||||
| @mixin nice-input($bg: $colorInputBg, $fg: $colorInputFg) { | ||||
| 	@include input-base($bg, $fg); | ||||
| } | ||||
|  | ||||
| @mixin contextArrow() { | ||||
| @@ -349,7 +344,7 @@ | ||||
| } | ||||
|  | ||||
| @mixin nice-textarea($bg: $colorBodyBg, $fg: $colorBodyFg) { | ||||
|     @include nice-input($bg, $fg); | ||||
|     @include input-base($bg, $fg); | ||||
|     padding: $interiorMargin; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,85 +0,0 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2017, United States Government | ||||
|  * as represented by the Administrator of the National Aeronautics and Space | ||||
|  * Administration. All rights reserved. | ||||
|  * | ||||
|  * Open MCT 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 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. | ||||
|  *****************************************************************************/ | ||||
| /*************************************************** MIXINS */ | ||||
| @mixin formulateStatusColors($c) { | ||||
|     // Sets bg and icon colors for elements | ||||
|     background: rgba($c, 0.4) !important; | ||||
|     &:before { color: $c !important; } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /*************************************************** GENERAL */ | ||||
| .s-limit-yellow, | ||||
| .s-limit-red, | ||||
| .s-limit-yellow-icon, | ||||
| .s-limit-red-icon, | ||||
| .s-status-warning-lo, | ||||
| .s-status-warning-hi, | ||||
| .s-status-diagnostic, | ||||
| .s-status-command, | ||||
| .s-status-info, | ||||
| .s-status-ok, | ||||
| .s-status-warning-lo-icon, | ||||
| .s-status-warning-hi-icon, | ||||
| .s-status-diagnostic-icon, | ||||
| .s-status-command-icon, | ||||
| .s-status-info-icon, | ||||
| .s-status-ok-icon { | ||||
|     @include trans-prop-nice($props: background, $dur: 500ms); | ||||
|     &:before { | ||||
|         content:''; | ||||
|         font-family: symbolsfont; | ||||
|         font-size: 0.8em; | ||||
|         margin-right: $interiorMarginSm; | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| /*************************************************** LIMITS */ | ||||
| .s-limit-yellow, .s-limit-yellow-icon { | ||||
|     @include formulateStatusColors($colorWarningLo); | ||||
| } | ||||
|  | ||||
| .s-limit-red, .s-limit-red-icon { | ||||
|     @include formulateStatusColors($colorWarningHi); | ||||
| } | ||||
|  | ||||
| .s-limit-upr:before { content: $glyph-icon-arrow-double-up; } | ||||
| .s-limit-lwr:before { content: $glyph-icon-arrow-double-down; } | ||||
| .s-limit-yellow-icon:before, | ||||
| .s-limit-red-icon:before { content: $glyph-icon-alert-triangle; } | ||||
|  | ||||
| /*************************************************** STATUS */ | ||||
| .s-status-warning-hi, .s-status-warning-hi-icon {  @include formulateStatusColors($colorWarningHi); } | ||||
| .s-status-warning-lo, .s-status-warning-lo-icon {  @include formulateStatusColors($colorWarningLo); } | ||||
| .s-status-diagnostic, .s-status-diagnostic-icon {  @include formulateStatusColors($colorDiagnostic); } | ||||
| .s-status-info, .s-status-info-icon {  @include formulateStatusColors($colorInfo); } | ||||
| .s-status-ok, .s-status-ok-icon {  @include formulateStatusColors($colorOk); } | ||||
|  | ||||
| .s-status-warning-hi-icon:before { content: $glyph-icon-alert-triangle; } | ||||
| .s-status-warning-lo-icon:before { content: $glyph-icon-alert-rect; } | ||||
| .s-status-diagnostic-icon:before { content: $glyph-icon-eye-open; } | ||||
| .s-status-info-icon:before { content: $glyph-icon-info; } | ||||
| .s-status-ok-icon:before { content: $glyph-icon-check; } | ||||
|  | ||||
|  | ||||
| @@ -26,26 +26,22 @@ | ||||
|     @include ellipsize(); | ||||
|     display: inline-block; | ||||
|     text-align: center; | ||||
|     .widget-label:before { | ||||
|         // Widget icon | ||||
|         font-size: 0.9em; | ||||
|         margin-right: $interiorMarginSm; | ||||
|     } | ||||
| } | ||||
|  | ||||
| .s-summary-widget { | ||||
|     // Widget style classes here | ||||
|     @include boxShdw($shdwBtns); | ||||
|     border-radius: $basicCr; | ||||
|     border-style: solid; | ||||
|     border-width: 1px; | ||||
|     box-sizing: border-box; | ||||
|     cursor: default; | ||||
|     font-size: 0.8rem; | ||||
|     padding: $interiorMarginLg $interiorMarginLg * 2; | ||||
|     &[href] { | ||||
|         cursor: pointer; | ||||
|     } | ||||
| } | ||||
|  | ||||
| .l-widget-outer-w, | ||||
| .widget-holder, | ||||
| .widget-edit-holder { | ||||
|     // In browse mode, all these things should be at .abs default | ||||
|     @extend .abs; | ||||
| } | ||||
|  | ||||
| .widget-edit-holder { | ||||
| @@ -64,42 +60,19 @@ | ||||
|     } | ||||
| } | ||||
|  | ||||
| .widget-rules-wrapper, | ||||
| .widget-rule-content, | ||||
| .w-widget-test-data-content { | ||||
|     @include trans-prop-nice($props: (height, min-height, opacity), $dur: 250ms); | ||||
| .widget-rule-content { | ||||
|     @include trans-prop-nice($props: (height, min-height), $dur: 250ms); | ||||
|     min-height: 0; | ||||
|     height: 0; | ||||
|     opacity: 0; | ||||
|     overflow: hidden; | ||||
|     pointer-events: none; | ||||
| } | ||||
|  | ||||
| .widget-rules-wrapper { | ||||
|     flex: 1 1 auto !important; | ||||
| } | ||||
|  | ||||
| .widget-rule-content.expanded { | ||||
|     overflow: visible !important; | ||||
|     min-height: 50px; | ||||
|     height: auto; | ||||
|     opacity: 1; | ||||
|     pointer-events: inherit; | ||||
| } | ||||
|  | ||||
| .w-widget-test-data-content { | ||||
|     .l-enable { | ||||
|         padding: $interiorMargin 0; | ||||
|     } | ||||
|  | ||||
|     .w-widget-test-data-items { | ||||
|         max-height: 20vh; | ||||
|         overflow-y: scroll !important; | ||||
|         padding-right: $interiorMargin; | ||||
|     &.expanded { | ||||
|         min-height: 50px; | ||||
|         height: auto; | ||||
|         overflow: visible; | ||||
|     } | ||||
| } | ||||
|  | ||||
| .l-widget-thumb-wrapper, | ||||
| .l-widget-thumb-w, | ||||
| .l-compact-form label { | ||||
|     $ruleLabelW: 40%; | ||||
|     $ruleLabelMaxW: 150px; | ||||
| @@ -108,199 +81,133 @@ | ||||
|     width: $ruleLabelW; | ||||
| } | ||||
|  | ||||
| .t-message-widget-no-data { | ||||
|     display: none; | ||||
| } | ||||
|  | ||||
| /********************************************************** EDITING A WIDGET */ | ||||
| .s-status-editing > mct-view > .w-summary-widget { | ||||
|     // Classes for editor layout while editing a widget | ||||
|     // This selector is ugly and brittle, but needed to prevent interface from showing when widget is in a layout | ||||
|     // being edited. | ||||
|     @include absPosDefault(); | ||||
|     @extend .l-flex-col; | ||||
| .s-status-editing .l-widget-outer-w { | ||||
|     $widgetHolderH: 100px; | ||||
|     @extend .abs; | ||||
|     //overflow: hidden; // Overflow scroll is handled by internal elements | ||||
|  | ||||
|     > .l-summary-widget { | ||||
|         // Main view of the summary widget | ||||
|         // Give some airspace and center the widget in the area | ||||
|         margin: 30px auto; | ||||
|     .widget-holder { | ||||
|         bottom: auto; | ||||
|         height: $widgetHolderH; | ||||
|         .l-summary-widget { | ||||
|             display: inline-block; | ||||
|             position: absolute; | ||||
|             top: 50%; left: 50%; | ||||
|             @include transform(translateX(-50%) translateY(-50%)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     .widget-edit-holder { | ||||
|         display: flex; // Overrides `display: none` during Browse mode | ||||
|         .flex-accordion-holder { | ||||
|             // Needed because otherwise accordion elements "creep" when contents expand and contract | ||||
|             display: block !important; | ||||
|         } | ||||
|         &.expanded-widget-test-data { | ||||
|             .w-widget-test-data-content { | ||||
|                 min-height: 50px; | ||||
|                 height: auto; | ||||
|                 opacity: 1; | ||||
|                 pointer-events: inherit; | ||||
|             } | ||||
|             &:not(.expanded-widget-rules) { | ||||
|                 // Test data is expanded and rules are collapsed | ||||
|                 // Make text data take up all the vertical space | ||||
|                 .flex-accordion-holder { display: flex; } | ||||
|                 .widget-test-data { | ||||
|                     flex-grow: 999999; | ||||
|                 } | ||||
|                 .w-widget-test-data-items { | ||||
|                     max-height: inherit; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         &.expanded-widget-rules { | ||||
|             .widget-rules-wrapper { | ||||
|                 min-height: 50px; | ||||
|                 height: auto; | ||||
|                 opacity: 1; | ||||
|                 pointer-events: inherit; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     &.s-status-no-data { | ||||
|         .widget-edit-holder { | ||||
|             opacity: 0.3; | ||||
|             pointer-events: none; | ||||
|         } | ||||
|         .t-message-widget-no-data { | ||||
|             display: flex; | ||||
|         } | ||||
|         @extend .l-flex-col; | ||||
|         display: block; // Needed to counteract display: none while browsing | ||||
|         overflow-y: scroll; | ||||
|         padding-right: $interiorMargin; | ||||
|         top: $widgetHolderH + $interiorMargin; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     .l-compact-form { | ||||
|         // Overrides on .l-compact-form | ||||
|         ul { | ||||
|             &:last-child { margin: 0; } | ||||
|             li { | ||||
|                 @include align-items(flex-start); | ||||
|                 @include flex-wrap(nowrap); | ||||
|                 line-height: 230%; // Provide enough space when controls wrap | ||||
|                 padding: 2px 0; | ||||
|                 &:not(.widget-rule-header) { | ||||
|                     &:not(.connects-to-previous) { | ||||
|                         border-top: 1px solid $colorFormLines; | ||||
|                     } | ||||
|                 } | ||||
|                 &.connects-to-previous { | ||||
|                     padding: $interiorMargin 0; | ||||
|                 } | ||||
|      | ||||
|     .widget-test-data, | ||||
|     .widget-rules-w { | ||||
|         @include test(blue, 0.1); | ||||
|     } | ||||
|      | ||||
|     .widget-test-data { | ||||
|  | ||||
|                 > label { | ||||
|                     display: block; // Needed to align text to right | ||||
|                     text-align: right; | ||||
|                 } | ||||
|             } | ||||
|     } | ||||
|  | ||||
|     .widget-rules-w { | ||||
|         // Wrapper area that holds n rules | ||||
|         @extend .flex-elem; | ||||
|         box-sizing: border-box; | ||||
|         font-size: 0.8em; | ||||
|     } | ||||
|  | ||||
|     .l-widget-rule { | ||||
|         box-sizing: border-box; | ||||
|         margin-bottom: $interiorMargin; | ||||
|         padding: $interiorMarginLg; | ||||
|     } | ||||
|  | ||||
|     .l-widget-thumb-w { | ||||
|         @extend .l-flex-row; | ||||
|         @include align-items(center); | ||||
|         > span { display: block; } | ||||
|         .grippy-holder, | ||||
|         .view-control { | ||||
|             margin-right: $interiorMargin; | ||||
|             width: 1em; | ||||
|             height: 1em; | ||||
|         } | ||||
|  | ||||
|         &.s-widget-test-data-item { | ||||
|             // Single line of ul li label span, etc. | ||||
|             ul { | ||||
|                 li { | ||||
|                     border: none !important; | ||||
|                     > label { | ||||
|                         display: inline-block; | ||||
|                         width: auto; | ||||
|                         text-align: left; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         .widget-thumb { | ||||
|             @include flex(1 1 auto); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| .widget-edit-holder { | ||||
|     font-size: 0.8rem; | ||||
| } | ||||
|     .rule-title { | ||||
|         @include flex(0 1 auto); | ||||
|         color: pullForward($colorBodyFg, 50%); | ||||
|     } | ||||
|  | ||||
| .widget-rules-wrapper { | ||||
|     // Wrapper area that holds n rules | ||||
|     box-sizing: border-box; | ||||
|     overflow-y: scroll; | ||||
|     padding-right: $interiorMargin; | ||||
| } | ||||
|     .rule-description { | ||||
|         @include flex(1 1 auto); | ||||
|         @include ellipsize(); | ||||
|         color: pushBack($colorBodyFg, 20%); | ||||
|     } | ||||
|  | ||||
| .l-widget-rule, | ||||
| .l-widget-test-data-item { | ||||
|     box-sizing: border-box; | ||||
|     margin-bottom: $interiorMarginSm; | ||||
|     padding: $interiorMargin $interiorMarginLg; | ||||
| } | ||||
|  | ||||
| .l-widget-thumb-wrapper { | ||||
|     @extend .l-flex-row; | ||||
|     @include align-items(center); | ||||
|     > span { display: block; } | ||||
|     .grippy-holder, | ||||
|     .view-control { | ||||
|         margin-right: $interiorMargin; | ||||
|         width: 1em; | ||||
|         height: 1em; | ||||
|     .s-widget-rule { | ||||
|         background-color: rgba($colorBodyFg, 0.1); | ||||
|         border-radius: $basicCr; | ||||
|     } | ||||
|  | ||||
|     .widget-thumb { | ||||
|         @include flex(1 1 auto); | ||||
|         width: 100%; | ||||
|         @include ellipsize(); | ||||
|         @extend .s-summary-widget; | ||||
|         @extend .l-summary-widget; | ||||
|         padding: $interiorMarginSm $interiorMargin; | ||||
|         .widget-icon { | ||||
|             font-size: 0.8em; | ||||
|             } | ||||
|     } | ||||
| } | ||||
|  | ||||
| .rule-title { | ||||
|     @include flex(0 1 auto); | ||||
|     color: pullForward($colorBodyFg, 50%); | ||||
| } | ||||
|  | ||||
| .rule-description { | ||||
|     @include flex(1 1 auto); | ||||
|     @include ellipsize(); | ||||
|     color: pushBack($colorBodyFg, 20%); | ||||
| } | ||||
|  | ||||
| .s-widget-rule, | ||||
| .s-widget-test-data-item { | ||||
|     background-color: rgba($colorBodyFg, 0.1); | ||||
|     border-radius: $basicCr; | ||||
| } | ||||
|  | ||||
| .widget-thumb { | ||||
|     @include ellipsize(); | ||||
|     @extend .s-summary-widget; | ||||
|     @extend .l-summary-widget; | ||||
|     padding: $interiorMarginSm $interiorMargin; | ||||
| } | ||||
|  | ||||
| // Hide and show elements in the rule-header on hover | ||||
| .l-widget-rule, | ||||
| .l-widget-test-data-item { | ||||
|     .grippy, | ||||
|     .l-rule-action-buttons-wrapper, | ||||
|     .l-condition-action-buttons-wrapper, | ||||
|     .l-widget-test-data-item-action-buttons-wrapper { | ||||
|         @include trans-prop-nice($props: opacity, $dur: 500ms); | ||||
|         opacity: 0; | ||||
|     } | ||||
|     &:hover { | ||||
|     // Hide and show elements in the rule-header on hover | ||||
|     .l-widget-rule { | ||||
|         .grippy, | ||||
|         .l-rule-action-buttons-wrapper, | ||||
|         .l-widget-test-data-item-action-buttons-wrapper { | ||||
|             @include trans-prop-nice($props: opacity, $dur: 0); | ||||
|             opacity: 1; | ||||
|         .l-rule-action-buttons-w, | ||||
|         .l-condition-action-buttons-w { | ||||
|             @include trans-prop-nice($props: opacity, $dur: 500ms); | ||||
|             opacity: 0; | ||||
|         } | ||||
|     } | ||||
|     .l-rule-action-buttons-wrapper { | ||||
|           .t-delete { | ||||
|             margin-left: 10px; | ||||
|           } | ||||
|     } | ||||
|     .t-condition { | ||||
|         &:hover { | ||||
|             .l-condition-action-buttons-wrapper { | ||||
|             .grippy, | ||||
|             .l-rule-action-buttons-w, | ||||
|             .l-condition-action-buttons-w { | ||||
|                 @include trans-prop-nice($props: opacity, $dur: 0); | ||||
|                 opacity: 1; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     .l-compact-form { | ||||
|         // Overrides | ||||
|         ul li { | ||||
|             padding: $interiorMargin 0; | ||||
|             &:not(.widget-rule-header) { | ||||
|                 &:not(.connects-to-previous) { | ||||
|                     border-top: 1px solid $colorFormLines; | ||||
|                 } | ||||
|             } | ||||
|             &.connects-to-previous { | ||||
|                 padding: $interiorMargin 0; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         label { | ||||
|             display: block; // Needed to align text to right | ||||
|             text-align: right; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -33,6 +33,7 @@ $pad: $interiorMargin * $baseRatio; | ||||
|     height: $btnStdH; | ||||
|     line-height: $btnStdH; | ||||
|     padding: 0 $pad; | ||||
|     vertical-align: top; | ||||
|  | ||||
|     &.labeled:before { | ||||
|         // Icon when it's included | ||||
|   | ||||
| @@ -72,13 +72,11 @@ | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Hyperlink objects | ||||
| .s-hyperlink { | ||||
|     .label { | ||||
|         font-size: 0.8rem !important; | ||||
|     } | ||||
|     // Hyperlink objects | ||||
|     &:not(.s-button) { | ||||
|         color: $colorKey; | ||||
|         font-size: 0.8rem; | ||||
|         &:hover { color: $colorKeyHov; } | ||||
|     } | ||||
| } | ||||
| @@ -234,16 +232,12 @@ textarea { | ||||
| } | ||||
|  | ||||
| /******************************************************** INPUTS */ | ||||
| %input-base { | ||||
|     @include input-base(); | ||||
| } | ||||
|  | ||||
| input[type="text"], | ||||
| input[type="search"], | ||||
| input[type="number"] { | ||||
|     @include nice-input(); | ||||
|     vertical-align: baseline; | ||||
|     padding: $inputTextPTopBtm $inputTextPLeftRight; | ||||
|     padding: $inputTextP; | ||||
|     &.numeric { | ||||
|         text-align: right; | ||||
|     } | ||||
| @@ -261,7 +255,7 @@ input[type="number"] { | ||||
| input[type="text"].lg {  width: 100% !important; } | ||||
| .l-input-med input[type="text"], | ||||
| input[type="text"].med { width: 200px !important; } | ||||
| input[type="text"].sm, input[type="number"].sm {  width: 50px !important; } | ||||
| input[type="text"].sm {  width: 50px !important; } | ||||
| .l-numeric input[type="text"], | ||||
| input[type="text"].numeric { text-align: right; } | ||||
|  | ||||
| @@ -287,44 +281,20 @@ textarea.lg { position: relative; height: 300px; } | ||||
|     } | ||||
| } | ||||
|  | ||||
| *[contenteditable].s-input-inline, | ||||
| input[type="text"].s-input-inline, | ||||
| .s-input-inline input[type="text"] { | ||||
|     // A text input or contenteditable element that indicates edit affordance on hover and looks like an input on focus | ||||
|     @extend %input-base; | ||||
|     @include trans-prop-nice((padding, box-shadow), 250ms); | ||||
|     background: none; | ||||
|     box-shadow: none; | ||||
|     border: 1px solid transparent; | ||||
|     min-width: 20px; | ||||
|     padding-left: 0; | ||||
|     padding-right: 0; | ||||
|     &:hover, | ||||
|     &:focus { | ||||
|         padding-left: $inputTextPLeftRight; | ||||
|         padding-right: $inputTextPLeftRight; | ||||
|     } | ||||
|     &:hover { | ||||
|         border-color: rgba($colorBodyFg, 0.2); | ||||
|     } | ||||
|     &:focus { | ||||
|         @include s-input(); | ||||
|         border-color: transparent; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /******************************************************** SELECTS */ | ||||
| .select { | ||||
|     @include btnSubtle($bg: $colorSelectBg); | ||||
|     @extend .icon-arrow-down; // Context arrow | ||||
|     //@if $shdwBtns != none { margin: 0 0 2px 0; } // Needed to avoid dropshadow from being clipped by parent containers | ||||
|     display: inline-block; | ||||
|     padding: 0 $interiorMargin; | ||||
|     overflow: hidden; | ||||
|     position: relative; | ||||
|     height: $btnStdH; | ||||
|     line-height: $btnStdH; | ||||
|     select { | ||||
|         @include appearance(none); | ||||
|         box-sizing: border-box; | ||||
|         &:focus { outline: 0; } | ||||
|         background: none; | ||||
|         color: $colorSelectFg; | ||||
|         cursor: pointer; | ||||
| @@ -394,7 +364,8 @@ input[type="text"].s-input-inline, | ||||
|     .l-elem-wrapper { | ||||
|         mct-representation { | ||||
|             // Holds the context-available item | ||||
|             // Must have min-width to make flex work properly in Safari | ||||
|             // Must have min-width to make flex work properly | ||||
|             // in Safari | ||||
|             min-width: 0.7em; | ||||
|         } | ||||
|     } | ||||
| @@ -560,6 +531,7 @@ input[type="text"].s-input-inline, | ||||
|     height: $h; | ||||
|     margin-top: 1 + floor($h/2) * -1; | ||||
|     @include btnSubtle(pullForward($colorBtnBg, 10%)); | ||||
|     //border-radius: 50% !important; | ||||
| } | ||||
|  | ||||
| @mixin sliderKnobRound() { | ||||
| @@ -574,6 +546,7 @@ input[type="text"].s-input-inline, | ||||
|  | ||||
| input[type="range"] { | ||||
|     // HTML5 range inputs | ||||
|  | ||||
|     -webkit-appearance: none; /* Hides the slider so that custom slider can be made */ | ||||
|     background: transparent; /* Otherwise white in Chrome */ | ||||
|     &:focus { | ||||
| @@ -772,15 +745,11 @@ body.desktop { | ||||
|     } | ||||
|  | ||||
|     .overlay ::-webkit-scrollbar-thumb { | ||||
|         $lr: 15%; | ||||
|         background: $scrollbarThumbColorOverlay; | ||||
|         &:hover { background: $scrollbarThumbColorOverlayHov; } | ||||
|     } | ||||
|  | ||||
|     .menu ::-webkit-scrollbar-thumb { | ||||
|         background: $scrollbarThumbColorMenu; | ||||
|         &:hover { background: $scrollbarThumbColorMenuHov; } | ||||
|     } | ||||
|  | ||||
|     ::-webkit-scrollbar-corner { | ||||
|         background: $scrollbarTrackColorBg; | ||||
|     } | ||||
|   | ||||
| @@ -21,20 +21,20 @@ | ||||
|  *****************************************************************************/ | ||||
| /******************************************************** MENU BUTTONS */ | ||||
| .s-menu-button { | ||||
|     // Formerly .btn-menu | ||||
|     @extend .s-button; | ||||
|     span.l-click-area { | ||||
|         // In markup, this element should not enclose anything. | ||||
|         @extend .abs; | ||||
|     } | ||||
| 	// Formerly .btn-menu | ||||
| 	@extend .s-button; | ||||
| 	span.l-click-area { | ||||
| 		// In markup, this element should not enclose anything. | ||||
| 		@extend .abs; | ||||
| 	} | ||||
|  | ||||
|     .icon { | ||||
|         font-size: 16px; | ||||
|     } | ||||
| 	.icon { | ||||
| 		font-size: 16px; //120%; | ||||
| 	} | ||||
|  | ||||
|     .title-label { | ||||
|         margin-left: $interiorMarginSm; | ||||
|     } | ||||
| 	.title-label { | ||||
| 		margin-left: $interiorMarginSm; | ||||
| 	} | ||||
|  | ||||
|     .icon-swatch, | ||||
|     .color-swatch { | ||||
| @@ -52,60 +52,66 @@ | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     &:after { | ||||
|         // Adds the downward facing 'context available / invoke menu' arrow element | ||||
|         @include contextArrow(); | ||||
|         color: rgba($colorInvokeMenu, percentToDecimal($contrastInvokeMenuPercent)); | ||||
|     } | ||||
| 	&:after { | ||||
| 		// Adds the downward facing 'context available / invoke menu' arrow element | ||||
| 		@include contextArrow(); | ||||
| 		color: rgba($colorInvokeMenu, percentToDecimal($contrastInvokeMenuPercent)); | ||||
| 	} | ||||
|  | ||||
|     &.create-button { | ||||
| 	&.create-button { | ||||
|         @extend .icon-plus; | ||||
|         .title-label { | ||||
|             font-size: 1rem; | ||||
|         } | ||||
|     } | ||||
| 		.title-label { | ||||
| 			font-size: 1rem; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|     .menu { | ||||
|         left: 0; | ||||
|         text-align: left; | ||||
|     } | ||||
| 	.menu { | ||||
| 		left: 0; | ||||
| 		text-align: left; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /******************************************************** MENUS THEMSELVES */ | ||||
| .menu-element { | ||||
|     cursor: pointer; | ||||
|     position: relative; | ||||
| 	cursor: pointer; | ||||
| 	position: relative; | ||||
| } | ||||
|  | ||||
| .s-menu { | ||||
| 	border-radius: $basicCr; | ||||
| 	@include containerSubtle($colorMenuBg, $colorMenuFg); | ||||
| 	@include boxShdw($shdwMenu); | ||||
| 	@include txtShdw($shdwMenuText); | ||||
| 	padding: $interiorMarginSm 0; | ||||
| } | ||||
|  | ||||
| .menu { | ||||
|     border-radius: $basicCr; | ||||
|     @include containerSubtle($colorMenuBg, $colorMenuFg); | ||||
|     @include boxShdw($shdwMenu); | ||||
|     @include txtShdw($shdwMenuText); | ||||
|     padding: $interiorMarginSm 0; | ||||
|     display: block; | ||||
|     position: absolute; | ||||
|     z-index: 10; | ||||
|     ul { | ||||
|         @include menuUlReset(); | ||||
|         li { | ||||
|             box-sizing: border-box; | ||||
|             border-top: 1px solid pullForward($colorMenuBg, 10%); | ||||
|     // TODO: reduce size of icons | ||||
| 	@extend .s-menu; | ||||
| 	display: block; | ||||
| 	position: absolute; | ||||
| 	z-index: 10; | ||||
| 	ul { | ||||
| 		@include menuUlReset(); | ||||
| 		li { | ||||
| 			box-sizing: border-box; | ||||
| 			border-top: 1px solid pullForward($colorMenuBg, 10%); | ||||
|             color: $colorMenuFg; | ||||
|             line-height: $menuLineH; | ||||
|             padding: $interiorMarginSm $interiorMargin * 2 $interiorMarginSm ($interiorMargin * 2) + $treeTypeIconW; | ||||
|             position: relative; | ||||
|             white-space: nowrap; | ||||
|             &:first-child { | ||||
|                 border: none; | ||||
|             } | ||||
|             &:hover { | ||||
|                 background: $colorMenuHovBg; | ||||
|                 color: $colorMenuHovFg; | ||||
| 			//color: pullForward($colorMenuBg, 60%); | ||||
| 			line-height: $menuLineH; | ||||
| 			padding: $interiorMarginSm $interiorMargin * 2 $interiorMarginSm ($interiorMargin * 2) + $treeTypeIconW; | ||||
| 			position: relative; | ||||
| 			white-space: nowrap; | ||||
| 			&:first-child { | ||||
| 				border: none; | ||||
| 			} | ||||
| 			&:hover { | ||||
| 				background: $colorMenuHovBg; | ||||
| 				color: $colorMenuHovFg; | ||||
|                 &:before { | ||||
|                     color: $colorMenuHovIc; | ||||
|                 } | ||||
|             } | ||||
| 			} | ||||
|             &:before { | ||||
|                 @extend .ui-symbol; | ||||
|                 @extend .type-icon; | ||||
| @@ -113,8 +119,8 @@ | ||||
|                 display: inline-block; | ||||
|                 left: $interiorMargin * 2; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| .menu, | ||||
| @@ -122,97 +128,94 @@ | ||||
| .context-menu, | ||||
| .super-menu, | ||||
| .s-menu-button .menu { | ||||
|     pointer-events: auto; | ||||
|     ul li { | ||||
|         a.menu-item-a { | ||||
| 	pointer-events: auto; | ||||
| 	ul li { | ||||
| 		a.menu-item-a { | ||||
|             color: $colorMenuFg; | ||||
|             display: block; | ||||
|         } | ||||
| 		} | ||||
|         &:before, | ||||
|         a.menu-item-a:before { | ||||
|             color: $colorMenuIc; | ||||
|             left: $interiorMargin; | ||||
|         } | ||||
|     } | ||||
| 	} | ||||
| } | ||||
|  | ||||
| .checkbox-menu { | ||||
|     // Used in search dropdown in tree | ||||
|     @extend .context-menu; | ||||
|     ul li { | ||||
|         padding-left: 50px; | ||||
|         .checkbox { | ||||
|             $d: 0.7rem; | ||||
|             position: absolute; | ||||
|             left: $interiorMargin; | ||||
|             top: ($menuLineH - $d) / 1.5; | ||||
|             em { | ||||
|                 height: $d; | ||||
|                 width: $d; | ||||
|                 &:before { | ||||
|                     font-size: 7px !important; | ||||
|                     height: $d; | ||||
|                     width: $d; | ||||
|                     line-height: $d; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         &:before { | ||||
| 	// Used in search dropdown in tree | ||||
| 	@extend .context-menu; | ||||
| 	ul li { | ||||
| 		padding-left: 50px; | ||||
| 		.checkbox { | ||||
| 			$d: 0.7rem; | ||||
| 			position: absolute; | ||||
| 			left: $interiorMargin; | ||||
| 			top: ($menuLineH - $d) / 1.5; | ||||
| 			em { | ||||
| 				height: $d; | ||||
| 				width: $d; | ||||
| 				&:before { | ||||
| 					font-size: 7px !important; | ||||
| 					height: $d; | ||||
| 					width: $d; | ||||
| 					line-height: $d; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		&:before { | ||||
|             // Type icon | ||||
|             left: 25px; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| .super-menu, | ||||
| .super-menu > mct-representation, | ||||
| .super-menu > .contents { | ||||
|     box-sizing: border-box; | ||||
|     display: block; | ||||
|     position: relative; | ||||
| 			left: 25px; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| .super-menu { | ||||
|     $plw: 50%; | ||||
|     $prw: 100% - $plw; | ||||
|     position: absolute; | ||||
|     .w-menu { | ||||
|         align-items: stretch; | ||||
|         display: flex; | ||||
|         flex-direction: row; | ||||
|         margin: $interiorMarginLg; | ||||
|     } | ||||
|     .col { | ||||
|         box-sizing: border-box; | ||||
|         flex: 1 1 auto; | ||||
|         overflow-x: hidden; | ||||
|         &.menu-items { | ||||
|             border-right: 1px solid pullForward($colorMenuBg, 10%); | ||||
|             overflow-y: auto; | ||||
|             padding-right: $interiorMargin; | ||||
|             width: $plw; | ||||
|             ul { | ||||
|                 li { | ||||
|                     border-radius: $controlCr; | ||||
|                     padding-left: 30px; | ||||
|                     border-top: none; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         &.menu-item-description { | ||||
|             $p: $interiorMargin * 3; | ||||
|             overflow-y: hidden; | ||||
|             padding: $p $p 0 $p; | ||||
|             width: $prw; | ||||
|  | ||||
| 	$w: 500px; | ||||
| 	$h: $w - 20; | ||||
| 	$plw: 50%; | ||||
| 	$prw: 50%; | ||||
| 	display: block; | ||||
| 	width: $w; | ||||
| 	height: $h; | ||||
| 	.contents { | ||||
| 		@include absPosDefault($interiorMargin); | ||||
| 	} | ||||
| 	.pane { | ||||
| 		box-sizing: border-box; | ||||
| 		&.menu-items { | ||||
| 			border-right: 1px solid pullForward($colorMenuBg, 10%); | ||||
| 			left: 0; | ||||
| 			padding-right: $interiorMargin; | ||||
| 			right: auto; | ||||
| 			width: $plw; | ||||
| 			overflow-x: hidden; | ||||
| 			overflow-y: auto; | ||||
| 			ul { | ||||
| 				li { | ||||
| 					border-radius: $controlCr; | ||||
| 					padding-left: 30px; | ||||
| 					border-top: none; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		&.menu-item-description { | ||||
| 			left: auto; | ||||
| 			right: 0; | ||||
| 			padding: $interiorMargin * 5; | ||||
| 			width: $prw; | ||||
|             .desc-area { | ||||
|                 &.icon { | ||||
|                     color: $colorCreateMenuLgIcon; | ||||
|                     font-size: 8em; | ||||
|                     margin-bottom: $interiorMargin * 3; | ||||
|                     position: relative; | ||||
|                     text-align: center; | ||||
|                 } | ||||
|                 &.title { | ||||
|                     color: $colorCreateMenuText; | ||||
|                     font-size: 1.2em; | ||||
|                     margin-bottom: $interiorMargin * 2; | ||||
|                 } | ||||
|                 &.description { | ||||
|                     color: pushBack($colorCreateMenuText, 20%); | ||||
| @@ -220,104 +223,67 @@ | ||||
|                     line-height: 1.5em; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     .w-title-desc { | ||||
|         display: flex; | ||||
|         flex-direction: column; | ||||
|         overflow: hidden; // Height set in specific menu instances | ||||
|     } | ||||
|  | ||||
|     // Specific menu instances | ||||
|     &.l-create-menu { | ||||
|         width: 500px; | ||||
|         .col { | ||||
|             max-height: 70vh; | ||||
|         } | ||||
|         .w-title-desc { | ||||
|             height: 190px; | ||||
|         } | ||||
|         .desc-area { | ||||
|             &.icon { | ||||
|                 font-size: 8em; | ||||
|                 height: 135px; | ||||
|                 margin-bottom: $interiorMargin * 3; | ||||
|             } | ||||
|             &.title { | ||||
|                 font-size: 1.2em; | ||||
|                 margin-bottom: $interiorMargin * 2; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|     &.mini { | ||||
|         width: 400px; | ||||
|         .col { | ||||
|             max-height: 50vh; | ||||
|         height: 300px; | ||||
|         .pane { | ||||
|             &.menu-items { | ||||
|                 font-size: 0.8em; | ||||
|             } | ||||
|             &.menu-item-description { | ||||
|                 $p: $interiorMargin * 2; | ||||
|                 padding: $p $p 0 $p; | ||||
|             } | ||||
|         } | ||||
|         .w-title-desc { | ||||
|             height: 180px; | ||||
|         } | ||||
|         .desc-area { | ||||
|             &.icon { | ||||
|                 font-size: 4em; | ||||
|                 height: 70px; | ||||
|                 margin-bottom: $interiorMargin * 3; | ||||
|             } | ||||
|             &.title { | ||||
|                 font-size: 1em; | ||||
|                 margin-bottom: $interiorMargin * 2; | ||||
|                 padding: $interiorMargin * 3; | ||||
|                 .desc-area { | ||||
|                     &.icon { | ||||
|                         font-size: 4em; | ||||
|                     } | ||||
|                     &.title { | ||||
|                         font-size: 1em; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| .context-menu { | ||||
|     font-size: 0.80rem; | ||||
| 	font-size: 0.80rem; | ||||
| } | ||||
|  | ||||
| .context-menu-holder, | ||||
| .menu-holder { | ||||
|     position: absolute; | ||||
|     z-index: 120; | ||||
|     .context-menu-wrapper { | ||||
|         position: absolute; | ||||
|         height: 100%; | ||||
|         width: 100%; | ||||
|     } | ||||
|     &.go-left .context-menu, | ||||
|     &.go-left .menu { | ||||
|         right: 0; | ||||
|     } | ||||
|     &.go-up .context-menu, | ||||
|     &.go-up .menu { | ||||
|         bottom: 0; | ||||
|     } | ||||
| 	position: absolute; | ||||
| 	z-index: 120; | ||||
| 	.context-menu-wrapper { | ||||
| 		position: absolute; | ||||
| 		height: 100%; | ||||
| 		width: 100%; | ||||
| 	} | ||||
| 	&.go-left .context-menu, | ||||
| 	&.go-left .menu { | ||||
| 		right: 0; | ||||
| 	} | ||||
| 	&.go-up .context-menu, | ||||
| 	&.go-up .menu { | ||||
| 		bottom: 0; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| .context-menu-holder { | ||||
|     pointer-events: none; | ||||
|     height: 200px; | ||||
|     width: 170px; | ||||
| 	pointer-events: none; | ||||
| 	height: 200px; | ||||
| 	width: 170px; | ||||
| } | ||||
|  | ||||
| .btn-bar.right .menu, | ||||
| .menus-to-left .menu { | ||||
|     z-index: 79; | ||||
|     left: auto; | ||||
|     right: 0; | ||||
|     width: auto; | ||||
| 	left: auto; | ||||
| 	right: 0; | ||||
| 	width: auto; | ||||
| } | ||||
|  | ||||
| .menus-up .menu { | ||||
|     bottom: $btnStdH; | ||||
|     top: auto; | ||||
|     bottom: $btnStdH; top: auto; | ||||
| } | ||||
|   | ||||
| @@ -19,7 +19,7 @@ | ||||
|  * this source code distribution or the Licensing information page available | ||||
|  * at runtime from the About dialog for additional information. | ||||
|  *****************************************************************************/ | ||||
| /******************************************************************* STATUS BLOCK ELEMS */ | ||||
|  | ||||
| @mixin statusBannerColors($bg, $fg: $colorStatusFg) { | ||||
| 	$bgPb: 30%; | ||||
| 	$bgPbD: 10%; | ||||
| @@ -39,7 +39,7 @@ | ||||
| // Status coloring | ||||
| .ok, .info { | ||||
|     .status-indicator { | ||||
|         color: $colorInfo; | ||||
|         color: $colorStatusInfo; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -120,11 +120,7 @@ | ||||
| 	} | ||||
|  | ||||
| 	.status-indicator { | ||||
|         background: none !important; | ||||
| 		margin-right: $interiorMarginSm; | ||||
|         &[class*='s-status']:before { | ||||
|             font-size: 1em; | ||||
|         } | ||||
| 	} | ||||
|  | ||||
| 	.count { | ||||
| @@ -140,7 +136,7 @@ | ||||
|     } | ||||
| } | ||||
|  | ||||
| /******************************************************************* MESSAGE BANNERS */ | ||||
| /* Styles for messages and message banners */ | ||||
| .message { | ||||
| 	&.block { | ||||
| 		border-radius: $basicCr; | ||||
| @@ -196,6 +192,7 @@ | ||||
| 		padding: 0 $interiorMargin; | ||||
| 	} | ||||
|     .close { | ||||
| 		//@include test(red, 0.7); | ||||
| 		cursor: pointer; | ||||
|         font-size: 7px; | ||||
| 		width: 8px; | ||||
| @@ -227,159 +224,144 @@ | ||||
| 	} | ||||
| 	&.ok, | ||||
|     &.info { | ||||
| 		@include statusBannerColors($colorInfo); | ||||
| 		@include statusBannerColors($colorStatusInfo); | ||||
| 	} | ||||
| 	&.caution, | ||||
|     &.warning, | ||||
|     &.alert { | ||||
| 		@include statusBannerColors($colorWarningLo); | ||||
| 		@include statusBannerColors($colorStatusAlert); | ||||
| 	} | ||||
|     &.error { | ||||
|         @include statusBannerColors($colorWarningHi); | ||||
|         @include statusBannerColors($colorStatusError); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /******************************************************************* MESSAGES */ | ||||
|  | ||||
| /* Contexts: | ||||
|     In .t-message-list | ||||
|     In .overlay as a singleton | ||||
|     Inline in the view area | ||||
|  */ | ||||
|  | ||||
| // Archetypal message | ||||
| .l-message { | ||||
|     $iconW: 32px; | ||||
|     @include display(flex); | ||||
|     @include flex-direction(row); | ||||
|     @include align-items(stretch); | ||||
|     padding: $interiorMarginLg; | ||||
|  | ||||
|     &:before { | ||||
|         // Icon | ||||
|         @include flex(0 1 auto); | ||||
| @mixin messageBlock($iconW: 32px) { | ||||
|     .type-icon.message-type { | ||||
|         @include txtShdw($shdwStatusIc); | ||||
|         @extend .icon-bell; | ||||
|         color: $colorStatusDefault; | ||||
|         font-size: $iconW; | ||||
|         padding: 1px; | ||||
|         width: $iconW + 2; | ||||
|         margin-right: $interiorMarginLg; | ||||
|     } | ||||
|  | ||||
|     &.message-severity-info:before { | ||||
|     .message-severity-info .type-icon.message-type { | ||||
|         @extend .icon-info; | ||||
|         color: $colorInfo; | ||||
|         color: $colorStatusInfo; | ||||
|     } | ||||
|  | ||||
|     &.message-severity-alert:before { | ||||
|         color: $colorWarningLo; | ||||
|     .message-severity-alert .type-icon.message-type { | ||||
|         @extend .icon-bell; | ||||
|         color: $colorStatusAlert; | ||||
|     } | ||||
|  | ||||
|     &.message-severity-error:before { | ||||
|     .message-severity-error .type-icon.message-type { | ||||
|         @extend .icon-alert-rect; | ||||
|         color: $colorWarningHi; | ||||
|         color: $colorStatusError; | ||||
|     } | ||||
| } | ||||
| /* Paths: | ||||
|     t-dialog | t-dialog-sm > t-message-single | t-message-list > overlay > holder > contents > l-message > | ||||
|         message-type > (icon) | ||||
|         message-contents > | ||||
|         top-bar > | ||||
|             title | ||||
|             hint | ||||
|         editor > | ||||
|             (if displaying list of messages) | ||||
|             ul > li > l-message > | ||||
|                 ... same as above | ||||
|         bottom-bar | ||||
| */ | ||||
|  | ||||
|  | ||||
| .w-message-contents { | ||||
|     @include flex(1 1 auto); | ||||
| .l-message { | ||||
|     @include display(flex); | ||||
|     @include flex-direction(column); | ||||
|  | ||||
|     > div, | ||||
|     > span { | ||||
|         //@include test(red); | ||||
|         margin-bottom: $interiorMargin; | ||||
|     @include flex-direction(row); | ||||
|     @include align-items(stretch); | ||||
|     .type-icon.message-type { | ||||
|         @include flex(0 1 auto); | ||||
|         position: relative; | ||||
|     } | ||||
|     .message-contents { | ||||
|         @include flex(1 1 auto); | ||||
|         margin-left: $overlayMargin; | ||||
|         position: relative; | ||||
|  | ||||
|     .message-body { | ||||
|         @include flex(1 1 100%); | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Singleton in an overlay dialog | ||||
| .t-message-single .l-message, | ||||
| .t-message-single.l-message { | ||||
|         $iconW: 80px; | ||||
|         @include absPosDefault(); | ||||
|         padding: 0; | ||||
|         &:before { | ||||
|             font-size: $iconW; | ||||
|             width: $iconW + 2; | ||||
|         } | ||||
|         .title { | ||||
|             font-size: 1.2em; | ||||
|         } | ||||
| } | ||||
|  | ||||
| // Singleton inline in a view | ||||
| .t-message-inline .l-message, | ||||
| .t-message-inline.l-message { | ||||
|     border-radius: $controlCr; | ||||
|     &.message-severity-info { background-color: rgba($colorInfo, 0.3); } | ||||
|     &.message-severity-alert { background-color: rgba($colorWarningLo, 0.3); } | ||||
|     &.message-severity-error { background-color: rgba($colorWarningHi, 0.3); } | ||||
|  | ||||
|     .w-message-contents.l-message-body-only { | ||||
|         .top-bar, | ||||
|         .message-body { | ||||
|             margin-top: $interiorMargin; | ||||
|             margin-bottom: $interiorMarginLg * 2; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| // In a list | ||||
| .t-message-list { | ||||
|     @include absPosDefault(); | ||||
|     @include display(flex); | ||||
|     @include flex-direction(column); | ||||
|  | ||||
|     > div, | ||||
|     > span { | ||||
|         margin-bottom: $interiorMargin; | ||||
| // Message as singleton | ||||
| .t-message-single { | ||||
|     @include messageBlock(80px); | ||||
| } | ||||
|  | ||||
| body.desktop .t-message-single { | ||||
|     .l-message, | ||||
|     .bottom-bar { | ||||
|         @include absPosDefault(); | ||||
|     } | ||||
|  | ||||
|     .w-messages { | ||||
|         @include flex(1 1 100%); | ||||
|         overflow-y: auto; | ||||
|         padding-right: $interiorMargin; | ||||
|     .bottom-bar { | ||||
|         top: auto; | ||||
|         height: $ovrFooterH; | ||||
|     } | ||||
|     // Each message | ||||
|     .l-message { | ||||
|         border-radius: $controlCr; | ||||
|         background: rgba($colorOvrFg, 0.1); | ||||
|         margin-bottom: $interiorMargin; | ||||
|         .hint, | ||||
|         .bottom-bar { | ||||
|             text-align: left; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| @include phonePortrait { | ||||
|     .t-message-single .l-message, | ||||
|     .t-message-single.l-message { | ||||
|         @include flex-direction(column); | ||||
|         &:before { | ||||
|             margin-right: 0; | ||||
|     .t-message-single { | ||||
|         .l-message { | ||||
|             @include flex-direction(column); | ||||
|             .message-contents { margin-left: 0; } | ||||
|         } | ||||
|         .type-icon.message-type { | ||||
|             margin-bottom: $interiorMarginLg; | ||||
|             text-align: center; | ||||
|             width: 100%; | ||||
|             text-align: center; | ||||
|         } | ||||
|  | ||||
|         .bottom-bar { | ||||
|             text-align: center; | ||||
|             .s-button { | ||||
|                 display: block; | ||||
|                 width: 100%; | ||||
|             text-align: center !important; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Messages in list | ||||
| .t-message-list { | ||||
|     @include messageBlock(32px); | ||||
|  | ||||
|     .message-contents { | ||||
|         .l-message { | ||||
|             border-radius: $controlCr; | ||||
|             background: rgba($colorOvrFg, 0.1); | ||||
|             margin-bottom: $interiorMargin; | ||||
|             padding: $interiorMarginLg; | ||||
|  | ||||
|             .message-contents, | ||||
|             .bottom-bar { | ||||
|                 position: relative; | ||||
|             } | ||||
|  | ||||
|             .message-contents { | ||||
|                 font-size: 0.9em; | ||||
|                 margin-left: $interiorMarginLg; | ||||
|                 .message-action { color: pushBack($colorOvrFg, 20%); } | ||||
|                 .bottom-bar { text-align: left; } | ||||
|             } | ||||
|  | ||||
|             .top-bar, | ||||
|             .message-body { | ||||
|                 margin-bottom: $interiorMarginLg; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| body.desktop .t-message-list { | ||||
|     .w-message-contents { padding-right: $interiorMargin; } | ||||
|     .message-contents .l-message { margin-right: $interiorMarginLg; } | ||||
| } | ||||
|  | ||||
| // Alert elements in views | ||||
|   | ||||
| @@ -80,32 +80,23 @@ | ||||
|  | ||||
|     // Editing Grids | ||||
|     .l-grid-holder { | ||||
|         display: block; | ||||
|         .l-grid { | ||||
|             &.l-grid-x { @include bgTicks($colorGridLines, 'x'); } | ||||
|             &.l-grid-y { @include bgTicks($colorGridLines, 'y'); } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Display grid when selected or selection parent. | ||||
|     .s-selected .l-grid-holder, | ||||
|     .s-selected-parent .l-grid-holder { | ||||
|         display: block; | ||||
|     // Prevent nested frames from showing their grids | ||||
|     .t-frame-outer .l-grid-holder { display: none !important; } | ||||
|  | ||||
|     // Prevent nested elements from showing s-hover-border | ||||
|     .t-frame-outer .s-hover-border { | ||||
|         border: none !important; | ||||
|     } | ||||
|  | ||||
|     // Display in nested frames... | ||||
|     .t-frame-outer { | ||||
|         // ...when drilled in or selection parent... | ||||
|         &.s-drilled-in, &.s-selected-parent { | ||||
|             .l-grid-holder { | ||||
|                 display: block; | ||||
|             } | ||||
|             .t-frame-outer:not(.s-drilled-in) .l-grid-holder { | ||||
|                 display: none; | ||||
|             } | ||||
|         } | ||||
|         // ...but hide otherwise. | ||||
|         .l-grid-holder { | ||||
|             display: none; | ||||
|         } | ||||
|     // Prevent nested frames from being selectable until we have proper sub-object editing | ||||
|     .t-frame-outer .t-frame-outer { | ||||
|         pointer-events: none; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -9,6 +9,7 @@ | ||||
| 	@if $enableImageryThumbs == true { | ||||
| 		bottom: $interiorMargin*2 +  $imageThumbsWrapperH; | ||||
| 	} | ||||
| 	min-height: 100px; | ||||
| 	min-width: 150px; | ||||
| 	.l-image-main { | ||||
| 		background-color: $colorPlotBg; | ||||
| @@ -21,9 +22,7 @@ | ||||
|  | ||||
| .l-image-thumbs-wrapper { | ||||
| 	top: auto; | ||||
| 	min-height: $imageThumbsWrapperH; | ||||
| 	max-height: 60%; | ||||
| 	box-sizing: border-box; | ||||
| 	height: $imageThumbsWrapperH; | ||||
| } | ||||
|  | ||||
| .l-date, | ||||
| @@ -44,16 +43,14 @@ | ||||
| .l-image-main-controlbar { | ||||
| 	font-size: 0.8em; | ||||
| 	line-height: inherit; | ||||
| 	.l-datetime-w, .l-controls-w { | ||||
| 	.left, .right { | ||||
| 		direction: rtl; | ||||
| 		overflow: hidden; | ||||
| 	} | ||||
| 	.l-datetime-w { | ||||
|         @include ellipsize(); | ||||
|         margin-right: $interiorMarginSm; | ||||
| 	.left { | ||||
| 		text-align: left; | ||||
| 	} | ||||
| 	.l-controls-w { | ||||
| 	.right { | ||||
| 		z-index: 2; | ||||
| 	} | ||||
| 	.l-date, | ||||
| @@ -85,8 +82,9 @@ | ||||
| /*************************************** THUMBS */ | ||||
|  | ||||
| .l-image-thumbs-wrapper { | ||||
| 	overflow-x: hidden; | ||||
| 	overflow-y: auto; | ||||
| 	//@include test(green); | ||||
| 	overflow-x: auto; | ||||
| 	overflow-y: hidden; | ||||
| 	padding-bottom: $interiorMargin; | ||||
| 	white-space: nowrap; | ||||
| } | ||||
| @@ -94,17 +92,8 @@ | ||||
| .l-image-thumb-item { | ||||
| 	@include transition(background-color, 0.25s); | ||||
| 	box-sizing: border-box; | ||||
|     cursor: pointer; | ||||
|     direction: ltr; | ||||
|     display: inline-block; | ||||
|     float: left; | ||||
|     font-size: 0.8em; | ||||
| 	padding: 1px; | ||||
|     margin-left: $interiorMarginSm; | ||||
|     position: relative; | ||||
|     text-align: left; | ||||
|     width: $imageThumbsD + $imageThumbPad*2; | ||||
|     white-space: normal; | ||||
| 	position: relative; | ||||
| 	.l-thumb, | ||||
| 	.l-date, | ||||
| 	.l-time { | ||||
| @@ -114,7 +103,14 @@ | ||||
| 	.l-time { | ||||
| 		padding: 2px 3px; | ||||
| 	} | ||||
|  | ||||
| 	cursor: pointer; | ||||
| 	direction: ltr; | ||||
| 	display: inline-block; | ||||
| 	font-size: 0.8em; | ||||
| 	margin-left: $interiorMarginSm; | ||||
| 	text-align: left; | ||||
| 	width: $imageThumbsD + $imageThumbPad*2; | ||||
| 	white-space: normal; | ||||
| 	&:hover { | ||||
| 		background: $colorThumbHoverBg; | ||||
| 		.l-date, | ||||
| @@ -140,7 +136,6 @@ | ||||
| /*************************************** LOCAL CONTROLS */ | ||||
| .l-local-controls { | ||||
|     max-width: 200px; | ||||
|     min-width: 100px; | ||||
|     width: 35%; | ||||
|     input[type="range"] { | ||||
|         display: block; | ||||
| @@ -189,8 +184,7 @@ | ||||
| /*************************************** WHEN IN FRAME */ | ||||
| .frame .t-imagery { | ||||
| 	.l-image-main-wrapper { | ||||
| 		bottom: 0 !important; | ||||
|         height: 100% !important; | ||||
| 		bottom: 0; | ||||
| 		.l-image-main-controlbar { | ||||
| 			font-size: 0.7em; | ||||
| 		} | ||||
| @@ -200,8 +194,7 @@ | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	.l-image-thumbs-wrapper, | ||||
|     mct-splitter { | ||||
| 	.l-image-thumbs-wrapper { | ||||
| 		display: none; | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -23,16 +23,10 @@ | ||||
|     border-radius: $basicCr; | ||||
|     background: $colorFormSectionHeader; | ||||
|     color: lighten($colorBodyFg, 20%); | ||||
|     font-size: inherit; | ||||
|     font-size: 0.8em; | ||||
|     margin: $interiorMargin 0; | ||||
|     padding: $formTBPad $formLRPad; | ||||
|     text-transform: uppercase; | ||||
|     .view-control { | ||||
|         display: inline-block; | ||||
|         margin-right: $interiorMargin; | ||||
|         width: 1em; | ||||
|         height: 1em; | ||||
|     } | ||||
| } | ||||
|  | ||||
| .form { | ||||
| @@ -60,6 +54,9 @@ | ||||
|         margin-bottom: $interiorMarginLg * 2; | ||||
| 		padding: $formTBPad 0; | ||||
| 		position: relative; | ||||
|         //&ng-form { | ||||
|         //    display: block; | ||||
|         //} | ||||
|  | ||||
| 		&.first { | ||||
| 			border-top: none; | ||||
| @@ -196,23 +193,16 @@ | ||||
|             label, | ||||
|             .control { | ||||
|                 @include display(flex); | ||||
|                 //min-width: $minW; | ||||
|             } | ||||
|             label { | ||||
|                 line-height: inherit; | ||||
|                 padding: $interiorMarginSm 0; | ||||
|                 width: $labelW; | ||||
|             } | ||||
|             .controls { | ||||
|                 @include flex-grow(1); | ||||
|                 margin-left: $interiorMargin; | ||||
|                 input[type="text"], | ||||
|                 input[type="search"], | ||||
|                 input[type="number"], | ||||
|                 .select { | ||||
|                     height: $btnStdH; | ||||
|                     line-height: $btnStdH; | ||||
|                     vertical-align: middle; | ||||
|                 } | ||||
|  | ||||
|                 margin-left: $interiorMargin    ; | ||||
|                 .e-control { | ||||
|                     // Individual form controls | ||||
|                     &:not(:first-child) { | ||||
| @@ -221,6 +211,12 @@ | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             &:not(.section-header) { | ||||
|                 &:not(.connects-to-previous) { | ||||
|                     //border-top: 1px solid $colorFormLines; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             &.connects-to-previous { | ||||
|                 padding-top: 0; | ||||
|             } | ||||
|   | ||||
| @@ -129,6 +129,9 @@ | ||||
| } | ||||
|  | ||||
| .s-filter { | ||||
|     input[type="search"] { | ||||
|         @include input-base(); | ||||
|     } | ||||
|     .clear-icon, | ||||
|     .menu-icon, | ||||
|     &:before { | ||||
|   | ||||
| @@ -79,7 +79,6 @@ | ||||
|  | ||||
|     // Dialog boxes, size constrained and centered in desktop/tablet | ||||
|     &.l-dialog { | ||||
|         font-size: 0.8rem; | ||||
|         .s-button { | ||||
|             &:not(.major) { | ||||
|                 @include btnSubtle($bg: $colorOvrBtnBg, $bgHov: pullForward($colorOvrBtnBg, 10%), $fg: $colorOvrBtnFg, $fgHov: $colorOvrBtnFg, $ic: $colorOvrBtnFg, $icHov: $colorOvrBtnFg); | ||||
| @@ -126,9 +125,9 @@ | ||||
|             @include containerSubtle($colorOvrBg, $colorOvrFg); | ||||
|         } | ||||
|  | ||||
|         .dialog-title { | ||||
|         .title { | ||||
|             @include ellipsize(); | ||||
|             font-size: 1.5em; | ||||
|             font-size: 1.2em; | ||||
|             line-height: 120%; | ||||
|             margin-bottom: $interiorMargin; | ||||
|         } | ||||
| @@ -157,8 +156,6 @@ | ||||
|             left: 0; | ||||
|             right: 0; | ||||
|             overflow: auto; | ||||
|             padding-right: $interiorMargin; | ||||
|             padding-bottom: $interiorMargin; | ||||
|             .field.l-input-med { | ||||
|                 input[type='text'] { | ||||
|                     width: 100%; | ||||
|   | ||||
| @@ -26,10 +26,12 @@ | ||||
|         z-index: 0; // Needed to prevent child-frame controls from showing through when another child-frame is above | ||||
|         &:not(.no-frame) { | ||||
|             background: $colorBodyBg; | ||||
|             border-color: $bc; | ||||
|             border: 1px solid $bc; | ||||
|             &:hover { | ||||
|                 border-color: lighten($bc, 10%); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     .object-browse-bar { | ||||
|         font-size: 0.75em; | ||||
|         height: $ohH; | ||||
| @@ -42,11 +44,10 @@ | ||||
|  | ||||
|     &.t-object-type-timer, | ||||
|     &.t-object-type-clock, | ||||
|     &.t-object-type-hyperlink, | ||||
|     &.t-object-type-summary-widget { | ||||
|     &.t-object-type-hyperlink { | ||||
|         // Hide the right side buttons for objects where they don't make sense | ||||
|         // Note that this will hide the view Switcher button if applied | ||||
|         // to an object that has it. | ||||
|         // to an object that it. | ||||
|         .object-browse-bar .right { display: none; } | ||||
|     } | ||||
|  | ||||
| @@ -90,9 +91,9 @@ | ||||
|  | ||||
|     &.no-frame { | ||||
|         background: transparent !important; | ||||
|         border-color: transparent; | ||||
|         border: none !important; | ||||
|         .object-browse-bar .right { | ||||
|             $m: 0; | ||||
|             $m: 0; // $interiorMarginSm; | ||||
|             background: rgba(black, 0.3); | ||||
|             border-radius: $basicCr; | ||||
|             padding: $interiorMarginSm; | ||||
| @@ -102,7 +103,7 @@ | ||||
|         } | ||||
|         &.t-frame-outer > .t-rep-frame { | ||||
|             &.contents { | ||||
|                 $m: 0px; | ||||
|                 $m: 2px; | ||||
|                 top: $m; | ||||
|                 right: $m; | ||||
|                 bottom: $m; | ||||
| @@ -113,33 +114,17 @@ | ||||
|                     display: none; | ||||
|                 } | ||||
|                 > .object-holder.abs { | ||||
|                     overflow: hidden; | ||||
|                     top: 0 !important; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     &.t-frame-outer .s-input-inline { | ||||
|         // Prevent inline inputs from being edited when nested in a Layout | ||||
|         pointer-events: none !important; | ||||
|     } | ||||
|  | ||||
|     /********************************************************** OBJECT TYPES */ | ||||
|     .t-object-type-hyperlink, | ||||
|     .t-object-type-summary-widget { | ||||
|         .object-holder { | ||||
|             overflow: hidden; | ||||
|         } | ||||
|         .w-summary-widget, | ||||
|         .l-summary-widget, | ||||
|         .l-hyperlink.s-button { | ||||
|             // Some object types expand to the full size of the object-holder. | ||||
|     .t-object-type-hyperlink { | ||||
|         .s-hyperlink.s-button { | ||||
|             // When a hyperlink is a button in a frame, make it expand to fill out to the object-holder | ||||
|             @extend .abs; | ||||
|         } | ||||
|  | ||||
|         .l-summary-widget, | ||||
|         .l-hyperlink.s-button { | ||||
|             .label { | ||||
|                 @include ellipsize(); | ||||
|                 @include transform(translateY(-50%)); | ||||
| @@ -157,7 +142,7 @@ | ||||
| body.desktop .frame { | ||||
|     // Hide local controls initially and show it them on hover when they're in an element that's in a frame context | ||||
|     // Frame template is used because we need to target the lowest nested frame | ||||
|     .object-browse-bar .btn-bar { | ||||
|     .right { | ||||
|         opacity: 0; | ||||
|         pointer-events: none; | ||||
|     } | ||||
| @@ -165,7 +150,7 @@ body.desktop .frame { | ||||
|     // Target the first descendant so that we only show the elements in the outermost container. | ||||
|     // Handles the case where we have layouts in layouts. | ||||
|     &:hover > .object-browse-bar { | ||||
|         .btn-bar { | ||||
|         .right { | ||||
|             opacity: 1; | ||||
|             pointer-events: inherit; | ||||
|         } | ||||
|   | ||||
| @@ -240,9 +240,7 @@ body.desktop .pane .mini-tab-icon.toggle-pane { | ||||
| .top-bar .buttons-main .s-button, | ||||
| .top-bar .s-menu-button, | ||||
| .tool-bar .s-button, | ||||
| .tool-bar .s-menu-button, | ||||
| .tool-bar .select, | ||||
| .tool-bar .input-labeled { | ||||
| .tool-bar .s-menu-button { | ||||
|     $h: $btnToolbarH; | ||||
|     height: $h; | ||||
|     line-height: $h; | ||||
|   | ||||
| @@ -20,52 +20,35 @@ | ||||
|  * at runtime from the About dialog for additional information. | ||||
|  *****************************************************************************/ | ||||
| .s-hover-border { | ||||
|     border: 1px solid transparent; | ||||
|     &:hover { | ||||
|         border-color: rgba($colorSelectableSelectedPrimary, 0.5) !important; | ||||
|     } | ||||
|     border: 1px dotted transparent; | ||||
| } | ||||
|  | ||||
| .s-status-editing { | ||||
|     // Limit to editing mode | ||||
|     $o: 0.5; | ||||
|     $oHover: 0.8; | ||||
|     $bc: $colorSelectableSelectedPrimary; | ||||
|     // Limit to editing mode until we have sub-object selection | ||||
|     .s-hover-border { | ||||
|         // Show a border by default so user can see object bounds and empty objects | ||||
|         border-color: rgba($bc, $o) !important; | ||||
|         border-style: dotted !important; | ||||
|  | ||||
|         border: 1px dotted rgba($colorSelectableSelectedPrimary, 0.3) !important; | ||||
|         &:hover { | ||||
|             border-color: rgba($bc, $oHover) !important; | ||||
|         } | ||||
|  | ||||
|         &.t-object-type-layout { | ||||
|             border-style: dashed !important; | ||||
|             border-color: rgba($colorSelectableSelectedPrimary, 0.7) !important; | ||||
|         } | ||||
|     } | ||||
|     .s-selected { | ||||
|         &.s-moveable { | ||||
|             &:not(.s-drilled-in) { | ||||
|                 cursor: move; | ||||
|  | ||||
|     .s-selected > .s-hover-border, | ||||
|     .s-selected.s-hover-border { | ||||
|         // Styles for a selected object. Also used by legacy Fixed Position/Panel objects. | ||||
|         border-color: $colorSelectableSelectedPrimary !important; | ||||
|         @include boxShdwLarge(); | ||||
|         // Show edit-corners if you got 'em | ||||
|         .edit-corner { | ||||
|             display: block; | ||||
|             &:hover { | ||||
|                 background-color: rgba($colorKey, 1); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| .s-selected > .s-hover-border, | ||||
| .s-selected.s-hover-border { | ||||
|     // Styles for a selected object. Also used by legacy Fixed Position/Panel objects. | ||||
|     border-color: $colorSelectableSelectedPrimary !important; | ||||
|     @include boxShdwLarge(); | ||||
|     // Show edit-corners if you got 'em | ||||
|     .edit-corner { | ||||
|         display: block; | ||||
|         &:hover { | ||||
|             background-color: rgba($colorKey, 1); | ||||
|         } | ||||
|     .s-selected > .s-moveable, | ||||
|     .s-selected.s-moveable { | ||||
|         cursor: move; | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| } | ||||
| @@ -20,7 +20,6 @@ | ||||
|  * at runtime from the About dialog for additional information. | ||||
|  *****************************************************************************/ | ||||
| .tool-bar { | ||||
|     font-size: 0.7rem; | ||||
|     &.btn-bar { | ||||
|         white-space: nowrap; | ||||
|     } | ||||
| @@ -31,7 +30,9 @@ | ||||
|     input[type="search"], | ||||
|     input[type="number"] { | ||||
| 		box-sizing: border-box; | ||||
| 		font-size: .8em; | ||||
| 		height: $btnToolbarH; | ||||
| 		margin-bottom: 1px; | ||||
| 		position: relative; | ||||
| 		&.sm { | ||||
| 			width: $btnToolbarH; | ||||
|   | ||||
| @@ -20,7 +20,7 @@ | ||||
|  at runtime from the About dialog for additional information. | ||||
| --> | ||||
| <span ng-controller="DateTimeFieldController"> | ||||
|     <input type="text" autocorrect="off" spellcheck="false" | ||||
|     <input type="text" | ||||
|            ng-model="textValue" | ||||
|            ng-blur="restoreTextValue(); ngBlur()" | ||||
|            ng-mouseup="ngMouseup()" | ||||
|   | ||||
| @@ -20,7 +20,7 @@ | ||||
|  at runtime from the About dialog for additional information. | ||||
| --> | ||||
| <!-- look at action-button for example --> | ||||
| <span class="t-filter l-filter" | ||||
| <span class="t-filter l-filter s-filter" | ||||
|       ng-controller="GetterSetterController"> | ||||
| 	<input type="search" | ||||
|            class="t-filter-input" | ||||
|   | ||||
| @@ -40,7 +40,7 @@ define( | ||||
|  | ||||
|             // Gets an array of the contextual parents/ancestors of the selected object | ||||
|             function getContextualPath() { | ||||
|                 var currentObj = $scope.domainObject, | ||||
|                 var currentObj = $scope.ngModel.selectedObject, | ||||
|                     currentParent, | ||||
|                     parents = []; | ||||
|  | ||||
| @@ -68,7 +68,7 @@ define( | ||||
|  | ||||
|                 // If this the the initial call of this recursive function | ||||
|                 if (!current) { | ||||
|                     current = $scope.domainObject; | ||||
|                     current = $scope.ngModel.selectedObject; | ||||
|                     $scope.primaryParents = []; | ||||
|                 } | ||||
|  | ||||
| @@ -87,16 +87,16 @@ define( | ||||
|  | ||||
|             // Gets the metadata for the selected object | ||||
|             function getMetadata() { | ||||
|                 $scope.metadata = $scope.domainObject && | ||||
|                     $scope.domainObject.hasCapability('metadata') && | ||||
|                     $scope.domainObject.useCapability('metadata'); | ||||
|                 $scope.metadata = $scope.ngModel.selectedObject && | ||||
|                     $scope.ngModel.selectedObject.hasCapability('metadata') && | ||||
|                     $scope.ngModel.selectedObject.useCapability('metadata'); | ||||
|             } | ||||
|  | ||||
|             // Set scope variables when the selected object changes | ||||
|             $scope.$watch('domainObject', function () { | ||||
|                 $scope.isLink = $scope.domainObject && | ||||
|                     $scope.domainObject.hasCapability('location') && | ||||
|                     $scope.domainObject.getCapability('location').isLink(); | ||||
|             $scope.$watch('ngModel.selectedObject', function () { | ||||
|                 $scope.isLink = $scope.ngModel.selectedObject && | ||||
|                     $scope.ngModel.selectedObject.hasCapability('location') && | ||||
|                     $scope.ngModel.selectedObject.getCapability('location').isLink(); | ||||
|  | ||||
|                 if ($scope.isLink) { | ||||
|                     getPrimaryPath(); | ||||
| @@ -108,11 +108,8 @@ define( | ||||
|  | ||||
|                 getMetadata(); | ||||
|             }); | ||||
|  | ||||
|             var mutation = $scope.domainObject.getCapability('mutation'); | ||||
|             var unlisten = mutation.listen(getMetadata); | ||||
|             $scope.$on('$destroy', unlisten); | ||||
|         } | ||||
|  | ||||
|         return ObjectInspectorController; | ||||
|     } | ||||
| ); | ||||
|   | ||||
| @@ -1,60 +0,0 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT, Copyright (c) 2014-2017, United States Government | ||||
|  * as represented by the Administrator of the National Aeronautics and Space | ||||
|  * Administration. All rights reserved. | ||||
|  * | ||||
|  * Open MCT 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 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. | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| define( | ||||
|     [], | ||||
|     function () { | ||||
|  | ||||
|         /** | ||||
|          * The mct-selectable directive allows selection functionality | ||||
|          * (click) to be attached to specific elements. | ||||
|          * | ||||
|          * @memberof platform/commonUI/general | ||||
|          * @constructor | ||||
|          */ | ||||
|         function MCTSelectable(openmct) { | ||||
|  | ||||
|             // Link; install event handlers. | ||||
|             function link(scope, element, attrs) { | ||||
|                 var removeSelectable = openmct.selection.selectable( | ||||
|                     element[0], | ||||
|                     scope.$eval(attrs.mctSelectable), | ||||
|                     attrs.hasOwnProperty('mctInitSelect') && scope.$eval(attrs.mctInitSelect) !== false | ||||
|                 ); | ||||
|  | ||||
|                 scope.$on("$destroy", function () { | ||||
|                     removeSelectable(); | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             return { | ||||
|                 // mct-selectable only makes sense as an attribute | ||||
|                 restrict: "A", | ||||
|                 // Link function, to install event handlers | ||||
|                 link: link | ||||
|             }; | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return MCTSelectable; | ||||
|     } | ||||
| ); | ||||
| @@ -117,8 +117,6 @@ define( | ||||
|  | ||||
|                 // Apply styles to child elements | ||||
|                 function updateChildren(children) { | ||||
|                     position = userWidthPreference || position; | ||||
|  | ||||
|                     // Pick out correct elements to update, flowing from | ||||
|                     // selected anchor edge. | ||||
|                     var first = children.eq(anchor.reversed ? 2 : 0), | ||||
| @@ -128,7 +126,7 @@ define( | ||||
|  | ||||
|                     splitterSize = getSize(splitter[0]); | ||||
|                     first.css(anchor.edge, "0px"); | ||||
|                     first.css(anchor.dimension, position + 'px'); | ||||
|                     first.css(anchor.dimension, (userWidthPreference || position) + 'px'); | ||||
|  | ||||
|                     // Get actual size (to obey min-width etc.) | ||||
|                     firstSize = getSize(first[0]); | ||||
| @@ -137,8 +135,8 @@ define( | ||||
|                     splitter.css(anchor.opposite, "auto"); | ||||
|  | ||||
|                     last.css(anchor.edge, firstSize + splitterSize + 'px'); | ||||
|                     last.css(anchor.opposite, '0px'); | ||||
|                     position = firstSize; | ||||
|                     last.css(anchor.opposite, "0px"); | ||||
|                     position = firstSize + splitterSize; | ||||
|                 } | ||||
|  | ||||
|                 // Update positioning of contained elements | ||||
| @@ -175,19 +173,17 @@ define( | ||||
|                             positionParsed.assign($scope, position); | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     return position; | ||||
|                 } | ||||
|  | ||||
|                 function setUserWidthPreference(value) { | ||||
|                     if (alias) { | ||||
|                         userWidthPreference = value; | ||||
|                     } | ||||
|                     userWidthPreference = value - splitterSize; | ||||
|                 } | ||||
|  | ||||
|                 function persistToLocalStorage(value) { | ||||
|                     if (alias) { | ||||
|                         $window.localStorage.setItem(alias, value); | ||||
|                         userWidthPreference = value - splitterSize; | ||||
|                         $window.localStorage.setItem(alias, userWidthPreference); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
| @@ -229,13 +225,13 @@ define( | ||||
|                     anchor: function () { | ||||
|                         return anchor; | ||||
|                     }, | ||||
|                     position: function (newPosition) { | ||||
|                         if (arguments.length === 0) { | ||||
|                     position: function (value) { | ||||
|                         if (arguments.length > 0) { | ||||
|                             setUserWidthPreference(value); | ||||
|                             return getSetPosition(value); | ||||
|                         } else { | ||||
|                             return getSetPosition(); | ||||
|                         } | ||||
|  | ||||
|                         setUserWidthPreference(newPosition); | ||||
|                         return getSetPosition(newPosition); | ||||
|                     }, | ||||
|                     startResizing: function () { | ||||
|                         toggleClass('resizing'); | ||||
|   | ||||
| @@ -57,10 +57,7 @@ define( | ||||
|  | ||||
|                         // Update the position of this splitter | ||||
|                         newPosition =  initialPosition + pixelDelta; | ||||
|  | ||||
|                         if (initialPosition !== newPosition) { | ||||
|                             mctSplitPane.position(newPosition); | ||||
|                         } | ||||
|                         mctSplitPane.position(newPosition); | ||||
|                     }, | ||||
|                     // Grab the event when the user is done moving | ||||
|                     // the splitter and pass it on | ||||
|   | ||||
| @@ -39,8 +39,10 @@ define( | ||||
|             beforeEach(function () { | ||||
|                 mockScope = jasmine.createSpyObj( | ||||
|                     "$scope", | ||||
|                     ["$watch", "$on"] | ||||
|                     ["$watch"] | ||||
|                 ); | ||||
|                 mockScope.ngModel = {}; | ||||
|                 mockScope.ngModel.selectedObject = 'mock selected object'; | ||||
|  | ||||
|                 mockObjectService = jasmine.createSpyObj( | ||||
|                     "objectService", | ||||
| @@ -67,27 +69,22 @@ define( | ||||
|                     "location capability", | ||||
|                     ["isLink"] | ||||
|                 ); | ||||
|  | ||||
|                 mockDomainObject.getCapability.andCallFake(function (param) { | ||||
|                     if (param === 'location') { | ||||
|                         return mockLocationCapability; | ||||
|                     } else if (param === 'context') { | ||||
|                         return mockContextCapability; | ||||
|                     } else if (param === 'mutation') { | ||||
|                         return { | ||||
|                             listen: function () { | ||||
|                                 return true; | ||||
|                             } | ||||
|                         }; | ||||
|                     } | ||||
|                 }); | ||||
|  | ||||
|                 mockScope.domainObject = mockDomainObject; | ||||
|                 controller = new ObjectInspectorController(mockScope, mockObjectService); | ||||
|  | ||||
|                 // Change the selected object to trigger the watch call | ||||
|                 mockScope.ngModel.selectedObject = mockDomainObject; | ||||
|             }); | ||||
|  | ||||
|             it("watches for changes to the selected object", function () { | ||||
|                 expect(mockScope.$watch).toHaveBeenCalledWith('domainObject', jasmine.any(Function)); | ||||
|                 expect(mockScope.$watch).toHaveBeenCalledWith('ngModel.selectedObject', jasmine.any(Function)); | ||||
|             }); | ||||
|  | ||||
|             it("looks for contextual parent objects", function () { | ||||
|   | ||||
| @@ -140,7 +140,7 @@ define( | ||||
|  | ||||
|                 it("exposes its splitter's initial position", function () { | ||||
|                     expect(controller.position()).toEqual( | ||||
|                         mockFirstPane[0].offsetWidth | ||||
|                         mockFirstPane[0].offsetWidth + mockSplitter[0].offsetWidth | ||||
|                     ); | ||||
|                 }); | ||||
|  | ||||
| @@ -168,7 +168,7 @@ define( | ||||
|                     controller.position(testValue); | ||||
|                     expect(mockFirstPane.css).toHaveBeenCalledWith( | ||||
|                         'width', | ||||
|                         (testValue) + 'px' | ||||
|                         (testValue - mockSplitter[0].offsetWidth) + 'px' | ||||
|                     ); | ||||
|                 }); | ||||
|  | ||||
| @@ -200,11 +200,11 @@ define( | ||||
|                     mockFirstPane[0].offsetWidth += 100; | ||||
|                     // Should not reflect the change yet | ||||
|                     expect(controller.position()).not.toEqual( | ||||
|                         mockFirstPane[0].offsetWidth | ||||
|                         mockFirstPane[0].offsetWidth + mockSplitter[0].offsetWidth | ||||
|                     ); | ||||
|                     mockInterval.mostRecentCall.args[0](); | ||||
|                     expect(controller.position()).toEqual( | ||||
|                         mockFirstPane[0].offsetWidth | ||||
|                         mockFirstPane[0].offsetWidth + mockSplitter[0].offsetWidth | ||||
|                     ); | ||||
|                 }); | ||||
|  | ||||
| @@ -216,7 +216,7 @@ define( | ||||
|  | ||||
|                 it("saves user preference to localStorage when user is done resizing", function () { | ||||
|                     controller.endResizing(100); | ||||
|                     expect(Number(mockWindow.localStorage.getItem('mctSplitPane-rightSide'))).toEqual(100); | ||||
|                     expect(Number(mockWindow.localStorage.getItem('mctSplitPane-rightSide'))).toEqual(100 - mockSplitter[0].offsetWidth); | ||||
|                 }); | ||||
|  | ||||
|             }); | ||||
|   | ||||
| @@ -65,10 +65,6 @@ define( | ||||
|             options = Object.create(OPTIONS); | ||||
|             options.marginX = -bubbleSpaceLR; | ||||
|  | ||||
|             // prevent bubble from appearing right under pointer, | ||||
|             // which causes hover callback to be called multiple times | ||||
|             options.offsetX = 1; | ||||
|  | ||||
|             // On a phone, bubble takes up more screen real estate, | ||||
|             // so position it differently (toward the bottom) | ||||
|             if (this.agentService.isPhone()) { | ||||
|   | ||||
| @@ -38,8 +38,7 @@ define([ | ||||
|                     "implementation": InspectorController, | ||||
|                     "depends": [ | ||||
|                         "$scope", | ||||
|                         "openmct", | ||||
|                         "$document" | ||||
|                         "policyService" | ||||
|                     ] | ||||
|                 } | ||||
|             ], | ||||
|   | ||||
| @@ -21,73 +21,44 @@ | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| define( | ||||
|     [], | ||||
|     function () { | ||||
|     ['../../browse/src/InspectorRegion'], | ||||
|     function (InspectorRegion) { | ||||
|  | ||||
|         /** | ||||
|          * The InspectorController listens for the selection changes and adds the selection | ||||
|          * object to the scope. | ||||
|          * The InspectorController adds region data for a domain object's type | ||||
|          * to the scope. | ||||
|          * | ||||
|          * @constructor | ||||
|          */ | ||||
|         function InspectorController($scope, openmct, $document) { | ||||
|             var self = this; | ||||
|             self.$scope = $scope; | ||||
|         function InspectorController($scope, policyService) { | ||||
|             var domainObject = $scope.domainObject, | ||||
|                 typeCapability = domainObject.getCapability('type'), | ||||
|                 statusListener; | ||||
|  | ||||
|             /** | ||||
|              * Callback handler for the selection change event. | ||||
|              * Adds the selection object to the scope. If the selected item has an inspector view, | ||||
|              * it puts the key in the scope. If provider view exists, it shows the view. | ||||
|              * Filters region parts to only those allowed by region policies | ||||
|              * @param regions | ||||
|              * @returns {{}} | ||||
|              */ | ||||
|             function setSelection(selection) { | ||||
|                 if (selection[0]) { | ||||
|                     var view = openmct.inspectorViews.get(selection); | ||||
|                     var container = $document[0].querySelectorAll('.inspector-provider-view')[0]; | ||||
|                     container.innerHTML = ""; | ||||
|  | ||||
|                     if (view) { | ||||
|                         self.providerView = true; | ||||
|                         view.show(container); | ||||
|                     } else { | ||||
|                         self.providerView = false; | ||||
|                         var selectedItem = selection[0].context.oldItem; | ||||
|  | ||||
|                         if (selectedItem) { | ||||
|                             $scope.inspectorKey = selectedItem.getCapability("type").typeDef.inspector; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 self.$scope.selection = selection; | ||||
|             function filterRegions(inspector) { | ||||
|                 //Dupe so we're not modifying the type definition. | ||||
|                 return inspector.regions && inspector.regions.filter(function (region) { | ||||
|                     return policyService.allow('region', region, domainObject); | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             openmct.selection.on("change", setSelection); | ||||
|  | ||||
|             setSelection(openmct.selection.get()); | ||||
|             function setRegions() { | ||||
|                 $scope.regions = filterRegions(typeCapability.getDefinition().inspector || new InspectorRegion()); | ||||
|             } | ||||
|  | ||||
|             statusListener = domainObject.getCapability("status").listen(setRegions); | ||||
|             $scope.$on("$destroy", function () { | ||||
|                 openmct.selection.off("change", setSelection); | ||||
|                 statusListener(); | ||||
|             }); | ||||
|  | ||||
|             setRegions(); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Gets the selected item. | ||||
|          * | ||||
|          * @returns a domain object | ||||
|          */ | ||||
|         InspectorController.prototype.selectedItem = function () { | ||||
|             return this.$scope.selection[0].context.oldItem; | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Checks if a provider view exists. | ||||
|          * | ||||
|          * @returns 'true' if provider view exists, 'false' otherwise | ||||
|          */ | ||||
|         InspectorController.prototype.hasProviderView = function () { | ||||
|             return this.providerView; | ||||
|         }; | ||||
|  | ||||
|         return InspectorController; | ||||
|     } | ||||
| ); | ||||
|   | ||||
| @@ -27,93 +27,82 @@ define( | ||||
|         describe("The inspector controller ", function () { | ||||
|             var mockScope, | ||||
|                 mockDomainObject, | ||||
|                 mockOpenMCT, | ||||
|                 mockSelection, | ||||
|                 mockInspectorViews, | ||||
|                 mockTypeDef, | ||||
|                 controller, | ||||
|                 container, | ||||
|                 $document = [], | ||||
|                 selectable = []; | ||||
|                 mockTypeCapability, | ||||
|                 mockTypeDefinition, | ||||
|                 mockPolicyService, | ||||
|                 mockStatusCapability, | ||||
|                 capabilities = {}, | ||||
|                 controller; | ||||
|  | ||||
|             beforeEach(function () { | ||||
|                 mockTypeDef = { | ||||
|                     typeDef: { | ||||
|                         inspector: "some-key" | ||||
|                     } | ||||
|                 mockTypeDefinition = { | ||||
|                     inspector: | ||||
|                         { | ||||
|                             'regions': [ | ||||
|                                 {'name': 'Part One'}, | ||||
|                                 {'name': 'Part Two'} | ||||
|                             ] | ||||
|                         } | ||||
|                 }; | ||||
|  | ||||
|                 mockTypeCapability = jasmine.createSpyObj('typeCapability', [ | ||||
|                     'getDefinition' | ||||
|                 ]); | ||||
|                 mockTypeCapability.getDefinition.andReturn(mockTypeDefinition); | ||||
|                 capabilities.type = mockTypeCapability; | ||||
|  | ||||
|                 mockStatusCapability = jasmine.createSpyObj('statusCapability', [ | ||||
|                     'listen' | ||||
|                 ]); | ||||
|                 capabilities.status = mockStatusCapability; | ||||
|  | ||||
|                 mockDomainObject = jasmine.createSpyObj('domainObject', [ | ||||
|                     'getCapability' | ||||
|                 ]); | ||||
|                 mockDomainObject.getCapability.andReturn(mockTypeDef); | ||||
|                 mockDomainObject.getCapability.andCallFake(function (name) { | ||||
|                     return capabilities[name]; | ||||
|                 }); | ||||
|  | ||||
|                 mockPolicyService = jasmine.createSpyObj('policyService', [ | ||||
|                    'allow' | ||||
|                 ]); | ||||
|  | ||||
|                 mockScope = jasmine.createSpyObj('$scope', | ||||
|                     ['$on', 'selection'] | ||||
|                     ['$on'] | ||||
|                 ); | ||||
|  | ||||
|                 selectable[0] = { | ||||
|                     context: { | ||||
|                         oldItem: mockDomainObject | ||||
|                     } | ||||
|                 }; | ||||
|  | ||||
|                 mockSelection = jasmine.createSpyObj("selection", [ | ||||
|                     'on', | ||||
|                     'off', | ||||
|                     'get' | ||||
|                 ]); | ||||
|                 mockSelection.get.andReturn(selectable); | ||||
|  | ||||
|                 mockInspectorViews = jasmine.createSpyObj('inspectorViews', ['get']); | ||||
|                 mockOpenMCT = { | ||||
|                     selection: mockSelection, | ||||
|                     inspectorViews: mockInspectorViews | ||||
|                 }; | ||||
|  | ||||
|                 container = jasmine.createSpy('container', ['innerHTML']); | ||||
|                 $document[0] = jasmine.createSpyObj("$document", ['querySelectorAll']); | ||||
|                 $document[0].querySelectorAll.andReturn([container]); | ||||
|  | ||||
|                 controller = new InspectorController(mockScope, mockOpenMCT, $document); | ||||
|                 mockScope.domainObject = mockDomainObject; | ||||
|             }); | ||||
|  | ||||
|             it("listens for selection change event", function () { | ||||
|                 expect(mockOpenMCT.selection.on).toHaveBeenCalledWith( | ||||
|                     'change', | ||||
|                     jasmine.any(Function) | ||||
|                 ); | ||||
|  | ||||
|                 expect(controller.selectedItem()).toEqual(mockDomainObject); | ||||
|  | ||||
|                 var mockItem = jasmine.createSpyObj('domainObject', [ | ||||
|                     'getCapability' | ||||
|                 ]); | ||||
|                 mockItem.getCapability.andReturn(mockTypeDef); | ||||
|                 selectable[0].context.oldItem = mockItem; | ||||
|  | ||||
|                 mockOpenMCT.selection.on.mostRecentCall.args[1](selectable); | ||||
|  | ||||
|                 expect(controller.selectedItem()).toEqual(mockItem); | ||||
|             it("filters out regions disallowed by region policy", function () { | ||||
|                 mockPolicyService.allow.andReturn(false); | ||||
|                 controller = new InspectorController(mockScope, mockPolicyService); | ||||
|                 expect(mockScope.regions.length).toBe(0); | ||||
|             }); | ||||
|  | ||||
|             it("cleans up on scope destroy", function () { | ||||
|                 expect(mockScope.$on).toHaveBeenCalledWith( | ||||
|                     '$destroy', | ||||
|                     jasmine.any(Function) | ||||
|                 ); | ||||
|  | ||||
|                 mockScope.$on.calls[0].args[1](); | ||||
|  | ||||
|                 expect(mockOpenMCT.selection.off).toHaveBeenCalledWith( | ||||
|                     'change', | ||||
|                     jasmine.any(Function) | ||||
|                 ); | ||||
|             it("does not filter out regions allowed by region policy", function () { | ||||
|                 mockPolicyService.allow.andReturn(true); | ||||
|                 controller = new InspectorController(mockScope, mockPolicyService); | ||||
|                 expect(mockScope.regions.length).toBe(2); | ||||
|             }); | ||||
|  | ||||
|             it("adds selection object to scope", function () { | ||||
|                 expect(mockScope.selection).toEqual(selectable); | ||||
|                 expect(controller.selectedItem()).toEqual(mockDomainObject); | ||||
|             it("Responds to status changes", function () { | ||||
|                 mockPolicyService.allow.andReturn(true); | ||||
|                 controller = new InspectorController(mockScope, mockPolicyService); | ||||
|                 expect(mockScope.regions.length).toBe(2); | ||||
|                 expect(mockStatusCapability.listen).toHaveBeenCalled(); | ||||
|                 mockPolicyService.allow.andReturn(false); | ||||
|                 mockStatusCapability.listen.mostRecentCall.args[0](); | ||||
|                 expect(mockScope.regions.length).toBe(0); | ||||
|             }); | ||||
|  | ||||
|             it("Unregisters status listener", function () { | ||||
|                 var mockListener = jasmine.createSpy('listener'); | ||||
|                 mockStatusCapability.listen.andReturn(mockListener); | ||||
|                 controller = new InspectorController(mockScope, mockPolicyService); | ||||
|                 expect(mockScope.$on).toHaveBeenCalledWith("$destroy", jasmine.any(Function)); | ||||
|                 mockScope.$on.mostRecentCall.args[1](); | ||||
|                 expect(mockListener).toHaveBeenCalled(); | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
|   | ||||
| @@ -53,15 +53,9 @@ $timeControllerToiLineColor: #00c2ff; | ||||
| $timeControllerToiLineColorHov: #fff; | ||||
| $colorTransLucBg: #666; // Used as a visual blocking element over variable backgrounds, like imagery | ||||
|  | ||||
| // Foundation Colors | ||||
| // General Colors | ||||
| $colorAlt1: #ffc700; | ||||
| $colorAlert: #ff3c00; | ||||
| $colorWarningHi: #cc0000; | ||||
| $colorWarningLo: #ff9900; | ||||
| $colorDiagnostic: #a4b442; | ||||
| $colorCommand: #3693bd; | ||||
| $colorInfo: #2294a2; | ||||
| $colorOk: #33cc33; | ||||
| $colorIconLink: #49dedb; | ||||
| $colorPausedBg: #c56f01; | ||||
| $colorPausedFg: #fff; | ||||
| @@ -90,8 +84,8 @@ $colorCreateMenuText: $colorMenuFg; | ||||
| // Form colors | ||||
| $colorCheck: $colorKey; | ||||
| $colorFormRequired: $colorAlt1; | ||||
| $colorFormValid: $colorOk; | ||||
| $colorFormError: $colorWarningHi; | ||||
| $colorFormValid: #33cc33; | ||||
| $colorFormError: #990000; | ||||
| $colorFormInvalid: #ff3300; | ||||
| $colorFormFieldErrorBg: $colorFormError; | ||||
| $colorFormFieldErrorFg: rgba(#fff, 0.6); | ||||
| @@ -115,8 +109,8 @@ $colorInspectorSectionHeaderFg: pullForward($colorInspectorBg, 40%); | ||||
| // Status colors, mainly used for messaging and item ancillary symbols | ||||
| $colorStatusFg: #ccc; | ||||
| $colorStatusDefault: #ccc; | ||||
| $colorStatusInfo: $colorInfo; | ||||
| $colorStatusAlert: $colorAlert; | ||||
| $colorStatusInfo: #62ba72; | ||||
| $colorStatusAlert: #ffa66d; | ||||
| $colorStatusError: #d4585c; | ||||
| $colorStatusAvailable: $colorKey; | ||||
| $colorStatusBtnBg: $colorBtnBg; | ||||
| @@ -131,14 +125,14 @@ $animPausedPulseDur: 500ms; | ||||
| $colorSelectBg: $colorBtnBg; | ||||
| $colorSelectFg: $colorBtnFg; | ||||
|  | ||||
| // Limits, status and staleness colors | ||||
| // Limits and staleness colors | ||||
| $colorTelemFresh: pullForward($colorBodyFg, 20%); | ||||
| $colorTelemStale: pushBack($colorBodyFg, 20%); | ||||
| $styleTelemStale: italic; | ||||
| $colorLimitYellowBg: rgba($colorWarningLo, 0.3); | ||||
| $colorLimitYellowIc: $colorWarningLo; | ||||
| $colorLimitRedBg: rgba($colorWarningHi, 0.3); | ||||
| $colorLimitRedIc: $colorWarningHi; | ||||
| $colorLimitYellowBg: rgba(#ffaa00, 0.3); | ||||
| $colorLimitYellowIc: #ffaa00; | ||||
| $colorLimitRedBg: rgba(red, 0.3); | ||||
| $colorLimitRedIc: red; | ||||
|  | ||||
| // Bubble colors | ||||
| $colorInfoBubbleBg: #ddd; | ||||
| @@ -201,15 +195,13 @@ $shdwItemTreeIcon: 0.6; | ||||
| $colorThumbHoverBg: $colorItemTreeHoverBg; | ||||
|  | ||||
| // Scrollbar | ||||
| $scrollbarTrackSize: 7px; | ||||
| $scrollbarTrackShdw: rgba(#000, 0.5) 0 1px 5px; | ||||
| $scrollbarTrackColorBg: transparent; //rgba(#000, 0.4); | ||||
| $scrollbarTrackSize: 10px; | ||||
| $scrollbarTrackShdw: rgba(#000, 0.7) 0 1px 5px; | ||||
| $scrollbarTrackColorBg: rgba(#000, 0.4); | ||||
| $scrollbarThumbColor: pullForward($colorBodyBg, 10%); | ||||
| $scrollbarThumbColorHov: pullForward($scrollbarThumbColor, 2%); | ||||
| $scrollbarThumbColorOverlay: pullForward($colorOvrBg, 10%); | ||||
| $scrollbarThumbColorOverlayHov: pullForward($scrollbarThumbColorOverlay, 2%); | ||||
| $scrollbarThumbColorMenu: pullForward($colorMenuBg, 20%); | ||||
| $scrollbarThumbColorMenuHov: pullForward($scrollbarThumbColorMenu, 2%); | ||||
|  | ||||
| // Splitter | ||||
| // All splitterD* values MUST both be either odd or even numbers | ||||
|   | ||||
| @@ -13,10 +13,3 @@ | ||||
|     // For dark interfaces, darker things move back - opposite for light interfaces | ||||
|     @return darken($c, $p); | ||||
| } | ||||
|  | ||||
| @function bgFg($c) { | ||||
|     // Given a single color, return valid background and foreground versions of that color | ||||
|     $bg: darken($c, 20%); | ||||
|     $fg: lighten($c, 20%); | ||||
|     @return $bg, $fg; | ||||
| } | ||||
|   | ||||
| @@ -53,15 +53,9 @@ $timeControllerToiLineColor: $colorBodyFg; | ||||
| $timeControllerToiLineColorHov: #0052b5; | ||||
| $colorTransLucBg: #666; // Used as a visual blocking element over variable backgrounds, like imagery | ||||
|  | ||||
| // Foundation Colors | ||||
| // General Colors | ||||
| $colorAlt1: #776ba2; | ||||
| $colorAlert: #ff3c00; | ||||
| $colorWarningHi: #990000; | ||||
| $colorWarningLo: #ff9900; | ||||
| $colorDiagnostic: #a4b442; | ||||
| $colorCommand: #3693bd; | ||||
| $colorInfo: #2294a2; | ||||
| $colorOk: #33cc33; | ||||
| $colorIconLink: #49dedb; | ||||
| $colorPausedBg: #ff9900; | ||||
| $colorPausedFg: #fff; | ||||
| @@ -90,8 +84,8 @@ $colorCreateMenuText: $colorBodyFg; | ||||
| // Form colors | ||||
| $colorCheck: $colorKey; | ||||
| $colorFormRequired: $colorKey; | ||||
| $colorFormValid: $colorOk; | ||||
| $colorFormError: $colorWarningHi; | ||||
| $colorFormValid: #33cc33; | ||||
| $colorFormError: #990000; | ||||
| $colorFormInvalid: #ff2200; | ||||
| $colorFormFieldErrorBg: $colorFormError; | ||||
| $colorFormFieldErrorFg: rgba(#fff, 0.6); | ||||
| @@ -113,7 +107,7 @@ $colorInspectorSectionHeaderBg: pullForward($colorInspectorBg, 5%); | ||||
| $colorInspectorSectionHeaderFg: pullForward($colorInspectorBg, 40%); | ||||
|  | ||||
| // Status colors, mainly used for messaging and item ancillary symbols | ||||
| $colorStatusFg: #999; | ||||
| $colorStatusFg: #fff; | ||||
| $colorStatusDefault: #ccc; | ||||
| $colorStatusInfo: #60ba7b; | ||||
| $colorStatusAlert: #ffb66c; | ||||
| @@ -201,15 +195,13 @@ $shdwItemTreeIcon: none; | ||||
| $colorThumbHoverBg: $colorItemTreeHoverBg; | ||||
|  | ||||
| // Scrollbar | ||||
| $scrollbarTrackSize: 7px; | ||||
| $scrollbarTrackSize: 10px; | ||||
| $scrollbarTrackShdw: rgba(#000, 0.2) 0 1px 2px; | ||||
| $scrollbarTrackColorBg: rgba(#000, 0.2); | ||||
| $scrollbarThumbColor: darken($colorBodyBg, 50%); | ||||
| $scrollbarThumbColorHov: $colorKey; | ||||
| $scrollbarThumbColorOverlay: darken($colorOvrBg, 50%); | ||||
| $scrollbarThumbColorOverlayHov: $scrollbarThumbColorHov; | ||||
| $scrollbarThumbColorMenu: pullForward($colorMenuBg, 10%); | ||||
| $scrollbarThumbColorMenuHov: pullForward($scrollbarThumbColorMenu, 2%); | ||||
|  | ||||
| // Splitter | ||||
| // All splitterD* values MUST both be either odd or even numbers | ||||
|   | ||||
| @@ -12,11 +12,3 @@ | ||||
|     // For dark interfaces, darker things move back - opposite for light interfaces | ||||
|     @return lighten($c, $p); | ||||
| } | ||||
|  | ||||
| @function bgFg($c) { | ||||
|     // Given a single color, return valid background and foreground versions of that color | ||||
|     $bg: darken($c, 20%); | ||||
|     $fg: lighten($c, 20%); | ||||
|     @return $bg, $fg; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -94,6 +94,31 @@ define([ | ||||
|             } | ||||
|         }, | ||||
|         "extensions": { | ||||
|             "versions": [ | ||||
|                 { | ||||
|                     "name": "Version", | ||||
|                     "value": "@@version", | ||||
|                     "priority": 999 | ||||
|                 }, | ||||
|                 { | ||||
|                     "name": "Built", | ||||
|                     "value": "@@timestamp", | ||||
|                     "description": "The date on which this version of the client was built.", | ||||
|                     "priority": 990 | ||||
|                 }, | ||||
|                 { | ||||
|                     "name": "Revision", | ||||
|                     "value": "@@revision", | ||||
|                     "description": "A unique revision identifier for the client sources.", | ||||
|                     "priority": 995 | ||||
|                 }, | ||||
|                 { | ||||
|                     "name": "Branch", | ||||
|                     "value": "@@branch", | ||||
|                     "description": "The name of the branch that was used during the build.", | ||||
|                     "priority": 994 | ||||
|                 } | ||||
|             ], | ||||
|             "components": [ | ||||
|                 { | ||||
|                     "provides": "objectService", | ||||
|   | ||||
| @@ -65,20 +65,6 @@ define(['csv'], function (CSV) { | ||||
|         this.saveAs(blob, filename); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Export an object as a JSON file. Triggers a download using the function | ||||
|      * provided when the ExportService was instantiated. | ||||
|      * | ||||
|      * @param {Object} obj an object to be exported as JSON | ||||
|      * @param {ExportOptions} [options] additional parameters for the file | ||||
|      *        export | ||||
|      */ | ||||
|     ExportService.prototype.exportJSON = function (obj, options) { | ||||
|         var filename = (options && options.filename) || "test-export.json"; | ||||
|         var jsonText = JSON.stringify(obj); | ||||
|         var blob = new Blob([jsonText], {type: "application/json"}); | ||||
|         this.saveAs(blob, filename); | ||||
|     }; | ||||
|     /** | ||||
|      * Additional parameters for file export. | ||||
|      * @typedef ExportOptions | ||||
|   | ||||
							
								
								
									
										54
									
								
								platform/features/autoflow/plugin.js
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										54
									
								
								platform/features/autoflow/plugin.js
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| define([ | ||||
|     'text!./res/templates/autoflow-tabular.html', | ||||
|     './src/AutoflowTabularController', | ||||
|     './src/MCTAutoflowTable' | ||||
| ], function ( | ||||
|     autoflowTabularTemplate, | ||||
|     AutoflowTabularController, | ||||
|     MCTAutoflowTable | ||||
| ) { | ||||
|     return function (options) { | ||||
|         return function (openmct) { | ||||
|             openmct.legacyRegistry.register("platform/features/autoflow", { | ||||
|                 "name": "WARP Telemetry Adapter", | ||||
|                 "description": "Retrieves telemetry from the WARP Server and provides related types and views.", | ||||
|                 "resources": "res", | ||||
|                 "extensions": { | ||||
|                     "views": [ | ||||
|                         { | ||||
|                             "key": "autoflow", | ||||
|                             "name": "Autoflow Tabular", | ||||
|                             "cssClass": "icon-packet", | ||||
|                             "description": "A tabular view of packet contents.", | ||||
|                             "template": autoflowTabularTemplate, | ||||
|                             "type": options && options.type, | ||||
|                             "needs": [ | ||||
|                                 "telemetry" | ||||
|                             ], | ||||
|                             "delegation": true | ||||
|                         } | ||||
|                     ], | ||||
|                     "controllers": [ | ||||
|                         { | ||||
|                             "key": "AutoflowTabularController", | ||||
|                             "implementation": AutoflowTabularController, | ||||
|                             "depends": [ | ||||
|                                 "$scope", | ||||
|                                 "$timeout", | ||||
|                                 "telemetrySubscriber" | ||||
|                             ] | ||||
|                         } | ||||
|                     ], | ||||
|                     "directives": [ | ||||
|                         { | ||||
|                             "key": "mctAutoflowTable", | ||||
|                             "implementation": MCTAutoflowTable | ||||
|                         } | ||||
|                     ] | ||||
|                 } | ||||
|             }); | ||||
|             openmct.legacyRegistry.enable("platform/features/autoflow"); | ||||
|         }; | ||||
|     }; | ||||
| }); | ||||
|  | ||||
							
								
								
									
										26
									
								
								platform/features/autoflow/res/templates/autoflow-tabular.html
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										26
									
								
								platform/features/autoflow/res/templates/autoflow-tabular.html
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| <div class="items-holder abs contents autoflow obj-value-format" | ||||
|      ng-controller="AutoflowTabularController as autoflow"> | ||||
|     <div class="abs l-flex-row holder t-autoflow-header l-autoflow-header"> | ||||
|         <mct-include key="'input-filter'" | ||||
|                      ng-model="autoflow.filter" | ||||
|                      class="flex-elem"> | ||||
|         </mct-include> | ||||
|         <div class="flex-elem grows t-last-update" title="Last Update">{{autoflow.updated()}}</div> | ||||
|         <a title="Change column width" | ||||
|             class="s-button flex-elem icon-arrows-right-left change-column-width" | ||||
|             ng-click="autoflow.increaseColumnWidth()"></a> | ||||
|     </div> | ||||
|     <div class="abs t-autoflow-items l-autoflow-items" | ||||
|          mct-resize="autoflow.setBounds(bounds)" | ||||
|          mct-resize-interval="50"> | ||||
|         <mct-autoflow-table values="autoflow.rangeValues()" | ||||
|                             objects="autoflow.getTelemetryObjects()" | ||||
|                             rows="autoflow.getRows()" | ||||
|                             classes="autoflow.classes()" | ||||
|                             updated="autoflow.updated()" | ||||
|                             column-width="autoflow.columnWidth()" | ||||
|                             counter="autoflow.counter()" | ||||
|                             > | ||||
|         </mct-autoflow-table> | ||||
|     </div> | ||||
| </div> | ||||
							
								
								
									
										169
									
								
								platform/features/autoflow/src/AutoflowTableLinker.js
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										169
									
								
								platform/features/autoflow/src/AutoflowTableLinker.js
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,169 @@ | ||||
| /*global angular*/ | ||||
| define( | ||||
|     [], | ||||
|     function () { | ||||
|  | ||||
|         /** | ||||
|          * The link step for the `mct-autoflow-table` directive; | ||||
|          * watches scope and updates the DOM appropriately. | ||||
|          * See documentation in `MCTAutoflowTable.js` for the rationale | ||||
|          * for including this directive, as well as for an explanation | ||||
|          * of which values are placed in scope. | ||||
|          * | ||||
|          * @constructor | ||||
|          * @param {Scope} scope the scope for this usage of the directive | ||||
|          * @param element the jqLite-wrapped element which used this directive | ||||
|          */ | ||||
|         function AutoflowTableLinker(scope, element) { | ||||
|             var objects, // Domain objects at last structure refresh | ||||
|                 rows, // Number of rows from last structure refresh | ||||
|                 priorClasses = {}, | ||||
|                 valueSpans = {}; // Span elements to put data values in | ||||
|  | ||||
|             // Create a new name-value pair in the specified column | ||||
|             function createListItem(domainObject, ul) { | ||||
|                 // Create a new li, and spans to go in it. | ||||
|                 var li = angular.element('<li>'), | ||||
|                     titleSpan = angular.element('<span>'), | ||||
|                     valueSpan = angular.element('<span>'); | ||||
|  | ||||
|                 // Place spans in the li, and li into the column. | ||||
|                 // valueSpan must precede titleSpan in the DOM due to new CSS float approach | ||||
|                 li.append(valueSpan).append(titleSpan); | ||||
|                 ul.append(li); | ||||
|  | ||||
|                 // Style appropriately | ||||
|                 li.addClass('l-autoflow-row'); | ||||
|                 titleSpan.addClass('l-autoflow-item l'); | ||||
|                 valueSpan.addClass('l-autoflow-item r l-obj-val-format'); | ||||
|  | ||||
|                 // Set text/tooltip for the name-value row | ||||
|                 titleSpan.text(domainObject.getModel().name); | ||||
|                 titleSpan.attr("title", domainObject.getModel().name); | ||||
|  | ||||
|                 // Keep a reference to the span which will hold the | ||||
|                 // data value, to populate in the next refreshValues call | ||||
|                 valueSpans[domainObject.getId()] = valueSpan; | ||||
|  | ||||
|                 return li; | ||||
|             } | ||||
|  | ||||
|             // Create a new column of name-value pairs in this table. | ||||
|             function createColumn(el) { | ||||
|                 // Create a ul | ||||
|                 var ul = angular.element('<ul>'); | ||||
|  | ||||
|                 // Add it into the mct-autoflow-table | ||||
|                 el.append(ul); | ||||
|  | ||||
|                 // Style appropriately | ||||
|                 ul.addClass('l-autoflow-col'); | ||||
|  | ||||
|                 // Get the current col width and apply at time of column creation | ||||
|                 // Important to do this here, as new columns could be created after | ||||
|                 // the user has changed the width. | ||||
|                 ul.css('width', scope.columnWidth + 'px'); | ||||
|  | ||||
|                 // Return it, so some li elements can be added | ||||
|                 return ul; | ||||
|             } | ||||
|  | ||||
|             // Change the width of the columns when user clicks the resize button. | ||||
|             function resizeColumn() { | ||||
|                 element.find('ul').css('width', scope.columnWidth + 'px'); | ||||
|             } | ||||
|  | ||||
|             // Rebuild the DOM associated with this table. | ||||
|             function rebuild(domainObjects, rowCount) { | ||||
|                 var activeColumn; | ||||
|  | ||||
|                 // Empty out our cached span elements | ||||
|                 valueSpans = {}; | ||||
|  | ||||
|                 // Start with an empty DOM beneath this directive | ||||
|                 element.html(""); | ||||
|  | ||||
|                 // Add DOM elements for each domain object being displayed | ||||
|                 // in this table. | ||||
|                 domainObjects.forEach(function (object, index) { | ||||
|                     // Start a new column if we'd run out of room | ||||
|                     if (index % rowCount === 0) { | ||||
|                         activeColumn = createColumn(element); | ||||
|                     } | ||||
|                     // Add the DOM elements for that object to whichever | ||||
|                     // column (a `ul` element) is current. | ||||
|                     createListItem(object, activeColumn); | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             // Update spans with values, as made available via the | ||||
|             // `values` attribute of this directive. | ||||
|             function refreshValues() { | ||||
|                 // Get the available values | ||||
|                 var values = scope.values || {}, | ||||
|                     classes = scope.classes || {}; | ||||
|  | ||||
|                 // Populate all spans with those values (or clear | ||||
|                 // those spans if no value is available) | ||||
|                 (objects || []).forEach(function (object) { | ||||
|                     var id = object.getId(), | ||||
|                         span = valueSpans[id], | ||||
|                         value; | ||||
|  | ||||
|                     if (span) { | ||||
|                         // Look up the value... | ||||
|                         value = values[id]; | ||||
|                         // ...and convert to empty string if it's undefined | ||||
|                         value = value === undefined ? "" : value; | ||||
|                         span.attr("data-value", value); | ||||
|  | ||||
|                         // Update the span | ||||
|                         span.text(value); | ||||
|                         span.attr("title", value); | ||||
|                         span.removeClass(priorClasses[id]); | ||||
|                         span.addClass(classes[id]); | ||||
|                         priorClasses[id] = classes[id]; | ||||
|                     } | ||||
|                     // Also need stale/alert/ok class | ||||
|                     // on span | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             // Refresh the DOM for this table, if necessary | ||||
|             function refreshStructure() { | ||||
|                 // Only rebuild if number of rows or set of objects | ||||
|                 // has changed; otherwise, our structure is still valid. | ||||
|                 if (scope.objects !== objects || | ||||
|                         scope.rows !== rows) { | ||||
|  | ||||
|                     // Track those values to support future refresh checks | ||||
|                     objects = scope.objects; | ||||
|                     rows = scope.rows; | ||||
|  | ||||
|                     // Rebuild the DOM | ||||
|                     rebuild(objects || [], rows || 1); | ||||
|  | ||||
|                     // Refresh all data values shown | ||||
|                     refreshValues(); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Changing the domain objects in use or the number | ||||
|             // of rows should trigger a structure change (DOM rebuild) | ||||
|             scope.$watch("objects", refreshStructure); | ||||
|             scope.$watch("rows", refreshStructure); | ||||
|  | ||||
|             // When the current column width has been changed, resize the column | ||||
|             scope.$watch('columnWidth', resizeColumn); | ||||
|  | ||||
|             // When the last-updated time ticks, | ||||
|             scope.$watch("updated", refreshValues); | ||||
|  | ||||
|             // Update displayed values when the counter changes. | ||||
|             scope.$watch("counter", refreshValues); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return AutoflowTableLinker; | ||||
|     } | ||||
| ); | ||||
							
								
								
									
										324
									
								
								platform/features/autoflow/src/AutoflowTabularController.js
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										324
									
								
								platform/features/autoflow/src/AutoflowTabularController.js
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,324 @@ | ||||
|  | ||||
| define( | ||||
|     ['moment'], | ||||
|     function (moment) { | ||||
|  | ||||
|         var ROW_HEIGHT = 16, | ||||
|             SLIDER_HEIGHT = 10, | ||||
|             INITIAL_COLUMN_WIDTH = 225, | ||||
|             MAX_COLUMN_WIDTH = 525, | ||||
|             COLUMN_WIDTH_STEP = 25, | ||||
|             DEBOUNCE_INTERVAL = 100, | ||||
|             DATE_FORMAT = "YYYY-DDD HH:mm:ss.SSS\\Z", | ||||
|             NOT_UPDATED = "No updates", | ||||
|             EMPTY_ARRAY = []; | ||||
|  | ||||
|         /** | ||||
|          * Responsible for supporting the autoflow tabular view. | ||||
|          * Implements the all-over logic which drives that view, | ||||
|          * mediating between template-provided areas, the included | ||||
|          * `mct-autoflow-table` directive, and the underlying | ||||
|          * domain object model. | ||||
|          * @constructor | ||||
|          */ | ||||
|         function AutflowTabularController( | ||||
|             $scope, | ||||
|             $timeout, | ||||
|             telemetrySubscriber | ||||
|         ) { | ||||
|             var filterValue = "", | ||||
|                 filterValueLowercase = "", | ||||
|                 subscription, | ||||
|                 filteredObjects = [], | ||||
|                 lastUpdated = {}, | ||||
|                 updateText = NOT_UPDATED, | ||||
|                 rangeValues = {}, | ||||
|                 classes = {}, | ||||
|                 limits = {}, | ||||
|                 updatePending = false, | ||||
|                 lastBounce = Number.NEGATIVE_INFINITY, | ||||
|                 columnWidth = INITIAL_COLUMN_WIDTH, | ||||
|                 rows = 1, | ||||
|                 counter = 0; | ||||
|  | ||||
|             // Trigger an update of the displayed table by incrementing | ||||
|             // the counter that it watches. | ||||
|             function triggerDisplayUpdate() { | ||||
|                 counter += 1; | ||||
|             } | ||||
|  | ||||
|             // Check whether or not an object's name matches the | ||||
|             // user-entered filter value. | ||||
|             function filterObject(domainObject) { | ||||
|                 return (domainObject.getModel().name || "") | ||||
|                     .toLowerCase() | ||||
|                     .indexOf(filterValueLowercase) !== -1; | ||||
|             } | ||||
|  | ||||
|             // Comparator for sorting points back into packet order | ||||
|             function compareObject(objectA, objectB) { | ||||
|                 var indexA = objectA.getModel().index || 0, | ||||
|                     indexB = objectB.getModel().index || 0; | ||||
|                 return indexA - indexB; | ||||
|             } | ||||
|  | ||||
|             // Update the list of currently-displayed objects; these | ||||
|             // will be the subset of currently subscribed-to objects | ||||
|             // which match a user-entered filter. | ||||
|             function doUpdateFilteredObjects() { | ||||
|                 // Generate the list | ||||
|                 filteredObjects = ( | ||||
|                     subscription ? | ||||
|                             subscription.getTelemetryObjects() : | ||||
|                             [] | ||||
|                 ).filter(filterObject).sort(compareObject); | ||||
|  | ||||
|                 // Clear the pending flag | ||||
|                 updatePending = false; | ||||
|  | ||||
|                 // Track when this occurred, so that we can wait | ||||
|                 // a whole before updating again. | ||||
|                 lastBounce = Date.now(); | ||||
|  | ||||
|                 triggerDisplayUpdate(); | ||||
|             } | ||||
|  | ||||
|             // Request an update to the list of current objects; this may | ||||
|             // run on a timeout to avoid excessive calls, e.g. while the user | ||||
|             // is typing a filter. | ||||
|             function updateFilteredObjects() { | ||||
|                 // Don't do anything if an update is already scheduled | ||||
|                 if (!updatePending) { | ||||
|                     if (Date.now() > lastBounce + DEBOUNCE_INTERVAL) { | ||||
|                         // Update immediately if it's been long enough | ||||
|                         doUpdateFilteredObjects(); | ||||
|                     } else { | ||||
|                         // Otherwise, update later, and track that we have | ||||
|                         // an update pending so that subsequent calls can | ||||
|                         // be ignored. | ||||
|                         updatePending = true; | ||||
|                         $timeout(doUpdateFilteredObjects, DEBOUNCE_INTERVAL); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Track the latest data values for this domain object | ||||
|             function recordData(telemetryObject) { | ||||
|                 // Get latest domain/range values for this object. | ||||
|                 var id = telemetryObject.getId(), | ||||
|                     domainValue = subscription.getDomainValue(telemetryObject), | ||||
|                     rangeValue = subscription.getRangeValue(telemetryObject); | ||||
|  | ||||
|                 // Track the most recent timestamp change observed... | ||||
|                 if (domainValue !== undefined && domainValue !== lastUpdated[id]) { | ||||
|                     lastUpdated[id] = domainValue; | ||||
|                     // ... and update the displayable text for that timestamp | ||||
|                     updateText = isNaN(domainValue) ? "" : | ||||
|                             moment.utc(domainValue).format(DATE_FORMAT); | ||||
|                 } | ||||
|  | ||||
|                 // Store data values into the rangeValues structure, which | ||||
|                 // will be used to populate the table itself. | ||||
|                 // Note that we want full precision here. | ||||
|                 rangeValues[id] = rangeValue; | ||||
|  | ||||
|                 // Update limit states as well | ||||
|                 classes[id] = limits[id] && (limits[id].evaluate({ | ||||
|                     // This relies on external knowledge that the | ||||
|                     // range value of a telemetry point is encoded | ||||
|                     // in its datum as "value." | ||||
|                     value: rangeValue | ||||
|                 }) || {}).cssClass; | ||||
|             } | ||||
|  | ||||
|  | ||||
|             // Look at telemetry objects from the subscription; this is watched | ||||
|             // to detect changes from the subscription. | ||||
|             function subscribedTelemetry() { | ||||
|                 return subscription ? | ||||
|                         subscription.getTelemetryObjects() : EMPTY_ARRAY; | ||||
|             } | ||||
|  | ||||
|             // Update the data values which will be used to populate the table | ||||
|             function updateValues() { | ||||
|                 subscribedTelemetry().forEach(recordData); | ||||
|                 triggerDisplayUpdate(); | ||||
|             } | ||||
|  | ||||
|             // Getter-setter function for user-entered filter text. | ||||
|             function filter(value) { | ||||
|                 // If value was specified, we're a setter | ||||
|                 if (value !== undefined) { | ||||
|                     // Store the new value | ||||
|                     filterValue = value; | ||||
|                     filterValueLowercase = value.toLowerCase(); | ||||
|                     // Change which objects appear in the table | ||||
|                     updateFilteredObjects(); | ||||
|                 } | ||||
|  | ||||
|                 // Always act as a getter | ||||
|                 return filterValue; | ||||
|             } | ||||
|  | ||||
|             // Update the bounds (width and height) of this view; | ||||
|             // called from the mct-resize directive. Recalculates how | ||||
|             // many rows should appear in the contained table. | ||||
|             function setBounds(bounds) { | ||||
|                 var availableSpace = bounds.height - SLIDER_HEIGHT; | ||||
|                 rows = Math.max(1, Math.floor(availableSpace / ROW_HEIGHT)); | ||||
|             } | ||||
|  | ||||
|             // Increment the current column width, up to the defined maximum. | ||||
|             // When the max is hit, roll back to the default. | ||||
|             function increaseColumnWidth() { | ||||
|                 columnWidth += COLUMN_WIDTH_STEP; | ||||
|                 // Cycle down to the initial width instead of exceeding max | ||||
|                 columnWidth = columnWidth > MAX_COLUMN_WIDTH ? | ||||
|                         INITIAL_COLUMN_WIDTH : columnWidth; | ||||
|             } | ||||
|  | ||||
|             // Get displayable text for last-updated value | ||||
|             function updated() { | ||||
|                 return updateText; | ||||
|             } | ||||
|  | ||||
|             // Unsubscribe, if a subscription is active. | ||||
|             function releaseSubscription() { | ||||
|                 if (subscription) { | ||||
|                     subscription.unsubscribe(); | ||||
|                     subscription = undefined; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Update set of telemetry objects managed by this view | ||||
|             function updateTelemetryObjects(telemetryObjects) { | ||||
|                 updateFilteredObjects(); | ||||
|                 limits = {}; | ||||
|                 telemetryObjects.forEach(function (telemetryObject) { | ||||
|                     var id = telemetryObject.getId(); | ||||
|                     limits[id] = telemetryObject.getCapability('limit'); | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             // Create a subscription for the represented domain object. | ||||
|             // This will resolve capability delegation as necessary. | ||||
|             function makeSubscription(domainObject) { | ||||
|                 // Unsubscribe, if there is an existing subscription | ||||
|                 releaseSubscription(); | ||||
|  | ||||
|                 // Clear updated timestamp | ||||
|                 lastUpdated = {}; | ||||
|                 updateText = NOT_UPDATED; | ||||
|  | ||||
|                 // Create a new subscription; telemetrySubscriber gets | ||||
|                 // to do the meaningful work here. | ||||
|                 subscription = domainObject && telemetrySubscriber.subscribe( | ||||
|                     domainObject, | ||||
|                     updateValues | ||||
|                 ); | ||||
|  | ||||
|                 // Our set of in-view telemetry objects may have changed, | ||||
|                 // so update the set that is being passed down to the table. | ||||
|                 updateFilteredObjects(); | ||||
|             } | ||||
|  | ||||
|             // Watch for changes to the set of objects which have telemetry | ||||
|             $scope.$watch(subscribedTelemetry, updateTelemetryObjects); | ||||
|  | ||||
|             // Watch for the represented domainObject (this field will | ||||
|             // be populated by mct-representation) | ||||
|             $scope.$watch("domainObject", makeSubscription); | ||||
|  | ||||
|             // Make sure we unsubscribe when this view is destroyed. | ||||
|             $scope.$on("$destroy", releaseSubscription); | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Get the number of rows which should be shown in this table. | ||||
|                  * @return {number} the number of rows to show | ||||
|                  */ | ||||
|                 getRows: function () { | ||||
|                     return rows; | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Get the objects which should currently be displayed in | ||||
|                  * this table. This will be watched, so the return value | ||||
|                  * should be stable when this list is unchanging. Only | ||||
|                  * objects which match the user-entered filter value should | ||||
|                  * be returned here. | ||||
|                  * @return {DomainObject[]} the domain objects to include in | ||||
|                  *         this table. | ||||
|                  */ | ||||
|                 getTelemetryObjects: function () { | ||||
|                     return filteredObjects; | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Set the bounds (width/height) of this autoflow tabular view. | ||||
|                  * The template must ensure that these bounds are tracked on | ||||
|                  * the table area only. | ||||
|                  * @param bounds the bounds; and object with `width` and | ||||
|                  *        `height` properties, both as numbers, in pixels. | ||||
|                  */ | ||||
|                 setBounds: setBounds, | ||||
|                 /** | ||||
|                  * Increments the width of the autoflow column. | ||||
|                  * Setting does not yet persist. | ||||
|                  */ | ||||
|                 increaseColumnWidth: increaseColumnWidth, | ||||
|                 /** | ||||
|                  * Get-or-set the user-supplied filter value. | ||||
|                  * @param {string} [value] the new filter value; omit to use | ||||
|                  *        as a getter | ||||
|                  * @returns {string} the user-supplied filter value | ||||
|                  */ | ||||
|                 filter: filter, | ||||
|                 /** | ||||
|                  * Get all range values for use in this table. These will be | ||||
|                  * returned as an object of key-value pairs, where keys are | ||||
|                  * domain object IDs, and values are the most recently observed | ||||
|                  * data values associated with those objects, formatted for | ||||
|                  * display. | ||||
|                  * @returns {object.<string,string>} most recent values | ||||
|                  */ | ||||
|                 rangeValues: function () { | ||||
|                     return rangeValues; | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Get CSS classes to apply to specific rows, representing limit | ||||
|                  * states and/or stale states. These are returned as key-value | ||||
|                  * pairs where keys are domain object IDs, and values are CSS | ||||
|                  * classes to display for domain objects with those IDs. | ||||
|                  * @returns {object.<string,string>} CSS classes | ||||
|                  */ | ||||
|                 classes: function () { | ||||
|                     return classes; | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Get the "last updated" text for this view; this will be | ||||
|                  * the most recent timestamp observed for any telemetry- | ||||
|                  * providing object, formatted for display. | ||||
|                  * @returns {string} the time of the most recent update | ||||
|                  */ | ||||
|                 updated: updated, | ||||
|                 /** | ||||
|                  * Get the current column width, in pixels. | ||||
|                  * @returns {number} column width | ||||
|                  */ | ||||
|                 columnWidth: function () { | ||||
|                     return columnWidth; | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Keep a counter and increment this whenever the display | ||||
|                  * should be updated; this will be watched by the | ||||
|                  * `mct-autoflow-table`. | ||||
|                  * @returns {number} a counter value | ||||
|                  */ | ||||
|                 counter: function () { | ||||
|                     return counter; | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         return AutflowTabularController; | ||||
|     } | ||||
| ); | ||||
							
								
								
									
										60
									
								
								platform/features/autoflow/src/MCTAutoflowTable.js
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										60
									
								
								platform/features/autoflow/src/MCTAutoflowTable.js
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,60 @@ | ||||
|  | ||||
| define( | ||||
|     ["./AutoflowTableLinker"], | ||||
|     function (AutoflowTableLinker) { | ||||
|  | ||||
|         /** | ||||
|          * The `mct-autoflow-table` directive specifically supports | ||||
|          * autoflow tabular views; it is not intended for use outside | ||||
|          * of that view. | ||||
|          * | ||||
|          * This directive is responsible for creating the structure | ||||
|          * of the table in this view, and for updating its values. | ||||
|          * While this is achievable using a regular Angular template, | ||||
|          * this is undesirable from the perspective of performance | ||||
|          * due to the number of watches that can be involved for large | ||||
|          * tables. Instead, this directive will maintain a small number | ||||
|          * of watches, rebuilding table structure only when necessary, | ||||
|          * and updating displayed values in the more common case of | ||||
|          * new data arriving. | ||||
|          * | ||||
|          * @constructor | ||||
|          */ | ||||
|         function MCTAutoflowTable() { | ||||
|             return { | ||||
|                 // Only applicable at the element level | ||||
|                 restrict: "E", | ||||
|  | ||||
|                 // The link function; handles DOM update/manipulation | ||||
|                 link: AutoflowTableLinker, | ||||
|  | ||||
|                 // Parameters to pass from attributes into scope | ||||
|                 scope: { | ||||
|                     // Set of domain objects to show in the table | ||||
|                     objects: "=", | ||||
|  | ||||
|                     // Values for those objects, by ID | ||||
|                     values: "=", | ||||
|  | ||||
|                     // CSS classes to show for objects, by ID | ||||
|                     classes: "=", | ||||
|  | ||||
|                     // Number of rows to show before autoflowing | ||||
|                     rows: "=", | ||||
|  | ||||
|                     // Time of last update; watched to refresh values | ||||
|                     updated: "=", | ||||
|  | ||||
|                     // Current width of the autoflow column | ||||
|                     columnWidth: "=", | ||||
|  | ||||
|                     // A counter used to trigger display updates | ||||
|                     counter: "=" | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         return MCTAutoflowTable; | ||||
|  | ||||
|     } | ||||
| ); | ||||
							
								
								
									
										178
									
								
								platform/features/autoflow/test/AutoflowTableLinkerSpec.js
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										178
									
								
								platform/features/autoflow/test/AutoflowTableLinkerSpec.js
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,178 @@ | ||||
|  | ||||
| define( | ||||
|     ["../src/AutoflowTableLinker"], | ||||
|     function (AutoflowTableLinker) { | ||||
|  | ||||
|         describe("The mct-autoflow-table linker", function () { | ||||
|             var cachedAngular, | ||||
|                 mockAngular, | ||||
|                 mockScope, | ||||
|                 mockElement, | ||||
|                 mockElements, | ||||
|                 linker; | ||||
|  | ||||
|             // Utility function to generate more mock elements | ||||
|             function createMockElement(html) { | ||||
|                 var mockEl = jasmine.createSpyObj( | ||||
|                     "element-" + html, | ||||
|                     [ | ||||
|                         "append", | ||||
|                         "addClass", | ||||
|                         "removeClass", | ||||
|                         "text", | ||||
|                         "attr", | ||||
|                         "html", | ||||
|                         "css", | ||||
|                         "find" | ||||
|                     ] | ||||
|                 ); | ||||
|                 mockEl.testHtml = html; | ||||
|                 mockEl.append.andReturn(mockEl); | ||||
|                 mockElements.push(mockEl); | ||||
|                 return mockEl; | ||||
|             } | ||||
|  | ||||
|             function createMockDomainObject(id) { | ||||
|                 var mockDomainObject = jasmine.createSpyObj( | ||||
|                     "domainObject-" + id, | ||||
|                     ["getId", "getModel"] | ||||
|                 ); | ||||
|                 mockDomainObject.getId.andReturn(id); | ||||
|                 mockDomainObject.getModel.andReturn({name: id.toUpperCase()}); | ||||
|                 return mockDomainObject; | ||||
|             } | ||||
|  | ||||
|             function fireWatch(watchExpression, value) { | ||||
|                 mockScope.$watch.calls.forEach(function (call) { | ||||
|                     if (call.args[0] === watchExpression) { | ||||
|                         call.args[1](value); | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             // AutoflowTableLinker accesses Angular in the global | ||||
|             // scope, since it is not injectable; we simulate that | ||||
|             // here by adding/removing it to/from the window object. | ||||
|             beforeEach(function () { | ||||
|                 mockElements = []; | ||||
|  | ||||
|                 mockAngular = jasmine.createSpyObj("angular", ["element"]); | ||||
|                 mockScope = jasmine.createSpyObj("scope", ["$watch"]); | ||||
|                 mockElement = createMockElement('<div>'); | ||||
|  | ||||
|                 mockAngular.element.andCallFake(createMockElement); | ||||
|  | ||||
|                 if (window.angular !== undefined) { | ||||
|                     cachedAngular = window.angular; | ||||
|                 } | ||||
|                 window.angular = mockAngular; | ||||
|  | ||||
|                 linker = new AutoflowTableLinker(mockScope, mockElement); | ||||
|             }); | ||||
|  | ||||
|             afterEach(function () { | ||||
|                 if (cachedAngular !== undefined) { | ||||
|                     window.angular = cachedAngular; | ||||
|                 } else { | ||||
|                     delete window.angular; | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             it("watches for changes in inputs", function () { | ||||
|                 expect(mockScope.$watch).toHaveBeenCalledWith( | ||||
|                     "objects", | ||||
|                     jasmine.any(Function) | ||||
|                 ); | ||||
|                 expect(mockScope.$watch).toHaveBeenCalledWith( | ||||
|                     "rows", | ||||
|                     jasmine.any(Function) | ||||
|                 ); | ||||
|                 expect(mockScope.$watch).toHaveBeenCalledWith( | ||||
|                     "counter", | ||||
|                     jasmine.any(Function) | ||||
|                 ); | ||||
|             }); | ||||
|  | ||||
|             it("changes structure when domain objects change", function () { | ||||
|                 // Set up scope | ||||
|                 mockScope.rows = 4; | ||||
|                 mockScope.objects = ['a', 'b', 'c', 'd', 'e', 'f'] | ||||
|                     .map(createMockDomainObject); | ||||
|  | ||||
|                 // Fire an update to the set of objects | ||||
|                 fireWatch("objects"); | ||||
|  | ||||
|                 // Should have rebuilt with two columns of | ||||
|                 // four and two rows each; first, by clearing... | ||||
|                 expect(mockElement.html).toHaveBeenCalledWith(""); | ||||
|  | ||||
|                 // Should have appended two columns... | ||||
|                 expect(mockElement.append.calls.length).toEqual(2); | ||||
|  | ||||
|                 // ...which should have received two and four rows each | ||||
|                 expect(mockElement.append.calls[0].args[0].append.calls.length) | ||||
|                     .toEqual(4); | ||||
|                 expect(mockElement.append.calls[1].args[0].append.calls.length) | ||||
|                     .toEqual(2); | ||||
|             }); | ||||
|  | ||||
|             it("updates values", function () { | ||||
|                 var mockSpans; | ||||
|  | ||||
|                 mockScope.objects = ['a', 'b', 'c', 'd', 'e', 'f'] | ||||
|                     .map(createMockDomainObject); | ||||
|                 mockScope.values = { a: 0 }; | ||||
|  | ||||
|                 // Fire an update to the set of values | ||||
|                 fireWatch("objects"); | ||||
|                 fireWatch("updated"); | ||||
|  | ||||
|                 // Get all created spans | ||||
|                 mockSpans = mockElements.filter(function (mockElem) { | ||||
|                     return mockElem.testHtml === '<span>'; | ||||
|                 }); | ||||
|  | ||||
|                 // First span should be a, should have gotten this value. | ||||
|                 // This test detects, in particular, WTD-749 | ||||
|                 expect(mockSpans[0].text).toHaveBeenCalledWith('A'); | ||||
|                 expect(mockSpans[1].text).toHaveBeenCalledWith(0); | ||||
|             }); | ||||
|  | ||||
|             it("listens for changes in column width", function () { | ||||
|                 var mockUL = createMockElement("<ul>"); | ||||
|                 mockElement.find.andReturn(mockUL); | ||||
|                 mockScope.columnWidth = 200; | ||||
|                 fireWatch("columnWidth", mockScope.columnWidth); | ||||
|                 expect(mockUL.css).toHaveBeenCalledWith("width", "200px"); | ||||
|             }); | ||||
|  | ||||
|             it("updates CSS classes", function () { | ||||
|                 var mockSpans; | ||||
|  | ||||
|                 mockScope.objects = ['a', 'b', 'c', 'd', 'e', 'f'] | ||||
|                     .map(createMockDomainObject); | ||||
|                 mockScope.values = { a: "a value to find" }; | ||||
|                 mockScope.classes = { a: 'class-a' }; | ||||
|  | ||||
|                 // Fire an update to the set of values | ||||
|                 fireWatch("objects"); | ||||
|                 fireWatch("updated"); | ||||
|  | ||||
|                 // Figure out which span holds the relevant value... | ||||
|                 mockSpans = mockElements.filter(function (mockElem) { | ||||
|                     return mockElem.testHtml === '<span>'; | ||||
|                 }).filter(function (mockSpan) { | ||||
|                     var attrCalls = mockSpan.attr.calls; | ||||
|                     return attrCalls.some(function (call) { | ||||
|                         return call.args[0] === 'title' && | ||||
|                                 call.args[1] === mockScope.values.a; | ||||
|                     }); | ||||
|                 }); | ||||
|  | ||||
|                 // ...and make sure it also has had its class applied | ||||
|                 expect(mockSpans[0].addClass) | ||||
|                     .toHaveBeenCalledWith(mockScope.classes.a); | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
| ); | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user