mirror of
https://github.com/nasa/openmct.git
synced 2025-04-16 15:29:20 +00:00
Merge branch 'open-master' into open1051b
Merge in latest to add license headers, WTD-1051
This commit is contained in:
commit
28fbc5be09
342
LICENSES.md
Normal file
342
LICENSES.md
Normal file
@ -0,0 +1,342 @@
|
||||
# Open MCT Web Licenses
|
||||
|
||||
Open MCT Web, Copyright (c) 2009-2015, United States Government as represented by the Administrator of the National Aeronautics and Space Administration. All rights reserved.
|
||||
|
||||
Open MCT Web is licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
||||
|
||||
Open MCT Web includes source code licensed under additional open source licenses as follows.
|
||||
|
||||
## Apache License
|
||||
|
||||
Version 2.0, January 2004
|
||||
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
|
||||
|
||||
You must give any other recipients of the Work or Derivative Works a copy of this License; and
|
||||
You must cause any modified files to carry prominent notices stating that You changed the files; and
|
||||
You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
|
||||
If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work
|
||||
|
||||
To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
||||
## Software Components Licenses
|
||||
|
||||
This software includes components released under the following licenses:
|
||||
|
||||
### Blanket.js
|
||||
|
||||
#### Info
|
||||
|
||||
* Link: http://blanketjs.org/
|
||||
|
||||
* Version: 1.1.5
|
||||
|
||||
* Author: Alex Seville
|
||||
|
||||
* Description: Code coverage measurement and reporting
|
||||
|
||||
#### License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
---
|
||||
|
||||
### Jasmine
|
||||
|
||||
#### Info
|
||||
|
||||
* Link: http://jasmine.github.io/
|
||||
|
||||
* Version: 1.3.1
|
||||
|
||||
* Author: Pivotal Labs
|
||||
|
||||
* Description: Unit testing
|
||||
|
||||
#### License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
---
|
||||
|
||||
### RequireJS
|
||||
|
||||
#### Info
|
||||
|
||||
* Link: http://requirejs.org/
|
||||
|
||||
* Version: 2.1.9
|
||||
|
||||
* Author: The Dojo Foundation
|
||||
|
||||
* Description: Script loader
|
||||
|
||||
#### License
|
||||
|
||||
Copyright (c) 2010-2015, The Dojo Foundation
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
---
|
||||
|
||||
### AngularJS
|
||||
|
||||
#### Info
|
||||
|
||||
* Link: http://angularjs.org/
|
||||
|
||||
* Version: 1.2.26
|
||||
|
||||
* Author: Google
|
||||
|
||||
* Description: Client-side web application framework
|
||||
|
||||
#### License
|
||||
|
||||
Copyright (c) 2010-2015 Google, Inc. http://angularjs.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
---
|
||||
|
||||
### Angular-Route
|
||||
|
||||
#### Info
|
||||
|
||||
* Link: http://angularjs.org/
|
||||
|
||||
* Version: 1.2.26
|
||||
|
||||
* Author: Google
|
||||
|
||||
* Description: Client-side view routing
|
||||
|
||||
#### License
|
||||
|
||||
Copyright (c) 2010-2015 Google, Inc. http://angularjs.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
---
|
||||
|
||||
### ES6-Promise
|
||||
|
||||
#### Info
|
||||
|
||||
* Link: https://github.com/jakearchibald/es6-promise
|
||||
|
||||
* Version: 2.0.0
|
||||
|
||||
* Authors: Yehuda Katz, Tom Dale, Stefan Penner and contributors
|
||||
|
||||
* Description: Promise polyfill for pre-ECMAScript 6 browsers
|
||||
|
||||
#### License
|
||||
|
||||
Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
---
|
||||
|
||||
### screenfull.js
|
||||
|
||||
#### Info
|
||||
|
||||
* Link: https://github.com/sindresorhus/screenfull.js/
|
||||
|
||||
* Version: 1.2.0
|
||||
|
||||
* Author: Sindre Sorhus
|
||||
|
||||
* Description: Wrapper for cross-browser usage of fullscreen API
|
||||
|
||||
#### License
|
||||
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
---
|
||||
|
||||
### Math.uuid.js
|
||||
|
||||
#### Info
|
||||
|
||||
* Link: https://github.com/broofa/node-uuid
|
||||
|
||||
* Version: 1.4
|
||||
|
||||
* Author: Robert Kieffer
|
||||
|
||||
* Description: Unique identifer generation (code adapted.)
|
||||
|
||||
#### License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
---
|
||||
|
||||
### Modernizr
|
||||
|
||||
#### Info
|
||||
|
||||
* Link: http://modernizr.com
|
||||
|
||||
* Version: 2.6.2
|
||||
|
||||
* Author: Faruk Ateş
|
||||
|
||||
* Description: Browser/device capability finding
|
||||
|
||||
#### License
|
||||
|
||||
Copyright (c) 2009–2015
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
---
|
||||
|
||||
### Normalize.css
|
||||
|
||||
#### Info
|
||||
|
||||
* Link: http://necolas.github.io/normalize.css/
|
||||
|
||||
* Version: 1.1.2
|
||||
|
||||
* Authors: Nicolas Gallagher, Jonathan Neal
|
||||
|
||||
* Description: Browser style normalization
|
||||
|
||||
#### License
|
||||
|
||||
Copyright (c) Nicolas Gallagher and Jonathan Neal
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
---
|
||||
|
||||
### Moment.js
|
||||
|
||||
#### Info
|
||||
|
||||
* Link: http://momentjs.com
|
||||
|
||||
* Version: 2.7.0
|
||||
|
||||
* Authors: Tim Wood, Iskren Chernev, Moment.js contributors
|
||||
|
||||
* Description: Time/date parsing/formatting
|
||||
|
||||
#### License
|
||||
|
||||
Copyright (c) 2011-2014 Tim Wood, Iskren Chernev, Moment.js contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
---
|
@ -10,6 +10,7 @@
|
||||
"platform/containment",
|
||||
"platform/telemetry",
|
||||
"platform/features/layout",
|
||||
"platform/features/pages",
|
||||
"platform/features/plot",
|
||||
"platform/features/scrolling",
|
||||
"platform/forms",
|
||||
|
@ -19,6 +19,14 @@
|
||||
{
|
||||
"key": "overlay-about",
|
||||
"templateUrl": "templates/overlay-about.html"
|
||||
},
|
||||
{
|
||||
"key": "license-apache",
|
||||
"templateUrl": "templates/license-apache.html"
|
||||
},
|
||||
{
|
||||
"key": "license-mit",
|
||||
"templateUrl": "templates/license-mit.html"
|
||||
}
|
||||
],
|
||||
"controllers": [
|
||||
@ -42,6 +50,10 @@
|
||||
{
|
||||
"when": "/licenses",
|
||||
"templateUrl": "templates/licenses.html"
|
||||
},
|
||||
{
|
||||
"when": "/licenses-md",
|
||||
"templateUrl": "templates/licenses-export-md.html"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1,13 +1,16 @@
|
||||
<div class="abs t-about l-about t-about-openmctweb" ng-controller = "AboutController as about">
|
||||
<div class="abs t-about l-about t-about-openmctweb s-about" ng-controller = "AboutController as about">
|
||||
<div class="l-logo-holder s-logo-holder">
|
||||
<div class="l-logo s-logo s-logo-nasa"></div>
|
||||
<div class="l-logo l-logo-app s-logo s-logo-openmctweb"></div>
|
||||
</div>
|
||||
|
||||
<div class="l-content">
|
||||
<div class="s-text l-content">
|
||||
<h1 class="l-title s-title">OpenMCT Web</h1>
|
||||
<div class="l-description s-description">
|
||||
<p>OpenMCT Web is a project of NASA's Ames Research Center. Copyright ©2015 NASA Ames Research Center, all rights reserved. <a ng-click="about.openLicenses()">Licensing information</a></p>
|
||||
<p>Open MCT Web, Copyright © 2009-2015, United States Government as represented by the Administrator of the National Aeronautics and Space Administration. All rights reserved.</p>
|
||||
<p>Open MCT Web is licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at <a target="_blank" href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>.</p>
|
||||
<p>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.</p>
|
||||
<p>Open MCT Web includes source code licensed under additional open source licenses. See the Open Source Licenses file included with this distribution or <a ng-click="about.openLicenses()">click here for licensing information</a>.</p>
|
||||
</div>
|
||||
<h2>Version Information</h2>
|
||||
<ul class="t-info l-info s-info" ng-repeat = "version in about.versions()">
|
||||
|
178
platform/commonUI/about/res/templates/license-apache.html
Normal file
178
platform/commonUI/about/res/templates/license-apache.html
Normal file
@ -0,0 +1,178 @@
|
||||
<!-- From http://www.apache.org/licenses/LICENSE-2.0 -->
|
||||
<br>
|
||||
<p>Version 2.0, January 2004</p>
|
||||
<p><a href="http://www.apache.org/licenses/">http://www.apache.org/licenses/</a></p>
|
||||
<h3>TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION</h3>
|
||||
<p><strong><a name="definitions">1. Definitions</a></strong>.</p>
|
||||
<p>"License" shall mean the terms and conditions for use, reproduction, and
|
||||
distribution as defined by Sections 1 through 9 of this document.</p>
|
||||
<p>"Licensor" shall mean the copyright owner or entity authorized by the
|
||||
copyright owner that is granting the License.</p>
|
||||
<p>"Legal Entity" shall mean the union of the acting entity and all other
|
||||
entities that control, are controlled by, or are under common control with
|
||||
that entity. For the purposes of this definition, "control" means (i) the
|
||||
power, direct or indirect, to cause the direction or management of such
|
||||
entity, whether by contract or otherwise, or (ii) ownership of fifty
|
||||
percent (50%) or more of the outstanding shares, or (iii) beneficial
|
||||
ownership of such entity.</p>
|
||||
<p>"You" (or "Your") shall mean an individual or Legal Entity exercising
|
||||
permissions granted by this License.</p>
|
||||
<p>"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation source,
|
||||
and configuration files.</p>
|
||||
<p>"Object" form shall mean any form resulting from mechanical transformation
|
||||
or translation of a Source form, including but not limited to compiled
|
||||
object code, generated documentation, and conversions to other media types.</p>
|
||||
<p>"Work" shall mean the work of authorship, whether in Source or Object form,
|
||||
made available under the License, as indicated by a copyright notice that
|
||||
is included in or attached to the work (an example is provided in the
|
||||
Appendix below).</p>
|
||||
<p>"Derivative Works" shall mean any work, whether in Source or Object form,
|
||||
that is based on (or derived from) the Work and for which the editorial
|
||||
revisions, annotations, elaborations, or other modifications represent, as
|
||||
a whole, an original work of authorship. For the purposes of this License,
|
||||
Derivative Works shall not include works that remain separable from, or
|
||||
merely link (or bind by name) to the interfaces of, the Work and Derivative
|
||||
Works thereof.</p>
|
||||
<p>"Contribution" shall mean any work of authorship, including the original
|
||||
version of the Work and any modifications or additions to that Work or
|
||||
Derivative Works thereof, that is intentionally submitted to Licensor for
|
||||
inclusion in the Work by the copyright owner or by an individual or Legal
|
||||
Entity authorized to submit on behalf of the copyright owner. For the
|
||||
purposes of this definition, "submitted" means any form of electronic,
|
||||
verbal, or written communication sent to the Licensor or its
|
||||
representatives, including but not limited to communication on electronic
|
||||
mailing lists, source code control systems, and issue tracking systems that
|
||||
are managed by, or on behalf of, the Licensor for the purpose of discussing
|
||||
and improving the Work, but excluding communication that is conspicuously
|
||||
marked or otherwise designated in writing by the copyright owner as "Not a
|
||||
Contribution."</p>
|
||||
<p>"Contributor" shall mean Licensor and any individual or Legal Entity on
|
||||
behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.</p>
|
||||
<p><strong><a name="copyright">2. Grant of Copyright License</a></strong>. Subject to the
|
||||
terms and conditions of this License, each Contributor hereby grants to You
|
||||
a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of, publicly
|
||||
display, publicly perform, sublicense, and distribute the Work and such
|
||||
Derivative Works in Source or Object form.</p>
|
||||
<p><strong><a name="patent">3. Grant of Patent License</a></strong>. Subject to the terms
|
||||
and conditions of this License, each Contributor hereby grants to You a
|
||||
perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made, use,
|
||||
offer to sell, sell, import, and otherwise transfer the Work, where such
|
||||
license applies only to those patent claims licensable by such Contributor
|
||||
that are necessarily infringed by their Contribution(s) alone or by
|
||||
combination of their Contribution(s) with the Work to which such
|
||||
Contribution(s) was submitted. If You institute patent litigation against
|
||||
any entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||
that the Work or a Contribution incorporated within the Work constitutes
|
||||
direct or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate as of the
|
||||
date such litigation is filed.</p>
|
||||
<p><strong><a name="redistribution">4. Redistribution</a></strong>. You may reproduce and
|
||||
distribute copies of the Work or Derivative Works thereof in any medium,
|
||||
with or without modifications, and in Source or Object form, provided that
|
||||
You meet the following conditions:</p>
|
||||
<ol style="list-style: lower-latin;">
|
||||
<li>You must give any other recipients of the Work or Derivative Works a
|
||||
copy of this License; and</li>
|
||||
|
||||
<li>You must cause any modified files to carry prominent notices stating
|
||||
that You changed the files; and</li>
|
||||
|
||||
<li>You must retain, in the Source form of any Derivative Works that You
|
||||
distribute, all copyright, patent, trademark, and attribution notices from
|
||||
the Source form of the Work, excluding those notices that do not pertain to
|
||||
any part of the Derivative Works; and</li>
|
||||
|
||||
<li>If the Work includes a "NOTICE" text file as part of its distribution,
|
||||
then any Derivative Works that You distribute must include a readable copy
|
||||
of the attribution notices contained within such NOTICE file, excluding
|
||||
those notices that do not pertain to any part of the Derivative Works, in
|
||||
at least one of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or documentation,
|
||||
if provided along with the Derivative Works; or, within a display generated
|
||||
by the Derivative Works, if and wherever such third-party notices normally
|
||||
appear. The contents of the NOTICE file are for informational purposes only
|
||||
and do not modify the License. You may add Your own attribution notices
|
||||
within Derivative Works that You distribute, alongside or as an addendum to
|
||||
the NOTICE text from the Work, provided that such additional attribution
|
||||
notices cannot be construed as modifying the License.
|
||||
<br>
|
||||
<br>
|
||||
You may add Your own copyright statement to Your modifications and may
|
||||
provide additional or different license terms and conditions for use,
|
||||
reproduction, or distribution of Your modifications, or for any such
|
||||
Derivative Works as a whole, provided Your use, reproduction, and
|
||||
distribution of the Work otherwise complies with the conditions stated in
|
||||
this License.
|
||||
</li>
|
||||
|
||||
</ol>
|
||||
|
||||
<p><strong><a name="contributions">5. Submission of Contributions</a></strong>. Unless You
|
||||
explicitly state otherwise, any Contribution intentionally submitted for
|
||||
inclusion in the Work by You to the Licensor shall be under the terms and
|
||||
conditions of this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify the
|
||||
terms of any separate license agreement you may have executed with Licensor
|
||||
regarding such Contributions.</p>
|
||||
<p><strong><a name="trademarks">6. Trademarks</a></strong>. This License does not grant
|
||||
permission to use the trade names, trademarks, service marks, or product
|
||||
names of the Licensor, except as required for reasonable and customary use
|
||||
in describing the origin of the Work and reproducing the content of the
|
||||
NOTICE file.</p>
|
||||
<p><strong><a name="no-warranty">7. Disclaimer of Warranty</a></strong>. Unless required by
|
||||
applicable law or agreed to in writing, Licensor provides the Work (and
|
||||
each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including,
|
||||
without limitation, any warranties or conditions of TITLE,
|
||||
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You
|
||||
are solely responsible for determining the appropriateness of using or
|
||||
redistributing the Work and assume any risks associated with Your exercise
|
||||
of permissions under this License.</p>
|
||||
<p><strong><a name="no-liability">8. Limitation of Liability</a></strong>. In no event and
|
||||
under no legal theory, whether in tort (including negligence), contract, or
|
||||
otherwise, unless required by applicable law (such as deliberate and
|
||||
grossly negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a result
|
||||
of this License or out of the use or inability to use the Work (including
|
||||
but not limited to damages for loss of goodwill, work stoppage, computer
|
||||
failure or malfunction, or any and all other commercial damages or losses),
|
||||
even if such Contributor has been advised of the possibility of such
|
||||
damages.</p>
|
||||
<p><strong><a name="additional">9. Accepting Warranty or Additional Liability</a></strong>.
|
||||
While redistributing the Work or Derivative Works thereof, You may choose
|
||||
to offer, and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this License.
|
||||
However, in accepting such obligations, You may act only on Your own behalf
|
||||
and on Your sole responsibility, not on behalf of any other Contributor,
|
||||
and only if You agree to indemnify, defend, and hold each Contributor
|
||||
harmless for any liability incurred by, or claims asserted against, such
|
||||
Contributor by reason of your accepting any such warranty or additional
|
||||
liability.</p>
|
||||
<h3>END OF TERMS AND CONDITIONS</h3>
|
||||
<h3 id="apply">APPENDIX: How to apply the Apache License to your work</h3>
|
||||
<p>To apply the Apache License to your work, attach the following boilerplate
|
||||
notice, with the fields enclosed by brackets "[]" replaced with your own
|
||||
identifying information. (Don't include the brackets!) The text should be
|
||||
enclosed in the appropriate comment syntax for the file format. We also
|
||||
recommend that a file or class name and description of purpose be included
|
||||
on the same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.</p>
|
||||
<div class="codehilite"><pre>Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
||||
</pre></div>
|
3
platform/commonUI/about/res/templates/license-mit.html
Normal file
3
platform/commonUI/about/res/templates/license-mit.html
Normal file
@ -0,0 +1,3 @@
|
||||
<p>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</p>
|
||||
<p>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</p>
|
||||
<p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</p>
|
@ -0,0 +1,21 @@
|
||||
<div ng-controller="LicenseController as lc" class="abs l-about l-standalone s-text s-md-export">
|
||||
<h1># Open MCT Web Licenses</h1>
|
||||
<h2>## Apache License</h2>
|
||||
<mct-include key="'license-apache'"></mct-include>
|
||||
|
||||
<h2>## Software Components Licenses</h2>
|
||||
<p>This software includes components released under the following licenses:</p>
|
||||
<div class="l-license-software" ng-repeat="license in lc.licenses()">
|
||||
<p>### {{license.name}}</p>
|
||||
<p>#### Info</p>
|
||||
<p>* Link: {{license.website}}</p>
|
||||
<p>* Version: {{license.version}}</p>
|
||||
<p>* Author<span ng-show="license.author.indexOf(',') > 0">s</span>: {{license.author}}</p>
|
||||
<p>* Description: {{license.description}}</p>
|
||||
<p>#### License</p>
|
||||
<p ng-show="license.copyright.length > 0">{{license.copyright}}</p>
|
||||
<mct-include key="license.license"></mct-include>
|
||||
<p> </p>
|
||||
<p>---</p>
|
||||
</div>
|
||||
</div>
|
@ -1,33 +1,23 @@
|
||||
<style>
|
||||
.licenses { padding: 1em; }
|
||||
.licenses th { font-weight: bold; padding: 0.5em; }
|
||||
.licenses td { padding: 0.5em; }
|
||||
</style>
|
||||
<div ng-controller="LicenseController as lc" class="abs l-standalone s-text l-about l-licenses s-about s-licenses">
|
||||
<h1>OpenMCT Web Licenses</h1>
|
||||
<h2>Apache License</h2>
|
||||
<mct-include key="'license-apache'"></mct-include>
|
||||
|
||||
<div ng-controller="LicenseController as lc" class="licenses">
|
||||
|
||||
<p>
|
||||
This software includes components released under the following licenses.
|
||||
</p>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Version</th>
|
||||
<th>Author</th>
|
||||
<th>Description</th>
|
||||
<th>License</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody style="font-weight: normal;">
|
||||
<tr ng-repeat="license in lc.licenses()">
|
||||
<td><a ng-href="{{license.website}}">{{license.name}}</a></td>
|
||||
<td>{{license.version}}</td>
|
||||
<td>{{license.author}}</td>
|
||||
<td>{{license.description}}</td>
|
||||
<td><a ng-href="{{license.link}}">{{license.license}}</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2>Software Components Licenses</h2>
|
||||
<p>This software includes components released under the following licenses:</p>
|
||||
<div class="l-licenses-software">
|
||||
<div class="l-license-software" ng-repeat="license in lc.licenses()">
|
||||
<h3><a target="_blank" ng-href="{{license.website}}">{{license.name}}</a></h3>
|
||||
<p>
|
||||
<em>Version</em> {{license.version}}
|
||||
<em> | Author<span ng-show="license.author.indexOf(',') > 0">s</span></em> {{license.author}}
|
||||
<em> | Description</em> {{license.description}}
|
||||
</p>
|
||||
<em>License</em>
|
||||
<div class="s-license-text">
|
||||
<p ng-show="license.copyright.length > 0">{{license.copyright}}</p>
|
||||
<mct-include key="license.license"></mct-include>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -85,7 +85,7 @@
|
||||
{
|
||||
"key": "window",
|
||||
"implementation": "windowing/NewWindowAction.js",
|
||||
"description": "Open this object in a new window.",
|
||||
"description": "Open this object in a new window",
|
||||
"category": "view-control",
|
||||
"depends": [ "$window" ],
|
||||
"group": "windowing",
|
||||
@ -104,7 +104,7 @@
|
||||
"key": "items",
|
||||
"name": "Items",
|
||||
"glyph": "9",
|
||||
"description": "Grid of available items.",
|
||||
"description": "Grid of available items",
|
||||
"templateUrl": "templates/items/items.html",
|
||||
"uses": [ "composition" ],
|
||||
"gestures": [ "drop" ],
|
||||
@ -125,10 +125,11 @@
|
||||
{
|
||||
"name": "screenfull.js",
|
||||
"version": "1.2.0",
|
||||
"description": "Wrapper for cross-browser usage of fullscreen API.",
|
||||
"description": "Wrapper for cross-browser usage of fullscreen API",
|
||||
"author": "Sindre Sorhus",
|
||||
"website": "https://github.com/sindresorhus/screenfull.js/",
|
||||
"license": "MIT",
|
||||
"copyright": "Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)",
|
||||
"license": "license-mit",
|
||||
"link": "https://github.com/sindresorhus/screenfull.js/blob/gh-pages/license"
|
||||
},
|
||||
{
|
||||
@ -137,7 +138,8 @@
|
||||
"description": "Unique identifer generation (code adapted.)",
|
||||
"author": "Robert Kieffer",
|
||||
"website": "https://github.com/broofa/node-uuid",
|
||||
"license": "MIT",
|
||||
"copyright": "",
|
||||
"license": "license-mit",
|
||||
"link": "http://opensource.org/licenses/MIT"
|
||||
}
|
||||
]
|
||||
|
@ -1,6 +1,6 @@
|
||||
<div content="jquery-wrapper" class="abs holder-all browse-mode">
|
||||
<mct-include key="'topbar-browse'"></mct-include>
|
||||
<div class="holder browse-area outline abs" ng-controller="BrowseController">
|
||||
<div class="holder browse-area s-browse-area abs" ng-controller="BrowseController">
|
||||
<div class='split-layout vertical contents abs'
|
||||
ng-controller="SplitPaneController as splitter">
|
||||
<div class='split-pane-component treeview pane'
|
||||
|
@ -2,7 +2,7 @@
|
||||
mct-object="domainObject"
|
||||
ng-model="representation">
|
||||
</mct-representation>
|
||||
<div class="holder edit-area outline abs"
|
||||
<div class="holder edit-area abs"
|
||||
ng-controller="SplitPaneController as vSplitter">
|
||||
<mct-toolbar name="mctToolbar"
|
||||
structure="toolbar.structure"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "General UI elements",
|
||||
"description": "General UI elements, meant to be reused across modes.",
|
||||
"description": "General UI elements, meant to be reused across modes",
|
||||
"resources": "res",
|
||||
"extensions": {
|
||||
"runs": [
|
||||
@ -211,19 +211,21 @@
|
||||
{
|
||||
"name": "Modernizr",
|
||||
"version": "2.6.2",
|
||||
"description": "Browser/device capability finding.",
|
||||
"description": "Browser/device capability finding",
|
||||
"author": "Faruk Ateş",
|
||||
"website": "http://modernizr.com",
|
||||
"license": "MIT",
|
||||
"copyright": "Copyright (c) 2009–2015",
|
||||
"license": "license-mit",
|
||||
"link": "http://modernizr.com/license/"
|
||||
},
|
||||
{
|
||||
"name": "Normalize.css",
|
||||
"version": "1.1.2",
|
||||
"description": "Browser style normalization.",
|
||||
"description": "Browser style normalization",
|
||||
"author": "Nicolas Gallagher, Jonathan Neal",
|
||||
"website": "http://necolas.github.io/normalize.css/",
|
||||
"license": "MIT",
|
||||
"copyright": "Copyright (c) Nicolas Gallagher and Jonathan Neal",
|
||||
"license": "license-mit",
|
||||
"link": "https://github.com/necolas/normalize.css/blob/master/LICENSE.md"
|
||||
}
|
||||
]
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* line 4, ../sass/items/_item.scss */
|
||||
.items-holder .contents {
|
||||
top: 0; }
|
||||
/* line 6, ../sass/items/_item.scss */
|
||||
/* line 8, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item {
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #595959), color-stop(100%, #4d4d4d));
|
||||
background-image: -webkit-linear-gradient(#595959, #4d4d4d);
|
||||
@ -43,56 +43,62 @@
|
||||
background-image: -moz-linear-gradient(#737373, #595959);
|
||||
background-image: -o-linear-gradient(#737373, #595959);
|
||||
background-image: linear-gradient(#737373, #595959); }
|
||||
/* line 19, ../sass/items/_item.scss */
|
||||
/* line 21, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item:hover .item-main .item-type {
|
||||
color: #0099cc !important; }
|
||||
/* line 22, ../sass/items/_item.scss */
|
||||
/* line 24, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item:hover .item-main .item-open {
|
||||
display: block; }
|
||||
/* line 27, ../sass/items/_item.scss */
|
||||
/* line 28, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .contents {
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
bottom: 5px;
|
||||
left: 5px; }
|
||||
/* line 32, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .bar.top-bar.abs {
|
||||
bottom: auto;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
z-index: 5; }
|
||||
/* line 32, ../sass/items/_item.scss */
|
||||
/* line 37, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .bar.top-bar.abs .left, .items-holder .item.grid-item .bar.top-bar.abs .right {
|
||||
width: auto; }
|
||||
/* line 34, ../sass/items/_item.scss */
|
||||
/* line 39, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .bar.top-bar.abs .left .icon, .items-holder .item.grid-item .bar.top-bar.abs .right .icon {
|
||||
margin-left: 5px; }
|
||||
/* line 39, ../sass/items/_item.scss */
|
||||
/* line 44, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .bar.bottom-bar.abs {
|
||||
top: auto;
|
||||
height: 40px;
|
||||
padding: 5px; }
|
||||
/* line 45, ../sass/items/_item.scss */
|
||||
/* line 50, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .item-main {
|
||||
z-index: 1; }
|
||||
/* line 53, ../sass/items/_item.scss */
|
||||
/* line 58, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .item-main .item-type {
|
||||
color: #737373;
|
||||
text-align: center;
|
||||
font-size: 7em;
|
||||
line-height: 180px; }
|
||||
/* line 59, ../sass/items/_item.scss */
|
||||
/* line 64, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .item-main .item-open {
|
||||
display: none;
|
||||
font-size: 5em;
|
||||
line-height: 180px;
|
||||
left: auto;
|
||||
width: 30px; }
|
||||
/* line 67, ../sass/items/_item.scss */
|
||||
/* line 72, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .title {
|
||||
text-shadow: rgba(0, 0, 0, 0.1) 0 1px 2px;
|
||||
color: #cccccc;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis; }
|
||||
/* line 75, ../sass/items/_item.scss */
|
||||
/* line 80, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item .details {
|
||||
font-size: 0.8em; }
|
||||
/* line 78, ../sass/items/_item.scss */
|
||||
/* line 83, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item.selected {
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #00bfff), color-stop(100%, #00ace6));
|
||||
background-image: -webkit-linear-gradient(#00bfff, #00ace6);
|
||||
@ -127,15 +133,15 @@
|
||||
background-image: -moz-linear-gradient(#66d9ff, #00bfff);
|
||||
background-image: -o-linear-gradient(#66d9ff, #00bfff);
|
||||
background-image: linear-gradient(#66d9ff, #00bfff); }
|
||||
/* line 83, ../sass/items/_item.scss */
|
||||
/* line 88, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item.selected .item-type, .items-holder .item.grid-item.selected .top-bar .icon:not(.alert) {
|
||||
color: #80dfff; }
|
||||
/* line 84, ../sass/items/_item.scss */
|
||||
/* line 89, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item.selected .item-main .item-open {
|
||||
color: #80dfff; }
|
||||
/* line 85, ../sass/items/_item.scss */
|
||||
/* line 90, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item.selected .title {
|
||||
color: white; }
|
||||
/* line 87, ../sass/items/_item.scss */
|
||||
/* line 92, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item.selected:hover .item-main .item-type {
|
||||
color: white !important; }
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* CONSTANTS */
|
||||
/* line 17, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
||||
/* line 17, ../../../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
||||
html, body, div, span, applet, object, iframe,
|
||||
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||
a, abbr, acronym, address, big, cite, code,
|
||||
@ -20,38 +20,38 @@ time, mark, audio, video {
|
||||
font-size: 100%;
|
||||
vertical-align: baseline; }
|
||||
|
||||
/* line 22, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
||||
/* line 22, ../../../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
||||
html {
|
||||
line-height: 1; }
|
||||
|
||||
/* line 24, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
||||
/* line 24, ../../../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
||||
ol, ul {
|
||||
list-style: none; }
|
||||
|
||||
/* line 26, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
||||
/* line 26, ../../../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0; }
|
||||
|
||||
/* line 28, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
||||
/* line 28, ../../../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
||||
caption, th, td {
|
||||
text-align: left;
|
||||
font-weight: normal;
|
||||
vertical-align: middle; }
|
||||
|
||||
/* line 30, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
||||
/* line 30, ../../../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
||||
q, blockquote {
|
||||
quotes: none; }
|
||||
/* line 103, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
||||
/* line 103, ../../../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
||||
q:before, q:after, blockquote:before, blockquote:after {
|
||||
content: "";
|
||||
content: none; }
|
||||
|
||||
/* line 32, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
||||
/* line 32, ../../../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
||||
a img {
|
||||
border: none; }
|
||||
|
||||
/* line 116, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
||||
/* line 116, ../../../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
|
||||
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section, summary {
|
||||
display: block; }
|
||||
|
||||
@ -108,7 +108,6 @@ body, html {
|
||||
|
||||
/* line 20, ../sass/_global.scss */
|
||||
em {
|
||||
color: rgba(255, 255, 255, 0.2);
|
||||
font-style: normal; }
|
||||
|
||||
/* line 25, ../sass/_global.scss */
|
||||
@ -148,36 +147,45 @@ span {
|
||||
width: auto; }
|
||||
|
||||
/* line 61, ../sass/_global.scss */
|
||||
.code {
|
||||
.code, .codehilite {
|
||||
font-family: "Lucida Console", monospace;
|
||||
font-size: 0.7em;
|
||||
line-height: 150%;
|
||||
white-space: pre; }
|
||||
|
||||
/* line 68, ../sass/_global.scss */
|
||||
.codehilite {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
padding: 1em; }
|
||||
|
||||
/* line 74, ../sass/_global.scss */
|
||||
.align-right {
|
||||
text-align: right; }
|
||||
|
||||
/* line 72, ../sass/_global.scss */
|
||||
/* line 78, ../sass/_global.scss */
|
||||
.centered {
|
||||
text-align: center; }
|
||||
|
||||
/* line 76, ../sass/_global.scss */
|
||||
/* line 82, ../sass/_global.scss */
|
||||
.no-margin {
|
||||
margin: 0; }
|
||||
|
||||
/* line 86, ../sass/_global.scss */
|
||||
.colorKey {
|
||||
color: #0099cc; }
|
||||
|
||||
/* line 80, ../sass/_global.scss */
|
||||
/* line 90, ../sass/_global.scss */
|
||||
.ds {
|
||||
-webkit-box-shadow: rgba(0, 0, 0, 0.7) 0 4px 10px 2px;
|
||||
-moz-box-shadow: rgba(0, 0, 0, 0.7) 0 4px 10px 2px;
|
||||
box-shadow: rgba(0, 0, 0, 0.7) 0 4px 10px 2px; }
|
||||
|
||||
/* line 85, ../sass/_global.scss */
|
||||
/* line 95, ../sass/_global.scss */
|
||||
.hide,
|
||||
.hidden {
|
||||
display: none !important; }
|
||||
|
||||
/* line 89, ../sass/_global.scss */
|
||||
/* line 99, ../sass/_global.scss */
|
||||
.sep {
|
||||
color: rgba(255, 255, 255, 0.2); }
|
||||
|
||||
@ -195,76 +203,55 @@ span {
|
||||
.ui-symbol {
|
||||
font-family: 'symbolsfont'; }
|
||||
|
||||
/* line 13, ../sass/user-environ/_layout.scss */
|
||||
/* line 11, ../sass/user-environ/_layout.scss */
|
||||
.holder-all {
|
||||
top: 3px;
|
||||
right: 3px;
|
||||
bottom: 3px;
|
||||
left: 3px; }
|
||||
|
||||
/* line 21, ../sass/user-environ/_layout.scss */
|
||||
.browse-area,
|
||||
.edit-area,
|
||||
.editor {
|
||||
position: absolute; }
|
||||
|
||||
/* line 25, ../sass/user-environ/_layout.scss */
|
||||
.editor {
|
||||
-webkit-border-radius: 4.5px;
|
||||
-moz-border-radius: 4.5px;
|
||||
-ms-border-radius: 4.5px;
|
||||
-o-border-radius: 4.5px;
|
||||
border-radius: 4.5px;
|
||||
position: absolute; }
|
||||
border-radius: 4.5px; }
|
||||
|
||||
/* line 24, ../sass/user-environ/_layout.scss */
|
||||
.user-environ .browse-area,
|
||||
.user-environ .edit-area,
|
||||
.user-environ .editor {
|
||||
top: 45px;
|
||||
right: 5px;
|
||||
bottom: 30px;
|
||||
left: 5px; }
|
||||
/* line 33, ../sass/user-environ/_layout.scss */
|
||||
.user-environ .edit-area .tool-bar {
|
||||
bottom: auto;
|
||||
height: 35px;
|
||||
line-height: 28px; }
|
||||
/* line 38, ../sass/user-environ/_layout.scss */
|
||||
.user-environ .edit-area .work-area {
|
||||
top: 45px; }
|
||||
/* line 43, ../sass/user-environ/_layout.scss */
|
||||
.user-environ .bottom-bar {
|
||||
top: auto;
|
||||
right: 5px;
|
||||
bottom: 5px;
|
||||
left: 5px;
|
||||
height: 20px; }
|
||||
/* line 49, ../sass/user-environ/_layout.scss */
|
||||
.user-environ .bottom-bar .status-holder {
|
||||
right: 110px; }
|
||||
/* line 52, ../sass/user-environ/_layout.scss */
|
||||
.user-environ .bottom-bar .app-logo {
|
||||
left: auto;
|
||||
width: 105px; }
|
||||
|
||||
/* line 60, ../sass/user-environ/_layout.scss */
|
||||
/* line 29, ../sass/user-environ/_layout.scss */
|
||||
.contents {
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
bottom: 5px;
|
||||
left: 5px; }
|
||||
/* line 68, ../sass/user-environ/_layout.scss */
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0; }
|
||||
/* line 37, ../sass/user-environ/_layout.scss */
|
||||
.contents.nomargin {
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px; }
|
||||
|
||||
/* line 77, ../sass/user-environ/_layout.scss */
|
||||
/* line 46, ../sass/user-environ/_layout.scss */
|
||||
.bar .icon.major {
|
||||
margin-right: 5px; }
|
||||
/* line 80, ../sass/user-environ/_layout.scss */
|
||||
/* line 49, ../sass/user-environ/_layout.scss */
|
||||
.bar.abs, .btn-menu span.bar.l-click-area {
|
||||
text-wrap: none;
|
||||
white-space: nowrap; }
|
||||
/* line 84, ../sass/user-environ/_layout.scss */
|
||||
/* line 53, ../sass/user-environ/_layout.scss */
|
||||
.bar.abs.left, .btn-menu span.bar.left.l-click-area,
|
||||
.bar.abs .left,
|
||||
.btn-menu span.bar.l-click-area .left {
|
||||
width: 45%;
|
||||
right: auto; }
|
||||
/* line 89, ../sass/user-environ/_layout.scss */
|
||||
/* line 58, ../sass/user-environ/_layout.scss */
|
||||
.bar.abs.right, .btn-menu span.bar.right.l-click-area,
|
||||
.bar.abs .right,
|
||||
.btn-menu span.bar.l-click-area .right {
|
||||
@ -272,17 +259,53 @@ span {
|
||||
left: auto;
|
||||
right: 0;
|
||||
text-align: right; }
|
||||
/* line 94, ../sass/user-environ/_layout.scss */
|
||||
/* line 63, ../sass/user-environ/_layout.scss */
|
||||
.bar.abs.right .icon.major, .btn-menu span.bar.right.l-click-area .icon.major,
|
||||
.bar.abs .right .icon.major,
|
||||
.btn-menu span.bar.l-click-area .right .icon.major {
|
||||
margin-left: 15px; }
|
||||
|
||||
/* line 104, ../sass/user-environ/_layout.scss */
|
||||
/* line 76, ../sass/user-environ/_layout.scss */
|
||||
.user-environ .browse-area,
|
||||
.user-environ .edit-area,
|
||||
.user-environ .editor {
|
||||
top: 45px;
|
||||
right: 5px;
|
||||
bottom: 30px;
|
||||
left: 5px; }
|
||||
/* line 85, ../sass/user-environ/_layout.scss */
|
||||
.user-environ .browse-area > .contents,
|
||||
.user-environ .edit-area > .contents {
|
||||
left: 0;
|
||||
right: 0; }
|
||||
/* line 93, ../sass/user-environ/_layout.scss */
|
||||
.user-environ .edit-area .tool-bar {
|
||||
bottom: auto;
|
||||
height: 35px;
|
||||
line-height: 28px; }
|
||||
/* line 98, ../sass/user-environ/_layout.scss */
|
||||
.user-environ .edit-area .work-area {
|
||||
top: 45px; }
|
||||
/* line 103, ../sass/user-environ/_layout.scss */
|
||||
.user-environ .bottom-bar {
|
||||
top: auto;
|
||||
right: 5px;
|
||||
bottom: 5px;
|
||||
left: 5px;
|
||||
height: 20px; }
|
||||
/* line 109, ../sass/user-environ/_layout.scss */
|
||||
.user-environ .bottom-bar .status-holder {
|
||||
right: 110px; }
|
||||
/* line 112, ../sass/user-environ/_layout.scss */
|
||||
.user-environ .bottom-bar .app-logo {
|
||||
left: auto;
|
||||
width: 105px; }
|
||||
|
||||
/* line 119, ../sass/user-environ/_layout.scss */
|
||||
.cols {
|
||||
overflow: hidden;
|
||||
*zoom: 1; }
|
||||
/* line 106, ../sass/user-environ/_layout.scss */
|
||||
/* line 121, ../sass/user-environ/_layout.scss */
|
||||
.cols .col {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
@ -293,89 +316,89 @@ span {
|
||||
margin-left: 1.5%;
|
||||
padding-left: 5px;
|
||||
position: relative; }
|
||||
/* line 114, ../sass/user-environ/_layout.scss */
|
||||
/* line 129, ../sass/user-environ/_layout.scss */
|
||||
.cols .col:first-child {
|
||||
margin-left: 0;
|
||||
padding-left: 0; }
|
||||
/* line 121, ../sass/user-environ/_layout.scss */
|
||||
/* line 136, ../sass/user-environ/_layout.scss */
|
||||
.cols.cols-2 .col-1 {
|
||||
min-width: 250px;
|
||||
width: 48.5%; }
|
||||
/* line 127, ../sass/user-environ/_layout.scss */
|
||||
/* line 142, ../sass/user-environ/_layout.scss */
|
||||
.cols.cols-2-ff .col-100px {
|
||||
width: 100px; }
|
||||
/* line 134, ../sass/user-environ/_layout.scss */
|
||||
/* line 149, ../sass/user-environ/_layout.scss */
|
||||
.cols.cols-6 .col-1 {
|
||||
min-width: 83.33333px;
|
||||
width: 15.16667%; }
|
||||
/* line 140, ../sass/user-environ/_layout.scss */
|
||||
/* line 155, ../sass/user-environ/_layout.scss */
|
||||
.cols.cols-16 .col-1 {
|
||||
min-width: 31.25px;
|
||||
width: 4.75%; }
|
||||
/* line 143, ../sass/user-environ/_layout.scss */
|
||||
/* line 158, ../sass/user-environ/_layout.scss */
|
||||
.cols.cols-16 .col-2 {
|
||||
min-width: 62.5px;
|
||||
width: 11%; }
|
||||
/* line 146, ../sass/user-environ/_layout.scss */
|
||||
/* line 161, ../sass/user-environ/_layout.scss */
|
||||
.cols.cols-16 .col-7 {
|
||||
min-width: 218.75px;
|
||||
width: 42.25%; }
|
||||
/* line 152, ../sass/user-environ/_layout.scss */
|
||||
/* line 167, ../sass/user-environ/_layout.scss */
|
||||
.cols.cols-32 .col-2 {
|
||||
min-width: 31.25px;
|
||||
width: 4.75%; }
|
||||
/* line 155, ../sass/user-environ/_layout.scss */
|
||||
/* line 170, ../sass/user-environ/_layout.scss */
|
||||
.cols.cols-32 .col-15 {
|
||||
min-width: 234.375px;
|
||||
width: 45.375%; }
|
||||
/* line 159, ../sass/user-environ/_layout.scss */
|
||||
/* line 174, ../sass/user-environ/_layout.scss */
|
||||
.cols .l-row {
|
||||
overflow: hidden;
|
||||
*zoom: 1;
|
||||
padding: 5px 0; }
|
||||
|
||||
/* line 165, ../sass/user-environ/_layout.scss */
|
||||
/* line 180, ../sass/user-environ/_layout.scss */
|
||||
.pane {
|
||||
position: absolute; }
|
||||
/* line 168, ../sass/user-environ/_layout.scss */
|
||||
/* line 183, ../sass/user-environ/_layout.scss */
|
||||
.pane.treeview .create-btn-holder {
|
||||
bottom: auto;
|
||||
height: 35px; }
|
||||
/* line 171, ../sass/user-environ/_layout.scss */
|
||||
/* line 186, ../sass/user-environ/_layout.scss */
|
||||
.pane.treeview .tree-holder {
|
||||
overflow: auto;
|
||||
top: 40px; }
|
||||
/* line 180, ../sass/user-environ/_layout.scss */
|
||||
/* line 195, ../sass/user-environ/_layout.scss */
|
||||
.pane.items .object-holder {
|
||||
top: 40px; }
|
||||
/* line 185, ../sass/user-environ/_layout.scss */
|
||||
/* line 200, ../sass/user-environ/_layout.scss */
|
||||
.pane.edit-main .object-holder {
|
||||
top: 0; }
|
||||
/* line 191, ../sass/user-environ/_layout.scss */
|
||||
/* line 206, ../sass/user-environ/_layout.scss */
|
||||
.pane .object-holder {
|
||||
overflow: auto; }
|
||||
|
||||
/* line 199, ../sass/user-environ/_layout.scss */
|
||||
/* line 214, ../sass/user-environ/_layout.scss */
|
||||
.split-layout.horizontal > .pane {
|
||||
margin-top: 5px; }
|
||||
/* line 202, ../sass/user-environ/_layout.scss */
|
||||
/* line 217, ../sass/user-environ/_layout.scss */
|
||||
.split-layout.horizontal > .pane:first-child {
|
||||
margin-top: 0; }
|
||||
/* line 209, ../sass/user-environ/_layout.scss */
|
||||
/* line 224, ../sass/user-environ/_layout.scss */
|
||||
.split-layout.vertical > .pane {
|
||||
margin-left: 5px; }
|
||||
/* line 211, ../sass/user-environ/_layout.scss */
|
||||
/* line 226, ../sass/user-environ/_layout.scss */
|
||||
.split-layout.vertical > .pane > .holder {
|
||||
left: 0;
|
||||
right: 0; }
|
||||
/* line 215, ../sass/user-environ/_layout.scss */
|
||||
/* line 230, ../sass/user-environ/_layout.scss */
|
||||
.split-layout.vertical > .pane:first-child {
|
||||
margin-left: 0; }
|
||||
/* line 217, ../sass/user-environ/_layout.scss */
|
||||
/* line 232, ../sass/user-environ/_layout.scss */
|
||||
.split-layout.vertical > .pane:first-child .holder {
|
||||
right: 5px; }
|
||||
|
||||
/* line 226, ../sass/user-environ/_layout.scss */
|
||||
/* line 241, ../sass/user-environ/_layout.scss */
|
||||
.vscroll {
|
||||
overflow-y: auto; }
|
||||
|
||||
@ -388,33 +411,33 @@ span {
|
||||
left: 0;
|
||||
width: auto;
|
||||
height: auto; }
|
||||
/* line 8, ../sass/_fixed-position.scss */
|
||||
/* line 12, ../sass/_fixed-position.scss */
|
||||
.t-fixed-position.l-fixed-position .l-grid-holder {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%; }
|
||||
/* line 11, ../sass/_fixed-position.scss */
|
||||
/* line 16, ../sass/_fixed-position.scss */
|
||||
.t-fixed-position.l-fixed-position .l-grid-holder .l-grid {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
pointer-events: none;
|
||||
z-index: 0; }
|
||||
/* line 21, ../sass/_fixed-position.scss */
|
||||
/* line 27, ../sass/_fixed-position.scss */
|
||||
.t-fixed-position .l-fixed-position-item {
|
||||
position: absolute;
|
||||
border: 1px solid transparent; }
|
||||
/* line 25, ../sass/_fixed-position.scss */
|
||||
/* line 31, ../sass/_fixed-position.scss */
|
||||
.t-fixed-position .l-fixed-position-item.s-selected {
|
||||
-webkit-box-shadow: rgba(0, 0, 0, 0.7) 0 3px 10px;
|
||||
-moz-box-shadow: rgba(0, 0, 0, 0.7) 0 3px 10px;
|
||||
box-shadow: rgba(0, 0, 0, 0.7) 0 3px 10px;
|
||||
border-color: #0099cc;
|
||||
cursor: move; }
|
||||
/* line 30, ../sass/_fixed-position.scss */
|
||||
/* line 36, ../sass/_fixed-position.scss */
|
||||
.t-fixed-position .l-fixed-position-item.s-not-selected {
|
||||
opacity: 0.8; }
|
||||
/* line 36, ../sass/_fixed-position.scss */
|
||||
/* line 42, ../sass/_fixed-position.scss */
|
||||
.t-fixed-position .l-fixed-position-item .l-fixed-position-box,
|
||||
.t-fixed-position .l-fixed-position-item .l-fixed-position-image,
|
||||
.t-fixed-position .l-fixed-position-item .l-fixed-position-text {
|
||||
@ -423,20 +446,20 @@ span {
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
width: 100%; }
|
||||
/* line 44, ../sass/_fixed-position.scss */
|
||||
/* line 51, ../sass/_fixed-position.scss */
|
||||
.t-fixed-position .l-fixed-position-item .l-fixed-position-image {
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center; }
|
||||
/* line 50, ../sass/_fixed-position.scss */
|
||||
/* line 57, ../sass/_fixed-position.scss */
|
||||
.t-fixed-position .l-fixed-position-item .l-fixed-position-text {
|
||||
text-shadow: rgba(0, 0, 0, 0.1) 0 1px 2px;
|
||||
border: 1px solid transparent;
|
||||
font-size: 0.8rem; }
|
||||
/* line 55, ../sass/_fixed-position.scss */
|
||||
/* line 62, ../sass/_fixed-position.scss */
|
||||
.t-fixed-position .l-fixed-position-item .l-fixed-position-text.l-static-text {
|
||||
padding: 3px; }
|
||||
/* line 60, ../sass/_fixed-position.scss */
|
||||
/* line 67, ../sass/_fixed-position.scss */
|
||||
.t-fixed-position .l-fixed-position-item .l-fixed-position-text.l-telemetry .l-elem {
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
@ -450,98 +473,142 @@ span {
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
width: 50%; }
|
||||
/* line 64, ../sass/_fixed-position.scss */
|
||||
/* line 71, ../sass/_fixed-position.scss */
|
||||
.t-fixed-position .l-fixed-position-item .l-fixed-position-text.l-telemetry .l-elem.l-title {
|
||||
right: auto;
|
||||
left: 3px; }
|
||||
/* line 68, ../sass/_fixed-position.scss */
|
||||
/* line 75, ../sass/_fixed-position.scss */
|
||||
.t-fixed-position .l-fixed-position-item .l-fixed-position-text.l-telemetry .l-elem.l-value {
|
||||
right: 3px;
|
||||
left: auto;
|
||||
text-align: right; }
|
||||
/* line 73, ../sass/_fixed-position.scss */
|
||||
/* line 80, ../sass/_fixed-position.scss */
|
||||
.t-fixed-position .l-fixed-position-item .l-fixed-position-text.l-telemetry .l-elem.l-value.telem-only {
|
||||
left: 3px;
|
||||
width: auto; }
|
||||
/* line 84, ../sass/_fixed-position.scss */
|
||||
/* line 91, ../sass/_fixed-position.scss */
|
||||
.t-fixed-position .l-fixed-position-item-handle {
|
||||
background: rgba(0, 153, 204, 0.5);
|
||||
cursor: crosshair;
|
||||
border: 1px solid #0099cc;
|
||||
position: absolute; }
|
||||
|
||||
/* line 98, ../sass/_fixed-position.scss */
|
||||
/* line 105, ../sass/_fixed-position.scss */
|
||||
.edit-mode .t-fixed-position.l-fixed-position .l-grid-holder .l-grid.l-grid-x {
|
||||
background-image: -webkit-linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 100%);
|
||||
background-image: -moz-linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 100%);
|
||||
background-image: -o-linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 100%);
|
||||
background-image: linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 100%);
|
||||
background-repeat: repeat-x; }
|
||||
/* line 102, ../sass/_fixed-position.scss */
|
||||
/* line 109, ../sass/_fixed-position.scss */
|
||||
.edit-mode .t-fixed-position.l-fixed-position .l-grid-holder .l-grid.l-grid-y {
|
||||
background-image: -webkit-linear-gradient(0deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 100%);
|
||||
background-image: -moz-linear-gradient(0deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 100%);
|
||||
background-image: -o-linear-gradient(0deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 100%);
|
||||
background-image: linear-gradient(0deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 100%);
|
||||
background-repeat: repeat-y; }
|
||||
/* line 110, ../sass/_fixed-position.scss */
|
||||
.edit-mode .t-fixed-position .l-fixed-position-item:not(.s-selected):hover {
|
||||
border: 1px dotted rgba(0, 153, 204, 0.5); }
|
||||
/* line 117, ../sass/_fixed-position.scss */
|
||||
.edit-mode .t-fixed-position .l-fixed-position-item:not(.s-selected) {
|
||||
border: 1px dotted rgba(0, 153, 204, 0.75); }
|
||||
/* line 119, ../sass/_fixed-position.scss */
|
||||
.edit-mode .t-fixed-position .l-fixed-position-item:not(.s-selected):hover {
|
||||
border: 1px dotted #0099cc; }
|
||||
|
||||
/* line 3, ../sass/_about.scss */
|
||||
.t-about {
|
||||
/* line 5, ../sass/_about.scss */
|
||||
.l-about.abs, .btn-menu span.l-about.l-click-area {
|
||||
overflow: auto; }
|
||||
/* line 10, ../sass/_about.scss */
|
||||
.l-about .l-logo-holder {
|
||||
position: relative;
|
||||
height: 45%; }
|
||||
/* line 13, ../sass/_about.scss */
|
||||
.l-about .l-logo-holder .l-logo {
|
||||
position: absolute; }
|
||||
/* line 16, ../sass/_about.scss */
|
||||
.l-about .l-logo-holder .l-logo.l-logo-app {
|
||||
top: 0;
|
||||
right: 15%;
|
||||
bottom: 0;
|
||||
left: 15%; }
|
||||
/* line 20, ../sass/_about.scss */
|
||||
.l-about .l-logo-holder .l-logo.s-logo-nasa {
|
||||
background-image: url("../images/logo-nasa.svg");
|
||||
top: 10px;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
left: 10px;
|
||||
width: 10%;
|
||||
height: auto;
|
||||
padding-bottom: 5%;
|
||||
padding-top: 5%; }
|
||||
/* line 29, ../sass/_about.scss */
|
||||
.l-about .l-content {
|
||||
position: relative;
|
||||
margin-top: 10px; }
|
||||
|
||||
/* line 36, ../sass/_about.scss */
|
||||
.s-about {
|
||||
line-height: 120%; }
|
||||
/* line 7, ../sass/_about.scss */
|
||||
.t-about .s-description,
|
||||
.t-about .s-info {
|
||||
font-size: 0.8em; }
|
||||
/* line 10, ../sass/_about.scss */
|
||||
.t-about .s-logo-holder {
|
||||
/* line 40, ../sass/_about.scss */
|
||||
.s-about a {
|
||||
color: #84b3ff; }
|
||||
/* line 47, ../sass/_about.scss */
|
||||
.s-about .s-logo-holder {
|
||||
background: url("../images/bg-about-openmctweb.jpg") no-repeat center;
|
||||
background-size: cover; }
|
||||
/* line 14, ../sass/_about.scss */
|
||||
.t-about .s-logo {
|
||||
/* line 51, ../sass/_about.scss */
|
||||
.s-about .s-logo {
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain; }
|
||||
/* line 20, ../sass/_about.scss */
|
||||
.t-about .s-logo-openmctweb {
|
||||
/* line 57, ../sass/_about.scss */
|
||||
.s-about .s-logo-openmctweb {
|
||||
background-image: url("../images/logo-openmctweb-shdw.svg"); }
|
||||
/* line 23, ../sass/_about.scss */
|
||||
.t-about h1, .t-about h2 {
|
||||
/* line 60, ../sass/_about.scss */
|
||||
.s-about .s-btn, .s-about .s-icon-btn {
|
||||
line-height: 2em; }
|
||||
/* line 64, ../sass/_about.scss */
|
||||
.s-about .l-licenses-software .l-license-software {
|
||||
border-top: 1px solid #4d4d4d;
|
||||
padding: 0.5em 0; }
|
||||
/* line 67, ../sass/_about.scss */
|
||||
.s-about .l-licenses-software .l-license-software:first-child {
|
||||
border-top: none; }
|
||||
/* line 70, ../sass/_about.scss */
|
||||
.s-about .l-licenses-software .l-license-software em {
|
||||
color: #666666; }
|
||||
/* line 77, ../sass/_about.scss */
|
||||
.s-about .l-licenses-software .l-license-software h3 {
|
||||
font-size: 1.25em; }
|
||||
/* line 80, ../sass/_about.scss */
|
||||
.s-about .l-licenses-software .l-license-software .s-license-text {
|
||||
font-size: 0.9em; }
|
||||
|
||||
/* line 3, ../sass/_text.scss */
|
||||
.abs.l-standalone, .btn-menu span.l-standalone.l-click-area {
|
||||
padding: 5% 20%; }
|
||||
|
||||
/* line 8, ../sass/_text.scss */
|
||||
.s-text {
|
||||
font-size: 0.8em; }
|
||||
/* line 10, ../sass/_text.scss */
|
||||
.s-text ol, .s-text ul {
|
||||
list-style: square;
|
||||
margin-left: 1.5em; }
|
||||
/* line 18, ../sass/_text.scss */
|
||||
.s-text h1, .s-text h2, .s-text h3 {
|
||||
color: #fff;
|
||||
font-weight: normal !important; }
|
||||
/* line 29, ../sass/_about.scss */
|
||||
.t-about.l-about.abs, .btn-menu span.t-about.l-about.l-click-area {
|
||||
overflow: auto; }
|
||||
/* line 34, ../sass/_about.scss */
|
||||
.t-about .l-logo-holder {
|
||||
position: relative;
|
||||
height: 45%; }
|
||||
/* line 37, ../sass/_about.scss */
|
||||
.t-about .l-logo-holder .l-logo {
|
||||
position: absolute; }
|
||||
/* line 40, ../sass/_about.scss */
|
||||
.t-about .l-logo-holder .l-logo.l-logo-app {
|
||||
top: 0;
|
||||
right: 15%;
|
||||
bottom: 0;
|
||||
left: 15%; }
|
||||
/* line 44, ../sass/_about.scss */
|
||||
.t-about .l-logo-holder .l-logo.s-logo-nasa {
|
||||
background-image: url("../images/logo-nasa.svg");
|
||||
top: 10px;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
left: 10px;
|
||||
width: 10%;
|
||||
height: auto;
|
||||
padding-bottom: 5%;
|
||||
padding-top: 5%; }
|
||||
/* line 53, ../sass/_about.scss */
|
||||
.t-about .l-content {
|
||||
position: relative;
|
||||
margin-top: 10px; }
|
||||
font-weight: normal !important;
|
||||
margin-bottom: 1em; }
|
||||
/* line 24, ../sass/_text.scss */
|
||||
.s-text h2 {
|
||||
border-top: 1px solid #4d4d4d;
|
||||
font-size: 1.5em;
|
||||
margin-top: 2em;
|
||||
padding-top: 1em; }
|
||||
/* line 31, ../sass/_text.scss */
|
||||
.s-text h3 {
|
||||
margin-top: 2em; }
|
||||
|
||||
/* line 1, ../sass/_badges.scss */
|
||||
.badge {
|
||||
@ -2524,6 +2591,10 @@ input[type="text"] {
|
||||
margin-left: 10px; }
|
||||
/* line 53, ../sass/overlay/_overlay.scss */
|
||||
.overlay .contents.l-dialog {
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
bottom: 5px;
|
||||
left: 5px;
|
||||
overflow: auto; }
|
||||
|
||||
/* line 4, ../sass/user-environ/_frame.scss */
|
||||
@ -2540,8 +2611,14 @@ input[type="text"] {
|
||||
/* line 18, ../sass/user-environ/_frame.scss */
|
||||
.frame > .object-holder.abs, .btn-menu .frame > span.object-holder.l-click-area {
|
||||
top: 23px; }
|
||||
/* line 21, ../sass/user-environ/_frame.scss */
|
||||
.frame .contents {
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
bottom: 5px;
|
||||
left: 5px; }
|
||||
|
||||
/* line 24, ../sass/user-environ/_frame.scss */
|
||||
/* line 31, ../sass/user-environ/_frame.scss */
|
||||
.edit-main .frame.child-frame.panel:hover {
|
||||
border-color: #0099cc;
|
||||
-webkit-box-shadow: rgba(0, 0, 0, 0.7) 0 3px 10px;
|
||||
@ -2553,27 +2630,28 @@ input[type="text"] {
|
||||
line-height: 35px; }
|
||||
/* line 7, ../sass/user-environ/_top-bar.scss */
|
||||
.top-bar.browse, .top-bar.edit {
|
||||
border-bottom: 1px solid #4d4d4d;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
bottom: auto;
|
||||
left: 5px;
|
||||
height: 35px; }
|
||||
/* line 15, ../sass/user-environ/_top-bar.scss */
|
||||
/* line 16, ../sass/user-environ/_top-bar.scss */
|
||||
.top-bar .title {
|
||||
color: #fff; }
|
||||
/* line 20, ../sass/user-environ/_top-bar.scss */
|
||||
/* line 21, ../sass/user-environ/_top-bar.scss */
|
||||
.top-bar .buttons-main {
|
||||
font-size: 0.8em;
|
||||
left: auto;
|
||||
text-align: right; }
|
||||
/* line 25, ../sass/user-environ/_top-bar.scss */
|
||||
/* line 26, ../sass/user-environ/_top-bar.scss */
|
||||
.top-bar .buttons-main .btn {
|
||||
margin-left: 5px; }
|
||||
|
||||
/* line 33, ../sass/user-environ/_top-bar.scss */
|
||||
/* line 34, ../sass/user-environ/_top-bar.scss */
|
||||
.edit-mode .top-bar .buttons-main {
|
||||
white-space: nowrap; }
|
||||
/* line 37, ../sass/user-environ/_top-bar.scss */
|
||||
/* line 38, ../sass/user-environ/_top-bar.scss */
|
||||
.edit-mode .top-bar .buttons-main.abs, .edit-mode .top-bar .btn-menu span.buttons-main.l-click-area, .btn-menu .edit-mode .top-bar span.buttons-main.l-click-area {
|
||||
bottom: auto;
|
||||
left: auto; }
|
||||
@ -2667,49 +2745,107 @@ input[type="text"] {
|
||||
.tool-bar .input-labeled label {
|
||||
font-size: 12.6px; }
|
||||
|
||||
/* line 1, ../sass/helpers/_bubbles.scss */
|
||||
.bubble-wrapper {
|
||||
/* line 6, ../sass/helpers/_bubbles.scss */
|
||||
.l-infobubble-wrapper {
|
||||
-webkit-box-shadow: rgba(0, 0, 0, 0.4) 0 1px 5px;
|
||||
-moz-box-shadow: rgba(0, 0, 0, 0.4) 0 1px 5px;
|
||||
box-shadow: rgba(0, 0, 0, 0.4) 0 1px 5px;
|
||||
position: absolute;
|
||||
z-index: 10; }
|
||||
/* line 8, ../sass/helpers/_bubbles.scss */
|
||||
.bubble-wrapper .bubble {
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
-ms-border-radius: 3px;
|
||||
-o-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
z-index: 70; }
|
||||
/* line 11, ../sass/helpers/_bubbles.scss */
|
||||
.l-infobubble-wrapper .l-infobubble {
|
||||
display: inline-block;
|
||||
background: #990000;
|
||||
color: #ff9999;
|
||||
font-size: 0.8rem;
|
||||
font-style: italic;
|
||||
max-width: 200px;
|
||||
padding: 4px 8px; }
|
||||
/* line 17, ../sass/helpers/_bubbles.scss */
|
||||
.bubble-wrapper .bubble:before {
|
||||
max-width: 250px;
|
||||
padding: 5px 10px; }
|
||||
/* line 15, ../sass/helpers/_bubbles.scss */
|
||||
.l-infobubble-wrapper .l-infobubble:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0; }
|
||||
/* line 24, ../sass/helpers/_bubbles.scss */
|
||||
.bubble-wrapper.arw-left .bubble:before {
|
||||
right: 100%;
|
||||
top: 50%;
|
||||
margin-top: -7px;
|
||||
border-top: 7px solid transparent;
|
||||
border-bottom: 7px solid transparent;
|
||||
border-right: 10.5px solid #990000; }
|
||||
/* line 32, ../sass/helpers/_bubbles.scss */
|
||||
.bubble-wrapper.arw-down .bubble:before {
|
||||
left: 50%;
|
||||
top: 100%;
|
||||
margin-left: -7px;
|
||||
border-left: 7px solid transparent;
|
||||
border-right: 7px solid transparent;
|
||||
border-top: 10.5px solid #990000; }
|
||||
/* line 21, ../sass/helpers/_bubbles.scss */
|
||||
.l-infobubble-wrapper .l-infobubble table {
|
||||
width: 100%; }
|
||||
/* line 24, ../sass/helpers/_bubbles.scss */
|
||||
.l-infobubble-wrapper .l-infobubble table tr td {
|
||||
padding: 2px 0;
|
||||
vertical-align: top; }
|
||||
/* line 31, ../sass/helpers/_bubbles.scss */
|
||||
.l-infobubble-wrapper .l-infobubble table tr td.label {
|
||||
padding-right: 10px;
|
||||
white-space: nowrap; }
|
||||
/* line 35, ../sass/helpers/_bubbles.scss */
|
||||
.l-infobubble-wrapper .l-infobubble table tr td.value {
|
||||
white-space: nowrap; }
|
||||
/* line 39, ../sass/helpers/_bubbles.scss */
|
||||
.l-infobubble-wrapper .l-infobubble table tr td.align-wrap {
|
||||
white-space: normal; }
|
||||
/* line 45, ../sass/helpers/_bubbles.scss */
|
||||
.l-infobubble-wrapper .l-infobubble .title {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
margin-bottom: 5px; }
|
||||
/* line 52, ../sass/helpers/_bubbles.scss */
|
||||
.l-infobubble-wrapper.arw-left {
|
||||
margin-left: 10px; }
|
||||
/* line 54, ../sass/helpers/_bubbles.scss */
|
||||
.l-infobubble-wrapper.arw-left .l-infobubble::before {
|
||||
right: 100%;
|
||||
border-top: 5px solid transparent;
|
||||
border-bottom: 5px solid transparent;
|
||||
border-right: 7.5px solid #dddddd; }
|
||||
/* line 62, ../sass/helpers/_bubbles.scss */
|
||||
.l-infobubble-wrapper.arw-right {
|
||||
margin-right: 10px; }
|
||||
/* line 64, ../sass/helpers/_bubbles.scss */
|
||||
.l-infobubble-wrapper.arw-right .l-infobubble::before {
|
||||
left: 100%;
|
||||
border-top: 5px solid transparent;
|
||||
border-bottom: 5px solid transparent;
|
||||
border-left: 7.5px solid #dddddd; }
|
||||
/* line 73, ../sass/helpers/_bubbles.scss */
|
||||
.l-infobubble-wrapper.arw-top .l-infobubble::before {
|
||||
top: 10px; }
|
||||
/* line 79, ../sass/helpers/_bubbles.scss */
|
||||
.l-infobubble-wrapper.arw-btm .l-infobubble::before {
|
||||
bottom: 10px; }
|
||||
/* line 84, ../sass/helpers/_bubbles.scss */
|
||||
.l-infobubble-wrapper.arw-down {
|
||||
margin-bottom: 10px; }
|
||||
/* line 86, ../sass/helpers/_bubbles.scss */
|
||||
.l-infobubble-wrapper.arw-down .l-infobubble::before {
|
||||
left: 50%;
|
||||
top: 100%;
|
||||
margin-left: -5px;
|
||||
border-left: 5px solid transparent;
|
||||
border-right: 5px solid transparent;
|
||||
border-top: 7.5px solid #dddddd; }
|
||||
|
||||
/* line 99, ../sass/helpers/_bubbles.scss */
|
||||
.s-infobubble {
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
-ms-border-radius: 3px;
|
||||
-o-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
background: #dddddd;
|
||||
color: #666666;
|
||||
font-size: 0.8rem; }
|
||||
/* line 105, ../sass/helpers/_bubbles.scss */
|
||||
.s-infobubble .title {
|
||||
color: #333333;
|
||||
font-weight: bold; }
|
||||
/* line 110, ../sass/helpers/_bubbles.scss */
|
||||
.s-infobubble tr td {
|
||||
border-top: 1px solid #c4c4c4;
|
||||
font-size: 0.9em; }
|
||||
/* line 114, ../sass/helpers/_bubbles.scss */
|
||||
.s-infobubble tr:first-child td {
|
||||
border-top: none; }
|
||||
/* line 118, ../sass/helpers/_bubbles.scss */
|
||||
.s-infobubble .value {
|
||||
color: #333333; }
|
||||
|
||||
/* line 8, ../sass/helpers/_splitter.scss */
|
||||
.split-layout .splitter {
|
||||
@ -2833,10 +2969,10 @@ input[type="text"] {
|
||||
.wait-spinner {
|
||||
display: block;
|
||||
position: absolute;
|
||||
-webkit-animation: rotation .6s infinite linear;
|
||||
-moz-animation: rotation .6s infinite linear;
|
||||
-o-animation: rotation .6s infinite linear;
|
||||
animation: rotation .6s infinite linear;
|
||||
-webkit-animation: rotation 0.6s infinite linear;
|
||||
-moz-animation: rotation 0.6s infinite linear;
|
||||
-o-animation: rotation 0.6s infinite linear;
|
||||
animation: rotation 0.6s infinite linear;
|
||||
border-color: rgba(0, 153, 204, 0.25);
|
||||
border-top-color: #0099cc;
|
||||
border-style: solid;
|
||||
@ -2875,10 +3011,10 @@ input[type="text"] {
|
||||
.treeview .wait-spinner {
|
||||
display: block;
|
||||
position: absolute;
|
||||
-webkit-animation: rotation .6s infinite linear;
|
||||
-moz-animation: rotation .6s infinite linear;
|
||||
-o-animation: rotation .6s infinite linear;
|
||||
animation: rotation .6s infinite linear;
|
||||
-webkit-animation: rotation 0.6s infinite linear;
|
||||
-moz-animation: rotation 0.6s infinite linear;
|
||||
-o-animation: rotation 0.6s infinite linear;
|
||||
animation: rotation 0.6s infinite linear;
|
||||
border-color: rgba(0, 153, 204, 0.25);
|
||||
border-top-color: #0099cc;
|
||||
border-style: solid;
|
||||
@ -2990,3 +3126,21 @@ input[type="text"] {
|
||||
.autoflow .l-autoflow-items .l-autoflow-col:first-child {
|
||||
border-left: none;
|
||||
padding-left: 0; }
|
||||
|
||||
/* Styles for the iframe EmbeddedPageController element */
|
||||
/* line 4, ../sass/_iframe.scss */
|
||||
.l-iframe iframe {
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 100%; }
|
||||
|
||||
/******************************** BROWSE */
|
||||
/* line 6, ../sass/_hide-non-functional.scss */
|
||||
.browse-mode .browse.top-bar {
|
||||
display: none; }
|
||||
/* line 11, ../sass/_hide-non-functional.scss */
|
||||
.browse-mode .browse-area.holder {
|
||||
top: 5px; }
|
||||
/* line 18, ../sass/_hide-non-functional.scss */
|
||||
.browse-mode .browse-area.holder > .contents.split-layout .object-browse-bar .t-btn.key-window {
|
||||
display: none; }
|
||||
|
Binary file not shown.
@ -2,7 +2,7 @@
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg>
|
||||
<metadata>
|
||||
Created by FontForge 20110222 at Thu Mar 19 18:28:43 2015
|
||||
Created by FontForge 20090622 at Tue Apr 28 20:52:23 2015
|
||||
By deploy user
|
||||
Copyright 2015 Adobe Systems Incorporated. All rights reserved.
|
||||
</metadata>
|
||||
@ -21,7 +21,7 @@ Copyright 2015 Adobe Systems Incorporated. All rights reserved.
|
||||
bbox="-33 -19 1143 787"
|
||||
underline-thickness="50"
|
||||
underline-position="-50"
|
||||
unicode-range="U+0020-2044"
|
||||
unicode-range="U+0020-U+2044"
|
||||
/>
|
||||
<missing-glyph horiz-adv-x="500"
|
||||
/>
|
||||
@ -129,7 +129,7 @@ v-356zM635 88v356h-83v-356h83z" />
|
||||
<glyph glyph-name="bracketleft" unicode="[" horiz-adv-x="742"
|
||||
d="M373 602l-238 -237l237 -237l236 238zM373 731q39 0 66 -28l270 -270q29 -28 29 -67.5t-29 -67.5l-271 -271q-26 -27 -66 -27q-41 0 -68 27l-271 271q-27 27 -27 67t27 67l271 271q28 28 69 28z" />
|
||||
<glyph glyph-name="backslash" unicode="\" horiz-adv-x="810"
|
||||
d="M806 0h-178l-228 265q-20 -6 -41 -6q-65 0 -111 47t-46 112q0 34 12 63l-214 251h178l139 -162q23 5 42 5q65 0 112 -46t47 -111q0 -30 -14 -65zM286 418q0 -31 21 -53t52 -22t53 22t22 53t-22 52t-53 21t-52 -21t-21 -52z" />
|
||||
d="M806 0h-178l-228 265q-19 -6 -41 -6q-65 0 -111 47t-46 112q0 34 12 63l-214 251h178l139 -162q23 5 42 5q65 0 112 -46t47 -111q0 -30 -14 -65zM286 418q0 -31 21 -53t52 -22t53 22t22 53t-22 52t-53 21t-52 -21t-21 -52z" />
|
||||
<glyph glyph-name="bracketright" unicode="]" horiz-adv-x="807"
|
||||
d="M128 237l-61 61q-27 27 -27 67t27 67l271 271q28 28 69 28q39 0 67 -28l61 -60l-85 -85l-43 44l-238 -237l44 -44zM683 494l61 -61q28 -28 28 -67.5t-28 -67.5l-271 -271q-27 -27 -67 -27q-41 0 -68 27l-61 62l84 84l45 -45l237 238l-44 44zM697 731h149l-731 -731h-148z
|
||||
" />
|
||||
@ -185,7 +185,7 @@ v-170z" />
|
||||
<glyph glyph-name="u" unicode="u" horiz-adv-x="809"
|
||||
d="M405 396l-397 -396h794zM740 732q29 0 49 -20t20 -49v-122q0 -29 -20 -49.5t-49 -20.5h-671q-29 0 -49 20.5t-20 49.5v122q0 29 20 49t49 20h671z" />
|
||||
<glyph glyph-name="v" unicode="v" horiz-adv-x="787"
|
||||
d="M394 202l-394 377h787q-63 -61 -194.5 -187t-198.5 -190z" />
|
||||
d="M394 202l-394 377h787z" />
|
||||
<glyph glyph-name="x" unicode="x" horiz-adv-x="726"
|
||||
d="M726 110q6 -6 6 -15t-6 -14l-72 -73q-6 -6 -15 -6t-14 6l-258 258l-257 -258q-6 -6 -15 -6t-15 6l-72 73q-6 5 -6 14t6 15l257 257l-257 258q-14 15 0 29l72 73q6 6 15 6t15 -6l257 -258l258 258q5 6 14 6t15 -6l72 -73q14 -14 0 -29l-257 -258z" />
|
||||
<glyph glyph-name="y" unicode="y" horiz-adv-x="806"
|
||||
@ -218,10 +218,12 @@ d="M656 750q39 0 66.5 -27.5t27.5 -66.5v-562q0 -39 -27.5 -66.5t-66.5 -27.5h-562q-
|
||||
<glyph glyph-name="egrave" unicode="è" horiz-adv-x="754"
|
||||
d="M703 703q47 -48 47 -116t-47 -117l-94 -94q-48 -48 -117 -48q-41 0 -84 24l-8 -9q28 -47 21.5 -104t-46.5 -97l-94 -94q-48 -48 -117 -48q-68 0 -116 48q-47 49 -47 117t47 116l94 94q47 47 115 47q47 0 85 -22l9 9q-28 47 -21.5 103.5t46.5 96.5l94 94q47 47 116 47
|
||||
q70 0 117 -47zM307 209q26 25 21 62l-41 -41q-14 -12 -30 -12q-15 0 -27 12q-12 10 -12 28t12 29l41 41h-14q-28 0 -48 -20l-94 -94q-20 -20 -20 -49t20 -49q21 -22 49 -22q29 0 50 22zM635 538q21 20 21 49t-21 49q-20 20 -49 20t-49 -20l-94 -94q-25 -24 -20 -62l41 41
|
||||
q10 12 28 12t29 -12q12 -12 12 -29q0 -14 -12 -28l-41 -41q3 0 7 -0.5t5 -0.5q29 0 50 22z" />
|
||||
q11 12 28 12q18 0 29 -12q12 -12 12 -29q0 -14 -12 -28l-41 -41q3 0 7 -0.5t5 -0.5q29 0 50 22z" />
|
||||
<glyph glyph-name="eacute" unicode="é"
|
||||
d="M188 235h-160q-28 67 -28 140q0 156 110 265.5t265 109.5q88 0 164 -37t129 -103h-105q-39 0 -66.5 -27.5t-27.5 -66.5v-92v-2h-188q-39 0 -66 -27t-27 -67v-92v-1zM564 516h160q26 -62 26 -141q0 -155 -109.5 -265t-265.5 -110q-86 0 -162.5 38t-128.5 103h104
|
||||
q39 0 66 27.5t27 66.5v93h2h186q39 0 66.5 27.5t27.5 66.5v94h1z" />
|
||||
<glyph glyph-name="ecircumflex" unicode="ê" horiz-adv-x="751"
|
||||
d="M376 750v-375h375v-235q0 -58 -41.5 -99t-99.5 -41h-469q-58 0 -99 41t-41 99v469q0 58 41 99.5t99 41.5h235zM470 750l281 -281h-281v281z" />
|
||||
<glyph glyph-name="fraction" unicode="⁄" horiz-adv-x="761"
|
||||
d="M380 751q158 0 269.5 -111.5t111.5 -268.5q0 -133 -82.5 -236.5t-209.5 -134.5l-4 491l-176 -490q-126 31 -207.5 134.5t-81.5 235.5q0 157 111.5 268.5t268.5 111.5zM168 488l55 20l-34 94l-56 -20zM410 530v100h-59v-100h59zM593 488l34 94l-55 20l-34 -94z" />
|
||||
<glyph glyph-name="H.002" horiz-adv-x="803"
|
||||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Binary file not shown.
Binary file not shown.
@ -1,32 +1,8 @@
|
||||
// General About dialog styling
|
||||
|
||||
.t-about {
|
||||
// Styling
|
||||
line-height: 120%;
|
||||
.s-description,
|
||||
.s-info {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.s-logo-holder {
|
||||
background: url($dirImgs + "bg-about-openmctweb.jpg") no-repeat center; // For OpenMCT Web.
|
||||
background-size: cover;
|
||||
}
|
||||
.s-logo {
|
||||
// @include txtShdwLarge(); // text-shadow doesn't work for svg
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
}
|
||||
.s-logo-openmctweb {
|
||||
background-image: url($dirImgs + 'logo-openmctweb-shdw.svg');
|
||||
}
|
||||
h1, h2 {
|
||||
color: #fff;
|
||||
font-weight: normal !important;
|
||||
}
|
||||
|
||||
.l-about {
|
||||
// Layout
|
||||
&.l-about.abs {
|
||||
&.abs {
|
||||
// top: 20px;
|
||||
overflow: auto;
|
||||
}
|
||||
@ -57,3 +33,54 @@
|
||||
}
|
||||
}
|
||||
|
||||
.s-about {
|
||||
// Styling
|
||||
line-height: 120%;
|
||||
|
||||
a {
|
||||
color: #84b3ff;
|
||||
}
|
||||
.s-description,
|
||||
.s-info {
|
||||
// font-size: 0.8em;
|
||||
}
|
||||
.s-logo-holder {
|
||||
background: url($dirImgs + "bg-about-openmctweb.jpg") no-repeat center; // For OpenMCT Web.
|
||||
background-size: cover;
|
||||
}
|
||||
.s-logo {
|
||||
// @include txtShdwLarge(); // text-shadow doesn't work for svg
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
}
|
||||
.s-logo-openmctweb {
|
||||
background-image: url($dirImgs + 'logo-openmctweb-shdw.svg');
|
||||
}
|
||||
.s-btn {
|
||||
line-height: 2em;
|
||||
}
|
||||
.l-licenses-software {
|
||||
.l-license-software {
|
||||
border-top: 1px solid $colorInteriorBorder;
|
||||
padding: 0.5em 0;
|
||||
&:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
em {
|
||||
color: darken($colorBodyFg, 20%);
|
||||
// margin-left: 2em;
|
||||
&:first-child {
|
||||
// margin-left: 0;
|
||||
}
|
||||
}
|
||||
h3 {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
.s-license-text {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,17 +1,23 @@
|
||||
.t-fixed-position {
|
||||
&.l-fixed-position {
|
||||
// @include test(red);
|
||||
// @include test(red);
|
||||
position: absolute;
|
||||
top: 0; right: 0; bottom: 0; left: 0;
|
||||
width: auto; height: auto;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: auto;
|
||||
height: auto;
|
||||
|
||||
.l-grid-holder {
|
||||
position: relative;
|
||||
height: 100%; width: 100%;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
.l-grid {
|
||||
// @include test(orange);
|
||||
// @include test(orange);
|
||||
position: absolute;
|
||||
height: 100%; width: 100%;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
}
|
||||
@ -35,12 +41,13 @@
|
||||
.l-fixed-position-image,
|
||||
.l-fixed-position-text {
|
||||
@include box-sizing(border-box);
|
||||
height: 100%; width: 100%;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.l-fixed-position-box {
|
||||
}
|
||||
|
||||
|
||||
.l-fixed-position-image {
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
@ -49,11 +56,11 @@
|
||||
|
||||
.l-fixed-position-text {
|
||||
@include txtShdwSubtle();
|
||||
border:1px solid transparent;
|
||||
border: 1px solid transparent;
|
||||
font-size: 0.8rem;
|
||||
$p: $interiorMarginSm;
|
||||
&.l-static-text {
|
||||
// overflow: auto;
|
||||
// overflow: auto;
|
||||
padding: $p;
|
||||
}
|
||||
&.l-telemetry {
|
||||
@ -66,12 +73,12 @@
|
||||
left: $p;
|
||||
}
|
||||
&.l-value {
|
||||
// @include test(blue);
|
||||
// @include test(blue);
|
||||
right: $p;
|
||||
left: auto;
|
||||
text-align: right;
|
||||
&.telem-only {
|
||||
// @include test(red);
|
||||
// @include test(red);
|
||||
left: $p;
|
||||
width: auto;
|
||||
}
|
||||
@ -107,8 +114,11 @@
|
||||
}
|
||||
|
||||
.l-fixed-position-item {
|
||||
&:not(.s-selected):hover {
|
||||
border: 1px dotted rgba($colorKey, 0.5);
|
||||
&:not(.s-selected) {
|
||||
border: 1px dotted rgba($colorKey, 0.75);
|
||||
&:hover {
|
||||
border: 1px dotted rgba($colorKey, 1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -18,7 +18,7 @@ body, html {
|
||||
}
|
||||
|
||||
em {
|
||||
color: rgba(white, 0.2);
|
||||
// color: rgba(white, 0.2); Removed this as a global setting
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@ -65,6 +65,12 @@ span {
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.codehilite {
|
||||
@extend .code;
|
||||
background-color: rgba(#fff, 0.1);
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.align-right {
|
||||
text-align: right;
|
||||
}
|
||||
@ -73,6 +79,10 @@ span {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.no-margin {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.colorKey {
|
||||
color: $colorKey;
|
||||
}
|
||||
|
25
platform/commonUI/general/res/sass/_hide-non-functional.scss
Normal file
25
platform/commonUI/general/res/sass/_hide-non-functional.scss
Normal file
@ -0,0 +1,25 @@
|
||||
// Styles to temporarily hide non-functional elements
|
||||
|
||||
/******************************** BROWSE */
|
||||
.browse-mode {
|
||||
.browse {
|
||||
&.top-bar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.browse-area.holder {
|
||||
// When .browse.top-bar is hidden, set the top of the browse-area holder
|
||||
top: $interiorMargin;
|
||||
> .contents.split-layout {
|
||||
// Don't pad in from top and bottom
|
||||
//top: 0; bottom: 0;
|
||||
.object-browse-bar {
|
||||
.t-btn.key-window {
|
||||
// Hide the Open in New Window button
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
9
platform/commonUI/general/res/sass/_iframe.scss
Normal file
9
platform/commonUI/general/res/sass/_iframe.scss
Normal file
@ -0,0 +1,9 @@
|
||||
/* Styles for the iframe EmbeddedPageController element */
|
||||
|
||||
.l-iframe {
|
||||
iframe {
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@
|
||||
@import "user-environ/layout";
|
||||
@import "fixed-position";
|
||||
@import "about";
|
||||
@import "text";
|
||||
@import "badges";
|
||||
@import "icons";
|
||||
@import "lists/tabular";
|
||||
@ -39,3 +40,5 @@
|
||||
@import "helpers/wait-spinner";
|
||||
@import "properties";
|
||||
@import "autoflow";
|
||||
@import "iframe";
|
||||
@import "hide-non-functional";
|
||||
|
35
platform/commonUI/general/res/sass/_text.scss
Normal file
35
platform/commonUI/general/res/sass/_text.scss
Normal file
@ -0,0 +1,35 @@
|
||||
// Styles for extended text copy
|
||||
|
||||
.abs.l-standalone {
|
||||
$d: 20%;
|
||||
padding: $d/4 $d;
|
||||
}
|
||||
|
||||
.s-text {
|
||||
font-size: 0.8em;
|
||||
ol, ul {
|
||||
list-style: square;
|
||||
margin-left: 1.5em;
|
||||
li {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
color: #fff;
|
||||
font-weight: normal !important;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
border-top: 1px solid $colorInteriorBorder;
|
||||
font-size: 1.5em;
|
||||
margin-top: 2em;
|
||||
padding-top: 1em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
}
|
@ -1,40 +1,122 @@
|
||||
.bubble-wrapper {
|
||||
$arwSize: 7px;
|
||||
$c: #990000;
|
||||
@include box-shadow(rgba(black, 0.4) 0 1px 5px);
|
||||
position: absolute;
|
||||
//top: 200px; left: 200px;
|
||||
z-index: 10;
|
||||
.bubble {
|
||||
@include border-radius($basicCr);
|
||||
display: inline-block;
|
||||
background: $c;
|
||||
color: lighten($c, 50%);
|
||||
font-size: 0.8rem;
|
||||
font-style: italic;
|
||||
max-width: 200px;
|
||||
padding: 4px 8px;
|
||||
&:before {
|
||||
content:"";
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
//************************************************* LAYOUT
|
||||
|
||||
$infoBubbleFg: #666;
|
||||
$infoBubbleBg: #ddd;
|
||||
|
||||
.l-infobubble-wrapper {
|
||||
$arwSize: 5px;
|
||||
@include box-shadow(rgba(black, 0.4) 0 1px 5px);
|
||||
position: absolute;
|
||||
z-index: 70;
|
||||
.l-infobubble {
|
||||
display: inline-block;
|
||||
max-width: 250px;
|
||||
padding: 5px 10px;
|
||||
&:before {
|
||||
content:"";
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
table {
|
||||
width: 100%;
|
||||
tr {
|
||||
td {
|
||||
//max-width: 150px;
|
||||
padding: 2px 0;
|
||||
vertical-align: top;
|
||||
//white-space: nowrap;
|
||||
//overflow: hidden;
|
||||
//text-overflow: ellipsis;
|
||||
&.label {
|
||||
padding-right: $interiorMargin * 2;
|
||||
white-space: nowrap;
|
||||
}
|
||||
&.value {
|
||||
white-space: nowrap;
|
||||
//width: 90%;
|
||||
}
|
||||
&.align-wrap {
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.title {
|
||||
@include ellipsize();
|
||||
margin-bottom: $interiorMargin;
|
||||
//max-width: 200px;
|
||||
}
|
||||
}
|
||||
&.arw-left .bubble:before {
|
||||
right: 100%;
|
||||
top: 50%; // 26px;
|
||||
margin-top: -1 * $arwSize;
|
||||
border-top: $arwSize solid transparent;
|
||||
border-bottom: $arwSize solid transparent;
|
||||
border-right: ($arwSize * 1.5) solid $c;
|
||||
}
|
||||
&.arw-down .bubble:before {
|
||||
left: 50%;
|
||||
top: 100%;
|
||||
margin-left: -1 * $arwSize;
|
||||
border-left: $arwSize solid transparent;
|
||||
border-right: $arwSize solid transparent;
|
||||
border-top: ($arwSize * 1.5) solid $c;
|
||||
}
|
||||
|
||||
&.arw-left {
|
||||
margin-left: $arwSize*2;
|
||||
.l-infobubble::before {
|
||||
right: 100%;
|
||||
border-top: $arwSize solid transparent;
|
||||
border-bottom: $arwSize solid transparent;
|
||||
border-right: ($arwSize * 1.5) solid $infoBubbleBg;
|
||||
}
|
||||
}
|
||||
|
||||
&.arw-right {
|
||||
margin-right: $arwSize*2;
|
||||
.l-infobubble::before {
|
||||
left: 100%;
|
||||
border-top: $arwSize solid transparent;
|
||||
border-bottom: $arwSize solid transparent;
|
||||
border-left: ($arwSize * 1.5) solid $infoBubbleBg;
|
||||
}
|
||||
}
|
||||
|
||||
&.arw-top {
|
||||
.l-infobubble::before {
|
||||
top: $arwSize * 2;
|
||||
}
|
||||
}
|
||||
|
||||
&.arw-btm {
|
||||
.l-infobubble::before {
|
||||
bottom: $arwSize * 2;
|
||||
}
|
||||
}
|
||||
|
||||
&.arw-down {
|
||||
margin-bottom: $arwSize*2;
|
||||
.l-infobubble::before {
|
||||
left: 50%;
|
||||
top: 100%;
|
||||
margin-left: -1 * $arwSize;
|
||||
border-left: $arwSize solid transparent;
|
||||
border-right: $arwSize solid transparent;
|
||||
border-top: ($arwSize * 1.5) solid $infoBubbleBg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//************************************************* LOOK AND FEEL
|
||||
|
||||
.s-infobubble {
|
||||
$emFg: darken($infoBubbleFg, 20%);
|
||||
@include border-radius($basicCr);
|
||||
background: $infoBubbleBg;
|
||||
color: $infoBubbleFg;
|
||||
font-size: 0.8rem;
|
||||
.title {
|
||||
color: $emFg;
|
||||
font-weight: bold;
|
||||
}
|
||||
tr {
|
||||
td {
|
||||
border-top: 1px solid darken($infoBubbleBg, 10%);
|
||||
font-size: 0.9em;
|
||||
}
|
||||
&:first-child td {
|
||||
border-top: none;
|
||||
}
|
||||
}
|
||||
.value {
|
||||
color: $emFg;
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
.items-holder {
|
||||
@include clearfix;
|
||||
overflow-y: auto;
|
||||
.contents { top: 0; }
|
||||
.contents {
|
||||
top: 0;
|
||||
}
|
||||
.item {
|
||||
&.grid-item {
|
||||
$d: $ueBrowseGridItemLg;
|
||||
@ -23,6 +25,9 @@
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.contents {
|
||||
top: $interiorMargin; right: $interiorMargin; bottom: $interiorMargin; left: $interiorMargin;
|
||||
}
|
||||
.bar {
|
||||
&.top-bar.abs {
|
||||
bottom: auto;
|
||||
|
@ -51,6 +51,11 @@
|
||||
}
|
||||
}
|
||||
.contents.l-dialog {
|
||||
$myM: $interiorMargin;
|
||||
top: $myM;
|
||||
right: $myM;
|
||||
bottom: $myM;
|
||||
left: $myM;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
@ -18,6 +18,13 @@
|
||||
>.object-holder.abs {
|
||||
top: $ohH + $interiorMarginSm;
|
||||
}
|
||||
.contents {
|
||||
$myM: $interiorMargin;
|
||||
top: $myM;
|
||||
right: $myM;
|
||||
bottom: $myM;
|
||||
left: $myM;
|
||||
}
|
||||
}
|
||||
|
||||
.edit-main .frame.child-frame.panel {
|
||||
|
@ -8,57 +8,26 @@
|
||||
}
|
||||
}
|
||||
|
||||
.holder-all {
|
||||
$myM: $interiorMarginSm;
|
||||
top: $myM;
|
||||
right: $myM;
|
||||
bottom: $myM;
|
||||
left: $myM;
|
||||
}
|
||||
|
||||
.browse-area,
|
||||
.edit-area,
|
||||
.editor {
|
||||
@include border-radius($basicCr * 1.5);
|
||||
position: absolute;
|
||||
.contents {
|
||||
// overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.user-environ {
|
||||
.browse-area,
|
||||
.edit-area,
|
||||
.editor {
|
||||
top: $bodyMargin + $ueTopBarH + ($interiorMargin);
|
||||
right: $bodyMargin;
|
||||
bottom: $bodyMargin + $ueFooterH + $interiorMargin;
|
||||
left: $bodyMargin;
|
||||
}
|
||||
|
||||
.edit-area {
|
||||
$tbH: $ueEditToolBarH;
|
||||
.tool-bar {
|
||||
bottom: auto;
|
||||
height: $tbH;
|
||||
line-height: $ueEditToolBarButtonH;
|
||||
}
|
||||
.work-area {
|
||||
top: $tbH + $interiorMargin * 2;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-bar {
|
||||
top: auto;
|
||||
right: $bodyMargin;
|
||||
bottom: $bodyMargin;
|
||||
left: $bodyMargin;
|
||||
height: $ueFooterH;
|
||||
.status-holder {
|
||||
right: $ueAppLogoW + $bodyMargin;
|
||||
}
|
||||
.app-logo {
|
||||
left: auto;
|
||||
width: $ueAppLogoW;
|
||||
}
|
||||
}
|
||||
.editor {
|
||||
@include border-radius($basicCr * 1.5);
|
||||
}
|
||||
|
||||
|
||||
.contents {
|
||||
$myM: $interiorMargin;
|
||||
$myM: 0; //$interiorMargin;
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
top: $myM;
|
||||
@ -101,6 +70,52 @@
|
||||
}
|
||||
}
|
||||
|
||||
.user-environ {
|
||||
.browse-area,
|
||||
.edit-area,
|
||||
.editor {
|
||||
top: $bodyMargin + $ueTopBarH + ($interiorMargin);
|
||||
right: $bodyMargin;
|
||||
bottom: $bodyMargin + $ueFooterH + $interiorMargin;
|
||||
left: $bodyMargin;
|
||||
}
|
||||
|
||||
.browse-area,
|
||||
.edit-area {
|
||||
> .contents {
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.edit-area {
|
||||
$tbH: $ueEditToolBarH;
|
||||
.tool-bar {
|
||||
bottom: auto;
|
||||
height: $tbH;
|
||||
line-height: $ueEditToolBarButtonH;
|
||||
}
|
||||
.work-area {
|
||||
top: $tbH + $interiorMargin * 2;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-bar {
|
||||
top: auto;
|
||||
right: $bodyMargin;
|
||||
bottom: $bodyMargin;
|
||||
left: $bodyMargin;
|
||||
height: $ueFooterH;
|
||||
.status-holder {
|
||||
right: $ueAppLogoW + $bodyMargin;
|
||||
}
|
||||
.app-logo {
|
||||
left: auto;
|
||||
width: $ueAppLogoW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cols {
|
||||
@include clearfix;
|
||||
.col {
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
&.browse,
|
||||
&.edit {
|
||||
border-bottom: 1px solid $colorInteriorBorder;
|
||||
top: $bodyMargin; right: $bodyMargin; bottom: auto; left: $bodyMargin;
|
||||
height: $ueTopBarH;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
<a class="t-btn l-btn s-btn s-icon-btn s-very-subtle"
|
||||
<a class="t-btn l-btn s-btn s-icon-btn s-very-subtle key-{{parameters.action.getMetadata().key}}"
|
||||
ng-class="{ labeled: parameters.labeled }"
|
||||
title="{{parameters.action.getMetadata().description}}"
|
||||
ng-click="parameters.action.perform()">
|
||||
|
21
platform/commonUI/inspect/bundle.json
Normal file
21
platform/commonUI/inspect/bundle.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"extensions": {
|
||||
"types": [
|
||||
{
|
||||
"key": "infobubble",
|
||||
"name": "Info Bubble",
|
||||
"glyph": "\u00EA",
|
||||
"description": "Static markup for info bubbles",
|
||||
"features": [ "creation" ]
|
||||
}
|
||||
],
|
||||
"views": [
|
||||
{
|
||||
"templateUrl": "infobubble.html",
|
||||
"name": "Info Bubble",
|
||||
"type": "infobubble",
|
||||
"key": "infobubble"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
50
platform/commonUI/inspect/res/infobubble.html
Normal file
50
platform/commonUI/inspect/res/infobubble.html
Normal file
@ -0,0 +1,50 @@
|
||||
<div ng-init="
|
||||
bubbles = [
|
||||
{layout: 'arw-top arw-left'},
|
||||
{layout: 'arw-top arw-right'},
|
||||
{layout: 'arw-btm arw-left'},
|
||||
{layout: 'arw-btm arw-right'}
|
||||
];
|
||||
|
||||
titlex='Egress Scenario scelerisque mauris pid montes nunc ut aliquam elementum tincidunt phasellus 1';
|
||||
title='Egress Scenario 1';
|
||||
|
||||
propertiesShort=[{label:'Type', value:'Timeline', align:'left'},
|
||||
{label:'Start', value:'2015-04-27 00:00:00 UTC', align:'left'},
|
||||
{label:'End', value:'2015-04-27 09:15:37 UTC', align:'left'},
|
||||
{label:'ID', value:'WRP-T-89', align:'left'}];
|
||||
|
||||
properties=[{label:'Type', value:'Timeline', align:'left'},
|
||||
{label:'Start', value:'2015-04-27 00:00:00 UTC', align:'left'},
|
||||
{label:'End', value:'2015-04-27 06:07:26 UTC', align:'left'},
|
||||
{label:'Duration', value:'06:07:26', align:'left'},
|
||||
{label:'Created', value:'2015-04-26 12:27:00 UTC', align:'left'},
|
||||
{label:'Modified', value:'2015-04-26 23:21:00 UTC', align:'left'},
|
||||
{label:'Status', value:'Up to date', align:'left'},
|
||||
{label:'URL', value:'http://www.logitech.com/en-us/product/bluetooth-mouse-m557?crid=7', align:'wrap'},
|
||||
{label:'Description', value:'Enjoy exceptional battery life for a Bluetooth mouse, and work for up to a full year between battery changes, An On/Off switch helps conserve power, smart sleep mode extends battery life, and an indicator light helps to ensure that you’ll never be caught off guard.', align:'wrap'},
|
||||
{label:'ID', value:'WRP-T-89', align:'left'}];
|
||||
"></div>
|
||||
|
||||
|
||||
<div
|
||||
style="position: absolute"
|
||||
ng-repeat="bubble in bubbles"
|
||||
ng-style="{left: $index * 300 + 'px'}"
|
||||
>
|
||||
<div class="t-infobubble s-infobubble l-infobubble-wrapper {{bubble.layout}}">
|
||||
<div class="l-infobubble">
|
||||
<div
|
||||
ng-show="title.length > 0"
|
||||
class="title"
|
||||
>{{title}}
|
||||
</div>
|
||||
<table>
|
||||
<tr ng-repeat="property in properties">
|
||||
<td class="label">{{property.label}}</td>
|
||||
<td title="{{property.value}}" class="value align-{{property.align}}">{{property.value}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -7,6 +7,11 @@
|
||||
"depends": [ "$injector" ],
|
||||
"message": "Objects of this type cannot contain objects of that type."
|
||||
},
|
||||
{
|
||||
"category": "composition",
|
||||
"implementation": "CompositionMutabilityPolicy.js",
|
||||
"message": "Objects of this type cannot be modified."
|
||||
},
|
||||
{
|
||||
"category": "action",
|
||||
"implementation": "ComposeActionPolicy.js",
|
||||
|
30
platform/containment/src/CompositionMutabilityPolicy.js
Normal file
30
platform/containment/src/CompositionMutabilityPolicy.js
Normal file
@ -0,0 +1,30 @@
|
||||
/*global define*/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Disallow composition changes to objects which are not mutable.
|
||||
* @constructor
|
||||
*/
|
||||
function CompositionMutabilityPolicy() {
|
||||
return {
|
||||
/**
|
||||
* Is the type identified by the candidate allowed to
|
||||
* contain the type described by the context?
|
||||
* @param {Type} candidate the type of domain object
|
||||
*/
|
||||
allow: function (candidate) {
|
||||
// Equate creatability with mutability; that is, users
|
||||
// can only modify objects of types they can create, and
|
||||
// vice versa.
|
||||
return candidate.hasFeature('creation');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return CompositionMutabilityPolicy;
|
||||
}
|
||||
);
|
26
platform/containment/test/CompositionMutabilityPolicySpec.js
Normal file
26
platform/containment/test/CompositionMutabilityPolicySpec.js
Normal file
@ -0,0 +1,26 @@
|
||||
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
["../src/CompositionMutabilityPolicy"],
|
||||
function (CompositionMutabilityPolicy) {
|
||||
"use strict";
|
||||
|
||||
describe("The composition mutability policy", function () {
|
||||
var mockType,
|
||||
policy;
|
||||
|
||||
beforeEach(function () {
|
||||
mockType = jasmine.createSpyObj('type', ['hasFeature']);
|
||||
policy = new CompositionMutabilityPolicy();
|
||||
});
|
||||
|
||||
it("only allows composition for types which will have a composition capability", function () {
|
||||
expect(policy.allow(mockType)).toBeFalsy();
|
||||
mockType.hasFeature.andReturn(true);
|
||||
expect(policy.allow(mockType)).toBeTruthy();
|
||||
expect(mockType.hasFeature).toHaveBeenCalledWith('creation');
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
);
|
@ -1,6 +1,7 @@
|
||||
[
|
||||
"CapabilityTable",
|
||||
"ComposeActionPolicy",
|
||||
"CompositionMutabilityPolicy",
|
||||
"CompositionPolicy",
|
||||
"ContainmentTable"
|
||||
]
|
@ -5,7 +5,7 @@
|
||||
"views": [
|
||||
{
|
||||
"key": "layout",
|
||||
"name": "Layout",
|
||||
"name": "Display Layout",
|
||||
"glyph": "L",
|
||||
"type": "layout",
|
||||
"templateUrl": "templates/layout.html",
|
||||
@ -197,7 +197,7 @@
|
||||
"types": [
|
||||
{
|
||||
"key": "layout",
|
||||
"name": "Layout",
|
||||
"name": "Display Layout",
|
||||
"glyph": "L",
|
||||
"description": "A layout in which multiple telemetry panels may be displayed.",
|
||||
"features": "creation",
|
||||
|
37
platform/features/pages/bundle.json
Normal file
37
platform/features/pages/bundle.json
Normal file
@ -0,0 +1,37 @@
|
||||
{
|
||||
"extensions": {
|
||||
"types": [
|
||||
{
|
||||
"key": "example.page",
|
||||
"name": "Web Page",
|
||||
"glyph": "\u00EA",
|
||||
"description": "A component to display a web page or image with a valid URL. Can be added to a Display Layout.",
|
||||
"features": [ "creation" ],
|
||||
"properties": [
|
||||
{
|
||||
"key": "url",
|
||||
"name": "URL",
|
||||
"control": "textfield",
|
||||
"pattern": "^(ftp|https?)\\:\\/\\/\\w+(\\.\\w+)*(\\:\\d+)?(\\/\\S*)*$",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"views": [
|
||||
{
|
||||
"templateUrl": "iframe.html",
|
||||
"name": "Page",
|
||||
"type": "example.page",
|
||||
"key": "example.page"
|
||||
}
|
||||
],
|
||||
"controllers": [
|
||||
{
|
||||
"key": "EmbeddedPageController",
|
||||
"implementation": "EmbeddedPageController.js",
|
||||
"depends": ["$sce"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
5
platform/features/pages/res/iframe.html
Normal file
5
platform/features/pages/res/iframe.html
Normal file
@ -0,0 +1,5 @@
|
||||
<div class="abs l-iframe">
|
||||
<iframe ng-controller="EmbeddedPageController as ctl"
|
||||
ng-src="{{ctl.trust(model.url)}}">
|
||||
</iframe>
|
||||
</div>
|
26
platform/features/pages/src/EmbeddedPageController.js
Normal file
26
platform/features/pages/src/EmbeddedPageController.js
Normal file
@ -0,0 +1,26 @@
|
||||
/*global define*/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Controller for embedded web pages; serves simply as a
|
||||
* wrapper for `$sce` to mark pages as trusted.
|
||||
*/
|
||||
function EmbeddedPageController($sce) {
|
||||
return {
|
||||
/**
|
||||
* Alias of `$sce.trustAsResourceUrl`.
|
||||
*/
|
||||
trust: function (url) {
|
||||
return $sce.trustAsResourceUrl(url);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return EmbeddedPageController;
|
||||
}
|
||||
|
||||
);
|
37
platform/features/pages/test/EmbeddedPageControllerSpec.js
Normal file
37
platform/features/pages/test/EmbeddedPageControllerSpec.js
Normal file
@ -0,0 +1,37 @@
|
||||
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
["../src/EmbeddedPageController"],
|
||||
function (EmbeddedPageController) {
|
||||
"use strict";
|
||||
|
||||
describe("The controller for embedded pages", function () {
|
||||
var mockSCE,
|
||||
controller;
|
||||
|
||||
beforeEach(function () {
|
||||
mockSCE = jasmine.createSpyObj(
|
||||
'$sce',
|
||||
["trustAsResourceUrl"]
|
||||
);
|
||||
|
||||
mockSCE.trustAsResourceUrl.andCallFake(function (v) {
|
||||
return v;
|
||||
});
|
||||
|
||||
controller = new EmbeddedPageController(mockSCE);
|
||||
});
|
||||
|
||||
it("allows URLs to be marked as trusted", function () {
|
||||
var testURL = "http://www.nasa.gov";
|
||||
|
||||
expect(controller.trust(testURL))
|
||||
.toEqual(testURL);
|
||||
|
||||
expect(mockSCE.trustAsResourceUrl)
|
||||
.toHaveBeenCalledWith(testURL);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
3
platform/features/pages/test/suite.json
Normal file
3
platform/features/pages/test/suite.json
Normal file
@ -0,0 +1,3 @@
|
||||
[
|
||||
"EmbeddedPageController"
|
||||
]
|
@ -22,7 +22,7 @@
|
||||
{
|
||||
"key": "PlotController",
|
||||
"implementation": "PlotController.js",
|
||||
"depends": [ "$scope", "telemetryFormatter", "telemetrySubscriber" ]
|
||||
"depends": [ "$scope", "telemetryFormatter", "telemetryHandler" ]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -30,13 +30,13 @@ define(
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function PlotController($scope, telemetryFormatter, telemetrySubscriber) {
|
||||
function PlotController($scope, telemetryFormatter, telemetryHandler) {
|
||||
var subPlotFactory = new SubPlotFactory(telemetryFormatter),
|
||||
modeOptions = new PlotModeOptions([], subPlotFactory),
|
||||
subplots = [],
|
||||
cachedObjects = [],
|
||||
updater,
|
||||
subscription,
|
||||
handle,
|
||||
domainOffset;
|
||||
|
||||
// Populate the scope with axis information (specifically, options
|
||||
@ -77,7 +77,7 @@ define(
|
||||
// new subscription.) This will clear the plot.
|
||||
function recreateUpdater() {
|
||||
updater = new PlotUpdater(
|
||||
subscription,
|
||||
handle,
|
||||
($scope.axes[0].active || {}).key,
|
||||
($scope.axes[1].active || {}).key
|
||||
);
|
||||
@ -85,8 +85,8 @@ define(
|
||||
|
||||
// Handle new telemetry data in this plot
|
||||
function updateValues() {
|
||||
if (subscription) {
|
||||
setupModes(subscription.getTelemetryObjects());
|
||||
if (handle) {
|
||||
setupModes(handle.getTelemetryObjects());
|
||||
}
|
||||
if (updater) {
|
||||
updater.update();
|
||||
@ -95,29 +95,44 @@ define(
|
||||
update();
|
||||
}
|
||||
|
||||
// Display new historical data as it becomes available
|
||||
function addHistoricalData(domainObject, series) {
|
||||
updater.addHistorical(domainObject, series);
|
||||
modeOptions.getModeHandler().plotTelemetry(updater);
|
||||
update();
|
||||
}
|
||||
|
||||
// Issue a new request for historical telemetry
|
||||
function requestTelemetry() {
|
||||
if (handle && updater) {
|
||||
handle.request({}, addHistoricalData);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new subscription; telemetrySubscriber gets
|
||||
// to do the meaningful work here.
|
||||
function subscribe(domainObject) {
|
||||
if (subscription) {
|
||||
subscription.unsubscribe();
|
||||
if (handle) {
|
||||
handle.unsubscribe();
|
||||
}
|
||||
subscription = domainObject && telemetrySubscriber.subscribe(
|
||||
handle = domainObject && telemetryHandler.handle(
|
||||
domainObject,
|
||||
updateValues,
|
||||
true // Lossless
|
||||
);
|
||||
if (subscription) {
|
||||
setupModes(subscription.getTelemetryObjects());
|
||||
setupAxes(subscription.getMetadata());
|
||||
if (handle) {
|
||||
setupModes(handle.getTelemetryObjects());
|
||||
setupAxes(handle.getMetadata());
|
||||
recreateUpdater();
|
||||
requestTelemetry();
|
||||
}
|
||||
}
|
||||
|
||||
// Release the current subscription (called when scope is destroyed)
|
||||
function releaseSubscription() {
|
||||
if (subscription) {
|
||||
subscription.unsubscribe();
|
||||
subscription = undefined;
|
||||
if (handle) {
|
||||
handle.unsubscribe();
|
||||
handle = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
94
platform/features/plot/src/elements/PlotLine.js
Normal file
94
platform/features/plot/src/elements/PlotLine.js
Normal file
@ -0,0 +1,94 @@
|
||||
/*global define,Float32Array*/
|
||||
|
||||
define(
|
||||
['./PlotSeriesWindow'],
|
||||
function (PlotSeriesWindow) {
|
||||
"use strict";
|
||||
|
||||
|
||||
function PlotLine(buffer) {
|
||||
|
||||
// Insert a time-windowed data series into the buffer
|
||||
function insertSeriesWindow(seriesWindow) {
|
||||
var count = seriesWindow.getPointCount();
|
||||
|
||||
function doInsert() {
|
||||
var firstTimestamp = seriesWindow.getDomainValue(0),
|
||||
lastTimestamp = seriesWindow.getDomainValue(count - 1),
|
||||
startIndex = buffer.findInsertionIndex(firstTimestamp),
|
||||
endIndex = buffer.findInsertionIndex(lastTimestamp);
|
||||
|
||||
// Does the whole series fit in between two adjacent indexes?
|
||||
if ((startIndex === endIndex) && startIndex > -1) {
|
||||
// Insert it in between
|
||||
buffer.insert(seriesWindow, startIndex);
|
||||
} else {
|
||||
// Split it up, and add the two halves
|
||||
seriesWindow.split().forEach(insertSeriesWindow);
|
||||
}
|
||||
}
|
||||
|
||||
// Only insert if there are points to insert
|
||||
if (count > 0) {
|
||||
doInsert();
|
||||
}
|
||||
}
|
||||
|
||||
function createWindow(series, domain, range) {
|
||||
return new PlotSeriesWindow(
|
||||
series,
|
||||
domain,
|
||||
range,
|
||||
0,
|
||||
series.getPointCount()
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* Add a point to this plot line.
|
||||
* @param {number} domainValue the domain value
|
||||
* @param {number} rangeValue the range value
|
||||
*/
|
||||
addPoint: function (domainValue, rangeValue) {
|
||||
var index;
|
||||
// Make sure we got real/useful values here...
|
||||
if (domainValue !== undefined && rangeValue !== undefined) {
|
||||
index = buffer.findInsertionIndex(domainValue);
|
||||
|
||||
// Already in the buffer? Skip insertion
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Insert the point
|
||||
if (!buffer.insertPoint(domainValue, rangeValue, index)) {
|
||||
// If insertion failed, trim from the beginning...
|
||||
buffer.trim(1);
|
||||
// ...and try again.
|
||||
buffer.insertPoint(domainValue, rangeValue, index);
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Add a series of telemetry data to this plot line.
|
||||
* @param {TelemetrySeries} series the data series
|
||||
* @param {string} [domain] the key indicating which domain
|
||||
* to use when looking up data from this series
|
||||
* @param {string} [range] the key indicating which range
|
||||
* to use when looking up data from this series
|
||||
*/
|
||||
addSeries: function (series, domain, range) {
|
||||
// Should try to add via insertion if a
|
||||
// clear insertion point is available;
|
||||
// if not, should split and add each half.
|
||||
// Insertion operation also needs to factor out
|
||||
// redundant timestamps, for overlapping data
|
||||
insertSeriesWindow(createWindow(series, domain, range));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return PlotLine;
|
||||
}
|
||||
);
|
240
platform/features/plot/src/elements/PlotLineBuffer.js
Normal file
240
platform/features/plot/src/elements/PlotLineBuffer.js
Normal file
@ -0,0 +1,240 @@
|
||||
/*global define,Float32Array*/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Contains the buffer used to draw a plot.
|
||||
* @param {number} domainOffset number to subtract from domain values
|
||||
* @param {number} initialSize initial buffer size
|
||||
* @param {number} maxSize maximum buffer size
|
||||
* @constructor
|
||||
*/
|
||||
function PlotLineBuffer(domainOffset, initialSize, maxSize) {
|
||||
var buffer = new Float32Array(initialSize * 2),
|
||||
rangeExtrema = [ Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY ],
|
||||
length = 0;
|
||||
|
||||
// Binary search for an insertion index
|
||||
function binSearch(value, min, max) {
|
||||
var mid = Math.floor((min + max) / 2),
|
||||
found = buffer[mid * 2];
|
||||
|
||||
// Collisions are not wanted
|
||||
if (found === value) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Otherwise, if we're down to a single index,
|
||||
// we've found our insertion point
|
||||
if (min >= max) {
|
||||
// Compare the found timestamp with the search
|
||||
// value to decide if we'll insert after or before.
|
||||
return min + ((found < value) ? 1 : 0);
|
||||
}
|
||||
|
||||
// Finally, do the recursive step
|
||||
if (found < value) {
|
||||
return binSearch(value, mid + 1, max);
|
||||
} else {
|
||||
return binSearch(value, min, mid - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Increase the size of the buffer
|
||||
function doubleBufferSize() {
|
||||
var sz = Math.min(maxSize * 2, buffer.length * 2),
|
||||
canDouble = sz > buffer.length,
|
||||
doubled = canDouble && new Float32Array(sz);
|
||||
|
||||
if (canDouble) {
|
||||
doubled.set(buffer); // Copy contents of original
|
||||
buffer = doubled;
|
||||
}
|
||||
|
||||
return canDouble;
|
||||
}
|
||||
|
||||
// Decrease the size of the buffer
|
||||
function halveBufferSize() {
|
||||
var sz = Math.max(initialSize * 2, buffer.length / 2),
|
||||
canHalve = sz < buffer.length;
|
||||
|
||||
if (canHalve) {
|
||||
buffer = new Float32Array(buffer.subarray(0, sz));
|
||||
}
|
||||
|
||||
return canHalve;
|
||||
}
|
||||
|
||||
// Set a value in the buffer
|
||||
function setValue(index, domainValue, rangeValue) {
|
||||
buffer[index * 2] = domainValue - domainOffset;
|
||||
buffer[index * 2 + 1] = rangeValue;
|
||||
// Track min/max of range values (min/max for
|
||||
// domain values can be read directly from buffer)
|
||||
rangeExtrema[0] = Math.min(rangeExtrema[0], rangeValue);
|
||||
rangeExtrema[1] = Math.max(rangeExtrema[1], rangeValue);
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* Get the WebGL-displayable buffer of points to plot.
|
||||
* @returns {Float32Array} displayable buffer for this line
|
||||
*/
|
||||
getBuffer: function () {
|
||||
return buffer;
|
||||
},
|
||||
/**
|
||||
* Get the number of points stored in this buffer.
|
||||
* @returns {number} the number of points stored
|
||||
*/
|
||||
getLength: function () {
|
||||
return length;
|
||||
},
|
||||
/**
|
||||
* Get the min/max range values that are currently in this
|
||||
* buffer. Unlike range extrema, these will change as the
|
||||
* buffer gets trimmed.
|
||||
* @returns {number[]} min, max domain values
|
||||
*/
|
||||
getDomainExtrema: function () {
|
||||
// Since these are ordered in the buffer, assume
|
||||
// these are the values at the first and last index
|
||||
return [
|
||||
buffer[0] + domainOffset,
|
||||
buffer[length * 2 - 2] + domainOffset
|
||||
];
|
||||
},
|
||||
/**
|
||||
* Get the min/max range values that have been observed for this
|
||||
* buffer. Note that these values may have been trimmed out at
|
||||
* some point.
|
||||
* @returns {number[]} min, max range values
|
||||
*/
|
||||
getRangeExtrema: function () {
|
||||
return rangeExtrema;
|
||||
},
|
||||
/**
|
||||
* Remove values from this buffer.
|
||||
* Normally, values are removed from the start
|
||||
* of the buffer; a truthy value in the second argument
|
||||
* will cause values to be removed from the end.
|
||||
* @param {number} count number of values to remove
|
||||
* @param {boolean} [fromEnd] true if the most recent
|
||||
* values should be removed
|
||||
*/
|
||||
trim: function (count, fromEnd) {
|
||||
// If we're removing values from the start...
|
||||
if (!fromEnd) {
|
||||
// ...do so by shifting buffer contents over
|
||||
buffer.set(buffer.subarray(2 * count));
|
||||
}
|
||||
// Reduce used buffer size accordingly
|
||||
length -= count;
|
||||
// Finally, if less than half of the buffer is being
|
||||
// used, free up some memory.
|
||||
if (length < buffer.length / 4) {
|
||||
halveBufferSize();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Insert data from the provided series at the specified
|
||||
* index. If this would exceed the buffer's maximum capacity,
|
||||
* this operation fails and the buffer is unchanged.
|
||||
* @param {TelemetrySeries} series the series to insert
|
||||
* @param {number} index the index at which to insert this
|
||||
* series
|
||||
* @returns {boolean} true if insertion succeeded; otherwise
|
||||
* false
|
||||
*/
|
||||
insert: function (series, index) {
|
||||
var sz = series.getPointCount(),
|
||||
i;
|
||||
|
||||
// Don't allow append after the end; that doesn't make sense
|
||||
index = Math.min(index, length);
|
||||
|
||||
// Resize if necessary
|
||||
while (sz > ((buffer.length / 2) - length)) {
|
||||
if (!doubleBufferSize()) {
|
||||
// Can't make room for this, insertion fails
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Shift data over if necessary
|
||||
if (index < length) {
|
||||
buffer.set(
|
||||
buffer.subarray(index * 2, length * 2),
|
||||
(index + sz) * 2
|
||||
);
|
||||
}
|
||||
|
||||
// Insert data into the set
|
||||
for (i = 0; i < sz; i += 1) {
|
||||
setValue(
|
||||
i + index,
|
||||
series.getDomainValue(i),
|
||||
series.getRangeValue(i)
|
||||
);
|
||||
}
|
||||
|
||||
// Increase the length
|
||||
length += sz;
|
||||
|
||||
// Indicate that insertion was successful
|
||||
return true;
|
||||
},
|
||||
/**
|
||||
* Append a single data point.
|
||||
*/
|
||||
insertPoint: function (domainValue, rangeValue, index) {
|
||||
// Don't allow
|
||||
index = Math.min(length, index);
|
||||
|
||||
// Ensure there is space for this point
|
||||
if (length >= (buffer.length / 2)) {
|
||||
if (!doubleBufferSize()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Put the data in the buffer
|
||||
setValue(length, domainValue, rangeValue);
|
||||
|
||||
// Update length
|
||||
length += 1;
|
||||
|
||||
// Indicate that this was successful
|
||||
return true;
|
||||
},
|
||||
/**
|
||||
* Find an index for inserting data with this
|
||||
* timestamp. The second argument indicates whether
|
||||
* we are searching for insert-before or insert-after
|
||||
* positions.
|
||||
* Timestamps are meant to be unique, so if a collision
|
||||
* occurs, this will return -1.
|
||||
* @param {number} timestamp timestamp to insert
|
||||
* @returns {number} the index for insertion (or -1)
|
||||
*/
|
||||
findInsertionIndex: function (timestamp) {
|
||||
var value = timestamp - domainOffset;
|
||||
|
||||
// Handle empty buffer case and check for an
|
||||
// append opportunity (which is most common case for
|
||||
// real-time data so is optimized-for) before falling
|
||||
// back to a binary search for the insertion point.
|
||||
return (length < 1) ? 0 :
|
||||
(value > buffer[length * 2 - 2]) ? length :
|
||||
binSearch(value, 0, length - 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return PlotLineBuffer;
|
||||
}
|
||||
);
|
47
platform/features/plot/src/elements/PlotSeriesWindow.js
Normal file
47
platform/features/plot/src/elements/PlotSeriesWindow.js
Normal file
@ -0,0 +1,47 @@
|
||||
/*global define*/
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Provides a window on a telemetry data series, to support
|
||||
* insertion into a plot line.
|
||||
*/
|
||||
function PlotSeriesWindow(series, domain, range, start, end) {
|
||||
return {
|
||||
getPointCount: function () {
|
||||
return end - start;
|
||||
},
|
||||
getDomainValue: function (index) {
|
||||
return series.getDomainValue(index + start, domain);
|
||||
},
|
||||
getRangeValue: function (index) {
|
||||
return series.getRangeValue(index + start, range);
|
||||
},
|
||||
split: function () {
|
||||
var mid = Math.floor((end + start) / 2);
|
||||
return ((end - start) > 1) ?
|
||||
[
|
||||
new PlotSeriesWindow(
|
||||
series,
|
||||
domain,
|
||||
range,
|
||||
start,
|
||||
mid
|
||||
),
|
||||
new PlotSeriesWindow(
|
||||
series,
|
||||
domain,
|
||||
range,
|
||||
mid,
|
||||
end
|
||||
)
|
||||
] : [];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return PlotSeriesWindow;
|
||||
}
|
||||
);
|
@ -5,7 +5,8 @@
|
||||
* the conversion from data API to displayable buffers.
|
||||
*/
|
||||
define(
|
||||
function () {
|
||||
['./PlotLine', './PlotLineBuffer'],
|
||||
function (PlotLine, PlotLineBuffer) {
|
||||
'use strict';
|
||||
|
||||
var MAX_POINTS = 86400,
|
||||
@ -17,117 +18,182 @@ define(
|
||||
* Float32Array for each trace, and tracks the boundaries of the
|
||||
* data sets (since this is convenient to do during the same pass).
|
||||
* @constructor
|
||||
* @param {Telemetry[]} datas telemetry data objects
|
||||
* @param {TelemetryHandle} handle the handle to telemetry access
|
||||
* @param {string} domain the key to use when looking up domain values
|
||||
* @param {string} range the key to use when looking up range values
|
||||
*/
|
||||
function PlotUpdater(subscription, domain, range, maxPoints) {
|
||||
var max = [Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
|
||||
min = [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
|
||||
x,
|
||||
y,
|
||||
domainOffset,
|
||||
buffers = {},
|
||||
lengths = {},
|
||||
lengthArray = [],
|
||||
bufferArray = [];
|
||||
function PlotUpdater(handle, domain, range, maxPoints) {
|
||||
var ids = [],
|
||||
lines = {},
|
||||
dimensions = [0, 0],
|
||||
origin = [0, 0],
|
||||
domainExtrema,
|
||||
rangeExtrema,
|
||||
bufferArray = [],
|
||||
domainOffset;
|
||||
|
||||
// Double the size of a Float32Array
|
||||
function doubleSize(buffer) {
|
||||
var doubled = new Float32Array(buffer.length * 2);
|
||||
doubled.set(buffer); // Copy contents of original
|
||||
return doubled;
|
||||
// Look up a domain object's id (for mapping, below)
|
||||
function getId(domainObject) {
|
||||
return domainObject.getId();
|
||||
}
|
||||
|
||||
// Make sure there is enough space in a buffer to accomodate a
|
||||
// new point at the specified index. This will updates buffers[id]
|
||||
// if necessary.
|
||||
function ensureBufferSize(buffer, id, index) {
|
||||
// Check if we don't have enough room
|
||||
if (index > (buffer.length / 2 - 1)) {
|
||||
// If we don't, can we expand?
|
||||
if (index < maxPoints) {
|
||||
// Double the buffer size
|
||||
buffer = buffers[id] = doubleSize(buffer);
|
||||
} else {
|
||||
// Just shift the existing buffer
|
||||
buffer.set(buffer.subarray(2));
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
// Check if this set of ids matches the current set of ids
|
||||
// (used to detect if line preparation can be skipped)
|
||||
function idsMatch(nextIds) {
|
||||
return nextIds.map(function (id, index) {
|
||||
return ids[index] === id;
|
||||
}).reduce(function (a, b) {
|
||||
return a && b;
|
||||
}, true);
|
||||
}
|
||||
|
||||
// Add data to the plot.
|
||||
function addData(obj) {
|
||||
var id = obj.getId(),
|
||||
index = lengths[id] || 0,
|
||||
buffer = buffers[id],
|
||||
domainValue = subscription.getDomainValue(obj, domain),
|
||||
rangeValue = subscription.getRangeValue(obj, range);
|
||||
// Prepare plot lines for this group of telemetry objects
|
||||
function prepareLines(telemetryObjects) {
|
||||
var nextIds = telemetryObjects.map(getId),
|
||||
next = {};
|
||||
|
||||
// If we don't already have a data buffer for that ID,
|
||||
// make one.
|
||||
if (!buffer) {
|
||||
buffer = new Float32Array(INITIAL_SIZE);
|
||||
buffers[id] = buffer;
|
||||
// Detect if we already have everything we need prepared
|
||||
if (ids.length === nextIds.length && idsMatch(nextIds)) {
|
||||
// Nothing to prepare, move on
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure there's data to add, and then add it
|
||||
if (domainValue !== undefined && rangeValue !== undefined &&
|
||||
(index < 1 || domainValue !== buffer[index * 2 - 2])) {
|
||||
// Use the first observed domain value as a domainOffset
|
||||
domainOffset = domainOffset !== undefined ?
|
||||
domainOffset : domainValue;
|
||||
// Ensure there is space for the new buffer
|
||||
buffer = ensureBufferSize(buffer, id, index);
|
||||
// Account for shifting that may have occurred
|
||||
index = Math.min(index, maxPoints - 1);
|
||||
// Update the buffer
|
||||
buffer[index * 2] = domainValue - domainOffset;
|
||||
buffer[index * 2 + 1] = rangeValue;
|
||||
// Update length
|
||||
lengths[id] = Math.min(index + 1, maxPoints);
|
||||
// Observe max/min range values
|
||||
max[1] = Math.max(max[1], rangeValue);
|
||||
min[1] = Math.min(min[1], rangeValue);
|
||||
// Built up a set of ids. Note that we can only
|
||||
// create plot lines after our domain offset has
|
||||
// been determined.
|
||||
if (domainOffset !== undefined) {
|
||||
// Update list of ids in use
|
||||
ids = nextIds;
|
||||
|
||||
// Create buffers for these objects
|
||||
bufferArray = ids.map(function (id) {
|
||||
var buffer = new PlotLineBuffer(
|
||||
domainOffset,
|
||||
INITIAL_SIZE,
|
||||
maxPoints
|
||||
);
|
||||
next[id] = lines[id] || new PlotLine(buffer);
|
||||
return buffer;
|
||||
});
|
||||
}
|
||||
|
||||
return buffer;
|
||||
// If there are no more lines, clear the domain offset
|
||||
if (Object.keys(next).length < 1) {
|
||||
domainOffset = undefined;
|
||||
}
|
||||
|
||||
// Update to the current set of lines
|
||||
lines = next;
|
||||
}
|
||||
|
||||
// Update min/max domain values for these objects
|
||||
function updateDomainExtrema(objects) {
|
||||
max[0] = Number.NEGATIVE_INFINITY;
|
||||
min[0] = Number.POSITIVE_INFINITY;
|
||||
objects.forEach(function (obj) {
|
||||
var id = obj.getId(),
|
||||
buffer = buffers[id],
|
||||
length = lengths[id],
|
||||
low = buffer[0] + domainOffset,
|
||||
high = buffer[length * 2 - 2] + domainOffset;
|
||||
max[0] = Math.max(high, max[0]);
|
||||
min[0] = Math.min(low, min[0]);
|
||||
});
|
||||
// Initialize the domain offset, based on these observed values
|
||||
function initializeDomainOffset(values) {
|
||||
domainOffset =
|
||||
((domainOffset === undefined) && (values.length > 0)) ?
|
||||
(values.reduce(function (a, b) {
|
||||
return (a || 0) + (b || 0);
|
||||
}, 0) / values.length) :
|
||||
domainOffset;
|
||||
}
|
||||
|
||||
// Used in the reduce step of updateExtrema
|
||||
function reduceExtrema(a, b) {
|
||||
return [ Math.min(a[0], b[0]), Math.max(a[1], b[1]) ];
|
||||
}
|
||||
|
||||
// Convert a domain/range extrema to plot dimensions
|
||||
function dimensionsOf(extrema) {
|
||||
return extrema[1] - extrema[0];
|
||||
}
|
||||
|
||||
// Convert a domain/range extrema to a plot origin
|
||||
function originOf(extrema) {
|
||||
return extrema[0];
|
||||
}
|
||||
|
||||
// Update dimensions and origin based on extrema of plots
|
||||
function updateExtrema() {
|
||||
if (bufferArray.length > 0) {
|
||||
domainExtrema = bufferArray.map(function (lineBuffer) {
|
||||
return lineBuffer.getDomainExtrema();
|
||||
}).reduce(reduceExtrema);
|
||||
|
||||
rangeExtrema = bufferArray.map(function (lineBuffer) {
|
||||
return lineBuffer.getRangeExtrema();
|
||||
}).reduce(reduceExtrema);
|
||||
|
||||
dimensions = (rangeExtrema[0] === rangeExtrema[1]) ?
|
||||
[dimensionsOf(domainExtrema), 2.0 ] :
|
||||
[dimensionsOf(domainExtrema), dimensionsOf(rangeExtrema)];
|
||||
origin = [originOf(domainExtrema), originOf(rangeExtrema)];
|
||||
}
|
||||
}
|
||||
|
||||
// Add latest data for this domain object
|
||||
function addPointFor(domainObject) {
|
||||
var line = lines[domainObject.getId()];
|
||||
if (line) {
|
||||
line.addPoint(
|
||||
handle.getDomainValue(domainObject, domain),
|
||||
handle.getRangeValue(domainObject, range)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle new telemetry data
|
||||
function update() {
|
||||
var objects = subscription.getTelemetryObjects();
|
||||
bufferArray = objects.map(addData);
|
||||
lengthArray = objects.map(function (obj) {
|
||||
return lengths[obj.getId()];
|
||||
});
|
||||
updateDomainExtrema(objects);
|
||||
var objects = handle.getTelemetryObjects();
|
||||
|
||||
// Initialize domain offset if necessary
|
||||
if (domainOffset === undefined) {
|
||||
initializeDomainOffset(objects.map(function (obj) {
|
||||
return handle.getDomainValue(obj, domain);
|
||||
}).filter(function (value) {
|
||||
return typeof value === 'number';
|
||||
}));
|
||||
}
|
||||
|
||||
// Make sure lines are available
|
||||
prepareLines(objects);
|
||||
|
||||
// Add new data
|
||||
objects.forEach(addPointFor);
|
||||
|
||||
// Finally, update extrema
|
||||
updateExtrema();
|
||||
}
|
||||
|
||||
// Prepare buffers and related state for this object
|
||||
function prepare(telemetryObject) {
|
||||
var id = telemetryObject.getId();
|
||||
lengths[id] = 0;
|
||||
buffers[id] = new Float32Array(INITIAL_SIZE);
|
||||
lengthArray.push(lengths[id]);
|
||||
bufferArray.push(buffers[id]);
|
||||
// Add historical data for this domain object
|
||||
function setHistorical(domainObject, series) {
|
||||
var count = series ? series.getPointCount() : 0,
|
||||
line;
|
||||
|
||||
// Nothing to do if it's an empty series
|
||||
if (count < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize domain offset if necessary
|
||||
if (domainOffset === undefined) {
|
||||
initializeDomainOffset([
|
||||
series.getDomainValue(0, domain),
|
||||
series.getDomainValue(count - 1, domain)
|
||||
]);
|
||||
}
|
||||
|
||||
// Make sure lines are available
|
||||
prepareLines(handle.getTelemetryObjects());
|
||||
|
||||
// Look up the line for this domain object
|
||||
line = lines[domainObject.getId()];
|
||||
|
||||
// ...and put the data into it.
|
||||
if (line) {
|
||||
line.addSeries(series, domain, range);
|
||||
}
|
||||
|
||||
// Finally, update extrema
|
||||
updateExtrema();
|
||||
}
|
||||
|
||||
// Use a default MAX_POINTS if none is provided
|
||||
@ -136,7 +202,7 @@ define(
|
||||
// Initially prepare state for these objects.
|
||||
// Note that this may be an empty array at this time,
|
||||
// so we also need to check during update cycles.
|
||||
subscription.getTelemetryObjects().forEach(prepare);
|
||||
update();
|
||||
|
||||
return {
|
||||
/**
|
||||
@ -146,10 +212,7 @@ define(
|
||||
* @returns {number[]} the dimensions which bound this data set
|
||||
*/
|
||||
getDimensions: function () {
|
||||
// Pad range if necessary
|
||||
return (max[1] === min[1]) ?
|
||||
[max[0] - min[0], 2.0 ] :
|
||||
[max[0] - min[0], max[1] - min[1]];
|
||||
return dimensions;
|
||||
},
|
||||
/**
|
||||
* Get the origin of this data set's boundary.
|
||||
@ -160,7 +223,7 @@ define(
|
||||
*/
|
||||
getOrigin: function () {
|
||||
// Pad range if necessary
|
||||
return (max[1] === min[1]) ? [ min[0], min[1] - 1.0 ] : min;
|
||||
return origin;
|
||||
},
|
||||
/**
|
||||
* Get the domain offset; this offset will have been subtracted
|
||||
@ -189,23 +252,17 @@ define(
|
||||
*
|
||||
* @returns {Float32Array[]} the buffers for these traces
|
||||
*/
|
||||
getBuffers: function () {
|
||||
getLineBuffers: function () {
|
||||
return bufferArray;
|
||||
},
|
||||
/**
|
||||
* Get the number of points in the buffer with the specified
|
||||
* index. Buffers are padded to minimize memory allocations,
|
||||
* so user code will need this information to know how much
|
||||
* data to plot.
|
||||
* @returns {number} the number of points in this buffer
|
||||
*/
|
||||
getLength: function (index) {
|
||||
return lengthArray[index] || 0;
|
||||
},
|
||||
/**
|
||||
* Update with latest data.
|
||||
*/
|
||||
update: update
|
||||
update: update,
|
||||
/**
|
||||
* Fill in historical data.
|
||||
*/
|
||||
addHistorical: setHistorical
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -34,11 +34,11 @@ define(
|
||||
subplot.setDomainOffset(prepared.getDomainOffset());
|
||||
|
||||
// Draw the buffers. Select color by index.
|
||||
subplot.getDrawingObject().lines = prepared.getBuffers().map(function (buf, i) {
|
||||
subplot.getDrawingObject().lines = prepared.getLineBuffers().map(function (buf, i) {
|
||||
return {
|
||||
buffer: buf,
|
||||
buffer: buf.getBuffer(),
|
||||
color: PlotPalette.getFloatColor(i),
|
||||
points: prepared.getLength(i)
|
||||
points: buf.getLength()
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -23,7 +23,7 @@ define(
|
||||
});
|
||||
|
||||
function plotTelemetryTo(subplot, prepared, index) {
|
||||
var buffer = prepared.getBuffers()[index];
|
||||
var buffer = prepared.getLineBuffers()[index];
|
||||
|
||||
// Track the domain offset, used to bias domain values
|
||||
// to minimize loss of precision when converted to 32-bit
|
||||
@ -33,9 +33,9 @@ define(
|
||||
// Draw the buffers. Always use the 0th color, because there
|
||||
// is one line per plot.
|
||||
subplot.getDrawingObject().lines = [{
|
||||
buffer: buffer,
|
||||
buffer: buffer.getBuffer(),
|
||||
color: PlotPalette.getFloatColor(0),
|
||||
points: prepared.getLength(index)
|
||||
points: buffer.getLength()
|
||||
}];
|
||||
|
||||
subplot.update();
|
||||
|
@ -11,9 +11,10 @@ define(
|
||||
describe("The plot controller", function () {
|
||||
var mockScope,
|
||||
mockFormatter,
|
||||
mockSubscriber,
|
||||
mockSubscription,
|
||||
mockHandler,
|
||||
mockHandle,
|
||||
mockDomainObject,
|
||||
mockSeries,
|
||||
controller;
|
||||
|
||||
|
||||
@ -30,28 +31,33 @@ define(
|
||||
"domainObject",
|
||||
[ "getId", "getModel", "getCapability" ]
|
||||
);
|
||||
mockSubscriber = jasmine.createSpyObj(
|
||||
mockHandler = jasmine.createSpyObj(
|
||||
"telemetrySubscriber",
|
||||
["subscribe"]
|
||||
["handle"]
|
||||
);
|
||||
mockSubscription = jasmine.createSpyObj(
|
||||
mockHandle = jasmine.createSpyObj(
|
||||
"subscription",
|
||||
[
|
||||
"unsubscribe",
|
||||
"getTelemetryObjects",
|
||||
"getMetadata",
|
||||
"getDomainValue",
|
||||
"getRangeValue"
|
||||
"getRangeValue",
|
||||
"request"
|
||||
]
|
||||
);
|
||||
mockSeries = jasmine.createSpyObj(
|
||||
'series',
|
||||
['getPointCount', 'getDomainValue', 'getRangeValue']
|
||||
);
|
||||
|
||||
mockSubscriber.subscribe.andReturn(mockSubscription);
|
||||
mockSubscription.getTelemetryObjects.andReturn([mockDomainObject]);
|
||||
mockSubscription.getMetadata.andReturn([{}]);
|
||||
mockSubscription.getDomainValue.andReturn(123);
|
||||
mockSubscription.getRangeValue.andReturn(42);
|
||||
mockHandler.handle.andReturn(mockHandle);
|
||||
mockHandle.getTelemetryObjects.andReturn([mockDomainObject]);
|
||||
mockHandle.getMetadata.andReturn([{}]);
|
||||
mockHandle.getDomainValue.andReturn(123);
|
||||
mockHandle.getRangeValue.andReturn(42);
|
||||
|
||||
controller = new PlotController(mockScope, mockFormatter, mockSubscriber);
|
||||
controller = new PlotController(mockScope, mockFormatter, mockHandler);
|
||||
});
|
||||
|
||||
it("provides plot colors", function () {
|
||||
@ -71,7 +77,7 @@ define(
|
||||
// Make an object available
|
||||
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
|
||||
// Should have subscribed
|
||||
expect(mockSubscriber.subscribe).toHaveBeenCalledWith(
|
||||
expect(mockHandler.handle).toHaveBeenCalledWith(
|
||||
mockDomainObject,
|
||||
jasmine.any(Function),
|
||||
true // Lossless
|
||||
@ -92,7 +98,7 @@ define(
|
||||
expect(controller.getSubPlots().length > 0).toBeTruthy();
|
||||
|
||||
// Broadcast data
|
||||
mockSubscriber.subscribe.mostRecentCall.args[1]();
|
||||
mockHandler.handle.mostRecentCall.args[1]();
|
||||
|
||||
controller.getSubPlots().forEach(function (subplot) {
|
||||
expect(subplot.getDrawingObject().lines)
|
||||
@ -104,17 +110,17 @@ define(
|
||||
// Make an object available
|
||||
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
|
||||
// Verify precondition - shouldn't unsubscribe yet
|
||||
expect(mockSubscription.unsubscribe).not.toHaveBeenCalled();
|
||||
expect(mockHandle.unsubscribe).not.toHaveBeenCalled();
|
||||
// Remove the domain object
|
||||
mockScope.$watch.mostRecentCall.args[1](undefined);
|
||||
// Should have unsubscribed
|
||||
expect(mockSubscription.unsubscribe).toHaveBeenCalled();
|
||||
expect(mockHandle.unsubscribe).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it("changes modes depending on number of objects", function () {
|
||||
// Act like one object is available
|
||||
mockSubscription.getTelemetryObjects.andReturn([
|
||||
mockHandle.getTelemetryObjects.andReturn([
|
||||
mockDomainObject
|
||||
]);
|
||||
|
||||
@ -124,7 +130,7 @@ define(
|
||||
expect(controller.getModeOptions().length).toEqual(1);
|
||||
|
||||
// Act like one object is available
|
||||
mockSubscription.getTelemetryObjects.andReturn([
|
||||
mockHandle.getTelemetryObjects.andReturn([
|
||||
mockDomainObject,
|
||||
mockDomainObject,
|
||||
mockDomainObject
|
||||
@ -174,17 +180,26 @@ define(
|
||||
expect(controller.isRequestPending()).toBeFalsy();
|
||||
});
|
||||
|
||||
it("requests historical telemetry", function () {
|
||||
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
|
||||
expect(mockHandle.request).toHaveBeenCalled();
|
||||
mockHandle.request.mostRecentCall.args[1](
|
||||
mockDomainObject,
|
||||
mockSeries
|
||||
);
|
||||
});
|
||||
|
||||
it("unsubscribes when destroyed", function () {
|
||||
// Make an object available
|
||||
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
|
||||
// Make sure $destroy is what's listened for
|
||||
expect(mockScope.$on.mostRecentCall.args[0]).toEqual('$destroy');
|
||||
// Also verify precondition
|
||||
expect(mockSubscription.unsubscribe).not.toHaveBeenCalled();
|
||||
expect(mockHandle.unsubscribe).not.toHaveBeenCalled();
|
||||
// Destroy the scope
|
||||
mockScope.$on.mostRecentCall.args[1]();
|
||||
// Should have unsubscribed
|
||||
expect(mockSubscription.unsubscribe).toHaveBeenCalled();
|
||||
expect(mockHandle.unsubscribe).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
151
platform/features/plot/test/elements/PlotLineBufferSpec.js
Normal file
151
platform/features/plot/test/elements/PlotLineBufferSpec.js
Normal file
@ -0,0 +1,151 @@
|
||||
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
/**
|
||||
* MergeModelsSpec. Created by vwoeltje on 11/6/14.
|
||||
*/
|
||||
define(
|
||||
["../../src/elements/PlotLineBuffer"],
|
||||
function (PlotLineBuffer) {
|
||||
"use strict";
|
||||
|
||||
var TEST_INITIAL_SIZE = 10,
|
||||
TEST_MAX_SIZE = 40,
|
||||
TEST_DOMAIN_OFFSET = 42;
|
||||
|
||||
describe("A plot line buffer", function () {
|
||||
var mockSeries,
|
||||
testDomainValues,
|
||||
testRangeValues,
|
||||
buffer;
|
||||
|
||||
beforeEach(function () {
|
||||
testDomainValues = [ 1, 3, 7, 9, 14, 15 ];
|
||||
testRangeValues = [ 8, 0, 3, 9, 8, 11 ];
|
||||
mockSeries = jasmine.createSpyObj(
|
||||
"series",
|
||||
['getPointCount', 'getDomainValue', 'getRangeValue']
|
||||
);
|
||||
mockSeries.getPointCount.andCallFake(function () {
|
||||
return testDomainValues.length;
|
||||
});
|
||||
mockSeries.getDomainValue.andCallFake(function (i) {
|
||||
return testDomainValues[i];
|
||||
});
|
||||
mockSeries.getRangeValue.andCallFake(function (i) {
|
||||
return testRangeValues[i];
|
||||
});
|
||||
|
||||
buffer = new PlotLineBuffer(
|
||||
TEST_DOMAIN_OFFSET,
|
||||
TEST_INITIAL_SIZE,
|
||||
TEST_MAX_SIZE
|
||||
);
|
||||
|
||||
// Start with some data in there
|
||||
buffer.insert(mockSeries, 0);
|
||||
});
|
||||
|
||||
it("allows insertion of series data", function () {
|
||||
// Convert to a regular array for checking.
|
||||
// Verify that domain/ranges were interleaved and
|
||||
// that domain offset was adjusted for.
|
||||
expect(
|
||||
Array.prototype.slice.call(buffer.getBuffer()).slice(0, 12)
|
||||
).toEqual([ -41, 8, -39, 0, -35, 3, -33, 9, -28, 8, -27, 11]);
|
||||
expect(buffer.getLength()).toEqual(6);
|
||||
});
|
||||
|
||||
it("finds insertion indexes", function () {
|
||||
expect(buffer.findInsertionIndex(0)).toEqual(0);
|
||||
expect(buffer.findInsertionIndex(2)).toEqual(1);
|
||||
expect(buffer.findInsertionIndex(5)).toEqual(2);
|
||||
expect(buffer.findInsertionIndex(10)).toEqual(4);
|
||||
expect(buffer.findInsertionIndex(14.5)).toEqual(5);
|
||||
expect(buffer.findInsertionIndex(20)).toEqual(6);
|
||||
|
||||
// 9 is already in there, disallow insertion
|
||||
expect(buffer.findInsertionIndex(9)).toEqual(-1);
|
||||
});
|
||||
|
||||
it("allows insertion in the middle", function () {
|
||||
var head = [ -41, 8, -39, 0, -35, 3 ],
|
||||
tail = [ -33, 9, -28, 8, -27, 11];
|
||||
buffer.insert(mockSeries, 3);
|
||||
expect(
|
||||
Array.prototype.slice.call(buffer.getBuffer()).slice(0, 24)
|
||||
).toEqual(head.concat(head).concat(tail).concat(tail));
|
||||
expect(buffer.getLength()).toEqual(12);
|
||||
});
|
||||
|
||||
it("allows values to be trimmed from the start", function () {
|
||||
buffer.trim(2);
|
||||
expect(buffer.getLength()).toEqual(4);
|
||||
expect(
|
||||
Array.prototype.slice.call(buffer.getBuffer()).slice(0, 8)
|
||||
).toEqual([ -35, 3, -33, 9, -28, 8, -27, 11]);
|
||||
});
|
||||
|
||||
it("expands buffer when needed to accommodate more data", function () {
|
||||
var i;
|
||||
|
||||
// Initial underlying buffer should be twice initial size...
|
||||
// (Since each pair will take up two elements)
|
||||
expect(buffer.getBuffer().length).toEqual(20);
|
||||
|
||||
// Should be able to insert 6 series of 6 points each
|
||||
// (After that, we'll hit the test max of 40)
|
||||
for (i = 1; i < 15; i += 1) {
|
||||
expect(buffer.insertPoint(i * 10, Math.sin(i), i))
|
||||
.toBeTruthy();
|
||||
}
|
||||
|
||||
// Buffer should have expanded in the process
|
||||
expect(buffer.getBuffer().length).toEqual(40);
|
||||
|
||||
// Push to maximum size just to make sure...
|
||||
for (i = 1; i < 150; i += 1) {
|
||||
buffer.insertPoint(i * 10, Math.sin(i), i);
|
||||
}
|
||||
|
||||
expect(buffer.getBuffer().length).toEqual(80);
|
||||
});
|
||||
|
||||
it("ensures a maximum size", function () {
|
||||
var i;
|
||||
|
||||
// Should be able to insert 6 series of 6 points each
|
||||
// (After that, we'll hit the test max of 40)
|
||||
for (i = 1; i < 6; i += 1) {
|
||||
expect(buffer.getLength()).toEqual(6 * i);
|
||||
expect(buffer.insert(mockSeries, Number.POSITIVE_INFINITY))
|
||||
.toBeTruthy();
|
||||
}
|
||||
|
||||
// Should be maxed out now
|
||||
expect(buffer.getLength()).toEqual(36);
|
||||
expect(buffer.insert(mockSeries, Number.POSITIVE_INFINITY))
|
||||
.toBeFalsy();
|
||||
expect(buffer.getLength()).toEqual(36);
|
||||
|
||||
});
|
||||
|
||||
it("reduces buffer size when space is no longer needed", function () {
|
||||
// Check that actual buffer is sized to the initial size
|
||||
// (double TEST_INITIAL_SIZE, since two elements are needed per
|
||||
// point; one for domain, one for range)
|
||||
expect(buffer.getBuffer().length).toEqual(20);
|
||||
// Should have 6 elements now... grow to 24
|
||||
buffer.insert(mockSeries, Number.POSITIVE_INFINITY);
|
||||
buffer.insert(mockSeries, Number.POSITIVE_INFINITY);
|
||||
buffer.insert(mockSeries, Number.POSITIVE_INFINITY);
|
||||
// This should have doubled the actual buffer size
|
||||
expect(buffer.getBuffer().length).toEqual(80);
|
||||
// Remove some values
|
||||
buffer.trim(20);
|
||||
// Actual buffer size should have been reduced accordingly
|
||||
expect(buffer.getBuffer().length).toBeLessThan(80);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
114
platform/features/plot/test/elements/PlotLineSpec.js
Normal file
114
platform/features/plot/test/elements/PlotLineSpec.js
Normal file
@ -0,0 +1,114 @@
|
||||
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
["../../src/elements/PlotLine"],
|
||||
function (PlotLine) {
|
||||
"use strict";
|
||||
|
||||
describe("A plot line", function () {
|
||||
var mockBuffer,
|
||||
mockSeries,
|
||||
testDomainBuffer,
|
||||
testRangeBuffer,
|
||||
testSeries,
|
||||
line;
|
||||
|
||||
beforeEach(function () {
|
||||
testDomainBuffer = [];
|
||||
testRangeBuffer = [];
|
||||
testSeries = [];
|
||||
|
||||
mockBuffer = jasmine.createSpyObj(
|
||||
'buffer',
|
||||
['findInsertionIndex', 'insert', 'insertPoint', 'trim']
|
||||
);
|
||||
mockSeries = jasmine.createSpyObj(
|
||||
'series',
|
||||
['getPointCount', 'getDomainValue', 'getRangeValue']
|
||||
);
|
||||
|
||||
mockSeries.getPointCount.andCallFake(function () {
|
||||
return testSeries.length;
|
||||
});
|
||||
mockSeries.getDomainValue.andCallFake(function (i) {
|
||||
return (testSeries[i] || [])[0];
|
||||
});
|
||||
mockSeries.getRangeValue.andCallFake(function (i) {
|
||||
return (testSeries[i] || [])[1];
|
||||
});
|
||||
|
||||
// Function like PlotLineBuffer, to aid in testability
|
||||
mockBuffer.findInsertionIndex.andCallFake(function (v) {
|
||||
var index = 0;
|
||||
if (testDomainBuffer.indexOf(v) !== -1) {
|
||||
return -1;
|
||||
}
|
||||
while ((index < testDomainBuffer.length) &&
|
||||
(testDomainBuffer[index] < v)) {
|
||||
index += 1;
|
||||
}
|
||||
return index;
|
||||
});
|
||||
mockBuffer.insert.andCallFake(function (series, index) {
|
||||
var domains = [], ranges = [], i;
|
||||
for (i = 0; i < series.getPointCount(); i += 1) {
|
||||
domains.push(series.getDomainValue(i));
|
||||
ranges.push(series.getRangeValue(i));
|
||||
}
|
||||
testDomainBuffer = testDomainBuffer.slice(0, index)
|
||||
.concat(domains)
|
||||
.concat(testDomainBuffer.slice(index));
|
||||
testRangeBuffer = testRangeBuffer.slice(0, index)
|
||||
.concat(ranges)
|
||||
.concat(testRangeBuffer.slice(index));
|
||||
return true;
|
||||
});
|
||||
mockBuffer.insertPoint.andCallFake(function (dv, rv, index) {
|
||||
testDomainBuffer.splice(index, 0, dv);
|
||||
testRangeBuffer.splice(index, 0, rv);
|
||||
return true;
|
||||
});
|
||||
|
||||
line = new PlotLine(mockBuffer);
|
||||
});
|
||||
|
||||
it("allows single point insertion", function () {
|
||||
line.addPoint(100, 200);
|
||||
line.addPoint(50, 42);
|
||||
line.addPoint(150, 12321);
|
||||
// Should have managed insertion index choices to get to...
|
||||
expect(testDomainBuffer).toEqual([50, 100, 150]);
|
||||
expect(testRangeBuffer).toEqual([42, 200, 12321]);
|
||||
});
|
||||
|
||||
it("allows series insertion", function () {
|
||||
testSeries = [ [ 50, 42 ], [ 100, 200 ], [ 150, 12321 ] ];
|
||||
line.addSeries(mockSeries);
|
||||
// Should have managed insertion index choices to get to...
|
||||
expect(testDomainBuffer).toEqual([50, 100, 150]);
|
||||
expect(testRangeBuffer).toEqual([42, 200, 12321]);
|
||||
});
|
||||
|
||||
it("splits series insertion when necessary", function () {
|
||||
testSeries = [ [ 50, 42 ], [ 100, 200 ], [ 150, 12321 ] ];
|
||||
line.addPoint(75, 1);
|
||||
line.addSeries(mockSeries);
|
||||
// Should have managed insertion index choices to get to...
|
||||
expect(testDomainBuffer).toEqual([50, 75, 100, 150]);
|
||||
expect(testRangeBuffer).toEqual([42, 1, 200, 12321]);
|
||||
});
|
||||
|
||||
it("attempts to remove points when insertion fails", function () {
|
||||
// Verify precondition - normally doesn't try to trim
|
||||
line.addPoint(1, 2);
|
||||
expect(mockBuffer.trim).not.toHaveBeenCalled();
|
||||
|
||||
// But if insertPoint fails, it should trim
|
||||
mockBuffer.insertPoint.andReturn(false);
|
||||
line.addPoint(2, 3);
|
||||
expect(mockBuffer.trim).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
74
platform/features/plot/test/elements/PlotSeriesWindowSpec.js
Normal file
74
platform/features/plot/test/elements/PlotSeriesWindowSpec.js
Normal file
@ -0,0 +1,74 @@
|
||||
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
["../../src/elements/PlotSeriesWindow"],
|
||||
function (PlotSeriesWindow) {
|
||||
"use strict";
|
||||
|
||||
describe("A plot's window on a telemetry series", function () {
|
||||
var mockSeries,
|
||||
testSeries,
|
||||
window;
|
||||
|
||||
beforeEach(function () {
|
||||
testSeries = [
|
||||
[ 0, 42 ],
|
||||
[ 10, 1 ],
|
||||
[ 20, 4 ],
|
||||
[ 30, 9 ],
|
||||
[ 40, 3 ]
|
||||
];
|
||||
|
||||
mockSeries = jasmine.createSpyObj(
|
||||
'series',
|
||||
['getPointCount', 'getDomainValue', 'getRangeValue']
|
||||
);
|
||||
|
||||
mockSeries.getPointCount.andCallFake(function () {
|
||||
return testSeries.length;
|
||||
});
|
||||
mockSeries.getDomainValue.andCallFake(function (i) {
|
||||
return testSeries[i][0];
|
||||
});
|
||||
mockSeries.getRangeValue.andCallFake(function (i) {
|
||||
return testSeries[i][1];
|
||||
});
|
||||
|
||||
window = new PlotSeriesWindow(
|
||||
mockSeries,
|
||||
"testDomain",
|
||||
"testRange",
|
||||
1,
|
||||
testSeries.length
|
||||
);
|
||||
});
|
||||
|
||||
it("provides a window upon a data series", function () {
|
||||
expect(window.getPointCount()).toEqual(4);
|
||||
expect(window.getDomainValue(0)).toEqual(10);
|
||||
expect(window.getRangeValue(0)).toEqual(1);
|
||||
});
|
||||
|
||||
it("looks up using specific domain/range keys", function () {
|
||||
window.getDomainValue(0);
|
||||
window.getRangeValue(0);
|
||||
expect(mockSeries.getDomainValue)
|
||||
.toHaveBeenCalledWith(1, 'testDomain');
|
||||
expect(mockSeries.getRangeValue)
|
||||
.toHaveBeenCalledWith(1, 'testRange');
|
||||
});
|
||||
|
||||
it("can be split into smaller windows", function () {
|
||||
var windows = window.split();
|
||||
expect(windows.length).toEqual(2);
|
||||
expect(windows[0].getPointCount()).toEqual(2);
|
||||
expect(windows[1].getPointCount()).toEqual(2);
|
||||
expect(windows[0].getDomainValue(0)).toEqual(10);
|
||||
expect(windows[1].getDomainValue(0)).toEqual(30);
|
||||
expect(windows[0].getRangeValue(0)).toEqual(1);
|
||||
expect(windows[1].getRangeValue(0)).toEqual(9);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -14,6 +14,7 @@ define(
|
||||
testRange,
|
||||
testDomainValues,
|
||||
testRangeValues,
|
||||
mockSeries,
|
||||
updater;
|
||||
|
||||
function makeMockDomainObject(id) {
|
||||
@ -33,6 +34,10 @@ define(
|
||||
"subscription",
|
||||
[ "getDomainValue", "getRangeValue", "getTelemetryObjects" ]
|
||||
);
|
||||
mockSeries = jasmine.createSpyObj(
|
||||
'series',
|
||||
['getPointCount', 'getDomainValue', 'getRangeValue']
|
||||
);
|
||||
testDomain = "testDomain";
|
||||
testRange = "testRange";
|
||||
testDomainValues = { a: 3, b: 7, c: 13 };
|
||||
@ -55,57 +60,14 @@ define(
|
||||
});
|
||||
|
||||
it("provides one buffer per telemetry object", function () {
|
||||
expect(updater.getBuffers().length).toEqual(3);
|
||||
expect(updater.getLineBuffers().length).toEqual(3);
|
||||
});
|
||||
|
||||
it("changes buffer count if telemetry object counts change", function () {
|
||||
mockSubscription.getTelemetryObjects
|
||||
.andReturn([makeMockDomainObject('a')]);
|
||||
updater.update();
|
||||
expect(updater.getBuffers().length).toEqual(1);
|
||||
});
|
||||
|
||||
it("maintains a buffer of received telemetry", function () {
|
||||
// Count should be large enough to trigger a buffer resize
|
||||
var count = 750,
|
||||
i;
|
||||
|
||||
// Increment values exposed by subscription
|
||||
function increment() {
|
||||
Object.keys(testDomainValues).forEach(function (k) {
|
||||
testDomainValues[k] += 1;
|
||||
testRangeValues[k] += 1;
|
||||
});
|
||||
}
|
||||
|
||||
// Simulate a lot of telemetry updates
|
||||
for (i = 0; i < count; i += 1) {
|
||||
updater.update();
|
||||
expect(updater.getLength(0)).toEqual(i + 1);
|
||||
expect(updater.getLength(1)).toEqual(i + 1);
|
||||
expect(updater.getLength(2)).toEqual(i + 1);
|
||||
increment();
|
||||
}
|
||||
|
||||
// Domain offset should be lowest domain value
|
||||
expect(updater.getDomainOffset()).toEqual(3);
|
||||
|
||||
// Test against initial values, offset by count,
|
||||
// as was the case during each update
|
||||
for (i = 0; i < count; i += 1) {
|
||||
expect(updater.getBuffers()[0][i * 2])
|
||||
.toEqual(3 + i - 3);
|
||||
expect(updater.getBuffers()[0][i * 2 + 1])
|
||||
.toEqual(123 + i);
|
||||
expect(updater.getBuffers()[1][i * 2])
|
||||
.toEqual(7 + i - 3);
|
||||
expect(updater.getBuffers()[1][i * 2 + 1])
|
||||
.toEqual(456 + i);
|
||||
expect(updater.getBuffers()[2][i * 2])
|
||||
.toEqual(13 + i - 3);
|
||||
expect(updater.getBuffers()[2][i * 2 + 1])
|
||||
.toEqual(789 + i);
|
||||
}
|
||||
expect(updater.getLineBuffers().length).toEqual(1);
|
||||
});
|
||||
|
||||
it("can handle delayed telemetry object availability", function () {
|
||||
@ -124,7 +86,7 @@ define(
|
||||
);
|
||||
|
||||
// Should have 0 buffers for 0 objects
|
||||
expect(updater.getBuffers().length).toEqual(0);
|
||||
expect(updater.getLineBuffers().length).toEqual(0);
|
||||
|
||||
// Restore the three objects the test subscription would
|
||||
// normally have.
|
||||
@ -132,30 +94,79 @@ define(
|
||||
updater.update();
|
||||
|
||||
// Should have 3 buffers for 3 objects
|
||||
expect(updater.getBuffers().length).toEqual(3);
|
||||
expect(updater.getLineBuffers().length).toEqual(3);
|
||||
});
|
||||
|
||||
it("accepts historical telemetry updates", function () {
|
||||
var mockObject = mockSubscription.getTelemetryObjects()[0];
|
||||
|
||||
it("shifts buffer upon expansion", function () {
|
||||
// Count should be large enough to hit buffer's max size
|
||||
var count = 1400,
|
||||
i;
|
||||
mockSeries.getPointCount.andReturn(3);
|
||||
mockSeries.getDomainValue.andCallFake(function (i) {
|
||||
return 1000 + i * 1000;
|
||||
});
|
||||
mockSeries.getRangeValue.andReturn(10);
|
||||
|
||||
// Initial update; should have 3 in first position
|
||||
// (a's initial domain value)
|
||||
// PlotLine & PlotLineBuffer are tested for most of the
|
||||
// details here, so just check for some expected side
|
||||
// effect; in this case, should see more points in the buffer
|
||||
expect(updater.getLineBuffers()[0].getLength()).toEqual(1);
|
||||
updater.addHistorical(mockObject, mockSeries);
|
||||
expect(updater.getLineBuffers()[0].getLength()).toEqual(4);
|
||||
});
|
||||
|
||||
it("clears the domain offset if no objects are present", function () {
|
||||
mockSubscription.getTelemetryObjects.andReturn([]);
|
||||
updater.update();
|
||||
expect(updater.getBuffers()[0][1]).toEqual(123);
|
||||
|
||||
// Simulate a lot of telemetry updates
|
||||
for (i = 0; i < count; i += 1) {
|
||||
testDomainValues.a += 1;
|
||||
testRangeValues.a += 1;
|
||||
updater.update();
|
||||
}
|
||||
|
||||
// Value at front of the buffer should have been pushed out
|
||||
expect(updater.getBuffers()[0][1]).not.toEqual(123);
|
||||
expect(updater.getDomainOffset()).toBeUndefined();
|
||||
});
|
||||
|
||||
it("handles empty historical telemetry updates", function () {
|
||||
// General robustness check for when a series is empty
|
||||
var mockObject = mockSubscription.getTelemetryObjects()[0];
|
||||
|
||||
mockSeries.getPointCount.andReturn(0);
|
||||
mockSeries.getDomainValue.andCallFake(function (i) {
|
||||
return 1000 + i * 1000;
|
||||
});
|
||||
mockSeries.getRangeValue.andReturn(10);
|
||||
|
||||
// PlotLine & PlotLineBuffer are tested for most of the
|
||||
// details here, so just check for some expected side
|
||||
// effect; in this case, should see more points in the buffer
|
||||
expect(updater.getLineBuffers()[0].getLength()).toEqual(1);
|
||||
updater.addHistorical(mockObject, mockSeries);
|
||||
expect(updater.getLineBuffers()[0].getLength()).toEqual(1);
|
||||
});
|
||||
|
||||
it("can initialize domain offset from historical telemetry", function () {
|
||||
var tmp = mockSubscription.getTelemetryObjects();
|
||||
|
||||
mockSubscription.getTelemetryObjects.andReturn([]);
|
||||
|
||||
// Reinstantiate with the empty subscription
|
||||
updater = new PlotUpdater(
|
||||
mockSubscription,
|
||||
testDomain,
|
||||
testRange
|
||||
);
|
||||
|
||||
// Restore subscription, provide some historical data
|
||||
mockSubscription.getTelemetryObjects.andReturn(tmp);
|
||||
mockSeries.getPointCount.andReturn(3);
|
||||
mockSeries.getDomainValue.andCallFake(function (i) {
|
||||
return 1000 + i * 1000;
|
||||
});
|
||||
mockSeries.getRangeValue.andReturn(10);
|
||||
|
||||
// PlotLine & PlotLineBuffer are tested for most of the
|
||||
// details here, so just check for some expected side
|
||||
// effect; in this case, should see more points in the buffer
|
||||
expect(updater.getDomainOffset()).toBeUndefined();
|
||||
updater.addHistorical(tmp[0], mockSeries);
|
||||
expect(updater.getDomainOffset()).toBeDefined();
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -57,18 +57,30 @@ define(
|
||||
// Prepared telemetry data
|
||||
mockPrepared = jasmine.createSpyObj(
|
||||
"prepared",
|
||||
[ "getDomainOffset", "getOrigin", "getDimensions", "getBuffers", "getLength" ]
|
||||
[
|
||||
"getDomainOffset",
|
||||
"getOrigin",
|
||||
"getDimensions",
|
||||
"getLineBuffers"
|
||||
]
|
||||
);
|
||||
|
||||
mockSubPlotFactory.createSubPlot.andCallFake(createMockSubPlot);
|
||||
|
||||
// Act as if we have three buffers full of data
|
||||
testBuffers = [["a"], ["b"], ["c"]];
|
||||
mockPrepared.getBuffers.andReturn(testBuffers);
|
||||
testBuffers = ['a', 'b', 'c'].map(function (id) {
|
||||
var mockBuffer = jasmine.createSpyObj(
|
||||
'buffer-' + id,
|
||||
['getBuffer', 'getLength']
|
||||
);
|
||||
mockBuffer.getBuffer.andReturn([id]);
|
||||
mockBuffer.getLength.andReturn(3);
|
||||
return mockBuffer;
|
||||
});
|
||||
mockPrepared.getLineBuffers.andReturn(testBuffers);
|
||||
mockPrepared.getDomainOffset.andReturn(1234);
|
||||
mockPrepared.getOrigin.andReturn([10, 10]);
|
||||
mockPrepared.getDimensions.andReturn([500, 500]);
|
||||
mockPrepared.getLength.andReturn(3);
|
||||
|
||||
// Clear out drawing objects
|
||||
testDrawingObjects = [];
|
||||
@ -104,7 +116,7 @@ define(
|
||||
// Make sure the right buffer was drawn to the
|
||||
// right subplot.
|
||||
testDrawingObject.lines.forEach(function (line, j) {
|
||||
expect(line.buffer).toEqual(testBuffers[j]);
|
||||
expect(line.buffer).toEqual(testBuffers[j].getBuffer());
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -57,18 +57,25 @@ define(
|
||||
// Prepared telemetry data
|
||||
mockPrepared = jasmine.createSpyObj(
|
||||
"prepared",
|
||||
[ "getDomainOffset", "getOrigin", "getDimensions", "getBuffers", "getLength" ]
|
||||
[ "getDomainOffset", "getOrigin", "getDimensions", "getLineBuffers" ]
|
||||
);
|
||||
|
||||
mockSubPlotFactory.createSubPlot.andCallFake(createMockSubPlot);
|
||||
|
||||
// Act as if we have three buffers full of data
|
||||
testBuffers = [["a"], ["b"], ["c"]];
|
||||
mockPrepared.getBuffers.andReturn(testBuffers);
|
||||
testBuffers = ['a', 'b', 'c'].map(function (id) {
|
||||
var mockBuffer = jasmine.createSpyObj(
|
||||
'buffer-' + id,
|
||||
['getBuffer', 'getLength']
|
||||
);
|
||||
mockBuffer.getBuffer.andReturn([id]);
|
||||
mockBuffer.getLength.andReturn(3);
|
||||
return mockBuffer;
|
||||
});
|
||||
mockPrepared.getLineBuffers.andReturn(testBuffers);
|
||||
mockPrepared.getDomainOffset.andReturn(1234);
|
||||
mockPrepared.getOrigin.andReturn([10, 10]);
|
||||
mockPrepared.getDimensions.andReturn([500, 500]);
|
||||
mockPrepared.getLength.andReturn(3);
|
||||
|
||||
// Objects that will be drawn to in sub-plots
|
||||
testDrawingObjects = [];
|
||||
@ -104,7 +111,7 @@ define(
|
||||
// Make sure the right buffer was drawn to the
|
||||
// right subplot.
|
||||
expect(testDrawingObject.lines[0].buffer)
|
||||
.toEqual(testBuffers[i]);
|
||||
.toEqual(testBuffers[i].getBuffer());
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -6,11 +6,14 @@
|
||||
"SubPlot",
|
||||
"SubPlotFactory",
|
||||
"elements/PlotAxis",
|
||||
"elements/PlotLine",
|
||||
"elements/PlotLineBuffer",
|
||||
"elements/PlotPalette",
|
||||
"elements/PlotPanZoomStack",
|
||||
"elements/PlotPanZoomStackGroup",
|
||||
"elements/PlotPosition",
|
||||
"elements/PlotPreparer",
|
||||
"elements/PlotSeriesWindow",
|
||||
"elements/PlotTickGenerator",
|
||||
"elements/PlotUpdater",
|
||||
"modes/PlotModeOptions",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Open MCT Web Framework Component",
|
||||
"description": "Framework layer for Open MCT Web; interprets bundle definitions and serves as an intermediary between Require and Angular.",
|
||||
"description": "Framework layer for Open MCT Web; interprets bundle definitions and serves as an intermediary between Require and Angular",
|
||||
"libraries": "lib",
|
||||
"configuration": {
|
||||
"paths": {
|
||||
@ -17,57 +17,65 @@
|
||||
{
|
||||
"name": "Blanket.js",
|
||||
"version": "1.1.5",
|
||||
"description": "Code coverage measurement and reporting.",
|
||||
"description": "Code coverage measurement and reporting",
|
||||
"author": "Alex Seville",
|
||||
"website": "http://blanketjs.org/",
|
||||
"license": "MIT",
|
||||
"copyright": "",
|
||||
"license": "license-mit",
|
||||
"link": "http://opensource.org/licenses/MIT"
|
||||
},
|
||||
{
|
||||
"name": "Jasmine",
|
||||
"version": "1.3.1",
|
||||
"description": "Unit testing.",
|
||||
"description": "Unit testing",
|
||||
"author": "Pivotal Labs",
|
||||
"website": "http://jasmine.github.io/",
|
||||
"license": "MIT",
|
||||
"copyright": "",
|
||||
"license": "license-mit",
|
||||
"link": "http://opensource.org/licenses/MIT"
|
||||
},
|
||||
{
|
||||
"name": "RequireJS",
|
||||
"version": "2.1.9",
|
||||
"description": "Script loader.",
|
||||
"description": "Script loader",
|
||||
"author": "The Dojo Foundation",
|
||||
"website": "http://requirejs.org/",
|
||||
"license": "MIT",
|
||||
"copyright": "Copyright (c) 2010-2015, The Dojo Foundation",
|
||||
"license": "license-mit",
|
||||
"link": "https://github.com/jrburke/requirejs/blob/master/LICENSE"
|
||||
},
|
||||
{
|
||||
"name": "AngularJS",
|
||||
"version": "1.2.26",
|
||||
"description": "Client-side web application framework.",
|
||||
"description": "Client-side web application framework",
|
||||
"author": "Google",
|
||||
"website": "http://angularjs.org/",
|
||||
"license": "MIT",
|
||||
"copyright": "Copyright (c) 2010-2015 Google, Inc. http://angularjs.org",
|
||||
"license": "license-mit",
|
||||
"link": "https://github.com/angular/angular.js/blob/master/LICENSE"
|
||||
},
|
||||
{
|
||||
"name": "Angular-Route",
|
||||
"version": "1.2.26",
|
||||
"description": "Client-side view routing.",
|
||||
"description": "Client-side view routing",
|
||||
"author": "Google",
|
||||
"website": "http://angularjs.org/",
|
||||
"license": "MIT",
|
||||
"copyright": "Copyright (c) 2010-2015 Google, Inc. http://angularjs.org",
|
||||
"license": "license-mit",
|
||||
"link": "https://github.com/angular/angular.js/blob/master/LICENSE"
|
||||
},
|
||||
{
|
||||
"name": "ES6-Promise",
|
||||
"version": "2.0.0",
|
||||
"description": "Promise polyfill for pre-ECMAScript 6 browsers.",
|
||||
"description": "Promise polyfill for pre-ECMAScript 6 browsers",
|
||||
"author": "Yehuda Katz, Tom Dale, Stefan Penner and contributors",
|
||||
"website": "https://github.com/jakearchibald/es6-promise",
|
||||
"license": "MIT",
|
||||
"copyright": "Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors",
|
||||
"license": "license-mit",
|
||||
"link": "https://github.com/jakearchibald/es6-promise/blob/master/LICENSE"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Data bundle",
|
||||
"description": "Interfaces and infrastructure for real-time and historical data.",
|
||||
"description": "Interfaces and infrastructure for real-time and historical data",
|
||||
"configuration": {
|
||||
"paths": {
|
||||
"moment": "moment.min"
|
||||
@ -43,6 +43,11 @@
|
||||
"key": "telemetrySubscriber",
|
||||
"implementation": "TelemetrySubscriber.js",
|
||||
"depends": [ "$q", "$timeout" ]
|
||||
},
|
||||
{
|
||||
"key": "telemetryHandler",
|
||||
"implementation": "TelemetryHandler.js",
|
||||
"depends": [ "$q", "telemetrySubscriber" ]
|
||||
}
|
||||
],
|
||||
"licenses": [
|
||||
@ -50,9 +55,10 @@
|
||||
"name": "Moment.js",
|
||||
"version": "2.7.0",
|
||||
"author": "Tim Wood, Iskren Chernev, Moment.js contributors",
|
||||
"description": "Time/date parsing/formatting.",
|
||||
"description": "Time/date parsing/formatting",
|
||||
"website": "http://momentjs.com",
|
||||
"license": "MIT",
|
||||
"copyright": "Copyright (c) 2011-2014 Tim Wood, Iskren Chernev, Moment.js contributors",
|
||||
"license": "license-mit",
|
||||
"link": "https://raw.githubusercontent.com/moment/moment/develop/LICENSE"
|
||||
}
|
||||
]
|
||||
|
45
platform/telemetry/src/TelemetryDelegator.js
Normal file
45
platform/telemetry/src/TelemetryDelegator.js
Normal file
@ -0,0 +1,45 @@
|
||||
/*global define*/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Used to handle telemetry delegation associated with a
|
||||
* given domain object.
|
||||
*/
|
||||
function TelemetryDelegator($q) {
|
||||
return {
|
||||
/**
|
||||
* Promise telemetry-providing objects associated with
|
||||
* this domain object (either the domain object itself,
|
||||
* or the objects it delegates)
|
||||
* @returns {Promise.<DomainObject[]>} domain objects with
|
||||
* a telemetry capability
|
||||
*/
|
||||
promiseTelemetryObjects: function (domainObject) {
|
||||
// If object has been cleared, there are no relevant
|
||||
// telemetry-providing domain objects.
|
||||
if (!domainObject) {
|
||||
return $q.when([]);
|
||||
}
|
||||
|
||||
// Otherwise, try delegation first, and attach the
|
||||
// object itself if it has a telemetry capability.
|
||||
return $q.when(domainObject.useCapability(
|
||||
"delegation",
|
||||
"telemetry"
|
||||
)).then(function (result) {
|
||||
var head = domainObject.hasCapability("telemetry") ?
|
||||
[ domainObject ] : [],
|
||||
tail = result || [];
|
||||
return head.concat(tail);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return TelemetryDelegator;
|
||||
}
|
||||
);
|
91
platform/telemetry/src/TelemetryHandle.js
Normal file
91
platform/telemetry/src/TelemetryHandle.js
Normal file
@ -0,0 +1,91 @@
|
||||
/*global define*/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* A telemetry handle acts as a helper in issuing requests for
|
||||
* new telemetry as well as subscribing to real-time updates
|
||||
* for the same telemetry series. This is exposed through the
|
||||
* `telemetryHandler` service.
|
||||
* @param $q Angular's $q, for promises
|
||||
* @param {TelemetrySubscription} subscription a subscription
|
||||
* to supplied telemetry
|
||||
*/
|
||||
function TelemetryHandle($q, subscription) {
|
||||
var seriesMap = {},
|
||||
self = Object.create(subscription);
|
||||
|
||||
// Request a telemetry series for this specific object
|
||||
function requestSeries(telemetryObject, request, callback) {
|
||||
var id = telemetryObject.getId(),
|
||||
telemetry = telemetryObject.getCapability('telemetry');
|
||||
|
||||
function receiveSeries(series) {
|
||||
// Store it for subsequent lookup
|
||||
seriesMap[id] = series;
|
||||
// Notify callback of new series data, if there is one
|
||||
if (callback) {
|
||||
callback(telemetryObject, series);
|
||||
}
|
||||
// Pass it along for promise-chaining
|
||||
return series;
|
||||
}
|
||||
|
||||
// Issue the request via the object's telemetry capability
|
||||
return telemetry.requestData(request).then(receiveSeries);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the most recently obtained telemetry data series associated
|
||||
* with this domain object.
|
||||
* @param {DomainObject} the domain object which has telemetry
|
||||
* data associated with it
|
||||
* @return {TelemetrySeries} the most recent telemetry series
|
||||
* (or undefined if there is not one)
|
||||
*/
|
||||
self.getSeries = function (domainObject) {
|
||||
var id = domainObject.getId();
|
||||
return seriesMap[id];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Change the request duration.
|
||||
* @param {object|number} request the duration of historical
|
||||
* data to look at; or, the request to issue
|
||||
* @param {Function} [callback] a callback that will be
|
||||
* invoked as new data becomes available, with the
|
||||
* domain object for which new data is available.
|
||||
*/
|
||||
self.request = function (request, callback) {
|
||||
// Issue (and handle) the new request from this object
|
||||
function issueRequest(telemetryObject) {
|
||||
return requestSeries(telemetryObject, request, callback);
|
||||
}
|
||||
|
||||
// Map the request to all telemetry objects
|
||||
function issueRequests(telemetryObjects) {
|
||||
return $q.all(telemetryObjects.map(issueRequest));
|
||||
}
|
||||
|
||||
// If the request is a simple number, treat it as a duration
|
||||
request = (typeof request === 'number') ?
|
||||
{ duration: request } : request;
|
||||
|
||||
// Look up telemetry-providing objects from the subscription,
|
||||
// then issue new requests.
|
||||
return subscription.promiseTelemetryObjects()
|
||||
.then(issueRequests);
|
||||
};
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
return TelemetryHandle;
|
||||
|
||||
}
|
||||
);
|
33
platform/telemetry/src/TelemetryHandler.js
Normal file
33
platform/telemetry/src/TelemetryHandler.js
Normal file
@ -0,0 +1,33 @@
|
||||
/*global define*/
|
||||
|
||||
define(
|
||||
['./TelemetryHandle'],
|
||||
function (TelemetryHandle) {
|
||||
"use strict";
|
||||
|
||||
|
||||
/**
|
||||
* A TelemetryRequester provides an easy interface to request
|
||||
* telemetry associated with a set of domain objects.
|
||||
*
|
||||
* @constructor
|
||||
* @param $q Angular's $q
|
||||
*/
|
||||
function TelemetryHandler($q, telemetrySubscriber) {
|
||||
return {
|
||||
handle: function (domainObject, callback, lossless) {
|
||||
var subscription = telemetrySubscriber.subscribe(
|
||||
domainObject,
|
||||
callback,
|
||||
lossless
|
||||
);
|
||||
|
||||
return new TelemetryHandle($q, subscription);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return TelemetryHandler;
|
||||
|
||||
}
|
||||
);
|
@ -1,8 +1,8 @@
|
||||
/*global define*/
|
||||
|
||||
define(
|
||||
['./TelemetryQueue', './TelemetryTable'],
|
||||
function (TelemetryQueue, TelemetryTable) {
|
||||
['./TelemetryQueue', './TelemetryTable', './TelemetryDelegator'],
|
||||
function (TelemetryQueue, TelemetryTable, TelemetryDelegator) {
|
||||
"use strict";
|
||||
|
||||
|
||||
@ -31,7 +31,9 @@ define(
|
||||
* the callback once, with access to the latest data
|
||||
*/
|
||||
function TelemetrySubscription($q, $timeout, domainObject, callback, lossless) {
|
||||
var unsubscribePromise,
|
||||
var delegator = new TelemetryDelegator($q),
|
||||
unsubscribePromise,
|
||||
telemetryObjectPromise,
|
||||
latestValues = {},
|
||||
telemetryObjects = [],
|
||||
pool = lossless ? new TelemetryQueue() : new TelemetryTable(),
|
||||
@ -42,23 +44,7 @@ define(
|
||||
// This will either be the object in view, or object that
|
||||
// this object delegates its telemetry capability to.
|
||||
function promiseRelevantObjects(domainObject) {
|
||||
// If object has been cleared, there are no relevant
|
||||
// telemetry-providing domain objects.
|
||||
if (!domainObject) {
|
||||
return $q.when([]);
|
||||
}
|
||||
|
||||
// Otherwise, try delegation first, and attach the
|
||||
// object itself if it has a telemetry capability.
|
||||
return $q.when(domainObject.useCapability(
|
||||
"delegation",
|
||||
"telemetry"
|
||||
)).then(function (result) {
|
||||
var head = domainObject.hasCapability("telemetry") ?
|
||||
[ domainObject ] : [],
|
||||
tail = result || [];
|
||||
return head.concat(tail);
|
||||
});
|
||||
return delegator.promiseTelemetryObjects(domainObject);
|
||||
}
|
||||
|
||||
function updateValuesFromPool() {
|
||||
@ -152,8 +138,8 @@ define(
|
||||
// will be unsubscribe functions. (This must be a promise
|
||||
// because delegation is supported, and retrieving delegate
|
||||
// telemetry-capable objects may be an asynchronous operation.)
|
||||
unsubscribePromise =
|
||||
promiseRelevantObjects(domainObject)
|
||||
telemetryObjectPromise = promiseRelevantObjects(domainObject);
|
||||
unsubscribePromise = telemetryObjectPromise
|
||||
.then(cacheObjectReferences)
|
||||
.then(subscribeAll);
|
||||
|
||||
@ -239,6 +225,17 @@ define(
|
||||
*/
|
||||
getMetadata: function () {
|
||||
return metadatas;
|
||||
},
|
||||
/**
|
||||
* Get a promise for all telemetry-providing objects
|
||||
* associated with this subscription.
|
||||
* @returns {Promise.<DomainObject[]>} a promise for
|
||||
* telemetry-providing objects
|
||||
*/
|
||||
promiseTelemetryObjects: function () {
|
||||
// Unsubscribe promise is available after objects
|
||||
// are loaded.
|
||||
return telemetryObjectPromise;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
12
platform/telemetry/test/TelemetryDelegatorSpec.js
Normal file
12
platform/telemetry/test/TelemetryDelegatorSpec.js
Normal file
@ -0,0 +1,12 @@
|
||||
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
["../src/TelemetryDelegator"],
|
||||
function (TelemetryDelegator) {
|
||||
"use strict";
|
||||
|
||||
describe("The telemetry delegator", function () {
|
||||
|
||||
});
|
||||
}
|
||||
);
|
88
platform/telemetry/test/TelemetryHandleSpec.js
Normal file
88
platform/telemetry/test/TelemetryHandleSpec.js
Normal file
@ -0,0 +1,88 @@
|
||||
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
["../src/TelemetryHandle"],
|
||||
function (TelemetryHandle) {
|
||||
"use strict";
|
||||
|
||||
describe("A telemetry handle", function () {
|
||||
var mockQ,
|
||||
mockSubscription,
|
||||
mockDomainObject,
|
||||
mockTelemetry,
|
||||
mockSeries,
|
||||
mockCallback,
|
||||
handle;
|
||||
|
||||
function asPromise(v) {
|
||||
return (v || {}).then ? v : {
|
||||
then: function (callback) {
|
||||
return asPromise(callback(v));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
mockQ = jasmine.createSpyObj('$q', ['when', 'all']);
|
||||
mockSubscription = jasmine.createSpyObj(
|
||||
'subscription',
|
||||
['unsubscribe', 'getTelemetryObjects', 'promiseTelemetryObjects']
|
||||
);
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
'domainObject',
|
||||
['getId', 'getCapability']
|
||||
);
|
||||
mockTelemetry = jasmine.createSpyObj(
|
||||
'telemetry',
|
||||
['requestData']
|
||||
);
|
||||
mockSeries = jasmine.createSpyObj(
|
||||
'series',
|
||||
['getPointCount', 'getDomainValue', 'getRangeValue']
|
||||
);
|
||||
mockCallback = jasmine.createSpy('callback');
|
||||
|
||||
// Simulate $q.all, at least for asPromise-provided promises
|
||||
mockQ.all.andCallFake(function (values) {
|
||||
return values.map(function (v) {
|
||||
var r;
|
||||
asPromise(v).then(function (value) { r = value; });
|
||||
return r;
|
||||
});
|
||||
});
|
||||
mockQ.when.andCallFake(asPromise);
|
||||
mockSubscription.getTelemetryObjects
|
||||
.andReturn([mockDomainObject]);
|
||||
mockSubscription.promiseTelemetryObjects
|
||||
.andReturn(asPromise([mockDomainObject]));
|
||||
mockDomainObject.getId.andReturn('testId');
|
||||
mockDomainObject.getCapability.andReturn(mockTelemetry);
|
||||
mockTelemetry.requestData.andReturn(asPromise(mockSeries));
|
||||
|
||||
handle = new TelemetryHandle(mockQ, mockSubscription);
|
||||
});
|
||||
|
||||
it("exposes subscription API", function () {
|
||||
// Should still expose methods from the provided subscription
|
||||
expect(handle.unsubscribe)
|
||||
.toBe(mockSubscription.unsubscribe);
|
||||
expect(handle.getTelemetryObjects)
|
||||
.toBe(mockSubscription.getTelemetryObjects);
|
||||
});
|
||||
|
||||
it("provides an interface for historical requests", function () {
|
||||
handle.request({}, mockCallback);
|
||||
expect(mockCallback).toHaveBeenCalledWith(
|
||||
mockDomainObject,
|
||||
mockSeries
|
||||
);
|
||||
});
|
||||
|
||||
it("provides the latest series for domain objects", function () {
|
||||
handle.request({});
|
||||
expect(handle.getSeries(mockDomainObject))
|
||||
.toEqual(mockSeries);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
64
platform/telemetry/test/TelemetryHandlerSpec.js
Normal file
64
platform/telemetry/test/TelemetryHandlerSpec.js
Normal file
@ -0,0 +1,64 @@
|
||||
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
["../src/TelemetryHandler"],
|
||||
function (TelemetryHandler) {
|
||||
"use strict";
|
||||
|
||||
describe("The telemetry handler", function () {
|
||||
// TelemetryHandler just provides a factory
|
||||
// for TelemetryHandle, so most real testing
|
||||
// should happen there.
|
||||
var mockQ,
|
||||
mockSubscriber,
|
||||
mockDomainObject,
|
||||
mockCallback,
|
||||
mockSubscription,
|
||||
handler;
|
||||
|
||||
beforeEach(function () {
|
||||
mockQ = jasmine.createSpyObj("$q", ["when"]);
|
||||
mockSubscriber = jasmine.createSpyObj(
|
||||
'telemetrySubscriber',
|
||||
['subscribe']
|
||||
);
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
'domainObject',
|
||||
['getId', 'getCapability']
|
||||
);
|
||||
mockCallback = jasmine.createSpy('callback');
|
||||
mockSubscription = jasmine.createSpyObj(
|
||||
'subscription',
|
||||
[
|
||||
'unsubscribe',
|
||||
'getTelemetryObjects',
|
||||
'getRangeValue',
|
||||
'getDomainValue'
|
||||
]
|
||||
);
|
||||
|
||||
mockSubscriber.subscribe.andReturn(mockSubscription);
|
||||
|
||||
handler = new TelemetryHandler(mockQ, mockSubscriber);
|
||||
});
|
||||
|
||||
it("acts as a factory for subscription objects", function () {
|
||||
var handle = handler.handle(
|
||||
mockDomainObject,
|
||||
mockCallback
|
||||
);
|
||||
// Just verify that this looks like a TelemetrySubscription
|
||||
[
|
||||
"unsubscribe",
|
||||
"getTelemetryObjects",
|
||||
"getRangeValue",
|
||||
"getDomainValue",
|
||||
"request"
|
||||
].forEach(function (method) {
|
||||
expect(handle[method]).toEqual(jasmine.any(Function));
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -184,6 +184,14 @@ define(
|
||||
it("fires callback when telemetry objects are available", function () {
|
||||
expect(mockCallback.calls.length).toEqual(1);
|
||||
});
|
||||
|
||||
it("exposes a promise for telemetry objects", function () {
|
||||
var mockCallback2 = jasmine.createSpy('callback');
|
||||
subscription.promiseTelemetryObjects().then(mockCallback2);
|
||||
|
||||
expect(mockCallback2)
|
||||
.toHaveBeenCalledWith([ mockDomainObject ]);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -2,7 +2,10 @@
|
||||
"TelemetryAggregator",
|
||||
"TelemetryCapability",
|
||||
"TelemetryController",
|
||||
"TelemetryDelegator",
|
||||
"TelemetryFormatter",
|
||||
"TelemetryHandle",
|
||||
"TelemetryHandler",
|
||||
"TelemetryQueue",
|
||||
"TelemetrySubscriber",
|
||||
"TelemetrySubscription",
|
||||
|
Loading…
x
Reference in New Issue
Block a user